info-beamer/ffnord-con-2015-2/29c3/scramble.lua

91 lines
2.9 KiB
Lua
Raw Permalink Normal View History

2015-09-03 13:26:21 +02:00
local sys = require "sys"
local math = require "math"
local table = require "table"
local base = _G
module("scramble")
function scramble(text)
local all_breaks = '/.-{}()[]<>|,;!?'
local breaks = {}
for idx = 1, #all_breaks do
breaks[all_breaks:sub(idx, idx)]=true
end
-- print(#breaks)
local mode = "up"
local interval = 0.2
local swap_end
local next_action = sys.now() + interval
local stack = {}
local function is_break(text, pos)
local char = text:sub(pos, pos)
local is_break = breaks[char]
-- print(char, is_break)
return is_break, char
end
local function random_break()
local pos = math.random(1, #all_breaks)
return all_breaks:sub(pos, pos)
end
local function replace2(text, pos, c1, c2)
return text:sub(1, pos-1) .. c1 .. c2 .. text:sub(pos+2)
end
local function replace(text, pos, c)
return text:sub(1, pos-1) .. c .. text:sub(pos+1)
end
local function get()
local now = sys.now()
if now > next_action then
-- print(mode)
if mode == "up" then
local pos, is_1_break, is_2_break, char_1, char_2
repeat
pos = math.random(1, #text-1)
is_1_break, char_1 = is_break(text, pos)
is_2_break, char_2 = is_break(text, pos+1)
until is_1_break ~= is_2_break
-- print(pos, is_1_break, is_2_break)
if is_1_break then
table.insert(stack, {pos, random_break(), char_2})
text = replace2(text, pos, char_2, random_break())
else
table.insert(stack, {pos, char_1, random_break()})
text = replace2(text, pos, random_break(), char_1)
end
interval = interval - 0.01
if interval < 0.02 then
mode = "down"
end
elseif mode == "down" then
local pos, char1, char2 = base.unpack(table.remove(stack, #stack))
text = replace2(text, pos, char1, char2)
interval = interval + 0.01
if #stack == 0 then
mode = "swap"
swap_end = now + 15
interval = 2
end
elseif mode == "swap" then
local pos, is_break_char, _
repeat
pos = math.random(1, #text-1)
is_break_char, _ = is_break(text, pos)
until is_break_char
text = replace(text, pos, random_break())
if now > swap_end then
interval = 0.2
mode = "up"
end
end
next_action = now + interval
end
return text
end
return get
end