Added about page.
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 == "gameoflife.html") {
42 init_gameoflife("text");
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"));
345 var offset = new Array(13, 17);
346 for (var c in text) {
348 for (p in char_map[text[c]]) {
349 var x = char_map[text[c]][p][0];
350 var y = char_map[text[c]][p][1];
352 var pos = new Array((x + offset[0]) * cell_size,
353 (y + offset[1]) * cell_size);
354 gameoflife.activate_cell(pos);
361 function Colour(r, g, b, a) {
365 this.a = a == undefined ? 255 : a;
367 Colour.prototype.equals = function(rhs) {
369 if (typeof(rhs[p]) == undefined
370 || this[p] != rhs[p]) {
376 Colour.prototype.str = function() {
377 return "rgba(" + this.r + "," + this.g + "," + this.b + "," + this.a + ")";
380 var white = new Colour(255, 255, 255);
381 var black = new Colour(0, 0, 0);
382 var orange = new Colour(201, 87, 35);
383 var green = new Colour(90, 215, 21);
384 var background = new Colour(34, 34, 34);
386 function setPixel(image, x, y, colour) {
387 var index = 4 * (x + y * image.width);
388 image.data[index] = colour.r;
389 image.data[index + 1] = colour.g;
390 image.data[index + 2] = colour.b;
391 image.data[index + 3] = colour.a;
394 function getPixel(image, x, y) {
395 var index = 4 * (x + y * image.width);
396 var r = image.data[index];
397 var g = image.data[index + 1];
398 var b = image.data[index + 2];
399 var a = image.data[index + 3];
400 return new Colour(r, g, b, a);
403 function load_random_quote() {
404 var file = "/quotes/quote" + Math.floor(Math.random() * QUOTES_NUMBER + 1) + ".html";
405 $.ajax({url: SERVER + file,
406 success: write_quote});
409 function write_quote(data, status, xhr) {
410 $("#random_quote").html(data);
413 function load_footer()
415 var file = "/footer.html";
416 var currentFile = self.location.hostname + self.location.pathname;
417 var request = http_request_object();
418 var url = "http://" + self.location.hostname + file;
419 request.open("GET", url, false);
420 request.setRequestHeader("User-Agent", navigator.userAgent);
422 // if (oRequest.status == 200) alert(oRequest.responseText);
423 // else alert("Error executing XMLHttpRequest call!");
424 //document.write(url);
425 //document.write(request.responseText);
426 document.getElementById('footer').innerHTML = request.responseText;
431 // Mandelbrot functions
432 function Complex(real, imag)
438 var MIN_C = new Complex(-2.2, -1.4);
439 var MAX_C = new Complex(1.0, 1.4);
443 var max_iter = MIN_ITER;
448 function Result(z, iter)
454 function complex_quad(c)
456 return new Complex(Math.pow(c.real, 2) - Math.pow(c.imag, 2),
457 2.0 * c.real * c.imag);
460 function complex_quad_value(c)
462 return Math.pow(c.real, 2) + Math.pow(c.imag, 2);
465 function complex_add(c1, c2)
467 return new Complex(c1.real + c2.real, c1.imag + c2.imag);
470 function complex_equal(c1, c2)
472 return (c1.real == c2.real) && (c1.imag == c2.imag);
475 function iterate(z, c)
477 z_quad = complex_quad(z);
478 return new Complex(z_quad.real + c.real, z_quad.imag + c.imag);
481 function test(c, max_iter)
484 var z = new Complex(0.0, 0.0);
485 var last_z = new Complex(-1.0, 0.0);
486 var quad_z = complex_quad_value(z);
488 while (iter < max_iter
489 && !complex_equal(z, last_z)
490 && quad_z <= bailout)
494 quad_z = complex_quad_value(z);
497 return new Result(quad_z, iter);
500 function draw(diter, dx, dy, dz, dres)
502 var canvas = document.getElementById('mandelbrot');
504 if (canvas.getContext)
507 var ctx = canvas.getContext('2d');
511 resolution = Math.max(1, resolution + dres);
516 max_iter = Math.max(MIN_ITER, max_iter + diter);
519 var red = "rgb(255, 0, 0)";
520 var white = "rgb(255, 255, 255)";
521 var width = canvas.width;
522 var height = canvas.height;
523 var dim = Math.max(width, height);
524 var dim_ratio = Math.round(width / height);
525 var diff_c = new Complex(max_c.real - min_c.real,
526 max_c.imag - min_c.imag);
527 dx_min = diff_c.real / 100 * (dx + dz);
528 dx_max = diff_c.real / 100 * (dx - dz);
530 dy_min = diff_c.imag / 100 * (dy + dz);
531 dy_max = diff_c.imag / 100 * (dy - dz);
533 var min_inc = new Complex(dx_min * dim_ratio / 2.0, dy_min);
534 var max_inc = new Complex(dx_max * dim_ratio / 2.0, dy_max);
535 min_c = complex_add(min_c, min_inc);
536 max_c = complex_add(max_c, max_inc);
537 diff_c = new Complex(max_c.real - min_c.real,
538 max_c.imag - min_c.imag);
540 for (var y = 0; y < height; y += resolution)
542 for (var x = 0; x < width; x += resolution)
544 var c = new Complex(min_c.real + diff_c.real / dim * x,
545 min_c.imag + diff_c.imag / dim * y);
546 var result = test(c, max_iter);
547 var r = Math.min(255, Math.pow(Math.max(0,
548 (result.iter - max_iter / 20.0)), 2));
549 var g = Math.min(255, Math.pow(Math.max(0,
550 (result.iter - max_iter / 25.0)), 2));
551 var b = Math.min(255, Math.pow(Math.max(0,
552 (result.iter - max_iter / 20.0)), 2));
553 var colour = "rgb(" + r + "," + g + "," + b + ")";
554 ctx.fillStyle = colour;
555 ctx.fillRect(x, y, resolution, resolution);
561 function getEventOffsetX(evt)
563 if (evt.offsetX != null)
566 var obj = evt.target || evt.srcElement;
568 return (evt.clientX - obj.pageLeft);
571 function getEventOffsetY(evt)
573 if (evt.offsetY != null)
576 var obj = evt.target || evt.srcElement;
578 return (evt.clientY - obj.pageTop);
581 function setPageTopLeft( o )
587 while (o.offsetParent)
589 left += o.offsetLeft ;
598 function draw2(evt) {
601 var x = (getEventOffsetX(evt) - 335) / 167.5;
602 var y = (getEventOffsetY(evt) - 140) / 70;
604 draw(iter, x, y, z, res);
616 function Grid(width, height, cell_size) {
617 this.width = parseInt(width / cell_size + 0.5);
618 this.height = parseInt(height / cell_size + 0.5);
619 this.canvas_width = width;
620 this.canvas_height = height;
621 this.cell_size = cell_size;
622 this.cells = new Array();
623 for (var y = 0; y < this.height; ++y) {
624 this.cells[y] = new Array();
625 for (var x = 0; x < this.width; ++x) {
626 this.cells[y][x] = new Cell(x, y, 0, this);
630 Grid.prototype.cell = function(x, y) {
631 return this.cells[y][x];
633 Grid.prototype.pick_cell = function(x, y) {
634 var lx = parseInt(x / this.cell_size - 0.5);
635 var ly = parseInt(y / this.cell_size - 0.5);
636 return this.cells[ly][lx];
639 function Cell(x, y, value, grid) {
642 this.canvas_x = x * grid.cell_size;
643 this.canvas_y = y * grid.cell_size;
646 this._neighbours = new Array();
649 Cell.prototype.hash = function() {
650 return this.x + ", " + this.y;
652 Cell.prototype.set_value = function(value) {
654 this.last_mod = $.now();
656 Cell.prototype.neighbours = function() {
657 if (this._neighbours.length) {
658 return this._neighbours;
661 this._neighbours.push(this.grid.cell(this.x-1, this.y));
663 this._neighbours.push(this.grid.cell(this.x-1, this.y-1));
664 this._neighbours.push(this.grid.cell(this.x, this.y-1));
666 if (this.y + 1 < this.grid.height) {
667 this._neighbours.push(this.grid.cell(this.x-1, this.y+1));
670 if (this.x + 1 < this.grid.width) {
671 this._neighbours.push(this.grid.cell(this.x+1, this.y));
672 if (this.y + 1 < this.grid.height) {
673 this._neighbours.push(this.grid.cell(this.x+1, this.y+1));
674 this._neighbours.push(this.grid.cell(this.x, this.y+1));
677 this._neighbours.push(this.grid.cell(this.x+1, this.y-1));
680 return this._neighbours;
682 Cell.prototype.density = function() {
684 var neighbours = this.neighbours();
685 for (var n in neighbours) {
686 d += neighbours[n].value;
691 function Simulation(canvas, w, h, cell_size, life_colour, dead_colour) {
692 this.last_update = $.now() + 3000;
694 this.last_mouse_moved = 0;
695 this.redraw = new Array();
696 this.canvas = canvas;
697 this.canvas.width = w;
698 this.canvas.height = h;
699 this.context = canvas.getContext("2d");
700 this.pos_queue = new Array();
701 this.cell_queue = new Array();
702 this.cell_size = cell_size;
703 this.life_colour = life_colour;
704 this.dead_colour = dead_colour;
705 this.grid = new Grid(this.canvas.width, this.canvas.height, cell_size);
708 Simulation.prototype.draw = function() {
710 if (this.redraw.length) {
711 var cell = this.redraw[0];
713 this.context.fillStyle = cell.value == 1 ?
714 this.life_colour.str() : this.dead_colour.str();
715 this.context.fillRect(cell.canvas_x, cell.canvas_y,
716 this.grid.cell_size, this.grid.cell_size);
717 this.last_draw = $.now();
720 Simulation.prototype.update = function() {
722 while (this.pos_queue.length) {
723 var pos = this.pos_queue.pop();
724 if (pos[0] < this.canvas.width
725 && pos[1] < this.canvas.height) {
726 var cell = this.grid.pick_cell(pos[0], pos[1]);
728 this.cell_queue.push(cell);
729 this.cell_queue.concat(cell.neighbours());
730 this.redraw.unshift(cell);
733 if (this.last_update + 1000 > now) {
736 var changed = new Array();
737 var next_cell_queue = new Array();
738 while (this.cell_queue.length) {
739 var cell = this.cell_queue.pop();
740 if (changed[cell.hash()]) {
743 var d = cell.density();
744 if (d == 3 && cell.value == 0) {
745 changed[cell.hash()] = cell;
746 next_cell_queue = next_cell_queue.concat(cell.neighbours());
747 } else if (cell.value == 1) {
748 if (d < 2 || d > 3) {
749 changed[cell.hash()] = cell;
750 next_cell_queue = next_cell_queue.concat(cell.neighbours());
754 for (var pos in changed) {
755 var cell = changed[pos];
756 cell.set_value(1 - cell.value);
757 this.redraw.push(cell);
759 this.cell_queue = next_cell_queue;
760 this.last_update = now;
762 Simulation.prototype.activate_cell = function(pos) {
763 this.pos_queue.push(pos);
765 Simulation.prototype.mouse_moved = function(pos) {
767 if (this.last_mouse_moved + 50 < now) {
768 this.pos_queue.push(pos);
769 this.last_mouse_moved = now;