summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--spec/channel_spec.lua80
-rw-r--r--src/channel.moon25
-rw-r--r--src/js_bridge.js54
-rw-r--r--tools/rewrite.lua4
4 files changed, 138 insertions, 25 deletions
diff --git a/spec/channel_spec.lua b/spec/channel_spec.lua
index 252c12e..d8dbb13 100644
--- a/spec/channel_spec.lua
+++ b/spec/channel_spec.lua
@@ -44,10 +44,18 @@ describe("channel module", function()
assert(#fc.buffer == 1)
assert(fc:recv() == "a")
end)
+ it("has a normal() function that does normal distribution", function()
+ local normal = channel.FaultyChannel.normal
+ for i = 1, 20 do
+ math.randomseed(i)
+ local res = normal(nil,1,0.1)
+ assert(res > 0.5 and res < 1.5)
+ end
+ 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,
+ loss = 0,
avg_latency = 5
})
fc:send("a")
@@ -56,28 +64,27 @@ describe("channel module", function()
fc:pump()
assert(#fc.to_deliver == 1)
assert(#fc.buffer == 0)
-
+ channel.FaultyChannel.time = 4
+ fc:pump()
+ fc:send("b")
+ assert(#fc.to_deliver == 2)
+ assert(#fc.buffer == 0)
+ channel.FaultyChannel.time = 6
+ fc:pump()
+ assert(#fc.to_deliver == 1)
+ assert(#fc.buffer == 1)
end)
- --[[
it("can be configured to not drop messages", function()
channel.FaultyChannel.time = 0
local fc = channel.FaultyChannel({
avg_latency = 5,
- loss_std = 0
+ loss = 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
@@ -100,6 +107,53 @@ describe("channel module", function()
end
assert(j < i)
end)
- ]]
+ it("should keep a queue of messages", function()
+ channel.FaultyChannel.time = 0
+ local fc = channel.FaultyChannel({
+ loss = 0,
+ avg_latency=0,
+ latency_std=0,
+ })
+ local i = 100
+ for j = 1, i do
+ fc:send(tostring(j))
+ end
+ channel.FaultyChannel.time = 1
+ fc:pump()
+ assert(#fc.to_deliver == 0)
+ assert(#fc.buffer == i)
+ for j = 1, i do
+ assert(tonumber(fc:recv()) == j)
+ end
+ assert(not fc:poll())
+ end)
+ it("should deliver messages with different latencies", function()
+ channel.FaultyChannel.time = 0
+ local fc = channel.FaultyChannel({
+ loss = 0,
+ avg_latency = 20,
+ latency_std = 5,
+ })
+ local i = 100
+ for j = 1, i do
+ fc:send(tostring(j))
+ end
+ local received = 0
+ local increment = 0.5
+ local last_received = nil
+ local found_out_of_order = false
+ while received < i do
+ while fc:poll() do
+ local recv = tonumber(fc:recv())
+ if last_received and last_received < recv then
+ found_out_of_order = true
+ end
+ last_received = recv
+ received = received + 1
+ end
+ channel.FaultyChannel.time = channel.FaultyChannel.time + increment
+ end
+ assert(found_out_of_order)
+ end)
end)
end)
diff --git a/src/channel.moon b/src/channel.moon
index 968ae09..6f87d46 100644
--- a/src/channel.moon
+++ b/src/channel.moon
@@ -34,26 +34,31 @@ class FaultyChannel extends Channel
@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
+ @loss = 0.1 -- between 0 (never) and 1 (always)
super(settings)
- normal: (avg, std, n) =>
+ @normal_at: (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)))
+ @normal: (avg, std) =>
+ -- Box-Muller transform
+ bm = math.sqrt(-2 * math.log(math.random())) * math.cos(2 * math.pi * math.random())
+ -- Box-Muller gives us std = e^-0.5 , avg = 0
+ ((bm / math.exp(-1/2)) * std) + avg
poll: =>
@pump!
#@buffer > 0
send: (message) =>
-- Do we deliver?
- if @normal(@avg_loss, @loss_std, math.random()) < 0.5
+ rng = math.random()
+ if @loss > rng
return
-- How long does it take?
- time = @normal(@avg_latency, @latency_std, math.random())
+ -- Only uses the positive half of the normal distribution, double the standard deviation?
+ time = @@normal(@avg_latency, @latency_std * 2, math.random())
if time < 0 then
time = 0 -- We can't deliver messages in the past
- table.insert(@to_deliver, {message,time})
+ table.insert(@to_deliver, {message,@@time + time})
recv: =>
@pump!
table.remove(@buffer, 1)
@@ -62,11 +67,11 @@ class FaultyChannel extends Channel
deliver_len = #@to_deliver
for k,tbl in ipairs(@to_deliver)
{m, t} = tbl
+ @to_deliver[defrag] = tbl
if @@time > t
- @to_deliver[k] = nil
table.insert(@buffer, m)
- if @to_deliver[defrag] == nil
- @to_deliver[defrag] = tbl
+ else
+ defrag = defrag + 1
for i = defrag, deliver_len do
@to_deliver[i] = nil
diff --git a/src/js_bridge.js b/src/js_bridge.js
new file mode 100644
index 0000000..2d32739
--- /dev/null
+++ b/src/js_bridge.js
@@ -0,0 +1,54 @@
+var s = document.createElement('script');
+s.setAttribute('src','https://unpkg.com/peerjs@1.5.2/dist/peerjs.min.js');
+document.body.appendChild(s);
+function genRanHex(size) {
+ return Array.apply(null,Array(size)).map(() => Math.floor(Math.random() * 16).toString(16)).join('');
+}
+PEER = {}
+PEER.event_queue = {}
+PEER.peers = {}
+PEER.message_queue = {}
+PEER["create"] = function(name, options) {
+ var peer = new Peer(name, options)
+ PEER.peers[name] = peer
+}
+PEER["on"] = function(name, e, message) {
+ PEER.peers[name].on(e, function(conn) {
+ PEER.message_queue.push(message)
+ }
+}
+PEER["connect"] = function(name, id, options) {
+ PEER.peers[name].connect(id, options)
+}
+var peer = new Peer("ANGRY_ADVENTURE_" + GLOBAL.lobby_id, {"debug": 3});
+var peer_id = null;
+var poo = peer.on('open', function(id) {
+ console.log('My peer ID is: ' + id);
+ peer.on("connection",function(conn){
+ console.log("Got a connection!")
+ GLOBAL.connections[conn.peer] = conn
+ conn.send("Hello!")
+ GLOBAL.message_queue.push({
+ "msg": "data",
+ "peer": conn.peer,
+ "data": '{"msg":"player_joined"}'
+ })
+ conn.on("data",function(data){
+ console.log("Got some data from a peer!:" + data)
+ GLOBAL.message_queue.push({
+ "msg": "data",
+ "peer": conn.peer,
+ "data": data
+ })
+ })
+ conn.on("error",function(err){
+ console.log("Error on a connection:" + err)
+ GLOBAL.message_queue.push({
+ "msg": "error",
+ "peer": conn.peer,
+ "err": err
+ })
+ })
+ })
+ GLOBAL.peer_id = id;
+});
diff --git a/tools/rewrite.lua b/tools/rewrite.lua
index 503a0c8..e26a8c3 100644
--- a/tools/rewrite.lua
+++ b/tools/rewrite.lua
@@ -1,7 +1,7 @@
--[[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+):(.*)")()
+ local spaces, filename, linenum, rest = data:gmatch("(%s*)(.*%.lua):(%d+):(.*)")()
if filename and linenum and rest then
local moonfilename = filename:gsub(".lua$",".moon")
@@ -18,7 +18,7 @@ for data in io.lines() do
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))
+ print(string.format("%s%s:%d: %s",spaces,moonfilename,moon,rest))
goto next
end
end