summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile51
-rw-r--r--data/.gitignore1
-rw-r--r--data_src/.gitignore0
-rw-r--r--spec/channel_spec.lua105
-rw-r--r--spec/ui_spec.lua0
-rw-r--r--src/channel.moon73
-rw-r--r--src/conf.lua1
-rw-r--r--src/main.lua0
-rw-r--r--tools/luastr.sh5
-rw-r--r--tools/rewrite.lua31
10 files changed, 267 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..9c4bcf4
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,51 @@
+
+LUA?="$(shell where lua | head -n 1)"
+CP?=cp
+AMULET?="$(shell where amulet | head -n 1)"
+RM?=rm
+UNZIP?=7z x -y
+CD?=cd
+MOONC?="$(shell where moonc | head -n 1)"
+BUSTED?="$(shell where busted | head -n 1)"
+
+src_moon=$(wildcard src/*.moon)
+built_moon=$(src_moon:src/%.moon=data/%.lua)
+dbg_moon=$(src_moon:src/%.moon=data/%.lua.X)
+
+src_tl=$(wildcard src/*.tl)
+built_tl=$(src_tl:src/%.tl=data/%.lua)
+
+src_lua=$(wildcard src/*.lua)
+built_lua=$(src_lua:src/%.lua=data/%.lua)
+
+src_js=$(wildcard src/*.js)
+built_js=$(src_js:src/%.js=data/%.lua)
+
+built=$(built_moon) $(built_tl) $(built_lua) $(built_js)
+built_dbg=$(built) $(dbg_moon)
+
+all: $(built_dbg)
+ $(AMULET) export -html -a data
+ $(UNZIP) *.zip
+ $(CD) ggj25 && python3 -m http.server
+
+clean:
+ $(RM) $(built)
+
+test: $(built_dbg)
+ $(BUSTED) -m "./data/?.lua" -o utfTerminal -v spec | $(LUA) tools/rewrite.lua
+
+$(built_lua) : data/%.lua : src/%.lua
+ $(CP) $< $@
+
+$(built_moon) : data/%.lua : src/%.moon
+ $(MOONC) -p $< > $@
+
+$(dbg_moon) : data/%.lua.X : src/%.moon
+ $(MOONC) -X $< > $@
+
+$(test_lua) : spec/%.lua : src/%.lua
+ $(CP) $< $@
+
+$(test_moon) : spec/%.lua : src/%.moon
+ $(MOONC) -p $< > $@
diff --git a/data/.gitignore b/data/.gitignore
new file mode 100644
index 0000000..72e8ffc
--- /dev/null
+++ b/data/.gitignore
@@ -0,0 +1 @@
+*
diff --git a/data_src/.gitignore b/data_src/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/data_src/.gitignore
diff --git a/spec/channel_spec.lua b/spec/channel_spec.lua
new file mode 100644
index 0000000..252c12e
--- /dev/null
+++ b/spec/channel_spec.lua
@@ -0,0 +1,105 @@
+
+describe("channel module", function()
+ it("should load",function()
+ require("channel")
+ end)
+ describe("SimpleChannel",function()
+ local channel = require("channel")
+ it("should exist",function()
+ assert(channel.SimpleChannel)
+ assert(channel.SimpleChannel())
+ end)
+ it("should send messages",function()
+ local sc = channel.SimpleChannel()
+ assert(not sc:poll())
+ sc:send("Hello")
+ assert(sc:poll())
+ assert(sc:recv() == "Hello")
+ end)
+ it("should send any string",function()
+ local sc = channel.SimpleChannel()
+ local rng = tostring(math.random())
+ sc:send(rng)
+ assert(sc:recv() == rng)
+ end)
+ end)
+ describe("FaultyChannel",function()
+ local channel = require("channel")
+ it("should exist",function()
+ assert(channel.FaultyChannel)
+ assert(channel.FaultyChannel())
+ end)
+ it("can has a .time that allows it to time travel",function()
+ channel.FaultyChannel.time = 0
+ local fc = channel.FaultyChannel({
+ loss_std = 0,
+ avg_latency = 5
+ })
+ fc:send("a")
+ assert(#fc.to_deliver == 1)
+ assert(#fc.buffer == 0)
+ channel.FaultyChannel.time = 10
+ fc:pump()
+ assert(#fc.to_deliver == 0)
+ assert(#fc.buffer == 1)
+ assert(fc:recv() == "a")
+ end)
+ it("can pump() with no side effects if time has not changed", function()
+ channel.FaultyChannel.time = 0
+ local fc = channel.FaultyChannel({
+ loss_std = 0,
+ avg_latency = 5
+ })
+ fc:send("a")
+ assert(#fc.to_deliver == 1)
+ assert(#fc.buffer == 0)
+ fc:pump()
+ assert(#fc.to_deliver == 1)
+ assert(#fc.buffer == 0)
+
+ end)
+ --[[
+ it("can be configured to not drop messages", function()
+ channel.FaultyChannel.time = 0
+ local fc = channel.FaultyChannel({
+ avg_latency = 5,
+ loss_std = 0
+ })
+ local i = 100
+ for _ = 1,i do
+ fc:send("a")
+ end
+ print(#fc.to_deliver)
+ print(#fc.buffer)
+ fc:pump()
+ print(#fc.to_deliver)
+ print(#fc.buffer)
+ channel.FaultyChannel.time = 10
+ fc:pump()
+ print(#fc.to_deliver)
+ print(#fc.buffer)
+ local j = 0
+ while fc:poll() do
+ j = j + 1
+ fc:recv()
+ end
+ assert(j == i)
+ end)
+ it("should drop messages sometimes",function()
+ local fc = channel.FaultyChannel()
+ local i = 100
+ for _ = 1, i do
+ fc:send("a")
+ end
+ -- Time forward
+ --channel.FaultyChannel.time = math.huge
+ local j = 0
+ while fc:poll() do
+ j = j + 1
+ fc:recv()
+ end
+ assert(j < i)
+ end)
+ ]]
+ end)
+end)
diff --git a/spec/ui_spec.lua b/spec/ui_spec.lua
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/spec/ui_spec.lua
diff --git a/src/channel.moon b/src/channel.moon
new file mode 100644
index 0000000..968ae09
--- /dev/null
+++ b/src/channel.moon
@@ -0,0 +1,73 @@
+
+-- Implements a channels, an abstraction for sending data
+
+class Channel
+ new: (settings) =>
+ settings = settings or {}
+ --Every channel has at least a buffer, the messages to be read on recv()
+ @buffer = {}
+ for setting_name, setting_value in pairs settings
+ @[setting_name] = setting_value
+ poll: =>
+ error("Channel must implement poll")
+ send: (message) =>
+ error("Channel must implement message")
+ recv: =>
+ error("Channel must implement recv")
+
+class SimpleChannel extends Channel
+ @time = 0
+ new: (settings) =>
+ super(settings)
+ poll: =>
+ #@buffer > 0
+ send: (message) =>
+ table.insert(@buffer, message)
+ recv: =>
+ table.remove(@buffer, 1)
+
+class FaultyChannel extends Channel
+ -- Mock channel for testing
+ @time = 0
+ new: (settings) =>
+ @to_deliver = {}
+ @avg_latency = 0 -- in ms
+ @latency_std = 0
+ -- Latency can never be below 0, but can go up as much as it likes
+ @avg_loss = 0 -- between 0 (never) and 1 (always)
+ @loss_std = 0.1
+ -- Loss is always a percentage between 0 and 1
+ super(settings)
+ normal: (avg, std, n) =>
+ assert(avg and std and n, string.format("normal(avg, std, n) called with %q %q %q", tostring(avg), tostring(std), tostring(n)))
+ -- Normal curve probability at N
+ (1/ (math.sqrt(2*math.pi) * avg)) * math.exp(-(n - avg)^2 / (2 * (std^2)))
+ poll: =>
+ @pump!
+ #@buffer > 0
+ send: (message) =>
+ -- Do we deliver?
+ if @normal(@avg_loss, @loss_std, math.random()) < 0.5
+ return
+ -- How long does it take?
+ time = @normal(@avg_latency, @latency_std, math.random())
+ if time < 0 then
+ time = 0 -- We can't deliver messages in the past
+ table.insert(@to_deliver, {message,time})
+ recv: =>
+ @pump!
+ table.remove(@buffer, 1)
+ pump: =>
+ defrag = 1
+ deliver_len = #@to_deliver
+ for k,tbl in ipairs(@to_deliver)
+ {m, t} = tbl
+ if @@time > t
+ @to_deliver[k] = nil
+ table.insert(@buffer, m)
+ if @to_deliver[defrag] == nil
+ @to_deliver[defrag] = tbl
+ for i = defrag, deliver_len do
+ @to_deliver[i] = nil
+
+{:Channel, :SimpleChannel, :FaultyChannel}
diff --git a/src/conf.lua b/src/conf.lua
new file mode 100644
index 0000000..662a017
--- /dev/null
+++ b/src/conf.lua
@@ -0,0 +1 @@
+shortname="ggj25"
diff --git a/src/main.lua b/src/main.lua
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/main.lua
diff --git a/tools/luastr.sh b/tools/luastr.sh
new file mode 100644
index 0000000..5b50c7d
--- /dev/null
+++ b/tools/luastr.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+echo "return [=====["
+echo "$(cat $1)"
+echo "]=====]"
diff --git a/tools/rewrite.lua b/tools/rewrite.lua
new file mode 100644
index 0000000..503a0c8
--- /dev/null
+++ b/tools/rewrite.lua
@@ -0,0 +1,31 @@
+--[[Script to rewrite a stack traceback in terms of moonscript instead of lua]]
+
+for data in io.lines() do
+ local filename, linenum, rest = data:gmatch("%s+(.*%.lua):(%d+):(.*)")()
+ if filename and linenum and rest then
+ local moonfilename = filename:gsub(".lua$",".moon")
+
+ --If our file is not moonscript, we won't have a debug file
+ local debugfile, err = io.open(filename .. ".X", "r")
+ if not debugfile then
+ --print("not debugfile" .. filename .. ":" .. err)
+ print(data)
+ goto next
+ end
+
+ --Skip first line
+ debugfile:read("*l")
+ for line in debugfile:lines() do
+ _,_,pos,lua,moon = line:find("(%d+)%s+(%d+):%b[] >> (%d+)")
+ if tonumber(linenum) == tonumber(lua) then
+ print(string.format("\t%s:%d: %s",moonfilename,moon,rest))
+ goto next
+ end
+ end
+ debugfile:close()
+ else
+ print(data)
+ end
+ ::next::
+end
+