
Dung-beetle style development - The feeling you get working on a code base where each change feels like pushing an ever bigger ball of crap.
A phrase I remembered from working with Roly that made me laugh!

data Cell = Off
| On
| Dying
deriving (Eq,Show)
type GameGrid = Array (Int,Int) Cell
type Neighbours = [Cell]
data Game = Game GameGrid Int deriving Show
type is just used to give friendly names to types so I don't forget what they are!cellToChar I'm sure there must be a way of encoding this information so that I don't have to explictly write out each case? I realise I could define Cell as type data Cell = State Char, but that still doesn't feel write as it's only for three specific instances of Char. Anyway!cellToChar :: Cell -> Char
cellToChar Off = '0'
cellToChar On = '1'
cellToChar Dying = '2'
charToCell :: Char -> Cell
charToCell '0' = Off
charToCell '1' = On
charToCell '2' = Dying
charToCell _ = error "Undefined character received"
createGame :: Int -> [Cell] -> Game
createGame x c = Game (listArray ((0,0),(x-1,x-1)) c) x
gridToString :: Game -> String
gridToString (Game g _) = map cellToChar (elems g)
processMessage :: String -> String
processMessage s = map cellToChar newGrid where
[cellSizeStr,original] = lines s
cells = map charToCell original
cellSize = read cellSizeStr :: Int
newGrid = step (createGame cellSize cells)
listenLoop :: Handle -> IO ()
listenLoop h = do
msg <- readFrame h
sendFrame h (processMessage msg)
listenLoop h
main :: IO ()
main = serverListen 9876 listenLoop
rules :: Cell -> Neighbours -> Cell
rules On _ = Dying
rules Off cells | length (filter (/= Off) cells) == 2 = On
| otherwise = Off
rules Dying _ = Off
neighbours by assuming it wraps around. neighbours :: Game -> (Int,Int) -> Neighbours
neighbours (Game c s) (x,y) = [c ! ((x+dx) `mod` s, (y+dy) `mod` s)
| dx <- [-1,0,1], dy <- [-1,0,1], dx /= dy]
step :: Game -> [Cell]
step g@(Game c s) = [ rules (c ! p) (neighbours g p) | p <- coords] where
coords = [(x,y) | x <- [0..(s-1)], y <- [0..(s-1)]]
ffmpeg you can create a video like this (assuming your files are named 001.jpg, 002.jpg and so on).
ffmpeg -r 3 -b 1800 -i %03d.jpg output.mp4
if ('WebSocket' in window) {
ws = new WebSocket('ws://localhost:9876/');
ws.onopen = function() {
$('#connectionStatus').text('Connection opened');
}
ws.onclose = function() {
$('#connectionStatus').text('Connection closed');
}
ws.onmessage = function(evt) {
updateGrid(evt.data);
drawGrid();
return true;
}
}
$('#step').bind('click', function() { runStep(ws); });
function runStep(ws) {
var cells = '';
var pos = 0;
for (i=0;i<cellCount;++i) {
for (j=0;j<cellCount;++j) {
cells += grid[i][j];
}
}
ws.send(cellCount + '\n' + cells);
}
acceptLoop function accept an additional argument which handles communication back and forth.
module Web (serverListen, sendFrame, readFrame) where
acceptLoop :: Socket -> (Handle -> IO ()) -> IO a
acceptLoop socket f = forever $ do
(h,_,_) <- accept socket
hPutStr h serverHandshake
hSetBuffering h NoBuffering
forkIO (f h)
listenLoop :: Handle -> IO ()
listenLoop h = do
msg <- readFrame h
sendFrame h msg
listenLoop h
main :: IO ()
main = serverListen 9876 listenLoop