Switched index page to game of life.
1 var QUOTES_NUMBER = 39;
2 var SERVER = "http://" + window.location.hostname + ":" + window.location.port;
6 $(document).ready(function() {
7 simulation = new Simulation(document.getElementById("sim"),
8 670, 50, 6, green, background);
9 var image = new Image();
10 image.onload = init_logo;
11 image.src = "images/logobase.png";
12 $("#logo").click(handle_click);
13 $("#logo").hover(function() {
14 $(this).css("cursor", "pointer");
16 $(this).css("cursor", "auto");
18 $("#sim").mousemove(function(event) { simulation.mouse_moved(mouse_pos(event, "#sim")); });
20 if (window.webkitRequestAnimationFrame) {
21 onEachFrame = function(cb) {
22 var _cb = function() { cb(); webkitRequestAnimationFrame(_cb); }
25 } else if (window.mozRequestAnimationFrame) {
26 onEachFrame = function(cb) {
27 var _cb = function() { cb(); mozRequestAnimationFrame(_cb); }
31 onEachFrame = function(cb) {
32 setInterval(cb, 1000 / 30);
35 window.onEachFrame = onEachFrame;
36 window.onEachFrame(update);
37 var pos = document.location.href.lastIndexOf("/") + 1;
38 var page = document.location.href.substr(pos);
39 if (page == "mandelbrot.html") {
41 } else if (page == "" || page == "index.html") {
42 init_gameoflife("ME73");
46 $(document).keypress(function(event) {
47 if (event.which == 13) {
48 event.preventDefault();
54 var menu_height = 100;
55 var menu_splits = new Array(180, 350, 505);
57 var click_events = new Array();
58 click_events["logo"] = new Array();
59 click_events["logo"][0] = new Object();
60 click_events["logo"][0]["min_x"] = 0;
61 click_events["logo"][0]["max_x"] = menu_splits[0];
62 click_events["logo"][0]["min_y"] = 0;
63 click_events["logo"][0]["max_y"] = menu_height;
64 click_events["logo"][0]["func"] = switch_page;
65 click_events["logo"][0]["args"] = new Array("personalwork.html");
66 click_events["logo"][1] = new Object();
67 click_events["logo"][1]["min_x"] = menu_splits[0] + 1;
68 click_events["logo"][1]["max_x"] = menu_splits[1];
69 click_events["logo"][1]["min_y"] = 0;
70 click_events["logo"][1]["max_y"] = menu_height;
71 click_events["logo"][1]["func"] = switch_page;
72 click_events["logo"][1]["args"] = new Array("howiwork.html");
73 click_events["logo"][2] = new Object();
74 click_events["logo"][2]["min_x"] = menu_splits[1] + 1;
75 click_events["logo"][2]["max_x"] = menu_splits[2];
76 click_events["logo"][2]["min_y"] = 0;
77 click_events["logo"][2]["max_y"] = menu_height;
78 click_events["logo"][2]["func"] = switch_page;
79 click_events["logo"][2]["args"] = new Array("books.html");
80 click_events["logo"][3] = new Object();
81 click_events["logo"][3]["min_x"] = menu_splits[2] + 1;
82 click_events["logo"][3]["max_x"] = menu_width - 1;
83 click_events["logo"][3]["min_y"] = 0;
84 click_events["logo"][3]["max_y"] = menu_height;
85 click_events["logo"][3]["func"] = switch_page;
86 click_events["logo"][3]["args"] = new Array("links.html", "linksend.html");
88 function mouse_pos(event, id) {
89 var offset = $(id).offset();
90 return new Array(event.pageX - offset.left,
91 event.pageY - offset.top);
94 function handle_click(event) {
95 var xy = mouse_pos(event, "#logo");
98 for (var i in click_events[event.target.id]) {
99 var ces = click_events[event.target.id][i];
100 if (ces && x >= ces["min_x"] && x <= ces["max_x"]
101 && y >= ces["min_y"] && y <= ces["max_y"]) {
102 ces["func"](event.target.id, ces);
108 function switch_page(id, params) {
109 var page = params["args"][0];
110 $("body").load(page);
111 document.location.href = page;
114 function colour_area(image, min_x, max_x, min_y, max_y, colour) {
115 var pixels = image.data;
116 for (var y = min_y; y <= max_y; y += 1) {
117 for (var x = min_x; x <= max_x; x += 1) {
118 var pix_colour = getPixel(image, x, y);
119 if (pix_colour.a > 0) {
120 colour.a = pix_colour.a;
121 setPixel(image, x, y, colour);
127 function init_logo(event) {
128 var canvas = document.getElementById("logo");
129 var context = canvas.getContext("2d");
130 canvas.width = menu_width;
131 canvas.height = menu_height;
132 context.drawImage(event.target, 0, 0);
133 var image = context.getImageData(0, 0, menu_width, menu_height);
134 for (var i in click_events["logo"]) {
135 var p = click_events["logo"][i];
136 var min_x = p["min_x"];
137 var max_x = p["max_x"];
138 var min_y = p["min_y"];
139 var max_y = p["max_y"];
140 var pos = document.location.href.lastIndexOf("/") + 1;
141 var page = document.location.href.substr(pos);
142 for (var j in p["args"]) {
143 if (page == p["args"][j]) {
144 colour_area(image, min_x, max_x, 0, 60, black);
145 colour_area(image, min_x, max_x, 60, max_y, white);
149 colour_area(image, min_x, max_x, 0, 60, white);
150 colour_area(image, min_x, max_x, 60, max_y, orange);
154 context.putImageData(image, 0, 0);
155 // context.fillStyle = green.str();
156 // console.log((found["max_x"] - found["min_x"]) / 2 + found["min_x"] - 2);
157 // context.fillRect((found["max_x"]-found["min_x"])/2+found["min_x"]-1, 95, 2, 5);
161 function draw_menu_lines() {
162 var canvas = document.getElementById("logo");
163 var context = canvas.getContext("2d");
164 var image = context.getImageData(0, 0, menu_width, menu_height);
165 var pixels = image.data;
166 context.lineCap = "round";
167 context.lineWidth = 1;
168 var colour1a = new Colour(0, 0, 0, 0.1);
170 context.moveTo(0, menu_height - 1);
171 context.lineTo(menu_width - 1, menu_height - 1);
173 context.strokeStyle = colour1a.str();
175 var colour1e = new Colour(0, 0, 0, 0.05);
177 context.moveTo(70, menu_height - 1);
178 context.lineTo(menu_width - 71, menu_height - 1);
180 context.strokeStyle = colour1e.str();
182 var colour1b = new Colour(0, 0, 0, 0.05);
184 context.moveTo(50, menu_height - 1);
185 context.lineTo(menu_width - 51, menu_height - 1);
187 context.strokeStyle = colour1b.str();
189 var colour1c = new Colour(0, 0, 0, 0.05);
191 context.moveTo(25, menu_height - 1);
192 context.lineTo(menu_width - 26, menu_height - 1);
194 context.strokeStyle = colour1c.str();
196 var colour1d = new Colour(0, 0, 0, 0.05);
198 context.moveTo(10, menu_height - 1);
199 context.lineTo(menu_width - 11, menu_height - 1);
201 context.strokeStyle = colour1d.str();
204 var colour2 = new Colour(0, 0, 0, 0.2);
206 context.moveTo(menu_splits[0], 0);
207 context.lineTo(menu_splits[0], menu_height - 1);
208 context.moveTo(menu_splits[1], 0);
209 context.lineTo(menu_splits[1], menu_height - 1);
210 context.moveTo(menu_splits[2], 0);
211 context.lineTo(menu_splits[2], menu_height - 1);
213 context.strokeStyle = colour2.str();
216 context.clearRect(menu_splits[0] - 1, menu_height - 1, 2, 2);
217 context.clearRect(menu_splits[1] - 1, menu_height - 1, 2, 2);
218 context.clearRect(menu_splits[2] - 1, menu_height - 1, 2, 2);
220 context.clearRect(menu_splits[0] - 1, menu_height - 2, 1, 1);
221 context.clearRect(menu_splits[1] - 1, menu_height - 2, 1, 1);
222 context.clearRect(menu_splits[2] - 1, menu_height - 2, 1, 1);
225 function clearMenuLines() {
226 var canvas = document.getElementById("logo");
227 var context = canvas.getContext("2d");
228 var image = context.getImageData(0, 0, menu_width, menu_height);
229 var pixels = image.data;
230 context.clearRect(0, menu_height - 2, menu_width - 1, 2);
231 context.clearRect(menu_splits[0] - 1, 0, 2, menu_height - 1);
232 context.clearRect(menu_splits[1] - 1, 0, 2, menu_height - 1);
233 context.clearRect(menu_splits[2] - 1, 0, 2, menu_height - 1);
236 function draw_sim_lines() {
239 var canvas = document.getElementById("sim");
240 var context = canvas.getContext("2d");
241 var image = context.getImageData(0, 0, w, h);
242 var pixels = image.data;
243 context.lineCap = "round";
244 context.lineWidth = 1;
245 var colour1a = new Colour(0, 0, 0, 0.1);
247 context.moveTo(0, h - 1);
248 context.lineTo(w - 1, h - 1);
250 context.strokeStyle = colour1a.str();
252 var colour1e = new Colour(0, 0, 0, 0.05);
254 context.moveTo(70, h - 1);
255 context.lineTo(w - 71, h - 1);
257 context.strokeStyle = colour1e.str();
259 var colour1b = new Colour(0, 0, 0, 0.05);
261 context.moveTo(50, h - 1);
262 context.lineTo(w - 51, h - 1);
264 context.strokeStyle = colour1b.str();
266 var colour1c = new Colour(0, 0, 0, 0.05);
268 context.moveTo(25, h - 1);
269 context.lineTo(w - 26, h - 1);
271 context.strokeStyle = colour1c.str();
273 var colour1d = new Colour(0, 0, 0, 0.05);
275 context.moveTo(10, h - 1);
276 context.lineTo(w - 11, h - 1);
278 context.strokeStyle = colour1d.str();
282 function update_logo() {
283 var canvas = document.getElementById("logo");
284 var context = canvas.getContext("2d");
285 var image = context.getImageData(0, 0, menu_width, menu_height);
286 var pixels = image.data;
287 var white = new Colour(255, 255, 255);
288 for (var y = 0; y < menu_height; y += 1) {
289 for (var x = 0; x < menu_width; x += 1) {
290 var pix_colour = getPixel(image, x, y);
291 if (pix_colour.a > 0) {
292 setPixel(image, x, y, new Colour(90, 215, 21, pix_colour.a));
296 context.putImageData(image, 0, 0);
299 var char_map = new Array();
300 char_map["A"] = new Array(new Array(0, 4), new Array(1, 3),
301 new Array(2, 2), new Array(3, 1),
302 new Array(4, 0), new Array(5, 1),
303 new Array(6, 2), new Array(7, 3),
304 new Array(8, 4), new Array(2, 3),
305 new Array(3, 3), new Array(4, 3),
306 new Array(5, 3), new Array(6, 3));
307 char_map["M"] = new Array(new Array(0, 4), new Array(0, 3),
308 new Array(0, 2), new Array(0, 1),
309 new Array(0, 0), new Array(0, 5),
310 new Array(5, 4), new Array(5, 3),
311 new Array(5, 2), new Array(5, 1),
312 new Array(5, 0), new Array(5, 5),
313 new Array(1, 1), new Array(2, 2),
314 new Array(4, 2), new Array(5, 1),
316 char_map["E"] = new Array(new Array(0, 4), new Array(0, 3),
317 new Array(0, 2), new Array(0, 1),
318 new Array(0, 0), new Array(0, 5),
319 new Array(1, 0), new Array(2, 0),
321 new Array(1, 3), new Array(2, 3),
322 new Array(1, 5), new Array(2, 5),
324 char_map["7"] = new Array(new Array(0, 0), new Array(1, 0),
326 new Array(0, 5), new Array(0, 4),
327 new Array(1, 3), new Array(2, 2));
328 char_map["3"] = new Array(new Array(2, 4), new Array(2, 3),
329 new Array(2, 2), new Array(2, 1),
330 new Array(0, 0), new Array(0, 5),
331 new Array(1, 0), new Array(2, 0),
332 new Array(1, 3), new Array(2, 3),
333 new Array(1, 5), new Array(2, 5))
335 function init_gameoflife(text) {
336 var canvas = document.getElementById("gameoflife");
339 gameoflife = new Simulation(canvas, 670, 670, cell_size,
341 $("#gameoflife").mousemove(function(event) {
342 gameoflife.mouse_moved(mouse_pos(event, "#gameoflife"));
344 var offset = new Array(13, 16);
345 for (var c in text) {
347 for (p in char_map[text[c]]) {
348 var x = char_map[text[c]][p][0];
349 var y = char_map[text[c]][p][1];
351 var pos = new Array((x + offset[0]) * cell_size,
352 (y + offset[1]) * cell_size);
353 gameoflife.activate_cell(pos);
360 function Colour(r, g, b, a) {
364 this.a = a == undefined ? 255 : a;
366 Colour.prototype.equals = function(rhs) {
368 if (typeof(rhs[p]) == undefined
369 || this[p] != rhs[p]) {
375 Colour.prototype.str = function() {
376 return "rgba(" + this.r + "," + this.g + "," + this.b + "," + this.a + ")";
379 var white = new Colour(255, 255, 255);
380 var black = new Colour(0, 0, 0);
381 var orange = new Colour(201, 87, 35);
382 var green = new Colour(90, 215, 21);
383 var background = new Colour(34, 34, 34);
385 function setPixel(image, x, y, colour) {
386 var index = 4 * (x + y * image.width);
387 image.data[index] = colour.r;
388 image.data[index + 1] = colour.g;
389 image.data[index + 2] = colour.b;
390 image.data[index + 3] = colour.a;
393 function getPixel(image, x, y) {
394 var index = 4 * (x + y * image.width);
395 var r = image.data[index];
396 var g = image.data[index + 1];
397 var b = image.data[index + 2];
398 var a = image.data[index + 3];
399 return new Colour(r, g, b, a);
402 function load_random_quote() {
403 var file = "/quotes/quote" + Math.floor(Math.random() * QUOTES_NUMBER + 1) + ".html";
404 $.ajax({url: SERVER + file,
405 success: write_quote});
408 function write_quote(data, status, xhr) {
409 $("#random_quote").html(data);
412 function load_footer()
414 var file = "/footer.html";
415 var currentFile = self.location.hostname + self.location.pathname;
416 var request = http_request_object();
417 var url = "http://" + self.location.hostname + file;
418 request.open("GET", url, false);
419 request.setRequestHeader("User-Agent", navigator.userAgent);
421 // if (oRequest.status == 200) alert(oRequest.responseText);
422 // else alert("Error executing XMLHttpRequest call!");
423 //document.write(url);
424 //document.write(request.responseText);
425 document.getElementById('footer').innerHTML = request.responseText;
430 // Mandelbrot functions
431 function Complex(real, imag)
437 var MIN_C = new Complex(-2.2, -1.4);
438 var MAX_C = new Complex(1.0, 1.4);
442 var max_iter = MIN_ITER;
447 function Result(z, iter)
453 function complex_quad(c)
455 return new Complex(Math.pow(c.real, 2) - Math.pow(c.imag, 2),
456 2.0 * c.real * c.imag);
459 function complex_quad_value(c)
461 return Math.pow(c.real, 2) + Math.pow(c.imag, 2);
464 function complex_add(c1, c2)
466 return new Complex(c1.real + c2.real, c1.imag + c2.imag);
469 function complex_equal(c1, c2)
471 return (c1.real == c2.real) && (c1.imag == c2.imag);
474 function iterate(z, c)
476 z_quad = complex_quad(z);
477 return new Complex(z_quad.real + c.real, z_quad.imag + c.imag);
480 function test(c, max_iter)
483 var z = new Complex(0.0, 0.0);
484 var last_z = new Complex(-1.0, 0.0);
485 var quad_z = complex_quad_value(z);
487 while (iter < max_iter
488 && !complex_equal(z, last_z)
489 && quad_z <= bailout)
493 quad_z = complex_quad_value(z);
496 return new Result(quad_z, iter);
499 function draw(diter, dx, dy, dz, dres)
501 var canvas = document.getElementById('mandelbrot');
503 if (canvas.getContext)
506 var ctx = canvas.getContext('2d');
510 resolution = Math.max(1, resolution + dres);
515 max_iter = Math.max(MIN_ITER, max_iter + diter);
518 var red = "rgb(255, 0, 0)";
519 var white = "rgb(255, 255, 255)";
520 var width = canvas.width;
521 var height = canvas.height;
522 var dim = Math.max(width, height);
523 var dim_ratio = Math.round(width / height);
524 var diff_c = new Complex(max_c.real - min_c.real,
525 max_c.imag - min_c.imag);
526 dx_min = diff_c.real / 100 * (dx + dz);
527 dx_max = diff_c.real / 100 * (dx - dz);
529 dy_min = diff_c.imag / 100 * (dy + dz);
530 dy_max = diff_c.imag / 100 * (dy - dz);
532 var min_inc = new Complex(dx_min * dim_ratio / 2.0, dy_min);
533 var max_inc = new Complex(dx_max * dim_ratio / 2.0, dy_max);
534 min_c = complex_add(min_c, min_inc);
535 max_c = complex_add(max_c, max_inc);
536 diff_c = new Complex(max_c.real - min_c.real,
537 max_c.imag - min_c.imag);
539 for (var y = 0; y < height; y += resolution)
541 for (var x = 0; x < width; x += resolution)
543 var c = new Complex(min_c.real + diff_c.real / dim * x,
544 min_c.imag + diff_c.imag / dim * y);
545 var result = test(c, max_iter);
546 var r = Math.min(255, Math.pow(Math.max(0,
547 (result.iter - max_iter / 20.0)), 2));
548 var g = Math.min(255, Math.pow(Math.max(0,
549 (result.iter - max_iter / 25.0)), 2));
550 var b = Math.min(255, Math.pow(Math.max(0,
551 (result.iter - max_iter / 20.0)), 2));
552 var colour = "rgb(" + r + "," + g + "," + b + ")";
553 ctx.fillStyle = colour;
554 ctx.fillRect(x, y, resolution, resolution);
560 function getEventOffsetX(evt)
562 if (evt.offsetX != null)
565 var obj = evt.target || evt.srcElement;
567 return (evt.clientX - obj.pageLeft);
570 function getEventOffsetY(evt)
572 if (evt.offsetY != null)
575 var obj = evt.target || evt.srcElement;
577 return (evt.clientY - obj.pageTop);
580 function setPageTopLeft( o )
586 while (o.offsetParent)
588 left += o.offsetLeft ;
597 function draw2(evt) {
600 var x = (getEventOffsetX(evt) - 335) / 167.5;
601 var y = (getEventOffsetY(evt) - 140) / 70;
603 draw(iter, x, y, z, res);
615 function Grid(width, height, cell_size) {
616 this.width = parseInt(width / cell_size + 0.5);
617 this.height = parseInt(height / cell_size + 0.5);
618 this.canvas_width = width;
619 this.canvas_height = height;
620 this.cell_size = cell_size;
621 this.cells = new Array();
622 for (var y = 0; y < this.height; ++y) {
623 this.cells[y] = new Array();
624 for (var x = 0; x < this.width; ++x) {
625 this.cells[y][x] = new Cell(x, y, 0, this);
629 Grid.prototype.cell = function(x, y) {
630 return this.cells[y][x];
632 Grid.prototype.pick_cell = function(x, y) {
633 var lx = parseInt(x / this.cell_size - 0.5);
634 var ly = parseInt(y / this.cell_size - 0.5);
635 return this.cells[ly][lx];
638 function Cell(x, y, value, grid) {
641 this.canvas_x = x * grid.cell_size;
642 this.canvas_y = y * grid.cell_size;
645 this._neighbours = new Array();
648 Cell.prototype.hash = function() {
649 return this.x + ", " + this.y;
651 Cell.prototype.set_value = function(value) {
653 this.last_mod = $.now();
655 Cell.prototype.neighbours = function() {
656 if (this._neighbours.length) {
657 return this._neighbours;
660 this._neighbours.push(this.grid.cell(this.x-1, this.y));
662 this._neighbours.push(this.grid.cell(this.x-1, this.y-1));
663 this._neighbours.push(this.grid.cell(this.x, this.y-1));
665 if (this.y + 1 < this.grid.height) {
666 this._neighbours.push(this.grid.cell(this.x-1, this.y+1));
669 if (this.x + 1 < this.grid.width) {
670 this._neighbours.push(this.grid.cell(this.x+1, this.y));
671 if (this.y + 1 < this.grid.height) {
672 this._neighbours.push(this.grid.cell(this.x+1, this.y+1));
673 this._neighbours.push(this.grid.cell(this.x, this.y+1));
676 this._neighbours.push(this.grid.cell(this.x+1, this.y-1));
679 return this._neighbours;
681 Cell.prototype.density = function() {
683 var neighbours = this.neighbours();
684 for (var n in neighbours) {
685 d += neighbours[n].value;
690 function Simulation(canvas, w, h, cell_size, life_colour, dead_colour) {
691 this.last_update = $.now() + 3000;
693 this.last_mouse_moved = 0;
694 this.redraw = new Array();
695 this.canvas = canvas;
696 this.canvas.width = w;
697 this.canvas.height = h;
698 this.context = canvas.getContext("2d");
699 this.pos_queue = new Array();
700 this.cell_queue = new Array();
701 this.cell_size = cell_size;
702 this.life_colour = life_colour;
703 this.dead_colour = dead_colour;
704 this.grid = new Grid(this.canvas.width, this.canvas.height, cell_size);
707 Simulation.prototype.draw = function() {
709 if (this.redraw.length) {
710 var cell = this.redraw[0];
712 this.context.fillStyle = cell.value == 1 ?
713 this.life_colour.str() : this.dead_colour.str();
714 this.context.fillRect(cell.canvas_x, cell.canvas_y,
715 this.grid.cell_size, this.grid.cell_size);
716 this.last_draw = $.now();
719 Simulation.prototype.update = function() {
721 while (this.pos_queue.length) {
722 var pos = this.pos_queue.pop();
723 if (pos[0] < this.canvas.width
724 && pos[1] < this.canvas.height) {
725 var cell = this.grid.pick_cell(pos[0], pos[1]);
727 this.cell_queue.push(cell);
728 this.cell_queue.concat(cell.neighbours());
729 this.redraw.unshift(cell);
732 if (this.last_update + 1000 > now) {
735 var changed = new Array();
736 var next_cell_queue = new Array();
737 while (this.cell_queue.length) {
738 var cell = this.cell_queue.pop();
739 if (changed[cell.hash()]) {
742 var d = cell.density();
743 if (d == 3 && cell.value == 0) {
744 changed[cell.hash()] = cell;
745 next_cell_queue = next_cell_queue.concat(cell.neighbours());
746 } else if (cell.value == 1) {
747 if (d < 2 || d > 3) {
748 changed[cell.hash()] = cell;
749 next_cell_queue = next_cell_queue.concat(cell.neighbours());
753 for (var pos in changed) {
754 var cell = changed[pos];
755 cell.set_value(1 - cell.value);
756 this.redraw.push(cell);
758 this.cell_queue = next_cell_queue;
759 this.last_update = now;
761 Simulation.prototype.activate_cell = function(pos) {
762 this.pos_queue.push(pos);
764 Simulation.prototype.mouse_moved = function(pos) {
766 if (this.last_mouse_moved + 50 < now) {
767 this.pos_queue.push(pos);
768 this.last_mouse_moved = now;