SHOW:
|
|
- or go back to the newest paste.
| 1 | - | function scheduleFromFile(path) |
| 1 | + | local LONG_PING = 5 |
| 2 | - | local file = fs.open(path, "r") |
| 2 | + | local MEDIUM_PING = 1 |
| 3 | - | local body = file.readAll() |
| 3 | + | local SHORT_PING = 0. |
| 4 | - | file.close() |
| 4 | + | |
| 5 | - | return textutils.unserialize(body) |
| 5 | + | local RANDOM_MIN = 60 |
| 6 | local RANDOM_MAX = 120 | |
| 7 | ||
| 8 | - | function scheduleFromStation() |
| 8 | + | local AUDIO_PATH = "audio/transit/" |
| 9 | - | return peripheral.find("Create_Station").getSchedule()
|
| 9 | + | |
| 10 | local VOLUME = 2.0 | |
| 11 | local inst1 = "pling" | |
| 12 | - | local args = {...}
|
| 12 | + | local inst2 = "iron_xylophone" |
| 13 | - | local filePath = args[1] |
| 13 | + | local inst3 = "bass" |
| 14 | - | local schedule |
| 14 | + | |
| 15 | - | if filePath == nil then |
| 15 | + | local JINGLES = {
|
| 16 | - | schedule = scheduleFromStation() |
| 16 | + | arrival = {
|
| 17 | - | else |
| 17 | + | {duration=0.5, notes={{inst1, VOLUME, 20}, {inst2, VOLUME, 20}, {inst3, VOLUME, 4}}},
|
| 18 | - | schedule = scheduleFromFile(filePath) |
| 18 | + | {duration=0.5, notes={{inst1, VOLUME, 16}, {inst2, VOLUME, 16}, {inst3, VOLUME, 8}}},
|
| 19 | {duration=0.5, notes={{inst1, VOLUME, 18}, {inst2, VOLUME, 18}, {inst3, VOLUME, 6}}},
| |
| 20 | {duration=0.5, notes={{inst1, VOLUME, 11}, {inst2, VOLUME, 11}, {inst3, VOLUME, 11}}}
| |
| 21 | - | local color = schedule.color |
| 21 | + | }, |
| 22 | - | if color == nil then |
| 22 | + | random = {
|
| 23 | - | color = 2048 |
| 23 | + | {duration=0.4, notes={{inst1, VOLUME, 4}, {inst2, VOLUME, 4}, {inst3, VOLUME, 16}}},
|
| 24 | {duration=0.4, notes={{inst1, VOLUME, 8}, {inst2, VOLUME, 8}, {inst3, VOLUME, 11}}},
| |
| 25 | - | term.setTextColor(colors.white) |
| 25 | + | {duration=0.4, notes={{inst1, VOLUME, 11}, {inst2, VOLUME, 11}, {inst3, VOLUME, 8}}}
|
| 26 | - | term.setBackgroundColor(colors.black) |
| 26 | + | } |
| 27 | - | term.clear() |
| 27 | + | } |
| 28 | ||
| 29 | - | local i = 1 |
| 29 | + | function splitWord(target, word) |
| 30 | - | for _, entry in ipairs(schedule.entries) do |
| 30 | + | local i, j = string.find(target, word) |
| 31 | - | if entry.instruction.id == "create:destination" then |
| 31 | + | if i == nil then return target end |
| 32 | - | local name = entry.instruction.data.text:gsub("%s%d+$", "")
|
| 32 | + | return string.sub(target, 1, i - 1), string.sub(target, j + 1, -1) |
| 33 | - | term.setCursorPos(4, i) |
| 33 | + | |
| 34 | - | term.write(name) |
| 34 | + | function getName(name) |
| 35 | - | i = i + 1 |
| 35 | + | return string.gfind(string.gsub(name, "%s%d", ""), "[%a%s%p]+")() |
| 36 | - | end |
| 36 | + | |
| 37 | function getFilename(name) | |
| 38 | - | term.setBackgroundColor(color) |
| 38 | + | return string.gsub(getName(name), "%s", "_") |
| 39 | - | for j=1,i-1 do |
| 39 | + | |
| 40 | - | term.setCursorPos(2, j) |
| 40 | + | function getNumber(name) |
| 41 | - | term.write(" ")
|
| 41 | + | return tonumber(string.gfind(name, "%d+$")()) |
| 42 | - | -- if j == 1 or j == i-1 then |
| 42 | + | |
| 43 | - | -- term.write("O")
|
| 43 | + | |
| 44 | - | -- else |
| 44 | + | local decoder = require("cc.audio.dfpwm").make_decoder()
|
| 45 | - | -- term.write("|")
|
| 45 | + | local speaker = peripheral.find("speaker")
|
| 46 | - | -- end |
| 46 | + | local stations = {}
|
| 47 | for _, name in pairs(peripheral.getNames()) do | |
| 48 | - | term.setBackgroundColor(colors.black) |
| 48 | + | pType = peripheral.getType(name) |
| 49 | - | term.setCursorPos(1, i) |
| 49 | + | if pType == "Create_Station" then |
| 50 | local station = peripheral.wrap(name) | |
| 51 | station.fullName = station.getStationName() | |
| 52 | station.name=getName(station.fullName) | |
| 53 | station.platform=getNumber(station.fullName) | |
| 54 | station.present=station.isTrainPresent() | |
| 55 | table.insert(stations, station) | |
| 56 | end | |
| 57 | end | |
| 58 | ||
| 59 | shell.run("clear")
| |
| 60 | ||
| 61 | local pingTimer = os.startTimer(SHORT_PING) | |
| 62 | local randomTimer = os.startTimer(math.random(RANDOM_MIN, RANDOM_MAX)) | |
| 63 | local soundTasks = {}
| |
| 64 | function addSoundTasks(newTasks) | |
| 65 | for i=1, #newTasks do | |
| 66 | if newTasks[i].filename ~= nil then | |
| 67 | for chunk in io.lines(AUDIO_PATH..newTasks[i].filename, 16*1024) do | |
| 68 | soundTasks[#soundTasks+1] = {buffer=chunk}
| |
| 69 | end | |
| 70 | else | |
| 71 | soundTasks[#soundTasks+1] = newTasks[i] | |
| 72 | end | |
| 73 | end | |
| 74 | end | |
| 75 | local soundTaskIndex = 1 | |
| 76 | local soundTaskTimer = nil | |
| 77 | local soundPlaying = false | |
| 78 | while true do | |
| 79 | local event, id = os.pullEvent() | |
| 80 | local startSound = false | |
| 81 | if event == "timer" and id == pingTimer then | |
| 82 | local newTime = LONG_PING | |
| 83 | for i, station in pairs(stations) do | |
| 84 | if station.isTrainPresent() then | |
| 85 | if not station.present then | |
| 86 | stations[i].present = true | |
| 87 | newTime = math.min(newTime, MEDIUM_PING) | |
| 88 | local name = station.getTrainName() | |
| 89 | write(name) | |
| 90 | ||
| 91 | if not soundPlaying then | |
| 92 | addSoundTasks(JINGLES.arrival) | |
| 93 | end | |
| 94 | ||
| 95 | local lineFilename = "lines/"..getFilename(name)..".dfpwm" | |
| 96 | if fs.exists(AUDIO_PATH..lineFilename) then | |
| 97 | addSoundTasks({{filename=lineFilename}})
| |
| 98 | else | |
| 99 | addSoundTasks({{filename="Train.dfpwm"}})
| |
| 100 | end | |
| 101 | if station.hasSchedule() then | |
| 102 | local schedule = station.getSchedule() | |
| 103 | local entries = schedule.entries | |
| 104 | local progress = schedule.progress -- BUG: This value is often incorrect. | |
| 105 | if progress == nil then progress = 1 end | |
| 106 | for i=1, #entries do | |
| 107 | if entries[i].instruction.id == "create:destination" and entries[i].instruction.data.text == station.fullName then | |
| 108 | progress = i | |
| 109 | break | |
| 110 | end | |
| 111 | end | |
| 112 | local stations = {}
| |
| 113 | local label = nil | |
| 114 | local index = math.mod(progress, #entries) + 1 | |
| 115 | while index ~= progress do | |
| 116 | --write(index..": ") | |
| 117 | local entry = entries[index] | |
| 118 | if entry.instruction.id == "create:destination" then | |
| 119 | stations[#stations + 1] = entry.instruction.data.text | |
| 120 | --print(stations[#stations]) | |
| 121 | elseif entry.instruction.id == "create:rename" then | |
| 122 | label = entry.instruction.data.text | |
| 123 | --print("-> "..label)
| |
| 124 | end | |
| 125 | index = math.mod(index, #entries) + 1 | |
| 126 | end | |
| 127 | ||
| 128 | if label ~= nil then | |
| 129 | write(" to "..label)
| |
| 130 | local name, andName = splitWord(label, " and ") | |
| 131 | local isVia = false | |
| 132 | if andName == nil then | |
| 133 | isVia = true | |
| 134 | name, andName = splitWord(label, " via ") | |
| 135 | end | |
| 136 | addSoundTasks({
| |
| 137 | {filename="To.dfpwm"},
| |
| 138 | {duration=0.4},
| |
| 139 | {filename="stations/"..getFilename(name)..".dfpwm"}
| |
| 140 | }) | |
| 141 | if andName ~= nil then | |
| 142 | addSoundTasks({{duration=0.2}})
| |
| 143 | if isVia then addSoundTasks({{filename="Via.dfpwm"}})
| |
| 144 | else addSoundTasks({{filename="And.dfpwm"}}) end
| |
| 145 | addSoundTasks({{duration=0.2}, {filename="stations/"..getFilename(andName)..".dfpwm"}})
| |
| 146 | end | |
| 147 | end | |
| 148 | end | |
| 149 | addSoundTasks({{filename="ArrivesNowOnTrack.dfpwm"}})
| |
| 150 | addSoundTasks({
| |
| 151 | {duration=0.2},
| |
| 152 | {filename="numbers/"..station.platform..".dfpwm"},
| |
| 153 | {duration=1.0}
| |
| 154 | }) | |
| 155 | startSound = true | |
| 156 | randomTimer = os.startTimer(math.random(RANDOM_MIN, RANDOM_MAX)) | |
| 157 | ||
| 158 | print(" arrived on platform "..station.platform)
| |
| 159 | end | |
| 160 | else | |
| 161 | stations[i].present = false | |
| 162 | if station.isTrainEnroute() then | |
| 163 | newTime = math.min(newTime, MEDIUM_PING) | |
| 164 | elseif station.isTrainImminent() then | |
| 165 | newTime = math.min(newTime, SHORT_PING) | |
| 166 | randomTimer = nil | |
| 167 | end | |
| 168 | end | |
| 169 | end | |
| 170 | pingTimer = os.startTimer(newTime) | |
| 171 | end | |
| 172 | if event == "timer" and id == randomTimer then | |
| 173 | local filenames = fs.list(AUDIO_PATH.."random") | |
| 174 | local randomFile = filenames[math.random(#filenames)] | |
| 175 | print("Playing announcment \""..randomFile.."\"...")
| |
| 176 | addSoundTasks(JINGLES.random) | |
| 177 | addSoundTasks({{filename="random/"..randomFile}})
| |
| 178 | startSound = true | |
| 179 | randomTimer = os.startTimer(math.random(RANDOM_MIN, RANDOM_MAX)) | |
| 180 | end | |
| 181 | if (event == "timer" and id == soundTaskTimer) or (event == "speaker_audio_empty") or (startSound and not soundPlaying) then | |
| 182 | soundPlaying = true | |
| 183 | local soundTask = soundTasks[soundTaskIndex] | |
| 184 | if soundTask == nil then | |
| 185 | soundPlaying = false | |
| 186 | soundTasks = {}
| |
| 187 | soundTaskIndex = 1 | |
| 188 | else | |
| 189 | if soundTask.notes ~= nil then | |
| 190 | for _, note in pairs(soundTask.notes) do | |
| 191 | speaker.playNote(unpack(note)) | |
| 192 | end | |
| 193 | elseif soundTask.buffer ~= nil then | |
| 194 | speaker.playAudio(decoder(soundTask.buffer), VOLUME) | |
| 195 | end | |
| 196 | if soundTask.duration ~= nil then | |
| 197 | soundTaskTimer = os.startTimer(soundTask.duration) | |
| 198 | end | |
| 199 | soundTaskIndex = soundTaskIndex + 1 | |
| 200 | end | |
| 201 | end | |
| 202 | end |