diff --git a/computer/0/apis/bitreader.lua b/computer/0/apis/bitreader.lua new file mode 100644 index 0000000..dc5c945 --- /dev/null +++ b/computer/0/apis/bitreader.lua @@ -0,0 +1,107 @@ +local bit = bit + +local function readBit_b8(self) + if (self.current > 8) then + return false, false + end + + self.current = self.current + 1 + local v = bit.band(self._value, self._bits[self.current]) + + return self.current < 8, v > 0 + +end + +local function new(self, value) + self.current = 0 + self._value = value + +end + +function Bits8() + -- Represents a byte, allows reading a bit at a time. + local self = {} + + self.current = 0 + self._value = 0 + self._bits = {128, 64, 32, 16, 8, 4, 2, 1} + + self.readBit = readBit_b8 + self.new = new + + return self + +end + + + +local function readBit_br(self) + local s, v = self.cb:readBit() + if (not s) then + self.pointer = self.pointer + 1 + self.cb:new(self.data[self.pointer]) + + end + + return v + +end + +local function readBits(self, n) + local bt = self._bittable + for i = 1, n do + bt[i] = self:readBit() + + end + for i = n+1, #bt do + bt[i] = nil + + end + + return bt + +end + +local function readNumber(self, n) + local m = 0 + + local t = self:readBits(n) + for i = 1, #t do + m = m * 2 + if (t[i]) then + m = m + 1 + + end + + end + + return m + +end + +local function reset(self) + self.cb = Bits8() + self.pointer = 1 + self.cb:new(self.data[self.pointer]) + +end + +function BitReader(data) + -- Class to read bits individually from a table of bytes. + local self = {} + + self.data = data + self.cb = Bits8() + self.pointer = 1 + self.cb:new(self.data[self.pointer]) + + self.readBit = readBit_br + self.readBits = readBits + self.readNumber = readNumber + self.reset = reset + + self._bittable = {} + + return self + +end \ No newline at end of file diff --git a/computer/0/apis/hexscreen.lua b/computer/0/apis/hexscreen.lua new file mode 100644 index 0000000..59a9985 --- /dev/null +++ b/computer/0/apis/hexscreen.lua @@ -0,0 +1,144 @@ +local table = table +local string = string +local term = term + +local function draw(self) + -- Draws the entire visible buffer. + local te = self.term + for y=1, self.height do + te.setCursorPos(1, y) + c0, c1, c2 = self:getLine(y) + + te.blit(c0, c1, c2) + + end + +end + +local n +local b + +local function getCharAt(self, x, y) + n = 0 + b = self.buffer + for i=y*3,y*3-2,-1 do + for j=x*2,x*2-1,-1 do + n = n * 2 + if (b[i][j]) then + n = n + 1 + end + + end + + end + + return n + +end + +local _t +local _c +local _bg +local _cl +local cs + +local c + +local function getLine(self, y) + _t = self._text + _c = self._color + _bg = self._bgcolor + _cl = self._charList + + cs = self.colors + + for x=1,self.width do + c = self:getCharAt(x, y) + _t[x] = _cl[c] + + if (c >= 32) then + _c[x] = cs[2] + _bg[x] = cs[1] + else + _c[x] = cs[1] + _bg[x] = cs[2] + + end + + end + + return table.concat(_t), table.concat(_c), table.concat(_bg) + +end + +local tb +local function setSize(self, w, h) + self.width, self.height = w, h + self.b_width = self.height * 2 + self.b_height = self.height * 3 + + self.buffer = {} + + for i=1, self.b_height do + tb = {} + for j=1, self.b_height do + tb[j] = false + end + self.buffer[i] = tb + end + +end + +local function setSizeBuffer(self, w, h) + self:setSize(math.floor(w/2), math.floor(h/3)) + +end + +function HexScreen(customTerm) + local self = {} + + self.term = customTerm or term + + self.width, self.height = self.term.getSize() + self.b_width = self.width * 2 + self.b_height = self.height * 3 + + self.buffer = {} + + for i=1, self.b_height do + local t = {} + for j=1, self.b_height do + table.insert(t, false) + end + table.insert(self.buffer, t) + end + + self._text = {} + self._color = {} + self._bgcolor = {} + + self.colors = {"0", "f"} + + self._charList = {} + for i=0,63 do + if (i < 32) then + c = string.char(128 + i) + + else + c = string.char(191 - i) + + end + + self._charList[i] = c + + end + + self.draw = draw + self.getCharAt = getCharAt + self.getLine = getLine + self.setSize = setSize + self.setSizeBuffer = setSizeBuffer + + return self + +end diff --git a/computer/0/apis/wave.lua b/computer/0/apis/wave.lua new file mode 100644 index 0000000..3b4a040 --- /dev/null +++ b/computer/0/apis/wave.lua @@ -0,0 +1,427 @@ +--[[ +wave version 0.1.5 + +The MIT License (MIT) +Copyright (c) 2020 CrazedProgrammer + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +]] + +-- I'm so happy I don't have to write or understand this code, thanks! - ax. + + +local wave = { } +wave.version = "0.1.5" + +wave._oldSoundMap = {"harp", "bassattack", "bd", "snare", "hat"} +wave._newSoundMap = {"harp", "bass", "basedrum", "snare", "hat"} +wave._defaultThrottle = 99 +wave._defaultClipMode = 1 +wave._maxInterval = 1 +wave._isNewSystem = false +if _HOST then + -- Redoing this, the correct and boring way, otherwise it doesn't work with versions above 1.100 until 1.800. - axisok + -- Likely to break only if CC:Tweaked changes how it writes versions. + local _matches = {} + for s in string.gmatch(_HOST, "%S+") do + _matches[#_matches + 1] = s + end + + local _v = _matches[2] + _matches = {} + for s in string.gmatch(_v, "%P+") do + _matches[#_matches + 1] = s + end + + local _new = {1, 80} + wave._isNewSystem = true + for i=1, #_new, 1 do + if (i <= #_matches and _new[i] < tonumber(_matches[i])) then + break + + elseif (i <= #_matches and _new[i] > tonumber(_matches[i])) then + wave._isNewSystem = false + break + end + + end + + +end + +wave.context = { } +wave.output = { } +wave.track = { } +wave.instance = { } + +function wave.createContext(clock, volume) + clock = clock or os.clock() + volume = volume or 1.0 + + local context = setmetatable({ }, {__index = wave.context}) + context.outputs = { } + context.instances = { } + context.vs = {0, 0, 0, 0, 0} + context.prevClock = clock + context.volume = volume + return context +end + +function wave.context:addOutput(...) + local output = wave.createOutput(...) + self.outputs[#self.outputs + 1] = output + return output +end + +function wave.context:addOutputs(...) + local outs = {...} + if #outs == 1 then + if not getmetatable(outs) then + outs = outs[1] + else + if getmetatable(outs).__index ~= wave.outputs then + outs = outs[1] + end + end + end + for i = 1, #outs do + self:addOutput(outs[i]) + end +end + +function wave.context:removeOutput(out) + if type(out) == "number" then + table.remove(self.outputs, out) + return + elseif type(out) == "table" then + if getmetatable(out).__index == wave.output then + for i = 1, #self.outputs do + if out == self.outputs[i] then + table.remove(self.outputs, i) + return + end + end + return + end + end + for i = 1, #self.outputs do + if out == self.outputs[i].native then + table.remove(self.outputs, i) + return + end + end +end + +function wave.context:addInstance(...) + local instance = wave.createInstance(...) + self.instances[#self.instances + 1] = instance + return instance +end + +function wave.context:removeInstance(instance) + if type(instance) == "number" then + table.remove(self.instances, instance) + else + for i = 1, #self.instances do + if self.instances == instance then + table.remove(self.instances, i) + return + end + end + end +end + +function wave.context:playNote(note, pitch, volume) + volume = volume or 1.0 + + self.vs[note] = self.vs[note] + volume + for i = 1, #self.outputs do + self.outputs[i]:playNote(note, pitch, volume * self.volume) + end +end + +function wave.context:update(interval) + local clock = os.clock() + interval = interval or (clock - self.prevClock) + + self.prevClock = clock + if interval > wave._maxInterval then + interval = wave._maxInterval + end + for i = 1, #self.outputs do + self.outputs[i].notes = 0 + end + for i = 1, 5 do + self.vs[i] = 0 + end + if interval > 0 then + for i = 1, #self.instances do + local notes = self.instances[i]:update(interval) + for j = 1, #notes / 3 do + self:playNote(notes[j * 3 - 2], notes[j * 3 - 1], notes[j * 3]) + end + end + end +end + + + +function wave.createOutput(out, volume, filter, throttle, clipMode) + volume = volume or 1.0 + filter = filter or {true, true, true, true, true} + throttle = throttle or wave._defaultThrottle + clipMode = clipMode or wave._defaultClipMode + + local output = setmetatable({ }, {__index = wave.output}) + output.native = out + output.volume = volume + output.filter = filter + output.notes = 0 + output.throttle = throttle + output.clipMode = clipMode + if type(out) == "function" then + output.nativePlayNote = out + output.type = "custom" + return output + elseif type(out) == "string" then + if peripheral.getType(out) == "iron_noteblock" then + if wave._isNewSystem then + local nb = peripheral.wrap(out) + output.type = "iron_noteblock" + function output.nativePlayNote(note, pitch, vol) + if output.volume * vol > 0 then + nb.playSound("minecraft:block.note."..wave._newSoundMap[note], vol, math.pow(2, (pitch - 12) / 12)) + end + end + return output + end + elseif peripheral.getType(out) == "speaker" then + if wave._isNewSystem then + local nb = peripheral.wrap(out) + output.type = "speaker" + function output.nativePlayNote(note, pitch, vol) + if output.volume * vol > 0 then + nb.playNote(wave._newSoundMap[note], vol, pitch) + end + end + return output + end + end + elseif type(out) == "table" then + if out.execAsync then + output.type = "commands" + if wave._isNewSystem then + function output.nativePlayNote(note, pitch, vol) + out.execAsync("playsound minecraft:block.note."..wave._newSoundMap[note].." record @a ~ ~ ~ "..tostring(vol).." "..tostring(math.pow(2, (pitch - 12) / 12))) + end + else + function output.nativePlayNote(note, pitch, vol) + out.execAsync("playsound note."..wave._oldSoundMap[note].." @a ~ ~ ~ "..tostring(vol).." "..tostring(math.pow(2, (pitch - 12) / 12))) + end + end + return output + elseif getmetatable(out) then + if getmetatable(out).__index == wave.output then + return out + end + end + end +end + +function wave.scanOutputs() + local outs = { } + if commands then + outs[#outs + 1] = wave.createOutput(commands) + end + local sides = peripheral.getNames() + for i = 1, #sides do + if peripheral.getType(sides[i]) == "iron_noteblock" then + outs[#outs + 1] = wave.createOutput(sides[i]) + elseif peripheral.getType(sides[i]) == "speaker" then + outs[#outs + 1] = wave.createOutput(sides[i]) + end + end + return outs +end + +function wave.output:playNote(note, pitch, volume) + volume = volume or 1.0 + + if self.clipMode == 1 then + if pitch < 0 then + pitch = 0 + elseif pitch > 24 then + pitch = 24 + end + elseif self.clipMode == 2 then + if pitch < 0 then + while pitch < 0 do + pitch = pitch + 12 + end + elseif pitch > 24 then + while pitch > 24 do + pitch = pitch - 12 + end + end + end + if self.filter[note] and self.notes < self.throttle then + self.nativePlayNote(note, pitch, volume * self.volume) + self.notes = self.notes + 1 + end +end + + + +function wave.loadTrack(path) + local track = setmetatable({ }, {__index = wave.track}) + local handle = fs.open(path, "rb") + if not handle then return end + + local function readInt(size) + local num = 0 + for i = 0, size - 1 do + local byte = handle.read() + if not byte then -- dont leave open file handles no matter what + handle.close() + return + end + num = num + byte * (256 ^ i) + end + return num + end + local function readStr() + local length = readInt(4) + if not length then return end + local data = { } + for i = 1, length do + data[i] = string.char(handle.read()) + end + return table.concat(data) + end + + -- Part #1: Metadata + track.length = readInt(2) -- song length (ticks) + track.height = readInt(2) -- song height + track.name = readStr() -- song name + track.author = readStr() -- song author + track.originalAuthor = readStr() -- original song author + track.description = readStr() -- song description + track.tempo = readInt(2) / 100 -- tempo (ticks per second) + track.autoSaving = readInt(1) == 0 and true or false -- auto-saving + track.autoSavingDuration = readInt(1) -- auto-saving duration + track.timeSignature = readInt(1) -- time signature (3 = 3/4) + track.minutesSpent = readInt(4) -- minutes spent + track.leftClicks = readInt(4) -- left clicks + track.rightClicks = readInt(4) -- right clicks + track.blocksAdded = readInt(4) -- blocks added + track.blocksRemoved = readInt(4) -- blocks removed + track.schematicFileName = readStr() -- midi/schematic file name + + -- Part #2: Notes + track.layers = { } + for i = 1, track.height do + track.layers[i] = {name = "Layer "..i, volume = 1.0} + track.layers[i].notes = { } + end + + local tick = 0 + while true do + local tickJumps = readInt(2) + if tickJumps == 0 then break end + tick = tick + tickJumps + local layer = 0 + while true do + local layerJumps = readInt(2) + if layerJumps == 0 then break end + layer = layer + layerJumps + if layer > track.height then -- nbs can be buggy + for i = track.height + 1, layer do + track.layers[i] = {name = "Layer "..i, volume = 1.0} + track.layers[i].notes = { } + end + track.height = layer + end + local instrument = readInt(1) + local key = readInt(1) + if instrument <= 4 then -- nbs can be buggy + track.layers[layer].notes[tick * 2 - 1] = instrument + 1 + track.layers[layer].notes[tick * 2] = key - 33 + end + end + end + + -- Part #3: Layers + for i = 1, track.height do + local name = readStr() + if not name then break end -- if layer data doesnt exist, abort + track.layers[i].name = name + track.layers[i].volume = readInt(1) / 100 + end + + handle.close() + return track +end + + + +function wave.createInstance(track, volume, playing, loop) + volume = volume or 1.0 + playing = (playing == nil) or playing + loop = (loop ~= nil) and loop + + if getmetatable(track).__index == wave.instance then + return track + end + local instance = setmetatable({ }, {__index = wave.instance}) + instance.track = track + instance.volume = volume or 1.0 + instance.playing = playing + instance.loop = loop + instance.tick = 1 + return instance +end + +function wave.instance:update(interval) + local notes = { } + if self.playing then + local dticks = interval * self.track.tempo + local starttick = self.tick + local endtick = starttick + dticks + local istarttick = math.ceil(starttick) + local iendtick = math.ceil(endtick) - 1 + for i = istarttick, iendtick do + for j = 1, self.track.height do + if self.track.layers[j].notes[i * 2 - 1] then + notes[#notes + 1] = self.track.layers[j].notes[i * 2 - 1] + notes[#notes + 1] = self.track.layers[j].notes[i * 2] + notes[#notes + 1] = self.track.layers[j].volume + end + end + end + self.tick = self.tick + dticks + + if endtick > self.track.length then + self.tick = 1 + self.playing = self.loop + end + end + return notes +end + + + +return wave diff --git a/computer/0/badapple.nbs b/computer/0/badapple.nbs new file mode 100644 index 0000000..e051d3f Binary files /dev/null and b/computer/0/badapple.nbs differ diff --git a/computer/0/badapple.qtv b/computer/0/badapple.qtv new file mode 100644 index 0000000..5b043f2 Binary files /dev/null and b/computer/0/badapple.qtv differ diff --git a/computer/0/sounds.lua b/computer/0/sounds.lua new file mode 100644 index 0000000..bcc444a --- /dev/null +++ b/computer/0/sounds.lua @@ -0,0 +1,55 @@ +noteblock = peripheral.wrap("right") +sfx = require("sfx") +speaker = peripheral.wrap("left") +instruments = { +"harp", +"bass", +"didgeridoo", +"xylophone", +"iron_xylophone", +"snare", +"hat", +"basedrum", +"bit", +"bit", +"bit", +"bit" +} +mobs = { + "skeleton", + "zombie", + "pig", + "cow", + "spider" +} +function sound() +while true do + if math.random(10)>5 then + speaker.playSound("entity."..mobs[math.random(#mobs)]..".ambient",10) + elseif math.random(100) < 95 then + noteblock.setInstrument(instruments[math.random(#instruments)]) + noteblock.play() + noteblock.setNote(math.random(24)) + elseif math.random(100) < 50 then + for i = 1,5 do + speaker.playSound("entity.creeper.step") + sleep(0.05) + end + speaker.playSound("entity.creeper.primed") + else + --speaker.playSound("BOOM") + end + sleep(math.random(1,20)) + --os.reboot() +end +end +while false and true do + --sound() + if math.random(100) then + sfx.success() + sleep(math.random(1,4)) + end +end +parallel.waitForAll(sound,sound,sound,sound,sound) +peripheral.call("top","turnOn") +os.reboot() diff --git a/computer/0/startup.lua b/computer/0/startup.lua index 360d8a0..e20da89 100644 --- a/computer/0/startup.lua +++ b/computer/0/startup.lua @@ -1,55 +1,22 @@ -noteblock = peripheral.wrap("right") -sfx = require("sfx") -speaker = peripheral.wrap("left") -instruments = { -"harp", -"bass", -"didgeridoo", -"xylophone", -"iron_xylophone", -"snare", -"hat", -"basedrum", -"bit", -"bit", -"bit", -"bit" -} -mobs = { - "skeleton", - "zombie", - "pig", - "cow", - "spider" -} -function sound() +term.clear() +term.setCursorPos(1,1) + +speaker = peripheral.wrap("right") while true do - if math.random(10)>5 then - speaker.playSound("entity."..mobs[math.random(#mobs)]..".ambient") - elseif math.random(100) < 95 then - noteblock.setInstrument(instruments[math.random(#instruments)]) - noteblock.play() - noteblock.setNote(math.random(24)) - elseif math.random(100) < 50 then - for i = 1,5 do - speaker.playSound("entity.creeper.step") - sleep(0.05) - end - speaker.playSound("entity.creeper.primed") - else - --speaker.playSound("BOOM") + for i = 1,100 do + pitch = math.random()*0.4+0.8 + volume = math.random()*.5+1.5 + --print("pitch: "..pitch,"volume: "..volume) + speaker.playSound( + "entity.wandering_trader.ambient", + volume, + pitch + ) + --sleep(math.random()*3+1) end - sleep(math.random(1,20)) - --os.reboot() + --sleep(math.random(300,600)) + shell.run("pastebin", "run", "KMRmKTc1") + sleep(math.random(300,600)) end -end -while true do - --sound() - if math.random(100) > 97 or true then - sfx.success() - sleep(math.random(1,4)) - end -end -parallel.waitForAll(sound,sound,sound,sound,sound) -peripheral.call("top","turnOn") --- os.reboot() + + diff --git a/computer/0/videoplayer.lua b/computer/0/videoplayer.lua new file mode 100644 index 0000000..52f7447 --- /dev/null +++ b/computer/0/videoplayer.lua @@ -0,0 +1,283 @@ +require("apis.hexscreen") +require("apis.bitreader") +local wave = require("apis.wave") + +local math = math +local sleep = sleep +local string = string +local screen = term + +local data +local frame + +local reader + +local width +local height +local sleep_ticks + +local _width_bits +local _height_bits + +local fi + +local arg = {...} + +local function findPer(pName) + if (peripheral.getName) then + local p = peripheral.find(pName) + local n + + if (p) then + n = peripheral.getName(p) + end + + return n, p + + else + local d = {"top", "bottom", "right", "left", "front", "back"} + for i=1, #d do + if (peripheral.getType(d[i]) == pName) then + local p = peripheral.wrap(d[i]) + local n = d[i] + return n, p + + end + + end + + end + +end + +local function invertQuad(x, y, w, h) + for i=y, y+h-1 do + fi = frame[i] + for j=x, x+w-1 do + fi[j] = not fi[j] + + end + end + + return frame + +end + +local function readQuad(x, y, w, h) + if (w * h == 0) then + return + end + + + if (reader:readBit()) then + -- Splits into 4 more quads. + + local cw = math.ceil(w/2) + local ch = math.ceil(h/2) + local fw = math.floor(w/2) + local fh = math.floor(h/2) + + readQuad(x, y, cw, ch) + readQuad(x+cw, y, fw, ch) + readQuad(x, y+ch, cw, fh) + readQuad(x+cw, y+ch, fw, fh) + + else + -- Doesn't split. + if (reader:readBit()) then + -- Inverts the region of this quad. + invertQuad(x, y, w, h) + + end + + end + +end + +local fx +local fy + +local w_bits +local h_bits + +local frw +local frh + +local function readFrame() + fx = reader:readNumber(_width_bits) + fy = reader:readNumber(_height_bits) + + w_bits = 0 + h_bits = 0 + + while (2^w_bits <= width - fx) do + w_bits = w_bits + 1 + end + + while (2^h_bits <= height - fy) do + h_bits = h_bits + 1 + end + + frw = reader:readNumber(w_bits) + + if (frw == 0) then + return + end + frh = reader:readNumber(h_bits) + + + + + readQuad(fx+1, fy+1, frw, frh) + +end + +local loop = false +for i=1, #arg do + if (arg[i] == "loop") then + loop = true + table.remove(arg, i) + break + + end + +end + +print("Reading files...") + +local videofile = arg[1] +local audiofile + +local dPos = videofile:find("%.") +if (dPos) then + audiofile = videofile:sub(1, dPos-1) .. ".nbs" + +else + audiofile = videofile .. ".nbs" + videofile = videofile .. ".qtv" + +end + +-- Read the audio file +local wc +if (audiofile and fs.exists(audiofile)) then + local dir, speaker = findPer("speaker") + + if (speaker ~= nil) then + wc = wave.createContext() + wc:addOutput(dir) + local t = wave.loadTrack(audiofile) + wc:addInstance(wave.createInstance(t)) + + end + +end + + +-- Read the video file +if (not fs.exists(videofile)) then + error("video file '" .. videofile .. "' not found.") + +end + +local f = fs.open(videofile, "rb") +local fileString = f.readAll() +data = {string.byte(fileString, 1, -1)} + +f.close() + + +reader = BitReader(data) + +sleep_ticks = reader:readNumber(5)+1 +width = reader:readNumber(10)+1 +height = reader:readNumber(9)+1 + +_width_bits = 0 +_height_bits = 0 + +while (2^_width_bits <= width) do + _width_bits = _width_bits + 1 +end + +while (2^_height_bits <= height) do + _height_bits = _height_bits + 1 +end + +local mon = peripheral.find("monitor") + +if (mon ~= nil) then + screen = mon + + for s=5,0.5,-0.5 do + screen.setTextScale(s) + w, h = screen.getSize() + if (width <= (w+1)*2 or height <= (h+1)*3) then + break + end + + end + +end + +local hs = HexScreen(screen) +hs:setSizeBuffer(width, height) + +local fri + +frame = {} +for i=1, height do + frame[i] = {} + fri = frame[i] + for j=1, width do + fri[j] = false + end +end + +hs.buffer = frame +local status, err +while true do + status, err = pcall(readFrame) + + if (not status) then + if (not loop) then + break + end + + reader:reset() + reader:readNumber(5) + reader:readNumber(10) + reader:readNumber(9) + + frame = {} + for i=1, height do + frame[i] = {} + fri = frame[i] + for j=1, width do + fri[j] = false + end + end + + hs.buffer = frame + + if (wc) then + for i = 1, #wc.instances do + wc.instances[i].playing = true + wc.instances[i].tick = 1 + + end + end + + else + hs:draw() + + if (wc) then + pcall(wc.update, wc, 0.05) + + end + + end + + sleep(0.05 * sleep_ticks) + +end \ No newline at end of file diff --git a/computer/1/startup.lua b/computer/1/startup.lua index b10f57d..5c06168 100644 --- a/computer/1/startup.lua +++ b/computer/1/startup.lua @@ -18,7 +18,7 @@ while true do filename, "r" ) - lines = {} + counts = {} vec = stringtovec(message) print(vector.new().tostring(vec)) record = nil @@ -26,22 +26,22 @@ while true do line = file.readLine() wec = (line and stringtovec(line)) or nil adding = wec - if + if (wec) and ( - (not record) - or + (not record) + or (wec.y <= record.y) - ) + ) then - if - (not record) - or + if + (not record) + or ( - (vec-wec):length() - < + (vec-wec):length() + < (vec-record):length() - ) + ) then --pp.pretty_print(wec) --write("is better than") @@ -51,18 +51,18 @@ while true do end end if adding then - table.insert(lines,adding:tostring()) + table.insert(counts,adding:tostring()) end until not line rednet.send(id,record:tostring(),"nexttobuild") print(record) file.close() file = fs.open(filename,"w") - for i,v in pairs(lines) do + for i,v in pairs(counts) do file.writeLine(v) end file.close() - + else file = fs.open(filename,"r") line = file.readLine() diff --git a/computer/1/tobuild b/computer/1/tobuild index c3fbe7e..e69de29 100644 --- a/computer/1/tobuild +++ b/computer/1/tobuild @@ -1,9942 +0,0 @@ -10,32,-78 -2,32,-70 --150,32,146 --142,32,146 --150,32,138 --134,32,146 --142,32,138 --150,32,130 --126,32,146 --134,32,138 --142,32,130 --150,32,122 --126,32,138 --134,32,130 --142,32,122 --150,32,114 --126,32,130 --134,32,122 --142,32,114 --150,32,106 --126,32,122 --118,32,130 --118,32,138 --118,32,146 --134,32,114 --142,32,106 --150,32,98 --118,32,122 --126,32,114 --134,32,106 --150,32,90 --142,32,98 --118,32,114 --126,32,106 --150,32,82 --134,32,98 --142,32,90 --150,32,74 --126,32,98 --142,32,82 --134,32,90 --150,32,66 --118,32,106 --142,32,74 --134,32,82 --150,32,58 --142,32,66 --150,32,50 --142,32,58 --150,32,42 --150,32,-150 --150,32,34 --150,32,-142 --150,32,26 --142,32,-150 --150,32,-134 --126,32,90 --110,32,114 --110,32,122 --110,32,130 --110,32,138 --110,32,146 --150,32,18 --150,32,-126 --142,32,-142 --150,32,10 --150,32,-118 --134,32,74 --150,32,2 --142,32,-134 --142,32,50 --118,32,98 --142,32,42 --134,32,-150 --134,32,66 --150,32,-110 --110,32,106 --126,32,82 --150,32,-6 --142,32,-126 --150,32,-102 --142,32,34 --150,32,-14 --142,32,26 --134,32,58 --150,32,-94 --150,32,-22 --134,32,-142 --118,32,90 --142,32,18 --150,32,-86 --150,32,-30 --150,32,-78 --150,32,-38 --142,32,2 --102,32,114 --102,32,122 --102,32,130 --102,32,138 --102,32,146 --142,32,-118 --134,32,-134 --150,32,-70 --142,32,10 --150,32,-46 --126,32,74 --142,32,-6 --142,32,-110 --126,32,-150 --150,32,-62 --110,32,98 --134,32,50 --102,32,106 --150,32,-54 --134,32,42 --118,32,82 --134,32,-126 --126,32,66 --134,32,34 --142,32,-102 --142,32,-14 --110,32,90 --126,32,58 --126,32,-142 --134,32,26 --142,32,-94 --142,32,-22 --118,32,74 --134,32,-118 --126,32,-134 --142,32,-86 --142,32,-30 --134,32,18 --94,32,114 --94,32,122 --94,32,130 --94,32,138 --94,32,146 --142,32,-78 --142,32,-38 --134,32,-6 --142,32,-70 --134,32,2 --102,32,98 --118,32,-150 --134,32,-110 --142,32,-46 --134,32,10 --94,32,106 --126,32,-126 --142,32,-62 --126,32,50 --110,32,82 --118,32,66 --126,32,42 --142,32,-54 --134,32,-102 --134,32,-14 --102,32,90 --126,32,34 --118,32,-142 --134,32,-94 --94,32,98 --118,32,58 --110,32,74 --134,32,-22 --126,32,-118 --126,32,26 --110,32,-150 --134,32,-86 --86,32,106 --86,32,114 --86,32,122 --86,32,130 --86,32,138 --86,32,146 --134,32,-30 --134,32,-78 --134,32,-38 --134,32,-70 --118,32,-134 --126,32,18 --126,32,-6 --126,32,-110 --134,32,-46 --118,32,-126 --126,32,10 --126,32,2 --134,32,-62 --118,32,50 --102,32,82 --110,32,66 --134,32,-54 --110,32,-142 --126,32,-102 --94,32,90 --118,32,42 --86,32,98 --118,32,34 --126,32,-14 --102,32,74 --118,32,-118 --126,32,-94 --110,32,58 --102,32,-150 --118,32,26 --126,32,-22 --118,32,18 --78,32,106 --78,32,114 --78,32,122 --78,32,130 --78,32,138 --78,32,146 --126,32,-86 --126,32,-30 --110,32,-134 --126,32,-78 --118,32,-110 --126,32,-38 --126,32,-70 --118,32,10 --126,32,-46 --118,32,-6 --94,32,82 --110,32,-126 --118,32,2 --110,32,50 --102,32,-142 --126,32,-62 --126,32,-54 --94,32,-150 --86,32,90 --102,32,66 --78,32,98 --110,32,42 --118,32,-102 --118,32,-14 --94,32,74 --110,32,-118 --102,32,58 --110,32,34 --118,32,-94 --118,32,-22 --118,32,-86 --86,32,82 --70,32,106 --70,32,114 --70,32,122 --70,32,130 --70,32,138 --70,32,146 --102,32,-134 --118,32,-30 --110,32,-110 --118,32,-78 --110,32,26 --110,32,18 --118,32,-38 --94,32,-142 --118,32,-70 --70,32,98 --102,32,-126 --78,32,90 --110,32,-6 --118,32,-46 --110,32,10 --110,32,-102 --86,32,-150 --102,32,50 --118,32,-62 --110,32,2 --94,32,66 --102,32,42 --118,32,-54 --102,32,-118 --110,32,-14 --86,32,74 --110,32,-94 --94,32,58 --110,32,-22 --78,32,82 --102,32,34 --62,32,98 --62,32,106 --62,32,114 --62,32,122 --62,32,130 --62,32,138 --62,32,146 --94,32,-134 --102,32,-110 --86,32,-142 --110,32,-86 --70,32,90 --94,32,-126 --110,32,-30 --110,32,-78 --102,32,26 --110,32,-38 --110,32,-70 --102,32,18 --102,32,-102 --78,32,-150 --102,32,-6 --94,32,-118 --110,32,-46 --86,32,66 --94,32,50 --102,32,10 --102,32,2 --110,32,-62 --110,32,-54 --78,32,74 --102,32,-14 --86,32,-134 --94,32,42 --102,32,-94 --62,32,90 --70,32,82 --86,32,58 --54,32,98 --54,32,106 --54,32,114 --54,32,122 --54,32,130 --54,32,138 --54,32,146 --102,32,-22 --78,32,-142 --94,32,-110 --70,32,-150 --102,32,-86 --102,32,-30 --102,32,-78 --94,32,34 --102,32,-38 --102,32,-70 --78,32,66 --86,32,-126 --94,32,26 --78,32,-134 --86,32,50 --94,32,-102 --94,32,18 --94,32,-6 --86,32,-118 --94,32,10 --94,32,2 --102,32,-46 --94,32,-14 --102,32,-62 --102,32,-54 --54,32,90 --70,32,74 --62,32,82 --86,32,42 --94,32,-94 --94,32,-22 --46,32,98 --46,32,106 --46,32,114 --46,32,122 --46,32,130 --46,32,138 --46,32,146 --70,32,-142 --62,32,-150 --86,32,-110 --94,32,-86 --78,32,-126 --78,32,58 --94,32,-30 --86,32,34 --94,32,-78 --70,32,-134 --70,32,66 --62,32,-142 --46,32,90 --94,32,-38 --78,32,50 --86,32,-102 --94,32,-70 --86,32,26 --78,32,-118 --54,32,82 --62,32,74 --86,32,-14 --86,32,-6 --94,32,-46 --86,32,18 --86,32,10 --54,32,-150 --86,32,2 --94,32,-62 --70,32,58 --38,32,90 --38,32,98 --38,32,106 --38,32,114 --38,32,122 --38,32,130 --38,32,138 --38,32,146 --94,32,-54 --86,32,-94 --78,32,-110 --86,32,-22 --70,32,-126 --86,32,-86 --78,32,42 --86,32,-30 --46,32,82 --62,32,66 --62,32,-134 --46,32,-150 --86,32,-78 --86,32,-38 --54,32,-142 --54,32,74 --78,32,34 --70,32,50 --78,32,-102 --86,32,-70 --70,32,-118 --78,32,-14 --78,32,26 --78,32,18 --78,32,2 --86,32,-46 --78,32,10 --78,32,-6 --38,32,82 --62,32,-126 --30,32,90 --30,32,98 --30,32,106 --30,32,114 --30,32,122 --30,32,130 --30,32,138 --30,32,146 --86,32,-62 --86,32,-54 --70,32,-110 --78,32,-94 --38,32,-150 --78,32,-22 --62,32,58 --54,32,-134 --78,32,-86 --46,32,-142 --78,32,-30 --70,32,42 --46,32,74 --54,32,66 --70,32,34 --70,32,-102 --78,32,-78 --62,32,50 --62,32,-118 --30,32,-150 --54,32,-126 --78,32,-38 --30,32,82 --38,32,-142 --70,32,26 --38,32,74 --78,32,-70 --54,32,58 --78,32,-46 --46,32,66 --22,32,90 --22,32,98 --22,32,106 --22,32,114 --22,32,122 --22,32,130 --22,32,138 --22,32,146 --46,32,-134 --78,32,-62 --70,32,-94 --62,32,-110 --78,32,-54 --70,32,-86 --70,32,-6 --62,32,-102 --70,32,18 --70,32,-14 --70,32,-22 --22,32,-150 --70,32,2 --62,32,42 --70,32,10 --62,32,34 --54,32,-118 --22,32,82 --30,32,-142 --46,32,-126 --70,32,-30 --30,32,74 --70,32,-78 --54,32,50 --70,32,-38 --38,32,66 --46,32,58 --70,32,-70 --62,32,26 --22,32,74 --14,32,90 --14,32,98 --14,32,106 --14,32,114 --14,32,122 --14,32,130 --14,32,138 --14,32,146 --38,32,-134 --62,32,-94 --54,32,-110 --14,32,-150 --70,32,-46 --70,32,-62 --46,32,-118 --62,32,-6 --22,32,-142 --70,32,-54 --62,32,-14 --62,32,-22 --14,32,82 --30,32,-134 --54,32,-102 --54,32,42 --62,32,18 --62,32,10 --62,32,2 --62,32,-86 --30,32,66 --46,32,50 --6,32,-150 --62,32,-30 --38,32,-126 --38,32,58 --54,32,34 --62,32,-78 --54,32,26 --14,32,74 --6,32,90 --6,32,98 --6,32,106 --6,32,114 --6,32,122 --6,32,130 --6,32,138 --6,32,146 --14,32,-142 -2,32,-150 --46,32,-110 --38,32,-118 --22,32,-134 --62,32,-38 --54,32,-94 --62,32,-70 --62,32,-46 --62,32,-62 --30,32,-126 --6,32,82 --54,32,-14 --22,32,66 --46,32,42 --54,32,-22 --46,32,-102 --54,32,18 --54,32,-6 --54,32,10 --6,32,-142 --54,32,2 --30,32,58 --38,32,50 --6,32,74 --14,32,-134 --54,32,-86 --14,32,66 --54,32,-30 -2,32,82 -2,32,90 -2,32,98 -2,32,106 -2,32,114 -2,32,122 -2,32,130 -2,32,138 -2,32,146 -10,32,-150 --38,32,-110 --22,32,-126 --54,32,-78 -2,32,-142 --54,32,-38 --46,32,-94 --30,32,-118 --54,32,-70 --6,32,-134 --46,32,34 --38,32,-102 --46,32,26 --46,32,-14 --54,32,-62 --54,32,-54 --22,32,58 --38,32,42 --46,32,-86 --6,32,66 --46,32,-22 -2,32,74 -10,32,-142 --30,32,-110 --30,32,50 --46,32,18 --46,32,-6 --46,32,10 --14,32,-126 -10,32,82 -10,32,90 -10,32,98 -10,32,106 -10,32,114 -10,32,122 -10,32,130 -10,32,138 -10,32,146 -18,32,-150 -18,32,-142 --46,32,-30 -2,32,-134 --46,32,-78 --22,32,-118 --46,32,-38 --46,32,-70 --46,32,2 --38,32,-94 --6,32,-126 --30,32,-102 --14,32,-118 -10,32,-134 --38,32,34 --14,32,58 --46,32,-46 --46,32,-62 --22,32,50 -10,32,74 -2,32,66 --30,32,42 -18,32,-134 --38,32,-86 --46,32,-54 --6,32,58 --38,32,26 --38,32,-14 -18,32,74 -18,32,82 -18,32,90 -18,32,98 -18,32,106 -18,32,114 -18,32,122 -18,32,130 -18,32,138 -18,32,146 -26,32,-150 -26,32,-142 --38,32,-30 --22,32,-110 -2,32,-126 -26,32,-134 --38,32,-78 --30,32,-94 --38,32,-6 --6,32,-118 --22,32,-102 --38,32,-22 --38,32,-38 --38,32,18 --38,32,-70 --30,32,-86 --14,32,-110 -2,32,58 -10,32,66 -10,32,-126 --38,32,10 --38,32,2 --38,32,-46 --14,32,50 --30,32,34 --22,32,42 --30,32,-30 -18,32,66 -26,32,74 -26,32,82 -26,32,90 -26,32,98 -26,32,106 -26,32,114 -26,32,122 -26,32,130 -26,32,138 -26,32,146 -34,32,-150 -34,32,-142 -34,32,-134 --22,32,-94 -2,32,-118 -18,32,-126 --38,32,-62 --6,32,-110 -26,32,-126 --38,32,-54 --30,32,-78 --6,32,50 -10,32,-118 -34,32,-126 --30,32,26 -10,32,58 --22,32,34 --30,32,-38 --30,32,-22 --30,32,-70 --30,32,18 --30,32,-14 --14,32,-102 --30,32,-6 --22,32,-86 -26,32,66 -2,32,50 --14,32,-94 -34,32,74 -34,32,82 -34,32,90 -34,32,98 -34,32,106 -34,32,114 -34,32,122 -34,32,130 -34,32,138 -34,32,146 -42,32,-150 -42,32,-142 -42,32,-134 -42,32,-126 -2,32,-110 --30,32,-46 -18,32,-118 -26,32,-118 --30,32,-62 --30,32,-54 --14,32,42 --22,32,-78 --22,32,-30 -18,32,58 --30,32,10 --6,32,-102 --22,32,-38 -10,32,50 --30,32,2 -34,32,66 -34,32,-118 --22,32,-14 -10,32,-110 --6,32,42 --22,32,26 --14,32,34 -26,32,58 -42,32,66 -42,32,74 -42,32,82 -42,32,90 -42,32,98 -42,32,106 -42,32,114 -42,32,122 -42,32,130 -42,32,138 -42,32,146 -50,32,-150 -50,32,-142 -50,32,-134 -50,32,-126 -42,32,-118 -2,32,-102 -50,32,-118 -18,32,-110 --22,32,-70 --14,32,-86 --22,32,18 --6,32,-94 --22,32,-22 -10,32,-102 -18,32,50 --22,32,-46 --22,32,-62 -26,32,-110 -2,32,42 --6,32,-86 -34,32,-110 -34,32,58 --22,32,-54 --22,32,-6 -18,32,42 -26,32,50 --22,32,10 -50,32,66 -50,32,74 -50,32,82 -50,32,90 -50,32,98 -50,32,106 -50,32,114 -50,32,122 -50,32,130 -50,32,138 -50,32,146 -58,32,-150 -58,32,-142 -58,32,-134 -58,32,-126 -58,32,-118 -58,32,-110 -42,32,-110 -50,32,-110 --14,32,-78 --14,32,-38 -18,32,-102 -2,32,-94 --14,32,-70 --14,32,-30 -26,32,-102 --6,32,-78 -42,32,58 -58,32,-102 -10,32,42 -50,32,58 --22,32,2 -10,32,-94 -34,32,50 -34,32,-102 -50,32,-102 --6,32,34 -58,32,58 -58,32,66 -58,32,74 -58,32,82 -58,32,90 -58,32,98 -58,32,106 -58,32,114 -58,32,122 -58,32,130 -58,32,138 -58,32,146 -66,32,-150 -66,32,-142 -66,32,-134 -66,32,-126 -66,32,-118 -66,32,-110 -66,32,-102 --14,32,-46 -2,32,-86 -18,32,-94 -42,32,-102 --14,32,-22 -66,32,-94 --14,32,-62 --14,32,-54 -26,32,-94 -10,32,-86 -42,32,50 --14,32,-14 --6,32,-30 -58,32,50 --6,32,-38 --6,32,-70 -50,32,50 -2,32,-78 -66,32,50 -66,32,58 -66,32,66 -66,32,74 -66,32,82 -66,32,90 -66,32,98 -66,32,106 -66,32,114 -66,32,122 -66,32,130 -66,32,138 -66,32,146 -74,32,-150 -74,32,-142 -74,32,-134 -74,32,-126 -74,32,-118 -74,32,-110 -74,32,-102 -74,32,-94 -74,32,-86 -58,32,-94 -50,32,-94 -34,32,-94 -66,32,-86 -42,32,-94 --6,32,-46 -18,32,-86 -74,32,-78 --14,32,26 --14,32,-6 --6,32,-62 -2,32,34 -66,32,42 -26,32,-86 --6,32,-54 -74,32,42 -74,32,50 -74,32,58 -74,32,66 -74,32,74 -74,32,82 -74,32,90 -74,32,98 -74,32,106 -74,32,114 -74,32,122 -74,32,130 -74,32,138 -74,32,146 -82,32,-150 -82,32,-142 -82,32,-134 -82,32,-126 -82,32,-118 -82,32,-110 -82,32,-102 -82,32,-94 -82,32,-86 -82,32,-78 -82,32,-70 -82,32,-62 -82,32,-54 -82,32,-46 -74,32,-46 -58,32,-86 -50,32,-86 -82,32,-38 -82,32,-6 --14,32,18 -74,32,34 -82,32,2 -82,32,26 -82,32,34 -82,32,42 -82,32,50 -82,32,58 -82,32,66 -82,32,74 -82,32,82 -82,32,90 -82,32,98 -82,32,106 -82,32,114 -82,32,122 -82,32,130 -82,32,138 -82,32,146 -90,32,-150 -90,32,-142 -90,32,-134 -90,32,-126 -90,32,-118 -90,32,-110 -90,32,-102 -90,32,-94 -90,32,-86 -90,32,-78 -90,32,-70 -90,32,-62 -90,32,-54 -90,32,-46 -90,32,-38 -90,32,-30 -90,32,-22 -90,32,-14 -90,32,-6 -90,32,2 -90,32,10 -90,32,18 -90,32,26 -90,32,34 -90,32,42 -90,32,50 -90,32,58 -90,32,66 -90,32,74 -90,32,82 -90,32,90 -90,32,98 -90,32,106 -90,32,114 -90,32,122 -90,32,130 -90,32,138 -90,32,146 -98,32,-150 -98,32,-142 -98,32,-134 -98,32,-126 -98,32,-118 -98,32,-110 -98,32,-102 -98,32,-94 -98,32,-86 -98,32,-78 -98,32,-70 -98,32,-62 -98,32,-54 -98,32,-46 -98,32,-38 -98,32,-30 -98,32,-22 -98,32,-14 -98,32,-6 -98,32,2 -98,32,10 -98,32,18 -98,32,26 -98,32,34 -98,32,42 -98,32,50 -98,32,58 -98,32,66 -98,32,74 -98,32,82 -98,32,90 -98,32,98 -98,32,106 -98,32,114 -98,32,122 -98,32,130 -98,32,138 -98,32,146 -106,32,-150 -106,32,-142 -106,32,-134 -106,32,-126 -106,32,-118 -106,32,-110 -106,32,-102 -106,32,-94 -106,32,-86 -106,32,-78 -106,32,-70 -106,32,-62 -106,32,-54 -106,32,-46 -106,32,-38 -106,32,-30 -106,32,-22 -106,32,-14 -106,32,-6 -106,32,2 -106,32,10 -106,32,18 -106,32,26 -106,32,34 -106,32,42 -106,32,50 -106,32,58 -106,32,66 -106,32,74 -106,32,82 -106,32,90 -106,32,98 -106,32,106 -106,32,114 -106,32,122 -106,32,130 -106,32,138 -106,32,146 -114,32,-150 -114,32,-142 -114,32,-134 -114,32,-126 -114,32,-118 -114,32,-110 -114,32,-102 -114,32,-94 -114,32,-86 -114,32,-78 -114,32,-70 -114,32,-62 -114,32,-54 -114,32,-46 -114,32,-38 -114,32,-30 -114,32,-22 -114,32,-14 -114,32,-6 -114,32,2 -114,32,10 -114,32,18 -114,32,26 -114,32,34 -114,32,42 -114,32,50 -114,32,58 -114,32,66 -114,32,74 -114,32,82 -114,32,90 -114,32,98 -114,32,106 -114,32,114 -114,32,122 -114,32,130 -114,32,138 -114,32,146 -122,32,-150 -122,32,-142 -122,32,-134 -122,32,-126 -122,32,-118 -122,32,-110 -122,32,-102 -122,32,-94 -122,32,-86 -122,32,-78 -122,32,-70 -122,32,-62 -122,32,-54 -122,32,-46 -122,32,-38 -122,32,-30 -122,32,-22 -122,32,-14 -122,32,-6 -122,32,2 -122,32,10 -122,32,18 -122,32,26 -122,32,34 -122,32,42 -122,32,50 -122,32,58 -122,32,66 -122,32,74 -122,32,82 -122,32,90 -122,32,98 -122,32,106 -122,32,114 -122,32,122 -122,32,130 -122,32,138 -122,32,146 -130,32,-150 -130,32,-142 -130,32,-134 -130,32,-126 -130,32,-118 -130,32,-110 -130,32,-102 -130,32,-94 -130,32,-86 -130,32,-78 -130,32,-70 -130,32,-62 -130,32,-54 -130,32,-46 -130,32,-38 -130,32,-30 -130,32,-22 -130,32,-14 -130,32,-6 -130,32,2 -130,32,10 -130,32,18 -130,32,26 -130,32,34 -130,32,42 -130,32,50 -130,32,58 -130,32,66 -130,32,74 -130,32,82 -130,32,90 -130,32,98 -130,32,106 -130,32,114 -130,32,122 -130,32,130 -130,32,138 -130,32,146 -138,32,-150 -138,32,-142 -138,32,-134 -138,32,-126 -138,32,-118 -138,32,-110 -138,32,-102 -138,32,-94 -138,32,-86 -138,32,-78 -138,32,-70 -138,32,-62 -138,32,-54 -138,32,-46 -138,32,-38 -138,32,-30 -138,32,-22 -138,32,-14 -138,32,-6 -138,32,2 -138,32,10 -138,32,18 -138,32,26 -138,32,34 -138,32,42 -138,32,50 -138,32,58 -138,32,66 -138,32,74 -138,32,82 -138,32,90 -138,32,98 -138,32,106 -138,32,114 -138,32,122 -138,32,130 -138,32,138 -138,32,146 -146,32,-150 -146,32,-142 -146,32,-134 -146,32,-126 -146,32,-118 -146,32,-110 -146,32,-102 -146,32,-94 -146,32,-86 -146,32,-78 -146,32,-70 -146,32,-62 -146,32,-54 -146,32,-46 -146,32,-38 -146,32,-30 -146,32,-22 -146,32,-14 -146,32,-6 -146,32,2 -146,32,10 -146,32,18 -146,32,26 -146,32,34 -146,32,42 -146,32,50 -146,32,58 -146,32,66 -146,32,74 -146,32,82 -146,32,90 -146,32,98 -146,32,106 -146,32,114 -146,32,122 -146,32,130 -146,32,138 -146,32,146 --150,40,-150 --150,40,-142 --150,40,-134 --150,40,-126 --150,40,-118 --150,40,-110 --150,40,-102 --150,40,-94 --150,40,-86 --150,40,-78 --150,40,-70 --150,40,-62 --150,40,-54 --150,40,-46 --150,40,-38 --150,40,-30 --150,40,-22 --150,40,-14 --150,40,-6 --150,40,2 --150,40,10 --150,40,18 --150,40,26 --150,40,34 --150,40,42 --150,40,50 --150,40,58 --150,40,66 --150,40,74 --150,40,82 --150,40,90 --150,40,98 --150,40,106 --150,40,114 --150,40,122 --150,40,130 --150,40,138 --150,40,146 --142,40,-150 --142,40,-142 --142,40,-134 --142,40,-126 --142,40,-118 --142,40,-110 --142,40,-102 --142,40,-94 --142,40,-86 --142,40,-78 --142,40,-70 --142,40,-62 --142,40,-54 --142,40,-46 --142,40,-38 --142,40,-30 --142,40,-22 --142,40,-14 --142,40,-6 --142,40,2 --142,40,10 --142,40,18 --142,40,26 --142,40,34 --142,40,42 --142,40,50 --142,40,58 --142,40,66 --142,40,74 --142,40,82 --142,40,90 --142,40,98 --142,40,106 --142,40,114 --142,40,122 --142,40,130 --142,40,138 --142,40,146 --134,40,-150 --134,40,-142 --134,40,-134 --134,40,-126 --134,40,-118 --134,40,-110 --134,40,-102 --134,40,-94 --134,40,-86 --134,40,-78 --134,40,-70 --134,40,-62 --134,40,-54 --134,40,-46 --134,40,-38 --134,40,-30 --134,40,-22 --134,40,-14 --134,40,-6 --134,40,2 --134,40,10 --134,40,18 --134,40,26 --134,40,34 --134,40,42 --134,40,50 --134,40,58 --134,40,66 --134,40,74 --134,40,82 --134,40,90 --134,40,98 --134,40,106 --134,40,114 --134,40,122 --134,40,130 --134,40,138 --134,40,146 --126,40,-150 --126,40,-142 --126,40,-134 --126,40,-126 --126,40,-118 --126,40,-110 --126,40,-102 --126,40,-94 --126,40,-86 --126,40,-78 --126,40,-70 --126,40,-62 --126,40,-54 --126,40,-46 --126,40,-38 --126,40,-30 --126,40,-22 --126,40,-14 --126,40,-6 --126,40,2 --126,40,10 --126,40,18 --126,40,26 --126,40,34 --126,40,42 --126,40,50 --126,40,58 --126,40,66 --126,40,74 --126,40,82 --126,40,90 --126,40,98 --126,40,106 --126,40,114 --126,40,122 --126,40,130 --126,40,138 --126,40,146 --118,40,-150 --118,40,-142 --118,40,-134 --118,40,-126 --118,40,-118 --118,40,-110 --118,40,-102 --118,40,-94 --118,40,-86 --118,40,-78 --118,40,-70 --118,40,-62 --118,40,-54 --118,40,-46 --118,40,-38 --118,40,-30 --118,40,-22 --118,40,-14 --118,40,-6 --118,40,2 --118,40,10 --118,40,18 --118,40,26 --118,40,34 --118,40,42 --118,40,50 --118,40,58 --118,40,66 --118,40,74 --118,40,82 --118,40,90 --118,40,98 --118,40,106 --118,40,114 --118,40,122 --118,40,130 --118,40,138 --118,40,146 --110,40,-150 --110,40,-142 --110,40,-134 --110,40,-126 --110,40,-118 --110,40,-110 --110,40,-102 --110,40,-94 --110,40,-86 --110,40,-78 --110,40,-70 --110,40,-62 --110,40,-54 --110,40,-46 --110,40,-38 --110,40,-30 --110,40,-22 --110,40,-14 --110,40,-6 --110,40,2 --110,40,10 --110,40,18 --110,40,26 --110,40,34 --110,40,42 --110,40,50 --110,40,58 --110,40,66 --110,40,74 --110,40,82 --110,40,90 --110,40,98 --110,40,106 --110,40,114 --110,40,122 --110,40,130 --110,40,138 --110,40,146 --102,40,-150 --102,40,-142 --102,40,-134 --102,40,-126 --102,40,-118 --102,40,-110 --102,40,-102 --102,40,-94 --102,40,-86 --102,40,-78 --102,40,-70 --102,40,-62 --102,40,-54 --102,40,-46 --102,40,-38 --102,40,-30 --102,40,-22 --102,40,-14 --102,40,-6 --102,40,2 --102,40,10 --102,40,18 --102,40,26 --102,40,34 --102,40,42 --102,40,50 --102,40,58 --102,40,66 --102,40,74 --102,40,82 --102,40,90 --102,40,98 --102,40,106 --102,40,114 --102,40,122 --102,40,130 --102,40,138 --102,40,146 --94,40,-150 --94,40,-142 --94,40,-134 --94,40,-126 --94,40,-118 --94,40,-110 --94,40,-102 --94,40,-94 --94,40,-86 --94,40,-78 --94,40,-70 --94,40,-62 --94,40,-54 --94,40,-46 --94,40,-38 --94,40,-30 --94,40,-22 --94,40,-14 --94,40,-6 --94,40,2 --94,40,10 --94,40,18 --94,40,26 --94,40,34 --94,40,42 --94,40,50 --94,40,58 --94,40,66 --94,40,74 --94,40,82 --94,40,90 --94,40,98 --94,40,106 --94,40,114 --94,40,122 --94,40,130 --94,40,138 --94,40,146 --86,40,-150 --86,40,-142 --86,40,-134 --86,40,-126 --86,40,-118 --86,40,-110 --86,40,-102 --86,40,-94 --86,40,-86 --86,40,-78 --86,40,-70 --86,40,-62 --86,40,-54 --86,40,-46 --86,40,-38 --86,40,-30 --86,40,-22 --86,40,-14 --86,40,-6 --86,40,2 --86,40,10 --86,40,18 --86,40,26 --86,40,34 --86,40,42 --86,40,50 --86,40,58 --86,40,66 --86,40,74 --86,40,82 --86,40,90 --86,40,98 --86,40,106 --86,40,114 --86,40,122 --86,40,130 --86,40,138 --86,40,146 --78,40,-150 --78,40,-142 --78,40,-134 --78,40,-126 --78,40,-118 --78,40,-110 --78,40,-102 --78,40,-94 --78,40,-86 --78,40,-78 --78,40,-70 --78,40,-62 --78,40,-54 --78,40,-46 --78,40,-38 --78,40,-30 --78,40,-22 --78,40,-14 --78,40,-6 --78,40,2 --78,40,10 --78,40,18 --78,40,26 --78,40,34 --78,40,42 --78,40,50 --78,40,58 --78,40,66 --78,40,74 --78,40,82 --78,40,90 --78,40,98 --78,40,106 --78,40,114 --78,40,122 --78,40,130 --78,40,138 --78,40,146 --70,40,-150 --70,40,-142 --70,40,-134 --70,40,-126 --70,40,-118 --70,40,-110 --70,40,-102 --70,40,-94 --70,40,-86 --70,40,-78 --70,40,-70 --70,40,-62 --70,40,-54 --70,40,-46 --70,40,-38 --70,40,-30 --70,40,-22 --70,40,-14 --70,40,-6 --70,40,2 --70,40,10 --70,40,18 --70,40,26 --70,40,34 --70,40,42 --70,40,50 --70,40,58 --70,40,66 --70,40,74 --70,40,82 --70,40,90 --70,40,98 --70,40,106 --70,40,114 --70,40,122 --70,40,130 --70,40,138 --70,40,146 --62,40,-150 --62,40,-142 --62,40,-134 --62,40,-126 --62,40,-118 --62,40,-110 --62,40,-102 --62,40,-94 --62,40,-86 --62,40,-78 --62,40,-70 --62,40,-62 --62,40,-54 --62,40,-46 --62,40,-38 --62,40,-30 --62,40,-22 --62,40,-14 --62,40,-6 --62,40,2 --62,40,10 --62,40,18 --62,40,26 --62,40,34 --62,40,42 --62,40,50 --62,40,58 --62,40,66 --62,40,74 --62,40,82 --62,40,90 --62,40,98 --62,40,106 --62,40,114 --62,40,122 --62,40,130 --62,40,138 --62,40,146 --54,40,-150 --54,40,-142 --54,40,-134 --54,40,-126 --54,40,-118 --54,40,-110 --54,40,-102 --54,40,-94 --54,40,-86 --54,40,-78 --54,40,-70 --54,40,-62 --54,40,-54 --54,40,-46 --54,40,-38 --54,40,-30 --54,40,-22 --54,40,-14 --54,40,-6 --54,40,2 --54,40,10 --54,40,18 --54,40,26 --54,40,34 --54,40,42 --54,40,50 --54,40,58 --54,40,66 --54,40,74 --54,40,82 --54,40,90 --54,40,98 --54,40,106 --54,40,114 --54,40,122 --54,40,130 --54,40,138 --54,40,146 --46,40,-150 --46,40,-142 --46,40,-134 --46,40,-126 --46,40,-118 --46,40,-110 --46,40,-102 --46,40,-94 --46,40,-86 --46,40,-78 --46,40,-70 --46,40,-62 --46,40,-54 --46,40,-46 --46,40,-38 --46,40,-30 --46,40,-22 --46,40,-14 --46,40,-6 --46,40,2 --46,40,10 --46,40,18 --46,40,26 --46,40,34 --46,40,42 --46,40,50 --46,40,58 --46,40,66 --46,40,74 --46,40,82 --46,40,90 --46,40,98 --46,40,106 --46,40,114 --46,40,122 --46,40,130 --46,40,138 --46,40,146 --38,40,-150 --38,40,-142 --38,40,-134 --38,40,-126 --38,40,-118 --38,40,-110 --38,40,-102 --38,40,-94 --38,40,-86 --38,40,-78 --38,40,-70 --38,40,-62 --38,40,-54 --38,40,-46 --38,40,-38 --38,40,-30 --38,40,-22 --38,40,-14 --38,40,-6 --38,40,2 --38,40,10 --38,40,18 --38,40,26 --38,40,34 --38,40,42 --38,40,50 --38,40,58 --38,40,66 --38,40,74 --38,40,82 --38,40,90 --38,40,98 --38,40,106 --38,40,114 --38,40,122 --38,40,130 --38,40,138 --38,40,146 --30,40,-150 --30,40,-142 --30,40,-134 --30,40,-126 --30,40,-118 --30,40,-110 --30,40,-102 --30,40,-94 --30,40,-86 --30,40,-78 --30,40,-70 --30,40,-62 --30,40,-54 --30,40,-46 --30,40,-38 --30,40,-30 --30,40,-22 --30,40,-14 --30,40,-6 --30,40,2 --30,40,10 --30,40,18 --30,40,26 --30,40,34 --30,40,42 --30,40,50 --30,40,58 --30,40,66 --30,40,74 --30,40,82 --30,40,90 --30,40,98 --30,40,106 --30,40,114 --30,40,122 --30,40,130 --30,40,138 --30,40,146 --22,40,-150 --22,40,-142 --22,40,-134 --22,40,-126 --22,40,-118 --22,40,-110 --22,40,-102 --22,40,-94 --22,40,-86 --22,40,-78 --22,40,-70 --22,40,-62 --22,40,-54 --22,40,-46 --22,40,-38 --22,40,-30 --22,40,-22 --22,40,-14 --22,40,-6 --22,40,2 --22,40,10 --22,40,18 --22,40,26 --22,40,34 --22,40,42 --22,40,50 --22,40,58 --22,40,66 --22,40,74 --22,40,82 --22,40,90 --22,40,98 --22,40,106 --22,40,114 --22,40,122 --22,40,130 --22,40,138 --22,40,146 --14,40,-150 --14,40,-142 --14,40,-134 --14,40,-126 --14,40,-118 --14,40,-110 --14,40,-102 --14,40,-94 --14,40,-86 --14,40,-78 --14,40,-70 --14,40,-62 --14,40,-54 --14,40,-46 --14,40,-38 --14,40,-30 --14,40,-22 --14,40,-14 --14,40,-6 --14,40,2 --14,40,10 --14,40,18 --14,40,26 --14,40,34 --14,40,42 --14,40,50 --14,40,58 --14,40,66 --14,40,74 --14,40,82 --14,40,90 --14,40,98 --14,40,106 --14,40,114 --14,40,122 --14,40,130 --14,40,138 --14,40,146 --6,40,-150 --6,40,-142 --6,40,-134 --6,40,-126 --6,40,-118 --6,40,-110 --6,40,-102 --6,40,-94 --6,40,-86 --6,40,-78 --6,40,-70 --6,40,-62 --6,40,-54 --6,40,-46 --6,40,-38 --6,40,-30 --6,40,-22 --6,40,-14 --6,40,-6 --6,40,2 --6,40,10 --6,40,18 --6,40,26 --6,40,34 --6,40,42 --6,40,50 --6,40,58 --6,40,66 --6,40,74 --6,40,82 --6,40,90 --6,40,98 --6,40,106 --6,40,114 --6,40,122 --6,40,130 --6,40,138 --6,40,146 -2,40,-150 -2,40,-142 -2,40,-134 -2,40,-126 -2,40,-118 -2,40,-110 -2,40,-102 -2,40,-94 -2,40,-86 -2,40,-78 -2,40,-70 -2,40,-62 -2,40,-54 -2,40,-46 -2,40,-38 -2,40,-30 -2,40,-22 -2,40,-14 -2,40,-6 -2,40,2 -2,40,10 -2,40,18 -2,40,26 -2,40,34 -2,40,42 -2,40,50 -2,40,58 -2,40,66 -2,40,74 -2,40,82 -2,40,90 -2,40,98 -2,40,106 -2,40,114 -2,40,122 -2,40,130 -2,40,138 -2,40,146 -10,40,-150 -10,40,-142 -10,40,-134 -10,40,-126 -10,40,-118 -10,40,-110 -10,40,-102 -10,40,-94 -10,40,-86 -10,40,-78 -10,40,-70 -10,40,-62 -10,40,-54 -10,40,-46 -10,40,-38 -10,40,-30 -10,40,-22 -10,40,-14 -10,40,-6 -10,40,2 -10,40,10 -10,40,18 -10,40,26 -10,40,34 -10,40,42 -10,40,50 -10,40,58 -10,40,66 -10,40,74 -10,40,82 -10,40,90 -10,40,98 -10,40,106 -10,40,114 -10,40,122 -10,40,130 -10,40,138 -10,40,146 -18,40,-150 -18,40,-142 -18,40,-134 -18,40,-126 -18,40,-118 -18,40,-110 -18,40,-102 -18,40,-94 -18,40,-86 -18,40,-78 -18,40,-70 -18,40,-62 -18,40,-54 -18,40,-46 -18,40,-38 -18,40,-30 -18,40,-22 -18,40,-14 -18,40,-6 -18,40,2 -18,40,10 -18,40,18 -18,40,26 -18,40,34 -18,40,42 -18,40,50 -18,40,58 -18,40,66 -18,40,74 -18,40,82 -18,40,90 -18,40,98 -18,40,106 -18,40,114 -18,40,122 -18,40,130 -18,40,138 -18,40,146 -26,40,-150 -26,40,-142 -26,40,-134 -26,40,-126 -26,40,-118 -26,40,-110 -26,40,-102 -26,40,-94 -26,40,-86 -26,40,-78 -26,40,-70 -26,40,-62 -26,40,-54 -26,40,-46 -26,40,-38 -26,40,-30 -26,40,-22 -26,40,-14 -26,40,-6 -26,40,2 -26,40,10 -26,40,18 -26,40,26 -26,40,34 -26,40,42 -26,40,50 -26,40,58 -26,40,66 -26,40,74 -26,40,82 -26,40,90 -26,40,98 -26,40,106 -26,40,114 -26,40,122 -26,40,130 -26,40,138 -26,40,146 -34,40,-150 -34,40,-142 -34,40,-134 -34,40,-126 -34,40,-118 -34,40,-110 -34,40,-102 -34,40,-94 -34,40,-86 -34,40,-78 -34,40,-70 -34,40,-62 -34,40,-54 -34,40,-46 -34,40,-38 -34,40,-30 -34,40,-22 -34,40,-14 -34,40,-6 -34,40,2 -34,40,10 -34,40,18 -34,40,26 -34,40,34 -34,40,42 -34,40,50 -34,40,58 -34,40,66 -34,40,74 -34,40,82 -34,40,90 -34,40,98 -34,40,106 -34,40,114 -34,40,122 -34,40,130 -34,40,138 -34,40,146 -42,40,-150 -42,40,-142 -42,40,-134 -42,40,-126 -42,40,-118 -42,40,-110 -42,40,-102 -42,40,-94 -42,40,-86 -42,40,-78 -42,40,-70 -42,40,-62 -42,40,-54 -42,40,-46 -42,40,-38 -42,40,-30 -42,40,-22 -42,40,-14 -42,40,-6 -42,40,2 -42,40,10 -42,40,18 -42,40,26 -42,40,34 -42,40,42 -42,40,50 -42,40,58 -42,40,66 -42,40,74 -42,40,82 -42,40,90 -42,40,98 -42,40,106 -42,40,114 -42,40,122 -42,40,130 -42,40,138 -42,40,146 -50,40,-150 -50,40,-142 -50,40,-134 -50,40,-126 -50,40,-118 -50,40,-110 -50,40,-102 -50,40,-94 -50,40,-86 -50,40,-78 -50,40,-70 -50,40,-62 -50,40,-54 -50,40,-46 -50,40,-38 -50,40,-30 -50,40,-22 -50,40,-14 -50,40,-6 -50,40,2 -50,40,10 -50,40,18 -50,40,26 -50,40,34 -50,40,42 -50,40,50 -50,40,58 -50,40,66 -50,40,74 -50,40,82 -50,40,90 -50,40,98 -50,40,106 -50,40,114 -50,40,122 -50,40,130 -50,40,138 -50,40,146 -58,40,-150 -58,40,-142 -58,40,-134 -58,40,-126 -58,40,-118 -58,40,-110 -58,40,-102 -58,40,-94 -58,40,-86 -58,40,-78 -58,40,-70 -58,40,-62 -58,40,-54 -58,40,-46 -58,40,-38 -58,40,-30 -58,40,-22 -58,40,-14 -58,40,-6 -58,40,2 -58,40,10 -58,40,18 -58,40,26 -58,40,34 -58,40,42 -58,40,50 -58,40,58 -58,40,66 -58,40,74 -58,40,82 -58,40,90 -58,40,98 -58,40,106 -58,40,114 -58,40,122 -58,40,130 -58,40,138 -58,40,146 -66,40,-150 -66,40,-142 -66,40,-134 -66,40,-126 -66,40,-118 -66,40,-110 -66,40,-102 -66,40,-94 -66,40,-86 -66,40,-78 -66,40,-70 -66,40,-62 -66,40,-54 -66,40,-46 -66,40,-38 -66,40,-30 -66,40,-22 -66,40,-14 -66,40,-6 -66,40,2 -66,40,10 -66,40,18 -66,40,26 -66,40,34 -66,40,42 -66,40,50 -66,40,58 -66,40,66 -66,40,74 -66,40,82 -66,40,90 -66,40,98 -66,40,106 -66,40,114 -66,40,122 -66,40,130 -66,40,138 -66,40,146 -74,40,-150 -74,40,-142 -74,40,-134 -74,40,-126 -74,40,-118 -74,40,-110 -74,40,-102 -74,40,-94 -74,40,-86 -74,40,-78 -74,40,-70 -74,40,-62 -74,40,-54 -74,40,-46 -74,40,-38 -74,40,-30 -74,40,-22 -74,40,-14 -74,40,-6 -74,40,2 -74,40,10 -74,40,18 -74,40,26 -74,40,34 -74,40,42 -74,40,50 -74,40,58 -74,40,66 -74,40,74 -74,40,82 -74,40,90 -74,40,98 -74,40,106 -74,40,114 -74,40,122 -74,40,130 -74,40,138 -74,40,146 -82,40,-150 -82,40,-142 -82,40,-134 -82,40,-126 -82,40,-118 -82,40,-110 -82,40,-102 -82,40,-94 -82,40,-86 -82,40,-78 -82,40,-70 -82,40,-62 -82,40,-54 -82,40,-46 -82,40,-38 -82,40,-30 -82,40,-22 -82,40,-14 -82,40,-6 -82,40,2 -82,40,10 -82,40,18 -82,40,26 -82,40,34 -82,40,42 -82,40,50 -82,40,58 -82,40,66 -82,40,74 -82,40,82 -82,40,90 -82,40,98 -82,40,106 -82,40,114 -82,40,122 -82,40,130 -82,40,138 -82,40,146 -90,40,-150 -90,40,-142 -90,40,-134 -90,40,-126 -90,40,-118 -90,40,-110 -90,40,-102 -90,40,-94 -90,40,-86 -90,40,-78 -90,40,-70 -90,40,-62 -90,40,-54 -90,40,-46 -90,40,-38 -90,40,-30 -90,40,-22 -90,40,-14 -90,40,-6 -90,40,2 -90,40,10 -90,40,18 -90,40,26 -90,40,34 -90,40,42 -90,40,50 -90,40,58 -90,40,66 -90,40,74 -90,40,82 -90,40,90 -90,40,98 -90,40,106 -90,40,114 -90,40,122 -90,40,130 -90,40,138 -90,40,146 -98,40,-150 -98,40,-142 -98,40,-134 -98,40,-126 -98,40,-118 -98,40,-110 -98,40,-102 -98,40,-94 -98,40,-86 -98,40,-78 -98,40,-70 -98,40,-62 -98,40,-54 -98,40,-46 -98,40,-38 -98,40,-30 -98,40,-22 -98,40,-14 -98,40,-6 -98,40,2 -98,40,10 -98,40,18 -98,40,26 -98,40,34 -98,40,42 -98,40,50 -98,40,58 -98,40,66 -98,40,74 -98,40,82 -98,40,90 -98,40,98 -98,40,106 -98,40,114 -98,40,122 -98,40,130 -98,40,138 -98,40,146 -106,40,-150 -106,40,-142 -106,40,-134 -106,40,-126 -106,40,-118 -106,40,-110 -106,40,-102 -106,40,-94 -106,40,-86 -106,40,-78 -106,40,-70 -106,40,-62 -106,40,-54 -106,40,-46 -106,40,-38 -106,40,-30 -106,40,-22 -106,40,-14 -106,40,-6 -106,40,2 -106,40,10 -106,40,18 -106,40,26 -106,40,34 -106,40,42 -106,40,50 -106,40,58 -106,40,66 -106,40,74 -106,40,82 -106,40,90 -106,40,98 -106,40,106 -106,40,114 -106,40,122 -106,40,130 -106,40,138 -106,40,146 -114,40,-150 -114,40,-142 -114,40,-134 -114,40,-126 -114,40,-118 -114,40,-110 -114,40,-102 -114,40,-94 -114,40,-86 -114,40,-78 -114,40,-70 -114,40,-62 -114,40,-54 -114,40,-46 -114,40,-38 -114,40,-30 -114,40,-22 -114,40,-14 -114,40,-6 -114,40,2 -114,40,10 -114,40,18 -114,40,26 -114,40,34 -114,40,42 -114,40,50 -114,40,58 -114,40,66 -114,40,74 -114,40,82 -114,40,90 -114,40,98 -114,40,106 -114,40,114 -114,40,122 -114,40,130 -114,40,138 -114,40,146 -122,40,-150 -122,40,-142 -122,40,-134 -122,40,-126 -122,40,-118 -122,40,-110 -122,40,-102 -122,40,-94 -122,40,-86 -122,40,-78 -122,40,-70 -122,40,-62 -122,40,-54 -122,40,-46 -122,40,-38 -122,40,-30 -122,40,-22 -122,40,-14 -122,40,-6 -122,40,2 -122,40,10 -122,40,18 -122,40,26 -122,40,34 -122,40,42 -122,40,50 -122,40,58 -122,40,66 -122,40,74 -122,40,82 -122,40,90 -122,40,98 -122,40,106 -122,40,114 -122,40,122 -122,40,130 -122,40,138 -122,40,146 -130,40,-150 -130,40,-142 -130,40,-134 -130,40,-126 -130,40,-118 -130,40,-110 -130,40,-102 -130,40,-94 -130,40,-86 -130,40,-78 -130,40,-70 -130,40,-62 -130,40,-54 -130,40,-46 -130,40,-38 -130,40,-30 -130,40,-22 -130,40,-14 -130,40,-6 -130,40,2 -130,40,10 -130,40,18 -130,40,26 -130,40,34 -130,40,42 -130,40,50 -130,40,58 -130,40,66 -130,40,74 -130,40,82 -130,40,90 -130,40,98 -130,40,106 -130,40,114 -130,40,122 -130,40,130 -130,40,138 -130,40,146 -138,40,-150 -138,40,-142 -138,40,-134 -138,40,-126 -138,40,-118 -138,40,-110 -138,40,-102 -138,40,-94 -138,40,-86 -138,40,-78 -138,40,-70 -138,40,-62 -138,40,-54 -138,40,-46 -138,40,-38 -138,40,-30 -138,40,-22 -138,40,-14 -138,40,-6 -138,40,2 -138,40,10 -138,40,18 -138,40,26 -138,40,34 -138,40,42 -138,40,50 -138,40,58 -138,40,66 -138,40,74 -138,40,82 -138,40,90 -138,40,98 -138,40,106 -138,40,114 -138,40,122 -138,40,130 -138,40,138 -138,40,146 -146,40,-150 -146,40,-142 -146,40,-134 -146,40,-126 -146,40,-118 -146,40,-110 -146,40,-102 -146,40,-94 -146,40,-86 -146,40,-78 -146,40,-70 -146,40,-62 -146,40,-54 -146,40,-46 -146,40,-38 -146,40,-30 -146,40,-22 -146,40,-14 -146,40,-6 -146,40,2 -146,40,10 -146,40,18 -146,40,26 -146,40,34 -146,40,42 -146,40,50 -146,40,58 -146,40,66 -146,40,74 -146,40,82 -146,40,90 -146,40,98 -146,40,106 -146,40,114 -146,40,122 -146,40,130 -146,40,138 -146,40,146 --150,48,-150 --150,48,-142 --150,48,-134 --150,48,-126 --150,48,-118 --150,48,-110 --150,48,-102 --150,48,-94 --150,48,-86 --150,48,-78 --150,48,-70 --150,48,-62 --150,48,-54 --150,48,-46 --150,48,-38 --150,48,-30 --150,48,-22 --150,48,-14 --150,48,-6 --150,48,2 --150,48,10 --150,48,18 --150,48,26 --150,48,34 --150,48,42 --150,48,50 --150,48,58 --150,48,66 --150,48,74 --150,48,82 --150,48,90 --150,48,98 --150,48,106 --150,48,114 --150,48,122 --150,48,130 --150,48,138 --150,48,146 --142,48,-150 --142,48,-142 --142,48,-134 --142,48,-126 --142,48,-118 --142,48,-110 --142,48,-102 --142,48,-94 --142,48,-86 --142,48,-78 --142,48,-70 --142,48,-62 --142,48,-54 --142,48,-46 --142,48,-38 --142,48,-30 --142,48,-22 --142,48,-14 --142,48,-6 --142,48,2 --142,48,10 --142,48,18 --142,48,26 --142,48,34 --142,48,42 --142,48,50 --142,48,58 --142,48,66 --142,48,74 --142,48,82 --142,48,90 --142,48,98 --142,48,106 --142,48,114 --142,48,122 --142,48,130 --142,48,138 --142,48,146 --134,48,-150 --134,48,-142 --134,48,-134 --134,48,-126 --134,48,-118 --134,48,-110 --134,48,-102 --134,48,-94 --134,48,-86 --134,48,-78 --134,48,-70 --134,48,-62 --134,48,-54 --134,48,-46 --134,48,-38 --134,48,-30 --134,48,-22 --134,48,-14 --134,48,-6 --134,48,2 --134,48,10 --134,48,18 --134,48,26 --134,48,34 --134,48,42 --134,48,50 --134,48,58 --134,48,66 --134,48,74 --134,48,82 --134,48,90 --134,48,98 --134,48,106 --134,48,114 --134,48,122 --134,48,130 --134,48,138 --134,48,146 --126,48,-150 --126,48,-142 --126,48,-134 --126,48,-126 --126,48,-118 --126,48,-110 --126,48,-102 --126,48,-94 --126,48,-86 --126,48,-78 --126,48,-70 --126,48,-62 --126,48,-54 --126,48,-46 --126,48,-38 --126,48,-30 --126,48,-22 --126,48,-14 --126,48,-6 --126,48,2 --126,48,10 --126,48,18 --126,48,26 --126,48,34 --126,48,42 --126,48,50 --126,48,58 --126,48,66 --126,48,74 --126,48,82 --126,48,90 --126,48,98 --126,48,106 --126,48,114 --126,48,122 --126,48,130 --126,48,138 --126,48,146 --118,48,-150 --118,48,-142 --118,48,-134 --118,48,-126 --118,48,-118 --118,48,-110 --118,48,-102 --118,48,-94 --118,48,-86 --118,48,-78 --118,48,-70 --118,48,-62 --118,48,-54 --118,48,-46 --118,48,-38 --118,48,-30 --118,48,-22 --118,48,-14 --118,48,-6 --118,48,2 --118,48,10 --118,48,18 --118,48,26 --118,48,34 --118,48,42 --118,48,50 --118,48,58 --118,48,66 --118,48,74 --118,48,82 --118,48,90 --118,48,98 --118,48,106 --118,48,114 --118,48,122 --118,48,130 --118,48,138 --118,48,146 --110,48,-150 --110,48,-142 --110,48,-134 --110,48,-126 --110,48,-118 --110,48,-110 --110,48,-102 --110,48,-94 --110,48,-86 --110,48,-78 --110,48,-70 --110,48,-62 --110,48,-54 --110,48,-46 --110,48,-38 --110,48,-30 --110,48,-22 --110,48,-14 --110,48,-6 --110,48,2 --110,48,10 --110,48,18 --110,48,26 --110,48,34 --110,48,42 --110,48,50 --110,48,58 --110,48,66 --110,48,74 --110,48,82 --110,48,90 --110,48,98 --110,48,106 --110,48,114 --110,48,122 --110,48,130 --110,48,138 --110,48,146 --102,48,-150 --102,48,-142 --102,48,-134 --102,48,-126 --102,48,-118 --102,48,-110 --102,48,-102 --102,48,-94 --102,48,-86 --102,48,-78 --102,48,-70 --102,48,-62 --102,48,-54 --102,48,-46 --102,48,-38 --102,48,-30 --102,48,-22 --102,48,-14 --102,48,-6 --102,48,2 --102,48,10 --102,48,18 --102,48,26 --102,48,34 --102,48,42 --102,48,50 --102,48,58 --102,48,66 --102,48,74 --102,48,82 --102,48,90 --102,48,98 --102,48,106 --102,48,114 --102,48,122 --102,48,130 --102,48,138 --102,48,146 --94,48,-150 --94,48,-142 --94,48,-134 --94,48,-126 --94,48,-118 --94,48,-110 --94,48,-102 --94,48,-94 --94,48,-86 --94,48,-78 --94,48,-70 --94,48,-62 --94,48,-54 --94,48,-46 --94,48,-38 --94,48,-30 --94,48,-22 --94,48,-14 --94,48,-6 --94,48,2 --94,48,10 --94,48,18 --94,48,26 --94,48,34 --94,48,42 --94,48,50 --94,48,58 --94,48,66 --94,48,74 --94,48,82 --94,48,90 --94,48,98 --94,48,106 --94,48,114 --94,48,122 --94,48,130 --94,48,138 --94,48,146 --86,48,-150 --86,48,-142 --86,48,-134 --86,48,-126 --86,48,-118 --86,48,-110 --86,48,-102 --86,48,-94 --86,48,-86 --86,48,-78 --86,48,-70 --86,48,-62 --86,48,-54 --86,48,-46 --86,48,-38 --86,48,-30 --86,48,-22 --86,48,-14 --86,48,-6 --86,48,2 --86,48,10 --86,48,18 --86,48,26 --86,48,34 --86,48,42 --86,48,50 --86,48,58 --86,48,66 --86,48,74 --86,48,82 --86,48,90 --86,48,98 --86,48,106 --86,48,114 --86,48,122 --86,48,130 --86,48,138 --86,48,146 --78,48,-150 --78,48,-142 --78,48,-134 --78,48,-126 --78,48,-118 --78,48,-110 --78,48,-102 --78,48,-94 --78,48,-86 --78,48,-78 --78,48,-70 --78,48,-62 --78,48,-54 --78,48,-46 --78,48,-38 --78,48,-30 --78,48,-22 --78,48,-14 --78,48,-6 --78,48,2 --78,48,10 --78,48,18 --78,48,26 --78,48,34 --78,48,42 --78,48,50 --78,48,58 --78,48,66 --78,48,74 --78,48,82 --78,48,90 --78,48,98 --78,48,106 --78,48,114 --78,48,122 --78,48,130 --78,48,138 --78,48,146 --70,48,-150 --70,48,-142 --70,48,-134 --70,48,-126 --70,48,-118 --70,48,-110 --70,48,-102 --70,48,-94 --70,48,-86 --70,48,-78 --70,48,-70 --70,48,-62 --70,48,-54 --70,48,-46 --70,48,-38 --70,48,-30 --70,48,-22 --70,48,-14 --70,48,-6 --70,48,2 --70,48,10 --70,48,18 --70,48,26 --70,48,34 --70,48,42 --70,48,50 --70,48,58 --70,48,66 --70,48,74 --70,48,82 --70,48,90 --70,48,98 --70,48,106 --70,48,114 --70,48,122 --70,48,130 --70,48,138 --70,48,146 --62,48,-150 --62,48,-142 --62,48,-134 --62,48,-126 --62,48,-118 --62,48,-110 --62,48,-102 --62,48,-94 --62,48,-86 --62,48,-78 --62,48,-70 --62,48,-62 --62,48,-54 --62,48,-46 --62,48,-38 --62,48,-30 --62,48,-22 --62,48,-14 --62,48,-6 --62,48,2 --62,48,10 --62,48,18 --62,48,26 --62,48,34 --62,48,42 --62,48,50 --62,48,58 --62,48,66 --62,48,74 --62,48,82 --62,48,90 --62,48,98 --62,48,106 --62,48,114 --62,48,122 --62,48,130 --62,48,138 --62,48,146 --54,48,-150 --54,48,-142 --54,48,-134 --54,48,-126 --54,48,-118 --54,48,-110 --54,48,-102 --54,48,-94 --54,48,-86 --54,48,-78 --54,48,-70 --54,48,-62 --54,48,-54 --54,48,-46 --54,48,-38 --54,48,-30 --54,48,-22 --54,48,-14 --54,48,-6 --54,48,2 --54,48,10 --54,48,18 --54,48,26 --54,48,34 --54,48,42 --54,48,50 --54,48,58 --54,48,66 --54,48,74 --54,48,82 --54,48,90 --54,48,98 --54,48,106 --54,48,114 --54,48,122 --54,48,130 --54,48,138 --54,48,146 --46,48,-150 --46,48,-142 --46,48,-134 --46,48,-126 --46,48,-118 --46,48,-110 --46,48,-102 --46,48,-94 --46,48,-86 --46,48,-78 --46,48,-70 --46,48,-62 --46,48,-54 --46,48,-46 --46,48,-38 --46,48,-30 --46,48,-22 --46,48,-14 --46,48,-6 --46,48,2 --46,48,10 --46,48,18 --46,48,26 --46,48,34 --46,48,42 --46,48,50 --46,48,58 --46,48,66 --46,48,74 --46,48,82 --46,48,90 --46,48,98 --46,48,106 --46,48,114 --46,48,122 --46,48,130 --46,48,138 --46,48,146 --38,48,-150 --38,48,-142 --38,48,-134 --38,48,-126 --38,48,-118 --38,48,-110 --38,48,-102 --38,48,-94 --38,48,-86 --38,48,-78 --38,48,-70 --38,48,-62 --38,48,-54 --38,48,-46 --38,48,-38 --38,48,-30 --38,48,-22 --38,48,-14 --38,48,-6 --38,48,2 --38,48,10 --38,48,18 --38,48,26 --38,48,34 --38,48,42 --38,48,50 --38,48,58 --38,48,66 --38,48,74 --38,48,82 --38,48,90 --38,48,98 --38,48,106 --38,48,114 --38,48,122 --38,48,130 --38,48,138 --38,48,146 --30,48,-150 --30,48,-142 --30,48,-134 --30,48,-126 --30,48,-118 --30,48,-110 --30,48,-102 --30,48,-94 --30,48,-86 --30,48,-78 --30,48,-70 --30,48,-62 --30,48,-54 --30,48,-46 --30,48,-38 --30,48,-30 --30,48,-22 --30,48,-14 --30,48,-6 --30,48,2 --30,48,10 --30,48,18 --30,48,26 --30,48,34 --30,48,42 --30,48,50 --30,48,58 --30,48,66 --30,48,74 --30,48,82 --30,48,90 --30,48,98 --30,48,106 --30,48,114 --30,48,122 --30,48,130 --30,48,138 --30,48,146 --22,48,-150 --22,48,-142 --22,48,-134 --22,48,-126 --22,48,-118 --22,48,-110 --22,48,-102 --22,48,-94 --22,48,-86 --22,48,-78 --22,48,-70 --22,48,-62 --22,48,-54 --22,48,-46 --22,48,-38 --22,48,-30 --22,48,-22 --22,48,-14 --22,48,-6 --22,48,2 --22,48,10 --22,48,18 --22,48,26 --22,48,34 --22,48,42 --22,48,50 --22,48,58 --22,48,66 --22,48,74 --22,48,82 --22,48,90 --22,48,98 --22,48,106 --22,48,114 --22,48,122 --22,48,130 --22,48,138 --22,48,146 --14,48,-150 --14,48,-142 --14,48,-134 --14,48,-126 --14,48,-118 --14,48,-110 --14,48,-102 --14,48,-94 --14,48,-86 --14,48,-78 --14,48,-70 --14,48,-62 --14,48,-54 --14,48,-46 --14,48,-38 --14,48,-30 --14,48,-22 --14,48,-14 --14,48,-6 --14,48,2 --14,48,10 --14,48,18 --14,48,26 --14,48,34 --14,48,42 --14,48,50 --14,48,58 --14,48,66 --14,48,74 --14,48,82 --14,48,90 --14,48,98 --14,48,106 --14,48,114 --14,48,122 --14,48,130 --14,48,138 --14,48,146 --6,48,-150 --6,48,-142 --6,48,-134 --6,48,-126 --6,48,-118 --6,48,-110 --6,48,-102 --6,48,-94 --6,48,-86 --6,48,-78 --6,48,-70 --6,48,-62 --6,48,-54 --6,48,-46 --6,48,-38 --6,48,-30 --6,48,-22 --6,48,-14 --6,48,-6 --6,48,2 --6,48,10 --6,48,18 --6,48,26 --6,48,34 --6,48,42 --6,48,50 --6,48,58 --6,48,66 --6,48,74 --6,48,82 --6,48,90 --6,48,98 --6,48,106 --6,48,114 --6,48,122 --6,48,130 --6,48,138 --6,48,146 -2,48,-150 -2,48,-142 -2,48,-134 -2,48,-126 -2,48,-118 -2,48,-110 -2,48,-102 -2,48,-94 -2,48,-86 -2,48,-78 -2,48,-70 -2,48,-62 -2,48,-54 -2,48,-46 -2,48,-38 -2,48,-30 -2,48,-22 -2,48,-14 -2,48,-6 -2,48,2 -2,48,10 -2,48,18 -2,48,26 -2,48,34 -2,48,42 -2,48,50 -2,48,58 -2,48,66 -2,48,74 -2,48,82 -2,48,90 -2,48,98 -2,48,106 -2,48,114 -2,48,122 -2,48,130 -2,48,138 -2,48,146 -10,48,-150 -10,48,-142 -10,48,-134 -10,48,-126 -10,48,-118 -10,48,-110 -10,48,-102 -10,48,-94 -10,48,-86 -10,48,-78 -10,48,-70 -10,48,-62 -10,48,-54 -10,48,-46 -10,48,-38 -10,48,-30 -10,48,-22 -10,48,-14 -10,48,-6 -10,48,2 -10,48,10 -10,48,18 -10,48,26 -10,48,34 -10,48,42 -10,48,50 -10,48,58 -10,48,66 -10,48,74 -10,48,82 -10,48,90 -10,48,98 -10,48,106 -10,48,114 -10,48,122 -10,48,130 -10,48,138 -10,48,146 -18,48,-150 -18,48,-142 -18,48,-134 -18,48,-126 -18,48,-118 -18,48,-110 -18,48,-102 -18,48,-94 -18,48,-86 -18,48,-78 -18,48,-70 -18,48,-62 -18,48,-54 -18,48,-46 -18,48,-38 -18,48,-30 -18,48,-22 -18,48,-14 -18,48,-6 -18,48,2 -18,48,10 -18,48,18 -18,48,26 -18,48,34 -18,48,42 -18,48,50 -18,48,58 -18,48,66 -18,48,74 -18,48,82 -18,48,90 -18,48,98 -18,48,106 -18,48,114 -18,48,122 -18,48,130 -18,48,138 -18,48,146 -26,48,-150 -26,48,-142 -26,48,-134 -26,48,-126 -26,48,-118 -26,48,-110 -26,48,-102 -26,48,-94 -26,48,-86 -26,48,-78 -26,48,-70 -26,48,-62 -26,48,-54 -26,48,-46 -26,48,-38 -26,48,-30 -26,48,-22 -26,48,-14 -26,48,-6 -26,48,2 -26,48,10 -26,48,18 -26,48,26 -26,48,34 -26,48,42 -26,48,50 -26,48,58 -26,48,66 -26,48,74 -26,48,82 -26,48,90 -26,48,98 -26,48,106 -26,48,114 -26,48,122 -26,48,130 -26,48,138 -26,48,146 -34,48,-150 -34,48,-142 -34,48,-134 -34,48,-126 -34,48,-118 -34,48,-110 -34,48,-102 -34,48,-94 -34,48,-86 -34,48,-78 -34,48,-70 -34,48,-62 -34,48,-54 -34,48,-46 -34,48,-38 -34,48,-30 -34,48,-22 -34,48,-14 -34,48,-6 -34,48,2 -34,48,10 -34,48,18 -34,48,26 -34,48,34 -34,48,42 -34,48,50 -34,48,58 -34,48,66 -34,48,74 -34,48,82 -34,48,90 -34,48,98 -34,48,106 -34,48,114 -34,48,122 -34,48,130 -34,48,138 -34,48,146 -42,48,-150 -42,48,-142 -42,48,-134 -42,48,-126 -42,48,-118 -42,48,-110 -42,48,-102 -42,48,-94 -42,48,-86 -42,48,-78 -42,48,-70 -42,48,-62 -42,48,-54 -42,48,-46 -42,48,-38 -42,48,-30 -42,48,-22 -42,48,-14 -42,48,-6 -42,48,2 -42,48,10 -42,48,18 -42,48,26 -42,48,34 -42,48,42 -42,48,50 -42,48,58 -42,48,66 -42,48,74 -42,48,82 -42,48,90 -42,48,98 -42,48,106 -42,48,114 -42,48,122 -42,48,130 -42,48,138 -42,48,146 -50,48,-150 -50,48,-142 -50,48,-134 -50,48,-126 -50,48,-118 -50,48,-110 -50,48,-102 -50,48,-94 -50,48,-86 -50,48,-78 -50,48,-70 -50,48,-62 -50,48,-54 -50,48,-46 -50,48,-38 -50,48,-30 -50,48,-22 -50,48,-14 -50,48,-6 -50,48,2 -50,48,10 -50,48,18 -50,48,26 -50,48,34 -50,48,42 -50,48,50 -50,48,58 -50,48,66 -50,48,74 -50,48,82 -50,48,90 -50,48,98 -50,48,106 -50,48,114 -50,48,122 -50,48,130 -50,48,138 -50,48,146 -58,48,-150 -58,48,-142 -58,48,-134 -58,48,-126 -58,48,-118 -58,48,-110 -58,48,-102 -58,48,-94 -58,48,-86 -58,48,-78 -58,48,-70 -58,48,-62 -58,48,-54 -58,48,-46 -58,48,-38 -58,48,-30 -58,48,-22 -58,48,-14 -58,48,-6 -58,48,2 -58,48,10 -58,48,18 -58,48,26 -58,48,34 -58,48,42 -58,48,50 -58,48,58 -58,48,66 -58,48,74 -58,48,82 -58,48,90 -58,48,98 -58,48,106 -58,48,114 -58,48,122 -58,48,130 -58,48,138 -58,48,146 -66,48,-150 -66,48,-142 -66,48,-134 -66,48,-126 -66,48,-118 -66,48,-110 -66,48,-102 -66,48,-94 -66,48,-86 -66,48,-78 -66,48,-70 -66,48,-62 -66,48,-54 -66,48,-46 -66,48,-38 -66,48,-30 -66,48,-22 -66,48,-14 -66,48,-6 -66,48,2 -66,48,10 -66,48,18 -66,48,26 -66,48,34 -66,48,42 -66,48,50 -66,48,58 -66,48,66 -66,48,74 -66,48,82 -66,48,90 -66,48,98 -66,48,106 -66,48,114 -66,48,122 -66,48,130 -66,48,138 -66,48,146 -74,48,-150 -74,48,-142 -74,48,-134 -74,48,-126 -74,48,-118 -74,48,-110 -74,48,-102 -74,48,-94 -74,48,-86 -74,48,-78 -74,48,-70 -74,48,-62 -74,48,-54 -74,48,-46 -74,48,-38 -74,48,-30 -74,48,-22 -74,48,-14 -74,48,-6 -74,48,2 -74,48,10 -74,48,18 -74,48,26 -74,48,34 -74,48,42 -74,48,50 -74,48,58 -74,48,66 -74,48,74 -74,48,82 -74,48,90 -74,48,98 -74,48,106 -74,48,114 -74,48,122 -74,48,130 -74,48,138 -74,48,146 -82,48,-150 -82,48,-142 -82,48,-134 -82,48,-126 -82,48,-118 -82,48,-110 -82,48,-102 -82,48,-94 -82,48,-86 -82,48,-78 -82,48,-70 -82,48,-62 -82,48,-54 -82,48,-46 -82,48,-38 -82,48,-30 -82,48,-22 -82,48,-14 -82,48,-6 -82,48,2 -82,48,10 -82,48,18 -82,48,26 -82,48,34 -82,48,42 -82,48,50 -82,48,58 -82,48,66 -82,48,74 -82,48,82 -82,48,90 -82,48,98 -82,48,106 -82,48,114 -82,48,122 -82,48,130 -82,48,138 -82,48,146 -90,48,-150 -90,48,-142 -90,48,-134 -90,48,-126 -90,48,-118 -90,48,-110 -90,48,-102 -90,48,-94 -90,48,-86 -90,48,-78 -90,48,-70 -90,48,-62 -90,48,-54 -90,48,-46 -90,48,-38 -90,48,-30 -90,48,-22 -90,48,-14 -90,48,-6 -90,48,2 -90,48,10 -90,48,18 -90,48,26 -90,48,34 -90,48,42 -90,48,50 -90,48,58 -90,48,66 -90,48,74 -90,48,82 -90,48,90 -90,48,98 -90,48,106 -90,48,114 -90,48,122 -90,48,130 -90,48,138 -90,48,146 -98,48,-150 -98,48,-142 -98,48,-134 -98,48,-126 -98,48,-118 -98,48,-110 -98,48,-102 -98,48,-94 -98,48,-86 -98,48,-78 -98,48,-70 -98,48,-62 -98,48,-54 -98,48,-46 -98,48,-38 -98,48,-30 -98,48,-22 -98,48,-14 -98,48,-6 -98,48,2 -98,48,10 -98,48,18 -98,48,26 -98,48,34 -98,48,42 -98,48,50 -98,48,58 -98,48,66 -98,48,74 -98,48,82 -98,48,90 -98,48,98 -98,48,106 -98,48,114 -98,48,122 -98,48,130 -98,48,138 -98,48,146 -106,48,-150 -106,48,-142 -106,48,-134 -106,48,-126 -106,48,-118 -106,48,-110 -106,48,-102 -106,48,-94 -106,48,-86 -106,48,-78 -106,48,-70 -106,48,-62 -106,48,-54 -106,48,-46 -106,48,-38 -106,48,-30 -106,48,-22 -106,48,-14 -106,48,-6 -106,48,2 -106,48,10 -106,48,18 -106,48,26 -106,48,34 -106,48,42 -106,48,50 -106,48,58 -106,48,66 -106,48,74 -106,48,82 -106,48,90 -106,48,98 -106,48,106 -106,48,114 -106,48,122 -106,48,130 -106,48,138 -106,48,146 -114,48,-150 -114,48,-142 -114,48,-134 -114,48,-126 -114,48,-118 -114,48,-110 -114,48,-102 -114,48,-94 -114,48,-86 -114,48,-78 -114,48,-70 -114,48,-62 -114,48,-54 -114,48,-46 -114,48,-38 -114,48,-30 -114,48,-22 -114,48,-14 -114,48,-6 -114,48,2 -114,48,10 -114,48,18 -114,48,26 -114,48,34 -114,48,42 -114,48,50 -114,48,58 -114,48,66 -114,48,74 -114,48,82 -114,48,90 -114,48,98 -114,48,106 -114,48,114 -114,48,122 -114,48,130 -114,48,138 -114,48,146 -122,48,-150 -122,48,-142 -122,48,-134 -122,48,-126 -122,48,-118 -122,48,-110 -122,48,-102 -122,48,-94 -122,48,-86 -122,48,-78 -122,48,-70 -122,48,-62 -122,48,-54 -122,48,-46 -122,48,-38 -122,48,-30 -122,48,-22 -122,48,-14 -122,48,-6 -122,48,2 -122,48,10 -122,48,18 -122,48,26 -122,48,34 -122,48,42 -122,48,50 -122,48,58 -122,48,66 -122,48,74 -122,48,82 -122,48,90 -122,48,98 -122,48,106 -122,48,114 -122,48,122 -122,48,130 -122,48,138 -122,48,146 -130,48,-150 -130,48,-142 -130,48,-134 -130,48,-126 -130,48,-118 -130,48,-110 -130,48,-102 -130,48,-94 -130,48,-86 -130,48,-78 -130,48,-70 -130,48,-62 -130,48,-54 -130,48,-46 -130,48,-38 -130,48,-30 -130,48,-22 -130,48,-14 -130,48,-6 -130,48,2 -130,48,10 -130,48,18 -130,48,26 -130,48,34 -130,48,42 -130,48,50 -130,48,58 -130,48,66 -130,48,74 -130,48,82 -130,48,90 -130,48,98 -130,48,106 -130,48,114 -130,48,122 -130,48,130 -130,48,138 -130,48,146 -138,48,-150 -138,48,-142 -138,48,-134 -138,48,-126 -138,48,-118 -138,48,-110 -138,48,-102 -138,48,-94 -138,48,-86 -138,48,-78 -138,48,-70 -138,48,-62 -138,48,-54 -138,48,-46 -138,48,-38 -138,48,-30 -138,48,-22 -138,48,-14 -138,48,-6 -138,48,2 -138,48,10 -138,48,18 -138,48,26 -138,48,34 -138,48,42 -138,48,50 -138,48,58 -138,48,66 -138,48,74 -138,48,82 -138,48,90 -138,48,98 -138,48,106 -138,48,114 -138,48,122 -138,48,130 -138,48,138 -138,48,146 -146,48,-150 -146,48,-142 -146,48,-134 -146,48,-126 -146,48,-118 -146,48,-110 -146,48,-102 -146,48,-94 -146,48,-86 -146,48,-78 -146,48,-70 -146,48,-62 -146,48,-54 -146,48,-46 -146,48,-38 -146,48,-30 -146,48,-22 -146,48,-14 -146,48,-6 -146,48,2 -146,48,10 -146,48,18 -146,48,26 -146,48,34 -146,48,42 -146,48,50 -146,48,58 -146,48,66 -146,48,74 -146,48,82 -146,48,90 -146,48,98 -146,48,106 -146,48,114 -146,48,122 -146,48,130 -146,48,138 -146,48,146 --150,56,-150 --150,56,-142 --150,56,-134 --150,56,-126 --150,56,-118 --150,56,-110 --150,56,-102 --150,56,-94 --150,56,-86 --150,56,-78 --150,56,-70 --150,56,-62 --150,56,-54 --150,56,-46 --150,56,-38 --150,56,-30 --150,56,-22 --150,56,-14 --150,56,-6 --150,56,2 --150,56,10 --150,56,18 --150,56,26 --150,56,34 --150,56,42 --150,56,50 --150,56,58 --150,56,66 --150,56,74 --150,56,82 --150,56,90 --150,56,98 --150,56,106 --150,56,114 --150,56,122 --150,56,130 --150,56,138 --150,56,146 --142,56,-150 --142,56,-142 --142,56,-134 --142,56,-126 --142,56,-118 --142,56,-110 --142,56,-102 --142,56,-94 --142,56,-86 --142,56,-78 --142,56,-70 --142,56,-62 --142,56,-54 --142,56,-46 --142,56,-38 --142,56,-30 --142,56,-22 --142,56,-14 --142,56,-6 --142,56,2 --142,56,10 --142,56,18 --142,56,26 --142,56,34 --142,56,42 --142,56,50 --142,56,58 --142,56,66 --142,56,74 --142,56,82 --142,56,90 --142,56,98 --142,56,106 --142,56,114 --142,56,122 --142,56,130 --142,56,138 --142,56,146 --134,56,-150 --134,56,-142 --134,56,-134 --134,56,-126 --134,56,-118 --134,56,-110 --134,56,-102 --134,56,-94 --134,56,-86 --134,56,-78 --134,56,-70 --134,56,-62 --134,56,-54 --134,56,-46 --134,56,-38 --134,56,-30 --134,56,-22 --134,56,-14 --134,56,-6 --134,56,2 --134,56,10 --134,56,18 --134,56,26 --134,56,34 --134,56,42 --134,56,50 --134,56,58 --134,56,66 --134,56,74 --134,56,82 --134,56,90 --134,56,98 --134,56,106 --134,56,114 --134,56,122 --134,56,130 --134,56,138 --134,56,146 --126,56,-150 --126,56,-142 --126,56,-134 --126,56,-126 --126,56,-118 --126,56,-110 --126,56,-102 --126,56,-94 --126,56,-86 --126,56,-78 --126,56,-70 --126,56,-62 --126,56,-54 --126,56,-46 --126,56,-38 --126,56,-30 --126,56,-22 --126,56,-14 --126,56,-6 --126,56,2 --126,56,10 --126,56,18 --126,56,26 --126,56,34 --126,56,42 --126,56,50 --126,56,58 --126,56,66 --126,56,74 --126,56,82 --126,56,90 --126,56,98 --126,56,106 --126,56,114 --126,56,122 --126,56,130 --126,56,138 --126,56,146 --118,56,-150 --118,56,-142 --118,56,-134 --118,56,-126 --118,56,-118 --118,56,-110 --118,56,-102 --118,56,-94 --118,56,-86 --118,56,-78 --118,56,-70 --118,56,-62 --118,56,-54 --118,56,-46 --118,56,-38 --118,56,-30 --118,56,-22 --118,56,-14 --118,56,-6 --118,56,2 --118,56,10 --118,56,18 --118,56,26 --118,56,34 --118,56,42 --118,56,50 --118,56,58 --118,56,66 --118,56,74 --118,56,82 --118,56,90 --118,56,98 --118,56,106 --118,56,114 --118,56,122 --118,56,130 --118,56,138 --118,56,146 --110,56,-150 --110,56,-142 --110,56,-134 --110,56,-126 --110,56,-118 --110,56,-110 --110,56,-102 --110,56,-94 --110,56,-86 --110,56,-78 --110,56,-70 --110,56,-62 --110,56,-54 --110,56,-46 --110,56,-38 --110,56,-30 --110,56,-22 --110,56,-14 --110,56,-6 --110,56,2 --110,56,10 --110,56,18 --110,56,26 --110,56,34 --110,56,42 --110,56,50 --110,56,58 --110,56,66 --110,56,74 --110,56,82 --110,56,90 --110,56,98 --110,56,106 --110,56,114 --110,56,122 --110,56,130 --110,56,138 --110,56,146 --102,56,-150 --102,56,-142 --102,56,-134 --102,56,-126 --102,56,-118 --102,56,-110 --102,56,-102 --102,56,-94 --102,56,-86 --102,56,-78 --102,56,-70 --102,56,-62 --102,56,-54 --102,56,-46 --102,56,-38 --102,56,-30 --102,56,-22 --102,56,-14 --102,56,-6 --102,56,2 --102,56,10 --102,56,18 --102,56,26 --102,56,34 --102,56,42 --102,56,50 --102,56,58 --102,56,66 --102,56,74 --102,56,82 --102,56,90 --102,56,98 --102,56,106 --102,56,114 --102,56,122 --102,56,130 --102,56,138 --102,56,146 --94,56,-150 --94,56,-142 --94,56,-134 --94,56,-126 --94,56,-118 --94,56,-110 --94,56,-102 --94,56,-94 --94,56,-86 --94,56,-78 --94,56,-70 --94,56,-62 --94,56,-54 --94,56,-46 --94,56,-38 --94,56,-30 --94,56,-22 --94,56,-14 --94,56,-6 --94,56,2 --94,56,10 --94,56,18 --94,56,26 --94,56,34 --94,56,42 --94,56,50 --94,56,58 --94,56,66 --94,56,74 --94,56,82 --94,56,90 --94,56,98 --94,56,106 --94,56,114 --94,56,122 --94,56,130 --94,56,138 --94,56,146 --86,56,-150 --86,56,-142 --86,56,-134 --86,56,-126 --86,56,-118 --86,56,-110 --86,56,-102 --86,56,-94 --86,56,-86 --86,56,-78 --86,56,-70 --86,56,-62 --86,56,-54 --86,56,-46 --86,56,-38 --86,56,-30 --86,56,-22 --86,56,-14 --86,56,-6 --86,56,2 --86,56,10 --86,56,18 --86,56,26 --86,56,34 --86,56,42 --86,56,50 --86,56,58 --86,56,66 --86,56,74 --86,56,82 --86,56,90 --86,56,98 --86,56,106 --86,56,114 --86,56,122 --86,56,130 --86,56,138 --86,56,146 --78,56,-150 --78,56,-142 --78,56,-134 --78,56,-126 --78,56,-118 --78,56,-110 --78,56,-102 --78,56,-94 --78,56,-86 --78,56,-78 --78,56,-70 --78,56,-62 --78,56,-54 --78,56,-46 --78,56,-38 --78,56,-30 --78,56,-22 --78,56,-14 --78,56,-6 --78,56,2 --78,56,10 --78,56,18 --78,56,26 --78,56,34 --78,56,42 --78,56,50 --78,56,58 --78,56,66 --78,56,74 --78,56,82 --78,56,90 --78,56,98 --78,56,106 --78,56,114 --78,56,122 --78,56,130 --78,56,138 --78,56,146 --70,56,-150 --70,56,-142 --70,56,-134 --70,56,-126 --70,56,-118 --70,56,-110 --70,56,-102 --70,56,-94 --70,56,-86 --70,56,-78 --70,56,-70 --70,56,-62 --70,56,-54 --70,56,-46 --70,56,-38 --70,56,-30 --70,56,-22 --70,56,-14 --70,56,-6 --70,56,2 --70,56,10 --70,56,18 --70,56,26 --70,56,34 --70,56,42 --70,56,50 --70,56,58 --70,56,66 --70,56,74 --70,56,82 --70,56,90 --70,56,98 --70,56,106 --70,56,114 --70,56,122 --70,56,130 --70,56,138 --70,56,146 --62,56,-150 --62,56,-142 --62,56,-134 --62,56,-126 --62,56,-118 --62,56,-110 --62,56,-102 --62,56,-94 --62,56,-86 --62,56,-78 --62,56,-70 --62,56,-62 --62,56,-54 --62,56,-46 --62,56,-38 --62,56,-30 --62,56,-22 --62,56,-14 --62,56,-6 --62,56,2 --62,56,10 --62,56,18 --62,56,26 --62,56,34 --62,56,42 --62,56,50 --62,56,58 --62,56,66 --62,56,74 --62,56,82 --62,56,90 --62,56,98 --62,56,106 --62,56,114 --62,56,122 --62,56,130 --62,56,138 --62,56,146 --54,56,-150 --54,56,-142 --54,56,-134 --54,56,-126 --54,56,-118 --54,56,-110 --54,56,-102 --54,56,-94 --54,56,-86 --54,56,-78 --54,56,-70 --54,56,-62 --54,56,-54 --54,56,-46 --54,56,-38 --54,56,-30 --54,56,-22 --54,56,-14 --54,56,-6 --54,56,2 --54,56,10 --54,56,18 --54,56,26 --54,56,34 --54,56,42 --54,56,50 --54,56,58 --54,56,66 --54,56,74 --54,56,82 --54,56,90 --54,56,98 --54,56,106 --54,56,114 --54,56,122 --54,56,130 --54,56,138 --54,56,146 --46,56,-150 --46,56,-142 --46,56,-134 --46,56,-126 --46,56,-118 --46,56,-110 --46,56,-102 --46,56,-94 --46,56,-86 --46,56,-78 --46,56,-70 --46,56,-62 --46,56,-54 --46,56,-46 --46,56,-38 --46,56,-30 --46,56,-22 --46,56,-14 --46,56,-6 --46,56,2 --46,56,10 --46,56,18 --46,56,26 --46,56,34 --46,56,42 --46,56,50 --46,56,58 --46,56,66 --46,56,74 --46,56,82 --46,56,90 --46,56,98 --46,56,106 --46,56,114 --46,56,122 --46,56,130 --46,56,138 --46,56,146 --38,56,-150 --38,56,-142 --38,56,-134 --38,56,-126 --38,56,-118 --38,56,-110 --38,56,-102 --38,56,-94 --38,56,-86 --38,56,-78 --38,56,-70 --38,56,-62 --38,56,-54 --38,56,-46 --38,56,-38 --38,56,-30 --38,56,-22 --38,56,-14 --38,56,-6 --38,56,2 --38,56,10 --38,56,18 --38,56,26 --38,56,34 --38,56,42 --38,56,50 --38,56,58 --38,56,66 --38,56,74 --38,56,82 --38,56,90 --38,56,98 --38,56,106 --38,56,114 --38,56,122 --38,56,130 --38,56,138 --38,56,146 --30,56,-150 --30,56,-142 --30,56,-134 --30,56,-126 --30,56,-118 --30,56,-110 --30,56,-102 --30,56,-94 --30,56,-86 --30,56,-78 --30,56,-70 --30,56,-62 --30,56,-54 --30,56,-46 --30,56,-38 --30,56,-30 --30,56,-22 --30,56,-14 --30,56,-6 --30,56,2 --30,56,10 --30,56,18 --30,56,26 --30,56,34 --30,56,42 --30,56,50 --30,56,58 --30,56,66 --30,56,74 --30,56,82 --30,56,90 --30,56,98 --30,56,106 --30,56,114 --30,56,122 --30,56,130 --30,56,138 --30,56,146 --22,56,-150 --22,56,-142 --22,56,-134 --22,56,-126 --22,56,-118 --22,56,-110 --22,56,-102 --22,56,-94 --22,56,-86 --22,56,-78 --22,56,-70 --22,56,-62 --22,56,-54 --22,56,-46 --22,56,-38 --22,56,-30 --22,56,-22 --22,56,-14 --22,56,-6 --22,56,2 --22,56,10 --22,56,18 --22,56,26 --22,56,34 --22,56,42 --22,56,50 --22,56,58 --22,56,66 --22,56,74 --22,56,82 --22,56,90 --22,56,98 --22,56,106 --22,56,114 --22,56,122 --22,56,130 --22,56,138 --22,56,146 --14,56,-150 --14,56,-142 --14,56,-134 --14,56,-126 --14,56,-118 --14,56,-110 --14,56,-102 --14,56,-94 --14,56,-86 --14,56,-78 --14,56,-70 --14,56,-62 --14,56,-54 --14,56,-46 --14,56,-38 --14,56,-30 --14,56,-22 --14,56,-14 --14,56,-6 --14,56,2 --14,56,10 --14,56,18 --14,56,26 --14,56,34 --14,56,42 --14,56,50 --14,56,58 --14,56,66 --14,56,74 --14,56,82 --14,56,90 --14,56,98 --14,56,106 --14,56,114 --14,56,122 --14,56,130 --14,56,138 --14,56,146 --6,56,-150 --6,56,-142 --6,56,-134 --6,56,-126 --6,56,-118 --6,56,-110 --6,56,-102 --6,56,-94 --6,56,-86 --6,56,-78 --6,56,-70 --6,56,-62 --6,56,-54 --6,56,-46 --6,56,-38 --6,56,-30 --6,56,-22 --6,56,-14 --6,56,-6 --6,56,2 --6,56,10 --6,56,18 --6,56,26 --6,56,34 --6,56,42 --6,56,50 --6,56,58 --6,56,66 --6,56,74 --6,56,82 --6,56,90 --6,56,98 --6,56,106 --6,56,114 --6,56,122 --6,56,130 --6,56,138 --6,56,146 -2,56,-150 -2,56,-142 -2,56,-134 -2,56,-126 -2,56,-118 -2,56,-110 -2,56,-102 -2,56,-94 -2,56,-86 -2,56,-78 -2,56,-70 -2,56,-62 -2,56,-54 -2,56,-46 -2,56,-38 -2,56,-30 -2,56,-22 -2,56,-14 -2,56,-6 -2,56,2 -2,56,10 -2,56,18 -2,56,26 -2,56,34 -2,56,42 -2,56,50 -2,56,58 -2,56,66 -2,56,74 -2,56,82 -2,56,90 -2,56,98 -2,56,106 -2,56,114 -2,56,122 -2,56,130 -2,56,138 -2,56,146 -10,56,-150 -10,56,-142 -10,56,-134 -10,56,-126 -10,56,-118 -10,56,-110 -10,56,-102 -10,56,-94 -10,56,-86 -10,56,-78 -10,56,-70 -10,56,-62 -10,56,-54 -10,56,-46 -10,56,-38 -10,56,-30 -10,56,-22 -10,56,-14 -10,56,-6 -10,56,2 -10,56,10 -10,56,18 -10,56,26 -10,56,34 -10,56,42 -10,56,50 -10,56,58 -10,56,66 -10,56,74 -10,56,82 -10,56,90 -10,56,98 -10,56,106 -10,56,114 -10,56,122 -10,56,130 -10,56,138 -10,56,146 -18,56,-150 -18,56,-142 -18,56,-134 -18,56,-126 -18,56,-118 -18,56,-110 -18,56,-102 -18,56,-94 -18,56,-86 -18,56,-78 -18,56,-70 -18,56,-62 -18,56,-54 -18,56,-46 -18,56,-38 -18,56,-30 -18,56,-22 -18,56,-14 -18,56,-6 -18,56,2 -18,56,10 -18,56,18 -18,56,26 -18,56,34 -18,56,42 -18,56,50 -18,56,58 -18,56,66 -18,56,74 -18,56,82 -18,56,90 -18,56,98 -18,56,106 -18,56,114 -18,56,122 -18,56,130 -18,56,138 -18,56,146 -26,56,-150 -26,56,-142 -26,56,-134 -26,56,-126 -26,56,-118 -26,56,-110 -26,56,-102 -26,56,-94 -26,56,-86 -26,56,-78 -26,56,-70 -26,56,-62 -26,56,-54 -26,56,-46 -26,56,-38 -26,56,-30 -26,56,-22 -26,56,-14 -26,56,-6 -26,56,2 -26,56,10 -26,56,18 -26,56,26 -26,56,34 -26,56,42 -26,56,50 -26,56,58 -26,56,66 -26,56,74 -26,56,82 -26,56,90 -26,56,98 -26,56,106 -26,56,114 -26,56,122 -26,56,130 -26,56,138 -26,56,146 -34,56,-150 -34,56,-142 -34,56,-134 -34,56,-126 -34,56,-118 -34,56,-110 -34,56,-102 -34,56,-94 -34,56,-86 -34,56,-78 -34,56,-70 -34,56,-62 -34,56,-54 -34,56,-46 -34,56,-38 -34,56,-30 -34,56,-22 -34,56,-14 -34,56,-6 -34,56,2 -34,56,10 -34,56,18 -34,56,26 -34,56,34 -34,56,42 -34,56,50 -34,56,58 -34,56,66 -34,56,74 -34,56,82 -34,56,90 -34,56,98 -34,56,106 -34,56,114 -34,56,122 -34,56,130 -34,56,138 -34,56,146 -42,56,-150 -42,56,-142 -42,56,-134 -42,56,-126 -42,56,-118 -42,56,-110 -42,56,-102 -42,56,-94 -42,56,-86 -42,56,-78 -42,56,-70 -42,56,-62 -42,56,-54 -42,56,-46 -42,56,-38 -42,56,-30 -42,56,-22 -42,56,-14 -42,56,-6 -42,56,2 -42,56,10 -42,56,18 -42,56,26 -42,56,34 -42,56,42 -42,56,50 -42,56,58 -42,56,66 -42,56,74 -42,56,82 -42,56,90 -42,56,98 -42,56,106 -42,56,114 -42,56,122 -42,56,130 -42,56,138 -42,56,146 -50,56,-150 -50,56,-142 -50,56,-134 -50,56,-126 -50,56,-118 -50,56,-110 -50,56,-102 -50,56,-94 -50,56,-86 -50,56,-78 -50,56,-70 -50,56,-62 -50,56,-54 -50,56,-46 -50,56,-38 -50,56,-30 -50,56,-22 -50,56,-14 -50,56,-6 -50,56,2 -50,56,10 -50,56,18 -50,56,26 -50,56,34 -50,56,42 -50,56,50 -50,56,58 -50,56,66 -50,56,74 -50,56,82 -50,56,90 -50,56,98 -50,56,106 -50,56,114 -50,56,122 -50,56,130 -50,56,138 -50,56,146 -58,56,-150 -58,56,-142 -58,56,-134 -58,56,-126 -58,56,-118 -58,56,-110 -58,56,-102 -58,56,-94 -58,56,-86 -58,56,-78 -58,56,-70 -58,56,-62 -58,56,-54 -58,56,-46 -58,56,-38 -58,56,-30 -58,56,-22 -58,56,-14 -58,56,-6 -58,56,2 -58,56,10 -58,56,18 -58,56,26 -58,56,34 -58,56,42 -58,56,50 -58,56,58 -58,56,66 -58,56,74 -58,56,82 -58,56,90 -58,56,98 -58,56,106 -58,56,114 -58,56,122 -58,56,130 -58,56,138 -58,56,146 -66,56,-150 -66,56,-142 -66,56,-134 -66,56,-126 -66,56,-118 -66,56,-110 -66,56,-102 -66,56,-94 -66,56,-86 -66,56,-78 -66,56,-70 -66,56,-62 -66,56,-54 -66,56,-46 -66,56,-38 -66,56,-30 -66,56,-22 -66,56,-14 -66,56,-6 -66,56,2 -66,56,10 -66,56,18 -66,56,26 -66,56,34 -66,56,42 -66,56,50 -66,56,58 -66,56,66 -66,56,74 -66,56,82 -66,56,90 -66,56,98 -66,56,106 -66,56,114 -66,56,122 -66,56,130 -66,56,138 -66,56,146 -74,56,-150 -74,56,-142 -74,56,-134 -74,56,-126 -74,56,-118 -74,56,-110 -74,56,-102 -74,56,-94 -74,56,-86 -74,56,-78 -74,56,-70 -74,56,-62 -74,56,-54 -74,56,-46 -74,56,-38 -74,56,-30 -74,56,-22 -74,56,-14 -74,56,-6 -74,56,2 -74,56,10 -74,56,18 -74,56,26 -74,56,34 -74,56,42 -74,56,50 -74,56,58 -74,56,66 -74,56,74 -74,56,82 -74,56,90 -74,56,98 -74,56,106 -74,56,114 -74,56,122 -74,56,130 -74,56,138 -74,56,146 -82,56,-150 -82,56,-142 -82,56,-134 -82,56,-126 -82,56,-118 -82,56,-110 -82,56,-102 -82,56,-94 -82,56,-86 -82,56,-78 -82,56,-70 -82,56,-62 -82,56,-54 -82,56,-46 -82,56,-38 -82,56,-30 -82,56,-22 -82,56,-14 -82,56,-6 -82,56,2 -82,56,10 -82,56,18 -82,56,26 -82,56,34 -82,56,42 -82,56,50 -82,56,58 -82,56,66 -82,56,74 -82,56,82 -82,56,90 -82,56,98 -82,56,106 -82,56,114 -82,56,122 -82,56,130 -82,56,138 -82,56,146 -90,56,-150 -90,56,-142 -90,56,-134 -90,56,-126 -90,56,-118 -90,56,-110 -90,56,-102 -90,56,-94 -90,56,-86 -90,56,-78 -90,56,-70 -90,56,-62 -90,56,-54 -90,56,-46 -90,56,-38 -90,56,-30 -90,56,-22 -90,56,-14 -90,56,-6 -90,56,2 -90,56,10 -90,56,18 -90,56,26 -90,56,34 -90,56,42 -90,56,50 -90,56,58 -90,56,66 -90,56,74 -90,56,82 -90,56,90 -90,56,98 -90,56,106 -90,56,114 -90,56,122 -90,56,130 -90,56,138 -90,56,146 -98,56,-150 -98,56,-142 -98,56,-134 -98,56,-126 -98,56,-118 -98,56,-110 -98,56,-102 -98,56,-94 -98,56,-86 -98,56,-78 -98,56,-70 -98,56,-62 -98,56,-54 -98,56,-46 -98,56,-38 -98,56,-30 -98,56,-22 -98,56,-14 -98,56,-6 -98,56,2 -98,56,10 -98,56,18 -98,56,26 -98,56,34 -98,56,42 -98,56,50 -98,56,58 -98,56,66 -98,56,74 -98,56,82 -98,56,90 -98,56,98 -98,56,106 -98,56,114 -98,56,122 -98,56,130 -98,56,138 -98,56,146 -106,56,-150 -106,56,-142 -106,56,-134 -106,56,-126 -106,56,-118 -106,56,-110 -106,56,-102 -106,56,-94 -106,56,-86 -106,56,-78 -106,56,-70 -106,56,-62 -106,56,-54 -106,56,-46 -106,56,-38 -106,56,-30 -106,56,-22 -106,56,-14 -106,56,-6 -106,56,2 -106,56,10 -106,56,18 -106,56,26 -106,56,34 -106,56,42 -106,56,50 -106,56,58 -106,56,66 -106,56,74 -106,56,82 -106,56,90 -106,56,98 -106,56,106 -106,56,114 -106,56,122 -106,56,130 -106,56,138 -106,56,146 -114,56,-150 -114,56,-142 -114,56,-134 -114,56,-126 -114,56,-118 -114,56,-110 -114,56,-102 -114,56,-94 -114,56,-86 -114,56,-78 -114,56,-70 -114,56,-62 -114,56,-54 -114,56,-46 -114,56,-38 -114,56,-30 -114,56,-22 -114,56,-14 -114,56,-6 -114,56,2 -114,56,10 -114,56,18 -114,56,26 -114,56,34 -114,56,42 -114,56,50 -114,56,58 -114,56,66 -114,56,74 -114,56,82 -114,56,90 -114,56,98 -114,56,106 -114,56,114 -114,56,122 -114,56,130 -114,56,138 -114,56,146 -122,56,-150 -122,56,-142 -122,56,-134 -122,56,-126 -122,56,-118 -122,56,-110 -122,56,-102 -122,56,-94 -122,56,-86 -122,56,-78 -122,56,-70 -122,56,-62 -122,56,-54 -122,56,-46 -122,56,-38 -122,56,-30 -122,56,-22 -122,56,-14 -122,56,-6 -122,56,2 -122,56,10 -122,56,18 -122,56,26 -122,56,34 -122,56,42 -122,56,50 -122,56,58 -122,56,66 -122,56,74 -122,56,82 -122,56,90 -122,56,98 -122,56,106 -122,56,114 -122,56,122 -122,56,130 -122,56,138 -122,56,146 -130,56,-150 -130,56,-142 -130,56,-134 -130,56,-126 -130,56,-118 -130,56,-110 -130,56,-102 -130,56,-94 -130,56,-86 -130,56,-78 -130,56,-70 -130,56,-62 -130,56,-54 -130,56,-46 -130,56,-38 -130,56,-30 -130,56,-22 -130,56,-14 -130,56,-6 -130,56,2 -130,56,10 -130,56,18 -130,56,26 -130,56,34 -130,56,42 -130,56,50 -130,56,58 -130,56,66 -130,56,74 -130,56,82 -130,56,90 -130,56,98 -130,56,106 -130,56,114 -130,56,122 -130,56,130 -130,56,138 -130,56,146 -138,56,-150 -138,56,-142 -138,56,-134 -138,56,-126 -138,56,-118 -138,56,-110 -138,56,-102 -138,56,-94 -138,56,-86 -138,56,-78 -138,56,-70 -138,56,-62 -138,56,-54 -138,56,-46 -138,56,-38 -138,56,-30 -138,56,-22 -138,56,-14 -138,56,-6 -138,56,2 -138,56,10 -138,56,18 -138,56,26 -138,56,34 -138,56,42 -138,56,50 -138,56,58 -138,56,66 -138,56,74 -138,56,82 -138,56,90 -138,56,98 -138,56,106 -138,56,114 -138,56,122 -138,56,130 -138,56,138 -138,56,146 -146,56,-150 -146,56,-142 -146,56,-134 -146,56,-126 -146,56,-118 -146,56,-110 -146,56,-102 -146,56,-94 -146,56,-86 -146,56,-78 -146,56,-70 -146,56,-62 -146,56,-54 -146,56,-46 -146,56,-38 -146,56,-30 -146,56,-22 -146,56,-14 -146,56,-6 -146,56,2 -146,56,10 -146,56,18 -146,56,26 -146,56,34 -146,56,42 -146,56,50 -146,56,58 -146,56,66 -146,56,74 -146,56,82 -146,56,90 -146,56,98 -146,56,106 -146,56,114 -146,56,122 -146,56,130 -146,56,138 -146,56,146 --150,64,-150 --150,64,-142 --150,64,-134 --150,64,-126 --150,64,-118 --150,64,-110 --150,64,-102 --150,64,-94 --150,64,-86 --150,64,-78 --150,64,-70 --150,64,-62 --150,64,-54 --150,64,-46 --150,64,-38 --150,64,-30 --150,64,-22 --150,64,-14 --150,64,-6 --150,64,2 --150,64,10 --150,64,18 --150,64,26 --150,64,34 --150,64,42 --150,64,50 --150,64,58 --150,64,66 --150,64,74 --150,64,82 --150,64,90 --150,64,98 --150,64,106 --150,64,114 --150,64,122 --150,64,130 --150,64,138 --150,64,146 --142,64,-150 --142,64,-142 --142,64,-134 --142,64,-126 --142,64,-118 --142,64,-110 --142,64,-102 --142,64,-94 --142,64,-86 --142,64,-78 --142,64,-70 --142,64,-62 --142,64,-54 --142,64,-46 --142,64,-38 --142,64,-30 --142,64,-22 --142,64,-14 --142,64,-6 --142,64,2 --142,64,10 --142,64,18 --142,64,26 --142,64,34 --142,64,42 --142,64,50 --142,64,58 --142,64,66 --142,64,74 --142,64,82 --142,64,90 --142,64,98 --142,64,106 --142,64,114 --142,64,122 --142,64,130 --142,64,138 --142,64,146 --134,64,-150 --134,64,-142 --134,64,-134 --134,64,-126 --134,64,-118 --134,64,-110 --134,64,-102 --134,64,-94 --134,64,-86 --134,64,-78 --134,64,-70 --134,64,-62 --134,64,-54 --134,64,-46 --134,64,-38 --134,64,-30 --134,64,-22 --134,64,-14 --134,64,-6 --134,64,2 --134,64,10 --134,64,18 --134,64,26 --134,64,34 --134,64,42 --134,64,50 --134,64,58 --134,64,66 --134,64,74 --134,64,82 --134,64,90 --134,64,98 --134,64,106 --134,64,114 --134,64,122 --134,64,130 --134,64,138 --134,64,146 --126,64,-150 --126,64,-142 --126,64,-134 --126,64,-126 --126,64,-118 --126,64,-110 --126,64,-102 --126,64,-94 --126,64,-86 --126,64,-78 --126,64,-70 --126,64,-62 --126,64,-54 --126,64,-46 --126,64,-38 --126,64,-30 --126,64,-22 --126,64,-14 --126,64,-6 --126,64,2 --126,64,10 --126,64,18 --126,64,26 --126,64,34 --126,64,42 --126,64,50 --126,64,58 --126,64,66 --126,64,74 --126,64,82 --126,64,90 --126,64,98 --126,64,106 --126,64,114 --126,64,122 --126,64,130 --126,64,138 --126,64,146 --118,64,-150 --118,64,-142 --118,64,-134 --118,64,-126 --118,64,-118 --118,64,-110 --118,64,-102 --118,64,-94 --118,64,-86 --118,64,-78 --118,64,-70 --118,64,-62 --118,64,-54 --118,64,-46 --118,64,-38 --118,64,-30 --118,64,-22 --118,64,-14 --118,64,-6 --118,64,2 --118,64,10 --118,64,18 --118,64,26 --118,64,34 --118,64,42 --118,64,50 --118,64,58 --118,64,66 --118,64,74 --118,64,82 --118,64,90 --118,64,98 --118,64,106 --118,64,114 --118,64,122 --118,64,130 --118,64,138 --118,64,146 --110,64,-150 --110,64,-142 --110,64,-134 --110,64,-126 --110,64,-118 --110,64,-110 --110,64,-102 --110,64,-94 --110,64,-86 --110,64,-78 --110,64,-70 --110,64,-62 --110,64,-54 --110,64,-46 --110,64,-38 --110,64,-30 --110,64,-22 --110,64,-14 --110,64,-6 --110,64,2 --110,64,10 --110,64,18 --110,64,26 --110,64,34 --110,64,42 --110,64,50 --110,64,58 --110,64,66 --110,64,74 --110,64,82 --110,64,90 --110,64,98 --110,64,106 --110,64,114 --110,64,122 --110,64,130 --110,64,138 --110,64,146 --102,64,-150 --102,64,-142 --102,64,-134 --102,64,-126 --102,64,-118 --102,64,-110 --102,64,-102 --102,64,-94 --102,64,-86 --102,64,-78 --102,64,-70 --102,64,-62 --102,64,-54 --102,64,-46 --102,64,-38 --102,64,-30 --102,64,-22 --102,64,-14 --102,64,-6 --102,64,2 --102,64,10 --102,64,18 --102,64,26 --102,64,34 --102,64,42 --102,64,50 --102,64,58 --102,64,66 --102,64,74 --102,64,82 --102,64,90 --102,64,98 --102,64,106 --102,64,114 --102,64,122 --102,64,130 --102,64,138 --102,64,146 --94,64,-150 --94,64,-142 --94,64,-134 --94,64,-126 --94,64,-118 --94,64,-110 --94,64,-102 --94,64,-94 --94,64,-86 --94,64,-78 --94,64,-70 --94,64,-62 --94,64,-54 --94,64,-46 --94,64,-38 --94,64,-30 --94,64,-22 --94,64,-14 --94,64,-6 --94,64,2 --94,64,10 --94,64,18 --94,64,26 --94,64,34 --94,64,42 --94,64,50 --94,64,58 --94,64,66 --94,64,74 --94,64,82 --94,64,90 --94,64,98 --94,64,106 --94,64,114 --94,64,122 --94,64,130 --94,64,138 --94,64,146 --86,64,-150 --86,64,-142 --86,64,-134 --86,64,-126 --86,64,-118 --86,64,-110 --86,64,-102 --86,64,-94 --86,64,-86 --86,64,-78 --86,64,-70 --86,64,-62 --86,64,-54 --86,64,-46 --86,64,-38 --86,64,-30 --86,64,-22 --86,64,-14 --86,64,-6 --86,64,2 --86,64,10 --86,64,18 --86,64,26 --86,64,34 --86,64,42 --86,64,50 --86,64,58 --86,64,66 --86,64,74 --86,64,82 --86,64,90 --86,64,98 --86,64,106 --86,64,114 --86,64,122 --86,64,130 --86,64,138 --86,64,146 --78,64,-150 --78,64,-142 --78,64,-134 --78,64,-126 --78,64,-118 --78,64,-110 --78,64,-102 --78,64,-94 --78,64,-86 --78,64,-78 --78,64,-70 --78,64,-62 --78,64,-54 --78,64,-46 --78,64,-38 --78,64,-30 --78,64,-22 --78,64,-14 --78,64,-6 --78,64,2 --78,64,10 --78,64,18 --78,64,26 --78,64,34 --78,64,42 --78,64,50 --78,64,58 --78,64,66 --78,64,74 --78,64,82 --78,64,90 --78,64,98 --78,64,106 --78,64,114 --78,64,122 --78,64,130 --78,64,138 --78,64,146 --70,64,-150 --70,64,-142 --70,64,-134 --70,64,-126 --70,64,-118 --70,64,-110 --70,64,-102 --70,64,-94 --70,64,-86 --70,64,-78 --70,64,-70 --70,64,-62 --70,64,-54 --70,64,-46 --70,64,-38 --70,64,-30 --70,64,-22 --70,64,-14 --70,64,-6 --70,64,2 --70,64,10 --70,64,18 --70,64,26 --70,64,34 --70,64,42 --70,64,50 --70,64,58 --70,64,66 --70,64,74 --70,64,82 --70,64,90 --70,64,98 --70,64,106 --70,64,114 --70,64,122 --70,64,130 --70,64,138 --70,64,146 --62,64,-150 --62,64,-142 --62,64,-134 --62,64,-126 --62,64,-118 --62,64,-110 --62,64,-102 --62,64,-94 --62,64,-86 --62,64,-78 --62,64,-70 --62,64,-62 --62,64,-54 --62,64,-46 --62,64,-38 --62,64,-30 --62,64,-22 --62,64,-14 --62,64,-6 --62,64,2 --62,64,10 --62,64,18 --62,64,26 --62,64,34 --62,64,42 --62,64,50 --62,64,58 --62,64,66 --62,64,74 --62,64,82 --62,64,90 --62,64,98 --62,64,106 --62,64,114 --62,64,122 --62,64,130 --62,64,138 --62,64,146 --54,64,-150 --54,64,-142 --54,64,-134 --54,64,-126 --54,64,-118 --54,64,-110 --54,64,-102 --54,64,-94 --54,64,-86 --54,64,-78 --54,64,-70 --54,64,-62 --54,64,-54 --54,64,-46 --54,64,-38 --54,64,-30 --54,64,-22 --54,64,-14 --54,64,-6 --54,64,2 --54,64,10 --54,64,18 --54,64,26 --54,64,34 --54,64,42 --54,64,50 --54,64,58 --54,64,66 --54,64,74 --54,64,82 --54,64,90 --54,64,98 --54,64,106 --54,64,114 --54,64,122 --54,64,130 --54,64,138 --54,64,146 --46,64,-150 --46,64,-142 --46,64,-134 --46,64,-126 --46,64,-118 --46,64,-110 --46,64,-102 --46,64,-94 --46,64,-86 --46,64,-78 --46,64,-70 --46,64,-62 --46,64,-54 --46,64,-46 --46,64,-38 --46,64,-30 --46,64,-22 --46,64,-14 --46,64,-6 --46,64,2 --46,64,10 --46,64,18 --46,64,26 --46,64,34 --46,64,42 --46,64,50 --46,64,58 --46,64,66 --46,64,74 --46,64,82 --46,64,90 --46,64,98 --46,64,106 --46,64,114 --46,64,122 --46,64,130 --46,64,138 --46,64,146 --38,64,-150 --38,64,-142 --38,64,-134 --38,64,-126 --38,64,-118 --38,64,-110 --38,64,-102 --38,64,-94 --38,64,-86 --38,64,-78 --38,64,-70 --38,64,-62 --38,64,-54 --38,64,-46 --38,64,-38 --38,64,-30 --38,64,-22 --38,64,-14 --38,64,-6 --38,64,2 --38,64,10 --38,64,18 --38,64,26 --38,64,34 --38,64,42 --38,64,50 --38,64,58 --38,64,66 --38,64,74 --38,64,82 --38,64,90 --38,64,98 --38,64,106 --38,64,114 --38,64,122 --38,64,130 --38,64,138 --38,64,146 --30,64,-150 --30,64,-142 --30,64,-134 --30,64,-126 --30,64,-118 --30,64,-110 --30,64,-102 --30,64,-94 --30,64,-86 --30,64,-78 --30,64,-70 --30,64,-62 --30,64,-54 --30,64,-46 --30,64,-38 --30,64,-30 --30,64,-22 --30,64,-14 --30,64,-6 --30,64,2 --30,64,10 --30,64,18 --30,64,26 --30,64,34 --30,64,42 --30,64,50 --30,64,58 --30,64,66 --30,64,74 --30,64,82 --30,64,90 --30,64,98 --30,64,106 --30,64,114 --30,64,122 --30,64,130 --30,64,138 --30,64,146 --22,64,-150 --22,64,-142 --22,64,-134 --22,64,-126 --22,64,-118 --22,64,-110 --22,64,-102 --22,64,-94 --22,64,-86 --22,64,-78 --22,64,-70 --22,64,-62 --22,64,-54 --22,64,-46 --22,64,-38 --22,64,-30 --22,64,-22 --22,64,-14 --22,64,-6 --22,64,2 --22,64,10 --22,64,18 --22,64,26 --22,64,34 --22,64,42 --22,64,50 --22,64,58 --22,64,66 --22,64,74 --22,64,82 --22,64,90 --22,64,98 --22,64,106 --22,64,114 --22,64,122 --22,64,130 --22,64,138 --22,64,146 --14,64,-150 --14,64,-142 --14,64,-134 --14,64,-126 --14,64,-118 --14,64,-110 --14,64,-102 --14,64,-94 --14,64,-86 --14,64,-78 --14,64,-70 --14,64,-62 --14,64,-54 --14,64,-46 --14,64,-38 --14,64,-30 --14,64,-22 --14,64,-14 --14,64,-6 --14,64,2 --14,64,10 --14,64,18 --14,64,26 --14,64,34 --14,64,42 --14,64,50 --14,64,58 --14,64,66 --14,64,74 --14,64,82 --14,64,90 --14,64,98 --14,64,106 --14,64,114 --14,64,122 --14,64,130 --14,64,138 --14,64,146 --6,64,-150 --6,64,-142 --6,64,-134 --6,64,-126 --6,64,-118 --6,64,-110 --6,64,-102 --6,64,-94 --6,64,-86 --6,64,-78 --6,64,-70 --6,64,-62 --6,64,-54 --6,64,-46 --6,64,-38 --6,64,-30 --6,64,-22 --6,64,-14 --6,64,-6 --6,64,2 --6,64,10 --6,64,18 --6,64,26 --6,64,34 --6,64,42 --6,64,50 --6,64,58 --6,64,66 --6,64,74 --6,64,82 --6,64,90 --6,64,98 --6,64,106 --6,64,114 --6,64,122 --6,64,130 --6,64,138 --6,64,146 -2,64,-150 -2,64,-142 -2,64,-134 -2,64,-126 -2,64,-118 -2,64,-110 -2,64,-102 -2,64,-94 -2,64,-86 -2,64,-78 -2,64,-70 -2,64,-62 -2,64,-54 -2,64,-46 -2,64,-38 -2,64,-30 -2,64,-22 -2,64,-14 -2,64,-6 -2,64,2 -2,64,10 -2,64,18 -2,64,26 -2,64,34 -2,64,42 -2,64,50 -2,64,58 -2,64,66 -2,64,74 -2,64,82 -2,64,90 -2,64,98 -2,64,106 -2,64,114 -2,64,122 -2,64,130 -2,64,138 -2,64,146 -10,64,-150 -10,64,-142 -10,64,-134 -10,64,-126 -10,64,-118 -10,64,-110 -10,64,-102 -10,64,-94 -10,64,-86 -10,64,-78 -10,64,-70 -10,64,-62 -10,64,-54 -10,64,-46 -10,64,-38 -10,64,-30 -10,64,-22 -10,64,-14 -10,64,-6 -10,64,2 -10,64,10 -10,64,18 -10,64,26 -10,64,34 -10,64,42 -10,64,50 -10,64,58 -10,64,66 -10,64,74 -10,64,82 -10,64,90 -10,64,98 -10,64,106 -10,64,114 -10,64,122 -10,64,130 -10,64,138 -10,64,146 -18,64,-150 -18,64,-142 -18,64,-134 -18,64,-126 -18,64,-118 -18,64,-110 -18,64,-102 -18,64,-94 -18,64,-86 -18,64,-78 -18,64,-70 -18,64,-62 -18,64,-54 -18,64,-46 -18,64,-38 -18,64,-30 -18,64,-22 -18,64,-14 -18,64,-6 -18,64,2 -18,64,10 -18,64,18 -18,64,26 -18,64,34 -18,64,42 -18,64,50 -18,64,58 -18,64,66 -18,64,74 -18,64,82 -18,64,90 -18,64,98 -18,64,106 -18,64,114 -18,64,122 -18,64,130 -18,64,138 -18,64,146 -26,64,-150 -26,64,-142 -26,64,-134 -26,64,-126 -26,64,-118 -26,64,-110 -26,64,-102 -26,64,-94 -26,64,-86 -26,64,-78 -26,64,-70 -26,64,-62 -26,64,-54 -26,64,-46 -26,64,-38 -26,64,-30 -26,64,-22 -26,64,-14 -26,64,-6 -26,64,2 -26,64,10 -26,64,18 -26,64,26 -26,64,34 -26,64,42 -26,64,50 -26,64,58 -26,64,66 -26,64,74 -26,64,82 -26,64,90 -26,64,98 -26,64,106 -26,64,114 -26,64,122 -26,64,130 -26,64,138 -26,64,146 -34,64,-150 -34,64,-142 -34,64,-134 -34,64,-126 -34,64,-118 -34,64,-110 -34,64,-102 -34,64,-94 -34,64,-86 -34,64,-78 -34,64,-70 -34,64,-62 -34,64,-54 -34,64,-46 -34,64,-38 -34,64,-30 -34,64,-22 -34,64,-14 -34,64,-6 -34,64,2 -34,64,10 -34,64,18 -34,64,26 -34,64,34 -34,64,42 -34,64,50 -34,64,58 -34,64,66 -34,64,74 -34,64,82 -34,64,90 -34,64,98 -34,64,106 -34,64,114 -34,64,122 -34,64,130 -34,64,138 -34,64,146 -42,64,-150 -42,64,-142 -42,64,-134 -42,64,-126 -42,64,-118 -42,64,-110 -42,64,-102 -42,64,-94 -42,64,-86 -42,64,-78 -42,64,-70 -42,64,-62 -42,64,-54 -42,64,-46 -42,64,-38 -42,64,-30 -42,64,-22 -42,64,-14 -42,64,-6 -42,64,2 -42,64,10 -42,64,18 -42,64,26 -42,64,34 -42,64,42 -42,64,50 -42,64,58 -42,64,66 -42,64,74 -42,64,82 -42,64,90 -42,64,98 -42,64,106 -42,64,114 -42,64,122 -42,64,130 -42,64,138 -42,64,146 -50,64,-150 -50,64,-142 -50,64,-134 -50,64,-126 -50,64,-118 -50,64,-110 -50,64,-102 -50,64,-94 -50,64,-86 -50,64,-78 -50,64,-70 -50,64,-62 -50,64,-54 -50,64,-46 -50,64,-38 -50,64,-30 -50,64,-22 -50,64,-14 -50,64,-6 -50,64,2 -50,64,10 -50,64,18 -50,64,26 -50,64,34 -50,64,42 -50,64,50 -50,64,58 -50,64,66 -50,64,74 -50,64,82 -50,64,90 -50,64,98 -50,64,106 -50,64,114 -50,64,122 -50,64,130 -50,64,138 -50,64,146 -58,64,-150 -58,64,-142 -58,64,-134 -58,64,-126 -58,64,-118 -58,64,-110 -58,64,-102 -58,64,-94 -58,64,-86 -58,64,-78 -58,64,-70 -58,64,-62 -58,64,-54 -58,64,-46 -58,64,-38 -58,64,-30 -58,64,-22 -58,64,-14 -58,64,-6 -58,64,2 -58,64,10 -58,64,18 -58,64,26 -58,64,34 -58,64,42 -58,64,50 -58,64,58 -58,64,66 -58,64,74 -58,64,82 -58,64,90 -58,64,98 -58,64,106 -58,64,114 -58,64,122 -58,64,130 -58,64,138 -58,64,146 -66,64,-150 -66,64,-142 -66,64,-134 -66,64,-126 -66,64,-118 -66,64,-110 -66,64,-102 -66,64,-94 -66,64,-86 -66,64,-78 -66,64,-70 -66,64,-62 -66,64,-54 -66,64,-46 -66,64,-38 -66,64,-30 -66,64,-22 -66,64,-14 -66,64,-6 -66,64,2 -66,64,10 -66,64,18 -66,64,26 -66,64,34 -66,64,42 -66,64,50 -66,64,58 -66,64,66 -66,64,74 -66,64,82 -66,64,90 -66,64,98 -66,64,106 -66,64,114 -66,64,122 -66,64,130 -66,64,138 -66,64,146 -74,64,-150 -74,64,-142 -74,64,-134 -74,64,-126 -74,64,-118 -74,64,-110 -74,64,-102 -74,64,-94 -74,64,-86 -74,64,-78 -74,64,-70 -74,64,-62 -74,64,-54 -74,64,-46 -74,64,-38 -74,64,-30 -74,64,-22 -74,64,-14 -74,64,-6 -74,64,2 -74,64,10 -74,64,18 -74,64,26 -74,64,34 -74,64,42 -74,64,50 -74,64,58 -74,64,66 -74,64,74 -74,64,82 -74,64,90 -74,64,98 -74,64,106 -74,64,114 -74,64,122 -74,64,130 -74,64,138 -74,64,146 -82,64,-150 -82,64,-142 -82,64,-134 -82,64,-126 -82,64,-118 -82,64,-110 -82,64,-102 -82,64,-94 -82,64,-86 -82,64,-78 -82,64,-70 -82,64,-62 -82,64,-54 -82,64,-46 -82,64,-38 -82,64,-30 -82,64,-22 -82,64,-14 -82,64,-6 -82,64,2 -82,64,10 -82,64,18 -82,64,26 -82,64,34 -82,64,42 -82,64,50 -82,64,58 -82,64,66 -82,64,74 -82,64,82 -82,64,90 -82,64,98 -82,64,106 -82,64,114 -82,64,122 -82,64,130 -82,64,138 -82,64,146 -90,64,-150 -90,64,-142 -90,64,-134 -90,64,-126 -90,64,-118 -90,64,-110 -90,64,-102 -90,64,-94 -90,64,-86 -90,64,-78 -90,64,-70 -90,64,-62 -90,64,-54 -90,64,-46 -90,64,-38 -90,64,-30 -90,64,-22 -90,64,-14 -90,64,-6 -90,64,2 -90,64,10 -90,64,18 -90,64,26 -90,64,34 -90,64,42 -90,64,50 -90,64,58 -90,64,66 -90,64,74 -90,64,82 -90,64,90 -90,64,98 -90,64,106 -90,64,114 -90,64,122 -90,64,130 -90,64,138 -90,64,146 -98,64,-150 -98,64,-142 -98,64,-134 -98,64,-126 -98,64,-118 -98,64,-110 -98,64,-102 -98,64,-94 -98,64,-86 -98,64,-78 -98,64,-70 -98,64,-62 -98,64,-54 -98,64,-46 -98,64,-38 -98,64,-30 -98,64,-22 -98,64,-14 -98,64,-6 -98,64,2 -98,64,10 -98,64,18 -98,64,26 -98,64,34 -98,64,42 -98,64,50 -98,64,58 -98,64,66 -98,64,74 -98,64,82 -98,64,90 -98,64,98 -98,64,106 -98,64,114 -98,64,122 -98,64,130 -98,64,138 -98,64,146 -106,64,-150 -106,64,-142 -106,64,-134 -106,64,-126 -106,64,-118 -106,64,-110 -106,64,-102 -106,64,-94 -106,64,-86 -106,64,-78 -106,64,-70 -106,64,-62 -106,64,-54 -106,64,-46 -106,64,-38 -106,64,-30 -106,64,-22 -106,64,-14 -106,64,-6 -106,64,2 -106,64,10 -106,64,18 -106,64,26 -106,64,34 -106,64,42 -106,64,50 -106,64,58 -106,64,66 -106,64,74 -106,64,82 -106,64,90 -106,64,98 -106,64,106 -106,64,114 -106,64,122 -106,64,130 -106,64,138 -106,64,146 -114,64,-150 -114,64,-142 -114,64,-134 -114,64,-126 -114,64,-118 -114,64,-110 -114,64,-102 -114,64,-94 -114,64,-86 -114,64,-78 -114,64,-70 -114,64,-62 -114,64,-54 -114,64,-46 -114,64,-38 -114,64,-30 -114,64,-22 -114,64,-14 -114,64,-6 -114,64,2 -114,64,10 -114,64,18 -114,64,26 -114,64,34 -114,64,42 -114,64,50 -114,64,58 -114,64,66 -114,64,74 -114,64,82 -114,64,90 -114,64,98 -114,64,106 -114,64,114 -114,64,122 -114,64,130 -114,64,138 -114,64,146 -122,64,-150 -122,64,-142 -122,64,-134 -122,64,-126 -122,64,-118 -122,64,-110 -122,64,-102 -122,64,-94 -122,64,-86 -122,64,-78 -122,64,-70 -122,64,-62 -122,64,-54 -122,64,-46 -122,64,-38 -122,64,-30 -122,64,-22 -122,64,-14 -122,64,-6 -122,64,2 -122,64,10 -122,64,18 -122,64,26 -122,64,34 -122,64,42 -122,64,50 -122,64,58 -122,64,66 -122,64,74 -122,64,82 -122,64,90 -122,64,98 -122,64,106 -122,64,114 -122,64,122 -122,64,130 -122,64,138 -122,64,146 -130,64,-150 -130,64,-142 -130,64,-134 -130,64,-126 -130,64,-118 -130,64,-110 -130,64,-102 -130,64,-94 -130,64,-86 -130,64,-78 -130,64,-70 -130,64,-62 -130,64,-54 -130,64,-46 -130,64,-38 -130,64,-30 -130,64,-22 -130,64,-14 -130,64,-6 -130,64,2 -130,64,10 -130,64,18 -130,64,26 -130,64,34 -130,64,42 -130,64,50 -130,64,58 -130,64,66 -130,64,74 -130,64,82 -130,64,90 -130,64,98 -130,64,106 -130,64,114 -130,64,122 -130,64,130 -130,64,138 -130,64,146 -138,64,-150 -138,64,-142 -138,64,-134 -138,64,-126 -138,64,-118 -138,64,-110 -138,64,-102 -138,64,-94 -138,64,-86 -138,64,-78 -138,64,-70 -138,64,-62 -138,64,-54 -138,64,-46 -138,64,-38 -138,64,-30 -138,64,-22 -138,64,-14 -138,64,-6 -138,64,2 -138,64,10 -138,64,18 -138,64,26 -138,64,34 -138,64,42 -138,64,50 -138,64,58 -138,64,66 -138,64,74 -138,64,82 -138,64,90 -138,64,98 -138,64,106 -138,64,114 -138,64,122 -138,64,130 -138,64,138 -138,64,146 -146,64,-150 -146,64,-142 -146,64,-134 -146,64,-126 -146,64,-118 -146,64,-110 -146,64,-102 -146,64,-94 -146,64,-86 -146,64,-78 -146,64,-70 -146,64,-62 -146,64,-54 -146,64,-46 -146,64,-38 -146,64,-30 -146,64,-22 -146,64,-14 -146,64,-6 -146,64,2 -146,64,10 -146,64,18 -146,64,26 -146,64,34 -146,64,42 -146,64,50 -146,64,58 -146,64,66 -146,64,74 -146,64,82 -146,64,90 -146,64,98 -146,64,106 -146,64,114 -146,64,122 -146,64,130 -146,64,138 -146,64,146 --150,72,-150 --150,72,-142 --150,72,-134 --150,72,-126 --150,72,-118 --150,72,-110 --150,72,-102 --150,72,-94 --150,72,-86 --150,72,-78 --150,72,-70 --150,72,-62 --150,72,-54 --150,72,-46 --150,72,-38 --150,72,-30 --150,72,-22 --150,72,-14 --150,72,-6 --150,72,2 --150,72,10 --150,72,18 --150,72,26 --150,72,34 --150,72,42 --150,72,50 --150,72,58 --150,72,66 --150,72,74 --150,72,82 --150,72,90 --150,72,98 --150,72,106 --150,72,114 --150,72,122 --150,72,130 --150,72,138 --150,72,146 --142,72,-150 --142,72,-142 --142,72,-134 --142,72,-126 --142,72,-118 --142,72,-110 --142,72,-102 --142,72,-94 --142,72,-86 --142,72,-78 --142,72,-70 --142,72,-62 --142,72,-54 --142,72,-46 --142,72,-38 --142,72,-30 --142,72,-22 --142,72,-14 --142,72,-6 --142,72,2 --142,72,10 --142,72,18 --142,72,26 --142,72,34 --142,72,42 --142,72,50 --142,72,58 --142,72,66 --142,72,74 --142,72,82 --142,72,90 --142,72,98 --142,72,106 --142,72,114 --142,72,122 --142,72,130 --142,72,138 --142,72,146 --134,72,-150 --134,72,-142 --134,72,-134 --134,72,-126 --134,72,-118 --134,72,-110 --134,72,-102 --134,72,-94 --134,72,-86 --134,72,-78 --134,72,-70 --134,72,-62 --134,72,-54 --134,72,-46 --134,72,-38 --134,72,-30 --134,72,-22 --134,72,-14 --134,72,-6 --134,72,2 --134,72,10 --134,72,18 --134,72,26 --134,72,34 --134,72,42 --134,72,50 --134,72,58 --134,72,66 --134,72,74 --134,72,82 --134,72,90 --134,72,98 --134,72,106 --134,72,114 --134,72,122 --134,72,130 --134,72,138 --134,72,146 --126,72,-150 --126,72,-142 --126,72,-134 --126,72,-126 --126,72,-118 --126,72,-110 --126,72,-102 --126,72,-94 --126,72,-86 --126,72,-78 --126,72,-70 --126,72,-62 --126,72,-54 --126,72,-46 --126,72,-38 --126,72,-30 --126,72,-22 --126,72,-14 --126,72,-6 --126,72,2 --126,72,10 --126,72,18 --126,72,26 --126,72,34 --126,72,42 --126,72,50 --126,72,58 --126,72,66 --126,72,74 --126,72,82 --126,72,90 --126,72,98 --126,72,106 --126,72,114 --126,72,122 --126,72,130 --126,72,138 --126,72,146 --118,72,-150 --118,72,-142 --118,72,-134 --118,72,-126 --118,72,-118 --118,72,-110 --118,72,-102 --118,72,-94 --118,72,-86 --118,72,-78 --118,72,-70 --118,72,-62 --118,72,-54 --118,72,-46 --118,72,-38 --118,72,-30 --118,72,-22 --118,72,-14 --118,72,-6 --118,72,2 --118,72,10 --118,72,18 --118,72,26 --118,72,34 --118,72,42 --118,72,50 --118,72,58 --118,72,66 --118,72,74 --118,72,82 --118,72,90 --118,72,98 --118,72,106 --118,72,114 --118,72,122 --118,72,130 --118,72,138 --118,72,146 --110,72,-150 --110,72,-142 --110,72,-134 --110,72,-126 --110,72,-118 --110,72,-110 --110,72,-102 --110,72,-94 --110,72,-86 --110,72,-78 --110,72,-70 --110,72,-62 --110,72,-54 --110,72,-46 --110,72,-38 --110,72,-30 --110,72,-22 --110,72,-14 --110,72,-6 --110,72,2 --110,72,10 --110,72,18 --110,72,26 --110,72,34 --110,72,42 --110,72,50 --110,72,58 --110,72,66 --110,72,74 --110,72,82 --110,72,90 --110,72,98 --110,72,106 --110,72,114 --110,72,122 --110,72,130 --110,72,138 --110,72,146 --102,72,-150 --102,72,-142 --102,72,-134 --102,72,-126 --102,72,-118 --102,72,-110 --102,72,-102 --102,72,-94 --102,72,-86 --102,72,-78 --102,72,-70 --102,72,-62 --102,72,-54 --102,72,-46 --102,72,-38 --102,72,-30 --102,72,-22 --102,72,-14 --102,72,-6 --102,72,2 --102,72,10 --102,72,18 --102,72,26 --102,72,34 --102,72,42 --102,72,50 --102,72,58 --102,72,66 --102,72,74 --102,72,82 --102,72,90 --102,72,98 --102,72,106 --102,72,114 --102,72,122 --102,72,130 --102,72,138 --102,72,146 --94,72,-150 --94,72,-142 --94,72,-134 --94,72,-126 --94,72,-118 --94,72,-110 --94,72,-102 --94,72,-94 --94,72,-86 --94,72,-78 --94,72,-70 --94,72,-62 --94,72,-54 --94,72,-46 --94,72,-38 --94,72,-30 --94,72,-22 --94,72,-14 --94,72,-6 --94,72,2 --94,72,10 --94,72,18 --94,72,26 --94,72,34 --94,72,42 --94,72,50 --94,72,58 --94,72,66 --94,72,74 --94,72,82 --94,72,90 --94,72,98 --94,72,106 --94,72,114 --94,72,122 --94,72,130 --94,72,138 --94,72,146 --86,72,-150 --86,72,-142 --86,72,-134 --86,72,-126 --86,72,-118 --86,72,-110 --86,72,-102 --86,72,-94 --86,72,-86 --86,72,-78 --86,72,-70 --86,72,-62 --86,72,-54 --86,72,-46 --86,72,-38 --86,72,-30 --86,72,-22 --86,72,-14 --86,72,-6 --86,72,2 --86,72,10 --86,72,18 --86,72,26 --86,72,34 --86,72,42 --86,72,50 --86,72,58 --86,72,66 --86,72,74 --86,72,82 --86,72,90 --86,72,98 --86,72,106 --86,72,114 --86,72,122 --86,72,130 --86,72,138 --86,72,146 --78,72,-150 --78,72,-142 --78,72,-134 --78,72,-126 --78,72,-118 --78,72,-110 --78,72,-102 --78,72,-94 --78,72,-86 --78,72,-78 --78,72,-70 --78,72,-62 --78,72,-54 --78,72,-46 --78,72,-38 --78,72,-30 --78,72,-22 --78,72,-14 --78,72,-6 --78,72,2 --78,72,10 --78,72,18 --78,72,26 --78,72,34 --78,72,42 --78,72,50 --78,72,58 --78,72,66 --78,72,74 --78,72,82 --78,72,90 --78,72,98 --78,72,106 --78,72,114 --78,72,122 --78,72,130 --78,72,138 --78,72,146 --70,72,-150 --70,72,-142 --70,72,-134 --70,72,-126 --70,72,-118 --70,72,-110 --70,72,-102 --70,72,-94 --70,72,-86 --70,72,-78 --70,72,-70 --70,72,-62 --70,72,-54 --70,72,-46 --70,72,-38 --70,72,-30 --70,72,-22 --70,72,-14 --70,72,-6 --70,72,2 --70,72,10 --70,72,18 --70,72,26 --70,72,34 --70,72,42 --70,72,50 --70,72,58 --70,72,66 --70,72,74 --70,72,82 --70,72,90 --70,72,98 --70,72,106 --70,72,114 --70,72,122 --70,72,130 --70,72,138 --70,72,146 --62,72,-150 --62,72,-142 --62,72,-134 --62,72,-126 --62,72,-118 --62,72,-110 --62,72,-102 --62,72,-94 --62,72,-86 --62,72,-78 --62,72,-70 --62,72,-62 --62,72,-54 --62,72,-46 --62,72,-38 --62,72,-30 --62,72,-22 --62,72,-14 --62,72,-6 --62,72,2 --62,72,10 --62,72,18 --62,72,26 --62,72,34 --62,72,42 --62,72,50 --62,72,58 --62,72,66 --62,72,74 --62,72,82 --62,72,90 --62,72,98 --62,72,106 --62,72,114 --62,72,122 --62,72,130 --62,72,138 --62,72,146 --54,72,-150 --54,72,-142 --54,72,-134 --54,72,-126 --54,72,-118 --54,72,-110 --54,72,-102 --54,72,-94 --54,72,-86 --54,72,-78 --54,72,-70 --54,72,-62 --54,72,-54 --54,72,-46 --54,72,-38 --54,72,-30 --54,72,-22 --54,72,-14 --54,72,-6 --54,72,2 --54,72,10 --54,72,18 --54,72,26 --54,72,34 --54,72,42 --54,72,50 --54,72,58 --54,72,66 --54,72,74 --54,72,82 --54,72,90 --54,72,98 --54,72,106 --54,72,114 --54,72,122 --54,72,130 --54,72,138 --54,72,146 --46,72,-150 --46,72,-142 --46,72,-134 --46,72,-126 --46,72,-118 --46,72,-110 --46,72,-102 --46,72,-94 --46,72,-86 --46,72,-78 --46,72,-70 --46,72,-62 --46,72,-54 --46,72,-46 --46,72,-38 --46,72,-30 --46,72,-22 --46,72,-14 --46,72,-6 --46,72,2 --46,72,10 --46,72,18 --46,72,26 --46,72,34 --46,72,42 --46,72,50 --46,72,58 --46,72,66 --46,72,74 --46,72,82 --46,72,90 --46,72,98 --46,72,106 --46,72,114 --46,72,122 --46,72,130 --46,72,138 --46,72,146 --38,72,-150 --38,72,-142 --38,72,-134 --38,72,-126 --38,72,-118 --38,72,-110 --38,72,-102 --38,72,-94 --38,72,-86 --38,72,-78 --38,72,-70 --38,72,-62 --38,72,-54 --38,72,-46 --38,72,-38 --38,72,-30 --38,72,-22 --38,72,-14 --38,72,-6 --38,72,2 --38,72,10 --38,72,18 --38,72,26 --38,72,34 --38,72,42 --38,72,50 --38,72,58 --38,72,66 --38,72,74 --38,72,82 --38,72,90 --38,72,98 --38,72,106 --38,72,114 --38,72,122 --38,72,130 --38,72,138 --38,72,146 --30,72,-150 --30,72,-142 --30,72,-134 --30,72,-126 --30,72,-118 --30,72,-110 --30,72,-102 --30,72,-94 --30,72,-86 --30,72,-78 --30,72,-70 --30,72,-62 --30,72,-54 --30,72,-46 --30,72,-38 --30,72,-30 --30,72,-22 --30,72,-14 --30,72,-6 --30,72,2 --30,72,10 --30,72,18 --30,72,26 --30,72,34 --30,72,42 --30,72,50 --30,72,58 --30,72,66 --30,72,74 --30,72,82 --30,72,90 --30,72,98 --30,72,106 --30,72,114 --30,72,122 --30,72,130 --30,72,138 --30,72,146 --22,72,-150 --22,72,-142 --22,72,-134 --22,72,-126 --22,72,-118 --22,72,-110 --22,72,-102 --22,72,-94 --22,72,-86 --22,72,-78 --22,72,-70 --22,72,-62 --22,72,-54 --22,72,-46 --22,72,-38 --22,72,-30 --22,72,-22 --22,72,-14 --22,72,-6 --22,72,2 --22,72,10 --22,72,18 --22,72,26 --22,72,34 --22,72,42 --22,72,50 --22,72,58 --22,72,66 --22,72,74 --22,72,82 --22,72,90 --22,72,98 --22,72,106 --22,72,114 --22,72,122 --22,72,130 --22,72,138 --22,72,146 --14,72,-150 --14,72,-142 --14,72,-134 --14,72,-126 --14,72,-118 --14,72,-110 --14,72,-102 --14,72,-94 --14,72,-86 --14,72,-78 --14,72,-70 --14,72,-62 --14,72,-54 --14,72,-46 --14,72,-38 --14,72,-30 --14,72,-22 --14,72,-14 --14,72,-6 --14,72,2 --14,72,10 --14,72,18 --14,72,26 --14,72,34 --14,72,42 --14,72,50 --14,72,58 --14,72,66 --14,72,74 --14,72,82 --14,72,90 --14,72,98 --14,72,106 --14,72,114 --14,72,122 --14,72,130 --14,72,138 --14,72,146 --6,72,-150 --6,72,-142 --6,72,-134 --6,72,-126 --6,72,-118 --6,72,-110 --6,72,-102 --6,72,-94 --6,72,-86 --6,72,-78 --6,72,-70 --6,72,-62 --6,72,-54 --6,72,-46 --6,72,-38 --6,72,-30 --6,72,-22 --6,72,-14 --6,72,-6 --6,72,2 --6,72,10 --6,72,18 --6,72,26 --6,72,34 --6,72,42 --6,72,50 --6,72,58 --6,72,66 --6,72,74 --6,72,82 --6,72,90 --6,72,98 --6,72,106 --6,72,114 --6,72,122 --6,72,130 --6,72,138 --6,72,146 -2,72,-150 -2,72,-142 -2,72,-134 -2,72,-126 -2,72,-118 -2,72,-110 -2,72,-102 -2,72,-94 -2,72,-86 -2,72,-78 -2,72,-70 -2,72,-62 -2,72,-54 -2,72,-46 -2,72,-38 -2,72,-30 -2,72,-22 -2,72,-14 -2,72,-6 -2,72,2 -2,72,10 -2,72,18 -2,72,26 -2,72,34 -2,72,42 -2,72,50 -2,72,58 -2,72,66 -2,72,74 -2,72,82 -2,72,90 -2,72,98 -2,72,106 -2,72,114 -2,72,122 -2,72,130 -2,72,138 -2,72,146 -10,72,-150 -10,72,-142 -10,72,-134 -10,72,-126 -10,72,-118 -10,72,-110 -10,72,-102 -10,72,-94 -10,72,-86 -10,72,-78 -10,72,-70 -10,72,-62 -10,72,-54 -10,72,-46 -10,72,-38 -10,72,-30 -10,72,-22 -10,72,-14 -10,72,-6 -10,72,2 -10,72,10 -10,72,18 -10,72,26 -10,72,34 -10,72,42 -10,72,50 -10,72,58 -10,72,66 -10,72,74 -10,72,82 -10,72,90 -10,72,98 -10,72,106 -10,72,114 -10,72,122 -10,72,130 -10,72,138 -10,72,146 -18,72,-150 -18,72,-142 -18,72,-134 -18,72,-126 -18,72,-118 -18,72,-110 -18,72,-102 -18,72,-94 -18,72,-86 -18,72,-78 -18,72,-70 -18,72,-62 -18,72,-54 -18,72,-46 -18,72,-38 -18,72,-30 -18,72,-22 -18,72,-14 -18,72,-6 -18,72,2 -18,72,10 -18,72,18 -18,72,26 -18,72,34 -18,72,42 -18,72,50 -18,72,58 -18,72,66 -18,72,74 -18,72,82 -18,72,90 -18,72,98 -18,72,106 -18,72,114 -18,72,122 -18,72,130 -18,72,138 -18,72,146 -26,72,-150 -26,72,-142 -26,72,-134 -26,72,-126 -26,72,-118 -26,72,-110 -26,72,-102 -26,72,-94 -26,72,-86 -26,72,-78 -26,72,-70 -26,72,-62 -26,72,-54 -26,72,-46 -26,72,-38 -26,72,-30 -26,72,-22 -26,72,-14 -26,72,-6 -26,72,2 -26,72,10 -26,72,18 -26,72,26 -26,72,34 -26,72,42 -26,72,50 -26,72,58 -26,72,66 -26,72,74 -26,72,82 -26,72,90 -26,72,98 -26,72,106 -26,72,114 -26,72,122 -26,72,130 -26,72,138 -26,72,146 -34,72,-150 -34,72,-142 -34,72,-134 -34,72,-126 -34,72,-118 -34,72,-110 -34,72,-102 -34,72,-94 -34,72,-86 -34,72,-78 -34,72,-70 -34,72,-62 -34,72,-54 -34,72,-46 -34,72,-38 -34,72,-30 -34,72,-22 -34,72,-14 -34,72,-6 -34,72,2 -34,72,10 -34,72,18 -34,72,26 -34,72,34 -34,72,42 -34,72,50 -34,72,58 -34,72,66 -34,72,74 -34,72,82 -34,72,90 -34,72,98 -34,72,106 -34,72,114 -34,72,122 -34,72,130 -34,72,138 -34,72,146 -42,72,-150 -42,72,-142 -42,72,-134 -42,72,-126 -42,72,-118 -42,72,-110 -42,72,-102 -42,72,-94 -42,72,-86 -42,72,-78 -42,72,-70 -42,72,-62 -42,72,-54 -42,72,-46 -42,72,-38 -42,72,-30 -42,72,-22 -42,72,-14 -42,72,-6 -42,72,2 -42,72,10 -42,72,18 -42,72,26 -42,72,34 -42,72,42 -42,72,50 -42,72,58 -42,72,66 -42,72,74 -42,72,82 -42,72,90 -42,72,98 -42,72,106 -42,72,114 -42,72,122 -42,72,130 -42,72,138 -42,72,146 -50,72,-150 -50,72,-142 -50,72,-134 -50,72,-126 -50,72,-118 -50,72,-110 -50,72,-102 -50,72,-94 -50,72,-86 -50,72,-78 -50,72,-70 -50,72,-62 -50,72,-54 -50,72,-46 -50,72,-38 -50,72,-30 -50,72,-22 -50,72,-14 -50,72,-6 -50,72,2 -50,72,10 -50,72,18 -50,72,26 -50,72,34 -50,72,42 -50,72,50 -50,72,58 -50,72,66 -50,72,74 -50,72,82 -50,72,90 -50,72,98 -50,72,106 -50,72,114 -50,72,122 -50,72,130 -50,72,138 -50,72,146 -58,72,-150 -58,72,-142 -58,72,-134 -58,72,-126 -58,72,-118 -58,72,-110 -58,72,-102 -58,72,-94 -58,72,-86 -58,72,-78 -58,72,-70 -58,72,-62 -58,72,-54 -58,72,-46 -58,72,-38 -58,72,-30 -58,72,-22 -58,72,-14 -58,72,-6 -58,72,2 -58,72,10 -58,72,18 -58,72,26 -58,72,34 -58,72,42 -58,72,50 -58,72,58 -58,72,66 -58,72,74 -58,72,82 -58,72,90 -58,72,98 -58,72,106 -58,72,114 -58,72,122 -58,72,130 -58,72,138 -58,72,146 -66,72,-150 -66,72,-142 -66,72,-134 -66,72,-126 -66,72,-118 -66,72,-110 -66,72,-102 -66,72,-94 -66,72,-86 -66,72,-78 -66,72,-70 -66,72,-62 -66,72,-54 -66,72,-46 -66,72,-38 -66,72,-30 -66,72,-22 -66,72,-14 -66,72,-6 -66,72,2 -66,72,10 -66,72,18 -66,72,26 -66,72,34 -66,72,42 -66,72,50 -66,72,58 -66,72,66 -66,72,74 -66,72,82 -66,72,90 -66,72,98 -66,72,106 -66,72,114 -66,72,122 -66,72,130 -66,72,138 -66,72,146 -74,72,-150 -74,72,-142 -74,72,-134 -74,72,-126 -74,72,-118 -74,72,-110 -74,72,-102 -74,72,-94 -74,72,-86 -74,72,-78 -74,72,-70 -74,72,-62 -74,72,-54 -74,72,-46 -74,72,-38 -74,72,-30 -74,72,-22 -74,72,-14 -74,72,-6 -74,72,2 -74,72,10 -74,72,18 -74,72,26 -74,72,34 -74,72,42 -74,72,50 -74,72,58 -74,72,66 -74,72,74 -74,72,82 -74,72,90 -74,72,98 -74,72,106 -74,72,114 -74,72,122 -74,72,130 -74,72,138 -74,72,146 -82,72,-150 -82,72,-142 -82,72,-134 -82,72,-126 -82,72,-118 -82,72,-110 -82,72,-102 -82,72,-94 -82,72,-86 -82,72,-78 -82,72,-70 -82,72,-62 -82,72,-54 -82,72,-46 -82,72,-38 -82,72,-30 -82,72,-22 -82,72,-14 -82,72,-6 -82,72,2 -82,72,10 -82,72,18 -82,72,26 -82,72,34 -82,72,42 -82,72,50 -82,72,58 -82,72,66 -82,72,74 -82,72,82 -82,72,90 -82,72,98 -82,72,106 -82,72,114 -82,72,122 -82,72,130 -82,72,138 -82,72,146 -90,72,-150 -90,72,-142 -90,72,-134 -90,72,-126 -90,72,-118 -90,72,-110 -90,72,-102 -90,72,-94 -90,72,-86 -90,72,-78 -90,72,-70 -90,72,-62 -90,72,-54 -90,72,-46 -90,72,-38 -90,72,-30 -90,72,-22 -90,72,-14 -90,72,-6 -90,72,2 -90,72,10 -90,72,18 -90,72,26 -90,72,34 -90,72,42 -90,72,50 -90,72,58 -90,72,66 -90,72,74 -90,72,82 -90,72,90 -90,72,98 -90,72,106 -90,72,114 -90,72,122 -90,72,130 -90,72,138 -90,72,146 -98,72,-150 -98,72,-142 -98,72,-134 -98,72,-126 -98,72,-118 -98,72,-110 -98,72,-102 -98,72,-94 -98,72,-86 -98,72,-78 -98,72,-70 -98,72,-62 -98,72,-54 -98,72,-46 -98,72,-38 -98,72,-30 -98,72,-22 -98,72,-14 -98,72,-6 -98,72,2 -98,72,10 -98,72,18 -98,72,26 -98,72,34 -98,72,42 -98,72,50 -98,72,58 -98,72,66 -98,72,74 -98,72,82 -98,72,90 -98,72,98 -98,72,106 -98,72,114 -98,72,122 -98,72,130 -98,72,138 -98,72,146 -106,72,-150 -106,72,-142 -106,72,-134 -106,72,-126 -106,72,-118 -106,72,-110 -106,72,-102 -106,72,-94 -106,72,-86 -106,72,-78 -106,72,-70 -106,72,-62 -106,72,-54 -106,72,-46 -106,72,-38 -106,72,-30 -106,72,-22 -106,72,-14 -106,72,-6 -106,72,2 -106,72,10 -106,72,18 -106,72,26 -106,72,34 -106,72,42 -106,72,50 -106,72,58 -106,72,66 -106,72,74 -106,72,82 -106,72,90 -106,72,98 -106,72,106 -106,72,114 -106,72,122 -106,72,130 -106,72,138 -106,72,146 -114,72,-150 -114,72,-142 -114,72,-134 -114,72,-126 -114,72,-118 -114,72,-110 -114,72,-102 -114,72,-94 -114,72,-86 -114,72,-78 -114,72,-70 -114,72,-62 -114,72,-54 -114,72,-46 -114,72,-38 -114,72,-30 -114,72,-22 -114,72,-14 -114,72,-6 -114,72,2 -114,72,10 -114,72,18 -114,72,26 -114,72,34 -114,72,42 -114,72,50 -114,72,58 -114,72,66 -114,72,74 -114,72,82 -114,72,90 -114,72,98 -114,72,106 -114,72,114 -114,72,122 -114,72,130 -114,72,138 -114,72,146 -122,72,-150 -122,72,-142 -122,72,-134 -122,72,-126 -122,72,-118 -122,72,-110 -122,72,-102 -122,72,-94 -122,72,-86 -122,72,-78 -122,72,-70 -122,72,-62 -122,72,-54 -122,72,-46 -122,72,-38 -122,72,-30 -122,72,-22 -122,72,-14 -122,72,-6 -122,72,2 -122,72,10 -122,72,18 -122,72,26 -122,72,34 -122,72,42 -122,72,50 -122,72,58 -122,72,66 -122,72,74 -122,72,82 -122,72,90 -122,72,98 -122,72,106 -122,72,114 -122,72,122 -122,72,130 -122,72,138 -122,72,146 -130,72,-150 -130,72,-142 -130,72,-134 -130,72,-126 -130,72,-118 -130,72,-110 -130,72,-102 -130,72,-94 -130,72,-86 -130,72,-78 -130,72,-70 -130,72,-62 -130,72,-54 -130,72,-46 -130,72,-38 -130,72,-30 -130,72,-22 -130,72,-14 -130,72,-6 -130,72,2 -130,72,10 -130,72,18 -130,72,26 -130,72,34 -130,72,42 -130,72,50 -130,72,58 -130,72,66 -130,72,74 -130,72,82 -130,72,90 -130,72,98 -130,72,106 -130,72,114 -130,72,122 -130,72,130 -130,72,138 -130,72,146 -138,72,-150 -138,72,-142 -138,72,-134 -138,72,-126 -138,72,-118 -138,72,-110 -138,72,-102 -138,72,-94 -138,72,-86 -138,72,-78 -138,72,-70 -138,72,-62 -138,72,-54 -138,72,-46 -138,72,-38 -138,72,-30 -138,72,-22 -138,72,-14 -138,72,-6 -138,72,2 -138,72,10 -138,72,18 -138,72,26 -138,72,34 -138,72,42 -138,72,50 -138,72,58 -138,72,66 -138,72,74 -138,72,82 -138,72,90 -138,72,98 -138,72,106 -138,72,114 -138,72,122 -138,72,130 -138,72,138 -138,72,146 -146,72,-150 -146,72,-142 -146,72,-134 -146,72,-126 -146,72,-118 -146,72,-110 -146,72,-102 -146,72,-94 -146,72,-86 -146,72,-78 -146,72,-70 -146,72,-62 -146,72,-54 -146,72,-46 -146,72,-38 -146,72,-30 -146,72,-22 -146,72,-14 -146,72,-6 -146,72,2 -146,72,10 -146,72,18 -146,72,26 -146,72,34 -146,72,42 -146,72,50 -146,72,58 -146,72,66 -146,72,74 -146,72,82 -146,72,90 -146,72,98 -146,72,106 -146,72,114 -146,72,122 -146,72,130 -146,72,138 -146,72,146 --150,80,-150 --150,80,-142 --150,80,-134 --150,80,-126 --150,80,-118 --150,80,-110 --150,80,-102 --150,80,-94 --150,80,-86 --150,80,-78 --150,80,-70 --150,80,-62 --150,80,-54 --150,80,-46 --150,80,-38 --150,80,-30 --150,80,-22 --150,80,-14 --150,80,-6 --150,80,2 --150,80,10 --150,80,18 --150,80,26 --150,80,34 --150,80,42 --150,80,50 --150,80,58 --150,80,66 --150,80,74 --150,80,82 --150,80,90 --150,80,98 --150,80,106 --150,80,114 --150,80,122 --150,80,130 --150,80,138 --150,80,146 --142,80,-150 --142,80,-142 --142,80,-134 --142,80,-126 --142,80,-118 --142,80,-110 --142,80,-102 --142,80,-94 --142,80,-86 --142,80,-78 --142,80,-70 --142,80,-62 --142,80,-54 --142,80,-46 --142,80,-38 --142,80,-30 --142,80,-22 --142,80,-14 --142,80,-6 --142,80,2 --142,80,10 --142,80,18 --142,80,26 --142,80,34 --142,80,42 --142,80,50 --142,80,58 --142,80,66 --142,80,74 --142,80,82 --142,80,90 --142,80,98 --142,80,106 --142,80,114 --142,80,122 --142,80,130 --142,80,138 --142,80,146 --134,80,-150 --134,80,-142 --134,80,-134 --134,80,-126 --134,80,-118 --134,80,-110 --134,80,-102 --134,80,-94 --134,80,-86 --134,80,-78 --134,80,-70 --134,80,-62 --134,80,-54 --134,80,-46 --134,80,-38 --134,80,-30 --134,80,-22 --134,80,-14 --134,80,-6 --134,80,2 --134,80,10 --134,80,18 --134,80,26 --134,80,34 --134,80,42 --134,80,50 --134,80,58 --134,80,66 --134,80,74 --134,80,82 --134,80,90 --134,80,98 --134,80,106 --134,80,114 --134,80,122 --134,80,130 --134,80,138 --134,80,146 --126,80,-150 --126,80,-142 --126,80,-134 --126,80,-126 --126,80,-118 --126,80,-110 --126,80,-102 --126,80,-94 --126,80,-86 --126,80,-78 --126,80,-70 --126,80,-62 --126,80,-54 --126,80,-46 --126,80,-38 --126,80,-30 --126,80,-22 --126,80,-14 --126,80,-6 --126,80,2 --126,80,10 --126,80,18 --126,80,26 --126,80,34 --126,80,42 --126,80,50 --126,80,58 --126,80,66 --126,80,74 --126,80,82 --126,80,90 --126,80,98 --126,80,106 --126,80,114 --126,80,122 --126,80,130 --126,80,138 --126,80,146 --118,80,-150 --118,80,-142 --118,80,-134 --118,80,-126 --118,80,-118 --118,80,-110 --118,80,-102 --118,80,-94 --118,80,-86 --118,80,-78 --118,80,-70 --118,80,-62 --118,80,-54 --118,80,-46 --118,80,-38 --118,80,-30 --118,80,-22 --118,80,-14 --118,80,-6 --118,80,2 --118,80,10 --118,80,18 --118,80,26 --118,80,34 --118,80,42 --118,80,50 --118,80,58 --118,80,66 --118,80,74 --118,80,82 --118,80,90 --118,80,98 --118,80,106 --118,80,114 --118,80,122 --118,80,130 --118,80,138 --118,80,146 --110,80,-150 --110,80,-142 --110,80,-134 --110,80,-126 --110,80,-118 --110,80,-110 --110,80,-102 --110,80,-94 --110,80,-86 --110,80,-78 --110,80,-70 --110,80,-62 --110,80,-54 --110,80,-46 --110,80,-38 --110,80,-30 --110,80,-22 --110,80,-14 --110,80,-6 --110,80,2 --110,80,10 --110,80,18 --110,80,26 --110,80,34 --110,80,42 --110,80,50 --110,80,58 --110,80,66 --110,80,74 --110,80,82 --110,80,90 --110,80,98 --110,80,106 --110,80,114 --110,80,122 --110,80,130 --110,80,138 --110,80,146 --102,80,-150 --102,80,-142 --102,80,-134 --102,80,-126 --102,80,-118 --102,80,-110 --102,80,-102 --102,80,-94 --102,80,-86 --102,80,-78 --102,80,-70 --102,80,-62 --102,80,-54 --102,80,-46 --102,80,-38 --102,80,-30 --102,80,-22 --102,80,-14 --102,80,-6 --102,80,2 --102,80,10 --102,80,18 --102,80,26 --102,80,34 --102,80,42 --102,80,50 --102,80,58 --102,80,66 --102,80,74 --102,80,82 --102,80,90 --102,80,98 --102,80,106 --102,80,114 --102,80,122 --102,80,130 --102,80,138 --102,80,146 --94,80,-150 --94,80,-142 --94,80,-134 --94,80,-126 --94,80,-118 --94,80,-110 --94,80,-102 --94,80,-94 --94,80,-86 --94,80,-78 --94,80,-70 --94,80,-62 --94,80,-54 --94,80,-46 --94,80,-38 --94,80,-30 --94,80,-22 --94,80,-14 --94,80,-6 --94,80,2 --94,80,10 --94,80,18 --94,80,26 --94,80,34 --94,80,42 --94,80,50 --94,80,58 --94,80,66 --94,80,74 --94,80,82 --94,80,90 --94,80,98 --94,80,106 --94,80,114 --94,80,122 --94,80,130 --94,80,138 --94,80,146 --86,80,-150 --86,80,-142 --86,80,-134 --86,80,-126 --86,80,-118 --86,80,-110 --86,80,-102 --86,80,-94 --86,80,-86 --86,80,-78 --86,80,-70 --86,80,-62 --86,80,-54 --86,80,-46 --86,80,-38 --86,80,-30 --86,80,-22 --86,80,-14 --86,80,-6 --86,80,2 --86,80,10 --86,80,18 --86,80,26 --86,80,34 --86,80,42 --86,80,50 --86,80,58 --86,80,66 --86,80,74 --86,80,82 --86,80,90 --86,80,98 --86,80,106 --86,80,114 --86,80,122 --86,80,130 --86,80,138 --86,80,146 --78,80,-150 --78,80,-142 --78,80,-134 --78,80,-126 --78,80,-118 --78,80,-110 --78,80,-102 --78,80,-94 --78,80,-86 --78,80,-78 --78,80,-70 --78,80,-62 --78,80,-54 --78,80,-46 --78,80,-38 --78,80,-30 --78,80,-22 --78,80,-14 --78,80,-6 --78,80,2 --78,80,10 --78,80,18 --78,80,26 --78,80,34 --78,80,42 --78,80,50 --78,80,58 --78,80,66 --78,80,74 --78,80,82 --78,80,90 --78,80,98 --78,80,106 --78,80,114 --78,80,122 --78,80,130 --78,80,138 --78,80,146 --70,80,-150 --70,80,-142 --70,80,-134 --70,80,-126 --70,80,-118 --70,80,-110 --70,80,-102 --70,80,-94 --70,80,-86 --70,80,-78 --70,80,-70 --70,80,-62 --70,80,-54 --70,80,-46 --70,80,-38 --70,80,-30 --70,80,-22 --70,80,-14 --70,80,-6 --70,80,2 --70,80,10 --70,80,18 --70,80,26 --70,80,34 --70,80,42 --70,80,50 --70,80,58 --70,80,66 --70,80,74 --70,80,82 --70,80,90 --70,80,98 --70,80,106 --70,80,114 --70,80,122 --70,80,130 --70,80,138 --70,80,146 --62,80,-150 --62,80,-142 --62,80,-134 --62,80,-126 --62,80,-118 --62,80,-110 --62,80,-102 --62,80,-94 --62,80,-86 --62,80,-78 --62,80,-70 --62,80,-62 --62,80,-54 --62,80,-46 --62,80,-38 --62,80,-30 --62,80,-22 --62,80,-14 --62,80,-6 --62,80,2 --62,80,10 --62,80,18 --62,80,26 --62,80,34 --62,80,42 --62,80,50 --62,80,58 --62,80,66 --62,80,74 --62,80,82 --62,80,90 --62,80,98 --62,80,106 --62,80,114 --62,80,122 --62,80,130 --62,80,138 --62,80,146 --54,80,-150 --54,80,-142 --54,80,-134 --54,80,-126 --54,80,-118 --54,80,-110 --54,80,-102 --54,80,-94 --54,80,-86 --54,80,-78 --54,80,-70 --54,80,-62 --54,80,-54 --54,80,-46 --54,80,-38 --54,80,-30 --54,80,-22 --54,80,-14 --54,80,-6 --54,80,2 --54,80,10 --54,80,18 --54,80,26 --54,80,34 --54,80,42 --54,80,50 --54,80,58 --54,80,66 --54,80,74 --54,80,82 --54,80,90 --54,80,98 --54,80,106 --54,80,114 --54,80,122 --54,80,130 --54,80,138 --54,80,146 --46,80,-150 --46,80,-142 --46,80,-134 --46,80,-126 --46,80,-118 --46,80,-110 --46,80,-102 --46,80,-94 --46,80,-86 --46,80,-78 --46,80,-70 --46,80,-62 --46,80,-54 --46,80,-46 --46,80,-38 --46,80,-30 --46,80,-22 --46,80,-14 --46,80,-6 --46,80,2 --46,80,10 --46,80,18 --46,80,26 --46,80,34 --46,80,42 --46,80,50 --46,80,58 --46,80,66 --46,80,74 --46,80,82 --46,80,90 --46,80,98 --46,80,106 --46,80,114 --46,80,122 --46,80,130 --46,80,138 --46,80,146 --38,80,-150 --38,80,-142 --38,80,-134 --38,80,-126 --38,80,-118 --38,80,-110 --38,80,-102 --38,80,-94 --38,80,-86 --38,80,-78 --38,80,-70 --38,80,-62 --38,80,-54 --38,80,-46 --38,80,-38 --38,80,-30 --38,80,-22 --38,80,-14 --38,80,-6 --38,80,2 --38,80,10 --38,80,18 --38,80,26 --38,80,34 --38,80,42 --38,80,50 --38,80,58 --38,80,66 --38,80,74 --38,80,82 --38,80,90 --38,80,98 --38,80,106 --38,80,114 --38,80,122 --38,80,130 --38,80,138 --38,80,146 --30,80,-150 --30,80,-142 --30,80,-134 --30,80,-126 --30,80,-118 --30,80,-110 --30,80,-102 --30,80,-94 --30,80,-86 --30,80,-78 --30,80,-70 --30,80,-62 --30,80,-54 --30,80,-46 --30,80,-38 --30,80,-30 --30,80,-22 --30,80,-14 --30,80,-6 --30,80,2 --30,80,10 --30,80,18 --30,80,26 --30,80,34 --30,80,42 --30,80,50 --30,80,58 --30,80,66 --30,80,74 --30,80,82 --30,80,90 --30,80,98 --30,80,106 --30,80,114 --30,80,122 --30,80,130 --30,80,138 --30,80,146 --22,80,-150 --22,80,-142 --22,80,-134 --22,80,-126 --22,80,-118 --22,80,-110 --22,80,-102 --22,80,-94 --22,80,-86 --22,80,-78 --22,80,-70 --22,80,-62 --22,80,-54 --22,80,-46 --22,80,-38 --22,80,-30 --22,80,-22 --22,80,-14 --22,80,-6 --22,80,2 --22,80,10 --22,80,18 --22,80,26 --22,80,34 --22,80,42 --22,80,50 --22,80,58 --22,80,66 --22,80,74 --22,80,82 --22,80,90 --22,80,98 --22,80,106 --22,80,114 --22,80,122 --22,80,130 --22,80,138 --22,80,146 --14,80,-150 --14,80,-142 --14,80,-134 --14,80,-126 --14,80,-118 --14,80,-110 --14,80,-102 --14,80,-94 --14,80,-86 --14,80,-78 --14,80,-70 --14,80,-62 --14,80,-54 --14,80,-46 --14,80,-38 --14,80,-30 --14,80,-22 --14,80,-14 --14,80,-6 --14,80,2 --14,80,10 --14,80,18 --14,80,26 --14,80,34 --14,80,42 --14,80,50 --14,80,58 --14,80,66 --14,80,74 --14,80,82 --14,80,90 --14,80,98 --14,80,106 --14,80,114 --14,80,122 --14,80,130 --14,80,138 --14,80,146 --6,80,-150 --6,80,-142 --6,80,-134 --6,80,-126 --6,80,-118 --6,80,-110 --6,80,-102 --6,80,-94 --6,80,-86 --6,80,-78 --6,80,-70 --6,80,-62 --6,80,-54 --6,80,-46 --6,80,-38 --6,80,-30 --6,80,-22 --6,80,-14 --6,80,-6 --6,80,2 --6,80,10 --6,80,18 --6,80,26 --6,80,34 --6,80,42 --6,80,50 --6,80,58 --6,80,66 --6,80,74 --6,80,82 --6,80,90 --6,80,98 --6,80,106 --6,80,114 --6,80,122 --6,80,130 --6,80,138 --6,80,146 -2,80,-150 -2,80,-142 -2,80,-134 -2,80,-126 -2,80,-118 -2,80,-110 -2,80,-102 -2,80,-94 -2,80,-86 -2,80,-78 -2,80,-70 -2,80,-62 -2,80,-54 -2,80,-46 -2,80,-38 -2,80,-30 -2,80,-22 -2,80,-14 -2,80,-6 -2,80,2 -2,80,10 -2,80,18 -2,80,26 -2,80,34 -2,80,42 -2,80,50 -2,80,58 -2,80,66 -2,80,74 -2,80,82 -2,80,90 -2,80,98 -2,80,106 -2,80,114 -2,80,122 -2,80,130 -2,80,138 -2,80,146 -10,80,-150 -10,80,-142 -10,80,-134 -10,80,-126 -10,80,-118 -10,80,-110 -10,80,-102 -10,80,-94 -10,80,-86 -10,80,-78 -10,80,-70 -10,80,-62 -10,80,-54 -10,80,-46 -10,80,-38 -10,80,-30 -10,80,-22 -10,80,-14 -10,80,-6 -10,80,2 -10,80,10 -10,80,18 -10,80,26 -10,80,34 -10,80,42 -10,80,50 -10,80,58 -10,80,66 -10,80,74 -10,80,82 -10,80,90 -10,80,98 -10,80,106 -10,80,114 -10,80,122 -10,80,130 -10,80,138 -10,80,146 -18,80,-150 -18,80,-142 -18,80,-134 -18,80,-126 -18,80,-118 -18,80,-110 -18,80,-102 -18,80,-94 -18,80,-86 -18,80,-78 -18,80,-70 -18,80,-62 -18,80,-54 -18,80,-46 -18,80,-38 -18,80,-30 -18,80,-22 -18,80,-14 -18,80,-6 -18,80,2 -18,80,10 -18,80,18 -18,80,26 -18,80,34 -18,80,42 -18,80,50 -18,80,58 -18,80,66 -18,80,74 -18,80,82 -18,80,90 -18,80,98 -18,80,106 -18,80,114 -18,80,122 -18,80,130 -18,80,138 -18,80,146 -26,80,-150 -26,80,-142 -26,80,-134 -26,80,-126 -26,80,-118 -26,80,-110 -26,80,-102 -26,80,-94 -26,80,-86 -26,80,-78 -26,80,-70 -26,80,-62 -26,80,-54 -26,80,-46 -26,80,-38 -26,80,-30 -26,80,-22 -26,80,-14 -26,80,-6 -26,80,2 -26,80,10 -26,80,18 -26,80,26 -26,80,34 -26,80,42 -26,80,50 -26,80,58 -26,80,66 -26,80,74 -26,80,82 -26,80,90 -26,80,98 -26,80,106 -26,80,114 -26,80,122 -26,80,130 -26,80,138 -26,80,146 -34,80,-150 -34,80,-142 -34,80,-134 -34,80,-126 -34,80,-118 -34,80,-110 -34,80,-102 -34,80,-94 -34,80,-86 -34,80,-78 -34,80,-70 -34,80,-62 -34,80,-54 -34,80,-46 -34,80,-38 -34,80,-30 -34,80,-22 -34,80,-14 -34,80,-6 -34,80,2 -34,80,10 -34,80,18 -34,80,26 -34,80,34 -34,80,42 -34,80,50 -34,80,58 -34,80,66 -34,80,74 -34,80,82 -34,80,90 -34,80,98 -34,80,106 -34,80,114 -34,80,122 -34,80,130 -34,80,138 -34,80,146 -42,80,-150 -42,80,-142 -42,80,-134 -42,80,-126 -42,80,-118 -42,80,-110 -42,80,-102 -42,80,-94 -42,80,-86 -42,80,-78 -42,80,-70 -42,80,-62 -42,80,-54 -42,80,-46 -42,80,-38 -42,80,-30 -42,80,-22 -42,80,-14 -42,80,-6 -42,80,2 -42,80,10 -42,80,18 -42,80,26 -42,80,34 -42,80,42 -42,80,50 -42,80,58 -42,80,66 -42,80,74 -42,80,82 -42,80,90 -42,80,98 -42,80,106 -42,80,114 -42,80,122 -42,80,130 -42,80,138 -42,80,146 -50,80,-150 -50,80,-142 -50,80,-134 -50,80,-126 -50,80,-118 -50,80,-110 -50,80,-102 -50,80,-94 -50,80,-86 -50,80,-78 -50,80,-70 -50,80,-62 -50,80,-54 -50,80,-46 -50,80,-38 -50,80,-30 -50,80,-22 -50,80,-14 -50,80,-6 -50,80,2 -50,80,10 -50,80,18 -50,80,26 -50,80,34 -50,80,42 -50,80,50 -50,80,58 -50,80,66 -50,80,74 -50,80,82 -50,80,90 -50,80,98 -50,80,106 -50,80,114 -50,80,122 -50,80,130 -50,80,138 -50,80,146 -58,80,-150 -58,80,-142 -58,80,-134 -58,80,-126 -58,80,-118 -58,80,-110 -58,80,-102 -58,80,-94 -58,80,-86 -58,80,-78 -58,80,-70 -58,80,-62 -58,80,-54 -58,80,-46 -58,80,-38 -58,80,-30 -58,80,-22 -58,80,-14 -58,80,-6 -58,80,2 -58,80,10 -58,80,18 -58,80,26 -58,80,34 -58,80,42 -58,80,50 -58,80,58 -58,80,66 -58,80,74 -58,80,82 -58,80,90 -58,80,98 -58,80,106 -58,80,114 -58,80,122 -58,80,130 -58,80,138 -58,80,146 -66,80,-150 -66,80,-142 -66,80,-134 -66,80,-126 -66,80,-118 -66,80,-110 -66,80,-102 -66,80,-94 -66,80,-86 -66,80,-78 -66,80,-70 -66,80,-62 -66,80,-54 -66,80,-46 -66,80,-38 -66,80,-30 -66,80,-22 -66,80,-14 -66,80,-6 -66,80,2 -66,80,10 -66,80,18 -66,80,26 -66,80,34 -66,80,42 -66,80,50 -66,80,58 -66,80,66 -66,80,74 -66,80,82 -66,80,90 -66,80,98 -66,80,106 -66,80,114 -66,80,122 -66,80,130 -66,80,138 -66,80,146 -74,80,-150 -74,80,-142 -74,80,-134 -74,80,-126 -74,80,-118 -74,80,-110 -74,80,-102 -74,80,-94 -74,80,-86 -74,80,-78 -74,80,-70 -74,80,-62 -74,80,-54 -74,80,-46 -74,80,-38 -74,80,-30 -74,80,-22 -74,80,-14 -74,80,-6 -74,80,2 -74,80,10 -74,80,18 -74,80,26 -74,80,34 -74,80,42 -74,80,50 -74,80,58 -74,80,66 -74,80,74 -74,80,82 -74,80,90 -74,80,98 -74,80,106 -74,80,114 -74,80,122 -74,80,130 -74,80,138 -74,80,146 -82,80,-150 -82,80,-142 -82,80,-134 -82,80,-126 -82,80,-118 -82,80,-110 -82,80,-102 -82,80,-94 -82,80,-86 -82,80,-78 -82,80,-70 -82,80,-62 -82,80,-54 -82,80,-46 -82,80,-38 -82,80,-30 -82,80,-22 -82,80,-14 -82,80,-6 -82,80,2 -82,80,10 -82,80,18 -82,80,26 -82,80,34 -82,80,42 -82,80,50 -82,80,58 -82,80,66 -82,80,74 -82,80,82 -82,80,90 -82,80,98 -82,80,106 -82,80,114 -82,80,122 -82,80,130 -82,80,138 -82,80,146 -90,80,-150 -90,80,-142 -90,80,-134 -90,80,-126 -90,80,-118 -90,80,-110 -90,80,-102 -90,80,-94 -90,80,-86 -90,80,-78 -90,80,-70 -90,80,-62 -90,80,-54 -90,80,-46 -90,80,-38 -90,80,-30 -90,80,-22 -90,80,-14 -90,80,-6 -90,80,2 -90,80,10 -90,80,18 -90,80,26 -90,80,34 -90,80,42 -90,80,50 -90,80,58 -90,80,66 -90,80,74 -90,80,82 -90,80,90 -90,80,98 -90,80,106 -90,80,114 -90,80,122 -90,80,130 -90,80,138 -90,80,146 -98,80,-150 -98,80,-142 -98,80,-134 -98,80,-126 -98,80,-118 -98,80,-110 -98,80,-102 -98,80,-94 -98,80,-86 -98,80,-78 -98,80,-70 -98,80,-62 -98,80,-54 -98,80,-46 -98,80,-38 -98,80,-30 -98,80,-22 -98,80,-14 -98,80,-6 -98,80,2 -98,80,10 -98,80,18 -98,80,26 -98,80,34 -98,80,42 -98,80,50 -98,80,58 -98,80,66 -98,80,74 -98,80,82 -98,80,90 -98,80,98 -98,80,106 -98,80,114 -98,80,122 -98,80,130 -98,80,138 -98,80,146 -106,80,-150 -106,80,-142 -106,80,-134 -106,80,-126 -106,80,-118 -106,80,-110 -106,80,-102 -106,80,-94 -106,80,-86 -106,80,-78 -106,80,-70 -106,80,-62 -106,80,-54 -106,80,-46 -106,80,-38 -106,80,-30 -106,80,-22 -106,80,-14 -106,80,-6 -106,80,2 -106,80,10 -106,80,18 -106,80,26 -106,80,34 -106,80,42 -106,80,50 -106,80,58 -106,80,66 -106,80,74 -106,80,82 -106,80,90 -106,80,98 -106,80,106 -106,80,114 -106,80,122 -106,80,130 -106,80,138 -106,80,146 -114,80,-150 -114,80,-142 -114,80,-134 -114,80,-126 -114,80,-118 -114,80,-110 -114,80,-102 -114,80,-94 -114,80,-86 -114,80,-78 -114,80,-70 -114,80,-62 -114,80,-54 -114,80,-46 -114,80,-38 -114,80,-30 -114,80,-22 -114,80,-14 -114,80,-6 -114,80,2 -114,80,10 -114,80,18 -114,80,26 -114,80,34 -114,80,42 -114,80,50 -114,80,58 -114,80,66 -114,80,74 -114,80,82 -114,80,90 -114,80,98 -114,80,106 -114,80,114 -114,80,122 -114,80,130 -114,80,138 -114,80,146 -122,80,-150 -122,80,-142 -122,80,-134 -122,80,-126 -122,80,-118 -122,80,-110 -122,80,-102 -122,80,-94 -122,80,-86 -122,80,-78 -122,80,-70 -122,80,-62 -122,80,-54 -122,80,-46 -122,80,-38 -122,80,-30 -122,80,-22 -122,80,-14 -122,80,-6 -122,80,2 -122,80,10 -122,80,18 -122,80,26 -122,80,34 -122,80,42 -122,80,50 -122,80,58 -122,80,66 -122,80,74 -122,80,82 -122,80,90 -122,80,98 -122,80,106 -122,80,114 -122,80,122 -122,80,130 -122,80,138 -122,80,146 -130,80,-150 -130,80,-142 -130,80,-134 -130,80,-126 -130,80,-118 -130,80,-110 -130,80,-102 -130,80,-94 -130,80,-86 -130,80,-78 -130,80,-70 -130,80,-62 -130,80,-54 -130,80,-46 -130,80,-38 -130,80,-30 -130,80,-22 -130,80,-14 -130,80,-6 -130,80,2 -130,80,10 -130,80,18 -130,80,26 -130,80,34 -130,80,42 -130,80,50 -130,80,58 -130,80,66 -130,80,74 -130,80,82 -130,80,90 -130,80,98 -130,80,106 -130,80,114 -130,80,122 -130,80,130 -130,80,138 -130,80,146 -138,80,-150 -138,80,-142 -138,80,-134 -138,80,-126 -138,80,-118 -138,80,-110 -138,80,-102 -138,80,-94 -138,80,-86 -138,80,-78 -138,80,-70 -138,80,-62 -138,80,-54 -138,80,-46 -138,80,-38 -138,80,-30 -138,80,-22 -138,80,-14 -138,80,-6 -138,80,2 -138,80,10 -138,80,18 -138,80,26 -138,80,34 -138,80,42 -138,80,50 -138,80,58 -138,80,66 -138,80,74 -138,80,82 -138,80,90 -138,80,98 -138,80,106 -138,80,114 -138,80,122 -138,80,130 -138,80,138 -138,80,146 -146,80,-150 -146,80,-142 -146,80,-134 -146,80,-126 -146,80,-118 -146,80,-110 -146,80,-102 -146,80,-94 -146,80,-86 -146,80,-78 -146,80,-70 -146,80,-62 -146,80,-54 -146,80,-46 -146,80,-38 -146,80,-30 -146,80,-22 -146,80,-14 -146,80,-6 -146,80,2 -146,80,10 -146,80,18 -146,80,26 -146,80,34 -146,80,42 -146,80,50 -146,80,58 -146,80,66 -146,80,74 -146,80,82 -146,80,90 -146,80,98 -146,80,106 -146,80,114 -146,80,122 -146,80,130 -146,80,138 -146,80,146 \ No newline at end of file diff --git a/computer/13/fluid_state.lua b/computer/13/fluid_state.lua index 2a82c79..329dbe1 100644 --- a/computer/13/fluid_state.lua +++ b/computer/13/fluid_state.lua @@ -1,7 +1,7 @@ return { { name = "water", - amount = 1409400, + amount = 0, }, { name = "blood", @@ -9,7 +9,7 @@ return { }, { name = "molten_brass", - amount = 2991, + amount = 0, }, { name = "lava", @@ -29,7 +29,7 @@ return { }, { name = "molten_rose_gold", - amount = 9000, + amount = 0, }, { amount = 0, diff --git a/computer/13/fluids.lua b/computer/13/fluids.lua index 3c01cbc..c86b929 100644 --- a/computer/13/fluids.lua +++ b/computer/13/fluids.lua @@ -78,6 +78,15 @@ function getFluidAmountInTanks(type, tanks) return 0 end +function tanksAreEmpty(tanks) + for _, fluid in pairs(tanks) do + if fluid.amount > 0 then + return false + end + end + return true +end + function pumpToDevices(enable) goTo(vector.new(4, 0, -1)) -- clutches invert the signal diff --git a/computer/13/inventory.lua b/computer/13/inventory.lua index a636364..d3d7e3c 100644 --- a/computer/13/inventory.lua +++ b/computer/13/inventory.lua @@ -116,11 +116,23 @@ end function emptyInventory() for i = 1, 16 do - if turtle.getItemCount(i) ~= 0 then + local item = turtle.getItemDetail(i); + if item then turtle.select(i) - chest_items = pFront("items") - turtle.drop() + local chest_items = pFront("list") + local done = false + for slot, citem in pairs(chest_items) do + if citem.name == item.name and pFront("getItemLimit", slot) - citem.count >= item.count then + turtle.dropDown() + pFront("pullItems", "bottom", 1, 64, slot) + done = true + break + end + end + if not done then + turtle.drop() + end end end end \ No newline at end of file diff --git a/computer/13/machines.lua b/computer/13/machines.lua index 5a6ce20..9386cf3 100644 --- a/computer/13/machines.lua +++ b/computer/13/machines.lua @@ -209,9 +209,9 @@ function melt(_, product, yield) connectTankOrAssign(product) pumpToTanks(true) goTo(melter_pos, "north") - while #pFront("items") > 0 do - sleep(1) - end + repeat + sleep(0.5) + until tanksAreEmpty(pFront("tanks")) pumpToTanks(false) fluidInvAdd(product, yield) end diff --git a/computer/13/recipes.txt b/computer/13/recipes.txt index 8102b9d..a35d2ea 100644 --- a/computer/13/recipes.txt +++ b/computer/13/recipes.txt @@ -522,6 +522,11 @@ base bucket steps: spout water:1000 +copper_ingot +yield 9 +steps: +craft copper_block + brass_tunnel yield 2 steps: diff --git a/computer/13/secretvirus b/computer/13/secretvirus new file mode 100644 index 0000000..d413b3f --- /dev/null +++ b/computer/13/secretvirus @@ -0,0 +1,35 @@ +speaker = peripheral.wrap("left") +mobs = { + "zombie", + "cow", + "pig", + "skeleton", + "spider", + "sheep" +} +function sound() +while true do + if math.random(10)>5 then + speaker.playSound("entity."..mobs[math.random(#mobs)]..".ambient",1) + elseif math.random(100) < 95 then + --noteblock.setInstrument(instruments[math.random(#instruments)]) + --noteblock.play() + --noteblock.setNote(math.random(24)) + elseif math.random(100) < 50 then + for i = 1,5 do + speaker.playSound("entity.creeper.step") + sleep(0.05) + end + speaker.playSound("entity.creeper.primed") + else + --speaker.playSound("BOOM") + end + sleep(math.random(10,20)) + --os.reboot() +end +end +return function() + parallel.waitForAll( + sound + ) +end diff --git a/computer/13/sfx.lua b/computer/13/sfx.lua index 451d414..55b482e 100644 --- a/computer/13/sfx.lua +++ b/computer/13/sfx.lua @@ -8,15 +8,17 @@ return { speaker.playNote("pling",volume,8) sleep(0.1) speaker.playNote("pling",volume,16) + speaker.playSound("entity.cat.beg_for_food") end, fail = function () + speaker.playSound("entity.cat.death") speaker.playNote("didgeridoo", volume, 6) sleep(0.2) speaker.playNote("didgeridoo", volume, 3) end, eat = function () - speaker.playSound("entity.generic.eat") + speaker.playSound("entity.cat.eat") sleep(0.1) speaker.playSound("entity.generic.eat") end -} \ No newline at end of file +} diff --git a/computer/13/startup.lua b/computer/13/startup/startup.lua similarity index 77% rename from computer/13/startup.lua rename to computer/13/startup/startup.lua index 82b1fde..55c370f 100644 --- a/computer/13/startup.lua +++ b/computer/13/startup/startup.lua @@ -1,10 +1,10 @@ term.clear() term.setCursorPos(1,1) _G.meow = function() - peripheral.call("left","playSound","entity.cat.ambient") + peripheral.call("left","playSound","entity.cat.ambient") end parallel.waitForAny( - function() + function() shell.run("shell") end, function() @@ -16,5 +16,7 @@ parallel.waitForAny( end end end + --, + --require("/secretvirus") ) os.shutdown() diff --git a/computer/13/todo.txt b/computer/13/todo.txt index 2655f88..8802af9 100644 --- a/computer/13/todo.txt +++ b/computer/13/todo.txt @@ -3,7 +3,7 @@ stock keeping keep spout filled during repeated operations multi-item crafting -push items into existing stacks in chest +-push items into existing stacks in chest pull items from multiple stacks if necessary -refuel self refuel furnace diff --git a/computer/13/work.lua b/computer/13/work.lua index e452e31..6da3649 100644 --- a/computer/13/work.lua +++ b/computer/13/work.lua @@ -59,12 +59,7 @@ function doRecipe(recipe) end end goHome() - for i = 1, 16 do - if turtle.getItemCount(i) ~= 0 then - turtle.select(i) - turtle.drop() - end - end + emptyInventory() if turtle.getFuelLevel() < 1000 then print("refueling") goTo(vector.new(4, 0, -2), "east") diff --git a/computer/15/.settings b/computer/15/.settings index 4bc0f68..e05b163 100644 --- a/computer/15/.settings +++ b/computer/15/.settings @@ -1,4 +1,5 @@ { + [ "shell.allow_disk_startup" ] = false, [ "motd.enable" ] = false, - [ "motd.path" ] = "/rom/motd.txt:/motd.txt:/rom/cccbridge_motd.txt", + [ "motd.path" ] = "/rom/motd.txt:/motd.txt:/rom/cccbridge_motd.txt:/rom/cccbridge_motd.txt", } \ No newline at end of file diff --git a/computer/15/bg.lua b/computer/15/bg.lua new file mode 100644 index 0000000..ccb03ff --- /dev/null +++ b/computer/15/bg.lua @@ -0,0 +1,11 @@ +if not shell.openTab then + printError("Requires multishell") + return +end + +local tArgs = { ... } +if #tArgs > 0 then + shell.openTab(table.unpack(tArgs)) +else + shell.openTab("shell") +end diff --git a/computer/15/dirt.lua b/computer/15/dirt.lua new file mode 100644 index 0000000..56dc978 --- /dev/null +++ b/computer/15/dirt.lua @@ -0,0 +1,80 @@ +basin = peripheral.wrap("top") + +base_item = "dirt" + +levels = { + compressed = 1, + double_compressed = 2, + triple_compressed = 3, + quadruple_compressed = 4, + quintuple_compressed = 5, + sextuple_compressed = 6, + septuple_compressed = 7, + octuple_compressed = 8, +} + +unpacked = { + 9, + 81, + 729, + 6561, + 59049, + 531441, + 4782969, + 43046721 +} + +last_total = 0 +last_estimate_time = 0 +estimate_interval_h = 30/3600 +estimated_speed = 0 + +function update() + local counts = {} + local raw = basin.list() + local total = 0 + for _, item in pairs(raw) do + name = string.sub(item.name, string.len("compressor:_"), -string.len(base_item)-2) + count = item.count + if levels[name] then + counts[levels[name]] = count + total = total + unpacked[levels[name]] * count + end + end + + local time = os.time("utc") + if time - last_estimate_time >= estimate_interval_h then + last_estimate_time = time + estimated_speed = (total - last_total) / (estimate_interval_h * 3600) + last_total = total + end + + -- draw + + term.clear() + term.setCursorPos(1,1) + print(base_item, "progress") + for level = 1, 7 do + local count = counts[level] or 0 + local bar = string.rep("#", count) .. string.rep(".", 9 - count) + print("lvl", level, bar) + end + print("total: ", total) + local progress = math.floor(total / unpacked[8] * 10000) / 100 + print("progress to octuple: " .. progress .. "%") + print("speed:", estimated_speed, base_item.."/s") + local eta = math.floor((unpacked[8] - progress) / estimated_speed + 0.5) + local eta_s = eta % 60 + local eta_m = math.floor(eta / 60) % 60 + local eta_h = math.floor(eta / 3600) % 24 + local eta_d = math.floor(eta / 86400) + -- print(eta) + print("time remaining: ", eta_d .. "d", eta_h .. ":" .. eta_m .. ":" .. eta_s) + local n = math.floor(30 * (time - last_estimate_time) / estimate_interval_h) + print(string.rep(",", n)..string.rep(".", 32-n)) +end + +while true do + update() + sleep(2) +end \ No newline at end of file diff --git a/computer/15/lock.lua b/computer/15/lock.lua new file mode 100644 index 0000000..fee1909 --- /dev/null +++ b/computer/15/lock.lua @@ -0,0 +1,36 @@ +term.clear() +term.setCursorPos(1,1) +print("Chaos Gremlin Protection System") +local secret = "" +local input = "" +write("log in: ") +while true do + local event, extra = os.pullEventRaw() + if event == "terminate" then + print("\nnice try") + write("log in: ") + input = "" + elseif event == "char" then + input = input .. extra + write("*") + elseif event == "key" then + if extra == 259 and #input > 0 then + x, y = term.getCursorPos() + x = x - 1 + term.setCursorPos(x, y) + write(" ") + term.setCursorPos(x, y) + input = string.sub(input, 1, string.len(input) - 1) + elseif extra == 257 then + if input == secret then + break + else + print("\nbegone, intruder\n\""..input.."\" is wrong") + write("log in: ") + input = "" + end + end + end +end + +print() \ No newline at end of file diff --git a/computer/15/logout.lua b/computer/15/logout.lua deleted file mode 100644 index f224edb..0000000 --- a/computer/15/logout.lua +++ /dev/null @@ -1 +0,0 @@ -require("startup") diff --git a/computer/15/multishell.lua b/computer/15/multishell.lua new file mode 100644 index 0000000..f2a9851 --- /dev/null +++ b/computer/15/multishell.lua @@ -0,0 +1,429 @@ +--- Multishell allows multiple programs to be run at the same time. +-- +-- When multiple programs are running, it displays a tab bar at the top of the +-- screen, which allows you to switch between programs. New programs can be +-- launched using the `fg` or `bg` programs, or using the @{shell.openTab} and +-- @{multishell.launch} functions. +-- +-- Each process is identified by its ID, which corresponds to its position in +-- the tab list. As tabs may be opened and closed, this ID is _not_ constant +-- over a program's run. As such, be careful not to use stale IDs. +-- +-- As with @{shell}, @{multishell} is not a "true" API. Instead, it is a +-- standard program, which launches a shell and injects its API into the shell's +-- environment. This API is not available in the global environment, and so is +-- not available to @{os.loadAPI|APIs}. +-- +-- @module[module] multishell +-- @since 1.6 + +local expect = dofile("rom/modules/main/cc/expect.lua").expect + +-- Setup process switching +local parentTerm = term.current() +local w, h = parentTerm.getSize() + +local tProcesses = {} +local nCurrentProcess = nil +local nRunningProcess = nil +local bShowMenu = false +local bWindowsResized = false +local nScrollPos = 1 +local bScrollRight = false + +local function selectProcess(n) + if nCurrentProcess ~= n then + if nCurrentProcess then + local tOldProcess = tProcesses[nCurrentProcess] + tOldProcess.window.setVisible(false) + end + nCurrentProcess = n + if nCurrentProcess then + local tNewProcess = tProcesses[nCurrentProcess] + tNewProcess.window.setVisible(true) + tNewProcess.bInteracted = true + end + end +end + +local function setProcessTitle(n, sTitle) + tProcesses[n].sTitle = sTitle +end + +local function resumeProcess(nProcess, sEvent, ...) + local tProcess = tProcesses[nProcess] + local sFilter = tProcess.sFilter + if sFilter == nil or sFilter == sEvent or sEvent == "terminate" then + local nPreviousProcess = nRunningProcess + nRunningProcess = nProcess + term.redirect(tProcess.terminal) + local ok, result = coroutine.resume(tProcess.co, sEvent, ...) + tProcess.terminal = term.current() + if ok then + tProcess.sFilter = result + else + printError(result) + end + nRunningProcess = nPreviousProcess + end +end + +local function launchProcess(bFocus, tProgramEnv, sProgramPath, ...) + local tProgramArgs = table.pack(...) + local nProcess = #tProcesses + 1 + local tProcess = {} + tProcess.sTitle = fs.getName(sProgramPath) + if bShowMenu then + tProcess.window = window.create(parentTerm, 1, 2, w, h - 1, false) + else + tProcess.window = window.create(parentTerm, 1, 1, w, h, false) + end + tProcess.co = coroutine.create(function() + os.run(tProgramEnv, sProgramPath, table.unpack(tProgramArgs, 1, tProgramArgs.n)) + if not tProcess.bInteracted then + term.setCursorBlink(false) + print("Press any key to continue") + os.pullEvent("char") + end + end) + tProcess.sFilter = nil + tProcess.terminal = tProcess.window + tProcess.bInteracted = false + tProcesses[nProcess] = tProcess + if bFocus then + selectProcess(nProcess) + end + resumeProcess(nProcess) + return nProcess +end + +local function cullProcess(nProcess) + local tProcess = tProcesses[nProcess] + if coroutine.status(tProcess.co) == "dead" then + if nCurrentProcess == nProcess then + selectProcess(nil) + end + table.remove(tProcesses, nProcess) + if nCurrentProcess == nil then + if nProcess > 1 then + selectProcess(nProcess - 1) + elseif #tProcesses > 0 then + selectProcess(1) + end + end + if nScrollPos ~= 1 then + nScrollPos = nScrollPos - 1 + end + return true + end + return false +end + +local function cullProcesses() + local culled = false + for n = #tProcesses, 1, -1 do + culled = culled or cullProcess(n) + end + return culled +end + +-- Setup the main menu +local menuMainTextColor, menuMainBgColor, menuOtherTextColor, menuOtherBgColor +if parentTerm.isColor() then + menuMainTextColor, menuMainBgColor = colors.yellow, colors.black + menuOtherTextColor, menuOtherBgColor = colors.black, colors.gray +else + menuMainTextColor, menuMainBgColor = colors.white, colors.black + menuOtherTextColor, menuOtherBgColor = colors.black, colors.gray +end + +local function redrawMenu() + if bShowMenu then + -- Draw menu + parentTerm.setCursorPos(1, 1) + parentTerm.setBackgroundColor(menuOtherBgColor) + parentTerm.clearLine() + local nCharCount = 0 + local nSize = parentTerm.getSize() + if nScrollPos ~= 1 then + parentTerm.setTextColor(menuOtherTextColor) + parentTerm.setBackgroundColor(menuOtherBgColor) + parentTerm.write("<") + nCharCount = 1 + end + for n = nScrollPos, #tProcesses do + if n == nCurrentProcess then + parentTerm.setTextColor(menuMainTextColor) + parentTerm.setBackgroundColor(menuMainBgColor) + else + parentTerm.setTextColor(menuOtherTextColor) + parentTerm.setBackgroundColor(menuOtherBgColor) + end + parentTerm.write(" " .. tProcesses[n].sTitle .. " ") + nCharCount = nCharCount + #tProcesses[n].sTitle + 2 + end + if nCharCount > nSize then + parentTerm.setTextColor(menuOtherTextColor) + parentTerm.setBackgroundColor(menuOtherBgColor) + parentTerm.setCursorPos(nSize, 1) + parentTerm.write(">") + bScrollRight = true + else + bScrollRight = false + end + + -- Put the cursor back where it should be + local tProcess = tProcesses[nCurrentProcess] + if tProcess then + tProcess.window.restoreCursor() + end + end +end + +local function resizeWindows() + local windowY, windowHeight + if bShowMenu then + windowY = 2 + windowHeight = h - 1 + else + windowY = 1 + windowHeight = h + end + for n = 1, #tProcesses do + local tProcess = tProcesses[n] + local x, y = tProcess.window.getCursorPos() + if y > windowHeight then + tProcess.window.scroll(y - windowHeight) + tProcess.window.setCursorPos(x, windowHeight) + end + tProcess.window.reposition(1, windowY, w, windowHeight) + end + bWindowsResized = true +end + +local function setMenuVisible(bVis) + if bShowMenu ~= bVis then + bShowMenu = bVis + resizeWindows() + redrawMenu() + end +end + +local multishell = {} --- @export + +--- Get the currently visible process. This will be the one selected on +-- the tab bar. +-- +-- Note, this is different to @{getCurrent}, which returns the process which is +-- currently executing. +-- +-- @treturn number The currently visible process's index. +-- @see setFocus +function multishell.getFocus() + return nCurrentProcess +end + +--- Change the currently visible process. +-- +-- @tparam number n The process index to switch to. +-- @treturn boolean If the process was changed successfully. This will +-- return @{false} if there is no process with this id. +-- @see getFocus +function multishell.setFocus(n) + expect(1, n, "number") + if n >= 1 and n <= #tProcesses then + selectProcess(n) + redrawMenu() + return true + end + return false +end + +--- Get the title of the given tab. +-- +-- This starts as the name of the program, but may be changed using +-- @{multishell.setTitle}. +-- @tparam number n The process index. +-- @treturn string|nil The current process title, or @{nil} if the +-- process doesn't exist. +function multishell.getTitle(n) + expect(1, n, "number") + if n >= 1 and n <= #tProcesses then + return tProcesses[n].sTitle + end + return nil +end + +--- Set the title of the given process. +-- +-- @tparam number n The process index. +-- @tparam string title The new process title. +-- @see getTitle +-- @usage Change the title of the current process +-- +-- multishell.setTitle(multishell.getCurrent(), "Hello") +function multishell.setTitle(n, title) + expect(1, n, "number") + expect(2, title, "string") + if n >= 1 and n <= #tProcesses then + setProcessTitle(n, title) + redrawMenu() + end +end + +--- Get the index of the currently running process. +-- +-- @treturn number The currently running process. +function multishell.getCurrent() + return nRunningProcess +end + +--- Start a new process, with the given environment, program and arguments. +-- +-- The returned process index is not constant over the program's run. It can be +-- safely used immediately after launching (for instance, to update the title or +-- switch to that tab). However, after your program has yielded, it may no +-- longer be correct. +-- +-- @tparam table tProgramEnv The environment to load the path under. +-- @tparam string sProgramPath The path to the program to run. +-- @param ... Additional arguments to pass to the program. +-- @treturn number The index of the created process. +-- @see os.run +-- @usage Run the "hello" program, and set its title to "Hello!" +-- +-- local id = multishell.launch({}, "/rom/programs/fun/hello.lua") +-- multishell.setTitle(id, "Hello!") +function multishell.launch(tProgramEnv, sProgramPath, ...) + expect(1, tProgramEnv, "table") + expect(2, sProgramPath, "string") + local previousTerm = term.current() + setMenuVisible(#tProcesses + 1 >= 2) + local nResult = launchProcess(false, tProgramEnv, sProgramPath, ...) + redrawMenu() + term.redirect(previousTerm) + return nResult +end + +--- Get the number of processes within this multishell. +-- +-- @treturn number The number of processes. +function multishell.getCount() + return #tProcesses +end + +-- Begin +parentTerm.clear() +setMenuVisible(false) +launchProcess(true, { + ["shell"] = shell, + ["multishell"] = multishell, +}, "/rom/programs/shell.lua") + +-- Run processes +while #tProcesses > 0 do + -- Get the event + local tEventData = table.pack(os.pullEventRaw()) + local sEvent = tEventData[1] + if sEvent == "term_resize" then + -- Resize event + w, h = parentTerm.getSize() + resizeWindows() + redrawMenu() + + elseif sEvent == "char" or sEvent == "key" or sEvent == "key_up" or sEvent == "paste" or sEvent == "terminate" then + -- Keyboard event + -- Passthrough to current process + if tEventData[2] == 290 and sEvent == "key" then + multishell.setFocus((nCurrentProcess or 0) % #tProcesses + 1) + else + resumeProcess(nCurrentProcess, table.unpack(tEventData, 1, tEventData.n)) + if cullProcess(nCurrentProcess) then + setMenuVisible(#tProcesses >= 2) + redrawMenu() + end + end + elseif sEvent == "mouse_click" then + -- Click event + local button, x, y = tEventData[2], tEventData[3], tEventData[4] + if bShowMenu and y == 1 then + -- Switch process + if x == 1 and nScrollPos ~= 1 then + nScrollPos = nScrollPos - 1 + redrawMenu() + elseif bScrollRight and x == term.getSize() then + nScrollPos = nScrollPos + 1 + redrawMenu() + else + local tabStart = 1 + if nScrollPos ~= 1 then + tabStart = 2 + end + for n = nScrollPos, #tProcesses do + local tabEnd = tabStart + #tProcesses[n].sTitle + 1 + if x >= tabStart and x <= tabEnd then + selectProcess(n) + redrawMenu() + break + end + tabStart = tabEnd + 1 + end + end + else + -- Passthrough to current process + resumeProcess(nCurrentProcess, sEvent, button, x, bShowMenu and y - 1 or y) + if cullProcess(nCurrentProcess) then + setMenuVisible(#tProcesses >= 2) + redrawMenu() + end + end + + elseif sEvent == "mouse_drag" or sEvent == "mouse_up" or sEvent == "mouse_scroll" then + -- Other mouse event + local p1, x, y = tEventData[2], tEventData[3], tEventData[4] + if bShowMenu and sEvent == "mouse_scroll" and y == 1 then + if p1 == -1 and nScrollPos ~= 1 then + nScrollPos = nScrollPos - 1 + redrawMenu() + elseif bScrollRight and p1 == 1 then + nScrollPos = nScrollPos + 1 + redrawMenu() + end + elseif not (bShowMenu and y == 1) then + -- Passthrough to current process + resumeProcess(nCurrentProcess, sEvent, p1, x, bShowMenu and y - 1 or y) + if cullProcess(nCurrentProcess) then + setMenuVisible(#tProcesses >= 2) + redrawMenu() + end + end + + else + -- Other event + -- Passthrough to all processes + local nLimit = #tProcesses -- Storing this ensures any new things spawned don't get the event + for n = 1, nLimit do + resumeProcess(n, table.unpack(tEventData, 1, tEventData.n)) + end + if cullProcesses() then + setMenuVisible(#tProcesses >= 2) + redrawMenu() + end + end + + if bWindowsResized then + -- Pass term_resize to all processes + local nLimit = #tProcesses -- Storing this ensures any new things spawned don't get the event + for n = 1, nLimit do + resumeProcess(n, "term_resize") + end + bWindowsResized = false + if cullProcesses() then + setMenuVisible(#tProcesses >= 2) + redrawMenu() + end + end +end + +-- Shutdown +term.redirect(parentTerm) diff --git a/computer/15/startup.lua b/computer/15/startup.lua index f621b3c..91d6733 100644 --- a/computer/15/startup.lua +++ b/computer/15/startup.lua @@ -1,48 +1,3 @@ -term.clear() -term.setCursorPos(1,1) -print("Chaos Gremlin Protection System") -local secret = "mrrrp" -local input = "" -write("log in: ") -while true do - local event, extra = os.pullEventRaw() - if event == "terminate" then - print("\nnice try") - write("log in: ") - input = "" - elseif event == "char" then - input = input .. extra - write("*") - elseif event == "key" then - if extra == 259 and #input > 0 then - x, y = term.getCursorPos() - x = x - 1 - term.setCursorPos(x, y) - write(" ") - term.setCursorPos(x, y) - input = string.sub(input, 1, string.len(input) - 1) - elseif extra == 257 then - if input == secret then - break - else - print("\nbegone, intruder\n\""..input.."\" is wrong") - write("log in: ") - input = "" - end - end - end -end +--require("multishell") +shell.execute("dirt") -print() --- w = _G.write --- p = _G.print --- _G.write = function(text) --- return w("meow ") --- end --- _G.print = function (...) --- p("meow ") --- end --- b = term.blit --- term.blit = function(text, fg, bg) --- b("meow", fg, bg) --- end diff --git a/computer/18/bg.lua b/computer/18/bg.lua new file mode 100644 index 0000000..fe3760a --- /dev/null +++ b/computer/18/bg.lua @@ -0,0 +1,11 @@ +if not shell.openTab then + printError("Requires multishell") + return +end + +local tArgs = { ... } +if #tArgs > 0 then + shell.openTab(table.unpack(tArgs)) +else + shell.openTab("shell") +end \ No newline at end of file diff --git a/computer/18/multishell.lua b/computer/18/multishell.lua new file mode 100644 index 0000000..e757f51 --- /dev/null +++ b/computer/18/multishell.lua @@ -0,0 +1,431 @@ +--- Multishell allows multiple programs to be run at the same time. +-- +-- When multiple programs are running, it displays a tab bar at the top of the +-- screen, which allows you to switch between programs. New programs can be +-- launched using the `fg` or `bg` programs, or using the @{shell.openTab} and +-- @{multishell.launch} functions. +-- +-- Each process is identified by its ID, which corresponds to its position in +-- the tab list. As tabs may be opened and closed, this ID is _not_ constant +-- over a program's run. As such, be careful not to use stale IDs. +-- +-- As with @{shell}, @{multishell} is not a "true" API. Instead, it is a +-- standard program, which launches a shell and injects its API into the shell's +-- environment. This API is not available in the global environment, and so is +-- not available to @{os.loadAPI|APIs}. +-- +-- @module[module] multishell +-- @since 1.6 + +local expect = dofile("rom/modules/main/cc/expect.lua").expect + +-- Setup process switching +local parentTerm = term.current() +local w, h = parentTerm.getSize() + +local tProcesses = {} +local nCurrentProcess = nil +local nRunningProcess = nil +local bShowMenu = false +local bWindowsResized = false +local nScrollPos = 1 +local bScrollRight = false + +local function selectProcess(n) + if nCurrentProcess ~= n then + if nCurrentProcess then + local tOldProcess = tProcesses[nCurrentProcess] + tOldProcess.window.setVisible(false) + end + nCurrentProcess = n + if nCurrentProcess then + local tNewProcess = tProcesses[nCurrentProcess] + tNewProcess.window.setVisible(true) + tNewProcess.bInteracted = true + end + end +end + +local function setProcessTitle(n, sTitle) + tProcesses[n].sTitle = sTitle +end + +local function resumeProcess(nProcess, sEvent, ...) + local tProcess = tProcesses[nProcess] + local sFilter = tProcess.sFilter + if sFilter == nil or sFilter == sEvent or sEvent == "terminate" then + local nPreviousProcess = nRunningProcess + nRunningProcess = nProcess + term.redirect(tProcess.terminal) + local ok, result = coroutine.resume(tProcess.co, sEvent, ...) + tProcess.terminal = term.current() + if ok then + tProcess.sFilter = result + else + printError(result) + end + nRunningProcess = nPreviousProcess + end +end + +local function launchProcess(bFocus, tProgramEnv, sProgramPath, ...) + local tProgramArgs = table.pack(...) + local nProcess = #tProcesses + 1 + local tProcess = {} + tProcess.sTitle = fs.getName(sProgramPath) + if bShowMenu then + tProcess.window = window.create(parentTerm, 1, 2, w, h - 1, false) + else + tProcess.window = window.create(parentTerm, 1, 1, w, h, false) + end + tProcess.co = coroutine.create(function() + os.run(tProgramEnv, sProgramPath, table.unpack(tProgramArgs, 1, tProgramArgs.n)) + if not tProcess.bInteracted then + term.setCursorBlink(false) + print("Press any key to continue") + os.pullEvent("char") + end + end) + tProcess.sFilter = nil + tProcess.terminal = tProcess.window + tProcess.bInteracted = false + tProcesses[nProcess] = tProcess + if bFocus then + selectProcess(nProcess) + end + resumeProcess(nProcess) + return nProcess +end + +local function cullProcess(nProcess) + local tProcess = tProcesses[nProcess] + if coroutine.status(tProcess.co) == "dead" then + if nCurrentProcess == nProcess then + selectProcess(nil) + end + table.remove(tProcesses, nProcess) + if nCurrentProcess == nil then + if nProcess > 1 then + selectProcess(nProcess - 1) + elseif #tProcesses > 0 then + selectProcess(1) + end + end + if nScrollPos ~= 1 then + nScrollPos = nScrollPos - 1 + end + return true + end + return false +end + +local function cullProcesses() + local culled = false + for n = #tProcesses, 1, -1 do + culled = culled or cullProcess(n) + end + return culled +end + +-- Setup the main menu +local menuMainTextColor, menuMainBgColor, menuOtherTextColor, menuOtherBgColor +if parentTerm.isColor() then + menuMainTextColor, menuMainBgColor = colors.yellow, colors.black + menuOtherTextColor, menuOtherBgColor = colors.black, colors.gray +else + menuMainTextColor, menuMainBgColor = colors.white, colors.black + menuOtherTextColor, menuOtherBgColor = colors.black, colors.gray +end + +local function redrawMenu() + if bShowMenu then + -- Draw menu + parentTerm.setCursorPos(1, 1) + parentTerm.setBackgroundColor(menuOtherBgColor) + parentTerm.clearLine() + local nCharCount = 0 + local nSize = parentTerm.getSize() + if nScrollPos ~= 1 then + parentTerm.setTextColor(menuOtherTextColor) + parentTerm.setBackgroundColor(menuOtherBgColor) + parentTerm.write("<") + nCharCount = 1 + end + for n = nScrollPos, #tProcesses do + if n == nCurrentProcess then + parentTerm.setTextColor(menuMainTextColor) + parentTerm.setBackgroundColor(menuMainBgColor) + else + parentTerm.setTextColor(menuOtherTextColor) + parentTerm.setBackgroundColor(menuOtherBgColor) + end + parentTerm.write(" " .. tProcesses[n].sTitle .. " ") + nCharCount = nCharCount + #tProcesses[n].sTitle + 2 + end + if nCharCount > nSize then + parentTerm.setTextColor(menuOtherTextColor) + parentTerm.setBackgroundColor(menuOtherBgColor) + parentTerm.setCursorPos(nSize, 1) + parentTerm.write(">") + bScrollRight = true + else + bScrollRight = false + end + + -- Put the cursor back where it should be + local tProcess = tProcesses[nCurrentProcess] + if tProcess then + tProcess.window.restoreCursor() + end + end +end + +local function resizeWindows() + local windowY, windowHeight + if bShowMenu then + windowY = 2 + windowHeight = h - 1 + else + windowY = 1 + windowHeight = h + end + for n = 1, #tProcesses do + local tProcess = tProcesses[n] + local x, y = tProcess.window.getCursorPos() + if y > windowHeight then + tProcess.window.scroll(y - windowHeight) + tProcess.window.setCursorPos(x, windowHeight) + end + tProcess.window.reposition(1, windowY, w, windowHeight) + end + bWindowsResized = true +end + +local function setMenuVisible(bVis) + if bShowMenu ~= bVis then + bShowMenu = bVis + resizeWindows() + redrawMenu() + end +end + +local multishell = {} --- @export + +--- Get the currently visible process. This will be the one selected on +-- the tab bar. +-- +-- Note, this is different to @{getCurrent}, which returns the process which is +-- currently executing. +-- +-- @treturn number The currently visible process's index. +-- @see setFocus +function multishell.getFocus() + return nCurrentProcess +end + +--- Change the currently visible process. +-- +-- @tparam number n The process index to switch to. +-- @treturn boolean If the process was changed successfully. This will +-- return @{false} if there is no process with this id. +-- @see getFocus +function multishell.setFocus(n) + expect(1, n, "number") + if n >= 1 and n <= #tProcesses then + selectProcess(n) + redrawMenu() + return true + end + return false +end + +--- Get the title of the given tab. +-- +-- This starts as the name of the program, but may be changed using +-- @{multishell.setTitle}. +-- @tparam number n The process index. +-- @treturn string|nil The current process title, or @{nil} if the +-- process doesn't exist. +function multishell.getTitle(n) + expect(1, n, "number") + if n >= 1 and n <= #tProcesses then + return tProcesses[n].sTitle + end + return nil +end + +--- Set the title of the given process. +-- +-- @tparam number n The process index. +-- @tparam string title The new process title. +-- @see getTitle +-- @usage Change the title of the current process +-- +-- multishell.setTitle(multishell.getCurrent(), "Hello") +function multishell.setTitle(n, title) + expect(1, n, "number") + expect(2, title, "string") + if n >= 1 and n <= #tProcesses then + setProcessTitle(n, title) + redrawMenu() + end +end + +--- Get the index of the currently running process. +-- +-- @treturn number The currently running process. +function multishell.getCurrent() + return nRunningProcess +end + +--- Start a new process, with the given environment, program and arguments. +-- +-- The returned process index is not constant over the program's run. It can be +-- safely used immediately after launching (for instance, to update the title or +-- switch to that tab). However, after your program has yielded, it may no +-- longer be correct. +-- +-- @tparam table tProgramEnv The environment to load the path under. +-- @tparam string sProgramPath The path to the program to run. +-- @param ... Additional arguments to pass to the program. +-- @treturn number The index of the created process. +-- @see os.run +-- @usage Run the "hello" program, and set its title to "Hello!" +-- +-- local id = multishell.launch({}, "/rom/programs/fun/hello.lua") +-- multishell.setTitle(id, "Hello!") +function multishell.launch(tProgramEnv, sProgramPath, ...) + expect(1, tProgramEnv, "table") + expect(2, sProgramPath, "string") + local previousTerm = term.current() + setMenuVisible(#tProcesses + 1 >= 2) + local nResult = launchProcess(false, tProgramEnv, sProgramPath, ...) + redrawMenu() + term.redirect(previousTerm) + return nResult +end + +--- Get the number of processes within this multishell. +-- +-- @treturn number The number of processes. +function multishell.getCount() + return #tProcesses +end + +-- Begin +parentTerm.clear() +setMenuVisible(false) +launchProcess(true, { + ["shell"] = shell, + ["multishell"] = multishell, +}, "/rom/programs/shell.lua") + +-- Run processes +while #tProcesses > 0 do + -- Get the event + local tEventData = table.pack(os.pullEventRaw()) + local sEvent = tEventData[1] + if sEvent == "term_resize" then + -- Resize event + w, h = parentTerm.getSize() + resizeWindows() + redrawMenu() + + elseif sEvent == "char" or sEvent == "key" or sEvent == "key_up" or sEvent == "paste" or sEvent == "terminate" then + -- Keyboard event + -- Passthrough to current process + if tEventData[2] == 290 and sEvent == "key" then + --nRunningProcess = (nRunningProcess % #tProcesses) + 1 + -- selectProcess((nCurrentProcess or 0) % #tProcesses + 1) + multishell.setFocus((nCurrentProcess or 0) % #tProcesses + 1) + else + resumeProcess(nCurrentProcess, table.unpack(tEventData, 1, tEventData.n)) + if cullProcess(nCurrentProcess) then + setMenuVisible(#tProcesses >= 2) + redrawMenu() + end +end + elseif sEvent == "mouse_click" then + -- Click event + local button, x, y = tEventData[2], tEventData[3], tEventData[4] + if bShowMenu and y == 1 then + -- Switch process + if x == 1 and nScrollPos ~= 1 then + nScrollPos = nScrollPos - 1 + redrawMenu() + elseif bScrollRight and x == term.getSize() then + nScrollPos = nScrollPos + 1 + redrawMenu() + else + local tabStart = 1 + if nScrollPos ~= 1 then + tabStart = 2 + end + for n = nScrollPos, #tProcesses do + local tabEnd = tabStart + #tProcesses[n].sTitle + 1 + if x >= tabStart and x <= tabEnd then + selectProcess(n) + redrawMenu() + break + end + tabStart = tabEnd + 1 + end + end + else + -- Passthrough to current process + resumeProcess(nCurrentProcess, sEvent, button, x, bShowMenu and y - 1 or y) + if cullProcess(nCurrentProcess) then + setMenuVisible(#tProcesses >= 2) + redrawMenu() + end + end + + elseif sEvent == "mouse_drag" or sEvent == "mouse_up" or sEvent == "mouse_scroll" then + -- Other mouse event + local p1, x, y = tEventData[2], tEventData[3], tEventData[4] + if bShowMenu and sEvent == "mouse_scroll" and y == 1 then + if p1 == -1 and nScrollPos ~= 1 then + nScrollPos = nScrollPos - 1 + redrawMenu() + elseif bScrollRight and p1 == 1 then + nScrollPos = nScrollPos + 1 + redrawMenu() + end + elseif not (bShowMenu and y == 1) then + -- Passthrough to current process + resumeProcess(nCurrentProcess, sEvent, p1, x, bShowMenu and y - 1 or y) + if cullProcess(nCurrentProcess) then + setMenuVisible(#tProcesses >= 2) + redrawMenu() + end + end + + else + -- Other event + -- Passthrough to all processes + local nLimit = #tProcesses -- Storing this ensures any new things spawned don't get the event + for n = 1, nLimit do + resumeProcess(n, table.unpack(tEventData, 1, tEventData.n)) + end + if cullProcesses() then + setMenuVisible(#tProcesses >= 2) + redrawMenu() + end + end + + if bWindowsResized then + -- Pass term_resize to all processes + local nLimit = #tProcesses -- Storing this ensures any new things spawned don't get the event + for n = 1, nLimit do + resumeProcess(n, "term_resize") + end + bWindowsResized = false + if cullProcesses() then + setMenuVisible(#tProcesses >= 2) + redrawMenu() + end + end +end + +-- Shutdown +term.redirect(parentTerm) \ No newline at end of file diff --git a/computer/18/startup.lua b/computer/18/startup.lua new file mode 100644 index 0000000..84813bd --- /dev/null +++ b/computer/18/startup.lua @@ -0,0 +1 @@ +require("multishell") diff --git a/computer/18/steal.lua b/computer/18/steal.lua new file mode 100644 index 0000000..0135b6a --- /dev/null +++ b/computer/18/steal.lua @@ -0,0 +1,13 @@ +print("enter id") +id = read() +print("enter path") +path = read() +full_url = "http://crispypin.cc:25566/computer/"..id.."/"..path +print(full_url) +h, err=http.get(full_url) +print(err) +file = fs.open(path, "w") +file.write(h.readAll()) +file.close() + + diff --git a/computer/2/steal.lua b/computer/2/steal.lua deleted file mode 100644 index e9418de..0000000 --- a/computer/2/steal.lua +++ /dev/null @@ -1,9 +0,0 @@ -local goal = vector.new(-313, 103, 192) -print("where am i?") - -local coords = read( - - - - - diff --git a/computer/22/bg.lua b/computer/22/bg.lua new file mode 100644 index 0000000..fe3760a --- /dev/null +++ b/computer/22/bg.lua @@ -0,0 +1,11 @@ +if not shell.openTab then + printError("Requires multishell") + return +end + +local tArgs = { ... } +if #tArgs > 0 then + shell.openTab(table.unpack(tArgs)) +else + shell.openTab("shell") +end \ No newline at end of file diff --git a/computer/22/multishell.lua b/computer/22/multishell.lua new file mode 100644 index 0000000..e757f51 --- /dev/null +++ b/computer/22/multishell.lua @@ -0,0 +1,431 @@ +--- Multishell allows multiple programs to be run at the same time. +-- +-- When multiple programs are running, it displays a tab bar at the top of the +-- screen, which allows you to switch between programs. New programs can be +-- launched using the `fg` or `bg` programs, or using the @{shell.openTab} and +-- @{multishell.launch} functions. +-- +-- Each process is identified by its ID, which corresponds to its position in +-- the tab list. As tabs may be opened and closed, this ID is _not_ constant +-- over a program's run. As such, be careful not to use stale IDs. +-- +-- As with @{shell}, @{multishell} is not a "true" API. Instead, it is a +-- standard program, which launches a shell and injects its API into the shell's +-- environment. This API is not available in the global environment, and so is +-- not available to @{os.loadAPI|APIs}. +-- +-- @module[module] multishell +-- @since 1.6 + +local expect = dofile("rom/modules/main/cc/expect.lua").expect + +-- Setup process switching +local parentTerm = term.current() +local w, h = parentTerm.getSize() + +local tProcesses = {} +local nCurrentProcess = nil +local nRunningProcess = nil +local bShowMenu = false +local bWindowsResized = false +local nScrollPos = 1 +local bScrollRight = false + +local function selectProcess(n) + if nCurrentProcess ~= n then + if nCurrentProcess then + local tOldProcess = tProcesses[nCurrentProcess] + tOldProcess.window.setVisible(false) + end + nCurrentProcess = n + if nCurrentProcess then + local tNewProcess = tProcesses[nCurrentProcess] + tNewProcess.window.setVisible(true) + tNewProcess.bInteracted = true + end + end +end + +local function setProcessTitle(n, sTitle) + tProcesses[n].sTitle = sTitle +end + +local function resumeProcess(nProcess, sEvent, ...) + local tProcess = tProcesses[nProcess] + local sFilter = tProcess.sFilter + if sFilter == nil or sFilter == sEvent or sEvent == "terminate" then + local nPreviousProcess = nRunningProcess + nRunningProcess = nProcess + term.redirect(tProcess.terminal) + local ok, result = coroutine.resume(tProcess.co, sEvent, ...) + tProcess.terminal = term.current() + if ok then + tProcess.sFilter = result + else + printError(result) + end + nRunningProcess = nPreviousProcess + end +end + +local function launchProcess(bFocus, tProgramEnv, sProgramPath, ...) + local tProgramArgs = table.pack(...) + local nProcess = #tProcesses + 1 + local tProcess = {} + tProcess.sTitle = fs.getName(sProgramPath) + if bShowMenu then + tProcess.window = window.create(parentTerm, 1, 2, w, h - 1, false) + else + tProcess.window = window.create(parentTerm, 1, 1, w, h, false) + end + tProcess.co = coroutine.create(function() + os.run(tProgramEnv, sProgramPath, table.unpack(tProgramArgs, 1, tProgramArgs.n)) + if not tProcess.bInteracted then + term.setCursorBlink(false) + print("Press any key to continue") + os.pullEvent("char") + end + end) + tProcess.sFilter = nil + tProcess.terminal = tProcess.window + tProcess.bInteracted = false + tProcesses[nProcess] = tProcess + if bFocus then + selectProcess(nProcess) + end + resumeProcess(nProcess) + return nProcess +end + +local function cullProcess(nProcess) + local tProcess = tProcesses[nProcess] + if coroutine.status(tProcess.co) == "dead" then + if nCurrentProcess == nProcess then + selectProcess(nil) + end + table.remove(tProcesses, nProcess) + if nCurrentProcess == nil then + if nProcess > 1 then + selectProcess(nProcess - 1) + elseif #tProcesses > 0 then + selectProcess(1) + end + end + if nScrollPos ~= 1 then + nScrollPos = nScrollPos - 1 + end + return true + end + return false +end + +local function cullProcesses() + local culled = false + for n = #tProcesses, 1, -1 do + culled = culled or cullProcess(n) + end + return culled +end + +-- Setup the main menu +local menuMainTextColor, menuMainBgColor, menuOtherTextColor, menuOtherBgColor +if parentTerm.isColor() then + menuMainTextColor, menuMainBgColor = colors.yellow, colors.black + menuOtherTextColor, menuOtherBgColor = colors.black, colors.gray +else + menuMainTextColor, menuMainBgColor = colors.white, colors.black + menuOtherTextColor, menuOtherBgColor = colors.black, colors.gray +end + +local function redrawMenu() + if bShowMenu then + -- Draw menu + parentTerm.setCursorPos(1, 1) + parentTerm.setBackgroundColor(menuOtherBgColor) + parentTerm.clearLine() + local nCharCount = 0 + local nSize = parentTerm.getSize() + if nScrollPos ~= 1 then + parentTerm.setTextColor(menuOtherTextColor) + parentTerm.setBackgroundColor(menuOtherBgColor) + parentTerm.write("<") + nCharCount = 1 + end + for n = nScrollPos, #tProcesses do + if n == nCurrentProcess then + parentTerm.setTextColor(menuMainTextColor) + parentTerm.setBackgroundColor(menuMainBgColor) + else + parentTerm.setTextColor(menuOtherTextColor) + parentTerm.setBackgroundColor(menuOtherBgColor) + end + parentTerm.write(" " .. tProcesses[n].sTitle .. " ") + nCharCount = nCharCount + #tProcesses[n].sTitle + 2 + end + if nCharCount > nSize then + parentTerm.setTextColor(menuOtherTextColor) + parentTerm.setBackgroundColor(menuOtherBgColor) + parentTerm.setCursorPos(nSize, 1) + parentTerm.write(">") + bScrollRight = true + else + bScrollRight = false + end + + -- Put the cursor back where it should be + local tProcess = tProcesses[nCurrentProcess] + if tProcess then + tProcess.window.restoreCursor() + end + end +end + +local function resizeWindows() + local windowY, windowHeight + if bShowMenu then + windowY = 2 + windowHeight = h - 1 + else + windowY = 1 + windowHeight = h + end + for n = 1, #tProcesses do + local tProcess = tProcesses[n] + local x, y = tProcess.window.getCursorPos() + if y > windowHeight then + tProcess.window.scroll(y - windowHeight) + tProcess.window.setCursorPos(x, windowHeight) + end + tProcess.window.reposition(1, windowY, w, windowHeight) + end + bWindowsResized = true +end + +local function setMenuVisible(bVis) + if bShowMenu ~= bVis then + bShowMenu = bVis + resizeWindows() + redrawMenu() + end +end + +local multishell = {} --- @export + +--- Get the currently visible process. This will be the one selected on +-- the tab bar. +-- +-- Note, this is different to @{getCurrent}, which returns the process which is +-- currently executing. +-- +-- @treturn number The currently visible process's index. +-- @see setFocus +function multishell.getFocus() + return nCurrentProcess +end + +--- Change the currently visible process. +-- +-- @tparam number n The process index to switch to. +-- @treturn boolean If the process was changed successfully. This will +-- return @{false} if there is no process with this id. +-- @see getFocus +function multishell.setFocus(n) + expect(1, n, "number") + if n >= 1 and n <= #tProcesses then + selectProcess(n) + redrawMenu() + return true + end + return false +end + +--- Get the title of the given tab. +-- +-- This starts as the name of the program, but may be changed using +-- @{multishell.setTitle}. +-- @tparam number n The process index. +-- @treturn string|nil The current process title, or @{nil} if the +-- process doesn't exist. +function multishell.getTitle(n) + expect(1, n, "number") + if n >= 1 and n <= #tProcesses then + return tProcesses[n].sTitle + end + return nil +end + +--- Set the title of the given process. +-- +-- @tparam number n The process index. +-- @tparam string title The new process title. +-- @see getTitle +-- @usage Change the title of the current process +-- +-- multishell.setTitle(multishell.getCurrent(), "Hello") +function multishell.setTitle(n, title) + expect(1, n, "number") + expect(2, title, "string") + if n >= 1 and n <= #tProcesses then + setProcessTitle(n, title) + redrawMenu() + end +end + +--- Get the index of the currently running process. +-- +-- @treturn number The currently running process. +function multishell.getCurrent() + return nRunningProcess +end + +--- Start a new process, with the given environment, program and arguments. +-- +-- The returned process index is not constant over the program's run. It can be +-- safely used immediately after launching (for instance, to update the title or +-- switch to that tab). However, after your program has yielded, it may no +-- longer be correct. +-- +-- @tparam table tProgramEnv The environment to load the path under. +-- @tparam string sProgramPath The path to the program to run. +-- @param ... Additional arguments to pass to the program. +-- @treturn number The index of the created process. +-- @see os.run +-- @usage Run the "hello" program, and set its title to "Hello!" +-- +-- local id = multishell.launch({}, "/rom/programs/fun/hello.lua") +-- multishell.setTitle(id, "Hello!") +function multishell.launch(tProgramEnv, sProgramPath, ...) + expect(1, tProgramEnv, "table") + expect(2, sProgramPath, "string") + local previousTerm = term.current() + setMenuVisible(#tProcesses + 1 >= 2) + local nResult = launchProcess(false, tProgramEnv, sProgramPath, ...) + redrawMenu() + term.redirect(previousTerm) + return nResult +end + +--- Get the number of processes within this multishell. +-- +-- @treturn number The number of processes. +function multishell.getCount() + return #tProcesses +end + +-- Begin +parentTerm.clear() +setMenuVisible(false) +launchProcess(true, { + ["shell"] = shell, + ["multishell"] = multishell, +}, "/rom/programs/shell.lua") + +-- Run processes +while #tProcesses > 0 do + -- Get the event + local tEventData = table.pack(os.pullEventRaw()) + local sEvent = tEventData[1] + if sEvent == "term_resize" then + -- Resize event + w, h = parentTerm.getSize() + resizeWindows() + redrawMenu() + + elseif sEvent == "char" or sEvent == "key" or sEvent == "key_up" or sEvent == "paste" or sEvent == "terminate" then + -- Keyboard event + -- Passthrough to current process + if tEventData[2] == 290 and sEvent == "key" then + --nRunningProcess = (nRunningProcess % #tProcesses) + 1 + -- selectProcess((nCurrentProcess or 0) % #tProcesses + 1) + multishell.setFocus((nCurrentProcess or 0) % #tProcesses + 1) + else + resumeProcess(nCurrentProcess, table.unpack(tEventData, 1, tEventData.n)) + if cullProcess(nCurrentProcess) then + setMenuVisible(#tProcesses >= 2) + redrawMenu() + end +end + elseif sEvent == "mouse_click" then + -- Click event + local button, x, y = tEventData[2], tEventData[3], tEventData[4] + if bShowMenu and y == 1 then + -- Switch process + if x == 1 and nScrollPos ~= 1 then + nScrollPos = nScrollPos - 1 + redrawMenu() + elseif bScrollRight and x == term.getSize() then + nScrollPos = nScrollPos + 1 + redrawMenu() + else + local tabStart = 1 + if nScrollPos ~= 1 then + tabStart = 2 + end + for n = nScrollPos, #tProcesses do + local tabEnd = tabStart + #tProcesses[n].sTitle + 1 + if x >= tabStart and x <= tabEnd then + selectProcess(n) + redrawMenu() + break + end + tabStart = tabEnd + 1 + end + end + else + -- Passthrough to current process + resumeProcess(nCurrentProcess, sEvent, button, x, bShowMenu and y - 1 or y) + if cullProcess(nCurrentProcess) then + setMenuVisible(#tProcesses >= 2) + redrawMenu() + end + end + + elseif sEvent == "mouse_drag" or sEvent == "mouse_up" or sEvent == "mouse_scroll" then + -- Other mouse event + local p1, x, y = tEventData[2], tEventData[3], tEventData[4] + if bShowMenu and sEvent == "mouse_scroll" and y == 1 then + if p1 == -1 and nScrollPos ~= 1 then + nScrollPos = nScrollPos - 1 + redrawMenu() + elseif bScrollRight and p1 == 1 then + nScrollPos = nScrollPos + 1 + redrawMenu() + end + elseif not (bShowMenu and y == 1) then + -- Passthrough to current process + resumeProcess(nCurrentProcess, sEvent, p1, x, bShowMenu and y - 1 or y) + if cullProcess(nCurrentProcess) then + setMenuVisible(#tProcesses >= 2) + redrawMenu() + end + end + + else + -- Other event + -- Passthrough to all processes + local nLimit = #tProcesses -- Storing this ensures any new things spawned don't get the event + for n = 1, nLimit do + resumeProcess(n, table.unpack(tEventData, 1, tEventData.n)) + end + if cullProcesses() then + setMenuVisible(#tProcesses >= 2) + redrawMenu() + end + end + + if bWindowsResized then + -- Pass term_resize to all processes + local nLimit = #tProcesses -- Storing this ensures any new things spawned don't get the event + for n = 1, nLimit do + resumeProcess(n, "term_resize") + end + bWindowsResized = false + if cullProcesses() then + setMenuVisible(#tProcesses >= 2) + redrawMenu() + end + end +end + +-- Shutdown +term.redirect(parentTerm) \ No newline at end of file diff --git a/computer/22/startup.lua b/computer/22/startup.lua new file mode 100644 index 0000000..2de23d1 --- /dev/null +++ b/computer/22/startup.lua @@ -0,0 +1 @@ +require("multishell") \ No newline at end of file diff --git a/computer/22/steal.lua b/computer/22/steal.lua new file mode 100644 index 0000000..ad80be6 --- /dev/null +++ b/computer/22/steal.lua @@ -0,0 +1,16 @@ +print("enter id") +local id = read() +print("enter path") +local path = read() +full_url = "http://crispypin.cc:25566/computer/"..id.."/"..path +print(full_url) +h,err = http.get(full_url) +if err then + print(err) + return +end +file = fs.open(path, "w") +file.write(h.readAll()) +file.close() +print("saved to "..path) + diff --git a/computer/26/bg.lua b/computer/26/bg.lua new file mode 100644 index 0000000..ccb03ff --- /dev/null +++ b/computer/26/bg.lua @@ -0,0 +1,11 @@ +if not shell.openTab then + printError("Requires multishell") + return +end + +local tArgs = { ... } +if #tArgs > 0 then + shell.openTab(table.unpack(tArgs)) +else + shell.openTab("shell") +end diff --git a/computer/26/expand.lua b/computer/26/expand.lua new file mode 100644 index 0000000..3fa6ca1 --- /dev/null +++ b/computer/26/expand.lua @@ -0,0 +1,106 @@ +require("path") +pp = require("cc.pretty").pretty_print + +require("progress") + +-- mirror = wall is to the right +local mirror = true +mirror = mirror or false + +local TILES = 13 + +function save(layer) + fs.delete("progress.lua") + repeat + file = fs.open("progress.lua", "w") + until file + file.write("progress = " .. progress .. "\n") + file.write("layer_start = " .. layer .. "\n") + -- todo save pos separately, more frequently + file.close() +end + +function mine_step() + repeat + turtle.dig() + until goForward() +end + +function mine3_step() + turtle.digUp() + turtle.digDown() + repeat + turtle.dig() + until goForward() +end + +local turnLeft = true +function turn() + if turnLeft then + goLeft() + else + goRight() + end +end + +-- assumes position is on lamp, right in front of the slice to be mined +-- nearest the wall +function clear_tile_slice() + for layer = layer_start, 5 do + save(layer) + local y = 12 - layer * 3 + local x = 9 + local length = 8 * TILES + 9 + if layer == 5 then + x = x - 3 + length = length - 3 + end + turnLeft = (layer % 2 == 0) ~= mirror + local z = progress*8 + 1 + (layer % 2) * 7 + if y < 0 then + -- avoid breaking the existing floor + for _ = 0, progress*8 do + goForward() + end + end + if mirror then + goTo(vector.new(-x,y,z), "east", true) + else + goTo(vector.new(x,y,z), "west", true) + end + + for strip = 1, 8 do + for _ = 1, length do + mine3_step() + end + if strip ~= 8 then + turn() + mine3_step() + turn() + turnLeft = not turnLeft; + end + end + goLeft() + goLeft() + end +end + +goHome() +clear_tile_slice() +progress = progress + 1 +save(0) +for i = 1, 16 do + turtle.select(i) + turtle.drop() +end +turtle.select(1) +goHome() +goLeft() +goLeft() +while turtle.getFuelLevel() < 20000 do + turtle.suck() + turtle.refuel() +end +turtle.drop() +goLeft() +goLeft() diff --git a/computer/26/garbidge/dig.lua b/computer/26/garbidge/dig.lua new file mode 100644 index 0000000..6056988 --- /dev/null +++ b/computer/26/garbidge/dig.lua @@ -0,0 +1,85 @@ +width = 5 +length = 31 +MinFuelLevel = 19500 + +y = 0 + + +function layer() + turnLeft = 1 + + function turn() + if turnLeft == 1 then + turtle.turnLeft() + else + turtle.turnRight() + end + end + function digStep() + turtle.dig() + turtle.digUp() + turtle.digDown() + turtle.forward() + end + + for row = 1, width do + for i = 1,length do + digStep() + end + turn() + digStep() + turn() + turnLeft = -turnLeft + end + if turnLeft == 1 then + turtle.turnRight() + for i = 1, width do + turtle.forward() + end + turtle.turnLeft() + else + turtle.turnLeft() + turtle.forward() + turtle.turnRight() + for i = 1, length do + turtle.forward() + end + turtle.turnLeft() + for i = 1, width do + turtle.forward() + end + turtle.turnLeft() + end +end + +function unload() + for i = 1, 16 do + turtle.select(i) + turtle.dropUp() + end + turtle.turnLeft() + turtle.turnLeft() + while turtle.getFuelLevel() < MinFuelLevel do + turtle.suck() + turtle.refuel() + end + turtle.drop() + turtle.turnLeft() + turtle.turnLeft() + +end + +while true do + turtle.forward() + for i = 1, y do + turtle.digDown() + turtle.down() + end + layer() + for i = 1, y do + turtle.up() + end + turtle.back() + unload() + y = y + 3 +end diff --git a/computer/26/garbidge/roof.lua b/computer/26/garbidge/roof.lua new file mode 100644 index 0000000..aef6c6c --- /dev/null +++ b/computer/26/garbidge/roof.lua @@ -0,0 +1,34 @@ +width = 5 +length = 23 + +turtle.select(1) + +tLeft = true + +function turn() + if tLeft then + turtle.turnLeft() + else + turtle.turnRight() + end +end + + +function step() + turtle.placeUp() + turtle.forward() + if turtle.getItemCount() == 0 then + turtle.select(turtle.getSelectedSlot()+1) + end +end + + +for row = 1, width do + for i = 1, length do + step() + end + turn() + step() + turn() + tLeft = not tLeft +end diff --git a/computer/26/garbidge/tile.lua b/computer/26/garbidge/tile.lua new file mode 100644 index 0000000..b3ba5a1 --- /dev/null +++ b/computer/26/garbidge/tile.lua @@ -0,0 +1,32 @@ +tile = function() +pf = require("pathfinding") +function selectItem(name) + for i = 1, 16 do + d= turtle.getItemDetail(i) + if d.name == name then + turtle.select(i) + return + end + end + print("pls give me", name) + turtle.select(16) + print("then press enter") + read() +end + +--turtle.forward() +--turtle.turnLeft() +--turtle.forward() +--turtle.turnRight() + +for x = 1, 7 do + for z = 1, 7 do + turtle.select(((x == 4) and (z==4) and 3) or math.mod(x+z,2)+1) + goTo(vector.new(x,0,z)) + turtle.placeDown() + end +end +goTo(vector.new(8,0,0)) +_G.pos=pos-pos +end +return tile diff --git a/computer/26/garbidge/tilemany.lua b/computer/26/garbidge/tilemany.lua new file mode 100644 index 0000000..c48fc64 --- /dev/null +++ b/computer/26/garbidge/tilemany.lua @@ -0,0 +1,4 @@ +t = require("tile") +for i = 1,2 do + t() +end diff --git a/computer/26/multishell.lua b/computer/26/multishell.lua new file mode 100644 index 0000000..f2a9851 --- /dev/null +++ b/computer/26/multishell.lua @@ -0,0 +1,429 @@ +--- Multishell allows multiple programs to be run at the same time. +-- +-- When multiple programs are running, it displays a tab bar at the top of the +-- screen, which allows you to switch between programs. New programs can be +-- launched using the `fg` or `bg` programs, or using the @{shell.openTab} and +-- @{multishell.launch} functions. +-- +-- Each process is identified by its ID, which corresponds to its position in +-- the tab list. As tabs may be opened and closed, this ID is _not_ constant +-- over a program's run. As such, be careful not to use stale IDs. +-- +-- As with @{shell}, @{multishell} is not a "true" API. Instead, it is a +-- standard program, which launches a shell and injects its API into the shell's +-- environment. This API is not available in the global environment, and so is +-- not available to @{os.loadAPI|APIs}. +-- +-- @module[module] multishell +-- @since 1.6 + +local expect = dofile("rom/modules/main/cc/expect.lua").expect + +-- Setup process switching +local parentTerm = term.current() +local w, h = parentTerm.getSize() + +local tProcesses = {} +local nCurrentProcess = nil +local nRunningProcess = nil +local bShowMenu = false +local bWindowsResized = false +local nScrollPos = 1 +local bScrollRight = false + +local function selectProcess(n) + if nCurrentProcess ~= n then + if nCurrentProcess then + local tOldProcess = tProcesses[nCurrentProcess] + tOldProcess.window.setVisible(false) + end + nCurrentProcess = n + if nCurrentProcess then + local tNewProcess = tProcesses[nCurrentProcess] + tNewProcess.window.setVisible(true) + tNewProcess.bInteracted = true + end + end +end + +local function setProcessTitle(n, sTitle) + tProcesses[n].sTitle = sTitle +end + +local function resumeProcess(nProcess, sEvent, ...) + local tProcess = tProcesses[nProcess] + local sFilter = tProcess.sFilter + if sFilter == nil or sFilter == sEvent or sEvent == "terminate" then + local nPreviousProcess = nRunningProcess + nRunningProcess = nProcess + term.redirect(tProcess.terminal) + local ok, result = coroutine.resume(tProcess.co, sEvent, ...) + tProcess.terminal = term.current() + if ok then + tProcess.sFilter = result + else + printError(result) + end + nRunningProcess = nPreviousProcess + end +end + +local function launchProcess(bFocus, tProgramEnv, sProgramPath, ...) + local tProgramArgs = table.pack(...) + local nProcess = #tProcesses + 1 + local tProcess = {} + tProcess.sTitle = fs.getName(sProgramPath) + if bShowMenu then + tProcess.window = window.create(parentTerm, 1, 2, w, h - 1, false) + else + tProcess.window = window.create(parentTerm, 1, 1, w, h, false) + end + tProcess.co = coroutine.create(function() + os.run(tProgramEnv, sProgramPath, table.unpack(tProgramArgs, 1, tProgramArgs.n)) + if not tProcess.bInteracted then + term.setCursorBlink(false) + print("Press any key to continue") + os.pullEvent("char") + end + end) + tProcess.sFilter = nil + tProcess.terminal = tProcess.window + tProcess.bInteracted = false + tProcesses[nProcess] = tProcess + if bFocus then + selectProcess(nProcess) + end + resumeProcess(nProcess) + return nProcess +end + +local function cullProcess(nProcess) + local tProcess = tProcesses[nProcess] + if coroutine.status(tProcess.co) == "dead" then + if nCurrentProcess == nProcess then + selectProcess(nil) + end + table.remove(tProcesses, nProcess) + if nCurrentProcess == nil then + if nProcess > 1 then + selectProcess(nProcess - 1) + elseif #tProcesses > 0 then + selectProcess(1) + end + end + if nScrollPos ~= 1 then + nScrollPos = nScrollPos - 1 + end + return true + end + return false +end + +local function cullProcesses() + local culled = false + for n = #tProcesses, 1, -1 do + culled = culled or cullProcess(n) + end + return culled +end + +-- Setup the main menu +local menuMainTextColor, menuMainBgColor, menuOtherTextColor, menuOtherBgColor +if parentTerm.isColor() then + menuMainTextColor, menuMainBgColor = colors.yellow, colors.black + menuOtherTextColor, menuOtherBgColor = colors.black, colors.gray +else + menuMainTextColor, menuMainBgColor = colors.white, colors.black + menuOtherTextColor, menuOtherBgColor = colors.black, colors.gray +end + +local function redrawMenu() + if bShowMenu then + -- Draw menu + parentTerm.setCursorPos(1, 1) + parentTerm.setBackgroundColor(menuOtherBgColor) + parentTerm.clearLine() + local nCharCount = 0 + local nSize = parentTerm.getSize() + if nScrollPos ~= 1 then + parentTerm.setTextColor(menuOtherTextColor) + parentTerm.setBackgroundColor(menuOtherBgColor) + parentTerm.write("<") + nCharCount = 1 + end + for n = nScrollPos, #tProcesses do + if n == nCurrentProcess then + parentTerm.setTextColor(menuMainTextColor) + parentTerm.setBackgroundColor(menuMainBgColor) + else + parentTerm.setTextColor(menuOtherTextColor) + parentTerm.setBackgroundColor(menuOtherBgColor) + end + parentTerm.write(" " .. tProcesses[n].sTitle .. " ") + nCharCount = nCharCount + #tProcesses[n].sTitle + 2 + end + if nCharCount > nSize then + parentTerm.setTextColor(menuOtherTextColor) + parentTerm.setBackgroundColor(menuOtherBgColor) + parentTerm.setCursorPos(nSize, 1) + parentTerm.write(">") + bScrollRight = true + else + bScrollRight = false + end + + -- Put the cursor back where it should be + local tProcess = tProcesses[nCurrentProcess] + if tProcess then + tProcess.window.restoreCursor() + end + end +end + +local function resizeWindows() + local windowY, windowHeight + if bShowMenu then + windowY = 2 + windowHeight = h - 1 + else + windowY = 1 + windowHeight = h + end + for n = 1, #tProcesses do + local tProcess = tProcesses[n] + local x, y = tProcess.window.getCursorPos() + if y > windowHeight then + tProcess.window.scroll(y - windowHeight) + tProcess.window.setCursorPos(x, windowHeight) + end + tProcess.window.reposition(1, windowY, w, windowHeight) + end + bWindowsResized = true +end + +local function setMenuVisible(bVis) + if bShowMenu ~= bVis then + bShowMenu = bVis + resizeWindows() + redrawMenu() + end +end + +local multishell = {} --- @export + +--- Get the currently visible process. This will be the one selected on +-- the tab bar. +-- +-- Note, this is different to @{getCurrent}, which returns the process which is +-- currently executing. +-- +-- @treturn number The currently visible process's index. +-- @see setFocus +function multishell.getFocus() + return nCurrentProcess +end + +--- Change the currently visible process. +-- +-- @tparam number n The process index to switch to. +-- @treturn boolean If the process was changed successfully. This will +-- return @{false} if there is no process with this id. +-- @see getFocus +function multishell.setFocus(n) + expect(1, n, "number") + if n >= 1 and n <= #tProcesses then + selectProcess(n) + redrawMenu() + return true + end + return false +end + +--- Get the title of the given tab. +-- +-- This starts as the name of the program, but may be changed using +-- @{multishell.setTitle}. +-- @tparam number n The process index. +-- @treturn string|nil The current process title, or @{nil} if the +-- process doesn't exist. +function multishell.getTitle(n) + expect(1, n, "number") + if n >= 1 and n <= #tProcesses then + return tProcesses[n].sTitle + end + return nil +end + +--- Set the title of the given process. +-- +-- @tparam number n The process index. +-- @tparam string title The new process title. +-- @see getTitle +-- @usage Change the title of the current process +-- +-- multishell.setTitle(multishell.getCurrent(), "Hello") +function multishell.setTitle(n, title) + expect(1, n, "number") + expect(2, title, "string") + if n >= 1 and n <= #tProcesses then + setProcessTitle(n, title) + redrawMenu() + end +end + +--- Get the index of the currently running process. +-- +-- @treturn number The currently running process. +function multishell.getCurrent() + return nRunningProcess +end + +--- Start a new process, with the given environment, program and arguments. +-- +-- The returned process index is not constant over the program's run. It can be +-- safely used immediately after launching (for instance, to update the title or +-- switch to that tab). However, after your program has yielded, it may no +-- longer be correct. +-- +-- @tparam table tProgramEnv The environment to load the path under. +-- @tparam string sProgramPath The path to the program to run. +-- @param ... Additional arguments to pass to the program. +-- @treturn number The index of the created process. +-- @see os.run +-- @usage Run the "hello" program, and set its title to "Hello!" +-- +-- local id = multishell.launch({}, "/rom/programs/fun/hello.lua") +-- multishell.setTitle(id, "Hello!") +function multishell.launch(tProgramEnv, sProgramPath, ...) + expect(1, tProgramEnv, "table") + expect(2, sProgramPath, "string") + local previousTerm = term.current() + setMenuVisible(#tProcesses + 1 >= 2) + local nResult = launchProcess(false, tProgramEnv, sProgramPath, ...) + redrawMenu() + term.redirect(previousTerm) + return nResult +end + +--- Get the number of processes within this multishell. +-- +-- @treturn number The number of processes. +function multishell.getCount() + return #tProcesses +end + +-- Begin +parentTerm.clear() +setMenuVisible(false) +launchProcess(true, { + ["shell"] = shell, + ["multishell"] = multishell, +}, "/rom/programs/shell.lua") + +-- Run processes +while #tProcesses > 0 do + -- Get the event + local tEventData = table.pack(os.pullEventRaw()) + local sEvent = tEventData[1] + if sEvent == "term_resize" then + -- Resize event + w, h = parentTerm.getSize() + resizeWindows() + redrawMenu() + + elseif sEvent == "char" or sEvent == "key" or sEvent == "key_up" or sEvent == "paste" or sEvent == "terminate" then + -- Keyboard event + -- Passthrough to current process + if tEventData[2] == 290 and sEvent == "key" then + multishell.setFocus((nCurrentProcess or 0) % #tProcesses + 1) + else + resumeProcess(nCurrentProcess, table.unpack(tEventData, 1, tEventData.n)) + if cullProcess(nCurrentProcess) then + setMenuVisible(#tProcesses >= 2) + redrawMenu() + end + end + elseif sEvent == "mouse_click" then + -- Click event + local button, x, y = tEventData[2], tEventData[3], tEventData[4] + if bShowMenu and y == 1 then + -- Switch process + if x == 1 and nScrollPos ~= 1 then + nScrollPos = nScrollPos - 1 + redrawMenu() + elseif bScrollRight and x == term.getSize() then + nScrollPos = nScrollPos + 1 + redrawMenu() + else + local tabStart = 1 + if nScrollPos ~= 1 then + tabStart = 2 + end + for n = nScrollPos, #tProcesses do + local tabEnd = tabStart + #tProcesses[n].sTitle + 1 + if x >= tabStart and x <= tabEnd then + selectProcess(n) + redrawMenu() + break + end + tabStart = tabEnd + 1 + end + end + else + -- Passthrough to current process + resumeProcess(nCurrentProcess, sEvent, button, x, bShowMenu and y - 1 or y) + if cullProcess(nCurrentProcess) then + setMenuVisible(#tProcesses >= 2) + redrawMenu() + end + end + + elseif sEvent == "mouse_drag" or sEvent == "mouse_up" or sEvent == "mouse_scroll" then + -- Other mouse event + local p1, x, y = tEventData[2], tEventData[3], tEventData[4] + if bShowMenu and sEvent == "mouse_scroll" and y == 1 then + if p1 == -1 and nScrollPos ~= 1 then + nScrollPos = nScrollPos - 1 + redrawMenu() + elseif bScrollRight and p1 == 1 then + nScrollPos = nScrollPos + 1 + redrawMenu() + end + elseif not (bShowMenu and y == 1) then + -- Passthrough to current process + resumeProcess(nCurrentProcess, sEvent, p1, x, bShowMenu and y - 1 or y) + if cullProcess(nCurrentProcess) then + setMenuVisible(#tProcesses >= 2) + redrawMenu() + end + end + + else + -- Other event + -- Passthrough to all processes + local nLimit = #tProcesses -- Storing this ensures any new things spawned don't get the event + for n = 1, nLimit do + resumeProcess(n, table.unpack(tEventData, 1, tEventData.n)) + end + if cullProcesses() then + setMenuVisible(#tProcesses >= 2) + redrawMenu() + end + end + + if bWindowsResized then + -- Pass term_resize to all processes + local nLimit = #tProcesses -- Storing this ensures any new things spawned don't get the event + for n = 1, nLimit do + resumeProcess(n, "term_resize") + end + bWindowsResized = false + if cullProcesses() then + setMenuVisible(#tProcesses >= 2) + redrawMenu() + end + end +end + +-- Shutdown +term.redirect(parentTerm) diff --git a/computer/26/path.lua b/computer/26/path.lua new file mode 100644 index 0000000..59c052c --- /dev/null +++ b/computer/26/path.lua @@ -0,0 +1,124 @@ +pp = require("cc.pretty").pretty_print + +_G.facing = _G.facing or "south" +_G.pos = _G.pos or vector.new(0,0,0) + +local up = vector.new(0,1,0) + +local rightOf = { + south = "west", + west = "north", + north = "east", + east = "south" +} + +local leftOf = { + west = "south", + north = "west", + east = "north", + south = "east" +} + +local vecOf = { + north = vector.new(0,0,-1), + south = vector.new(0,0,1), + east = vector.new(1,0,0), + west = vector.new(-1,0,0), +} + +function goUp() + if turtle.up() then + _G.pos.y = _G.pos.y + 1 + return true + end + printError("failed to go up") + printError(pos) + return false +end + +function goDown() + if turtle.down() then + _G.pos.y = _G.pos.y - 1 + return true + end + printError("failed to go down") + printError(pos) + return false +end + +function goLeft() + turtle.turnLeft() + _G.facing = leftOf[_G.facing] +end + +function goRight() + turtle.turnRight() + _G.facing = rightOf[_G.facing] +end + +function goForward() + if turtle.forward() then + _G.pos = _G.pos + vecOf[_G.facing] + return true + end + -- printError("failed to go forward") + -- printError(pos) + return false +end + +function goBack() + if turtle.back() then + _G.pos = _G.pos - vecOf[_G.facing] + return true + end + printError("failed to go backward") + printError(pos) + return false +end + +function stepTo(target, dig) + local delta = target - _G.pos + -- print(delta) + if delta.y > 0 then + if dig then + repeat turtle.digUp() until goUp() + else + goUp() + end + elseif delta.y < 0 then + if dig then + turtle.digDown() + end + goDown() + elseif delta:dot(vecOf[_G.facing]) > 0 then + if dig then + repeat turtle.dig() until goForward() + else + goForward() + end + elseif delta:dot(vecOf[_G.facing]:cross(up)) > 0 then + goRight() + else + goLeft() + end +end + +function goTo(target, face, dig) + while target ~= _G.pos do + stepTo(target, dig) + end + if face and face ~= _G.facing then + if rightOf[_G.facing] == face then + goRight() + elseif leftOf[_G.facing] == face then + goLeft() + else + goRight() + goRight() + end + end +end + +function goHome() + goTo(vector.new(0,0,0), "south") +end diff --git a/computer/26/progress.lua b/computer/26/progress.lua new file mode 100644 index 0000000..9e71bd1 --- /dev/null +++ b/computer/26/progress.lua @@ -0,0 +1,2 @@ +progress = 1 +layer_start = 1 diff --git a/computer/26/startup.lua b/computer/26/startup.lua new file mode 100644 index 0000000..84813bd --- /dev/null +++ b/computer/26/startup.lua @@ -0,0 +1 @@ +require("multishell") diff --git a/computer/27/dismemberer.lua b/computer/27/dismemberer.lua new file mode 100644 index 0000000..b026d7e --- /dev/null +++ b/computer/27/dismemberer.lua @@ -0,0 +1,31 @@ +ts = peripheral.wrap("back") + +--[[ +on the tick where the train +was imminent, but was not present. +and now is present and imminent: +payload sequence +]] +function ready() + wasimminent = isimminent + isimminent = ts.isTrainImminent() + waspresent = ispresent + ispresent = ts.isTrainPresent() + if + wasimminent and + isimminent and + (not waspresent) and + ispresent + then + payload() + end +end +function payload() + sleep(0.3) + if ts.isTrainPresent() then + ts.disassemble() + sleep(0.3) + ts.assemble() + end +end +repeat ready() sleep(0.05) until false diff --git a/computer/27/startup.lua b/computer/27/startup.lua new file mode 100644 index 0000000..d70493c --- /dev/null +++ b/computer/27/startup.lua @@ -0,0 +1,2 @@ +rednet.open("top") +rednet.host("elevator") diff --git a/computer/28/char b/computer/28/char new file mode 100644 index 0000000..16e0e90 --- /dev/null +++ b/computer/28/char @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/computer/28/lib/argparse.lua b/computer/28/lib/argparse.lua new file mode 100644 index 0000000..5a86d96 --- /dev/null +++ b/computer/28/lib/argparse.lua @@ -0,0 +1,477 @@ +local function e(t,a)for o,i in pairs(a)do if type(i)=="table"then i=e({},i)end +t[o]=i end return t end local function n(s,h,r)local d={}d.__index=d if r then +d.__prototype=e(e({},r.__prototype),s)else d.__prototype=s end if h then local +l={}for u,c in ipairs(h)do local m,f=c[1],c[2]d[m]=function(w,y)if not +f(w,y)then w["_"..m]=y end return w end l[m]=true end function +d.__call(p,...)if type((...))=="table"then for v,b in pairs((...))do if +l[v]then p[v](p,b)end end else local g=select("#",...)for k,q in ipairs(h)do if +k>g or k>h.args then break end local arg=select(k,...)if arg~=nil then +p[q[1]](p,arg)end end end return p end end local j={}j.__index=r function +j.__call(x,...)local z=e({},x.__prototype)setmetatable(z,x)return z(...)end +return setmetatable(d,j)end local function E(T,A,O)for I,N in ipairs(A)do if +type(O)==N then return true end end +error(("bad property '%s' (%s expected, got %s)"):format(T,table.concat(A," or "),type(O)))end +local function S(H,...)local R={...}return{H,function(D,L)E(H,R,L)end}end local +U={"name",function(C,M)E("name",{"string"},M)for F in M:gmatch("%S+")do +C._name=C._name or F +table.insert(C._aliases,F)table.insert(C._public_aliases,F)if +F:find("_",1,true)then table.insert(C._aliases,(F:gsub("_","-")))end end return +true end}local W={"hidden_name",function(Y,P)E("hidden_name",{"string"},P)for V +in P:gmatch("%S+")do table.insert(Y._aliases,V)if V:find("_",1,true)then +table.insert(Y._aliases,(V:gsub("_","-")))end end return true end}local +function B(G)if tonumber(G)then return tonumber(G),tonumber(G)end if G=="*"then +return 0,math.huge end if G=="+"then return 1,math.huge end if G=="?"then +return 0,1 end if G:match"^%d+%-%d+$"then local +K,Q=G:match"^(%d+)%-(%d+)$"return tonumber(K),tonumber(Q)end if +G:match"^%d+%+$"then local J=G:match"^(%d+)%+$"return tonumber(J),math.huge end +end local function X(Z)return{Z,function(et,tt)E(Z,{"number","string"},tt)local +at,ot=B(tt)if not at then error(("bad property '%s'"):format(Z))end +et["_min"..Z],et["_max"..Z]=at,ot end}end local it={}local +nt={"action",function(st,ht)E("action",{"function","string"},ht)if +type(ht)=="string"and not it[ht]then +error(("unknown action '%s'"):format(ht))end end}local +rt={"init",function(dt)dt._has_init=true end}local +lt={"default",function(ut,ct)if type(ct)~="string"then ut._init=ct +ut._has_init=true return true end end}local +mt={"add_help",function(ft,wt)E("add_help",{"boolean","string","table"},wt)if +ft._help_option_idx then +table.remove(ft._options,ft._help_option_idx)ft._help_option_idx=nil end if wt +then local +yt=ft:flag():description"Show this help message and exit.":action(function()print(ft:get_help())error()end)if +wt~=true then yt=yt(wt)end if not yt._name then yt"-h""--help"end +ft._help_option_idx=#ft._options end end}local +pt=n({_arguments={},_options={},_commands={},_mutexes={},_groups={},_require_command=true,_handle_options=true},{args=3,S("name","string"),S("description","string"),S("epilog","string"),S("usage","string"),S("help","string"),S("require_command","boolean"),S("handle_options","boolean"),S("action","function"),S("command_target","string"),S("help_vertical_space","number"),S("usage_margin","number"),S("usage_max_width","number"),S("help_usage_margin","number"),S("help_description_margin","number"),S("help_max_width","number"),mt})local +vt=n({_aliases={},_public_aliases={}},{args=3,U,S("description","string"),S("epilog","string"),W,S("summary","string"),S("target","string"),S("usage","string"),S("help","string"),S("require_command","boolean"),S("handle_options","boolean"),S("action","function"),S("command_target","string"),S("help_vertical_space","number"),S("usage_margin","number"),S("usage_max_width","number"),S("help_usage_margin","number"),S("help_description_margin","number"),S("help_max_width","number"),S("hidden","boolean"),mt},pt)local +bt=n({_minargs=1,_maxargs=1,_mincount=1,_maxcount=1,_defmode="unused",_show_default=true},{args=5,S("name","string"),S("description","string"),lt,S("convert","function","table"),X("args"),S("target","string"),S("defmode","string"),S("show_default","boolean"),S("argname","string","table"),S("choices","table"),S("hidden","boolean"),nt,rt})local +gt=n({_aliases={},_public_aliases={},_mincount=0,_overwrite=true},{args=6,U,S("description","string"),lt,S("convert","function","table"),X("args"),X("count"),W,S("target","string"),S("defmode","string"),S("show_default","boolean"),S("overwrite","boolean"),S("argname","string","table"),S("choices","table"),S("hidden","boolean"),nt,rt},bt)function +pt:_inherit_property(kt,qt)local jt=self while true do local xt=jt["_"..kt]if +xt~=nil then return xt end if not jt._parent then return qt end jt=jt._parent +end end function bt:_get_argument_list()local zt={}local Et=1 while +Et<=math.min(self._minargs,3)do local Tt=self:_get_argname(Et)if self._default +and self._defmode:find"a"then Tt="["..Tt.."]"end table.insert(zt,Tt)Et=Et+1 end +while Et<=math.min(self._maxargs,3)do +table.insert(zt,"["..self:_get_argname(Et).."]")Et=Et+1 if +self._maxargs==math.huge then break end end if Et1 or(self._minargs==1 and not +self._defmode:find"a")then At="["..At.."]"end end return At end function +it.store_true(Ot,It)Ot[It]=true end function it.store_false(Nt,St)Nt[St]=false +end function it.store(Ht,Rt,Dt)Ht[Rt]=Dt end function it.count(Lt,Ut,Ct,Mt)if +not Mt then Lt[Ut]=Lt[Ut]+1 end end function +it.append(Ft,Wt,Yt,Pt)Ft[Wt]=Ft[Wt]or{}table.insert(Ft[Wt],Yt)if Pt then +table.remove(Ft[Wt],1)end end function it.concat(Vt,Bt,Gt,Kt)if Kt then +error("'concat' action can't handle too many invocations")end +Vt[Bt]=Vt[Bt]or{}for Qt,Jt in ipairs(Gt)do table.insert(Vt[Bt],Jt)end end +function bt:_get_action()local Xt,Zt if self._maxcount==1 then if +self._maxargs==0 then Xt,Zt="store_true",nil else Xt,Zt="store",nil end else if +self._maxargs==0 then Xt,Zt="count",0 else Xt,Zt="append",{}end end if +self._action then Xt=self._action end if self._has_init then Zt=self._init end +if type(Xt)=="string"then Xt=it[Xt]end return Xt,Zt end function +bt:_get_argname(ea)local ta=self._argname or self:_get_default_argname()if +type(ta)=="table"then return ta[ea]else return ta end end function +bt:_get_choices_list()return"{"..table.concat(self._choices,",").."}"end +function bt:_get_default_argname()if self._choices then return +self:_get_choices_list()else return"<"..self._name..">"end end function +gt:_get_default_argname()if self._choices then return +self:_get_choices_list()else return"<"..self:_get_default_target()..">"end end +function bt:_get_label_lines()if self._choices then +return{self:_get_choices_list()}else return{self._name}end end function +gt:_get_label_lines()local aa=self:_get_argument_list()if#aa==0 then +return{table.concat(self._public_aliases,", ")}end local oa=-1 for ia,na in +ipairs(self._public_aliases)do oa=math.max(oa,#na)end local +sa=table.concat(aa," ")local ha={}for ra,da in ipairs(self._public_aliases)do +local la=(" "):rep(oa-#da)..da.." "..sa if ra~=#self._public_aliases then +la=la..","end table.insert(ha,la)end return ha end function +vt:_get_label_lines()return{table.concat(self._public_aliases,", ")}end +function bt:_get_description()if self._default and self._show_default then if +self._description then +return("%s (default: %s)"):format(self._description,self._default)else +return("default: %s"):format(self._default)end else return self._description +or""end end function vt:_get_description()return self._summary or +self._description or""end function gt:_get_usage()local +ua=self:_get_argument_list()table.insert(ua,1,self._name)ua=table.concat(ua," ")if +self._mincount==0 or self._default then ua="["..ua.."]"end return ua end +function bt:_get_default_target()return self._name end function +gt:_get_default_target()local ca for ma,fa in ipairs(self._public_aliases)do if +fa:sub(1,1)==fa:sub(2,2)then ca=fa:sub(3)break end end ca=ca or +self._name:sub(2)return(ca:gsub("-","_"))end function gt:_is_vararg()return +self._maxargs~=self._minargs end function pt:_get_fullname(wa)local +ya=self._parent if wa and not ya then return""end local pa={self._name}while ya +do if not wa or ya._parent then table.insert(pa,1,ya._name)end ya=ya._parent +end return table.concat(pa," ")end function pt:_update_charset(va)va=va or{}for +ba,ga in ipairs(self._commands)do ga:_update_charset(va)end for ka,qa in +ipairs(self._options)do for ka,ja in ipairs(qa._aliases)do va[ja:sub(1,1)]=true +end end return va end function pt:argument(...)local +xa=bt(...)table.insert(self._arguments,xa)return xa end function +pt:option(...)local za=gt(...)table.insert(self._options,za)return za end +function pt:flag(...)return self:option():args(0)(...)end function +pt:command(...)local Ea=vt():add_help(true)(...)Ea._parent=self +table.insert(self._commands,Ea)return Ea end function pt:mutex(...)local +Ta={...}for Aa,Oa in ipairs(Ta)do local Ia=getmetatable(Oa)assert(Ia==gt or +Ia==bt,("bad argument #%d to 'mutex' (Option or Argument expected)"):format(Aa))end +table.insert(self._mutexes,Ta)return self end function +pt:group(Na,...)assert(type(Na)=="string",("bad argument #1 to 'group' (string expected, got %s)"):format(type(Na)))local +Sa={name=Na,...}for Ha,Ra in ipairs(Sa)do local +Da=getmetatable(Ra)assert(Da==gt or Da==bt or +Da==vt,("bad argument #%d to 'group' (Option or Argument or Command expected)"):format(Ha+1))end +table.insert(self._groups,Sa)return self end local La="Usage: "function +pt:get_usage()if self._usage then return self._usage end local +Ua=self:_inherit_property("usage_margin",#La)local +Ca=self:_inherit_property("usage_max_width",70)local +Ma={La..self:_get_fullname()}local function Fa(Wa)if#Ma[#Ma]+1+#Wa<=Ca then +Ma[#Ma]=Ma[#Ma].." "..Wa else Ma[#Ma+1]=(" "):rep(Ua)..Wa end end local +Ya={}local Pa={}local Va={}local Ba={}local function Ga(Ka,Qa)if Va[Ka]then +return end Va[Ka]=true local Ja={}for Xa,Za in ipairs(Ka)do if not Za._hidden +and not Pa[Za]then if getmetatable(Za)==gt or Za==Qa then +table.insert(Ja,Za:_get_usage())Pa[Za]=true end end end if#Ja==1 then +Fa(Ja[1])elseif#Ja>1 then Fa("("..table.concat(Ja," | ")..")")end end local +function eo(to)if not to._hidden and not Pa[to]then +Fa(to:_get_usage())Pa[to]=true end end for ao,oo in ipairs(self._mutexes)do +local no=false local so=false for ao,ho in ipairs(oo)do if getmetatable(ho)==gt +then if ho:_is_vararg()then no=true end else so=true +Ba[ho]=Ba[ho]or{}table.insert(Ba[ho],oo)end Ya[ho]=true end if not no and not +so then Ga(oo)end end for ro,lo in ipairs(self._options)do if not Ya[lo]and not +lo:_is_vararg()then eo(lo)end end for uo,co in ipairs(self._arguments)do local +mo if Ya[co]then for uo,fo in ipairs(Ba[co])do if not Va[fo]then mo=fo end end +end if mo then Ga(mo,co)else eo(co)end end for wo,yo in ipairs(self._mutexes)do +Ga(yo)end for po,vo in ipairs(self._options)do eo(vo)end if#self._commands>0 +then if self._require_command then Fa("")else Fa("[]")end +Fa("...")end return table.concat(Ma,"\n")end local function bo(go)if go==""then +return{}end local ko={}if go:sub(-1)~="\n"then go=go.."\n"end for qo in +go:gmatch("([^\n]*)\n")do table.insert(ko,qo)end return ko end local function +jo(xo,zo)local Eo={}local To=xo:match("^ *")if xo:find("^ *[%*%+%-]")then +To=To.." "..xo:match("^ *[%*%+%-]( *)")end local Ao={}local Oo=0 local Io=1 +while true do local No,So,Ho=xo:find("([^ ]+)",Io)if not No then break end +local Ro=xo:sub(Io,No-1)Io=So+1 if(#Ao==0)or(Oo+#Ro+#Ho<=zo)then +table.insert(Ao,Ro)table.insert(Ao,Ho)Oo=Oo+#Ro+#Ho else +table.insert(Eo,table.concat(Ao))Ao={To,Ho}Oo=#To+#Ho end end if#Ao>0 then +table.insert(Eo,table.concat(Ao))end if#Eo==0 then Eo[1]=""end return Eo end +local function Do(Lo,Uo)local Co={}for Mo,Fo in ipairs(Lo)do local +Wo=jo(Fo,Uo)for Mo,Yo in ipairs(Wo)do table.insert(Co,Yo)end end return Co end +function pt:_get_element_help(Po)local Vo=Po:_get_label_lines()local +Bo=bo(Po:_get_description())local Go={}local +Ko=self:_inherit_property("help_usage_margin",1)local Qo=(" "):rep(Ko)local +Jo=self:_inherit_property("help_description_margin",23)local +Xo=(" "):rep(Jo)local Zo=self:_inherit_property("help_max_width")if Zo then +local ei=math.max(Zo-Jo,10)Bo=Do(Bo,ei)end if#Vo[1]>=(Jo-Ko)then for ti,ai in +ipairs(Vo)do table.insert(Go,Qo..ai)end for oi,ii in ipairs(Bo)do +table.insert(Go,Xo..ii)end else for ni=1,math.max(#Vo,#Bo)do local +si=Vo[ni]local hi=Bo[ni]local ri=""if si then ri=Qo..si end if hi and +hi~=""then ri=ri..(" "):rep(Jo-#ri)..hi end table.insert(Go,ri)end end return +table.concat(Go,"\n")end local function di(li)local ui={}for ci,mi in +ipairs(li)do ui[getmetatable(mi)]=true end return ui end function +pt:_add_group_help(fi,wi,yi,pi)local vi={yi}for bi,gi in ipairs(pi)do if not +gi._hidden and not wi[gi]then wi[gi]=true +table.insert(vi,self:_get_element_help(gi))end end if#vi>1 then +table.insert(fi,table.concat(vi,("\n"):rep(self:_inherit_property("help_vertical_space",0)+1)))end +end function pt:get_help()if self._help then return self._help end local +ki={self:get_usage()}local qi=self:_inherit_property("help_max_width")if +self._description then local ji=self._description if qi then +ji=table.concat(Do(bo(ji),qi),"\n")end table.insert(ki,ji)end local +xi={[bt]={},[gt]={},[vt]={}}for zi,Ei in ipairs(self._groups)do local +Ti=di(Ei)for zi,Ai in ipairs({bt,gt,vt})do if Ti[Ai]then +table.insert(xi[Ai],Ei)break end end end local +Oi={{name="Arguments",type=bt,elements=self._arguments},{name="Options",type=gt,elements=self._options},{name="Commands",type=vt,elements=self._commands}}local +Ii={}for Ni,Si in ipairs(Oi)do local Hi=xi[Si.type]for Ni,Ri in ipairs(Hi)do +self:_add_group_help(ki,Ii,Ri.name..":",Ri)end local Di=Si.name..":"if#Hi>0 +then Di="Other "..Di:gsub("^.",string.lower)end +self:_add_group_help(ki,Ii,Di,Si.elements)end if self._epilog then local +Li=self._epilog if qi then Li=table.concat(Do(bo(Li),qi),"\n")end +table.insert(ki,Li)end return table.concat(ki,"\n\n")end function +pt:add_help_command(Ui)if Ui then assert(type(Ui)=="string"or +type(Ui)=="table",("bad argument #1 to 'add_help_command' (string or table expected, got %s)"):format(type(Ui)))end +local +Ci=self:command():description"Show help for commands."Ci:argument"command":description"The command to show help for.":args"?":action(function(Mi,Mi,Fi)if +not Fi then print(self:get_help())error()else for Mi,Wi in +ipairs(self._commands)do for Mi,Yi in ipairs(Wi._aliases)do if Yi==Fi then +print(Wi:get_help())error()end end end end +Ci:error(("unknown command '%s'"):format(Fi))end)if Ui then Ci=Ci(Ui)end if not +Ci._name then Ci"help"end Ci._is_help_command=true return self end function +pt:_is_shell_safe()if self._basename then if +self._basename:find("[^%w_%-%+%.]")then return false end else for Pi,Vi in +ipairs(self._aliases)do if Vi:find("[^%w_%-%+%.]")then return false end end end +for Bi,Gi in ipairs(self._options)do for Bi,Ki in ipairs(Gi._aliases)do if +Ki:find("[^%w_%-%+%.]")then return false end end if Gi._choices then for Bi,Qi +in ipairs(Gi._choices)do if Qi:find("[%s'\"]")then return false end end end end +for Ji,Xi in ipairs(self._arguments)do if Xi._choices then for Ji,Zi in +ipairs(Xi._choices)do if Zi:find("[%s'\"]")then return false end end end end +for en,tn in ipairs(self._commands)do if not tn:_is_shell_safe()then return +false end end return true end function pt:add_complete(an)if an then +assert(type(an)=="string"or +type(an)=="table",("bad argument #1 to 'add_complete' (string or table expected, got %s)"):format(type(an)))end +local +on=self:option():description"Output a shell completion script for the specified shell.":args(1):choices{"bash","zsh","fish"}:action(function(nn,nn,sn)io.write(self["get_"..sn.."_complete"](self))error()end)if +an then on=on(an)end if not on._name then on"--completion"end return self end +function pt:add_complete_command(hn)if hn then assert(type(hn)=="string"or +type(hn)=="table",("bad argument #1 to 'add_complete_command' (string or table expected, got %s)"):format(type(hn)))end +local +rn=self:command():description"Output a shell completion script."rn:argument"shell":description"The shell to output a completion script for.":choices{"bash","zsh","fish"}:action(function(dn,dn,ln)io.write(self["get_"..ln.."_complete"](self))error()end)if +hn then rn=rn(hn)end if not rn._name then rn"completion"end return self end +local function un(cn)return cn:gsub("[/\\]*$",""):match(".*[/\\]([^/\\]*)")or +cn end local function mn(fn)local +wn=fn:_get_description():match("^(.-)%.%s")return wn or +fn:_get_description():match("^(.-)%.?$")end function pt:_get_options()local +yn={}for pn,vn in ipairs(self._options)do for pn,bn in ipairs(vn._aliases)do +table.insert(yn,bn)end end return table.concat(yn," ")end function +pt:_get_commands()local gn={}for kn,qn in ipairs(self._commands)do for kn,jn in +ipairs(qn._aliases)do table.insert(gn,jn)end end return table.concat(gn," ")end +function pt:_bash_option_args(xn,zn)local En={}for Tn,An in +ipairs(self._options)do if An._choices or An._minargs>0 then local On if +An._choices then +On='COMPREPLY=($(compgen -W "'..table.concat(An._choices," ")..'" -- "$cur"))'else +On='COMPREPLY=($(compgen -f -- "$cur"))'end +table.insert(En,(" "):rep(zn+4)..table.concat(An._aliases,"|")..")")table.insert(En,(" "):rep(zn+8)..On)table.insert(En,(" "):rep(zn+8).."return 0")table.insert(En,(" "):rep(zn+8)..";;")end +end if#En>0 then +table.insert(xn,(" "):rep(zn)..'case "$prev" in')table.insert(xn,table.concat(En,"\n"))table.insert(xn,(" "):rep(zn).."esac\n")end +end function pt:_bash_get_cmd(In,Nn)if#self._commands==0 then return end +table.insert(In,(" "):rep(Nn)..'args=("${args[@]:1}")')table.insert(In,(" "):rep(Nn)..'for arg in "${args[@]}"; do')table.insert(In,(" "):rep(Nn+4)..'case "$arg" in')for +Sn,Hn in ipairs(self._commands)do +table.insert(In,(" "):rep(Nn+8)..table.concat(Hn._aliases,"|")..")")if +self._parent then +table.insert(In,(" "):rep(Nn+12)..'cmd="$cmd '..Hn._name..'"')else +table.insert(In,(" "):rep(Nn+12)..'cmd="'..Hn._name..'"')end +table.insert(In,(" "):rep(Nn+12)..'opts="$opts '..Hn:_get_options()..'"')Hn:_bash_get_cmd(In,Nn+12)table.insert(In,(" "):rep(Nn+12).."break")table.insert(In,(" "):rep(Nn+12)..";;")end +table.insert(In,(" "):rep(Nn+4).."esac")table.insert(In,(" "):rep(Nn).."done")end +function pt:_bash_cmd_completions(Rn)local Dn={}if self._parent then +self:_bash_option_args(Dn,12)end if#self._commands>0 then +table.insert(Dn,(" "):rep(12)..'COMPREPLY=($(compgen -W "'..self:_get_commands()..'" -- "$cur"))')elseif +self._is_help_command then +table.insert(Dn,(" "):rep(12)..'COMPREPLY=($(compgen -W "'..self._parent:_get_commands()..'" -- "$cur"))')end +if#Dn>0 then +table.insert(Rn,(" "):rep(8).."'"..self:_get_fullname(true).."')")table.insert(Rn,table.concat(Dn,"\n"))table.insert(Rn,(" "):rep(12)..";;")end +for Ln,Un in ipairs(self._commands)do Un:_bash_cmd_completions(Rn)end end +function +pt:get_bash_complete()self._basename=un(self._name)assert(self:_is_shell_safe())local +Cn={([[ +_%s() { + local IFS=$' \t\n' + local args cur prev cmd opts arg + args=("${COMP_WORDS[@]}") + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + opts="%s" +]]):format(self._basename,self:_get_options())}self:_bash_option_args(Cn,4)self:_bash_get_cmd(Cn,4)if#self._commands>0 +then +table.insert(Cn,"")table.insert(Cn,(" "):rep(4)..'case "$cmd" in')self:_bash_cmd_completions(Cn)table.insert(Cn,(" "):rep(4).."esac\n")end +table.insert(Cn,([=[ + if [[ "$cur" = -* ]]; then + COMPREPLY=($(compgen -W "$opts" -- "$cur")) + fi +} + +complete -F _%s -o bashdefault -o default %s +]=]):format(self._basename,self._basename))return +table.concat(Cn,"\n")end function pt:_zsh_arguments(Mn,Fn,Wn)if self._parent +then +table.insert(Mn,(" "):rep(Wn).."options=(")table.insert(Mn,(" "):rep(Wn+2).."$options")else +table.insert(Mn,(" "):rep(Wn).."local -a options=(")end for Yn,Pn in +ipairs(self._options)do local Vn={}if#Pn._aliases>1 then if Pn._maxcount>1 then +table.insert(Vn,'"*"')end +table.insert(Vn,"{"..table.concat(Pn._aliases,",")..'}"')else +table.insert(Vn,'"')if Pn._maxcount>1 then table.insert(Vn,"*")end +table.insert(Vn,Pn._name)end if Pn._description then local +Bn=mn(Pn):gsub('["%]:`$]',"\\%0")table.insert(Vn,"["..Bn.."]")end if +Pn._maxargs==math.huge then table.insert(Vn,":*")end if Pn._choices then +table.insert(Vn,": :("..table.concat(Pn._choices," ")..")")elseif Pn._maxargs>0 +then table.insert(Vn,": :_files")end +table.insert(Vn,'"')table.insert(Mn,(" "):rep(Wn+2)..table.concat(Vn))end +table.insert(Mn,(" "):rep(Wn)..")")table.insert(Mn,(" "):rep(Wn).."_arguments -s -S \\")table.insert(Mn,(" "):rep(Wn+2).."$options \\")if +self._is_help_command then +table.insert(Mn,(" "):rep(Wn+2)..'": :('..self._parent:_get_commands()..')" \\')else +for Gn,Kn in ipairs(self._arguments)do local Qn if Kn._choices then +Qn=": :("..table.concat(Kn._choices," ")..")"else Qn=": :_files"end if +Kn._maxargs==math.huge then +table.insert(Mn,(" "):rep(Wn+2)..'"*'..Qn..'" \\')break end for +Gn=1,Kn._maxargs do table.insert(Mn,(" "):rep(Wn+2)..'"'..Qn..'" \\')end end +if#self._commands>0 then +table.insert(Mn,(" "):rep(Wn+2)..'": :_'..Fn..'_cmds" \\')table.insert(Mn,(" "):rep(Wn+2)..'"*:: :->args" \\')end +end table.insert(Mn,(" "):rep(Wn+2).."&& return 0")end function +pt:_zsh_cmds(Jn,Xn)table.insert(Jn,"\n_"..Xn.."_cmds() {")table.insert(Jn," local -a commands=(")for +Zn,es in ipairs(self._commands)do local ts={}if#es._aliases>1 then +table.insert(ts,"{"..table.concat(es._aliases,",")..'}"')else +table.insert(ts,'"'..es._name)end if es._description then +table.insert(ts,":"..mn(es):gsub('["`$]',"\\%0"))end +table.insert(Jn," "..table.concat(ts)..'"')end +table.insert(Jn,' )\n _describe "command" commands\n}')end function +pt:_zsh_complete_help(as,os,is,ns)if#self._commands==0 then return end +self:_zsh_cmds(os,is)table.insert(as,"\n"..(" "):rep(ns).."case $words[1] in")for +ss,hs in ipairs(self._commands)do local rs=is.."_"..hs._name +table.insert(as,(" "):rep(ns+2)..table.concat(hs._aliases,"|")..")")hs:_zsh_arguments(as,rs,ns+4)hs:_zsh_complete_help(as,os,rs,ns+4)table.insert(as,(" "):rep(ns+4)..";;\n")end +table.insert(as,(" "):rep(ns).."esac")end function +pt:get_zsh_complete()self._basename=un(self._name)assert(self:_is_shell_safe())local +ds={("#compdef %s\n"):format(self._basename)}local +ls={}table.insert(ds,"_"..self._basename.."() {")if#self._commands>0 then +table.insert(ds," local context state state_descr line")table.insert(ds," typeset -A opt_args\n")end +self:_zsh_arguments(ds,self._basename,2)self:_zsh_complete_help(ds,ls,self._basename,2)table.insert(ds,"\n return 1")table.insert(ds,"}")local +us=table.concat(ds,"\n")if#ls>0 then us=us.."\n"..table.concat(ls,"\n")end +return us.."\n\n_"..self._basename.."\n"end local function cs(ms)return +ms:gsub("[\\']","\\%0")end function pt:_fish_get_cmd(fs,ws)if#self._commands==0 +then return end +table.insert(fs,(" "):rep(ws).."set -e cmdline[1]")table.insert(fs,(" "):rep(ws).."for arg in $cmdline")table.insert(fs,(" "):rep(ws+4).."switch $arg")for +ys,ps in ipairs(self._commands)do +table.insert(fs,(" "):rep(ws+8).."case "..table.concat(ps._aliases," "))table.insert(fs,(" "):rep(ws+12).."set cmd $cmd "..ps._name)ps:_fish_get_cmd(fs,ws+12)table.insert(fs,(" "):rep(ws+12).."break")end +table.insert(fs,(" "):rep(ws+4).."end")table.insert(fs,(" "):rep(ws).."end")end +function pt:_fish_complete_help(vs,bs)local gs="complete -c "..bs +table.insert(vs,"")for ks,qs in ipairs(self._commands)do local +js=table.concat(qs._aliases," ")local xs if self._parent then +xs=("%s -n '__fish_%s_using_command %s' -xa '%s'"):format(gs,bs,self:_get_fullname(true),js)else +xs=("%s -n '__fish_%s_using_command' -xa '%s'"):format(gs,bs,js)end if +qs._description then xs=("%s -d '%s'"):format(xs,cs(mn(qs)))end +table.insert(vs,xs)end if self._is_help_command then local +zs=("%s -n '__fish_%s_using_command %s' -xa '%s'"):format(gs,bs,self:_get_fullname(true),self._parent:_get_commands())table.insert(vs,zs)end +for Es,Ts in ipairs(self._options)do local As={gs}if self._parent then +table.insert(As,"-n '__fish_"..bs.."_seen_command "..self:_get_fullname(true).."'")end +for Es,Os in ipairs(Ts._aliases)do if Os:match("^%-.$")then +table.insert(As,"-s "..Os:sub(2))elseif Os:match("^%-%-.+")then +table.insert(As,"-l "..Os:sub(3))end end if Ts._choices then +table.insert(As,"-xa '"..table.concat(Ts._choices," ").."'")elseif +Ts._minargs>0 then table.insert(As,"-r")end if Ts._description then +table.insert(As,"-d '"..cs(mn(Ts)).."'")end +table.insert(vs,table.concat(As," "))end for Is,Ns in ipairs(self._commands)do +Ns:_fish_complete_help(vs,bs)end end function +pt:get_fish_complete()self._basename=un(self._name)assert(self:_is_shell_safe())local +Ss={}if#self._commands>0 then +table.insert(Ss,([[ +function __fish_%s_print_command + set -l cmdline (commandline -poc) + set -l cmd]]):format(self._basename))self:_fish_get_cmd(Ss,4)table.insert(Ss,([[ + echo "$cmd" +end + +function __fish_%s_using_command + test (__fish_%s_print_command) = "$argv" + and return 0 + or return 1 +end + +function __fish_%s_seen_command + string match -q "$argv*" (__fish_%s_print_command) + and return 0 + or return 1 +end]]):format(self._basename,self._basename,self._basename,self._basename))end +self:_fish_complete_help(Ss,self._basename)return +table.concat(Ss,"\n").."\n"end local function Hs(Rs,Ds)local Ls={}local Us +local Cs={}for Ms in pairs(Rs)do if type(Ms)=="string"then for Fs=1,#Ms do +Us=Ms:sub(1,Fs-1)..Ms:sub(Fs+1)if not Ls[Us]then Ls[Us]={}end +table.insert(Ls[Us],Ms)end end end for Ws=1,#Ds+1 do +Us=Ds:sub(1,Ws-1)..Ds:sub(Ws+1)if Rs[Us]then Cs[Us]=true elseif Ls[Us]then for +Ys,Ps in ipairs(Ls[Us])do Cs[Ps]=true end end end local Vs=next(Cs)if Vs then +if next(Cs,Vs)then local Bs={}for Gs in pairs(Cs)do +table.insert(Bs,"'"..Gs.."'")end +table.sort(Bs)return"\nDid you mean one of these: "..table.concat(Bs," ").."?"else +return"\nDid you mean '"..Vs.."'?"end else return""end end local +Ks=n({invocations=0})function Ks:__call(Qs,Js)self.state=Qs +self.result=Qs.result self.element=Js self.target=Js._target or +Js:_get_default_target()self.action,self.result[self.target]=Js:_get_action()return +self end function Ks:error(Xs,...)self.state:error(Xs,...)end function +Ks:convert(Zs,eh)local th=self.element._convert if th then local ah,oh if +type(th)=="function"then ah,oh=th(Zs)elseif type(th[eh])=="function"then +ah,oh=th[eh](Zs)else ah=th[Zs]end if ah==nil then self:error(oh +and"%s"or"malformed argument '%s'",oh or Zs)end Zs=ah end return Zs end +function Ks:default(ih)return self.element._defmode:find(ih)and +self.element._default end local function nh(sh,hh,rh,dh)local lh=""if hh~=rh +then lh="at "..(dh and"most"or"least").." "end local uh=dh and rh or hh return +lh..tostring(uh).." "..sh..(uh==1 and""or"s")end function +Ks:set_name(ch)self.name=("%s '%s'"):format(ch and"option"or"argument",ch or +self.element._name)end function Ks:invoke()self.open=true self.overwrite=false +if self.invocations>=self.element._maxcount then if self.element._overwrite +then self.overwrite=true else local +mh=nh("time",self.element._mincount,self.element._maxcount,true)self:error("%s must be used %s",self.name,mh)end +else self.invocations=self.invocations+1 end self.args={}if +self.element._maxargs<=0 then self:close()end return self.open end function +Ks:check_choices(fh)if self.element._choices then for wh,yh in +ipairs(self.element._choices)do if fh==yh then return end end local +ph="'"..table.concat(self.element._choices,"', '").."'"local +vh=getmetatable(self.element)==gt self:error("%s%s must be one of %s",vh +and"argument for "or"",self.name,ph)end end function +Ks:pass(bh)self:check_choices(bh)bh=self:convert(bh,#self.args+1)table.insert(self.args,bh)if#self.args>=self.element._maxargs +then self:close()end return self.open end function +Ks:complete_invocation()while#self.args0 then +self:error("unknown command '%s'%s",Mh,Hs(self.commands,Mh))else +self:error("too many arguments")end else return Fh end end function +kh:check_mutexes(Wh)if self.element_to_mutexes[Wh.element]then for Yh,Ph in +ipairs(self.element_to_mutexes[Wh.element])do local +Vh=self.mutex_to_element_state[Ph]if Vh and Vh~=Wh then +self:error("%s can not be used together with %s",Wh.name,Vh.name)else +self.mutex_to_element_state[Ph]=Wh end end end end function +kh:invoke(Bh,Gh)self:close()Bh:set_name(Gh)self:check_mutexes(Bh,Gh)if +Bh:invoke()then self.option=Bh end end function kh:pass(Kh)if self.option then +if not self.option:pass(Kh)then self.option=nil end elseif self.argument then +self:check_mutexes(self.argument)if not self.argument:pass(Kh)then +self.argument_i=self.argument_i+1 +self.argument=self.arguments[self.argument_i]end else local +Qh=self:get_command(Kh)self.result[Qh._target or Qh._name]=true if +self.parser._command_target then +self.result[self.parser._command_target]=Qh._name end self:switch(Qh)end end +function kh:close()if self.option then self.option:close()self.option=nil end +end function kh:finalize()self:close()for Jh=self.argument_i,#self.arguments do +local Xh=self.arguments[Jh]if#Xh.args==0 and Xh:default("u")then +Xh:complete_invocation()else Xh:close()end end if self.parser._require_command +and#self.commands>0 then self:error("a command is required")end for Zh,er in +ipairs(self.options)do er.name=er.name +or("option '%s'"):format(er.element._name)if er.invocations==0 then if +er:default("u")then er:invoke()er:complete_invocation()er:close()end end local +tr=er.element._mincount if er.invocations1 +then hr=false if sr:sub(2,2)==rr then if#sr==2 then if self.options[sr]then +local dr=self:get_option(sr)self:invoke(dr,sr)else self:close()end +self.handle_options=false else local lr=sr:find"="if lr then local +ur=sr:sub(1,lr-1)local cr=self:get_option(ur)if cr.element._maxargs<=0 then +self:error("option '%s' does not take arguments",ur)end +self:invoke(cr,ur)self:pass(sr:sub(lr+1))else local +mr=self:get_option(sr)self:invoke(mr,sr)end end else for fr=2,#sr do local +wr=rr..sr:sub(fr,fr)local yr=self:get_option(wr)self:invoke(yr,wr)if fr~=#sr +and yr.element._maxargs>0 then self:pass(sr:sub(fr+1))break end end end end end +end if hr then self:pass(sr)end end self:finalize()return self.result end +function +pt:error(pr)io.stderr:write(("%s\n\nError: %s\n"):format(self:get_usage(),pr))error()end +local vr=rawget(_G,"arg")or{}function pt:_parse(br,gr)return +kh(self,gr):parse(br or vr)end function pt:parse(kr)return +self:_parse(kr,self.error)end local function qr(jr)return +tostring(jr).."\noriginal "..debug.traceback("",2):sub(2)end function +pt:pparse(xr)local zr local Er,Tr=xpcall(function()return +self:_parse(xr,function(Ar,Or)zr=Or error(Or,0)end)end,qr)if Er then return +true,Tr elseif not zr then error(Tr,0)else return false,zr end end local +Ir={}Ir.version="0.7.3"setmetatable(Ir,{__call=function(Nr,...)return +pt(vr[0]):add_help(true)(...)end})return +Ir \ No newline at end of file diff --git a/computer/28/lib/numberformatter.lua b/computer/28/lib/numberformatter.lua new file mode 100644 index 0000000..d11eb2a --- /dev/null +++ b/computer/28/lib/numberformatter.lua @@ -0,0 +1,84 @@ +--[[- Library for formatting numbers + @module numberformatter +]] + +--[[ numberformatter.lua +_ _ _ _ _ _ ___ ____ ____ +|\ | | | |\/| |__] |___ |__/ +| \| |__| | | |__] |___ | \ +____ ____ ____ _ _ ____ ___ ___ ____ ____ +|___ | | |__/ |\/| |__| | | |___ |__/ +| |__| | \ | | | | | | |___ | \ +]] + +local NumberFormatter = { + --- "Metadata" - Version + _VERSION = "1.1.0", + --- "Metadata" - Description + _DESCRIPTION = "Library for formatting numbers", + --- "Metadata" - Homepage / Url + _URL = "https://github.com/Commandcracker/YouCube", + --- "Metadata" - License + _LICENSE = "GPL-3.0" +} +--[[ + NumberFormatter.compact and NumberFormatter.abbreviate based on: + https://devforum.roblox.com/t/how-can-i-turn-a-number-to-a-shorter-number-i-dont-know-how-to-explain-click-to-understand-3/649496/3 +]] + +local Suffixes = { "k", "M", "B", "T", "qd", "Qn", "sx", "Sp", "O", "N", "de", "Ud", "DD", "tdD", "qdD", "QnD", "sxD", + "SpD", "OcD", "NvD", "Vgn", "UVg", "DVg", "TVg", "qtV", "QnV", "SeV", "SPG", "OVG", "NVG", "TGN", "UTG", "DTG", + "tsTG", "qtTG", "QnTG", "ssTG", "SpTG", "OcTG", "NoTG", "QdDR", "uQDR", "dQDR", "tQDR", "qdQDR", "QnQDR", "sxQDR", + "SpQDR", "OQDDr", "NQDDr", "qQGNT", "uQGNT", "dQGNT", "tQGNT", "qdQGNT", "QnQGNT", "sxQGNT", "SpQGNT", "OQQGNT", + "NQQGNT", "SXGNTL" } + +--[[- Format number by LDML's specification for [Compact Number Formats](http://unicode.org/reports/tr35/tr35-numbers.html#Compact_Number_Formats) + @tparam number number The number to format + @treturn string formatted number + @usage Example: + + local numberformatter = require("numberformatter") + print(numberformatter.compact(1000)) + + Output: `1k` +]] +function NumberFormatter.compact(number) + local Negative = number < 0 + number = math.abs(number) + + local Paired = false + for i in pairs(Suffixes) do + if not (number >= 10 ^ (3 * i)) then + number = number / 10 ^ (3 * (i - 1)) + local isComplex = string.find(tostring(number), ".") and string.sub(tostring(number), 4, 4) ~= "." + number = string.sub(tostring(number), 1, isComplex and 4 or 3) .. (Suffixes[i - 1] or "") + Paired = true + break + end + end + if not Paired then + local Rounded = math.floor(number) + number = tostring(Rounded) + end + if Negative then + return "-" .. number + end + return number -- returns 1.0k for example +end + +--[[- Format number - separate thousands by comma + @tparam number number The number to format + @treturn string formatted number + @usage Example: + + local numberformatter = require("numberformatter") + print(numberformatter.abbreviate(1000)) + + Output: `1,000` +]] +function NumberFormatter.abbreviate(number) + local left, num, right = string.match(number, '^([^%d]*%d)(%d*)(.-)$') + return left .. num:reverse():gsub('(%d%d%d)', '%1,'):reverse() .. right +end + +return NumberFormatter diff --git a/computer/28/lib/semver.lua b/computer/28/lib/semver.lua new file mode 100644 index 0000000..c512a9a --- /dev/null +++ b/computer/28/lib/semver.lua @@ -0,0 +1,68 @@ +local +e={_VERSION='1.2.1',_DESCRIPTION='semver for Lua',_URL='https://github.com/kikito/semver.lua',_LICENSE=[[ + MIT LICENSE + + Copyright (c) 2015 Enrique García Cota + + Permission is hereby granted, free of charge, to any person obtaining a + copy of tother software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and tother permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + ]]}local +function +t(a,o)assert(a>=0,o..' must be a valid positive number')assert(math.floor(a)==a,o..' must be an integer')end +local function i(n)return n and n~=''end local function s(h)h=h or""local +r,d={},0 h:gsub("([^%.]+)",function(l)d=d+1 r[d]=l end)return r end local +function u(c)local m,f=c:match("^(-[^+]+)(+.+)$")if not(m and f)then +m=c:match("^(-.+)$")f=c:match("^(+.+)$")end assert(m or +f,("The parameter %q must begin with + or - to denote a prerelease or a build"):format(c))return +m,f end local function w(y)if y then local +p=y:match("^-(%w[%.%w-]*)$")assert(p,("The prerelease %q is not a slash followed by alphanumerics, dots and slashes"):format(y))return +p end end local function v(b)if b then local +g=b:match("^%+(%w[%.%w-]*)$")assert(g,("The build %q is not a + sign followed by alphanumerics, dots and slashes"):format(b))return +g end end local function k(q)if not i(q)then return nil,nil end local +j,x=u(q)local z=w(j)local E=v(x)return z,E end local function T(A)local +O,I,N,S=A:match("^(%d+)%.?(%d*)%.?(%d*)(.-)$")assert(type(O)=='string',("Could not extract version number(s) from %q"):format(A))local +H,R,D=tonumber(O),tonumber(I),tonumber(N)local L,U=k(S)return H,R,D,L,U end +local function C(M,F)return M==F and 0 or M= 0.5 then return math.ceil(n) else return math.floor(n) end end + +local function floatToRawIntBits(f) + if f == 0 then return 0 + elseif f == -0 then return 0x80000000 + elseif f == math.huge then return 0x7F800000 + elseif f == -math.huge then return 0xFF800000 end + local m, e = math.frexp(f) + if e > 127 or e < -126 then error("number out of range", 3) end + e, m = e + 126, round((math.abs(m) - 0.5) * 0x1000000) + if m > 0x7FFFFF then e = e + 1 end + return bit32.bor(f < 0 and 0x80000000 or 0, bit32.lshift(bit32.band(e, 0xFF), 23), bit32.band(m, 0x7FFFFF)) +end + +local function doubleToRawLongBits(f) + if f == 0 then return 0, 0 + elseif f == -0 then return 0x80000000, 0 + elseif f == math.huge then return 0x7FF00000, 0 + elseif f == -math.huge then return 0xFFF00000, 0 end + local m, e = math.frexp(f) + if e > 1023 or e < -1022 then error("number out of range", 3) end + e, m = e + 1022, round((math.abs(m) - 0.5) * 0x20000000000000) + if m > 0xFFFFFFFFFFFFF then e = e + 1 end + return bit32.bor(f < 0 and 0x80000000 or 0, bit32.lshift(bit32.band(e, 0x7FF), 20), bit32.band(m / 0x100000000, 0xFFFFF)), bit32.band(m, 0xFFFFFFFF) +end + +local function intBitsToFloat(l) + if l == 0 then return 0 + elseif l == 0x80000000 then return -0 + elseif l == 0x7F800000 then return math.huge + elseif l == 0xFF800000 then return -math.huge end + local m, e = bit32.band(l, 0x7FFFFF), bit32.band(bit32.rshift(l, 23), 0xFF) + e, m = e - 126, m / 0x1000000 + 0.5 + local n = math.ldexp(m, e) + return bit32.btest(l, 0x80000000) and -n or n +end + +local function longBitsToDouble(lh, ll) + if lh == 0 and ll == 0 then return 0 + elseif lh == 0x80000000 and ll == 0 then return -0 + elseif lh == 0x7FF00000 and ll == 0 then return math.huge + elseif lh == 0xFFF00000 and ll == 0 then return -math.huge end + local m, e = bit32.band(lh, 0xFFFFF) * 0x100000000 + bit32.band(ll, 0xFFFFFFFF), bit32.band(bit32.rshift(lh, 20), 0x7FF) + e, m = e - 1022, m / 0x20000000000000 + 0.5 + local n = math.ldexp(m, e) + return bit32.btest(lh, 0x80000000) and -n or n +end + +local function packint(num, size, output, offset, alignment, endianness, signed) + local total_size = 0 + if offset % math.min(size, alignment) ~= 0 and alignment > 1 then + local i = 0 + while offset % math.min(size, alignment) ~= 0 and i < alignment do + output[offset] = 0 + offset = offset + 1 + total_size = total_size + 1 + i = i + 1 + end + end + if endianness == ByteOrder.BIG_ENDIAN then + local added_padding = 0 + if size > 8 then for i = 0, size - 9 do + output[offset + i] = (signed and num >= 2^(size * 8 - 1) ~= 0) and 0xFF or 0 + added_padding = added_padding + 1 + total_size = total_size + 1 + end end + for i = added_padding, size - 1 do + output[offset + i] = bit32.band(bit32.rshift(num, ((size - i - 1) * 8)), 0xFF) + total_size = total_size + 1 + end + else + for i = 0, math.min(size, 8) - 1 do + output[offset + i] = num / 2^(i * 8) % 256 + total_size = total_size + 1 + end + for i = 8, size - 1 do + output[offset + i] = (signed and num >= 2^(size * 8 - 1) ~= 0) and 0xFF or 0 + total_size = total_size + 1 + end + end + return total_size +end + +local function unpackint(str, offset, size, endianness, alignment, signed) + local result, rsize = 0, 0 + if offset % math.min(size, alignment) ~= 0 and alignment > 1 then + for i = 0, alignment - 1 do + if offset % math.min(size, alignment) == 0 then break end + offset = offset + 1 + rsize = rsize + 1 + end + end + for i = 0, size - 1 do + result = result + str:byte(offset + i) * 2^((endianness == ByteOrder.BIG_ENDIAN and size - i - 1 or i) * 8) + rsize = rsize + 1 + end + if (signed and result >= 2^(size * 8 - 1)) then result = result - 2^(size * 8) end + return result, rsize +end + +local function packoptsize(opt, alignment) + local retval = packoptsize_tbl[opt] or 0 + if (alignment > 1 and retval % alignment ~= 0) then retval = retval + (alignment - (retval % alignment)) end + return retval +end + +--[[ + * string.pack (fmt, v1, v2, ...) + * + * Returns a binary string containing the values v1, v2, etc. + * serialized in binary form (packed) according to the format string fmt. + ]] +local function pack(...) + local fmt = expect(1, ..., "string") + local endianness = ByteOrder.LITTLE_ENDIAN + local alignment = 1 + local pos = 1 + local argnum = 2 + local output = {} + local i = 1 + while i <= #fmt do + local c = fmt:sub(i, i) + i = i + 1 + if c == '=' or c == '<' then + endianness = ByteOrder.LITTLE_ENDIAN + elseif c == '>' then + endianness = ByteOrder.BIG_ENDIAN + elseif c == '!' then + local size = -1 + while (i <= #fmt and fmt:sub(i, i):match("%d")) do + if (size >= 0xFFFFFFFF / 10) then error("bad argument #1 to 'pack' (invalid format)", 2) end + size = (math.max(size, 0) * 10) + tonumber(fmt:sub(i, i)) + i = i + 1 + end + if (size > 16 or size == 0) then error(string.format("integral size (%d) out of limits [1,16]", size), 2) + elseif (size == -1) then alignment = 4 + else alignment = size end + elseif isint[c] then + local num = expect(argnum, select(argnum, ...), "number") + argnum = argnum + 1 + if (num >= math.pow(2, (packoptsize(c, 0) * 8 - (c:match("%l") and 1 or 0))) or + num < (c:match("%l") and -math.pow(2, (packoptsize(c, 0) * 8 - 1)) or 0)) then + error(string.format("bad argument #%d to 'pack' (integer overflow)", argnum - 1), 2) + end + pos = pos + packint(num, packoptsize(c, 0), output, pos, alignment, endianness, false) + elseif c:lower() == 'i' then + local signed = c == 'i' + local size = -1 + while i <= #fmt and fmt:sub(i, i):match("%d") do + if (size >= 0xFFFFFFFF / 10) then error("bad argument #1 to 'pack' (invalid format)", 2) end + size = (math.max(size, 0) * 10) + tonumber(fmt:sub(i, i)) + i = i + 1 + end + if (size > 16 or size == 0) then + error(string.format("integral size (%d) out of limits [1,16]", size), 2) + elseif (alignment > 1 and (size ~= 1 and size ~= 2 and size ~= 4 and size ~= 8 and size ~= 16)) then + error("bad argument #1 to 'pack' (format asks for alignment not power of 2)", 2) + elseif (size == -1) then size = 4 end + local num = expect(argnum, select(argnum, ...), "number") + argnum = argnum + 1 + if (num >= math.pow(2, (size * 8 - (c:match("%l") and 1 or 0))) or + num < (c:match("%l") and -math.pow(2, (size * 8 - 1)) or 0)) then + error(string.format("bad argument #%d to 'pack' (integer overflow)", argnum - 1), 2) + end + pos = pos + packint(num, size, output, pos, alignment, endianness, signed) + elseif c == 'f' then + local f = expect(argnum, select(argnum, ...), "number") + argnum = argnum + 1 + local l = floatToRawIntBits(f) + if (pos % math.min(4, alignment) ~= 0 and alignment > 1) then + for j = 0, alignment - 1 do + if pos % math.min(4, alignment) == 0 then break end + output[pos] = 0 + pos = pos + 1 + end + end + for j = 0, 3 do output[pos + (endianness == ByteOrder.BIG_ENDIAN and 3 - j or j)] = bit32.band(bit32.rshift(l, (j * 8)), 0xFF) end + pos = pos + 4 + elseif c == 'd' or c == 'n' then + local f = expect(argnum, select(argnum, ...), "number") + argnum = argnum + 1 + local lh, ll = doubleToRawLongBits(f) + if (pos % math.min(8, alignment) ~= 0 and alignment > 1) then + for j = 0, alignment - 1 do + if pos % math.min(8, alignment) == 0 then break end + output[pos] = 0 + pos = pos + 1 + end + end + for j = 0, 3 do output[pos + (endianness == ByteOrder.BIG_ENDIAN and 7 - j or j)] = bit32.band(bit32.rshift(ll, (j * 8)), 0xFF) end + for j = 4, 7 do output[pos + (endianness == ByteOrder.BIG_ENDIAN and 7 - j or j)] = bit32.band(bit32.rshift(lh, ((j - 4) * 8)), 0xFF) end + pos = pos + 8 + elseif c == 'c' then + local size = 0 + if (i > #fmt or not fmt:sub(i, i):match("%d")) then + error("missing size for format option 'c'", 2) + end + while (i <= #fmt and fmt:sub(i, i):match("%d")) do + if (size >= 0xFFFFFFFF / 10) then error("bad argument #1 to 'pack' (invalid format)", 2) end + size = (size * 10) + tonumber(fmt:sub(i, i)) + i = i + 1 + end + if (pos + size < pos or pos + size > 0xFFFFFFFF) then error("bad argument #1 to 'pack' (format result too large)", 2) end + local str = expect(argnum, select(argnum, ...), "string") + argnum = argnum + 1 + if (#str > size) then error(string.format("bad argument #%d to 'pack' (string longer than given size)", argnum - 1), 2) end + if size > 0 then + for j = 0, size - 1 do output[pos+j] = str:byte(j + 1) or 0 end + pos = pos + size + end + elseif c == 'z' then + local str = expect(argnum, select(argnum, ...), "string") + argnum = argnum + 1 + for b in str:gmatch "." do if (b == '\0') then error(string.format("bad argument #%d to 'pack' (string contains zeros)", argnum - 1), 2) end end + for j = 0, #str - 1 do output[pos+j] = str:byte(j + 1) end + output[pos + #str] = 0 + pos = pos + #str + 1 + elseif c == 's' then + local size = 0 + while (i <= #fmt and fmt:sub(i, i):match("%d")) do + if (size >= 0xFFFFFFFF / 10) then error("bad argument #1 to 'pack' (invalid format)", 2) end + size = (size * 10) + tonumber(fmt:sub(i, i)) + i = i + 1 + end + if (size > 16) then + error(string.format("integral size (%d) out of limits [1,16]", size), 2) + elseif (size == 0) then size = 4 end + local str = expect(argnum, select(argnum, ...), "string") + argnum = argnum + 1 + if (#str >= math.pow(2, (size * 8))) then + error(string.format("bad argument #%d to 'pack' (string length does not fit in given size)", argnum - 1), 2) + end + packint(#str, size, output, pos, 1, endianness, false) + for j = size, #str + size - 1 do output[pos+j] = str:byte(j - size + 1) or 0 end + pos = pos + #str + size + elseif c == 'x' then + output[pos] = 0 + pos = pos + 1 + elseif c == 'X' then + if (i >= #fmt) then error("invalid next option for option 'X'", 2) end + local size = 0 + local c = fmt:sub(i, i) + i = i + 1 + if c:lower() == 'i' then + while i <= #fmt and fmt:sub(i, i):match("%d") do + if (size >= 0xFFFFFFFF / 10) then error("bad argument #1 to 'pack' (invalid format)", 2) end + size = (size * 10) + tonumber(fmt:sub(i, i)) + i = i + 1 + end + if (size > 16 or size == 0) then + error(string.format("integral size (%d) out of limits [1,16]", size), 2) + end + else size = packoptsize(c, 0) end + if (size < 1) then error("invalid next option for option 'X'", 2) end + if (pos % math.min(size, alignment) ~= 0 and alignment > 1) then + for j = 1, alignment do + if pos % math.min(size, alignment) == 0 then break end + output[pos] = 0 + pos = pos + 1 + end + end + elseif c ~= ' ' then error(string.format("invalid format option '%s'", c), 2) end + end + return string.char(table.unpack(output)) +end + +--[[ + * string.packsize (fmt) + * + * Returns the size of a string resulting from string.pack with the given format. + * The format string cannot have the variable-length options 's' or 'z'. + ]] +local function packsize(fmt) + local pos = 0 + local alignment = 1 + local i = 1 + while i <= #fmt do + local c = fmt:sub(i, i) + i = i + 1 + if c == '!' then + local size = 0 + while i <= #fmt and fmt:sub(i, i):match("%d") do + if (size >= 0xFFFFFFFF / 10) then error("bad argument #1 to 'pack' (invalid format)", 2) end + size = (size * 10) + tonumber(fmt:sub(i, i)) + i = i + 1 + end + if (size > 16) then error(string.format("integral size (%d) out of limits [1,16]", size), 2) + elseif (size == 0) then alignment = 4 + else alignment = size end + elseif isint[c] then + local size = packoptsize(c, 0) + if (pos % math.min(size, alignment) ~= 0 and alignment > 1) then + for j = 1, alignment do + if pos % math.min(size, alignment) == 0 then break end + pos = pos + 1 + end + end + pos = pos + size + elseif c:lower() == 'i' then + local size = 0 + while i <= #fmt and fmt:sub(i, i):match("%d") do + if (size >= 0xFFFFFFFF / 10) then error("bad argument #1 to 'pack' (invalid format)", 2) end + size = (size * 10) + tonumber(fmt:sub(i, i)) + i = i + 1 + end + if (size > 16) then + error(string.format("integral size (%d) out of limits [1,16]", size)) + elseif (alignment > 1 and (size ~= 1 and size ~= 2 and size ~= 4 and size ~= 8 and size ~= 16)) then + error("bad argument #1 to 'pack' (format asks for alignment not power of 2)", 2) + elseif (size == 0) then size = 4 end + if (pos % math.min(size, alignment) ~= 0 and alignment > 1) then + for j = 1, alignment do + if pos % math.min(size, alignment) == 0 then break end + pos = pos + 1 + end + end + pos = pos + size + elseif c == 'f' then + if (pos % math.min(4, alignment) ~= 0 and alignment > 1) then + for j = 1, alignment do + if pos % math.min(4, alignment) == 0 then break end + pos = pos + 1 + end + end + pos = pos + 4 + elseif c == 'd' or c == 'n' then + if (pos % math.min(8, alignment) ~= 0 and alignment > 1) then + for j = 1, alignment do + if pos % math.min(8, alignment) == 0 then break end + pos = pos + 1 + end + end + pos = pos + 8 + elseif c == 'c' then + local size = 0 + if (i > #fmt or not fmt:sub(i, i):match("%d")) then + error("missing size for format option 'c'", 2) + end + while i <= #fmt and fmt:sub(i, i):match("%d") do + if (size >= 0xFFFFFFFF / 10) then error("bad argument #1 to 'pack' (invalid format)", 2) end + size = (size * 10) + tonumber(fmt:sub(i, i)) + i = i + 1 + end + if (pos + size < pos or pos + size > 0x7FFFFFFF) then error("bad argument #1 to 'packsize' (format result too large)", 2) end + pos = pos + size + elseif c == 'x' then + pos = pos + 1 + elseif c == 'X' then + if (i >= #fmt) then error("invalid next option for option 'X'", 2) end + local size = 0 + local c = fmt:sub(i, i) + i = i + 1 + if c:lower() == 'i' then + while i <= #fmt and fmt:sub(i, i):match("%d") do + if (size >= 0xFFFFFFFF / 10) then error("bad argument #1 to 'pack' (invalid format)", 2) end + size = (size * 10) + tonumber(fmt:sub(i, i)) + i = i + 1 + end + if (size > 16 or size == 0) then + error(string.format("integral size (%d) out of limits [1,16]", size), 2) + end + else size = packoptsize(c, 0) end + if (size < 1) then error("invalid next option for option 'X'", 2) end + if (pos % math.min(size, alignment) ~= 0 and alignment > 1) then + for j = 1, alignment do + if pos % math.min(size, alignment) == 0 then break end + pos = pos + 1 + end + end + elseif c == 's' or c == 'z' then error("bad argument #1 to 'packsize' (variable-length format)", 2) + elseif c ~= ' ' and c ~= '<' and c ~= '>' and c ~= '=' then error(string.format("invalid format option '%s'", c), 2) end + end + return pos +end + +--[[ + * string.unpack (fmt, s [, pos]) + * + * Returns the values packed in string s (see string.pack) according to the format string fmt. + * An optional pos marks where to start reading in s (default is 1). + * After the read values, this function also returns the index of the first unread byte in s. + ]] +local function unpack(fmt, str, pos) + expect(1, fmt, "string") + expect(2, str, "string") + expect(3, pos, "number", "nil") + if pos then + if (pos < 0) then pos = #str + pos + elseif (pos == 0) then error("bad argument #3 to 'unpack' (initial position out of string)", 2) end + if (pos > #str or pos < 0) then error("bad argument #3 to 'unpack' (initial position out of string)", 2) end + else pos = 1 end + local endianness = ByteOrder.LITTLE_ENDIAN + local alignment = 1 + local retval = {} + local i = 1 + while i <= #fmt do + local c = fmt:sub(i, i) + i = i + 1 + if c == '<' or c == '=' then + endianness = ByteOrder.LITTLE_ENDIAN + elseif c == '>' then + endianness = ByteOrder.BIG_ENDIAN + elseif c == '!' then + local size = 0 + while i <= #fmt and fmt:sub(i, i):match("%d") do + if (size >= 0xFFFFFFFF / 10) then error("bad argument #1 to 'pack' (invalid format)", 2) end + size = (size * 10) + tonumber(fmt:sub(i, i)) + i = i + 1 + end + if (size > 16) then + error(string.format("integral size (%d) out of limits [1,16]", size)) + elseif (size == 0) then alignment = 4 + else alignment = size end + elseif isint[c] then + if (pos + packoptsize(c, 0) > #str + 1) then error("data string too short", 2) end + local res, ressz = unpackint(str, pos, packoptsize(c, 0), endianness, alignment, c:match("%l") ~= nil) + retval[#retval+1] = res + pos = pos + ressz + elseif c:lower() == 'i' then + local signed = c == 'i' + local size = 0 + while (i <= #fmt and fmt:sub(i, i):match("%d")) do + if (size >= 0xFFFFFFFF / 10) then error("bad argument #1 to 'pack' (invalid format)", 2) end + size = (size * 10) + tonumber(fmt:sub(i, i)) + i = i + 1 + end + if (size > 16) then + error(string.format("integral size (%d) out of limits [1,16]", size), 2) + elseif (size > 8) then + error(string.format("%d-byte integer does not fit into Lua Integer", size), 2) + elseif (size == 0) then size = 4 end + if (pos + size > #str + 1) then error("data string too short", 2) end + local res, ressz = unpackint(str, pos, size, endianness, alignment, signed) + retval[#retval+1] = res + pos = pos + ressz + elseif c == 'f' then + if (pos % math.min(4, alignment) ~= 0 and alignment > 1) then + for j = 1, alignment do + if pos % math.min(4, alignment) == 0 then break end + pos = pos + 1 + end + end + if (pos + 4 > #str + 1) then error("data string too short", 2) end + local res = unpackint(str, pos, 4, endianness, alignment, false) + retval[#retval+1] = intBitsToFloat(res) + pos = pos + 4 + elseif c == 'd' or c == 'n' then + if (pos % math.min(8, alignment) ~= 0 and alignment > 1) then + for j = 1, alignment do + if pos % math.min(8, alignment) == 0 then break end + pos = pos + 1 + end + end + if (pos + 8 > #str + 1) then error("data string too short", 2) end + local lh, ll = 0, 0 + for j = 0, 3 do lh = bit32.bor(lh, bit32.lshift((str:byte(pos + j)), ((endianness == ByteOrder.BIG_ENDIAN and 3 - j or j) * 8))) end + for j = 0, 3 do ll = bit32.bor(ll, bit32.lshift((str:byte(pos + j + 4)), ((endianness == ByteOrder.BIG_ENDIAN and 3 - j or j) * 8))) end + if endianness == ByteOrder.LITTLE_ENDIAN then lh, ll = ll, lh end + retval[#retval+1] = longBitsToDouble(lh, ll) + pos = pos + 8 + elseif c == 'c' then + local size = 0 + if (i > #fmt or not fmt:sub(i, i):match("%d")) then + error("missing size for format option 'c'", 2) + end + while i <= #fmt and fmt:sub(i, i):match("%d") do + if (size >= 0xFFFFFFFF / 10) then error("bad argument #1 to 'pack' (invalid format)") end + size = (size * 10) + tonumber(fmt:sub(i, i)) + i = i + 1 + end + if (pos + size > #str + 1) then error("data string too short", 2) end + retval[#retval+1] = str:sub(pos, pos + size - 1) + pos = pos + size + elseif c == 'z' then + local size = 0 + while (str:byte(pos + size) ~= 0) do + size = size + 1 + if (pos + size > #str) then error("unfinished string for format 'z'", 2) end + end + retval[#retval+1] = str:sub(pos, pos + size - 1) + pos = pos + size + 1 + elseif c == 's' then + local size = 0 + while i <= #fmt and fmt:sub(i, i):match("%d") do + if (size >= 0xFFFFFFFF / 10) then error("bad argument #1 to 'pack' (invalid format)", 2) end + size = (size * 10) + tonumber(fmt:sub(i, i)) + i = i + 1 + end + if (size > 16) then + error(string.format("integral size (%d) out of limits [1,16]", size), 2) + elseif (size == 0) then size = 4 end + if (pos + size > #str + 1) then error("data string too short", 2) end + local num, numsz = unpackint(str, pos, size, endianness, alignment, false) + pos = pos + numsz + if (pos + num > #str + 1) then error("data string too short", 2) end + retval[#retval+1] = str:sub(pos, pos + num - 1) + pos = pos + num + elseif c == 'x' then + pos = pos + 1 + elseif c == 'X' then + if (i >= #fmt) then error("invalid next option for option 'X'", 2) end + local size = 0 + local c = fmt:sub(i, i) + i = i + 1 + if c:lower() == 'i' then + while i <= #fmt and fmt:sub(i, i):match("%d") do + if (size >= 0xFFFFFFFF / 10) then error("bad argument #1 to 'pack' (invalid format)", 2) end + size = (size * 10) + tonumber(fmt:sub(i, i)) + i = i + 1 + end + if (size > 16 or size == 0) then + error(string.format("integral size (%d) out of limits [1,16]", size), 2) + elseif (size == -1) then size = 4 end + else size = packoptsize(c, 0) end + if (size < 1) then error("invalid next option for option 'X'", 2) end + if (pos % math.min(size, alignment) ~= 0 and alignment > 1) then + for j = 1, alignment do + if pos % math.min(size, alignment) == 0 then break end + pos = pos + 1 + end + end + elseif c ~= ' ' then error(string.format("invalid format option '%s'", c), 2) end + end + retval[#retval+1] = pos + return table.unpack(retval) +end + +return { + pack = pack, + packsize = packsize, + unpack = unpack +} \ No newline at end of file diff --git a/computer/28/lib/youcubeapi.lua b/computer/28/lib/youcubeapi.lua new file mode 100644 index 0000000..9a5b0c1 --- /dev/null +++ b/computer/28/lib/youcubeapi.lua @@ -0,0 +1,637 @@ +--[[- Lua library for accessing [YouCub's API](https://commandcracker.github.io/YouCube/) + @module youcubeapi +]] + +--[[ youcubeapi.lua +_ _ ____ _ _ ____ _ _ ___ ____ ____ ___ _ + \_/ | | | | | | | |__] |___ |__| |__] | + | |__| |__| |___ |__| |__] |___ | | | | +]] + +--[[- "wrapper" for accessing [YouCub's API](https://commandcracker.github.io/YouCube/) + @type API + @usage Example: + + local youcubeapi = require("youcubeapi") + local api = youcubeapi.API.new() + api:detect_bestest_server() + api:request_media(url) + local data = api.websocket.receive() +]] +local API = {} + +--- Create's a new API instance. +-- @param websocket [Websocket](https://tweaked.cc/module/http.html#ty:Websocket) The websocket. +-- @treturn API instance +function API.new(websocket) + return setmetatable({ + websocket = websocket, + }, { __index = API }) +end + +-- Look at the [Documentation](https://commandcracker.github.io/YouCube/) for moor information +-- Contact the server owner on Discord, when the server is down +local servers = { + "ws://127.0.0.1:5000", -- Your server! + "wss://us-ky.youcube.knijn.one", -- By EmmaKnijn + "wss://youcube.knijn.one", -- By EmmaKnijn + "wss://youcube.onrender.com", -- By Commandcracker#8528 +} + +if settings then + local server = settings.get("youcube.server") + if server then + table.insert(servers, 1, server) + end +end + +local function websocket_with_timeout(_url, _headers, _timeout) + if http.websocketAsync then + local websocket, websocket_error = http.websocketAsync(_url, _headers) + if not websocket then + return false, websocket_error + end + + local timerID = os.startTimer(_timeout) + + while true do + local event, param1, param2 = os.pullEvent() + + -- TODO: Close web-socket when the connection succeeds after the timeout + if event == "websocket_success" and param1 == _url then + return param2 + elseif event == "websocket_failure" and param1 == _url then + return false, param2 + elseif event == "timer" and param1 == timerID then + return false, "Timeout" + end + end + end + + -- use websocket without timeout + -- when the CC version dos not support websocketAsync + return http.websocket(_url, _headers) +end + +--- Connects to a YouCub Server +function API:detect_bestest_server(_server, _verbose) + if _server then + table.insert(servers, 1, _server) + end + + for i = 1, #servers do + local server = servers[i] + local ok, err = http.checkURL(server:gsub("^ws://", "http://"):gsub("^wss://", "https://")) + + if ok then + if _verbose then + print("Trying to connect to:", server) + end + local websocket, websocket_error = websocket_with_timeout(server, nil, 5) + + if websocket ~= false then + term.write("Using the YouCube server: ") + term.setTextColor(colors.blue) + print(server) + term.setTextColor(colors.white) + self.websocket = websocket + break + elseif i == #servers then + error(websocket_error) + elseif _verbose then + print(websocket_error) + end + elseif i == #servers then + error(err) + elseif _verbose then + print(err) + end + end +end + +--- Receive data from The YouCub Server +-- @tparam string filter action filter +-- @treturn table retval data +function API:receive(filter) + local status, retval = pcall(self.websocket.receive) + if not status then + error("Lost connection to server\n" .. retval) + end + + if retval == nil then + error("Received empty message or max message size exceeded") + end + + local data, err = textutils.unserialiseJSON(retval) + + if data == nil then + error("Failed to parse message\n" .. err) + end + + if filter then + --if type(filter) == "table" then + -- if not filter[data.action] then + -- return self:receive(filter) + -- end + --else + if data.action ~= filter then + return self:receive(filter) + end + end + + return data +end + +--- Send data to The YouCub Server +-- @tparam table data data to send +function API:send(data) + local status, retval = pcall(self.websocket.send, textutils.serialiseJSON(data)) + if not status then + error("Lost connection to server\n" .. retval) + end +end + +--[[- [Base64](https://wikipedia.org/wiki/Base64) functions + @type Base64 +]] +local Base64 = {} + +local b64str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" + +-- based on https://github.com/MCJack123/sanjuuni/blob/c64f8725a9f24dec656819923457717dfb964515/raw-player.lua +--- Decode base64 string +-- @tparam string str base64 string +-- @treturn string string decoded string +function Base64.decode(str) + local retval = "" + for s in str:gmatch("....") do + if s:sub(3, 4) == "==" then + retval = retval + .. string.char( + bit32.bor( + bit32.lshift(b64str:find(s:sub(1, 1)) - 1, 2), + bit32.rshift(b64str:find(s:sub(2, 2)) - 1, 4) + ) + ) + elseif s:sub(4, 4) == "=" then + local n = (b64str:find(s:sub(1, 1)) - 1) * 4096 + + (b64str:find(s:sub(2, 2)) - 1) * 64 + + (b64str:find(s:sub(3, 3)) - 1) + retval = retval .. string.char(bit32.extract(n, 10, 8)) .. string.char(bit32.extract(n, 2, 8)) + else + local n = (b64str:find(s:sub(1, 1)) - 1) * 262144 + + (b64str:find(s:sub(2, 2)) - 1) * 4096 + + (b64str:find(s:sub(3, 3)) - 1) * 64 + + (b64str:find(s:sub(4, 4)) - 1) + retval = retval + .. string.char(bit32.extract(n, 16, 8)) + .. string.char(bit32.extract(n, 8, 8)) + .. string.char(bit32.extract(n, 0, 8)) + end + end + return retval +end + +--- Request a `16 * 1024` bit chunk +-- @tparam number chunkindex The chunkindex +-- @tparam string id Media id +-- @treturn bytes chunk `16 * 1024` bit chunk +function API:get_chunk(chunkindex, id) + self:send({ + ["action"] = "get_chunk", + ["chunkindex"] = chunkindex, + ["id"] = id, + }) + return Base64.decode(self:receive("chunk").chunk) +end + +--- Get 32vid +-- @tparam number line The line to return +-- @tparam string id Media id +-- @tparam number width Video width +-- @tparam number height Video height +-- @treturn string line one line of the given 32vid +function API:get_vid(tracker, id, width, height) + self:send({ + ["action"] = "get_vid", + ["tracker"] = tracker, + ["id"] = id, + ["width"] = width * 2, + ["height"] = height * 3, + }) + return self:receive("vid") +end + +--- Request media +-- @tparam string url Url or Search Term +--@treturn table json response +function API:request_media(url, width, height) + local request = { + ["action"] = "request_media", + ["url"] = url, + } + if width and height then + request.width = width * 2 + request.height = height * 3 + end + self:send(request) + --return self:receive({ ["media"] = true, ["status"] = true }) +end + +--- Handshake - get Server capabilities and version +--@treturn table json response +function API:handshake() + self:send({ + ["action"] = "handshake", + }) + return self:receive("handshake") +end + +--[[- Abstraction for Audio Devices + @type AudioDevice +]] +local AudioDevice = {} + +--- Create's a new AudioDevice instance. +-- @tparam table object Base values +-- @treturn AudioDevice instance +function AudioDevice.new(object) + -- @type AudioDevice + local self = object or {} + + function self:validate() end + + function self:setLabel(lable) end + + function self:write(chunk) end + + function self:play() end + + function self:reset() end + + function self:setVolume(volume) end + + return self +end + +--[[- @{AudioDevice} from a Speaker + @type Speaker + @usage Example: + + local youcubeapi = require("youcubeapi") + local speaker = peripheral.find("speaker") + local audiodevice = youcubeapi.Speaker.new(speaker) +]] +local Speaker = {} + +local decoder +local status, dfpwm = pcall(require, "cc.audio.dfpwm") + +if status then + decoder = dfpwm.make_decoder() +end + +--- Create's a new Tape instance. +-- @tparam speaker speaker The speaker +-- @treturn AudioDevice|Speaker instance +function Speaker.new(speaker) + local self = AudioDevice.new({ speaker = speaker }) + + function self:validate() + if not decoder then + return "This ComputerCraft version dos not support DFPWM" + end + end + + function self:setVolume(volume) + self.volume = volume + end + + function self:write(chunk) + local buffer = decoder(chunk) + while not self.speaker.playAudio(buffer, self.volume) do + os.pullEvent("speaker_audio_empty") + end + end + + return self +end + +--[[- @{AudioDevice} from a [Computronics tape_drive](https://wiki.vexatos.com/wiki:computronics:tape) + @type Tape + @usage Example: + + local youcubeapi = require("youcubeapi") + local tape_drive = peripheral.find("tape_drive") + local audiodevice = youcubeapi.Tape.new(tape_drive) +]] +local Tape = {} + +--- Create's a new Tape instance. +-- @tparam tape tape The tape_drive +-- @treturn AudioDevice|Tape instance +function Tape.new(tape) + local self = AudioDevice.new({ tape = tape }) + + function self:validate() + if not self.tape.isReady() then + return "You need to insert a tape" + end + end + + function self:setVolume(volume) + if volume then + self.tape.setVolume(volume) + end + end + + function self:play(chunk) + self.tape.seek(-self.tape.getSize()) + self.tape.play() + end + + function self:write(chunk) + self.tape.write(chunk) + end + + function self:setLabel(lable) + self.tape.setLabel(lable) + end + + function self:reset() + -- based on https://github.com/Vexatos/Computronics/blob/b0ade53cab10529dbe91ebabfa882d1b4b21fa90/src/main/resources/assets/computronics/lua/peripheral/tape_drive/programs/tape_drive/tape#L109-L123 + local size = self.tape.getSize() + self.tape.stop() + self.tape.seek(-size) + self.tape.stop() + self.tape.seek(-90000) + local s = string.rep(string.char(170), 8192) + for i = 1, size + 8191, 8192 do + self.tape.write(s) + end + self.tape.seek(-size) + self.tape.seek(-90000) + end + + return self +end + +--[[- Abstract object for filling a @{Buffer} + @type Filler +]] +local Filler = {} + +--- Create's a new Filler instance. +-- @treturn Filler instance +function Filler.new() + local self = {} + function self:next() end + + return self +end + +--[[- @{Filler} for Audio + @type AudioFiller +]] +local AudioFiller = {} + +--- Create's a new AudioFiller instance. +-- @tparam API youcubeapi API object +-- @tparam string id Media id +-- @treturn AudioFiller|Filler instance +function AudioFiller.new(youcubeapi, id) + local self = { + id = id, + chunkindex = 0, + youcubeapi = youcubeapi, + } + + function self:next() + local response = self.youcubeapi:get_chunk(self.chunkindex, self.id) + self.chunkindex = self.chunkindex + 1 + return response + end + + return self +end + +--[[- @{Filler} for Video + @type VideoFiller +]] +local VideoFiller = {} + +--- Create's a new VideoFiller instance. +-- @tparam API youcubeapi API object +-- @tparam string id Media id +-- @tparam number width Video width +-- @tparam number height Video height +-- @treturn VideoFiller|Filler instance +function VideoFiller.new(youcubeapi, id, width, height) + local self = { + id = id, + width = width, + height = height, + tracker = 0, + youcubeapi = youcubeapi, + } + + function self:next() + local response = self.youcubeapi:get_vid(self.tracker, self.id, self.width, self.height) + for i = 1, #response.lines do + self.tracker = self.tracker + #response.lines[i] + 1 + end + return response.lines + end + + return self +end + +--[[- Buffers Data + @type Buffer +]] +local Buffer = {} + +--- Create's a new Buffer instance. +-- @tparam Filler filler filler instance +-- @tparam number size buffer limit +-- @treturn Buffer instance +function Buffer.new(filler, size) + local self = { + filler = filler, + size = size, + } + self.buffer = {} + + function self:next() + while #self.buffer == 0 do + os.pullEvent() + end -- Wait until next is available + local next = self.buffer[1] + table.remove(self.buffer, 1) + return next + end + + function self:fill() + if #self.buffer < self.size then + local next = filler:next() + if type(next) == "table" then + for i = 1, #next do + self.buffer[#self.buffer + 1] = next[i] + end + else + self.buffer[#self.buffer + 1] = next + end + return true + end + return false + end + + return self +end + +local currnt_palette = {} + +for i = 0, 15 do + local r, g, b = term.getPaletteColour(2 ^ i) + currnt_palette[i] = { r, g, b } +end + +local function reset_term() + for i = 0, 15 do + term.setPaletteColor(2 ^ i, currnt_palette[i][1], currnt_palette[i][2], currnt_palette[i][3]) + end + term.setBackgroundColor(colors.black) + term.setTextColor(colors.white) + term.clear() + term.setCursorPos(1, 1) +end + +--[[- Create's a new Buffer instance. + + Based on [sanjuuni/raw-player.lua](https://github.com/MCJack123/sanjuuni/blob/c64f8725a9f24dec656819923457717dfb964515/raw-player.lua) + and [sanjuuni/websocket-player.lua](https://github.com/MCJack123/sanjuuni/blob/30dcabb4b56f1eb32c88e1bce384b0898367ebda/websocket-player.lua) + @tparam Buffer buffer filled with frames +]] +local function play_vid(buffer, force_fps, string_unpack) + if not string_unpack then + string_unpack = string.unpack + end + local Fwidth, Fheight = term.getSize() + local tracker = 0 + + if buffer:next() ~= "32Vid 1.1" then + error("Unsupported file") + end + + local fps = tonumber(buffer:next()) + if force_fps then + fps = force_fps + end + + -- Adjust buffer size + buffer.size = math.ceil(fps) * 2 + + local first, second = buffer:next(), buffer:next() + + if second == "" or second == nil then + fps = 0 + end + term.clear() + + local start = os.epoch("utc") + local frame_count = 0 + while true do + frame_count = frame_count + 1 + local frame + if first then + frame, first = first, nil + elseif second then + frame, second = second, nil + else + frame = buffer:next() + end + if frame == "" or frame == nil then + break + end + local mode = frame:match("^!CP([CD])") + if not mode then + error("Invalid file") + end + local b64data + if mode == "C" then + local len = tonumber(frame:sub(5, 8), 16) + b64data = frame:sub(9, len + 8) + else + local len = tonumber(frame:sub(5, 16), 16) + b64data = frame:sub(17, len + 16) + end + local data = Base64.decode(b64data) + -- TODO: maybe verify checksums? + assert(data:sub(1, 4) == "\0\0\0\0" and data:sub(9, 16) == "\0\0\0\0\0\0\0\0", "Invalid file") + local width, height = string_unpack("HH", data, 5) + local c, n, pos = string_unpack("c1B", data, 17) + local text = {} + for y = 1, height do + text[y] = "" + for x = 1, width do + text[y] = text[y] .. c + n = n - 1 + if n == 0 then + c, n, pos = string_unpack("c1B", data, pos) + end + end + end + c = c:byte() + for y = 1, height do + local fg, bg = "", "" + for x = 1, width do + fg, bg = fg .. ("%x"):format(bit32.band(c, 0x0F)), bg .. ("%x"):format(bit32.rshift(c, 4)) + n = n - 1 + if n == 0 then + c, n, pos = string_unpack("BB", data, pos) + end + end + term.setCursorPos(1, y) + term.blit(text[y], fg, bg) + end + pos = pos - 2 + local r, g, b + for i = 0, 15 do + r, g, b, pos = string_unpack("BBB", data, pos) + term.setPaletteColor(2 ^ i, r / 255, g / 255, b / 255) + end + if fps == 0 then + read() + break + else + while os.epoch("utc") < start + (frame_count + 1) / fps * 1000 do + sleep(1 / fps) + end + end + end + reset_term() +end + +return { + --- "Metadata" - [YouCube API](https://commandcracker.github.io/YouCube/) Version + _API_VERSION = "0.0.0-poc.1.0.0", + --- "Metadata" - Library Version + _VERSION = "0.0.0-poc.1.4.2", + --- "Metadata" - Description + _DESCRIPTION = "Library for accessing YouCub's API", + --- "Metadata" - Homepage / Url + _URL = "https://github.com/Commandcracker/YouCube", + --- "Metadata" - License + _LICENSE = "GPL-3.0", + API = API, + AudioDevice = AudioDevice, + Speaker = Speaker, + Tape = Tape, + Base64 = Base64, + Filler = Filler, + AudioFiller = AudioFiller, + VideoFiller = VideoFiller, + Buffer = Buffer, + play_vid = play_vid, + reset_term = reset_term, +} diff --git a/computer/28/startup.lua b/computer/28/startup.lua new file mode 100644 index 0000000..8cc70de --- /dev/null +++ b/computer/28/startup.lua @@ -0,0 +1,19 @@ +rednet.open("right") + + +while true do + sender,message = rednet.receive("elevator") + if sender == 27 then + rednet.send( + sender, + { + pcall( + peripheral.call, + unpack(message) + ) + }, + "elevator" + ) + print(unpack(message),"called") + end +end diff --git a/computer/28/youcube.lua b/computer/28/youcube.lua new file mode 100644 index 0000000..5dbc5fc --- /dev/null +++ b/computer/28/youcube.lua @@ -0,0 +1,604 @@ +--[[ +_ _ ____ _ _ ____ _ _ ___ ____ + \_/ | | | | | | | |__] |___ + | |__| |__| |___ |__| |__] |___ + +Github Repository: https://github.com/Commandcracker/YouCube +License: GPL-3.0 +]] + +local _VERSION = "0.0.0-poc.1.1.2" + +-- Libraries - OpenLibrarieLoader v1.0.1 -- + +--TODO: Optional libs: +-- For something like a JSON lib that is only needed for older CC Versions or +-- optional logging.lua support + +local function is_lib(libs, lib) + for i = 1, #libs do + local value = libs[i] + if value == lib or value .. ".lua" == lib then + return true, value + end + end + return false +end + +local libs = { "youcubeapi", "numberformatter", "semver", "argparse", "string_pack" } +local lib_paths = { ".", "./lib", "./apis", "./modules", "/", "/lib", "/apis", "/modules" } + +-- LevelOS Support +if _G.lOS then + lib_paths[#lib_paths + 1] = "/Program_Files/YouCube/lib" +end + +local function load_lib(lib) + if require then + return require(lib:gsub(".lua", "")) + end + return dofile(lib) +end + +for i_path = 1, #lib_paths do + local path = lib_paths[i_path] + if fs.exists(path) then + local files = fs.list(path) + for i_file = 1, #files do + local found, lib = is_lib(libs, files[i_file]) + if found and lib ~= nil and libs[lib] == nil then + libs[lib] = load_lib(path .. "/" .. files[i_file]) + end + end + end +end + +for i = 1, #libs do + local lib = libs[i] + if libs[lib] == nil then + error(('Library "%s" not found.'):format(lib)) + end +end + +-- args -- + +local function get_program_name() + if arg then + return arg[0] + end + return fs.getName(shell.getRunningProgram()):gsub("[\\.].*$", "") +end + +-- stylua: ignore start + +local parser = libs.argparse { + help_max_width = ({ term.getSize() })[1], + name = get_program_name() +} + :description "Official YouCube client for accessing media from services like YouTube" + +parser:argument "URL" + :args "*" + :description "URL or search term." + +parser:flag "-v" "--verbose" + :description "Enables verbose output." + :target "verbose" + :action "store_true" + +parser:option "-V" "--volume" + :description "Sets the volume of the audio. A value from 0-100" + :target "volume" + +parser:option "-s" "--server" + :description "The server that YC should use." + :target "server" + :args(1) + +parser:flag "--nv" "--no-video" + :description "Disables video." + :target "no_video" + :action "store_true" + +parser:flag "--na" "--no-audio" + :description "Disables audio." + :target "no_audio" + :action "store_true" + +parser:flag "--sh" "--shuffle" + :description "Shuffles audio before playing" + :target "shuffle" + :action "store_true" + +parser:flag "-l" "--loop" + :description "Loops the media." + :target "loop" + :action "store_true" + +parser:flag "--lp" "--loop-playlist" + :description "Loops the playlist." + :target "loop_playlist" + :action "store_true" + +parser:option "--fps" + :description "Force sanjuuni to use a specified frame rate" + :target "force_fps" + +-- stylua: ignore end + +local args = parser:parse({ ... }) + +if args.force_fps then + args.force_fps = tonumber(args.force_fps) +end + +if args.volume then + args.volume = tonumber(args.volume) + if args.volume == nil then + parser:error("Volume must be a number") + end + + if args.volume > 100 then + parser:error("Volume cant be over 100") + end + + if args.volume < 0 then + parser:error("Volume cant be below 0") + end + args.volume = args.volume / 100 +end + +if #args.URL > 0 then + args.URL = table.concat(args.URL, " ") +else + args.URL = nil +end + +if args.no_video and args.no_audio then + parser:error("Nothing will happen, when audio and video is disabled!") +end + +-- CraftOS-PC support -- + +if periphemu then + periphemu.create("top", "speaker") + -- Fuck the max websocket message police + config.set("http_max_websocket_message", 2 ^ 30) +end + +local function get_audiodevices() + local audiodevices = {} + + local speakers = { peripheral.find("speaker") } + for i = 1, #speakers do + audiodevices[#audiodevices + 1] = libs.youcubeapi.Speaker.new(speakers[i]) + end + + local tapes = { peripheral.find("tape_drive") } + for i = 1, #tapes do + audiodevices[#audiodevices + 1] = libs.youcubeapi.Tape.new(tapes[i]) + end + + if #audiodevices == 0 then + -- Disable audio when no audiodevice is found + args.no_audio = true + return audiodevices + end + + -- Validate audiodevices + local last_error + local valid_audiodevices = {} + + for i = 1, #audiodevices do + local audiodevice = audiodevices[i] + local _error = audiodevice:validate() + if _error == nil then + valid_audiodevices[#valid_audiodevices + 1] = audiodevice + else + last_error = _error + end + end + + if #valid_audiodevices == 0 then + error(last_error) + end + + return valid_audiodevices +end + +-- main -- + +local youcubeapi = libs.youcubeapi.API.new() +local audiodevices = get_audiodevices() + +-- update check -- + +local function get_versions() + local url = "https://raw.githubusercontent.com/CC-YouCube/installer/main/versions.json" + + -- Check if the URL is valid + local ok, err = http.checkURL(url) + if not ok then + printError("Invalid Update URL.", '"' .. url .. '" ', err) + return + end + + local response, http_err = http.get(url, nil, true) + if not response then + printError('Failed to retreat data from update URL. "' .. url .. '" (' .. http_err .. ")") + return + end + + local sResponse = response.readAll() + response.close() + + return textutils.unserialiseJSON(sResponse) +end + +local function write_colored(text, color) + term.setTextColor(color) + term.write(text) +end + +local function new_line() + local w, h = term.getSize() + local x, y = term.getCursorPos() + if y + 1 <= h then + term.setCursorPos(1, y + 1) + else + term.setCursorPos(1, h) + term.scroll(1) + end +end + +local function write_outdated(current, latest) + if libs.semver(current) ^ libs.semver(latest) then + term.setTextColor(colors.yellow) + else + term.setTextColor(colors.red) + end + + term.write(current) + write_colored(" -> ", colors.lightGray) + write_colored(latest, colors.lime) + term.setTextColor(colors.white) + new_line() +end + +local function can_update(name, current, latest) + if libs.semver(current) < libs.semver(latest) then + term.write(name .. " ") + write_outdated(current, latest) + end +end + +local function update_checker() + local versions = get_versions() + if versions == nil then + return + end + + can_update("youcube", _VERSION, versions.client.version) + can_update("youcubeapi", libs.youcubeapi._VERSION, versions.client.libraries.youcubeapi.version) + can_update("numberformatter", libs.numberformatter._VERSION, versions.client.libraries.numberformatter.version) + can_update("semver", tostring(libs.semver._VERSION), versions.client.libraries.semver.version) + can_update("argparse", libs.argparse.version, versions.client.libraries.argparse.version) + + local handshake = youcubeapi:handshake() + + if libs.semver(handshake.server.version) < libs.semver(versions.server.version) then + print("Tell the server owner to update their server!") + write_outdated(handshake.server.version, versions.server.version) + end + + if not libs.semver(libs.youcubeapi._API_VERSION) ^ libs.semver(handshake.api.version) then + print("Client is not compatible with server") + write_colored(libs.youcubeapi._API_VERSION, colors.red) + write_colored(" ^ ", colors.lightGray) + write_colored(handshake.api.version, colors.red) + term.setTextColor(colors.white) + new_line() + end + + if libs.semver(libs.youcubeapi._API_VERSION) < libs.semver(versions.api.version) then + print("Your client is using an outdated API version") + write_outdated(libs.youcubeapi._API_VERSION, versions.api.version) + end + + if libs.semver(handshake.api.version) < libs.semver(versions.api.version) then + print("The server is using an outdated API version") + write_outdated(libs.youcubeapi._API_VERSION, versions.api.version) + end +end + +local function play_audio(buffer, title) + for i = 1, #audiodevices do + local audiodevice = audiodevices[i] + audiodevice:reset() + audiodevice:setLabel(title) + audiodevice:setVolume(args.volume) + end + + while true do + local chunk = buffer:next() + + -- Adjust buffer size on first chunk + if buffer.filler.chunkindex == 1 then + buffer.size = math.ceil(1024 / (#chunk / 16)) + end + + if chunk == "" then + local play_functions = {} + for i = 1, #audiodevices do + local audiodevice = audiodevices[i] + play_functions[#play_functions + 1] = function() + audiodevice:play() + end + end + + parallel.waitForAll(table.unpack(play_functions)) + return + end + + local write_functions = {} + for i = 1, #audiodevices do + local audiodevice = audiodevices[i] + table.insert(write_functions, function() + audiodevice:write(chunk) + end) + end + + parallel.waitForAll(table.unpack(write_functions)) + end +end + +-- #region playback controll vars +local back_buffer = {} +local max_back = settings.get("youcube.max_back") or 32 +local queue = {} +local restart = false +-- #endregion + +-- keys +local skip_key = settings.get("youcube.keys.skip") or keys.d +local restart_key = settings.get("youcube.keys.restart") or keys.r +local back_key = settings.get("youcube.keys.back") or keys.a + +local function play(url) + restart = false + print("Requesting media ...") + + if not args.no_video then + youcubeapi:request_media(url, term.getSize()) + else + youcubeapi:request_media(url) + end + + local data + local x, y = term.getCursorPos() + + repeat + data = youcubeapi:receive() + if data.action == "status" then + os.queueEvent("youcube:status", data) + term.setCursorPos(x, y) + term.clearLine() + term.write("Status: ") + write_colored(data.message, colors.green) + term.setTextColor(colors.white) + else + new_line() + end + until data.action == "media" + + if data.action == "error" then + error(data.message) + end + + term.write("Playing: ") + term.setTextColor(colors.lime) + print(data.title) + term.setTextColor(colors.white) + + if data.like_count then + print("Likes: " .. libs.numberformatter.compact(data.like_count)) + end + + if data.view_count then + print("Views: " .. libs.numberformatter.compact(data.view_count)) + end + + if not args.no_video then + -- wait, that the user can see the video info + sleep(2) + end + + local video_buffer = libs.youcubeapi.Buffer.new( + libs.youcubeapi.VideoFiller.new(youcubeapi, data.id, term.getSize()), + 60 -- Most videos run on 30 fps, so we store 2s of video. + ) + + local audio_buffer = libs.youcubeapi.Buffer.new( + libs.youcubeapi.AudioFiller.new(youcubeapi, data.id), + --[[ + We want to buffer 1024 chunks. + One chunks is 16 bits. + The server (with default settings) sends 32 chunks at once. + ]] + 32 + ) + + if args.verbose then + term.clear() + term.setCursorPos(1, 1) + term.write("[DEBUG MODE]") + end + + local function fill_buffers() + while true do + os.queueEvent("youcube:fill_buffers") + + local event = os.pullEventRaw() + + if event == "terminate" then + libs.youcubeapi.reset_term() + end + + if not args.no_audio then + audio_buffer:fill() + end + + if args.verbose then + term.setCursorPos(1, ({ term.getSize() })[2]) + term.clearLine() + term.write("Audio_Buffer: " .. #audio_buffer.buffer) + end + + if not args.no_video then + video_buffer:fill() + end + end + end + + local function _play_video() + if not args.no_video then + local string_unpack + if not string.unpack then + string_unpack = libs.string_pack.unpack + end + + os.queueEvent("youcube:vid_playing", data) + libs.youcubeapi.play_vid(video_buffer, args.force_fps, string_unpack) + os.queueEvent("youcube:vid_eof", data) + end + end + + local function _play_audio() + if not args.no_audio then + os.queueEvent("youcube:audio_playing", data) + play_audio(audio_buffer, data.title) + os.queueEvent("youcube:audio_eof", data) + end + end + + local function _play_media() + os.queueEvent("youcube:playing") + parallel.waitForAll(_play_video, _play_audio) + end + + local function _hotkey_handler() + while true do + local _, key = os.pullEvent("key") + + if key == skip_key then + back_buffer[#back_buffer + 1] = url --finished playing, push the value to the back buffer + if #back_buffer > max_back then + back_buffer[1] = nil --remove it from the front of the buffer + end + if not args.no_video then + libs.youcubeapi.reset_term() + end + break + end + + if key == restart_key then + queue[#queue + 1] = url --add the current song to upcoming + if not args.no_video then + libs.youcubeapi.reset_term() + end + restart = true + break + end + end + end + + parallel.waitForAny(fill_buffers, _play_media, _hotkey_handler) + + if data.playlist_videos then + return data.playlist_videos + end +end + +local function shuffle_playlist(playlist) + local shuffled = {} + for i = 1, #queue do + local pos = math.random(1, #shuffled + 1) + shuffled[pos] = queue[i] + end + return shuffled +end + +local function play_playlist(playlist) + queue = playlist + if args.shuffle then + queue = shuffle_playlist(queue) + end + while #queue ~= 0 do + local pl = table.remove(queue) + + local function handle_back_hotkey() + while true do + local _, key = os.pullEvent("key") + if key == back_key then + queue[#queue + 1] = pl --add the current song to upcoming + local prev = table.remove(back_buffer) + if prev then --nil/false check + queue[#queue + 1] = prev --add previous song to upcoming + end + if not args.no_video then + libs.youcubeapi.reset_term() + end + break + end + end + end + + parallel.waitForAny(handle_back_hotkey, function() + play(pl) --play the url + end) + end +end + +local function main() + youcubeapi:detect_bestest_server(args.server, args.verbose) + pcall(update_checker) + + if not args.URL then + print("Enter Url or Search Term:") + term.setTextColor(colors.lightGray) + args.URL = read() + term.setTextColor(colors.white) + end + + local playlist_videos = play(args.URL) + + if args.loop == true then + while true do + play(args.URL) + end + end + if playlist_videos then + if args.loop_playlist == true then + while true do + if playlist_videos then + play_playlist(playlist_videos) + end + end + end + play_playlist(playlist_videos) + end + + while restart do + play(args.URL) + end + + youcubeapi.websocket.close() + + if not args.no_video then + libs.youcubeapi.reset_term() + end + + os.queueEvent("youcube:playback_ended") +end + +main() diff --git a/computer/29/vaultmanager.lua b/computer/29/vaultmanager.lua new file mode 100644 index 0000000..49144ac --- /dev/null +++ b/computer/29/vaultmanager.lua @@ -0,0 +1,41 @@ +controller = peripheral.wrap("right") +print(controller) + +write("which row? ") +--row = read() +write("which column? ") +--col = read() + +sleep(1) +print(row, col) +function rotatetomove(blocks) + sleep(0.05) + controller.move( + math.abs(blocks), + math.abs(blocks)/blocks + ) + while controller.isRunning() do + sleep(0.05) + end +end +function travelY(blocks) + redstone.setAnalogOutput("top",0) + rotatetomove(blocks) +end + +function travelX(blocks) + redstone.setAnalogOutput("top",1) + rotatetomove(blocks) +end + +function travelZ(blocks) + redstone.setAnalogOutput("top",2) + rotatetomove(blocks) +end +travelY(4) +travelX(5) +travelZ(6) +sleep(10) +travelZ(-9) +travelX(-20) +travelY(-20) diff --git a/computer/3/removeemptychunks.lua b/computer/3/removeemptychunks.lua index d211c0e..d4cbf68 100644 --- a/computer/3/removeemptychunks.lua +++ b/computer/3/removeemptychunks.lua @@ -10,15 +10,15 @@ sf = require("structure") function removechunks() file = fs.open("tobuild","r") - lines = {} + counts = {} line = file.readLine() - + while line do i = math.mod((i or 0)+1,100) if i == 0 then sleep(0.05) end xyz = stringtovec(line) if not chunkisempty(xyz) then - table.insert(lines,line) + table.insert(counts,line) print(line) end line = file.readLine() @@ -26,19 +26,19 @@ function removechunks() file.close() fs.delete("tobuildcopy") file = fs.open("tobuildcopy","w") - for i,line in ipairs(lines) do + for i,line in ipairs(counts) do file.writeLine(line) print(line) if math.mod(i,100) == 0 then sleep(0.05) end end - file.close() + file.close() end function chunkisempty(vec) x,y,z = vec.x,vec.y,vec.z for w = 1,8 do for h = 1,8 do for d = 1,8 do - bool,block = sf.blockat(x+w,z+d,y+h) + bool,block = sf.blockat(x+w,z+d,y+h) if bool then print(block) return false diff --git a/computer/4/felling b/computer/4/felling index e4f541c..359e03c 100644 --- a/computer/4/felling +++ b/computer/4/felling @@ -21,7 +21,14 @@ im = require("inventorymanager") function fell(index) im.select("techreborn:rubber_sapling") - pf.lookat(trees[index or math.random(#trees)]) + pf.lookat(trees[index], + function() + has, data = turtle.inspect() + if has and data and data.name == "techreborn:rubber_leaves" then + turtle.dig() + end + end + ) has, data = turtle.inspect() --print(has,data) if @@ -43,9 +50,17 @@ function fell(index) turtle.place() end +repeat for i = 1,#trees do fell(i) end +sleep(300) +until ( + (turtle.getFuelLevel() < 500) + or + (im.count("techeborn:rubber_sapling") < 2*#trees) +) + pf.to(pf.home+vector.new(0,10,0)) pf.returnHome() diff --git a/computer/4/pathfinding.lua b/computer/4/pathfinding.lua index 3e71143..1c5b74a 100644 --- a/computer/4/pathfinding.lua +++ b/computer/4/pathfinding.lua @@ -67,9 +67,11 @@ function greedystep(target) return true end greedystep = require("pathfinding2").greedystep -function to(target) +function to(target, func) + func = func or function() end print(tostring(target)) while greedystep(target) do + func() end end function returnhome() @@ -89,11 +91,12 @@ function returnhome() _G.facing = facing _G.position = position end -function lookat(target) +function lookat(target, func) print("lookat"..target:tostring()) while (position+facing).x ~= target.x or (position+facing).z ~= target.z do greedystep(target) + if func then func() end end print("temp") temp = target.y-position.y diff --git a/disk/3/bg b/disk/3/bg new file mode 100644 index 0000000..ccb03ff --- /dev/null +++ b/disk/3/bg @@ -0,0 +1,11 @@ +if not shell.openTab then + printError("Requires multishell") + return +end + +local tArgs = { ... } +if #tArgs > 0 then + shell.openTab(table.unpack(tArgs)) +else + shell.openTab("shell") +end diff --git a/disk/3/multishell.lua b/disk/3/multishell.lua new file mode 100644 index 0000000..59de715 --- /dev/null +++ b/disk/3/multishell.lua @@ -0,0 +1,426 @@ +--- Multishell allows multiple programs to be run at the same time. +-- +-- When multiple programs are running, it displays a tab bar at the top of the +-- screen, which allows you to switch between programs. New programs can be +-- launched using the `fg` or `bg` programs, or using the @{shell.openTab} and +-- @{multishell.launch} functions. +-- +-- Each process is identified by its ID, which corresponds to its position in +-- the tab list. As tabs may be opened and closed, this ID is _not_ constant +-- over a program's run. As such, be careful not to use stale IDs. +-- +-- As with @{shell}, @{multishell} is not a "true" API. Instead, it is a +-- standard program, which launches a shell and injects its API into the shell's +-- environment. This API is not available in the global environment, and so is +-- not available to @{os.loadAPI|APIs}. +-- +-- @module[module] multishell +-- @since 1.6 + +local expect = dofile("rom/modules/main/cc/expect.lua").expect + +-- Setup process switching +local parentTerm = term.current() +local w, h = parentTerm.getSize() + +local tProcesses = {} +local nCurrentProcess = nil +local nRunningProcess = nil +local bShowMenu = false +local bWindowsResized = false +local nScrollPos = 1 +local bScrollRight = false + +local function selectProcess(n) + if nCurrentProcess ~= n then + if nCurrentProcess then + local tOldProcess = tProcesses[nCurrentProcess] + tOldProcess.window.setVisible(false) + end + nCurrentProcess = n + if nCurrentProcess then + local tNewProcess = tProcesses[nCurrentProcess] + tNewProcess.window.setVisible(true) + tNewProcess.bInteracted = true + end + end +end + +local function setProcessTitle(n, sTitle) + tProcesses[n].sTitle = sTitle +end + +local function resumeProcess(nProcess, sEvent, ...) + local tProcess = tProcesses[nProcess] + local sFilter = tProcess.sFilter + if sFilter == nil or sFilter == sEvent or sEvent == "terminate" then + local nPreviousProcess = nRunningProcess + nRunningProcess = nProcess + term.redirect(tProcess.terminal) + local ok, result = coroutine.resume(tProcess.co, sEvent, ...) + tProcess.terminal = term.current() + if ok then + tProcess.sFilter = result + else + printError(result) + end + nRunningProcess = nPreviousProcess + end +end + +local function launchProcess(bFocus, tProgramEnv, sProgramPath, ...) + local tProgramArgs = table.pack(...) + local nProcess = #tProcesses + 1 + local tProcess = {} + tProcess.sTitle = fs.getName(sProgramPath) + if bShowMenu then + tProcess.window = window.create(parentTerm, 1, 2, w, h - 1, false) + else + tProcess.window = window.create(parentTerm, 1, 1, w, h, false) + end + tProcess.co = coroutine.create(function() + os.run(tProgramEnv, sProgramPath, table.unpack(tProgramArgs, 1, tProgramArgs.n)) + if not tProcess.bInteracted then + term.setCursorBlink(false) + print("Press any key to continue") + os.pullEvent("char") + end + end) + tProcess.sFilter = nil + tProcess.terminal = tProcess.window + tProcess.bInteracted = false + tProcesses[nProcess] = tProcess + if bFocus then + selectProcess(nProcess) + end + resumeProcess(nProcess) + return nProcess +end + +local function cullProcess(nProcess) + local tProcess = tProcesses[nProcess] + if coroutine.status(tProcess.co) == "dead" then + if nCurrentProcess == nProcess then + selectProcess(nil) + end + table.remove(tProcesses, nProcess) + if nCurrentProcess == nil then + if nProcess > 1 then + selectProcess(nProcess - 1) + elseif #tProcesses > 0 then + selectProcess(1) + end + end + if nScrollPos ~= 1 then + nScrollPos = nScrollPos - 1 + end + return true + end + return false +end + +local function cullProcesses() + local culled = false + for n = #tProcesses, 1, -1 do + culled = culled or cullProcess(n) + end + return culled +end + +-- Setup the main menu +local menuMainTextColor, menuMainBgColor, menuOtherTextColor, menuOtherBgColor +if parentTerm.isColor() then + menuMainTextColor, menuMainBgColor = colors.yellow, colors.black + menuOtherTextColor, menuOtherBgColor = colors.black, colors.gray +else + menuMainTextColor, menuMainBgColor = colors.white, colors.black + menuOtherTextColor, menuOtherBgColor = colors.black, colors.gray +end + +local function redrawMenu() + if bShowMenu then + -- Draw menu + parentTerm.setCursorPos(1, 1) + parentTerm.setBackgroundColor(menuOtherBgColor) + parentTerm.clearLine() + local nCharCount = 0 + local nSize = parentTerm.getSize() + if nScrollPos ~= 1 then + parentTerm.setTextColor(menuOtherTextColor) + parentTerm.setBackgroundColor(menuOtherBgColor) + parentTerm.write("<") + nCharCount = 1 + end + for n = nScrollPos, #tProcesses do + if n == nCurrentProcess then + parentTerm.setTextColor(menuMainTextColor) + parentTerm.setBackgroundColor(menuMainBgColor) + else + parentTerm.setTextColor(menuOtherTextColor) + parentTerm.setBackgroundColor(menuOtherBgColor) + end + parentTerm.write(" " .. tProcesses[n].sTitle .. " ") + nCharCount = nCharCount + #tProcesses[n].sTitle + 2 + end + if nCharCount > nSize then + parentTerm.setTextColor(menuOtherTextColor) + parentTerm.setBackgroundColor(menuOtherBgColor) + parentTerm.setCursorPos(nSize, 1) + parentTerm.write(">") + bScrollRight = true + else + bScrollRight = false + end + + -- Put the cursor back where it should be + local tProcess = tProcesses[nCurrentProcess] + if tProcess then + tProcess.window.restoreCursor() + end + end +end + +local function resizeWindows() + local windowY, windowHeight + if bShowMenu then + windowY = 2 + windowHeight = h - 1 + else + windowY = 1 + windowHeight = h + end + for n = 1, #tProcesses do + local tProcess = tProcesses[n] + local x, y = tProcess.window.getCursorPos() + if y > windowHeight then + tProcess.window.scroll(y - windowHeight) + tProcess.window.setCursorPos(x, windowHeight) + end + tProcess.window.reposition(1, windowY, w, windowHeight) + end + bWindowsResized = true +end + +local function setMenuVisible(bVis) + if bShowMenu ~= bVis then + bShowMenu = bVis + resizeWindows() + redrawMenu() + end +end + +local multishell = {} --- @export + +--- Get the currently visible process. This will be the one selected on +-- the tab bar. +-- +-- Note, this is different to @{getCurrent}, which returns the process which is +-- currently executing. +-- +-- @treturn number The currently visible process's index. +-- @see setFocus +function multishell.getFocus() + return nCurrentProcess +end + +--- Change the currently visible process. +-- +-- @tparam number n The process index to switch to. +-- @treturn boolean If the process was changed successfully. This will +-- return @{false} if there is no process with this id. +-- @see getFocus +function multishell.setFocus(n) + expect(1, n, "number") + if n >= 1 and n <= #tProcesses then + selectProcess(n) + redrawMenu() + return true + end + return false +end + +--- Get the title of the given tab. +-- +-- This starts as the name of the program, but may be changed using +-- @{multishell.setTitle}. +-- @tparam number n The process index. +-- @treturn string|nil The current process title, or @{nil} if the +-- process doesn't exist. +function multishell.getTitle(n) + expect(1, n, "number") + if n >= 1 and n <= #tProcesses then + return tProcesses[n].sTitle + end + return nil +end + +--- Set the title of the given process. +-- +-- @tparam number n The process index. +-- @tparam string title The new process title. +-- @see getTitle +-- @usage Change the title of the current process +-- +-- multishell.setTitle(multishell.getCurrent(), "Hello") +function multishell.setTitle(n, title) + expect(1, n, "number") + expect(2, title, "string") + if n >= 1 and n <= #tProcesses then + setProcessTitle(n, title) + redrawMenu() + end +end + +--- Get the index of the currently running process. +-- +-- @treturn number The currently running process. +function multishell.getCurrent() + return nRunningProcess +end + +--- Start a new process, with the given environment, program and arguments. +-- +-- The returned process index is not constant over the program's run. It can be +-- safely used immediately after launching (for instance, to update the title or +-- switch to that tab). However, after your program has yielded, it may no +-- longer be correct. +-- +-- @tparam table tProgramEnv The environment to load the path under. +-- @tparam string sProgramPath The path to the program to run. +-- @param ... Additional arguments to pass to the program. +-- @treturn number The index of the created process. +-- @see os.run +-- @usage Run the "hello" program, and set its title to "Hello!" +-- +-- local id = multishell.launch({}, "/rom/programs/fun/hello.lua") +-- multishell.setTitle(id, "Hello!") +function multishell.launch(tProgramEnv, sProgramPath, ...) + expect(1, tProgramEnv, "table") + expect(2, sProgramPath, "string") + local previousTerm = term.current() + setMenuVisible(#tProcesses + 1 >= 2) + local nResult = launchProcess(false, tProgramEnv, sProgramPath, ...) + redrawMenu() + term.redirect(previousTerm) + return nResult +end + +--- Get the number of processes within this multishell. +-- +-- @treturn number The number of processes. +function multishell.getCount() + return #tProcesses +end + +-- Begin +parentTerm.clear() +setMenuVisible(false) +launchProcess(true, { + ["shell"] = shell, + ["multishell"] = multishell, +}, "/rom/programs/shell.lua") + +-- Run processes +while #tProcesses > 0 do + -- Get the event + local tEventData = table.pack(os.pullEventRaw()) + local sEvent = tEventData[1] + if sEvent == "term_resize" then + -- Resize event + w, h = parentTerm.getSize() + resizeWindows() + redrawMenu() + + elseif sEvent == "char" or sEvent == "key" or sEvent == "key_up" or sEvent == "paste" or sEvent == "terminate" then + -- Keyboard event + -- Passthrough to current process + resumeProcess(nCurrentProcess, table.unpack(tEventData, 1, tEventData.n)) + if cullProcess(nCurrentProcess) then + setMenuVisible(#tProcesses >= 2) + redrawMenu() + end + + elseif sEvent == "mouse_click" then + -- Click event + local button, x, y = tEventData[2], tEventData[3], tEventData[4] + if bShowMenu and y == 1 then + -- Switch process + if x == 1 and nScrollPos ~= 1 then + nScrollPos = nScrollPos - 1 + redrawMenu() + elseif bScrollRight and x == term.getSize() then + nScrollPos = nScrollPos + 1 + redrawMenu() + else + local tabStart = 1 + if nScrollPos ~= 1 then + tabStart = 2 + end + for n = nScrollPos, #tProcesses do + local tabEnd = tabStart + #tProcesses[n].sTitle + 1 + if x >= tabStart and x <= tabEnd then + selectProcess(n) + redrawMenu() + break + end + tabStart = tabEnd + 1 + end + end + else + -- Passthrough to current process + resumeProcess(nCurrentProcess, sEvent, button, x, bShowMenu and y - 1 or y) + if cullProcess(nCurrentProcess) then + setMenuVisible(#tProcesses >= 2) + redrawMenu() + end + end + + elseif sEvent == "mouse_drag" or sEvent == "mouse_up" or sEvent == "mouse_scroll" then + -- Other mouse event + local p1, x, y = tEventData[2], tEventData[3], tEventData[4] + if bShowMenu and sEvent == "mouse_scroll" and y == 1 then + if p1 == -1 and nScrollPos ~= 1 then + nScrollPos = nScrollPos - 1 + redrawMenu() + elseif bScrollRight and p1 == 1 then + nScrollPos = nScrollPos + 1 + redrawMenu() + end + elseif not (bShowMenu and y == 1) then + -- Passthrough to current process + resumeProcess(nCurrentProcess, sEvent, p1, x, bShowMenu and y - 1 or y) + if cullProcess(nCurrentProcess) then + setMenuVisible(#tProcesses >= 2) + redrawMenu() + end + end + + else + -- Other event + -- Passthrough to all processes + local nLimit = #tProcesses -- Storing this ensures any new things spawned don't get the event + for n = 1, nLimit do + resumeProcess(n, table.unpack(tEventData, 1, tEventData.n)) + end + if cullProcesses() then + setMenuVisible(#tProcesses >= 2) + redrawMenu() + end + end + + if bWindowsResized then + -- Pass term_resize to all processes + local nLimit = #tProcesses -- Storing this ensures any new things spawned don't get the event + for n = 1, nLimit do + resumeProcess(n, "term_resize") + end + bWindowsResized = false + if cullProcesses() then + setMenuVisible(#tProcesses >= 2) + redrawMenu() + end + end +end + +-- Shutdown +term.redirect(parentTerm) diff --git a/disk/3/pf b/disk/3/pf new file mode 100644 index 0000000..ba0886e --- /dev/null +++ b/disk/3/pf @@ -0,0 +1,112 @@ +pp = require("cc.pretty").pretty_print + +_G.facing = _G.facing or "south" +_G.pos = _G.pos or vector.new(0,0,0) + +local up = vector.new(0,1,0) + +local rightOf = { + south = "west", + west = "north", + north = "east", + east = "south" +} + +local leftOf = { + west = "south", + north = "west", + east = "north", + south = "east" +} + +local vecOf = { + north = vector.new(0,0,-1), + south = vector.new(0,0,1), + east = vector.new(1,0,0), + west = vector.new(-1,0,0), +} + +function goUp() + if turtle.up() then + _G.pos.y = _G.pos.y + 1 + else + printError("failed to go up") + printError(pos) + end +end + +function goDown() + if turtle.down() then + _G.pos.y = _G.pos.y - 1 + else + printError("failed to go down") + printError(pos) + end +end + +function goLeft() + turtle.turnLeft() + _G.facing = leftOf[_G.facing] +end + +function goRight() + turtle.turnRight() + _G.facing = rightOf[_G.facing] +end + +function goForward() + if turtle.forward() then + _G.pos = _G.pos + vecOf[_G.facing] + if math.random(10) > 9 then + meow() + end + else + printError("failed to go forward") + printError(pos) + end +end + +function goBack() + if turtle.back() then + _G.pos = _G.pos - vecOf[_G.facing] + else + printError("failed to go backward") + printError(pos) + end +end + +function stepTo(target) + local delta = target - _G.pos + -- print(delta) + if delta.y > 0 then + goUp() + elseif delta.y < 0 then + goDown() + elseif delta:dot(vecOf[_G.facing]) > 0 then + goForward() + elseif delta:dot(vecOf[_G.facing]:cross(up)) > 0 then + goRight() + else + goLeft() + end +end + +function goTo(target, face) + while target ~= _G.pos do + stepTo(target) + end + if face and face ~= _G.facing then + if rightOf[_G.facing] == face then + goRight() + elseif leftOf[_G.facing] == face then + goLeft() + else + goRight() + goRight() + end + end +end + +function goHome() + goTo(vector.new(0,0,0), "south") +end diff --git a/disk/3/sounds b/disk/3/sounds new file mode 100644 index 0000000..bcc444a --- /dev/null +++ b/disk/3/sounds @@ -0,0 +1,55 @@ +noteblock = peripheral.wrap("right") +sfx = require("sfx") +speaker = peripheral.wrap("left") +instruments = { +"harp", +"bass", +"didgeridoo", +"xylophone", +"iron_xylophone", +"snare", +"hat", +"basedrum", +"bit", +"bit", +"bit", +"bit" +} +mobs = { + "skeleton", + "zombie", + "pig", + "cow", + "spider" +} +function sound() +while true do + if math.random(10)>5 then + speaker.playSound("entity."..mobs[math.random(#mobs)]..".ambient",10) + elseif math.random(100) < 95 then + noteblock.setInstrument(instruments[math.random(#instruments)]) + noteblock.play() + noteblock.setNote(math.random(24)) + elseif math.random(100) < 50 then + for i = 1,5 do + speaker.playSound("entity.creeper.step") + sleep(0.05) + end + speaker.playSound("entity.creeper.primed") + else + --speaker.playSound("BOOM") + end + sleep(math.random(1,20)) + --os.reboot() +end +end +while false and true do + --sound() + if math.random(100) then + sfx.success() + sleep(math.random(1,4)) + end +end +parallel.waitForAll(sound,sound,sound,sound,sound) +peripheral.call("top","turnOn") +os.reboot() diff --git a/disk/3/startup.lua b/disk/3/startup.lua new file mode 100644 index 0000000..d6ec306 --- /dev/null +++ b/disk/3/startup.lua @@ -0,0 +1 @@ +print("heehee") diff --git a/ids.json b/ids.json index e0dc88d..69abf7e 100644 --- a/ids.json +++ b/ids.json @@ -1,5 +1,5 @@ { - "computer": 26, + "computer": 29, "disk": 4, "peripheral.create:fluid_tank": 2, "peripheral.create:item_vault": 0,