Advertisement
cc-editor

Bahnhof

Oct 7th, 2024 (edited)
270
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 12.12 KB | None | 0 0
  1. settings.load()
  2.  
  3. local track_count = settings.get("bahnhof.gleisanzahl")
  4. local tracks = {}
  5.  
  6. local decoder = require("cc.audio.dfpwm").make_decoder()
  7. local station_link = peripheral.wrap(settings.get("bahnhof.anzeigelink"))
  8. station_link.setWidth(48)
  9.  
  10. for i = 1, track_count do
  11.     tracks[i] = {
  12.         station_a = peripheral.wrap(settings.get("bahnhof.gleis" .. i .. ".station_a")),
  13.         station_b = peripheral.wrap(settings.get("bahnhof.gleis" .. i .. ".station_b")),
  14.         monitors = {},
  15.         speaker = peripheral.wrap(settings.get("bahnhof.gleis" .. i .. ".speaker")),
  16.         state = "empty",
  17.         previous_state = "empty"
  18.     }
  19.     for j, v in ipairs(settings.get("bahnhof.gleis" .. i .. ".monitors")) do
  20.         tracks[i].monitors[j] = peripheral.wrap(v)
  21.     end
  22. end
  23.  
  24. -- #region Helper functions
  25.  
  26. local function string_trim(s)
  27.     return (string.gsub(s, "^%s*(.-)%s*$", "%1"))
  28. end
  29.  
  30. local function monitor_write(track_id, x_pos, y_pos, text, color)
  31.     if color == nil then
  32.         color = colors.white
  33.     end
  34.     for i, m in ipairs(tracks[track_id].monitors) do
  35.         m.setCursorPos(x_pos, y_pos)
  36.         m.setTextColor(color)
  37.         m.write(text)
  38.     end
  39. end
  40.  
  41. local function monitor_clear_line(track_id, line)
  42.     for i, m in ipairs(tracks[track_id].monitors) do
  43.         m.setCursorPos(1, line)
  44.         m.clearLine()
  45.     end
  46. end
  47.  
  48. -- #endregion
  49.  
  50. -- #region Station functions
  51.  
  52. local function read_station_link(track_id)
  53.     local display_line = nil
  54.     for i = 1, track_count do
  55.         display_line = string_trim(station_link.getLine(i))
  56.         if string.sub(display_line, -1) == tostring(track_id) then
  57.             return display_line
  58.         end
  59.     end
  60.     return nil
  61. end
  62.  
  63. local function get_arrival_time(track_id)
  64.     if tracks[track_id].station_a.isTrainImminent() or
  65.     tracks[track_id].station_b.isTrainImminent() then
  66.         return 0
  67.     end
  68.     if tracks[track_id].station_a.isTrainPresent() or
  69.     tracks[track_id].station_b.isTrainPresent() then
  70.         return nil
  71.     end
  72.  
  73.     local display_line = read_station_link(track_id)
  74.     if display_line == nil then
  75.         return nil
  76.     end
  77.  
  78.     if string.find(display_line, "~") then
  79.         return 99
  80.     elseif string.find(display_line, "min") then
  81.         return tonumber(string.sub(display_line, 1, 3))
  82.     elseif string.find(display_line, "s") or string.find(display_line, "now") then
  83.         return 0
  84.     else
  85.         return nil
  86.     end
  87. end
  88.  
  89. local function get_train_name(track_id)
  90.     local train_name = nil
  91.     if tracks[track_id].station_a.isTrainPresent() then
  92.         train_name = tracks[track_id].station_a.getTrainName()
  93.     elseif tracks[track_id].station_b.isTrainPresent() then
  94.         train_name = tracks[track_id].station_b.getTrainName()
  95.     end
  96.  
  97.     if train_name == nil then
  98.         local display_line = read_station_link(track_id)
  99.         if display_line == nil then
  100.             return nil
  101.         end
  102.         local i, _ = string.find(display_line, "BB-")
  103.         if i == nil then
  104.             return "UNKW"
  105.         end
  106.         train_name = string.sub(display_line, i, i + 6)
  107.     end
  108.  
  109.     if #train_name ~= 7 and not string.sub(train_name, 1, 3) == "BB-" then
  110.         return "UNKW"
  111.     end
  112.  
  113.     return string.sub(train_name, 4, 7)
  114. end
  115.  
  116. local function get_destination(track_id)
  117.     local display_line = read_station_link(track_id)
  118.     if display_line == nil then
  119.         return nil
  120.     end
  121.  
  122.     local i, j = string.find(display_line, "(^).+($)")
  123.     if i == nil then
  124.         return nil
  125.     end
  126.     return string.sub(display_line, i + 1, j - 1)
  127. end
  128.  
  129. local function get_station_infos(track_id)
  130.     local station_info = {
  131.         arrival_time = get_arrival_time(track_id),
  132.         train_name = get_train_name(track_id),
  133.         destination = get_destination(track_id)
  134.     }
  135.  
  136.     return station_info
  137. end
  138.  
  139. -- #endregion
  140.  
  141. -- #region Display functions
  142. local function init_displays()
  143.     print("Initializing displays")
  144.     for i = 1, track_count do
  145.         for _, m in ipairs(tracks[i].monitors) do
  146.             m.clear()
  147.         end
  148.  
  149.         monitor_write(i, 1, 1, "Gleis " .. i)
  150.     end
  151. end
  152.  
  153. local function print_clock(track_id)
  154.     local time = textutils.formatTime(os.time(), true)
  155.     if #time == 4 then
  156.         time = "0" .. time
  157.     end
  158.     monitor_write(track_id, 14, 1, time)
  159. end
  160.  
  161. local function print_train_name(track_id, train_name)
  162.     if train_name == nil then
  163.         monitor_clear_line(track_id, 3)
  164.     else
  165.         monitor_write(track_id, 2, 3, train_name, colors.cyan)
  166.     end
  167. end
  168.  
  169. local function print_arrival_time(track_id, arrival_time)
  170.     monitor_clear_line(track_id, 4)
  171.  
  172.     if arrival_time == nil then
  173.         return
  174.     elseif tracks[track_id].state == "incoming" then
  175.         monitor_write(track_id, 2, 4, " Zug faehrt ein ", colors.yellow)
  176.     elseif arrival_time > 0 then
  177.         monitor_write(track_id, 2, 4, "Ankunft:        ")
  178.         if arrival_time >= 99 then
  179.             monitor_write(track_id, 11, 4, ">10 min", colors.lightGray)
  180.         else
  181.             local time_str = tostring(arrival_time)
  182.             monitor_write(track_id, 14 - #time_str, 4, time_str .. " min")
  183.         end
  184.     end
  185. end
  186.  
  187. local function print_destination(track_id, destination)
  188.     monitor_write(track_id, 7, 3, "           ")
  189.  
  190.     if destination == nil then
  191.         return
  192.     end
  193.     local i, j = string.find(destination, "via ")
  194.     local via = nil
  195.  
  196.     if i == nil then
  197.         destination = string.sub(destination, 1, 11)
  198.     else
  199.         via = string.sub(destination, i, j + 1 + 11)
  200.         if i > 11 then
  201.             destination = string.sub(destination, 1, 11)
  202.         else
  203.             destination = string.sub(destination, 1, i - 1)
  204.         end
  205.     end
  206.  
  207.     if tracks[track_id].station_a.isTrainPresent() or
  208.     tracks[track_id].station_b.isTrainPresent() then
  209.         if destination == "FINAL_DEST" then
  210.             monitor_write(track_id, 2, 4, "nicht einsteigen", colors.red)
  211.             return
  212.         end
  213.  
  214.         if via == nil then
  215.             monitor_write(track_id, 2, 4, "bitte einsteigen", colors.green)
  216.         else
  217.             monitor_write(track_id, 3, 4, via)
  218.         end
  219.     end
  220.  
  221.     if destination ~= "FINAL_DEST" then
  222.         monitor_write(track_id, 7, 3, destination)
  223.     end
  224. end
  225. -- #endregion
  226.  
  227. -- #region Speaker functions
  228. local function play_chime(track_id)
  229.     tracks[track_id].speaker.playNote("pling", 3, 10)
  230.     sleep(0.3)
  231.     tracks[track_id].speaker.playNote("pling", 3, 6)
  232.     sleep(0.3)
  233.     tracks[track_id].speaker.playNote("pling", 3, 1)
  234. end
  235.  
  236. local function play_text(track_id, text)
  237.     play_chime(track_id)
  238.     sleep(0.3)
  239.     local url = "https://music.madefor.cc/tts?text=" .. textutils.urlEncode(text) .. "&voice=de"
  240.     local response, err = http.get { url = url, binary = true }
  241.     if not response then error(err, 0) end
  242.  
  243.     while true do
  244.         local chunk = response.read(16 * 1024)
  245.         if not chunk then break end
  246.  
  247.         local buffer = decoder(chunk)
  248.         while not tracks[track_id].speaker.playAudio(buffer, 3) do
  249.             os.pullEvent("speaker_audio_empty")
  250.         end
  251.     end
  252.     sleep(3)
  253. end
  254.  
  255. local function play_announcement(track_id, station_info)
  256.     if tracks[track_id].state == "incoming" then
  257.         if station_info.destination == nil or station_info.train_name == nil or station_info.train_name =="UNKW" then
  258.             play_text(track_id, "Vorsicht am Gleis ".. track_id ..". Ein Zug faehrt ein")
  259.         elseif station_info.destination == "FINAL_DEST" then
  260.             play_text(track_id, "Vorsicht am Gleis ".. track_id ..". Der einfahrende Zug endet hier. Bitte nicht einsteigen!")
  261.         else
  262.             local i, j = string.find(station_info.destination, "via ")
  263.             if i == nil then
  264.                 play_text(track_id, "Gleis ".. track_id ..". Einfahrt, ".. station_info.train_name .." Richtung ".. station_info.destination)
  265.             else
  266.                 local via = string.sub(station_info.destination, j+1, #station_info.destination)
  267.                 local destination = string.sub(station_info.destination, 1, i-1)
  268.                 play_text(track_id, "Gleis ".. track_id ..". Einfahrt, ".. station_info.train_name .." Richtung ".. destination .. ", ueber ".. via)
  269.             end
  270.         end
  271.     elseif tracks[track_id].state == "final" then
  272.         play_text(track_id, "Der eingfahrene Zug auf Gleis " .. track_id .. " endet hier. Bitte alle aussteigen!")
  273.     elseif tracks[track_id].state == "arrived" then
  274.         local i, j = string.find(station_info.destination, "via ")
  275.  
  276.         if i == nil then
  277.             play_text(track_id, "Eingefahrener Zug auf Gleis ".. track_id ..": ".. station_info.train_name .." Richtung ".. station_info.destination)
  278.         else
  279.             local via = string.sub(station_info.destination, j+1, #station_info.destination)
  280.             local destination = string.sub(station_info.destination, 1, i-1)
  281.             play_text(track_id, "Eingefahrener Zug auf Gleis ".. track_id ..": ".. station_info.train_name .." Richtung ".. destination .. ", ueber ".. via)
  282.         end
  283.  
  284.     elseif tracks[track_id].state == "boarding" then
  285.         local i, j = string.find(station_info.destination, "via ")
  286.  
  287.         if i == nil then
  288.             play_text(track_id, "Gleis ".. track_id .." steht: ".. station_info.train_name .." Richtung ".. station_info.destination ..". Bitte einsteigen!")
  289.         else
  290.             local via = string.sub(station_info.destination, j+1, #station_info.destination)
  291.             local destination = string.sub(station_info.destination, 1, i-1)
  292.             play_text(track_id, "Gleis ".. track_id .." steht: ".. station_info.train_name .." Richtung ".. destination .. ", ueber ".. via ..". Bitte einsteigen!")
  293.         end
  294.     end
  295. end
  296. -- #endregion
  297.  
  298. local function update_displays()
  299.     while true do
  300.         for i = 1, track_count do
  301.             monitor_write(i, 14, 1, textutils.formatTime(os.time(), true))
  302.             local station_info = get_station_infos(i)
  303.  
  304.             print_clock(i)
  305.             print_train_name(i, station_info.train_name)
  306.             print_arrival_time(i, station_info.arrival_time)
  307.             print_destination(i, station_info.destination)
  308.         end
  309.         sleep(1)
  310.     end
  311. end
  312.  
  313. local function update_states()
  314.     while true do
  315.         for i = 1, track_count do
  316.             local station_info = get_station_infos(i)
  317.             tracks[i].previous_state = tracks[i].state
  318.  
  319.             if tracks[i].station_a.isTrainPresent() or
  320.             tracks[i].station_b.isTrainPresent() then
  321.                 if station_info.destination == nil then
  322.                     tracks[i].state = "present"
  323.                 elseif station_info.destination == "FINAL_DEST" then
  324.                     tracks[i].state = "final"
  325.                 elseif tracks[i].previous_state == "incoming" or tracks[i].previous_state == "arrived" then
  326.                     tracks[i].state = "arrived"
  327.                 else
  328.                     tracks[i].state = "boarding"
  329.                 end
  330.             elseif tracks[i].previous_state == "present" or tracks[i].previous_state == "final" or tracks[i].previous_state == "arrived" or tracks[i].previous_state == "boarding" then
  331.                 tracks[i].state = "leaving"
  332.             elseif station_info.arrival_time ~= nil and station_info.arrival_time < 1 and (tracks[i].previous_state == "empty" or tracks[i].previous_state == "incoming") then
  333.                 tracks[i].state = "incoming"
  334.             else
  335.                 tracks[i].state = "empty"
  336.             end
  337.  
  338.             print("Track " .. i .. " state: " .. tracks[i].state)
  339.         end
  340.         sleep(2.5)
  341.     end
  342. end
  343.  
  344. local function play_announcements()
  345.     while true do
  346.         for i = 1, track_count do
  347.             if tracks[i].previous_state ~= tracks[i].state then
  348.                 print("Playing announcement for track " .. i)
  349.                 local station_info = get_station_infos(i)
  350.                 play_announcement(i, station_info)
  351.             end
  352.         end
  353.         sleep(1)
  354.     end
  355. end
  356.  
  357. print("Train Station Control")
  358. init_displays()
  359. parallel.waitForAll(update_states, update_displays, play_announcements)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement