mirror of
https://github.com/AR2000AR/openComputers_codes.git
synced 2025-09-08 06:31:14 +02:00
359 lines
10 KiB
Lua
359 lines
10 KiB
Lua
---@diagnostic disable: cast-local-type
|
|
local libCB = require("libCB")
|
|
local bank = require("bank_api")
|
|
local shell = require("shell")
|
|
local sides = require("sides")
|
|
local coin = require("libCoin")
|
|
local gui = require("libGUI")
|
|
local event = require("event")
|
|
local os = require("os")
|
|
local component = require("component")
|
|
local gpu = component.gpu
|
|
local transposer = component.transposer
|
|
local disk_drive = component.disk_drive
|
|
local proxy = component.proxy
|
|
local beep = component.computer.beep
|
|
|
|
local STORAGE = 0
|
|
local EXTERIOR = 0
|
|
|
|
local MODE_IDLE = 0
|
|
local MODE_PIN = 1
|
|
local MODE_MENU = 2
|
|
local MODE_WITHDRAW = 3
|
|
local MODE_DEPOSIT = 4
|
|
local MODE_STATS = 5
|
|
local MODE_CLOSING = -1
|
|
local mode = MODE_IDLE
|
|
local CARD_IN_READER = false
|
|
|
|
local BUTTON_NAME_WITHDRAW = "bw"
|
|
local BUTTON_NAME_DEPOSIT = "bd"
|
|
local BUTTON_NAME_EJECT = "be"
|
|
|
|
local main_screen = nil
|
|
local card_wait = nil
|
|
local keypad = nil
|
|
local error_popup = nil
|
|
local success_popup = nil
|
|
local main_menu = nil
|
|
local sold_text = nil
|
|
local bin_text = nil
|
|
|
|
local event_touch, event_drive, event_eject, event_magData = nil, nil, nil, nil
|
|
|
|
local old_res_x, old_res_y = nil, nil
|
|
|
|
---@type Component
|
|
local drive = nil
|
|
---@type cardData
|
|
local cbData = nil
|
|
---@type encryptedCardData
|
|
local encryptedData = nil
|
|
local solde = 0
|
|
-- =============================================================================
|
|
local eject = disk_drive.eject
|
|
|
|
local function endSession()
|
|
mode = MODE_IDLE
|
|
card_wait:setVisible(true)
|
|
error_popup:setVisible(false)
|
|
success_popup:setVisible(false)
|
|
main_menu:enable(false)
|
|
keypad:enable(false)
|
|
keypad:setVisible(false)
|
|
cbData = nil
|
|
encryptedData = nil
|
|
solde = 0
|
|
sold_text:setText("Solde : 0")
|
|
eject()
|
|
end
|
|
|
|
local function showMenu()
|
|
mode = MODE_MENU
|
|
card_wait:setVisible(false)
|
|
error_popup:hide()
|
|
success_popup:hide()
|
|
main_menu:enable(true)
|
|
keypad:enable(false)
|
|
keypad:setVisible(false)
|
|
success_popup:hide()
|
|
error_popup:hide()
|
|
local binVal = coin.getValue(coin.getCoin(EXTERIOR))
|
|
bin_text:setText("Bin : " .. binVal)
|
|
local status
|
|
status, solde = bank.getCredit(cbData)
|
|
if (status == 0) then
|
|
sold_text:setText("Solde : " .. solde)
|
|
else
|
|
endSession()
|
|
end
|
|
end
|
|
|
|
local function closeClient(...)
|
|
if (event_touch) then event.cancel(event_touch) end
|
|
if (event_eject) then event.cancel(event_eject) end
|
|
if (event_drive) then event.cancel(event_drive) end
|
|
if (event_magData) then event.cancel(event_magData) end
|
|
gpu.setResolution(old_res_x, old_res_y)
|
|
main_screen:setVisible(false)
|
|
main_screen:enable(false)
|
|
mode = MODE_CLOSING
|
|
require("component").gpu.setActiveBuffer(0)
|
|
return false
|
|
end
|
|
|
|
-- =============================================================================
|
|
local function makeTransaction(amount)
|
|
local status = nil
|
|
status, solde = bank.getCredit(cbData)
|
|
if (status ~= 0) then
|
|
error_popup:show("Serveur unavailable.", true)
|
|
endSession()
|
|
else
|
|
local coinGiven, b, s, g, p = 0, 0, 0, 0, 0
|
|
if (mode == MODE_WITHDRAW) then
|
|
if (solde < amount) then
|
|
error_popup:show("Insufisant balance.", true)
|
|
amount = 0
|
|
else
|
|
amount = amount * -1
|
|
end
|
|
b, s, g, p = coin.moveCoin(math.abs(amount), STORAGE, EXTERIOR)
|
|
elseif (mode == MODE_DEPOSIT) then
|
|
b, s, g, p = coin.moveCoin(amount, EXTERIOR, STORAGE)
|
|
end
|
|
if (b) then
|
|
---@cast b number
|
|
---@cast s number
|
|
---@cast g number
|
|
---@cast p number
|
|
coinGiven = coin.getValue(b, s, g, p)
|
|
if (mode == MODE_WITHDRAW) then coinGiven = coinGiven * -1 end
|
|
bank.editAccount(cbData, coinGiven)
|
|
if (amount ~= coinGiven) then
|
|
error_popup:show("Output chest full\nCall the owner.", true)
|
|
end
|
|
if (not CARD_IN_READER) then endSession() else showMenu() end
|
|
else
|
|
error_popup:show("Can't output coins.", true)
|
|
if (not CARD_IN_READER) then endSession() else showMenu() end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- =============================================================================
|
|
local function keypadPinCallback(kp)
|
|
if (#kp:getInput() == 4) then
|
|
cbData = libCB.getCB(encryptedData, kp:getInput())
|
|
kp:clearInput()
|
|
if (cbData ~= false) then
|
|
kp:enable(false)
|
|
kp:setVisible(false)
|
|
local status, credit = bank.getCredit(cbData)
|
|
if (status == 0) then
|
|
showMenu()
|
|
status = bank.editAccount(cbData, 0) --check that the atm can do it's job
|
|
if (status ~= 0) then
|
|
endSession()
|
|
closeClient()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local function keypadNumericalCallback(kp)
|
|
if (#kp:getInput() ~= 0) then
|
|
local amount = tonumber(kp:getInput())
|
|
kp:clearInput()
|
|
kp:enable(false)
|
|
kp:setVisible(false)
|
|
makeTransaction(amount)
|
|
end
|
|
end
|
|
|
|
-- =============================================================================
|
|
local function showPinKeypad()
|
|
keypad:clearInput()
|
|
keypad:setMaxInputLen(4)
|
|
keypad:setVisible(true)
|
|
keypad:enable(true)
|
|
keypad:hideInput(true)
|
|
keypad:setValidateCallback(keypadPinCallback)
|
|
end
|
|
|
|
local function showNumericalKeypad()
|
|
keypad:clearInput()
|
|
keypad:setMaxInputLen(-1)
|
|
keypad:setVisible(true)
|
|
keypad:enable(true)
|
|
keypad:hideInput(false)
|
|
keypad:setValidateCallback(keypadNumericalCallback)
|
|
end
|
|
|
|
-- =============================================================================
|
|
local function buttonEventHandler(buttonName)
|
|
if (mode == MODE_MENU) then
|
|
if (buttonName == BUTTON_NAME_EJECT) then
|
|
endSession()
|
|
elseif (buttonName == BUTTON_NAME_DEPOSIT) then
|
|
mode = MODE_DEPOSIT
|
|
showNumericalKeypad()
|
|
elseif (buttonName == BUTTON_NAME_WITHDRAW) then
|
|
mode = MODE_WITHDRAW
|
|
showNumericalKeypad()
|
|
end
|
|
end
|
|
end
|
|
|
|
local function componentAddedHandler(eventName, address, component_type)
|
|
if (component_type == "drive") then
|
|
CARD_IN_READER = true
|
|
drive = proxy(address)
|
|
encryptedData = libCB.loadCB(drive)
|
|
showPinKeypad()
|
|
end
|
|
end
|
|
|
|
local function magDataHandler(eventName, address, ...)
|
|
encryptedData = libCB.loadCB(proxy(address))
|
|
showPinKeypad()
|
|
end
|
|
|
|
local function driveEjectedHandler(eventName, component_type)
|
|
if (component_type == "drive") then
|
|
CARD_IN_READER = false
|
|
endSession()
|
|
end
|
|
end
|
|
|
|
-- =============================================================================
|
|
local function init()
|
|
--look for the input chest
|
|
while (transposer.getInventoryName(STORAGE) == nil) do
|
|
STORAGE = STORAGE + 1
|
|
if (STORAGE == 6) then
|
|
print("Need 2 chest")
|
|
os.exit()
|
|
end
|
|
end
|
|
--look for the output chest
|
|
if (STORAGE == EXTERIOR) then EXTERIOR = EXTERIOR + 1 end
|
|
while (transposer.getInventoryName(EXTERIOR) == nil) do
|
|
EXTERIOR = EXTERIOR + 1
|
|
if (EXTERIOR == STORAGE) then EXTERIOR = EXTERIOR + 1 end
|
|
if (EXTERIOR == 6) then
|
|
print("Need 2 chest")
|
|
os.exit()
|
|
end
|
|
end
|
|
|
|
old_res_x, old_res_y = gpu.getResolution()
|
|
gpu.setResolution(26, 13)
|
|
|
|
main_screen = gui.Screen()
|
|
main_screen:addChild(gui.widget.Rectangle(1, 1, 26, 13, 0))
|
|
event_touch = event.listen("touch", function(...) main_screen:trigger(...) end)
|
|
|
|
main_menu = gui.Screen()
|
|
|
|
sold_text = gui.widget.Text(1, 2, 26, 1, 0xffffff, "Solde : 0")
|
|
sold_text:setBackground(0)
|
|
main_menu:addChild(sold_text)
|
|
|
|
bin_text = gui.widget.Text(1, 3, 26, 1, 0xffffff, "Bin : 0")
|
|
bin_text:setBackground(0)
|
|
main_menu:addChild(bin_text)
|
|
|
|
local button_withdraw = gui.widget.Rectangle(1, 5, 3, 2, 0xffffff)
|
|
button_withdraw:setCallback(function(...) buttonEventHandler(BUTTON_NAME_WITHDRAW) end)
|
|
main_menu:addChild(button_withdraw)
|
|
local label_withdraw = gui.widget.Text(4, 6, 8, 1, 0xffffff, "WITHDRAW")
|
|
label_withdraw:setBackground(0)
|
|
main_menu:addChild(label_withdraw)
|
|
|
|
local button_deposit = gui.widget.Rectangle(1, 8, 3, 2, 0xffffff)
|
|
button_deposit:setCallback(function(...) buttonEventHandler(BUTTON_NAME_DEPOSIT) end)
|
|
main_menu:addChild(button_deposit)
|
|
local label_deposit = gui.widget.Text(4, 9, 7, 1, 0xffffff, "DEPOSIT")
|
|
label_deposit:setBackground(0)
|
|
main_menu:addChild(label_deposit)
|
|
|
|
local button_eject = gui.widget.Rectangle(1, 11, 3, 2, 0xffffff)
|
|
button_eject:setCallback(function(...) buttonEventHandler(BUTTON_NAME_EJECT) end)
|
|
main_menu:addChild(button_eject)
|
|
local label_eject = gui.widget.Text(4, 12, 8, 1, 0xffffff, "EXIT")
|
|
label_eject:setBackground(0)
|
|
main_menu:addChild(label_eject)
|
|
|
|
main_menu:enable(false)
|
|
main_screen:addChild(main_menu)
|
|
|
|
card_wait = gui.Screen()
|
|
card_wait:addChild(gui.widget.Rectangle(1, 1, 26, 13, 0xffffff))
|
|
card_wait:addChild(gui.widget.Image(9, 4, "/usr/share/bank_atm/floppy8x8.pam"))
|
|
main_screen:addChild(card_wait)
|
|
|
|
keypad = gui.widget.Keypad(10, 2, 0xc3c3c3, true, 4)
|
|
keypad:enable(false)
|
|
keypad:setVisible(false)
|
|
main_screen:addChild(keypad)
|
|
|
|
local function show(self, text, blocking)
|
|
self.text:setText(text)
|
|
self:setVisible(true)
|
|
self:enable(true)
|
|
if (blocking) then
|
|
while (self:isVisible()) do
|
|
main_screen:draw()
|
|
os.sleep()
|
|
end
|
|
end
|
|
end
|
|
|
|
local function hide(self, ...)
|
|
success_popup:setVisible(false)
|
|
success_popup:enable(false)
|
|
error_popup:setVisible(false)
|
|
error_popup:enable(false)
|
|
end
|
|
|
|
error_popup = gui.Screen()
|
|
success_popup = gui.Screen()
|
|
error_popup.show = show
|
|
success_popup.show = show
|
|
error_popup.hide = hide
|
|
success_popup.hide = hide
|
|
local popup_bg = gui.widget.Rectangle(2, 5, 24, 5, 0xc3c3c3)
|
|
popup_bg:setCallback(hide)
|
|
error_popup:addChild(popup_bg)
|
|
success_popup:addChild(popup_bg)
|
|
error_popup.text = gui.widget.Text(3, 6, 22, 2, 0, "???")
|
|
error_popup.text:setBackground(popup_bg:getColor())
|
|
error_popup:addChild(error_popup.text)
|
|
success_popup.text = error_popup.text
|
|
success_popup:addChild(success_popup.text)
|
|
success_popup:addChild(gui.widget.Rectangle(2, 5, 24, 1, 0x00ff00))
|
|
error_popup:addChild(gui.widget.Rectangle(2, 5, 24, 1, 0xff0000))
|
|
main_screen:addChild(success_popup)
|
|
main_screen:addChild(error_popup)
|
|
success_popup:hide()
|
|
error_popup:hide()
|
|
|
|
event_drive = event.listen("component_added", componentAddedHandler)
|
|
event_eject = event.listen("component_unavailable", driveEjectedHandler)
|
|
event_magData = event.listen("magData", magDataHandler)
|
|
event.listen("interrupted", closeClient)
|
|
end
|
|
|
|
-- =============================================================================
|
|
init()
|
|
while (mode ~= MODE_CLOSING) do
|
|
main_screen:draw()
|
|
os.sleep()
|
|
end
|
|
closeClient()
|
|
|
|
--TODO handle keypad X
|