local db = require("stratumBackend") local completion = require("cc.completion") local total_items = {} local printer = peripheral.find("printer") local monitor = peripheral.find("monitor") local price_map = {} local unit_name = nil local full_item_qoute local dirtied = false term.clear() if monitor then monitor.clear() end local function tallyUpItems(price) local items = {} local currencies = db.getCurrencies() local worthmap = {} local worths = {} local minimum = 999 for k,v in ipairs(currencies) do worthmap[db.getCurrencyWorth(v)] = v worths[#worths+1] = db.getCurrencyWorth(v) minimum = math.min(db.getCurrencyWorth(v),minimum) end table.sort(worths, function (a, b) return a > b end) price = math.ceil(price/minimum)*minimum for _,i in ipairs(worths) do local subcount = math.floor(price/i) if subcount > 0 then items[worthmap[i]] = (items[worthmap[i]] or 0)+subcount price = price - subcount*1 end end return items end local function printTotal() print("printing total...") if not printer then print("no printer found") return end if not printer.newPage() then print("not enough ink/pages") end printer.setPageTitle("Receipt") printer.write("Material Cost:") local x,y = printer.getCursorPos() printer.setCursorPos(1,y+2) local total = 0 for k,v in pairs(total_items) do printer.write("- "..tostring(k).." x"..tostring(v)) local x,y = printer.getCursorPos() printer.setCursorPos(1,y+1) total = total + (( db.getPrice(k) or 0)*v) end local x,y = printer.getCursorPos() printer.setCursorPos(1,y+1) printer.write("Total cost: "..tostring(math.floor(total*100+0.5)/100).." "..tostring(db.getCurrencyUnit())) local x,y = printer.getCursorPos() printer.setCursorPos(1,y+2) printer.write("Price in items:") local x,y = printer.getCursorPos() printer.setCursorPos(1,y+2) full_item_qoute = tallyUpItems(total) for k,v in pairs(full_item_qoute) do printer.write("- "..tostring(k).." x"..tostring(v)) local x,y = printer.getCursorPos() printer.setCursorPos(1,y+1) total = total + (( db.getPrice(k) or 0)*v) end printer.endPage() print("printed the total!") end local function input() while true do local event = {os.pullEvent()} if event[1] == "key" then if event[2] == keys.a then sleep(0) local added_item_name = nil local added_item_count = nil local x,y = term.getSize() term.setCursorPos(1,y) term.write("item name > ") local materials = db.getMaterials() added_item_name = read(nil,nil, function(text) return completion.choice(text, materials) end) if added_item_name == "" then added_item_name = nil else repeat term.write("item count > ") added_item_count = tonumber(read()) until added_item_count ~= nil if added_item_count <= 0 then added_item_name = nil added_item_count = nil else if not db.getPrice(added_item_name) then print("item not found... define a price?") print("price in items per 1 "..unit_name) local new_price = nil repeat term.write("item price > ") new_price = 1/tonumber(read()) until new_price ~= nil ---@cast new_price number if new_price > 0 then db.setPrice(added_item_name,new_price) end end total_items[added_item_name] = (total_items[added_item_name] or 0 ) + added_item_count price_map[added_item_name] = db.getPrice(added_item_name) end dirtied = true end elseif event[2] == keys.l then for k,v in pairs(total_items) do print(tostring(k).." x"..tostring(v)) end elseif event[2] == keys.t then if not unit_name then unit_name = db.getCurrencyUnit() end local total = 0 for k,v in pairs(total_items) do total = total + (( price_map[k] or 0)*v) end print("total: "..tostring(math.floor(total*100+0.5)/100).." "..tostring(unit_name)) elseif event[2] == keys.f then if not unit_name then unit_name = db.getCurrencyUnit() end sleep(0) local total = 0 for k,v in pairs(total_items) do print(tostring(k).." x"..tostring(v)) total = total + (( price_map[k] or 0)*v) end print("total: "..tostring(math.floor(total*100+0.5)/100).." "..tostring(unit_name)) print("\nprice in items:") full_item_qoute = tallyUpItems(total) dirtied = true for k,v in pairs(full_item_qoute) do print(tostring(k).." x"..tostring(v)) total = total + (( price_map[k] or 0)*v) end term.write("print receipt? (Y/n)") local resp = read() if string.find("n", string.lower(resp)) == nil or resp == "" then printTotal() end term.write("finish order? (Y/n)") local resp = read() if string.find("n", string.lower(resp)) == nil or resp == "" then total_items = {} print("finished order..") end dirtied = true full_item_qoute = nil elseif event[2] == keys.d then sleep(0) local removed_item_name = nil local x,y = term.getSize() term.setCursorPos(1,y) term.write("item name > ") local materials = db.getMaterials() removed_item_name = read(nil,nil, function(text) return completion.choice(text, materials) end) if removed_item_name == "" then removed_item_name = nil else if total_items[removed_item_name] then total_items[removed_item_name] = nil print("removed item") end end dirtied = true elseif event[2] == keys.n then sleep(0) term.setCursorPos(1,y) term.write("unit name > ") local unit_namel = read() if unit_namel ~= "" then db.setCurrencyUnit(unit_namel) unit_name = unit_namel print("set currency unit") end dirtied = true elseif event[2] == keys.c then sleep(0) local added_currency_name = nil local added_currency_worth = nil local x,y = term.getSize() term.setCursorPos(1,y) term.write("currency name > ") added_currency_name = read() if added_currency_name == "" then added_currency_name = nil else repeat term.write("currency worth > ") added_currency_worth = tonumber(read()) until added_currency_worth ~= nil if added_currency_worth <= 0 then added_currency_name = nil added_currency_worth = nil else ---@cast added_currency_worth number db.setWorth(added_currency_name,added_currency_worth) end end dirtied = true elseif event[2] == keys.i then sleep(0) local added_item_name = nil local added_item_price = nil local x,y = term.getSize() term.setCursorPos(1,y) term.write("item name > ") local materials = db.getMaterials() added_item_name = read(nil,nil, function(text) return completion.choice(text, materials) end) if added_item_name == "" then added_item_name = nil else repeat print("price in items per 1 "..unit_name) term.write("item price > ") added_item_price = 1/tonumber(read()) until added_item_price ~= nil if added_item_price <= 0 then added_item_name = nil added_item_price = nil else ---@cast added_item_price number db.setPrice(added_item_name,added_item_price) price_map[added_item_name] = db.getPrice(added_item_name) end end dirtied = true end end end end local function render_monitor() while true do sleep(0) if monitor and dirtied then if not full_item_qoute then if not unit_name then unit_name = db.getCurrencyUnit() end monitor.clear() local x,y = monitor.getSize() local total = 0 for k,v in pairs(total_items) do monitor.setCursorPos(1,y) monitor.write(tostring(k).." x"..tostring(v).."") monitor.scroll(1) total = total + (( price_map[k] or 0)*v) end monitor.setCursorPos(1,y) monitor.write("total: "..tostring(math.floor(total*100+0.5)/100).." "..tostring(unit_name)) else if not unit_name then unit_name = db.getCurrencyUnit() end monitor.clear() local x,y = monitor.getSize() local total = 0 for k,v in pairs(total_items) do total = total + (( price_map[k] or 0)*v) end for k,v in pairs(full_item_qoute) do monitor.setCursorPos(1,y) monitor.write(tostring(k).." x"..tostring(v).."") monitor.scroll(1) end monitor.setCursorPos(1,1) monitor.write("Full Item Quote:") monitor.setCursorPos(1,y) monitor.write("total: "..tostring(math.floor(total*100+0.5)/100).." "..tostring(unit_name)) end dirtied = false end end end local loops = {input,render_monitor} if db.loop then loops[#loops+1] = db.loop end for k,v in ipairs(loops) do ---@cast loops thread[] loops[k] = coroutine.create(v) coroutine.resume(loops[k]) end term.setCursorPos(1,1) print([[Welcome to the cash register! Controls are: a to add an item to the order. d to delete an item from the order. l to list current items in the order. t to get the total in the terminal. (not listing items) f to finalize the transaction. (and optionally print the receipt) i to add or set the price of an item to the database. c to add or set the worth of a currency to the database. n to set the displayed currency unit. (default is cr for credits) ]]) local x,y = term.getSize() term.setCursorPos(1,y) while true do local event = {os.pullEvent()} for _,v in ipairs(loops) do if coroutine.status(v) ~= "dead" then local succ, err = coroutine.resume(v, table.unpack(event)) if not succ then print(err) end end end end