<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-11885757</id><updated>2012-05-22T21:02:34.832-04:00</updated><title type='text'>Medicine for the Sky</title><subtitle type='html'>Curtis Autery's ramblings.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://cautery.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default'/><link rel='alternate' type='text/html' href='http://cautery.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default?start-index=26&amp;max-results=25'/><author><name>Curtis Autery</name><uri>https://profiles.google.com/107677530285177731535</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/--J3C_khtLqQ/AAAAAAAAAAI/AAAAAAAADT4/e2Qa5ncfAMk/s512-c/photo.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>182</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-11885757.post-9024029464091626638</id><published>2012-05-18T23:05:00.000-04:00</published><updated>2012-05-20T00:01:50.497-04:00</updated><title type='text'>Compass and Straightedge geometry meets HTML5</title><content type='html'>&lt;p&gt;This is a proof of concept build of an HTML5 engine to perform classical Greek compass and straightedge calculations, as described in &lt;a href="http://en.wikipedia.org/wiki/Compass_and_straightedge_constructions"&gt;this Wikipedia article&lt;/a&gt;. In brief, an initial set of points can be created, and then points can be connected by lines, circles can be drawn with one point as center and another as one point in the circumference, and finally the points where circles and/or lines intersect can be added as new points. With those simple rules, angles and line segments can be bisected, and certain regular (equilateral) shapes can be created. &lt;/p&gt;&lt;p&gt;I have created a rudimentary language to describe the adding of points, lines, and circles, and finding their intersections, which I discuss briefly after the demo below. Without further ado, choose a sample "program" to run to bisect an angle or create a regular shape. If you're a fan of Gauss, be sure to check out the heptadecagon. &lt;/p&gt;&lt;a name='more'&gt;&lt;/a&gt;Display area&lt;br /&gt;&lt;canvas width=640 height=480 id="cnv"&gt;&lt;/canvas&gt;&lt;br /&gt;&lt;input type=text id=delay value=250 size=4 /&gt; Frame delay (ms)&lt;br /&gt;&lt;input type=button onclick=run() value=Run /&gt;&lt;br /&gt;&lt;br /&gt;Samples&lt;br /&gt;&lt;a href=javascript:bisect()&gt;Bisect an angle&lt;/a&gt;&lt;br /&gt;&lt;a href=javascript:triangle()&gt;Construct a regular triangle&lt;/a&gt;&lt;br /&gt;&lt;a href=javascript:pentagon()&gt;Pentagon&lt;/a&gt;&lt;br /&gt;&lt;a href=javascript:hep()&gt;Heptadecagon&lt;/a&gt;&lt;br /&gt;Instructions&lt;br /&gt;&lt;textarea id="ta"&gt;&lt;/textarea&gt; &lt;style type="text/css"&gt;canvas {   border: 1px solid black;   display: block;   background:#FFF; }  textarea {   display: block;   width:640px;   height:480px;   border: 1px solid black;   padding: 0; } &lt;/style&gt; &lt;script type="text/javascript"&gt;// Things I'm allowed to do: // http://en.wikipedia.org/wiki/File:Basic-construction-demo.png var cnv, ctx; // Canvas, 2d context var cr = Math.PI * 2; var Type = {POINT : 0, LINE : 1, CIRCLE : 2}; var col, sm, interval, label; var pointRadius = 3; var textOffsetX = 5; var textOffsetY = -5; var canvasBounds = {};  function Point(x, y) {   this.x = x;   this.y = y;    this.type = Type.POINT;   this.draw = function() {     ctx.beginPath();     ctx.moveTo(this.x, this.y);     ctx.arc(this.x, this.y, pointRadius, 0, cr, false);     ctx.fill();   } }  function Circle(center, R) { // Add orientation stuff   this.center = center; // a Point   this.R = R;   this.radius = dist(center, R);   this.r2 = this.radius * this.radius;    this.type = Type.CIRCLE;   this.draw = function() {     ctx.beginPath();     ctx.moveTo(this.center.x + this.radius, this.center.y);     ctx.arc(this.center.x, this.center.y, this.radius, 0, cr, false);     ctx.stroke();   }    this.getCircleIntersect = function(circle) {     var d = dist(this.center, circle.center);     if (d &gt; this.radius + circle.radius) {       return new Intersect([], "Circles do not intersect");     }     if (d &lt; Math.abs(this.radius - circle.radius) || d == 0) {       return new Intersect([], "One circle encloses the other");     }     var a = (this.r2 - circle.r2 + d * d) / (2 * d);     var h = Math.sqrt(this.r2 - a * a);     var midX = this.center.x + a * (circle.center.x - this.center.x) / d;     var midY = this.center.y + a * (circle.center.y - this.center.y) / d;     var hyy = h * (circle.center.y - this.center.y) / d;     var hxx = h * (circle.center.x - this.center.x) / d     var points = []     points[0] = new Point(midX + hyy, midY - hxx);     // if d = r1 + r2, circles are tangent, else add second intersect point     if (d &lt; this.radius + circle.radius) {       points[1] = new Point(midX - hyy, midY + hxx);     }     return new Intersect(points, "");   }    this.getLineIntersect = function(line) {     var x1 = line.A.x - this.center.x;     var x2 = line.B.x - this.center.x;     var y1 = line.A.y - this.center.y;     var y2 = line.B.y - this.center.y;     var dx = x2 - x1;     var dy = y2 - y1;     var dr = Math.sqrt(dx * dx + dy * dy);     var dr2 = dr * dr;     var D = x1 * y2 - x2 * y1;     var D2 = D * D;     var sgn = dy &lt; 0 ? -1 : 1;     var disc = this.r2 * dr2 - D2;     if (disc &lt; 0) return new Intersect([], "Line does not intersect circle");     var points = [];     var tmpSqrt = Math.sqrt(this.r2 * dr2 - D2);     var x = (D * dy + sgn * dx * tmpSqrt)/ dr2 + this.center.x;     var y = (-D * dx + Math.abs(dy) * tmpSqrt) / dr2 + this.center.y;     points[0] = new Point(x, y);     if (disc &gt; 0) {       x = (D * dy - sgn * dx * tmpSqrt)/ dr2 + this.center.x;       y = (-D * dx - Math.abs(dy) * tmpSqrt) / dr2 + this.center.y;       points[1] = new Point(x, y);     }     return new Intersect(points, "");   } }  function Line(A, B) {   this.A = A; // A and B are Points   this.B = B;   var extended = false;   this.type = Type.LINE;    this.extend = function() {     if (extended) return;     extended = true;     // move points A and B to edge of canvas     var i = this.getLineIntersect(canvasBounds.top);     if (i.points.length == 0) i = this.getLineIntersect(canvasBounds.left);     var j = this.getLineIntersect(canvasBounds.bottom);     if (j.points.length == 0) j = this.getLineIntersect(canvasBounds.right);     this.A = i.points[0];     this.B = j.points[0];   }    this.draw = function() {     ctx.beginPath();     ctx.moveTo(this.A.x, this.A.y);     ctx.lineTo(this.B.x, this.B.y);     ctx.stroke();   }    this.getLineIntersect = function(line) {     var x1 = this.A.x;     var x2 = this.B.x;     var x3 = line.A.x;     var x4 = line.B.x;     var y1 = this.A.y;     var y2 = this.B.y;     var y3 = line.A.y;     var y4 = line.B.y;          var denom = det(x1 - x2, y1 - y2, x3 - x4, y3 - y4);     if (denom == 0) return new Intersect([], "Lines don't intersect");     var leftA = det(x1, y1, x2, y2);     var leftC = det(x3, y3, x4, y4);     var x = det(leftA, x1 - x2, leftC, x3 - x4) / denom;     var y = det(leftA, y1 - y2, leftC, y3 - y4) / denom;     return new Intersect([new Point(x, y)], "");   } }  function det(a, b, c, d) { // Determinate in format |a b| //                       |c d|   return a * d - b * c; }  function dist(A, B) {   var x = A.x - B.x;   var y = A.y - B.y;   return Math.sqrt(x * x + y * y); }  function Intersect(points, message) {   this.points = points;   this.message = message; }  function init() {   if (interval != null) clearInterval(interval);   cnv = document.getElementById('cnv');   var tl = new Point(0, 0);   var tr = new Point(cnv.width, 0);   var bl = new Point(0, cnv.height);   var br = new Point(cnv.width, cnv.height);   canvasBounds.top    = new Line(tl, tr);   canvasBounds.bottom = new Line(bl, br);   canvasBounds.left   = new Line(tl, bl);   canvasBounds.right  = new Line(tr, br);    ctx = cnv.getContext('2d');   ctx.translate(.5, .5);   ctx.strokeStyle = "black";   col = {};   sm = new StepManager();   bisect(); }  function frame() {   sm.frame(); }  function drawBoard() { // Clear board   ctx.clearRect(0, 0, cnv.width, cnv.height)  // Draw current label, if any   if (label != "") ctx.fillText(label, 20, 20);  // Iterate through collection (col) of points, lines and circles, and call their draw() methods   for (var e in col) {     var elem = col[e];     elem.draw();     // ...and label the points     if (elem.type == Type.POINT) {       ctx.fillText(e, elem.x + textOffsetX, elem.y + textOffsetY);     }   } }  function run() {   col = {};   if (interval != null) clearInterval(interval);   sm.init(document.getElementById('ta').value.split(/\n+/));   interval = setInterval(frame, document.getElementById('delay').value); }  function StepManager() {   var index, done, i, steps;    this.init = function(s) {     steps = s;     i = null;     index = 0;     done = false;     label = "";     drawBoard();   }    function point(x, y, name) {     y = parseInt(y);     if (x == 'i') col[name] = i.points[y];     else col[name] = new Point(parseInt(x), y);   }    function line(a, b) {     var name = '_ln_' + a + '_' + b;     col[name] = new Line(col[a], col[b]);   }    function extend(a, b) {      var name = '_ln_' + a + '_' + b;     col[name].extend();   }    function circle(a, b) {     var name = '_cr_' + a + '_' + b;     col[name] = new Circle(col[a], col[b]);   }    function getObj(type, a, b) {     return col[nameFromElems(type, a, b)];   }    function intersect(typeA, a, b, typeB, c, d) {     var objA = getObj(typeA, a, b);     var objB = getObj(typeB, c, d);     if (typeB == "circle") i = objA.getCircleIntersect(objB);     else i = objA.getLineIntersect(objB)   }    function nameFromElems(type, a, b) {     if (type == "circle")return '_cr_' + a + '_' + b;     if (type == "line")  return '_ln_' + a + '_' + b;     return a;   }    function deleteObj(type, a, b) {     delete(col[nameFromElems(type, a, b)]);   }    function display(msg) {     label = msg;   }    this.frame = function() {     if (done == true) {       clearInterval(interval);     }     else this.nextStep();     drawBoard();   }    this.nextStep = function() {     if (index &gt;= steps.length) {       done = true;       display("done");       return;     }     var step = steps[index++];     if (step.charAt(0) == '#') this.nextStep();     else if (step.charAt(0) == ':') {       display(step.substr(1));     } else {       var elems = step.split(' ');       switch(elems[0]) {       case '': return;       case 'point':         point(elems[1], elems[2], elems[3]);         break;       case 'circle':         circle(elems[1], elems[2]);         break;       case 'line':         line(elems[1], elems[2]);         break;       case 'extend':         extend(elems[1], elems[2]);         break;       case 'intersect':         intersect(elems[1], elems[2], elems[3], elems[4], elems[5], elems[6]);         this.nextStep();         break;       case 'delete':         deleteObj(elems[1], elems[2], elems[3]);         break;       default:         display("Unknown step type: " + elems[0]);         done = true;         return;       }     }   }  }  function bisect() {   document.getElementById('ta').value = "#Bisect an angle\n:Draw angle ABC\npoint 280 100 A\npoint 320 240 B\npoint 420 240 C\nline A B\nline B C\n:Draw circle at B with C radius\ncircle B C\n:Mark intersect point of circle and line AB as D\nintersect circle B C line A B\npoint i 1 D\n:Draw circles DB and CB\ncircle D B\ncircle C B\n:Mark intersect point of two new circles (other than B) as E\nintersect circle D B circle C B\npoint i 0 E\n:Draw bisecting line BE\nline B E\nextend B E\n:Erase chaff\ndelete circle D B\ndelete circle C B\ndelete point D\ndelete circle B C\n"; }  function hep() {   document.getElementById('ta').value = "#Construct a regular 17-gon\n:Draw origin and P1, circle, and diameter\npoint 320 300 O\npoint 490 300 P1\ncircle O P1\nline O P1\nextend O P1\n\n:Find perpendicular bisector of diameter\nintersect circle O P1 line O P1\npoint i 1 tmp\ncircle tmp P1\ncircle P1 tmp\nintersect circle tmp P1 circle P1 tmp\npoint i 0 b1\nline b1 O\nintersect circle O P1 line b1 O\npoint i 1 B\ndelete circle tmp P1\ndelete circle P1 tmp\ndelete point tmp\ndelete line b1 O\ndelete point b1\nline O B\n\n:Create point J 1/4 of the way up OB\ncircle B O\nintersect circle B O circle O P1\npoint i 1 b1\npoint i 0 b2\nline b1 b2\nintersect line O B line b1 b2\npoint i 0 tmp\ndelete circle B O\ndelete line b1 b2\ndelete point b1\ndelete point b2\ncircle O tmp\ncircle tmp O\nintersect circle O tmp circle tmp O\npoint i 0 b1\npoint i 1 b2\nline b1 b2\nline O tmp\nintersect line b1 b2 line O tmp\npoint i 0 J\ndelete circle O tmp\ndelete circle tmp O\ndelete point tmp\ndelete line b1 b2\ndelete point b1\ndelete point b2\ndelete line O tmp\n\n:Create line JP1 and find E on bisector line where OJE is 1/4 of OJP1\nline J P1\ncircle J O\nintersect circle J O line J P1\npoint i 0 tmp\ncircle O J\ncircle tmp J\nintersect circle O J circle tmp J\ndelete point tmp\npoint i 1 t\nline J t\ndelete circle tmp J\nintersect circle J O line J t\npoint i 0 tmp\nline J tmp\ndelete line J t\ndelete point t\ndelete circle J O\ncircle tmp J\nintersect circle O J circle tmp J\npoint i 1 t\nline J t\ndelete circle O J\ndelete circle tmp J\ndelete line J tmp\ndelete point tmp\nintersect line O P1 line J t\npoint i 0 E\nline J E\ndelete line J t\ndelete point t\n\n:create F on circle bisect line such that EJF is 45 degrees\ncircle J E\nextend J E\nintersect circle J E line J E\npoint i 1 tmp\ncircle tmp E\ncircle E tmp\nintersect circle tmp E circle E tmp\npoint i 1 t\nline J t\ndelete circle tmp E\ndelete circle E tmp\ndelete point tmp\nline J E\nintersect circle J E line J t\npoint i 0 tmp\ndelete line J t\ndelete point t\ncircle E J\ncircle tmp J\nintersect circle E J circle tmp J\npoint i 0 t\nline J t\ndelete circle E J\ndelete circle tmp J\ndelete point tmp\ndelete circle J E\nintersect line O P1 line J t\npoint i 0 F\nline J F\ndelete line J t\ndelete point t\n\n:Create circle with diameter F P1\ncircle F P1\ncircle P1 F\nintersect circle F P1 circle P1 F\npoint i 0 b1\npoint i 1 b2\nline b1 b2\nintersect line b1 b2 line O P1\npoint i 0 t\ndelete circle F P1\ndelete circle P1 F\ndelete line b1 b2\ndelete point b1\ndelete point b2\ncircle t P1\nintersect circle t P1 line O B\npoint i 1 K\ndelete point t\ncircle E K\nintersect circle E K line O P1\npoint i 0 N4\n\n:Create perpendicular line through OP1 at N4\ncircle N4 E\nintersect circle N4 E line O P1\npoint i 0 t\ncircle t E\ncircle E t\nintersect circle t E circle E t\npoint i 1 b1\nline N4 b1\ndelete circle t E\ndelete circle E t\ndelete circle N4 E\ndelete point t\nextend line N4 b1\n\n:Perpendicular line at N4 cuts circle O P1 at P4\nintersect circle O P1 line N4 b1\npoint i 1 P4\nline N4 P4\ndelete line N4 b1\ndelete point b1\n\n:Delete artifacts\ndelete circle t P1\ndelete circle E K\ndelete point K\ndelete line J F\ndelete point F\ndelete line J E\ndelete point E\ndelete line J P1\ndelete point J\ndelete line N4 P4\ndelete point N4\ndelete line O B\ndelete point B\n\n:Create remaining 15 points using P1/P4 as initial radius\ncircle P4 P1\nintersect circle O P1 circle P4 P1\npoint i 0 P7\ndelete circle P4 P1\ncircle P7 P4\nintersect circle O P1 circle P7 P4\npoint i 0 P10\ndelete circle P7 P4\ncircle P10 P7\nintersect circle O P1 circle P10 P7\npoint i 0 P13\ndelete circle P10 P7\ncircle P13 P10\nintersect circle O P1 circle P13 P10\npoint i 0 P16\ndelete circle P13 P10\ncircle P16 P13\nintersect circle O P1 circle P16 P13\npoint i 0 P2\ndelete circle P16 P13\ncircle P2 P16\nintersect circle O P1 circle P2 P16\npoint i 0 P5\ndelete circle P2 P16\ncircle P5 P2\nintersect circle O P1 circle P5 P2\npoint i 0 P8\ndelete circle P5 P2\ncircle P8 P5\nintersect circle O P1 circle P8 P5\npoint i 0 P11\ndelete circle P8 P5\ncircle P11 P8\nintersect circle O P1 circle P11 P8\npoint i 0 P14\ndelete circle P11 P8\ncircle P14 P11\nintersect circle O P1 circle P14 P11\npoint i 0 P17\ndelete circle P14 P11\ncircle P17 P14\nintersect circle O P1 circle P17 P14\npoint i 0 P3\ndelete circle P17 P14\ncircle P3 P17\nintersect circle O P1 circle P3 P17\npoint i 0 P6\ndelete circle P3 P17\ncircle P6 P3\nintersect circle O P1 circle P6 P3\npoint i 0 P9\ndelete circle P6 P3\ncircle P9 P6\nintersect circle O P1 circle P9 P6\npoint i 0 P12\ndelete circle P9 P6\ncircle P12 P9\nintersect circle O P1 circle P12 P9\npoint i 0 P15\ndelete circle P12 P9\n\n:Connect the dots\nline P1 P2\nline P2 P3\nline P3 P4\nline P4 P5\nline P5 P6\nline P6 P7\nline P7 P8\nline P8 P9\nline P9 P10\nline P10 P11\nline P11 P12\nline P12 P13\nline P13 P14\nline P14 P15\nline P15 P16\nline P16 P17\nline P17 P1\ndelete circle O P1\ndelete line O P1\ndelete point O"; }  function triangle() {   document.getElementById('ta').value = "#Construct an equilateral triangle\n:Draw origin and P0, circle, and diameter\npoint 320 300 O\npoint 490 300 P0\ncircle O P0\nline O P0\nextend O P0\n\n:Find perpendicular bisector of diameter\nintersect circle O P0 line O P0\npoint i 1 tmp\ncircle tmp P0\ncircle P0 tmp\nintersect circle tmp P0 circle P0 tmp\npoint i 0 b1\nline b1 O\nintersect circle O P0 line b1 O\npoint i 1 B\ndelete circle tmp P0\ndelete circle P0 tmp\ndelete point tmp\ndelete line b1 O\ndelete point b1\nline O B\n\n:Circle BO cuts circle O P0 at top two points of triangle\ncircle B O\nintersect circle O P0 circle B O\npoint i 0 P1\npoint i 1 P2\nline P1 P2\ndelete circle B O\n\n:Extend line OB to other end of circle to find final point of triangle\nextend O B\nintersect circle O P0 line O B\npoint i 0 P3\nline P1 P3\nline P3 P2\ndelete line O B\ndelete point B\ndelete line O P0\ndelete point P0\ndelete point O\ndelete circle O P0"; }  function pentagon() {   document.getElementById('ta').value = "#Construct a regular pentagon\n:Draw origin and P1, circle, and diameter\npoint 320 300 O\npoint 490 300 P1\ncircle O P1\nline O P1\nextend O P1\n\n:Find perpendicular bisector of diameter\nintersect circle O P1 line O P1\npoint i 1 tmp\ncircle tmp P1\ncircle P1 tmp\nintersect circle tmp P1 circle P1 tmp\npoint i 0 b1\nline b1 O\nintersect circle O P1 line b1 O\npoint i 1 B\ndelete circle tmp P1\ndelete circle P1 tmp\ndelete point tmp\ndelete line b1 O\ndelete point b1\nline O B\n\n:Bisect line OB at point D, connect to P1\ncircle B O\nintersect circle B O circle O P1\npoint i 1 b1\npoint i 0 b2\nline b1 b2\nintersect line O B line b1 b2\npoint i 0 D\ndelete circle B O\ndelete line b1 b2\ndelete point b1\ndelete point b2\nline D P1\n\n:Bisect angle ODP1, connect to line OP1 as N2\ncircle D O\nintersect circle D O line D P1\npoint i 0 tmp\ndelete circle D O\ncircle O D\ncircle tmp D\nintersect circle O D circle tmp D\npoint i 1 t\nline D t\ndelete circle O D\ndelete circle tmp D\ndelete point tmp\nintersect line O P1 line D t\npoint i 0 N2\nline D N2\ndelete line D t\ndelete point t\n\n:Line at N2 perpendicular to line OP1 is point P2\ncircle N2 O\nintersect circle N2 O line O P1\npoint i 0 t\ncircle O t\ncircle t O\ndelete circle N2 O\nintersect circle O t circle t O\npoint i 0 b1\nline b1 N2\nextend b1 N2\ndelete circle O t\ndelete circle t O\ndelete point t\nintersect circle O P1 line b1 N2\npoint i 1 P2\ndelete point b1\nline N2 P2\ndelete line b1 N2\n\n:Delete artifacts\ndelete line N2 P2\ndelete line D N2\ndelete point N2\ndelete line D P1\ndelete point D\ndelete line O B\ndelete point B\n\n:Create remaining 3 points using P1/P2 as initial radius\ncircle P2 P1\nintersect circle O P1 circle P2 P1\npoint i 0 P3\ndelete circle P2 P1\ncircle P3 P2\nintersect circle O P1 circle P3 P2\npoint i 0 P4\ndelete circle P3 P2\ncircle P4 P3\nintersect circle O P1 circle P4 P3\npoint i 0 P5\ndelete circle P4 P3\n\n:Connect the dots\nline P1 P2\nline P2 P3\nline P3 P4\nline P4 P5\nline P5 P1\ndelete line O P1\ndelete circle O P1\ndelete point O"; }  init(); &lt;/script&gt; &lt;p class="section" style="clear:both"&gt;The language&lt;/p&gt;&lt;ul&gt;&lt;li /&gt;point [x] [y] [name] &lt;br /&gt;This creates a point at canvas position [x,y], and labels it [name]. This is intended only to be used for creating starting points to be used by the remaining commands. In HTML5 canvases, point 0,0 is the upper-left corner, and numbers increase as you move right and down. &lt;li /&gt;line [a] [b] &lt;br /&gt;This draws a line between points a and b. &lt;li /&gt;circle [a] [b] &lt;br /&gt;This draws a circle centered at point a, with point b as a point on the circumference (line ab describes the circle's radius) &lt;li /&gt;intersect [circle|line] [a] [b] [circle|line] [c] [d] &lt;br /&gt;Identify's the intersection points between two circles, two lines, or a circle and a line (for this last combination, specify the circle first). This doesn't add any new points, it just identifies the intersections. A separate "point" command must follow an intersect command to add new points &lt;li /&gt;point i [0|1] [a] &lt;br /&gt;This creates a new point [a] based on the two possible results of the last "intersect" command. You will need to test whether intersect point 0 or 1 is the one you need. In fact, if you're building your own program, you'll want to do several tests as you go. I recommend setting the frame delay to 0 before testing to speed things up. &lt;li /&gt;: [text] &lt;br /&gt;Sets the current "label" in the display area, used for giving the audience an idea about what they're looking at. &lt;li /&gt;# [comment] &lt;br /&gt;Comments in the instructions that aren't shown in the display area &lt;/ul&gt;Enjoy!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11885757-9024029464091626638?l=cautery.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cautery.blogspot.com/feeds/9024029464091626638/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://cautery.blogspot.com/2012/05/compass-and-straightedge-geometry-meets.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/9024029464091626638'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/9024029464091626638'/><link rel='alternate' type='text/html' href='http://cautery.blogspot.com/2012/05/compass-and-straightedge-geometry-meets.html' title='Compass and Straightedge geometry meets HTML5'/><author><name>Curtis Autery</name><uri>https://profiles.google.com/107677530285177731535</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/--J3C_khtLqQ/AAAAAAAAAAI/AAAAAAAADT4/e2Qa5ncfAMk/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11885757.post-967219085563953290</id><published>2012-05-10T21:32:00.000-04:00</published><updated>2012-05-10T21:32:10.209-04:00</updated><title type='text'>Animated prime number machine</title><content type='html'>&lt;p&gt;This uses the HTML5 canvas architecture, so no IE8 or less; sorry. I have only tested it with Google Chrome, so it may not work in other HTML5-capable browsers. If you find this to be the case, please leave feedback with any errors you see, and what browser version you're using, and I'll see what I can do to get it working for you. &lt;/p&gt;&lt;p&gt;The principle of the prime number machine is of rolling coins and elevators. I created this because I thought it would be neat to have a way for prime numbers to be produced by a set of mechanical rules rather than with pure mathematical methods. Here is a basic description of the rules: &lt;ul&gt;&lt;li /&gt;If a coin rolls into an empty box, it creates an elevator with the height shown on the coin, and a new empty box appears. &lt;li /&gt;If a coin hits the top or bottom of an existing elevator, it bounces off with no effect. &lt;li /&gt;The coin's number increments after each cycle &lt;li /&gt;The elevators go down a floor during each cycle until the top car is flush with the ground line, then they begin going back up to where they started. &lt;/ul&gt;&lt;/p&gt;&lt;p&gt;This results in two basic phenomena: All new elevators correspond to prime numbers. When a coin does not have a prime number on it, all of the elevators corresponding to the coin's prime factors have a car flush with the ground. &lt;/p&gt;&lt;p&gt;Enjoy!&lt;/p&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;canvas width=640 height=480 id="cnv"&gt;&lt;/canvas&gt; &lt;style type="text/css"&gt;canvas {   border: 1px solid black;   margin: 0 auto;   display: block; } &lt;/style&gt; &lt;script type="text/javascript"&gt;var cnv, ctx; // Canvas, 2d context  var elevatorLeft = 30; var columnWidth = 25; var barWidth = 20; var rowHeight = 25; var barHeight = 16; var textOffsetX = 9; var textOffsetY = 11;  var bw2 = barWidth / 2; var speed = 1;  var em = new ElevatorManager(); var mh = new ModeHandler(); var ball = new Ball(); var interval; var centerY, baseY;  function init() {   if (interval != null) clearInterval(interval);   cnv = document.getElementById('cnv');   ctx = cnv.getContext('2d');   ctx.translate(.5, .5);   ctx.strokeStyle = "black";   ctx.textAlign = "center";   centerY = cnv.height / 2;   baseY = centerY - barHeight;   mh.init();   ball.init();   em.init();   em.add();   interval = setInterval(frame, 0); //  frame(); }  function frame() {   if (mh.isGameOver()) {     clearInterval(interval);     return;   }   mh.isModeDone() ? mh.nextMode() : mh.nextFrame();   drawBoard(); }  function drawBoard() { // Clear board   ctx.clearRect(0, 0, cnv.width, cnv.height)  // Draw elevators   em.draw();  // Draw ball   ball.draw();  // Draw center line   ctx.strokeRect(0, centerY, cnv.width, 0); }  function ModeHandler() { // ROLL_BALL adds an elevator if nothing is blocking // MOVE_ELEVATORS starts with incrementing ballNum   var Mode = {     FIND_BALL_DEST    : 0   , ROLL_BALL         : 1   , ADD_ELEVATOR      : 2   , INCREMENT_BALLNUM : 3   , MOVE_ELEVATORS    : 4   };    var mode, gameOver, modeDone;    var mode, gameOver, modeDonel   this.init = function() {     mode = Mode.FIND_BALL_DEST;     gameOver = false;     modeDone = false;   }   this.init();    this.isGameOver = function() { return gameOver; }   this.isModeDone = function() { return modeDone; }   var setModeDone = function() { modeDone = true; }    this.nextMode = function() {     if (++mode &gt; 4) mode = 0;     modeDone = false;   }    this.nextFrame = function() {     if (mode == Mode.FIND_BALL_DEST) {       //       if (ball.getNum() &gt; 89) {         gameOver = true;         return;       }       ball.setDestPos(em.findDestPos());       modeDone = true;       return;     }     if (mode == Mode.ROLL_BALL) {       //       ball.frame(setModeDone);       return;     }     if (mode == Mode.ADD_ELEVATOR) {       //       if (!em.isBlocking()) em.setPrime(ball.getNum());       modeDone = true;       return;     }     if (mode == Mode.INCREMENT_BALLNUM) {       ball.inc();       modeDone = true;       return;     }     if (mode == Mode.MOVE_ELEVATORS) {       //       em.frame(setModeDone);     }   }  }  function ElevatorManager() {   var elevators, frameNum;   var initialized = false;   var blocking;    this.init = function() {     elevators = [];     frameNum = 0;     done = false;     initialized = true;     blocking = false;   }    this.isDone = function() { return done; }   this.isBlocking = function() { return blocking; }    this.add = function() {     if (!initialized) init();     var el = elevators.length;     elevators[el] = new Elevator(el);   }    this.frame = function(callback) {     if (done == true) done = false;     for (var n = 0; n &lt; elevators.length; n++) {       var e = elevators[n];       e.offset = frameNum;     }     if (++frameNum &gt;= rowHeight) {       frameNum = 0;       increment();       callback();     }   }    this.findDestPos = function() {     var el = elevators.length - 1; // Last elevator doesn't block     for (var n = 0; n &lt; el; n++) {       if (elevators[n].isBlocking()) {         blocking = true;         return elevatorLeft + n * columnWidth;       }     }     blocking = false;     return elevatorLeft + el * columnWidth + bw2;   }     function increment() {     var el = elevators.length - 1; // Last elevator doesn't get incremented     for (var n = 0; n &lt; el; n++) {       var e = elevators[n];       e.increment();     }   }    this.setPrime = function(n) {     elevators[elevators.length - 1].setPrime(n);     this.add();   }    this.draw = function() {     for (var n = 0; n &lt; elevators.length; n++) {       elevators[n].draw();     }   } }  function Elevator(pos) {   var prime  = null;   var currentHeight = 0;   var inc  = 0;   var baseX = pos * columnWidth + elevatorLeft;   var length = 0;   this.offset = 0;   var y = baseY;   var bl, bly;    this.draw = function() {     ctx.save();     ctx.translate(baseX, y - inc * this.offset);     ctx.strokeRect(0, 0, barWidth, barHeight);     if(prime != null) {       ctx.strokeRect(bw2, barHeight, 0, length);       ctx.strokeRect(0, bl, barWidth, barHeight);       ctx.fillText(prime, textOffsetX, textOffsetY);       ctx.fillText(prime, textOffsetX, bly);     }     ctx.restore();   }    this.setPrime = function(n) {     prime = n;     length = n * rowHeight - barHeight;     currentHeight = n;     inc = -1;     y = baseY - n * rowHeight;     bl = length + barHeight;     bly = bl + textOffsetY;   }    this.increment = function() {     currentHeight += inc;     y = baseY - currentHeight * rowHeight;     this.offset = 0;     if (this.isBlocking()) inc *= -1;   }    this.isBlocking = function() {     return (currentHeight == 0 || currentHeight == prime);   } }  function Ball() {   var num, destPos, angle, x;   var cr = Math.PI*2;  // a circle, in radians   var y, rotateStep;    this.init = function() {     num = 2;     y = centerY - bw2;     rotateStep = 2 * speed / columnWidth;     this.reset();   }    this.reset = function() {     x = bw2;     destPos = 0;     angle = 0;   }    this.setDestPos = function(n) { if (destPos == 0) destPos = n; }    this.draw = function() {     // draw Circle at current location     ctx.beginPath();     ctx.moveTo(x + bw2, y);     ctx.arc(x, y, bw2, cr, false);     ctx.stroke();      // draw num in circle, rotated at current angle     ctx.save();     ctx.translate(x, y);     ctx.rotate(angle);     ctx.fillText(num, 0, 3);     ctx.restore();   }    this.frame = function(callback) {     if (x &gt;= destPos) {       callback();       return;     }     x += speed;     angle += rotateStep;   }    this.inc = function() {     num++;     if (num == 30) speed = 2;     this.reset();   }    this.getNum = function() { return num; } }   init(); &lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11885757-967219085563953290?l=cautery.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cautery.blogspot.com/feeds/967219085563953290/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://cautery.blogspot.com/2012/05/animated-prime-number-machine.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/967219085563953290'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/967219085563953290'/><link rel='alternate' type='text/html' href='http://cautery.blogspot.com/2012/05/animated-prime-number-machine.html' title='Animated prime number machine'/><author><name>Curtis Autery</name><uri>https://profiles.google.com/107677530285177731535</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/--J3C_khtLqQ/AAAAAAAAAAI/AAAAAAAADT4/e2Qa5ncfAMk/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11885757.post-3799777866509520020</id><published>2011-12-07T17:27:00.000-05:00</published><updated>2011-12-07T18:06:23.588-05:00</updated><title type='text'>Encounters with the police</title><content type='html'>&lt;p&gt;The cops have had an awful lot of bad press lately, for example the interactions with OWS protestors such as &lt;a href="http://www.news.com.au/top-stories/police-criticised-after-tent-dress-torn-off-occupy-protester/story-e6frfkp9-1226215166929"&gt;this one&lt;/a&gt;, and &lt;a href="http://www.heraldtribune.com/article/20111204/ARTICLE/111209980/2416/NEWS?Title=SPECIAL-REPORT-How-Florida-s-rogue-officers-remain-on-the-job&amp;tc=ar"&gt;this sobering article&lt;/a&gt; from the Sarasota Herald-Tribune, or &lt;a href="http://news.yahoo.com/swat-teams-shooting-marine-causes-outrage-184928360.html"&gt;this report&lt;/a&gt; of a former marine killed in his home by a SWAT team who erroneously thought he was a drug dealer. And erroneously thought their team member who tripped had just been shot. &lt;/p&gt;&lt;p&gt;My personal encounters with law enforcement have been qualitatively different. I have interacted with the police 26 times, and although that number seems large, none of them ended in an arrest, and in only two seemed like good material for an episode of Cops. In rough order of occurrence (I'm approximating my age on a few of these), they are: &lt;a name='more'&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;1. When I was about 13, I was on a canoe trip where a boy drowned, and the police were called to investigate. A friend of the victim broke down crying at one point, and the officer taking the report was very consoling to her. &lt;/p&gt;&lt;p&gt;2. At 15, my bicycle was stolen. My stepfather called the police, an officer came to our apartment to take a report. Our apartment smelled of weed most of the time, as my folks smoked quite a bit of it. The officer either didn't notice, or didn't mention it. He took the report, informed us that it's rare to make a recovery, but they would nonetheless give it the ol' college try. &lt;/p&gt;&lt;p&gt;3. At 16, a pair of officers knocked on our open apartment door late one night when we were sleeping, to verify we weren't being robbed. I assume a neighbor saw the door accidentally left open and called on our behalf. &lt;/p&gt;&lt;p&gt;4. Also at about 16, a group of my friends and I were horsing around at Graceland shopping center, jumping up and smacking a high awning. We were mainly just seeing who could jump higher and not trying to vandalize it. A patrol car slowed down and warned us to knock it off. &lt;/p&gt;&lt;p&gt;5. At 17, I took a late-night walk, and ended up near some closed office buildings. A patrol car came to make sure I wasn't vandalizing the buildings or trying to break in. I was in sort of a bleak mood that night, prompting them to give me the "Problems at home?" quiz. I passed, apparently, and they shood me on, asking me only to stay on the sidewalk so as not to look like a prowler. &lt;/p&gt;&lt;p&gt;6. At 18, my car was in the shop, and I wanted a late-night snack, so I walked down to a local gas station. I took a shortcut back home, crossing through a car dealership and onto the train tracks behind it (Jack Maxton Chevrolet by 161 and Proprietors, if you're familiar with Worthington). Unbeknownst to me, a car had recently been stolen there the previous night, so the police were patrolling around it more. An officer jogged up to me on the railroad tracks, but saw that I was just drinking my Mountain Dew and strolling along, so he explained all this to me. When he asked my name, he even went so far as to say I wasn't obligated to answer. I cooperated, said I'd stick to the sidewalks in the future, and he let me go. &lt;/p&gt;&lt;p&gt;7. My first speeding ticket, and the first time I thought I was about to get shot. At 18, I thought I was invincible behind the wheel of a car, and took late-night drives through the hilly backroads between Worthington and Linworth, and just went nuts, flying around curves, pedal pegged. During one of these outings, a cop passed me going the other way. For some reason, I assumed he wouldn't even try to turn around and catch up to me. About a mile and a half later, I was proven wrong when I saw his lights in my rear-view mirror. &lt;/p&gt;&lt;p&gt;I pulled over, and I knew that I would be asked for my registration, which was in the glove box... you can see where this is going, can't you? As the officer approached my window, he saw me rooting around in the glove box, and barked out a sharp "HANDS ON THE WHEEL!". I complied immediately. He followed this by questions about my drinking (none, by the way, I didn't start drinking until my late 30s), how he'd like nothing more than to haul me away to jail, but a moving violation wasn't enough cause, and he left me with a ticket, and went on his way. &lt;/p&gt;&lt;p&gt;A lot of that was basic "scared straight" material, which I saw for what it was, but I reflected a lot on how he seemed ready to draw on me when he saw me in the glove box, and I decided to stop driving like a maniac. In hindsight, this probably saved my life, as I was less likely to wreck in an infrequently traveled backroad in the middle of the night. &lt;/p&gt;&lt;p&gt;8. At 19, my cousin Glenn and I were driving back from a city east of Winston Salem, NC (possibly Raleigh, but I can't remember for sure) where we were helping to open a new "Shoe Show" store. I was a passenger, and Glenn was trying to make good time on the way back. A state trooper pulled him over for speeding, and asked him to step out of the car. &lt;/p&gt;&lt;p&gt;As it turns out, this wasn't a bad thing, the officer just wanted to scold Glenn in private rather than embarrass him in front of me (southern politeness - I was still sort of a kid, making Glenn, about 10 years my senior, an authority figure by default. It would demean that authority to get publicly scolded. This probably sounds confusing to you Yankees, but that type of thing is a standard tenet of our culture). Glenn was completely "yes, sir" and "no, sir" to the officer, who let him off with a warning. &lt;/p&gt;&lt;p&gt;9. At 19, I was a passenger in a car with my friend Steve, who suffers from sleep apnea. We were both beat after coming home from either a party or a concert, and he swerved a little, and was pulled over. After the officer assessed that we were both just tired and not drunk, he told Steve to be careful and try to get off the road soon and find a bed. &lt;/p&gt;&lt;p&gt;10. At 20, I would typically close the pizza store I worked at, and then head off to a 24 hour gym to work out before I went home. On one particular night, I went flying through a speed trap, and was pulled over. The officer asked me where I was going in such a hurry. "World's Gym," I replied. &lt;/p&gt;&lt;p&gt;As luck would have it, that was the gym that a lot of police officers worked out at. I was let go with a warning (possibly from the serendipitousness of my destination), and also informed that one of my brake lights was out. &lt;/p&gt;&lt;p&gt;11. At the tail-end of my reckless youth, I liked to play on playgrounds in the middle of the night with friends. On one particular night, my friend Lisa and I stopped by Colonial Hills Elementary at about midnight after picking up some Jolly Pirate donuts. We sat on top of the school's jungle gym, ate our donuts, and chatted. &lt;/p&gt;&lt;p&gt;After a while, a cruiser pulled up and shone its lights at us. The officer asked what we were doing, and I flashed him the Jolly Pirate bag I was holding. "Just eating some donuts". He then asked our ages (18 for her, 20 for me), and then told us simply to "stay out of trouble". He left, without even demanding we leave the school. &lt;/p&gt;&lt;p&gt;12. At 21, the pizza store I worked for had run out of an ingredient, and I was sent to another store to borrow some. Trying to hurry back, I ended up read-ending someone who stopped suddenly. The police arrived to take a report, where I admitted I was at fault and was cited for unassured clear distance. &lt;/p&gt;&lt;p&gt;13. Also at about 21, I was pulled over for speeding on the West Virginia turnpike. The state trooper invited me back to his patrol car, where I sat in the front as he filled out my ticket. He was very chatty, and was listening to classic rock in his car. I think maybe he was just lonely and wanted someone to talk to. Nice guy, if you don't count that he gave me a $60 ticket. &lt;/p&gt;&lt;p&gt;14. At 22, I was an assistant manager at a pizza store, and had a free night with nothing to do at 12:30am. I decided to play a prank on that night's closing manager, so I parked in the empty lot next to our store and snuck over, then quickly unlocked the back door and jumped in to the suprise of the people doing closing cleaning and paperwork. &lt;/p&gt;&lt;p&gt;Meanwhile, a patrol noticed my car in an empty parking lot, and ran my plates. By some means, they put two and two together and phoned the store and asked if I was inside... then asked me to come outside. I did, and the two officers spread out around me until they formed an equilateral triangle with me as the third point. They were clearly on edge and expecting trouble. &lt;/p&gt;&lt;p&gt;It turned out that I had never paid my ticket from number 13. Combine that with my car being in a vacant parking lot, and they thought maybe I was a criminal robbing the store. A few minutes of conversation assured them otherwise, and they ended up not citing me with anything, but taking my car's license plates (!) until the matter with the West Virginia tickets was resolved. &lt;/p&gt;&lt;p&gt;I'm not sure if taking my plates was legal or warranted, and it did come close to causing me to lose my job (managers have to be able to drive). I managed to get the ticket cleared up in a few days, and got my plates returned to me, so there wasn't any long-term consequence. &lt;/p&gt;&lt;p&gt;15. Also as 22, shortly before stepping down from pizza management to the less stressful and equal paying job of delivery boy, an officer came into my store to pick up a pizza. This happened a lot, and I haven't listed the score or so times I've handed an officer a pie and told him to have a nice day. In this instance, however, a young man, college age, who was in the store prior to the officer's arrival stiffened and was visibly nervous. His order came up first, so I handed it to him. He said an abrupt "thanks", and quickly left the store. &lt;/p&gt;&lt;p&gt;After he left, I mentally played back the conversation he had with Dave, my inside closing help that night, and didn't remember him ringing the man up. "Did he pay?" I called to Dave. He replied "I thought you rung him up." &lt;/p&gt;&lt;p&gt;Without speaking to us, the officer (Shicks, I think, from the Westerville police) got on his shirt-mounted CB and called for a car to come pull the guy over as he drove away. Being a trained observer, he knew the make, model, and color of the car, the road the car left on and which direction he went. &lt;/p&gt;&lt;p&gt;About 10 seconds later a police car with lights flashing came flying past the store. About 5 minutes after that, the ghost-white, shaking man came back in, stammered out "I'm so sorry," and paid for his food. Our running theory is that he was holding, and thought he was about to get busted. To my knowledge, the officers didn't pursue that angle. Scaring the crap out of a college boy is more fun than a nickle-bag bust, I imagine, plus the amount of paperwork to show probable cause for a search was probably insane back in the pre-9/11 days. &lt;/p&gt;&lt;p&gt;16. At 23, an SUV rear-ended my Ford Escort, smashing my back window and cleaning my clock pretty badly. An officer ticketed the man who hit me, made sure I was ok and didn't need a doctor, and called a tow-truck for me. &lt;/p&gt;&lt;p&gt;17. Also at 23, I was booking back to the pizza store at 1:45am after making my final delivery one Saturday night, and went a little left of center on the final left-turn onto the road the store was on. An officer pulled me over, and sat there until backup arrived. Then both officers exited their cars, one approached my driver's-side window, the other took a vantage point behind my car and to the right. &lt;/p&gt;&lt;p&gt;So basically I'm sitting there with my store driver's hat on, the empty pizza bags beside me, and about a block from the store. Despite that, I was at first unable to convince the officers that I was working and on my way to the store, rather than going home from a bar or a party. "How much have you had to drink tonight?" came up more than once. I blew a 0.0 on their portable breathalyzer, naturally, and they then accepted my story, and let me go without a ticket. Possibly that was their way of apologizing for the wrong assumption. &lt;/p&gt;&lt;p&gt;18. Again at 23, near the time I stopped working pizza, I was asked to give one of the teenage counter-girls a ride home since her ride fell through. I combined this with a delivery going the other direction, so I sped a little so I could finish the delivery, drop her off, and get back to the store quicker, as we were short-staffed on drivers that night. I was pulled over for speeding, however, making my efforts at timesaving moot. &lt;/p&gt;&lt;p&gt;It was near Christmas, and the young lady riding with me, fit and lovely, was wearing a snug sweater that the officer was visibly distracted by. He casually and quickly gave the standard warning speach "Hey, it's close to the holidays, and kids are out going wild, be careful on the streets... man, that's a nice sweater!" I was let off with a warning, which I attribute to Tracy's charm and the young officer's libido. &lt;/p&gt;&lt;p&gt;19. At 24, I had quit pizza, started working at CompuServe, and moved my girlfriend in with me. She would later become my wife, and later still would become my ex-wife. I received a phone call one evening when she and I were watching television. The call was from a police officer who introduced himself politely, asked if I was Gayle's son, and said that she and her friend needed a lift home. &lt;/p&gt;&lt;p&gt;I got the address, and my girlfriend and I went to pick them up. On arrival, the officer gave me the full story. He pulled them over for drunk driving, and was more interested to see that they got home safely than to cite anyone (my mom and her friends were pretty entertaining and likeable back in her party days, which probably helped). I said thanks, my girlfriend and I each drove a car, and no one got ticketed or sent to the drunk tank. &lt;/p&gt;&lt;p&gt;20. At 25, I let my tags expire. Life with a new baby was sort of hectic, which I rationalized as an excuse to keep procrastinating. I stopped by the bank on my morning commute one day, and wanted to finish my business and get to work as soon as possible. The side road the bank was on intersected a major road (Sawmill) and a block down the main road to the left was a stoplight. The light had just changed to green, sending traffic my way, and I had the opportunity to beat the traffic, provided I blew a stop sign. I scanned for pedestrians or other obstructions, and punched it, pulling in just ahead of the first car. &lt;/p&gt;&lt;p&gt;I pulled into the left turn lane (for Snouffer), and got caught at the light. Mozying up behind me came the first car from the previous light, a Columbus police officer. And he sat there and waited. And I spent the next 90 seconds thinking about all the opportunities I had to renew my tags but decided not to. The light changed, his lights came on, and I took my lumps (figuratively). I think the ticket for the stop sign and driving on expired tags was a little north of $100. &lt;/p&gt;&lt;p&gt;21. At 27, my wife and I took a vacation to North Carolina with our toddler daughter, and decided to stop at a hotel in West Virginia when little Stacey started getting fussy. While driving down a service road to the hotel, a police car coming the other way stopped and turned his emergency lights on and approached us on foot, cautiously. &lt;/p&gt;&lt;p&gt;"Where you guys heading?" asked the officer "Yon hotel," I said, pointing. I probably didn't say "yon hotel". &lt;/p&gt;&lt;p&gt;He looked us up and down, shone his flashlight inside our car, and explained that we were driving the same make and model of a car they were looking for. He didn't say what the guy in the car was wanted for, but after assuring himself that no one was hiding in our floorboards, he tipped his hat, bid us good day, and ambled back to his car. He probably didn't bid us good day. &lt;/p&gt;&lt;p&gt;22. At 30, my first wife and I had split up, and I was for a few months dating a woman in Kirkersville when I was living in Dublin. A few times a week, I would trek the 40 miles to her house, play with her kids, go out to dinner, and trek back home. She was great, her kids were great, and despite our good relationship, we just sort of stopped calling each other. My assumption has always been that Tia looked up my court records and saw that my divorce wasn't actually finalized like I told her it was. I felt like an asshole for a long time after we stopped seeing each other, especially for how her 8 year old would feel abandoned by me. Thinking about little Merica being sad was the main reason I didn't date anyone else for the following 7 years. &lt;/p&gt;&lt;p&gt;Anyway, police, right... During that time, I drove this little Saturn whose previous owner drove the hell out of it. Shortly after I bought the car, a host of things started to go wrong with it faster than I could afford to get them repaired. During one of my 40 mile treks back from Kirkersville, my headlights went out. My parking lights still worked, and so did my brights. It was about 11pm on a weekday when I was heading back, so there wasn't much traffic. I alternated between driving with my brights on, and switching to just parking lights when a car came from the opposite direction, so as not to blind them. &lt;/p&gt;&lt;p&gt;I made it almost all the way home, and then about half a mile from the freeway exit back to my neighborhood, a cop pulled me over to see what was going on. I explained the situation, and promised to get the car to a shop come daylight. He advised me just to leave my brights on and not worry about blinding people, and let me go. &lt;/p&gt;&lt;p&gt;23. At 32, I was at the apex of a horrible undiagnosed sinus infection that would probably eventually have killed me had I not found a good ENT to perform a septoplatsy. For about 6 months, I kept going to my family doctor complaining of headaches that put pressure on my eyes and teeth, but for whatever reason the idea that I might have a sinus problem never crossed his mind. He would load me up on vicodin under the assumption that I had cluster headaches. After finding that they didn't fully alleviate the pain, but wanted to take them anyway, I threw them away to avoid becoming an addict, and switched to ibuprofen and benadryl, which combined to make life tolerable. &lt;/p&gt;&lt;p&gt;During the next famliy get-together in North Carolina, I had an attack, and on the way back took a dose of my mother's benadryl, which was, in hindsight, a much stronger dose than my body was used to taking. I was driving her and 7 year old Stacey back to Ohio, and progressively getting more drowsy. &lt;/p&gt;&lt;p&gt;After passing Wytheville, Virginia, we came to the Big Walker Mountain Tunnel, a quiet, dark oasis from the noisy, bright freeway. After passing through it's 4/5ths of a mile, I was lulled nearly to sleep, and my foot kept getting heavier on the accelerator. I exited the tunnel going about 70 (55 is the speed limit from about 1/4 mile before to 1/4 mile after the tunnel), to the waiting speed trap on the other side. &lt;/p&gt;&lt;p&gt;Seeing my speedometer be nowhere near where I thought it was, combined with the flashing lights, I got a jolt of adrenalin, counteracting the diphenhydramine-induced coma I was heading towards. I uneventfully signed for my ticket, drove the remainder of the trip fully awake, and wrote my speeding users-fee check a few days later. &lt;/p&gt;&lt;p&gt;24. At 37, I fell victim to a stop sign trap at the corner of College ave. and Nicole in Westerville. When I first moved to Westerville, the stop sign was one street to the west, at the corner of College ave. and College ct., where it was immediately adjacent to the Middle School. A local petition was circulated for a ballot initiative to move the stop sign to Nicole, which has more houses on it. With the sign moved, the kids can immediately cross College from Nicole, then walk a block to their school, instead of walking down College for a block, then crossing immediately to their school. This is another reason why the rest of the world shakes their head at us and the obsession we have with our first-world problems. &lt;/p&gt;&lt;p&gt;Anyway, I drive past that stop-sign on the way to the freeway in the morning about an hour after the Middle School classes start, and until then I had just slowed down and looked for oncoming cars or kids late for school, and coasted through the stop sign at a slow crawl. Westerville posted a crusier down Nicole far enough to not be recognized as a threat by folks like myself who coasted through the stop sign, and I'm assuming pulled over about 20 people that day, netting the city an easy $2 grand. &lt;/p&gt;&lt;p&gt;After being pulled over, the officer asked me "Do you know why I pulled you over?". "Yes," I replied, and then bit my tongue to avoid blurting out any smartass comments about it being the end of the month and time for local police to "pay the rent", or my being more concerned with where pedestrians were than hidden patrol cars. &lt;/p&gt;&lt;p&gt;My ticket was over $100, due a week later. I hate the suburbs. &lt;/p&gt;&lt;p&gt;25. At 38, a friend and I drove up to Cleveland to see a band whose bassist we went to High School with. On the way back, my friend had to pee, so we pulled over on the freeway and he started to head to the bushes. A state trooper pulled over then, and asked us if everything was alright. "I'm sorry, officer, I just really need to pee," says my friend. The officer replies "alright, then, just making sure your car wasn't broken down." &lt;/p&gt;&lt;p&gt;I'm pretty sure it's a violation of some sort to stop on the freeway to pee in the bushes, but the trooper was less concerned about that than the possibility that someone might need help. &lt;/p&gt;&lt;p&gt;26. At 40, again with the expired tags. This time I was just heading to the grocery store with my pregnant wife, and driving "safely" - in my opinion, I always drive safely; this time I just wasn't breaking any traffic laws. The officer who pulled me over let me off with a warning in return for a promise to renew the tags soon. &lt;/p&gt;&lt;p&gt;So what can we make of all this? How could I have had all these encounters with cops and not been victimized, arrested, pepper-sprayed, cuffed, been threatened with dogs, or subjected to searches without probable cause? Well, being a white male probably skews things in my favor, I'll admit, but 26 times all ending without incident? Something else is at play. &lt;/p&gt;&lt;p&gt;Maybe the way I behave matters. I give cops respect and cooperation as a rule, and knowing that they quickly divide people into the "might kill me" and "probably won't kill me" categories, I try an awful lot to look like the latter, especially after my wakeup call when I was 18 and not thinking about how rooting around in a glove box might look. They do have jobs that put them in harm's way, obviously, and getting home without injury is going to weigh on them stronger than what I think my constitutional rights are. A pragmatic rule of thumb is cooperate on the street, object in the courtroom. In my case, doing much of the former has meant I needed to do none of the latter. Your mileage may vary. &lt;/p&gt;&lt;p&gt;I think what matters most, though, is that the negative stories you hear about corrupt police, OWS protestors getting smacked around, and adrenaline junkies with badges are mainly the exceptions to the rule. Most of the police are the good guys. If that weren't the case, I think I'd definitely have a different story to tell. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11885757-3799777866509520020?l=cautery.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cautery.blogspot.com/feeds/3799777866509520020/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://cautery.blogspot.com/2011/12/encounters-with-police.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/3799777866509520020'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/3799777866509520020'/><link rel='alternate' type='text/html' href='http://cautery.blogspot.com/2011/12/encounters-with-police.html' title='Encounters with the police'/><author><name>Curtis Autery</name><uri>https://profiles.google.com/107677530285177731535</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/--J3C_khtLqQ/AAAAAAAAAAI/AAAAAAAADT4/e2Qa5ncfAMk/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11885757.post-996800447069184932</id><published>2011-11-23T14:51:00.001-05:00</published><updated>2011-11-23T15:06:57.480-05:00</updated><title type='text'>Think of the children!!</title><content type='html'>&lt;p&gt;No seriously, think of the children. And not the bounty. &lt;/p&gt;&lt;p&gt;About a month ago, I listened to an NPR story on "All Things Considered" on my drive home from work, which concerned Native American children in South Dakota being declared "neglected" in high numbers, and being removed from their families and put up for adoption. The implication is that the South Dakota government was using a financial incentive as an excuse to go all Captain Pratt on the natives, killing the Indian and saving the man, by means of placing their kids in white homes. The text version of the NPR story is &lt;a href="http://www.npr.org/2011/10/25/141662357/incentives-and-cultural-bias-fuel-foster-system"&gt;available here&lt;/a&gt;. &lt;/p&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;p&gt;Some background on the NPR story: &lt;/p&gt;&lt;p&gt;In 1997, &lt;a href="http://www.gpo.gov/fdsys/pkg/BILLS-105hr867ih/pdf/BILLS-105hr867ih.pdf"&gt;HR 867&lt;/a&gt; was enacted by Bill Clinton, ammending section 473 of Part E (Federal Payments for Foster Care and Adoption Assistance) of title IV of the Social Security Act with some seemingly good-intentioned language, which had some disturbing consequences. Section 473a now contains this (ellipses, brackets, and sentence reformatting are mine): &lt;/p&gt;&lt;p&gt;&lt;i&gt;...the adoption incentive payment payable to a State ... shall be equal to the sum of $4,000, multiplied by the amount (if any) by which the number of foster child adoptions in the State during the fiscal year exceeds the base number of [same]; and $2,000, multiplied by the amount (if any) by which the number of special needs adoptions in the State during the fiscal year exceeds the base number of [same]&lt;/i&gt;&lt;/p&gt;&lt;p&gt;In 2008, the 110th Congress passed &lt;a href="http://www.fosteringconnections.org/tools/assets/files/Public_Law_110-351.pdf"&gt;Public Law 110–351&lt;/a&gt; (the "Fostering Connections to Success and Increasing Adoptions Act") which upped this last amount to $4,000, making the total take for getting a special needs kid adopted $8,000. &lt;/p&gt;&lt;p&gt;In basic English, one would assume "special needs" refers to children with mental retardation, epilepsy, behavioral problems, or other conditions requiring specialized care - basically kids that don't fit the happy suburban white couple Disney mold of the perfect kid to adopt. Title IV-E disagrees with that assumption, though. It's context of "special needs" implies only things that would make it harder to place a child with an adoptive family without a financial incentive. It states in section 473c: &lt;/p&gt;&lt;p&gt;&lt;i&gt;the child shall not be considered a child with special needs unless ... the State had first determined (A) that there exists with respect to the child a specific factor or condition (such as his ethnic background...)&lt;/i&gt;&lt;/p&gt;&lt;p&gt;This language basically invites states to declare all their black or native populations as special needs. A quick glance at the Child Welfare Information Gateway's &lt;a href="http://www.childwelfare.gov/adoption/adopt_assistance/questions.cfm?quest_id=1"&gt;Adoption Assistance by State page&lt;/a&gt; shows that many states have done just that. The two I want to focus on have been in the news recently for abuses by their Child Protective Services departments: South Dakota in regard to natives, and Virginia in regard to something a little more subtle. &lt;/p&gt;&lt;p&gt;South Dakota's categories for special needs: &lt;/p&gt;&lt;ul&gt;&lt;li /&gt;Eight years of age or older &lt;li /&gt;Race or religion (Native American) &lt;li /&gt;Member of a sibling group to be placed together for adoption &lt;li /&gt;Physical, emotional, neurological, or intellectual handicap or problem &lt;li /&gt;Need of a prosthesis, extensive, on-going, or anticipated medical care, or therapy for speech, physical, or psychological problems &lt;li /&gt;Adoption by foster parents with whom the child is living is the only appropriate permanency plan &lt;/ul&gt; And Virginia's:  &lt;ul&gt;&lt;li /&gt;Six years of age or older &lt;li /&gt;Member of a minority race &lt;li /&gt;Member of a sibling group that is ready for placement at the same time and should not be separated &lt;li /&gt;A physical, mental, or emotional disability &lt;li /&gt;Hereditary tendency, congenital problem or birth injury resulting in a substantial risk of future disability &lt;li /&gt;A child with a physical, mental, emotional disability or hereditary tendency, congenital problem or birth injury present at the time of adoption but not diagnosed until up to one year after the final order is entered &lt;/ul&gt;&lt;p&gt;Does "birth injury" sound a little vague? Hold that thought. &lt;/p&gt;&lt;p&gt;Combine the $8,000 per head federal assistance with defining an entire race of people as harder to adopt, and you have just created a financial incentive to err on the side of removing minority children from their families. &lt;/p&gt;&lt;p&gt;The NPR story focussed on one particular group of kids who were seized from a family guilty of nothing more than poverty, and who had community and extended family childcare available. The story ends on sort of an up-note: A tribal council passed a resolution warning the state of South Dakota that criminal kidnapping charges would be filed if the kids weren't returned. They were returned, along with some snarky comments in the vein of "we can still come take your kids with impunity, so watch your step, Tonto." (The "Tonto" was silent, but implied.) The family of the kids is very worried by those comments, but to me they were an admission of defeat, the bully's retreating "I'll kick your ass" after getting knocked down by his intended victim. &lt;/p&gt;&lt;p&gt;For what it's worth, South Dakota &lt;a href="http://www.dakotahillslaw.com/wp-content/uploads/2011/11/2011-11-02-NPR-report-follow-up.pdf"&gt;responded to the NPR story&lt;/a&gt;, basically declaring their innocence and good intentions, falling just shy of espousing the "white man's burden". &lt;/p&gt;&lt;p&gt;I thought that was the end of it, some Black Hills comeuppance by natives who have been systematically harassed and disenfranchised by whites for centuries, and finally landed a good blow to them. But it isn't. A seemingly unrelated scandal is going on currently in Virginia, and was &lt;a href="http://washingtonexaminer.com/opinion/columnists/2011/11/federal-judge-should-hear-arlington-cps-case"&gt;publicly called out&lt;/a&gt; in the Washington Examiner. &lt;/p&gt;&lt;p&gt;In Baby Sabrina's case, there was enough going on to make it a case worth a quick peek by Virginia CPS, namely a diagnosis of "failure to thrive". My reading of the issue on the &lt;a href="http://www.kitandnancy.com/"&gt;mom's website&lt;/a&gt; is that Nancy was having trouble breastfeeding. The baby lost weight after birth, which all kids do, but did not then regain the lost weight, and in fact over the next weeks lost an additional couple of ounces. Sabrina was admitted to the hospital, fed a lot of formula, and then started gaining weight. &lt;/p&gt;&lt;p&gt;CPS investigated, which they were well within their right to do. Losing weight immediately after birth is par for the course, but a healthy baby who isn't being neglected should recover soon. Sabrina didn't. When CPS investigated, the correct response should have been "thanks for being concerned about our baby. We're trying hard, and now the doctors are helping, and we'll comply with their recommendations because we want nothing more than for Sabrina to be healthy." What they said instead was "fuck you, we're getting a lawyer," which raised the ire of the CPS. &lt;/p&gt;&lt;p&gt;From there, I would have expected a quick resolution, possibly with CPS backing off, or possibly with them temporarily placing the baby with Nancy's mom. Instead, they removed the baby from the family, and put it up for adoption. Why? Two reasons. First, because you don't stand up to the man; he's a spiteful son of a bitch. Second, the "failure to thrive" diagnosis fits well with the Virginia special needs category of "birth injury resulting in a substantial risk of future disability". &lt;/p&gt;&lt;p&gt;In my opinion, and I have nothing to back this up other than a gut feeling, Sabrina's possible status as special needs caused Virginia CPS to side with removal and adoption outside the family, rather than just monitoring or placing her with grandma. Even though the state's legal costs quickly surpassed the $8,000 take. Nancy's site does have a good deal of atrocity propaganda on it, and it's hard to read through that and find the true story, but there are enough questions about the case that it should at least be heard by a federal judge. Maybe they're full of crap and were truly neglectful, or maybe Virginia CPS overstepped, but either way they should get their day in court. &lt;/p&gt;&lt;p&gt;Maybe neither the South Dakota nor Virginia cases are caused by official state evil. Maybe the intentions are always good, with an eye on protecting children and giving them the best homes possible, and after seeing enough bad in the truly neglectful parents, CPS case workers see bad in all parents. I don't know, but I do know that there is a conflict of interest for any state that accepts per-child adoption bounties. Yes, a little rhetorical, but a bounty is what it is. The spirit of the law is to use the money when standard attempts to place the child have failed, but in Sabrina's case as with the South Dakota case, an acceptable placement was available and ignored. So there is at least the perception, a revealed preference, that underfunded state CPS agencies now have an eye on potential federal money, and skew their cases accordingly. &lt;/p&gt;&lt;p&gt;No matter the true nature of the South Dakota and Virginia cases, adding this motivation for funding into organizations tasked with removing children from their homes is a powderkeg, especially in today's world of protesters fighting the police, unemployment bringing children into poverty, and the simple fact that parents who feel their children are threatened are irrational, more likely to put up their dukes than to investigate the proper appeals process. The 473a ammendment to Title IV-E will be responsible for needlessly breaking up families, and for police, social workers, parents, or children getting injured or worse. And it needs to be repealed. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11885757-996800447069184932?l=cautery.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cautery.blogspot.com/feeds/996800447069184932/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://cautery.blogspot.com/2011/11/think-of-children.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/996800447069184932'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/996800447069184932'/><link rel='alternate' type='text/html' href='http://cautery.blogspot.com/2011/11/think-of-children.html' title='Think of the children!!'/><author><name>Curtis Autery</name><uri>https://profiles.google.com/107677530285177731535</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/--J3C_khtLqQ/AAAAAAAAAAI/AAAAAAAADT4/e2Qa5ncfAMk/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11885757.post-7517359464595946055</id><published>2011-10-30T16:17:00.001-04:00</published><updated>2011-10-30T16:20:00.249-04:00</updated><title type='text'>Tinkering with Calculus</title><content type='html'>A little document I whipped up on Google Docs after dusting off a calculus book: &lt;br/&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;iframe src="https://docs.google.com/document/pub?id=1K9JFgwmG9uP56CbCaMWDsEICWVk01ZB99tBcFbyP3P4&amp;amp;embedded=true" frameborder=0 style="width:100%;height:100%"&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11885757-7517359464595946055?l=cautery.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cautery.blogspot.com/feeds/7517359464595946055/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://cautery.blogspot.com/2011/10/tinkering-with-calculus.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/7517359464595946055'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/7517359464595946055'/><link rel='alternate' type='text/html' href='http://cautery.blogspot.com/2011/10/tinkering-with-calculus.html' title='Tinkering with Calculus'/><author><name>Curtis Autery</name><uri>https://profiles.google.com/107677530285177731535</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/--J3C_khtLqQ/AAAAAAAAAAI/AAAAAAAADT4/e2Qa5ncfAMk/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11885757.post-6841478193942933347</id><published>2011-10-16T13:08:00.001-04:00</published><updated>2011-10-18T12:10:32.455-04:00</updated><title type='text'>Adelaide</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-CYQialjHMtQ/TprlvwnJ2MI/AAAAAAAADUo/utzKCWKGbBA/s1600/adelaide.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://1.bp.blogspot.com/-CYQialjHMtQ/TprlvwnJ2MI/AAAAAAAADUo/utzKCWKGbBA/s320/adelaide.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p style="text-align: center;"&gt;Adelaide Lenora Allerding&lt;br/&gt;October 14, 2011 4:20am&lt;br/&gt;6lbs 12oz, 19.5"&lt;/p&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;p&gt;As I mentioned a while back, my wife and I decided to have a baby. It's an easy time for us to have a baby, because I have a stable job, I'm still young enough and healthy enough, our marriage is strong, Liberty and I agree on most things, and Liberty has a strong support network of family and friends. It's a hard time for us to have a baby because I am no longer happy working corporate IT, or living in Ohio, Liberty is unemployed and has a mountain of student loan debt, the house is falling apart, and although I'm healthy now at 40, I'm worried about what my health will be in 10 years at 50. The more I dwell on these negatives, in fact, the grayer my hair seems to get.&lt;/p&gt;&lt;p&gt;In our shared opinion, the easy outweighed the hard, but if we didn't think that was so, we probably would have had a baby anyway. Because we both love babies, and each other, and, you know... come at me, bro. Just bring it, world. Rain some more bad on us and see who's still standing tomorrow.&lt;/p&gt;&lt;p&gt;Liberty was originally due on October 12, according to the pregnancy wheel used by our CHOICE midwife, Audra. We planned to drive down to "The Farm" in Tennessee, home to Ina May Gaskin, and rent one of their birthing cabins for a month and have the baby there. (Even though we are the 99%, as the protest saying goes, and it would have taken more cash than I could comfortably afford, with no guarantee that insurance would cover any of it -- see "come at me, bro" above.) We would see local midwives here at the CHOICE center, and when she seemed close to ready for labor, we would truck on down south to spend a month on The Farm. That was the plan, anyway.&lt;/p&gt;&lt;p&gt;Throughout the pregnancy, Liberty had stomach pains that were pretty severe. She was diagnosed as having H. Pylori, easily treated with some hard core antibiotics whose side effects include birth defects and miscarriages. So instead she suffered the entire pregnancy, nursing her way through the pain with probiotics, red raspberry/nettle tea, and other herbal stomach aids.&lt;/p&gt;&lt;p&gt;Whether a direct result of the stomach problem or coincidental to it, the baby was the wrong size late in the second trimester. The midwives weren't sure if the due date was correct, if a lull in growth was baseline for how Liberty made babies, or if there was a nutrition or development problem. So we did what we had been trying explicitly to avoid: started medicalizing the pregnancy. We got a few ultrasounds over the next month, Liberty started making appointments at the Department of Health for various tests and labwork, and The Farm dropped us as clients.&lt;/p&gt;&lt;p&gt;The last was a bad blow, and Liberty was inconsolable for a few days. "I tried to do everything right," she said during the worst of it. A guy needs to fix things, it's just how we're made, and I could do nothing to either attack the problem or comfort my wife. I still get a little choked up when I think about it.&lt;/p&gt;&lt;p&gt;CHOICE kept us as clients, and the baby made up for lost time over the next few weeks, due either to providence's original plan, or Liberty forcing down food she knew was going to make her feel like hell in a couple hours. As the original due date approached, the baby was the right size, no problems were indicated on ultrasound or blood tests, and we planned for a home birth. Audra and another midwife, Amy, came for a home visit, gave us a kit of baby making stuff including pads to catch blood and stuff, instructions I was to memorize in case we couldn't get help in time ("if the umbilical cord seems looped around the neck..." I was really hoping it wouldn't come down to me being Liberty's only help in delivery), and the ominous infant resuscitation board. Just in case.&lt;/p&gt;&lt;p&gt;Just imagine living with your pregnant wife for a couple months with an infant resuscitation board in your bedroom. Just think about that for a minute.&lt;/p&gt;&lt;p&gt;On Thursday, October 13 at about 10pm, Liberty's behavior changed, and her contractions were visibly making her more uncomfortable than usual. (For those not in the know, pregnant women have contractions pretty much all the time in the third trimester. Not constantly, but most days there will be at least a few, growing in regularity and duration. When this happens, the stomach gets rock hard. It's pretty wild.) Anyway, I figured this was it, so I went down and made some coffee, got re-dressed, and started pitching the idea of calling Audra.&lt;/p&gt;&lt;p&gt;At 11, Liberty made the first call. With a midwife now on standby, Liberty tried to take a warm bath to see if the contractions would pass. I drank my coffee, and went in to check on Scout. She was awake, as we were making plenty of noise. "I think your mom's in labor," I said to her, "this can take a long time, so try to get some rest, and I'll come wake you up if anything interesting happens." Naturally she didn't sleep any more, nor, I'm pretty sure, did she try to.&lt;/p&gt;&lt;p&gt;The bath didn't help. Liberty's pain level got worse, and the contractions got stronger. I made the second call to Audra at about 12:15, as Liberty was reduced to communicating through head nods and shakes. "I think we need you," I said, and hearing Liberty's cries in the background, she said she would get ready and come over. She showed up about a half hour later, and Amy shortly after that.&lt;/p&gt;&lt;p&gt;At about 1:30, I could hear Scout rustling around, and I checked on her again. She wanted to come help. Liberty and the midwives were all OK with her coming in, so she did. Throughout the labor, little Scout was ..and again, I'm choking up just thinking about it... the absolute best that humanity has to offer. She watched quietly, whispered a few questions to Amy, held mom's hand and patted her hair, ran to get water or juice when mom was thirsty, and held it to her mouth so she could drink from the straw if she didn't have a free hand to hold her own cup. I told her later how proud I was of her, and I swear I felt as much love for her then as I did when little Stacey explained to me how the sunset was medicine for the sky.&lt;/p&gt;&lt;p&gt;It was a little scary for Scout, watching her mom in pain, and I geared up to give her the following consoling speech: "Angel, do you see how the midwives faces are all calm and relaxed? They've seen a lot of deliveries before, and they know this is all normal. See how they don't looked worried?" Before I started to say that, though, I looked at their faces. I saw something hiding behind the relaxed expressions. Concern. Worry. The feeling that something isn't right. The problem was that everything seemed to be going normally, but Liberty was in much more pain than she should be. So I withheld my reassuring speech, and waited for the problem to reveal itself.&lt;/p&gt;&lt;p&gt;It did so very soon thereafter. Liberty became completely dilated and effaced, and as soon as she started pushing, the baby's heartbeat dropped to about 80, by my estimate. A midwife pitched her voice low and said softly to the other "that's too low." They gave Liberty oxygen, told her to lie on her left side (I think it was the left side), and try not to push for a minute. The baby's heart rate came back up, but not quite to where it should have been. The next push, the problem was still there. "We might need to go to the hospital," a midwife said.&lt;/p&gt;&lt;p&gt;I put on my socks and shoes, got some socks for Scout and told her to go put them on with her boots, and I ran down to get her a coat. By then, the plan was definite: we would leave for the hospital immediately. Liberty and Amy would ride in the back of my car, Audra would call the hospital, canvas the house, and follow. I helped Liberty, now in pain, scared, and confused ("what's happening?!" a near sob, "what are we doing?") out of the house to the car. Amy barked an order to remove Scout's car seat, which I did, and directed Liberty to get on her hands an knees in the back, which she did. Amy got in beside Liberty and reaffixed the oxygen mask, I got Scout buckled into her car seat in the front, made sure everyone was ready...&lt;/p&gt;&lt;p&gt;And I put the God-damned hammer down.&lt;/p&gt;&lt;p&gt;It was 4 in the morning, and the streets from my house to St. Ann's were nearly vacant. We pulled up to the hospital about 5 minutes after we left the house, including two blown stop signs, a left turn on red, and a 90 in a 45.&lt;/p&gt;&lt;p&gt;Amy went in to get a wheelchair, and I got Liberty out and started walking her to the door. Scout followed along, and had an almost pleasant look to her. Very calm, inquisitive even. "What's all this crazy driving and running to the hospital all about?" The ladies went in together while I parked the car, and by the time I made it in the hospital everyone was gone. I had a brief conversation with the security guard:&lt;/p&gt;&lt;p&gt;"Hey, there was a pregnant woman in a wheelchair..."&lt;/p&gt;&lt;p&gt;While pointing to the elevator, "Second floor."&lt;/p&gt;&lt;p&gt;I got off on the second floor, which on first glance was a ghost town. The receptionist's desk was empty, and the security doors allowing one back to the delivery rooms were closing. I dashed to them and grabbed one before it closed, and slipped into the secure area. I heard the sounds of people around a corner to my right, and headed over that way purposefully, damned near storming up to the nurse's station. "LIBERTY ALLERDING!" If you know me at all, you know that this is completely out of character for me. Yelling at people at a nurse's station is as unlikely a thing to happen as me pushing people out of the way at Disney World... which I also did when I realized 6 year old Stacey wasn't beside me any more. Issues with my kids tend to bring to the surface that testosterone response I'm always suppressing. &lt;/p&gt;&lt;p&gt;Anyway, before I leapt the desk and started rifling through charts, a very nice and polite lady told me where she was, and asked me first to come to the reception area to give them my insurance card, date of birth, and whatnot. She took the information quickly, and I went to the delivery room and caught the last bit of the action: My wife in exactly the position she had been trying to avoid for the entire pregnancy: surrounded by doctors, on a delivery table, legs in stirrups.&lt;/p&gt;&lt;p&gt;Strangely, the delivery at this point was completely uneventful. "Push!",  "OK, I have the head, one more!", "Waah!". Adelaide was delivered naturally, all things considered, at 4:20am, a fact that will give all the heads she meets no end of giggles.&lt;/p&gt;&lt;p&gt;The St. Ann's staff was everything I thought they wouldn't be. They were polite, they took our direction (no episiotomy, leave the baby with us instead of taking it to the nursery), they waited for Adelaide to pink up before clamping the umbilical cord, and only offered token resistance when Liberty said not to stitch her tears up. Despite being lit up with testosterone and unable to keep my legs from shaking as I watched, I only said one cross thing to the staff: "She said no, leave it at that."&lt;/p&gt;&lt;p&gt;A side note here: This isn't my story, and while I'm writing it from my point of view, I don't intend for this to look like it was all about me. This is Liberty's story, slowly pushed off the course she had for a pregnancy and labor experience, but nonetheless emerging victorious. She did all the suffering, and my actions, despite their comedic value and reflection of how much I care for Liberty, could have been performed by a chauffeur  just as easily. And a personal assistant. And a bodyguard. But still, her story. I'm not the hero, I can just only report what I saw.&lt;/p&gt;&lt;p&gt;We asked to be released from the hospital as soon as we could, which we thought at first was going to involve staying at least 24 hours for observation since the labor was problematic. At this point we realized that Liberty and Scout were wearing nightgowns, and Liberty didn't have her purse or shoes, and no one had a toothbrush. And little Adelaide had no clothes and her car seat was disassembled at the house, since we didn't expect to need it for a while. So I drove home, obeying many more traffic laws than the trip to the hospital, packed up a bag of stuff, put the car seat together, and came back to find that we were being released.&lt;/p&gt;&lt;p&gt;Adelaide's responses were all normal (I think someone said "8, 9, and 9", referring to some reflex/awareness test), the delivery was vaginal with no cutting, and mom was coherent, so there was no reason to keep us. Another plus for St. Ann's in my book: "You seem OK, take off and let us know if you need anything." So, good on them for being more supportive of moms and less interventionist. And good on the ladies at CHOICE who were humble enough to see when more help was needed, but strong enough to continue to advocate for Liberty at the hospital.&lt;/p&gt; Naturally I'm proud of Liberty for enduring both  monumental suffering and indignity, and little Adelaide for hanging in there and coming out healthy. But when I think back over the whole affair, my strongest memory is of Scout and a cup of juice held out to her mom, the fearlessness when things started to go wrong, and the excitement at getting to meet her sister.  &lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-rVqGiHBP-Kk/Tprl0nt8ugI/AAAAAAAADUw/A5J0KR0WUDE/s1600/IMG_5540.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://4.bp.blogspot.com/-rVqGiHBP-Kk/Tprl0nt8ugI/AAAAAAAADUw/A5J0KR0WUDE/s320/IMG_5540.JPG" width="240" /&gt;&lt;/a&gt;&lt;/div&gt; &lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11885757-6841478193942933347?l=cautery.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cautery.blogspot.com/feeds/6841478193942933347/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://cautery.blogspot.com/2011/10/adelaide.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/6841478193942933347'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/6841478193942933347'/><link rel='alternate' type='text/html' href='http://cautery.blogspot.com/2011/10/adelaide.html' title='Adelaide'/><author><name>Curtis Autery</name><uri>https://profiles.google.com/107677530285177731535</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/--J3C_khtLqQ/AAAAAAAAAAI/AAAAAAAADT4/e2Qa5ncfAMk/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-CYQialjHMtQ/TprlvwnJ2MI/AAAAAAAADUo/utzKCWKGbBA/s72-c/adelaide.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11885757.post-5439340503750743643</id><published>2011-04-22T11:48:00.000-04:00</published><updated>2011-04-22T11:48:46.962-04:00</updated><title type='text'>Designing a Notes iPhone web app</title><content type='html'>&lt;blockquote&gt;"A pedagogical decision hides behind every design decision" -Dan Meyer &lt;/blockquote&gt;&lt;p&gt;For the last few weekends, I've been coding in the early mornings while my wife sleeps beside me, working on a replacement for the broken built-in Notes app on her iPhone. My replacement is usable and stable at this point, and I'm just putting the final polish on the code to remove duplication, improve comments, delete orphan code, etc. &lt;/p&gt;&lt;p&gt;The tools I used to design this are the same as the &lt;a href="http://lentiltracker.appspot.com"&gt;diet tracker app&lt;/a&gt; I wrote for her to track her protein and calcium during her pregnancy: handwritten JavaScript, and Google's appspot.com webserver to properly serve the cache manifest's content type. This was initially going to be a quick hack to learn the API for Web SQL Databases, so I could retrofit database support in the diet tracker, but along the way I learned a lot about designing an HTML Notes application, which was more involved than I anticipated. &lt;/p&gt;&lt;p&gt;This post recounts some of the lessons I learned, and the decisions I made between competing solutions that each had pluses and minuses. Some screenshots of the current product are available below the fold. &lt;/p&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;p&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-Yl-lncVUyHY/TbGib0gqYWI/AAAAAAAADRA/scnJ9-vENl8/s1600/notesIconScreenshot.png" imageanchor="1" style=""&gt;&lt;img border="0" height="320" width="214" src="http://1.bp.blogspot.com/-Yl-lncVUyHY/TbGib0gqYWI/AAAAAAAADRA/scnJ9-vENl8/s320/notesIconScreenshot.png" /&gt;&lt;/a&gt;&lt;/div&gt;  Custom icon on iPhone home screen. &lt;/p&gt;&lt;p&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-TdZzpIv17RI/TbGion2hm2I/AAAAAAAADRI/0r_kCgj-tJ8/s1600/notesInputScreenshot.png" imageanchor="1" style=""&gt;&lt;img border="0" height="320" width="214" src="http://3.bp.blogspot.com/-TdZzpIv17RI/TbGion2hm2I/AAAAAAAADRI/0r_kCgj-tJ8/s320/notesInputScreenshot.png" /&gt;&lt;/a&gt;&lt;/div&gt; Editing: The "back" button on the menu bar is three rectangles and a circle drawn using the HTML5 canvas spec. More on that below. &lt;/p&gt;&lt;p&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-7Or7TtG0KBY/TbGiwGIBBYI/AAAAAAAADRQ/gquT1po7l50/s1600/notesListScreenshot.png" imageanchor="1" style=""&gt;&lt;img border="0" height="320" width="214" src="http://1.bp.blogspot.com/-7Or7TtG0KBY/TbGiwGIBBYI/AAAAAAAADRQ/gquT1po7l50/s320/notesListScreenshot.png" /&gt;&lt;/a&gt;&lt;/div&gt;  List: Normally all those minus signs won't be there. The red minus sign at the very top is twisted to indicate being in delete mode. Then each note gets its own minus sign, and twisting them unlocks a delete button. Again, more on that below. &lt;/p&gt;&lt;p class=section&gt;Impetus &lt;/p&gt;&lt;p&gt;The story starts a few years ago when the first iPhone came out. I bought one for Liberty, and it quickly became the source of many pictures of Scout, and of our adventures - pictures that we didn't want to lose. Because of the fear of losing these images, we rarely synced the phone with iTunes, always backing the images up first, and fearing the bad things that would happen when newer iOS versions were installed. &lt;/p&gt;&lt;p&gt;During syncing, we've lost music, saw the built-in applications get slower, had mysterious timeouts backing up data, but fortunately have never lost any of the images. Since each upgrade seemed to make the whole system slower, and assuming newer OS versions would need even more horsepower, syncing again would make the phone virtually unusable. &lt;/p&gt;&lt;p&gt;"Why not upgrade to an iPhone 4" you ask? I've pitched this idea to Liberty, which she soundly dismissed. Her reason: the newer iPhones look more boxy, whereas the original looks curvy and sleek. Well, there's no arguing with that logic... or at least, I don't really know where I'd start, so there's nothing for it but to help her use the phone she has. &lt;/p&gt;&lt;p&gt;The current state of her phone is iOS 3.1.3 with the version of Safari using WebKit engine 528.18. Theses specific versions have some anomalies, namely the Notes app tends to break during the upgrade (file permission problems), and Safari's HTML5 support had some minor issues that have since been ironed out (such as placeholders on textarea fields, which I'll get into later). &lt;/p&gt;&lt;p&gt;The Notes app breaking was the real impetus of this project. Our symptoms consist of the app opening fine, but clicking on most of the notes results in the app simply closing. Only one note opens, but trying to alter it also results in the app closing. There are some suggestions for fixes online, which mainly involve monkeying around with the Settings app and trying again, but those haven't worked for us. &lt;/p&gt;&lt;p&gt;Unix hacker that I am, I could jailbreak the phone, install an SSH daemon, then connect from my PC and do some commandline chmods on the note files, but Liberty didn't like the idea of me hacking her phone like that. One of the things that is helping the two of us have a successful marriage is my not fixating on things like this like I would have a decade ago. If she wants an older phone with an unaltered OS, then that's the environment I work in. If the puzzle is hard to solve under those conditions, so much the better: the puzzle is the fun part. Solving the puzzle is the main focus, not advocacy for being modern or edgy (whatever that means). &lt;/p&gt;&lt;p&gt;When I finished the diet tracker app enough to be usable, I looked for another app to write to learn web databases, and the broken Notes app was the obvious candidate. And so, I began. &lt;/p&gt;&lt;p&gt;My &lt;a href="http://cautery.blogspot.com/2011/04/rage-against-pitocin-cesarean-complex.html"&gt;previous blog entry&lt;/a&gt; on the diet tracker web app shows (along with my radical views on childbirth) some basics of using offline application caches, and how to turn a website bookmarked to the iPhone home screen into something that behaves like a native application, so I won't dwell on those points here. Let's start instead with databases. &lt;/p&gt;&lt;p class=section&gt;Web Databases &lt;/p&gt;&lt;p&gt;There are two basic flavors of JavaScript accessible local databases: the &lt;a href="http://www.w3.org/TR/webdatabase/"&gt;Web SQL Database&lt;/a&gt;, which is supported in WebKit browsers (Chrome and Safari), and the &lt;a href="http://www.w3.org/TR/IndexedDB/"&gt;Indexed Database API&lt;/a&gt;. The latter was proposed by Oracle a couple years ago, and currently the W3C is declaring Web SQL a deprecated standard. The newer standard has been adopted by Firefox 4, so Wikipedia tells me, as well as Chrome 11 (meaning support for it should be rolled back into WebKit in the near future, propagating to Safari and Chromium). For now, though, Web SQL is what's available to me for iPhone web apps, and that is what I used. &lt;/p&gt;&lt;p&gt;In Web SQL, the method window.openDatabase() returns a handle to a database object. You pass that method a few variables - the local and friendly names of the database, its version number, and the number of bytes that should be allocated for it - and the browser uses a built-in instance of SQLite to attempt to find or create the database. &lt;/p&gt;&lt;p&gt;A SQL transaction function, (transaction handle).executeSql(), can be created that specifies the SQL to execute, any variables to substitute for question marks in the SQL, and asynchronous functions to call on the success or failure of the SQL statement. &lt;/p&gt;&lt;p&gt;The database handle and the transaction function are married together with an odd construct, resulting in code that can look like this: &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;var db = openDatabase('etchnotes', '1.0', 'etchnotes', 200000);&lt;br /&gt;db.transaction(function(t){&lt;br /&gt;  t.executeSql('SELECT rowid, name FROM notes', [], function(tx, result) {&lt;br /&gt;    var firstName = result.rows.item(0).name;&lt;br /&gt;    // ...do other stuff with results;&lt;br /&gt;  });&lt;br /&gt;});&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;First, that's too much abstraction and punctuation for my taste; without a lot of familiarity with constructs like the above, it's hard to parse, and harder still find syntax errors in it. But such is the world of asynchronous callbacks. &lt;/p&gt;&lt;p&gt;A slightly better construct is this: &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;var db = openDatabase('etchnotes', '1.0', 'etchnotes', 200000);&lt;br /&gt;function onSuccess(tx, result) { ...stuff... }&lt;br /&gt;function onFailure(tx, result) { ...stuff... }&lt;br /&gt;&lt;br /&gt;db.transaction(function(t){&lt;br /&gt;  t.executeSql('SELECT rowid, name FROM notes', [], onSuccess, onFailure);&lt;br /&gt;});&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;That reads a lot more clean to me, but I still don't like that the db object can't take SQL directly. To address that, I created a closure function that has a runSql method, opens and initializes the database, and manages its own transactions and error callbacks. This is a simplified version of the closure: &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;function getNotesDB() {&lt;br /&gt;  var db = openDatabase('etchnotes', '1.0', 'etchnotes', 200000);&lt;br /&gt;  var errorHandler = function(tx, e) { alert("Database error\n" + e.message); }&lt;br /&gt;&lt;br /&gt;  this.runSql = function(sql, callback) {&lt;br /&gt;    db.transaction(function(t){&lt;br /&gt;      t.executeSql(sql, [], callback, errorHandler);&lt;br /&gt;    });&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  return this;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;And calling it is a breeze: &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;var dbClosure = getNotesDB();&lt;br /&gt;dbClosure.runSql("select rowid, name from notes", onSuccess);&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;After a little exposure, I was able to get my head around async database work, and splitting functions into two parts: the click handler that submits a SQL query, and the callback function that parses the results. I won't dwell on that any more here, but the source code is available below. &lt;/p&gt;&lt;p class=section&gt;Rotating an HTML5 canvas &lt;/p&gt;&lt;p&gt;A standard design pattern on the iPhone is unlocking a delete button. Rather than each removable item having a delete button always present, and an "are you sure?" popup to deal with, some iPhone apps have an edit mode that provides each item with a minus sign on the left. Touching that makes it rotate counter-clockwise, and exposes a hidden delete button for that item. Click the delete button, and the app assumes you knew what you were doing and deletes the item with no verification. Or click the minus button again, and it rotate back to where it was, hiding the delete button. Intuitive and neat, typical of Apple's UI design, and hard to find fault with. &lt;/p&gt;&lt;p&gt;Implementing a similar minus button rotation with JavaScript took a little research, but ultimately wasn't very difficult. The two basic methods I chose between were CSS transforms using something like: &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;minusButton.style['-webkit-transform'] = "rotate(30deg)";&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;...and HTML5 canvas context rotations, for example &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;var ctx = canvas.getContext('2d');&lt;br /&gt;ctx.rotate(angle);&lt;br /&gt;ctx.fillRect(x, y, w, h);&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;I chose the latter, choosing also to not use image files, but instead to draw the button objects on canvases using paths (think GeneralPath from Java2D). Since all I needed was a circle and a line for a minus button, this was pretty trivial. While rotating the canvas was easy after I figured out to use ctx.translate() to move the origin point to the center of the image, animating the rotation was a little more involved. &lt;/p&gt;&lt;p&gt;I may have been better off using a CSS transition, but having already headed down the path of canvases, I stuck with it, ending up with some arcane looking infrastructure around canvases and their states. Behold the Spinner Factory: &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;function SpinnerFactory(size) {&lt;br /&gt;  var cr = Math.PI*2;        // Circle&lt;br /&gt;  var deg = Math.PI/180;     // One degree&lt;br /&gt;  var scale = size/100;&lt;br /&gt;&lt;br /&gt;  function getScaledContext(obj) {&lt;br /&gt;   // Get canvas context&lt;br /&gt;    var ctx = obj.getContext('2d');&lt;br /&gt;&lt;br /&gt;    if (!obj.scaled) {&lt;br /&gt;      ctx.scale(scale, scale);&lt;br /&gt;      ctx.translate(50, 50);&lt;br /&gt;      obj.scaled = true;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    ctx.clearRect(-50, -50, 100, 100);&lt;br /&gt;    return ctx;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  function drawMinus(obj) {&lt;br /&gt;    // Get scaled canvas context, and clear previous image&lt;br /&gt;    var ctx = getScaledContext(obj);&lt;br /&gt;  &lt;br /&gt;    // Red circle&lt;br /&gt;    ctx.fillStyle = 'red';&lt;br /&gt;    ctx.beginPath();&lt;br /&gt;    ctx.arc(0, 0, 50, 0, cr, true);&lt;br /&gt;    ctx.fill();&lt;br /&gt;  &lt;br /&gt;    // White minus sign, rotated to obj.angle degrees&lt;br /&gt;    ctx.save();&lt;br /&gt;    ctx.rotate(obj.angle * deg);&lt;br /&gt;    ctx.fillStyle = 'white';&lt;br /&gt;    ctx.fillRect(-29, -6, 58, 12);&lt;br /&gt;    ctx.restore();&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  function spinLeft(obj) { spin(obj, -15, -90); }&lt;br /&gt;  function spinRight(obj) { spin(obj, 15, 0); }&lt;br /&gt;  &lt;br /&gt;  function spin(obj, step, goal) {&lt;br /&gt;    // While spinning, disable object's click handler to prevent competing spins&lt;br /&gt;    if (obj.onclick) {&lt;br /&gt;      obj.deferredOnclick = obj.onclick;&lt;br /&gt;      obj.onclick = null;&lt;br /&gt;    }&lt;br /&gt;    if (step == 0) return;&lt;br /&gt;    if ((step &amp;lt; 0 &amp;amp;&amp;amp; obj.angle &amp;lt;= goal) || (step &amp;gt; 0 &amp;amp;&amp;amp; obj.angle &amp;gt;= goal)) {&lt;br /&gt;      obj.angle = goal;&lt;br /&gt;      if (obj.nextLeft) {&lt;br /&gt;        obj.nextLeft = false;&lt;br /&gt;        if (obj.unlockCbk != null) obj.unlockCbk();&lt;br /&gt;        obj.unlockObj.style.display = 'block';&lt;br /&gt;      } else {&lt;br /&gt;        obj.nextLeft = true;&lt;br /&gt;        if (obj.lockCbk != null) obj.lockCbk();&lt;br /&gt;        obj.unlockObj.style.display = 'none';&lt;br /&gt;      }&lt;br /&gt;      if (obj.deferredOnclick) {&lt;br /&gt;        obj.onclick = obj.deferredOnclick;&lt;br /&gt;        obj.deferredOnclick = null;&lt;br /&gt;      }&lt;br /&gt;      return;&lt;br /&gt;    }&lt;br /&gt;    obj.angle += step;&lt;br /&gt;    drawMinus(obj);&lt;br /&gt;    setTimeout(function() {spin(obj, step, goal)}, 30);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  this.makeSpinner = function(className, unlockObj, lockCbk) {&lt;br /&gt;    unlockObj.style.display = 'none';&lt;br /&gt;    var cnv = document.createElement('canvas');&lt;br /&gt;    cnv.width = size;&lt;br /&gt;    cnv.height = size;&lt;br /&gt;    cnv.className = className;&lt;br /&gt;    cnv.angle = 0;&lt;br /&gt;    cnv.nextLeft = true;&lt;br /&gt;    cnv.unlockObj = unlockObj;&lt;br /&gt;    cnv.spinRight = function() { spinRight(cnv); }&lt;br /&gt;    cnv.onclick = function(e) {&lt;br /&gt;      cnv.nextLeft ? spinLeft(cnv) : spinRight(cnv);&lt;br /&gt;      e.stopPropagation();&lt;br /&gt;    }&lt;br /&gt;    if (lockCbk != null) cnv.lockCbk = lockCbk;&lt;br /&gt;    drawMinus(cnv);&lt;br /&gt;    return cnv;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;The Spinner Factory is a JavaScript closure that takes a single variable, size, which determines the diameter of the spinner buttons it creates. Individual spinners are created with the makeSpinner() method, which takes variables for the CSS class name for the spinner, the object to hide/unhide at the end of the spin, and an optional function reference to call after an object is re-locked. Typical usage would look like this: &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;sf = new SpinnerFactory(30);&lt;br /&gt;item.appendChild(sf.makeSpinner('minusBtn', deleteBtn));&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;...where "item" is a div tag you want to add a spinner to, and "deleteBtn" is the object that gets unhidden. &lt;/p&gt;&lt;p&gt;After getting all that working, I created some additional methods for the Spinner Factory to use the same scale to draw plus signs and arrows, which don't spin. &lt;/p&gt;&lt;p class=section&gt;Sizing a textarea to fit its content &lt;/p&gt;&lt;p&gt;This was a fun one! After taking great pains to tweak CSS settings to make the note text line up with the lines on the background image, I noticed during testing that if I entered too much text, I couldn't scroll to see it. To complicate matters, mobile Safari doesn't appear to use scrollbars, so there wasn't even an indication that there was more text to see. &lt;/p&gt;&lt;p&gt;After some online searching, I found that you can scroll textareas on the iPhone by using two-fingered swipes. I tested this, and although it worked, it was awkward, and transitions between edit mode (when the keyboard display pops up) and normal viewing mode left the display in unusual positions. I could struggle through it, but it wasn't ideal, and certainly not good enough for my wife. &lt;/p&gt;&lt;p&gt;There are DOM properties for textareas that can be monitored after each character is entered. The one that seemed most important was scrollHeight. It remained constant until any text overflowed off of the screen, then the value changed to the height needed by all the text. This was all independent of font size or the width of the textarea. &lt;/p&gt;&lt;p&gt;I quickly hacked out an event listener that monitored for scrollHeight changes, and set the textarea height to match. Since no scrollbars ever appeared, the user would have no indication that anything interesting was happening. The main problem with this is that the box wouldn't shrink back down if you deleted a bunch of text. The scrollHeight attribute doesn't go below the current height of the textarea. Although not necessarily a showstopper, I didn't like the idea that a user might think there was a lot of whitespace offscreen at the end of the note. I wanted a box that could grow and shrink with the text. &lt;/p&gt;&lt;p&gt;I switched instead to a method that uses a second textarea, hidden offscreen, to make measurements. First, all textareas in this app have some very specific CSS settings for positioning: &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;textarea {&lt;br /&gt;  border: 0;&lt;br /&gt;  background-image:url('images/paper.png');&lt;br /&gt;  margin:0;&lt;br /&gt;  padding:0;&lt;br /&gt;  padding-left: 13px;&lt;br /&gt;  width: 307px;&lt;br /&gt;  font-size: 17px;&lt;br /&gt;  outline: none;&lt;br /&gt;  font-family: Georgia;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Next, some simple CSS tells the "tester" area to hide offscreen (and to turn off scrollbars for testing with desktop Safari). &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;.tester {&lt;br /&gt;  position: absolute;&lt;br /&gt;  top: -1000px;&lt;br /&gt;  overflow: hidden;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;And finally the meat: &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;function textAreaSizer(obj) {&lt;br /&gt;  hiddenTextArea = document.createElement('textarea');&lt;br /&gt;  hiddenTextArea.rows = 20;&lt;br /&gt;  hiddenTextArea.className = 'tester';&lt;br /&gt;  obj.parentElement.appendChild(hiddenTextArea);&lt;br /&gt;  var last = '';&lt;br /&gt;&lt;br /&gt;  this.size = function(e) {&lt;br /&gt;    if (last != obj.value) {&lt;br /&gt;      last = obj.value;&lt;br /&gt;      hiddenTextArea.value = obj.value + "\n";&lt;br /&gt;      obj.style.height = hiddenTextArea.scrollHeight + 'px';&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  this.size();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;This closure accepts a textarea as input, and creates a sibling textarea using the "tester" class name. Note that I'm setting the hidden textarea's row size to 20, which means its scrollHeight will never fall below what's needed for 20 rows of text. &lt;/p&gt;&lt;p&gt;The web app in its current state is available &lt;a href="http://etchapps.appspot.com/notes.html"&gt;here&lt;/a&gt;. The source code doesn't try to obfuscate anything, but I still have some commenting and cleanup to do. &lt;/p&gt;&lt;p&gt;Enjoy! &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11885757-5439340503750743643?l=cautery.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cautery.blogspot.com/feeds/5439340503750743643/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://cautery.blogspot.com/2011/04/designing-notes-iphone-web-app.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/5439340503750743643'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/5439340503750743643'/><link rel='alternate' type='text/html' href='http://cautery.blogspot.com/2011/04/designing-notes-iphone-web-app.html' title='Designing a Notes iPhone web app'/><author><name>Curtis Autery</name><uri>https://profiles.google.com/107677530285177731535</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/--J3C_khtLqQ/AAAAAAAAAAI/AAAAAAAADT4/e2Qa5ncfAMk/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-Yl-lncVUyHY/TbGib0gqYWI/AAAAAAAADRA/scnJ9-vENl8/s72-c/notesIconScreenshot.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11885757.post-3323308881025409864</id><published>2011-04-13T20:48:00.004-04:00</published><updated>2011-04-13T20:52:38.223-04:00</updated><title type='text'>Emulating iPhone rotating buttons with HTML5 canvases</title><content type='html'>This is a quick proof of concept tested with Chrome and Safari (which might also work in Firefox... testers?). I'm using timeouts and HTML5 canvas operations to spin buttons, and some DOM tomfoolery to add and remove rows to the document's body. The end result is an approximation of some iPhone settings screens that make you unlock delete buttons before you can remove items. &lt;br /&gt;&lt;br /&gt;Enjoy! &lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;style&gt; .minus {   float: left;   margin: 4px;   display: none; }  .btn {   float: right;   margin: 10px;   background: red;   line-height: 40px;   color: white;   height: 30px;   font-weight: bold;   text-align: center;   color: white;   line-height: 28px;   -webkit-border-radius: 7px;   padding-left: 6px;   padding-right: 6px;   display: none;   text-indent: 0; }  .row {   height: 50px;   line-height: 50px;   width: 100%;   border: 1px solid black;   margin-bottom: 5px;   text-indent: 10px; } &lt;/style&gt;&lt;script type="text/javascript"&gt; var cr = Math.PI*2; // Circle var deg = Math.PI/180; // One degree var count = 0;  function drawMinus(obj) {   // Get canvas context, and clear previous image   var ctx = obj.getContext('2d');   ctx.clearRect(0, 0, 40, 40);    // Red circle   ctx.fillStyle = "red";   ctx.beginPath();   ctx.arc(20, 20, 20, 0, cr, true);   ctx.fill();    // White minus sign, rotated to obj.angle degrees   ctx.save();   ctx.translate(20, 20);   ctx.rotate(obj.angle * deg);   ctx.fillStyle = "white";   ctx.fillRect(-11, -3, 22, 6);   ctx.restore(); }  function drawPlus(obj) {   // Get canvas context   var ctx = obj.getContext('2d');    // Green circle   ctx.fillStyle = "green";   ctx.beginPath();   ctx.arc(20, 20, 20, 0, cr, true);   ctx.fill();    // White plus sign   ctx.fillStyle = "white";   ctx.fillRect(9, 17, 22, 6);   ctx.fillRect(17, 9, 6, 22); }  function makeDiv(className, cellText) {   var cell = document.createElement('div');   cell.className = className;   cell.innerText = cellText;   return cell; }  function addButton() {   var container = document.getElementById('btnContainer');   var rowDiv = makeDiv('row', 'Row ' + (++count));   container.appendChild(rowDiv);   var deleteBtn = makeDiv('btn', 'Delete');   rowDiv.appendChild(deleteBtn);   deleteBtn.onclick = function() { container.removeChild(rowDiv); }    var cnv = document.createElement('canvas');   cnv.className = 'minus';   cnv.width = 40;   cnv.height = 40;   cnv.onclick = function() { spinLeft(cnv) };   cnv.angle = 0;   cnv.callbackRight = function() {     deleteBtn.style.display = null;     cnv.onclick = function() { spinLeft(cnv) };   }   cnv.callbackLeft = function() {     deleteBtn.style.display = 'block';     cnv.onclick = function() { spinRight(cnv) };   }   rowDiv.appendChild(cnv);   drawMinus(cnv); }  function spinLeft(obj) { spin(obj, -15, -90); } function spinRight(obj) { spin(obj, 15, 0); }  function spin(obj, step, goal) {   if (obj.onclick) obj.onclick = null;   if (step == 0) return;   if ((step &lt; 0 &amp;&amp; obj.angle &lt;= goal) || (step &gt; 0 &amp;&amp; obj.angle &gt;= goal)) {     obj.angle = goal;     if (step &lt; 0) obj.callbackLeft();     else obj.callbackRight();     return;   }   obj.angle += step;   drawMinus(obj);   setTimeout(function() {spin(obj, step, goal)}, 30); }  function init() {   var styleSheet = document.styleSheets[document.styleSheets.length - 1];   var container = document.getElementById('btnContainer');   var cnv = document.createElement('canvas');   cnv.width = 40;   cnv.height = 40;   cnv.onclick = function() { spinLeft(cnv) };   cnv.angle = 0;   cnv.callbackRight = function() {     styleSheet.cssRules[0].style.display = 'none';     var elements = document.getElementsByClassName('minus');     for (var n = 0; n &lt; elements.length; n++) spinRight(elements[n]);     cnv.onclick = function() { spinLeft(cnv) };   }   cnv.callbackLeft = function() {     styleSheet.cssRules[0].style.display = 'block';     cnv.onclick = function() { spinRight(cnv) };   }   drawMinus(cnv);   container.appendChild(cnv);    var cnvPlus = document.createElement('canvas');   cnvPlus.width = 40;   cnvPlus.height = 40;   drawPlus(cnvPlus);   cnvPlus.style.float = 'right';   cnvPlus.onclick = addButton;   container.appendChild(cnvPlus);    addButton(); }  document.body.onload = init;  &lt;/script&gt;&lt;div id=btnContainer&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11885757-3323308881025409864?l=cautery.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cautery.blogspot.com/feeds/3323308881025409864/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://cautery.blogspot.com/2011/04/emulating-iphone-rotating-buttons-with_13.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/3323308881025409864'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/3323308881025409864'/><link rel='alternate' type='text/html' href='http://cautery.blogspot.com/2011/04/emulating-iphone-rotating-buttons-with_13.html' title='Emulating iPhone rotating buttons with HTML5 canvases'/><author><name>Curtis Autery</name><uri>https://profiles.google.com/107677530285177731535</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/--J3C_khtLqQ/AAAAAAAAAAI/AAAAAAAADT4/e2Qa5ncfAMk/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11885757.post-866897149267894445</id><published>2011-04-08T08:53:00.000-04:00</published><updated>2011-04-08T08:53:08.013-04:00</updated><title type='text'>HTML5 Web Databases in Chrome, round 1</title><content type='html'>New fact of life: To keep up with modern web programming, you need to get your head around asynchronous callbacks. To illustrate, here is a quick script I wrote to experiment with Chrome's JavaScript calls into it's SQLite implementation:&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;pre&gt;var output = null;&lt;br /&gt;&lt;br /&gt;function onSuccess(transaction, result) {&lt;br /&gt;  output = result.rows.item(0).sql;&lt;br /&gt;  console.log('onSuccess completed');&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function getDB(dbName) {&lt;br /&gt;  var fm = 5*1024*1024; // Five Megs&lt;br /&gt;  var db = openDatabase(dbName, '1.0', dbName, fm);&lt;br /&gt;  console.log('Database opened');&lt;br /&gt;&lt;br /&gt;  this.runSql = function(sql) {&lt;br /&gt;    db.readTransaction(function(t){&lt;br /&gt;      t.executeSql(sql, [], onSuccess)&lt;br /&gt;    });&lt;br /&gt;    console.log('runSql completed');&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  return this;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;var joe = getDB('db');&lt;br /&gt;joe.runSql("select * from sqlite_master");&lt;br /&gt;console.log('output: ' + output);&lt;br /&gt;console.log('End of script');&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Until it dawned on me that the SQL execution was asynchronous, I spent about 30 minutes chasing my tail trying to find a variable scope problem. In the console debugger, everything seemed to be set right when I manually entered commands one at a time, but the script didn't seem to be setting them when it ran. Didn't &lt;b&gt;seem&lt;/b&gt; to be, but it just wasn't happening when I thought.&lt;br /&gt;&lt;br /&gt;The above script was a re-write of what I was doing initially, with loggers at each step to show when the "output" variable gets set. Unsurprisingly, it happens on its own good time, not when the "procedural" part of the script reaches the end.&lt;br /&gt;&lt;br /&gt;Here's a screenshot of the console output:&lt;br /&gt;&lt;br /&gt;&lt;img src="https://lh3.googleusercontent.com/_YH1HTjXGzNU/TZ8EPEsX9rI/AAAAAAAADQk/vtC366bob6o/s640/DBcallsAreAsync.PNG" /&gt;&lt;br /&gt;&lt;br /&gt;The value of "output" is still null when the script reaches its last line. Manually checking the value after onSuccess completes shows that it does get set correctly, just later. So, there you have it. Writing that iPhone app or new web game? Start thinking async.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11885757-866897149267894445?l=cautery.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cautery.blogspot.com/feeds/866897149267894445/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://cautery.blogspot.com/2011/04/html5-web-databases-in-chrome-round-1.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/866897149267894445'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/866897149267894445'/><link rel='alternate' type='text/html' href='http://cautery.blogspot.com/2011/04/html5-web-databases-in-chrome-round-1.html' title='HTML5 Web Databases in Chrome, round 1'/><author><name>Curtis Autery</name><uri>https://profiles.google.com/107677530285177731535</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/--J3C_khtLqQ/AAAAAAAAAAI/AAAAAAAADT4/e2Qa5ncfAMk/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='https://lh3.googleusercontent.com/_YH1HTjXGzNU/TZ8EPEsX9rI/AAAAAAAADQk/vtC366bob6o/s72-c/DBcallsAreAsync.PNG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11885757.post-7953709664290972226</id><published>2011-04-06T19:35:00.005-04:00</published><updated>2011-04-06T20:21:14.462-04:00</updated><title type='text'>Rage against the Pitocin-Cesarean Complex</title><content type='html'>(and how I wrote my first iPhone web app) &lt;blockquote&gt;"So I got me a pen and a paper and I made up my own little sign. I said thank you Lord for thinking about me, I'm alive and doing fine." - Five Man Electrical Band &lt;/blockquote&gt;&lt;p&gt;Before rambling about my latest tinkerings, I have a small announcement: My wife and I decided to have a baby. She asked me not to make a big deal about it online, not post a broadcast "guess what?!?!" message on Facebook, and in the spirit of that I won't make flowery pronouncements here about the joys of fatherhood, or starting over at 40, or any of the hundreds of other things I would otherwise go on at length about. But there it is: I'm in love with a woman I think the world of, and at the beginning of January, with our third wedding anniversary near us and neither of us having one foot out the door or buyer's remorse, we decided to stop using birth control and try to have a baby. &lt;/p&gt;&lt;p&gt;By the end of the month, Liberty was pregnant. &lt;a name='more'&gt;&lt;/a&gt;When she was pregnant with Scout, Liberty wanted as natural and non-medicalized birth as possible, preferably a home birth with a midwife to assist. In Ohio, home birth and birthing centers are in a grey area legally. Instead of outright declaring that birth is only allowed in hospitals, the cost of liability insurance for midwifery prices many centers out of existence, and not all medical insurance plans cover them. Liberty unfortunately could not find a local center who took her insurance, but found one in Cincinnati that did. During a 37th week appointment with them, Liberty's blood pressure was elevated, so her midwife recommended going to a hospital for a urine test. At the hospital, the doctors were quick to diagnose preeclampsia, and demanded that she stay and be induced immediately. Needless to say, this wasn't the birth plan she had in mind. &lt;/p&gt;&lt;p&gt;The hospital tried to enforce the standard medical interventions designed to get the doctor to the golf course by tee time: Pitocin, epidural, Cesarean. Her midwife (bless her heart) went to bat for Liberty, telling them to back the hell off, insisting on a private room with a bathtub, that she be allowed to get up and move around, have access to food to keep her strength up, and helped Liberty maintain as much control over the process as possible. Scout's dad was caught between dueling ideologies and unsure of whose side to take. As much as I like him, I don't think he had the life experience needed to cope with a hospital trying to force its agenda on you through scare tactics. He tended to side with the doctors more often than not, but nothing in his experience told him to have anything but faith in what a doctor recommended. Despite that, Liberty's force of will and the strong advocacy of the midwife kept the unnecessary interventions to a minimum. &lt;/p&gt;&lt;p&gt;To be fair to Scout's dad, when Stacey was born, I was of a similar mindset, and Stacey's mom and I thought the hospital was just where you were supposed to go for labor. It wasn't until years later that it dawned on me that doctors are normal people with their own agenda, and a healthy skepticism was needed. I also knew that people still gave birth before there were hospitals, and people were trained to assist the mother before the field of medical obstetrics was invented. It wasn't until recently that it all clicked together for me: In the 60 years that hospital birth in developed countries has been the norm, we've progressed only marginally from twilight sleep and leather straps. The medical community continues to lack empathy and support for mothers in labor, and until this changes, hospital births should be avoided where possible. The field of obstetrics has done too much to disempower and dehumanize women in what is supposed to be an important, memorable, beautiful event. Women should be revered while they're creating life; doing otherwise is God-damned unconscionable. &lt;/p&gt;&lt;p&gt;Back to the story: Because Liberty was induced before her body was ready, her body balked, and she endured a painful 3 day labor. Despite the long labor, the constant onslaught of doctors saying, as if scolding a small child for not cleaning her room, "you know, it's going to be time for a C-section if you don't progress soon," and despite the physical pain of prolonged use of Pitocin, Scout was born vaginally, without need of scalpel or forceps, and from what I've divined in the 3 and a half years I've known her, is both healthy and intelligent. Everything ended well with Scout's birth, but needless to say that isn't the type of birth we want this time. &lt;/p&gt;&lt;p&gt;We found a good midwife center here in Columbus, &lt;a href="http://www.choicemidwives.org/"&gt;CHOICE&lt;/a&gt;, to see during the pregnancy, and we intend to have the baby on &lt;a href="http://www.thefarmmidwives.org/"&gt;The Farm&lt;/a&gt;, a commune that managed to survive after the 70s when the popular hippie movement died down, and home to the mother of modern midwifery, Ina May Gaskin. Ina May authored &lt;a href="http://www.bookpubco.com/products/spiritual-midwifery"&gt;"Spiritual Midwifery"&lt;/a&gt;, which I can't recommend highly enough to anyone planning on having a baby, and was interviewed in Ricki Lake's movie, &lt;a href="http://movies.netflix.com/WiMovie/The-Business-of-Being-Born/70075502"&gt;"The Business of Being Born"&lt;/a&gt;, a must-see for the expecting couple. She is also the namesake of the Gaskin Maneuver, a Guatemalan technique that she popularized that helps with shoulder dystocia - where an infant's shoulder gets stuck when they crown. (When we went down to visit The Farm recently, Liberty saw Ina May driving by, and was all excited. It was cute.) &lt;/p&gt;&lt;p&gt;After being frank about the previous birth to our CHOICE midwife, she said some things that we were happy to hear, namely that preeclampsia is more common in first-time mothers, and a high protein, high calcium diet is good insurance against a repeat occurrence. I found some articles and a study that supported both of those assertions, which was reassuring to me. Before meeting Liberty, I had no experience with what midwives were supposed to be (as is true of most Americans). Based on my experiences so far, I'm sold on them. They are competent professionals, more knowledgeable about childbirth than the surgeons who call themselves obstetricians. Midwives believe, like I do, that childbirth doesn't belong in a hospital with medical intervention, or with the mother on her back, scared, and taking orders. &lt;/p&gt;&lt;p&gt;So coupled with the protein/calcium diet advice, Liberty wanted to monitor her fluid and fiber intake as well, so she set out to look for an iPhone app that could help her track all that. Sadly there weren't any that had all four, or that were customizable. And this is where I come in, using my geek mojo to try to attack the problem. &lt;/p&gt;&lt;p&gt;About 6 months back, I signed up for Apple's developer program, giving them my gmail address, but never heard back. My main home workstations run XP and Linux, so to use XCode to write iPhone apps, I would need to confiscate Liberty's Macbook, giving me two reasons not to code a native app right off the bat. After some digging, I found that Safari supports the offline application cache and web storage specs, and iOS lets you bookmark a website to the "desktop" with a custom icon and splash screen, and provides controls to put Safari in a sort of kiosk mode. In other words, you can click on a button on the main screen, have it open a web app that can save data locally, and the result is basically indistinguishable from a native app. With this approach, I would be able to code for the iPhone with Windows or Linux, and not pay Apple for the right to do so, so that's the road I took. &lt;/p&gt;&lt;p class=section&gt;Getting started &lt;/p&gt;&lt;p&gt;At the beginning of this effort, I decided to code the UI from scratch using un-obfuscated JavaScript to build tables, "buttons" (&amp;lt;span&amp;gt; tags, actually), and onclick handlers. In an attempt to move things along quickly, I didn't fully separate out functionality using MVP, MVC, or other mainstream architectural patterns, but the UI and object functions are fairly split apart. To illustrate, here are functions to build a generic button (UI), and another to remove a food item from a day's eating history (object model). &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;function makeButton(buttonText, callBack) {&lt;br /&gt;  var button = document.createElement('span');&lt;br /&gt;  button.className = 'button';&lt;br /&gt;  button.innerText = buttonText;&lt;br /&gt;  button.onclick = callBack;&lt;br /&gt;  return button;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function removeItem(index, dayString) {&lt;br /&gt;  if (lentil[dayString] == null || lentil[dayString][index] == null) return;&lt;br /&gt;  lentil[dayString].splice(index, 1);&lt;br /&gt;  saveData();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Whereas, here is sort of a kluge to return a table of a day's eating, that can't decide if it's the user interface, the object model, or a controller: &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;function getDayTable(dayString) {&lt;br /&gt;  var outTable = initTable();&lt;br /&gt;  if (lentil[dayString] == null) lentil[dayString] = [];&lt;br /&gt;  var totals = [];&lt;br /&gt;  for (var n = 0; n &amp;lt; trackElements.length; n++) totals.push(0);&lt;br /&gt;&lt;br /&gt;  var counts = {};&lt;br /&gt;  for (var n in lentil[dayString]) {&lt;br /&gt;    var name = items[lentil[dayString][n]].name;&lt;br /&gt;    counts[name] = (counts[name] == null) ? 1 : counts[name] + 1;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  var seen = {};&lt;br /&gt;  for (var n in lentil[dayString]) {&lt;br /&gt;    var itemNum = lentil[dayString][n];&lt;br /&gt;    var item = items[itemNum];&lt;br /&gt;    if (seen[item.name] == null) {&lt;br /&gt;      roundCollection(item.elements);&lt;br /&gt;      var row = collectionToCountsRow(item.name, item.elements, counts[item.name]);&lt;br /&gt;      var callback = new callbackRef('verifyRemove', itemNum, n, dayString);&lt;br /&gt;      row.onclick = callback.invoke;&lt;br /&gt;      outTable.appendChild(row);&lt;br /&gt;      incrementTotals(itemNum, totals, counts[item.name]);&lt;br /&gt;      seen[item.name] = true;&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;  outTable.appendChild(totalsRow(totals));&lt;br /&gt;  return outTable;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;There's still quite a bit of overlap, and as the code progresses I'll get better role separation. Round one, though, quick and dirty, weighing in at only 400 lines of JavaScript and giving my wife something usable while she's still pregnant, a more important concern than glass-tower programming theory. &lt;/p&gt;&lt;p class=section&gt;Lentil &lt;/p&gt;&lt;p&gt;You may have noticed references above to a hash named "lentil". When Liberty was early in her first trimester, she estimated the baby's size to be about that of a lentil. When she would have baby-related symptoms such as an upset stomach, she would say things like "Lentil is really doing a number on me today." So after she balked at my naming the first build of my program "Preggers", she recommended the name Lentil instead, which was more agreeable to both of us. &lt;/p&gt;&lt;p&gt;We shamelessly stole an image off the net for the home screen button: &lt;/p&gt;&lt;p&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-r-rwz0egigk/TZz2DKKdfTI/AAAAAAAADOs/RTaB0fqoOjo/s1600/01a-iPhoneScreenshot.png" imageanchor="1" style=""&gt;&lt;img border="0" height="320" width="214" src="http://4.bp.blogspot.com/-r-rwz0egigk/TZz2DKKdfTI/AAAAAAAADOs/RTaB0fqoOjo/s320/01a-iPhoneScreenshot.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;&lt;p&gt;...but we have a wooden bowl and a bag of lentils at home with which to make a similar image of our own so we won't be dirty cheaters. Or get sued. &lt;/p&gt;&lt;p class=section&gt;Making a web page look like an app &lt;/p&gt;&lt;p&gt;There are a pair of HTML meta tags to enable fullscreen mode and darken the status bar (the top of the iPhone screen that shows your battery level, time, etc.) They are as follows: &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;meta name="apple-mobile-web-app-capable" content="yes" /&amp;gt;&lt;br /&gt;&amp;lt;meta name="apple-mobile-web-app-status-bar-style" content="black" /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Another meta tag can change viewport settings, like disabling zooming, and setting the viewport's width and initial zoom levels: &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0"/&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;The last iPhone-specific HTML-based hints I used are for setting the home screen icon and the splash-screen. The addresses are relative to the location of the page they are referenced from. &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;link rel="apple-touch-icon" href="images/icon.jpg"/&amp;gt;&lt;br /&gt;&amp;lt;link rel="apple-touch-startup-image" href="images/startup.png" /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;My splashscreen is a little cartoony right now; it's definitely something that will be professionalled-up when this comes out of beta. Here's the current image: &lt;/p&gt;&lt;p&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-TFtGGJux6h0/TZz2c9r1HBI/AAAAAAAADO0/i_w4DpidG1s/s1600/01b-startup.png" imageanchor="1" style=""&gt;&lt;img border="0" height="320" width="222" src="http://3.bp.blogspot.com/-TFtGGJux6h0/TZz2c9r1HBI/AAAAAAAADO0/i_w4DpidG1s/s320/01b-startup.png" /&gt;&lt;/a&gt;&lt;/div&gt;  &lt;/p&gt;&lt;p&gt;With those HTML tags on a page, you can visit it from Safari on the iPhone, bookmark it to your homescreen, and from then on it will open like a native app. More information about tags that will influence Safari on the iPhone are available &lt;a href="http://developer.apple.com/library/safari/#documentation/appleapplications/reference/SafariHTMLRef/Articles/MetaTags.html"&gt;here&lt;/a&gt; (as well as scores of other pages). &lt;/p&gt;&lt;p class=section&gt;Offline Web applications &lt;/p&gt;&lt;p&gt;The W3C's HTML5 working draft has a nice summary of how offline caching of web applications works, available &lt;a href="http://www.w3.org/TR/html5/offline.html"&gt;here&lt;/a&gt;. Briefly, the main HTML page references a manifest file. The manifest file lists what files to cache, and the browser caches them. The next time the page is opened, a single query to the web server is made to see if the manifest file has been altered. If it hasn't (or if the browser is offline), all the web resources are loaded from the cache instead of the network. &lt;/p&gt;&lt;p&gt;In other words, if I open a cached web application while the iPhone is in airplane mode, it will still open. Additionally, if the manifest file hasn't been updated, only a single HTTP GET is issued for the manifest file before the application opens, speeding up opening quite a bit. &lt;/p&gt;&lt;p&gt;The caveat is that the manifest file must be served with a content type of "text/cache-manifest" for browsers to turn on caching. In the near future, I imagine by default most web servers will serve .manifest files with this content type, but currently some twiddling is needed - at least, that's true on my current web server of choice, Google's App Engine. &lt;/p&gt;&lt;p&gt;I use Eclipse/Java for deploying App Engine projects, and changing the content type served for a given file extension is accomplished with a few lines in the project's web.xml file: &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;mime-mapping&amp;gt;    &lt;br /&gt;  &amp;lt;extension&amp;gt;manifest&amp;lt;/extension&amp;gt;        &lt;br /&gt;  &amp;lt;mime-type&amp;gt;text/cache-manifest&amp;lt;/mime-type&amp;gt;        &lt;br /&gt;&amp;lt;/mime-mapping&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;To verify this was working as expected, I deployed a project, telnetted to the web server on port 80, and did a manual GET for the file: &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;GET /lentil.manifest HTTP/1.1&lt;br /&gt;Host: lentiltracker.appspot.com&lt;br /&gt;&lt;br /&gt;HTTP/1.1 200 OK&lt;br /&gt;ETag: "kRe4nQ"&lt;br /&gt;Date: Sat, 02 Apr 2011 08:47:45 GMT&lt;br /&gt;Expires: Sat, 02 Apr 2011 08:57:45 GMT&lt;br /&gt;Cache-Control: public, max-age=600&lt;br /&gt;&lt;b&gt;Content-Type: text/cache-manifest&lt;/b&gt;&lt;br /&gt;Server: Google Frontend&lt;br /&gt;Transfer-Encoding: chunked&lt;br /&gt;&lt;br /&gt;a3&lt;br /&gt;CACHE MANIFEST&lt;br /&gt;&lt;br /&gt;# Beta 9.&lt;br /&gt;&lt;br /&gt;# js files&lt;br /&gt;json2.js&lt;br /&gt;lentil.js&lt;br /&gt;...rest of file&lt;br /&gt;0&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;As you can see, the content type came through correctly. Rather than the browser downloading the entire file each time and comparing it with a cached copy, the HTTP entity tag reference (&lt;a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.19"&gt;ETag&lt;/a&gt;) is used to determine if the web server thinks the file has changed. This is accomplished by including an &lt;a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.26"&gt;"If-None-Match"&lt;/a&gt; field in the GET request, specifying the last ETag value. If the browser gets back an HTTP 304 response, it knows there's no need to re-download the entire file. Here's how that looks over telnet: &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;GET /lentil.manifest HTTP/1.1&lt;br /&gt;Host: lentiltracker.appspot.com&lt;br /&gt;If-None-Match: "kRe4nQ"&lt;br /&gt;&lt;br /&gt;HTTP/1.1 304 Not Modified&lt;br /&gt;ETag: "kRe4nQ"&lt;br /&gt;Date: Sat, 02 Apr 2011 08:53:31 GMT&lt;br /&gt;Server: Google Frontend&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;My project has a number of resource files with it: The main HTML page, a CSS file, JavaScript file, the icon and splashscreen images, and of course the manifest file. My App Engine resource usage will look something like this for requests that come after all of those files have been cached: &lt;/p&gt;&lt;p&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-ZRfMk6cRs6s/TZz2rEK635I/AAAAAAAADO8/dhMLSdkGzfM/s1600/02-recentRequests.png" imageanchor="1" style=""&gt;&lt;img border="0" height="83" width="320" src="http://1.bp.blogspot.com/-ZRfMk6cRs6s/TZz2rEK635I/AAAAAAAADO8/dhMLSdkGzfM/s320/02-recentRequests.png" /&gt;&lt;/a&gt;&lt;/div&gt;  &lt;/p&gt;&lt;p&gt;Ideally, just the manifest file, and most of those should be HTTP 304s. What I've found in practice, though, is that App Engine gives the occasional HTTP 200 for a file that hasn't changed, which leads me to believe they don't always store the ETag field the same way on all mirrored servers, or possibly each App instance regenerates new values. Consequently, Safari busies itself with comparing the file contents, and sees that all is well so doesn't re-download the CSS, JavaScript or main page files. In some of these cases, the iPhone's desktop subsystem will re-download the icon and splashscreen files, sending a user agent containing CFNetwork and Darwin, contrasted with Safari's AppleWebKit. A typical set of log entries looks like this: &lt;/p&gt;&lt;p&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-zGPi4FEKW0M/TZz2y9MIoEI/AAAAAAAADPE/0t0G-EGKZ2E/s1600/03-serverLog.png" imageanchor="1" style=""&gt;&lt;img border="0" height="130" width="320" src="http://2.bp.blogspot.com/-zGPi4FEKW0M/TZz2y9MIoEI/AAAAAAAADPE/0t0G-EGKZ2E/s320/03-serverLog.png" /&gt;&lt;/a&gt;&lt;/div&gt;  &lt;/p&gt;&lt;p&gt;Even considering that the 304s aren't consistent, this is still a lot less traffic than having each file be downloaded fresh each time the app runs. The web traffic benefit is good reason to use application caching of static content (or code) where possible, even if you aren't trying to make a web page look like a native iPhone app. &lt;/p&gt;&lt;p&gt;Since Safari on the iPhone and Google Chrome both use the WebKit engine, I did most of my testing for this project with Chrome on Windows for the basic reason that its debugging tools are fantastic. For example, from the chrome://net-internals/ URL, you can capture and view raw network bytes, as well as see when Chrome is grabbing a resource from the application cache instead of the network. For example, here is how Chrome responded to the order to load my app's CSS file: &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;Start Time: Sat Apr 02 2011 04:33:06 GMT-0400 (Eastern Daylight Time)&lt;br /&gt;&lt;br /&gt;t=1301733186906 [st= 0] +REQUEST_ALIVE             [dt=69]&lt;br /&gt;t=1301733186906 [st= 0]    +URL_REQUEST_START_JOB  [dt=29]&lt;br /&gt;                            --&amp;gt; load_flags = 65536 (VERIFY_EV_CERT)&lt;br /&gt;                            --&amp;gt; method = "GET"   &lt;br /&gt;                            --&amp;gt; priority = 1     &lt;br /&gt;                            --&amp;gt; url = "http://lentiltracker.appspot.com/lentil.css"&lt;br /&gt;t=1301733186916 [st=10]        APPCACHE_DELIVERING_CACHED_RESPONSE  &lt;br /&gt;t=1301733186935 [st=29]    -URL_REQUEST_START_JOB  &lt;br /&gt;t=1301733186975 [st=69] -REQUEST_ALIVE &lt;br /&gt;&lt;/pre&gt;&lt;p&gt;In fact, the net-internals page is where I first noticed the business with ETags and HTTP 304 responses: &lt;/p&gt;&lt;p&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-xDpw2rpheSI/TZz3TSMwoWI/AAAAAAAADPM/NBPhzBSQVZM/s1600/10-netInternals.PNG" imageanchor="1" style=""&gt;&lt;img border="0" height="311" width="320" src="http://4.bp.blogspot.com/-xDpw2rpheSI/TZz3TSMwoWI/AAAAAAAADPM/NBPhzBSQVZM/s320/10-netInternals.PNG" /&gt;&lt;/a&gt;&lt;/div&gt;  &lt;/p&gt;&lt;p&gt;If you want to see all the stored manifest files, or delete individual application caches, you can accomplish that from chrome://appcache-internals/, as shown in this screenshot: &lt;/p&gt;&lt;p&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-A8NN3yg2wQs/TZz3p4n2TkI/AAAAAAAADPU/CiybqfRinko/s1600/09-appcacheInternals.png" imageanchor="1" style=""&gt;&lt;img border="0" height="320" width="300" src="http://4.bp.blogspot.com/-A8NN3yg2wQs/TZz3p4n2TkI/AAAAAAAADPU/CiybqfRinko/s320/09-appcacheInternals.png" /&gt;&lt;/a&gt;&lt;/div&gt;  &lt;/p&gt;&lt;p class=section&gt;Storing data locally &lt;/p&gt;&lt;p&gt;In the past, having a browser store data locally could only be accomplished with HTTP cookies, the much-maligned bastard stepchild of the Internet. There are two major drawbacks to using them, namely size limits (4k per cookie, 20 cookies per domain), and the fact that they are sent by the client with every request. The original Netscape recommendation for cookies indicated the idea was for them to manage "state". The server would be notified what state the browser thought it was in, and the server could make decisions based on that. &lt;/p&gt;&lt;p&gt;A newer recommendation for &lt;a href="http://www.w3.org/TR/webstorage/"&gt;web storage&lt;/a&gt; is being hashed out for the HTML5 standard, and Chrome and Safari (and I assume other browsers) already have it implemented, complete with a handy JavaScript accessor: localStorage.[name] = [string] for storing simple strings. There is also a web database recommendation that allows local DB objects that can be queried with SQL, but I chose the simple localStorage method so I could get something functional quickly, and used JSON to turn my JavaScript objects into strings. &lt;/p&gt;&lt;p&gt;I ended up with a pair of simple functions that manage turning an eating history object and a food types object into localStorage strings, and back again: &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;var lentil = {}; // History hash&lt;br /&gt;var items = [];  // Array of food types&lt;br /&gt;&lt;br /&gt;function init() {&lt;br /&gt;  if (localStorage == null) {&lt;br /&gt;    alert("Local storage features won't work in this browser.");&lt;br /&gt;  } else {&lt;br /&gt;    if (localStorage.lentilHistory) lentil = JSON.parse(localStorage.lentilHistory);&lt;br /&gt;    if (localStorage.lentilItems) items = JSON.parse(localStorage.lentilItems);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function saveData() {&lt;br /&gt;  localStorage.lentilHistory = JSON.stringify(lentil);&lt;br /&gt;  localStorage.lentilItems = JSON.stringify(items);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Chrome's developer tools can be used to see the raw contents of the local storage DOM tree, as shown here: &lt;/p&gt;&lt;p&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-vSihvR_x-1U/TZz3xejaOxI/AAAAAAAADPc/9iG7BcCszIU/s1600/11-localStorage.png" imageanchor="1" style=""&gt;&lt;img border="0" height="135" width="320" src="http://2.bp.blogspot.com/-vSihvR_x-1U/TZz3xejaOxI/AAAAAAAADPc/9iG7BcCszIU/s320/11-localStorage.png" /&gt;&lt;/a&gt;&lt;/div&gt;  &lt;/p&gt;&lt;p&gt;Now that I have my feet under me with web apps, I can either databasify this, or at least split foods and days into unique objects so that the entire history can't be blown away with one bad write. How to manage doing that and save all the data Liberty already has entered will take some hemming and hawing, but shouldn't be too much of a puzzler. &lt;/p&gt;&lt;p&gt;The rest is all JavaScript to handle events and turn arrays of food items into tables. Here are a few screenshots of how the pages look now, but it needs a little usability tweaking, and a lot of prettying up. &lt;/p&gt;&lt;p&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-VLRWb9lmTQw/TZz4IhnFIdI/AAAAAAAADPk/rTVdg56u-Zs/s1600/04-Calendar.png" imageanchor="1" style=""&gt;&lt;img border="0" height="320" width="260" src="http://2.bp.blogspot.com/-VLRWb9lmTQw/TZz4IhnFIdI/AAAAAAAADPk/rTVdg56u-Zs/s320/04-Calendar.png" /&gt;&lt;/a&gt;&lt;/div&gt; &lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-M-mINdV85mo/TZz4I83WEkI/AAAAAAAADPs/vETZcNJ_q-g/s1600/05-newFood.png" imageanchor="1" style=""&gt;&lt;img border="0" height="273" width="320" src="http://4.bp.blogspot.com/-M-mINdV85mo/TZz4I83WEkI/AAAAAAAADPs/vETZcNJ_q-g/s320/05-newFood.png" /&gt;&lt;/a&gt;&lt;/div&gt; &lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-HqMUmnhBBA8/TZz4JbR5AKI/AAAAAAAADP0/jTjqGCkLEbE/s1600/07-showDay.png" imageanchor="1" style=""&gt;&lt;img border="0" height="257" width="320" src="http://1.bp.blogspot.com/-HqMUmnhBBA8/TZz4JbR5AKI/AAAAAAAADP0/jTjqGCkLEbE/s320/07-showDay.png" /&gt;&lt;/a&gt;&lt;/div&gt; &lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-EtI3ov8wduM/TZz4J93s2OI/AAAAAAAADP8/RHtNBXc88OA/s1600/08-summary.png" imageanchor="1" style=""&gt;&lt;img border="0" height="320" width="258" src="http://2.bp.blogspot.com/-EtI3ov8wduM/TZz4J93s2OI/AAAAAAAADP8/RHtNBXc88OA/s320/08-summary.png" /&gt;&lt;/a&gt;&lt;/div&gt;  &lt;/p&gt;More tweaks of the app will come, and in all likelihood I'll leave it up on the &lt;a href="http://lentiltracker.appspot.com/"&gt;App Engine page&lt;/a&gt; as a free tool. The end result that I care about, though, is Liberty's use of it. She is tracking her calcium and protein, and can see at a glance if she's on the road to avoiding a second hospital birth. As a husband who cares about this sort of thing, I'm doing everything in my power to support a natural birth. I'm just glad in this case there is enough overlap between what I'm good at and what Liberty needs so that I can contribute.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11885757-7953709664290972226?l=cautery.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cautery.blogspot.com/feeds/7953709664290972226/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://cautery.blogspot.com/2011/04/rage-against-pitocin-cesarean-complex.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/7953709664290972226'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/7953709664290972226'/><link rel='alternate' type='text/html' href='http://cautery.blogspot.com/2011/04/rage-against-pitocin-cesarean-complex.html' title='Rage against the Pitocin-Cesarean Complex'/><author><name>Curtis Autery</name><uri>https://profiles.google.com/107677530285177731535</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/--J3C_khtLqQ/AAAAAAAAAAI/AAAAAAAADT4/e2Qa5ncfAMk/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-r-rwz0egigk/TZz2DKKdfTI/AAAAAAAADOs/RTaB0fqoOjo/s72-c/01a-iPhoneScreenshot.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11885757.post-5396732055206039059</id><published>2011-03-05T11:46:00.001-05:00</published><updated>2011-03-05T11:47:10.974-05:00</updated><title type='text'>Success through embracing mistakes</title><content type='html'>&lt;blockquote&gt;&lt;i&gt;"The dogmas of the quiet past, are inadequate to the stormy present. The occasion is piled high with difficulty, and we must rise -- with the occasion. As our case is new, so we must think anew, and act anew. We must disenthrall ourselves, and then we shall save our country."&lt;/i&gt; - Abraham Lincoln&lt;/blockquote&gt;"I hate math, dad" my daughter said to me a few days ago. It wasn't really a shock to hear it, rather it was the final nail in the coffin, which I'd seen coming for the last few years. The middle school years, sitting in rows, staring at the backs of her peers' heads, listening to lectures, seeing story problems which were so fanciful as to be ridiculous. So Bill's dad's age is 5 less than 3 times Bill's age, and the sum of their ages is 49? Really? Does that sort of thing come up in life a lot?&lt;br /&gt;&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;As a toddler, we played with shapes and numbers for fun. I showed her how fractions work at 4 years old, by drawing on my whiteboard at the office. I drew a circle and drew lines through it, then shaded parts in and wrote down the fraction it represented. With some experimentation, she saw how shading two quarters of a circle took up the same space as one half. She "got it", and was thrilled to figure out fractions. Innoculated against the idea that math is hard, she spent all of her elementary school years scoring off the charts in math, and was offered a spot in an advanced math/science program in the 4th and 5th grades, going to a different school once a week to work solely on math and science topics.&lt;br /&gt;&lt;br /&gt;And then there was middle school. Now in high school, with the middle school craziness coupled with years of peer pressure to reject appearing smart in order to be more popular, her standardized test scores slipped from "phenomenal" to merely "advanced". The coup de grâce happened this year, when she told me flatly how she feels about math. Another creative spirit successfully crushed by an education system designed in the 19th century to meet the needs of industrialism.&lt;br /&gt;&lt;br /&gt;Something similar happened to me, back in the day. One of the reasons that I didn't go to college is that traditional education doesn't agree with me. In school I learned many strategies for test-taking that did not involve learning the subject matter of the class. I felt stifled by the needless repetition of lessons. I dislike the overall layout of textbooks, and the transparent committee thinking that goes into them.&lt;br /&gt;&lt;br /&gt;What I disliked the most, though, was the idea that mistakes were bad, and not a tool for learning. A test would have, say, 20 questions on a chapter's topic, and you would have 20 chances to make a mistake that would cost you points. In classes where I "got it" to the point of being bored and wanting to move on, the repetition would get me. By question 5 I'd be hurrying through the uninteresting test and making speed-based errors rather than mistakes based on not knowing the material. In classes where I didn't "get it", the opposite behavior of going slower and using test-taking strategies artificially inflated my test scores, and made it seem that I knew material that I didn't.&lt;br /&gt;&lt;br /&gt;Somehow I managed to come out of school with a love of numbers, and of science, history, and books, but all of that was at risk of being crushed by traditional schooling. For me it was a close shave with rejecting all academics, as I was more focused on passing tests and getting the hell away from school than I was in embracing what was being taught. It was a lot of effort to find the tiny nuggets of "interesting" buried in the rubble of textbooks and lesson plans, but I eventually found them. My high school helped when I was on the brink of throwing it all away. I went to the &lt;a href="http://linworth.org/program.htm"&gt;Linworth Alternative Program&lt;/a&gt;, whose teachers were much easier to cope with. The AP was a much better approach to education than I had seen in the seven schools I had been to previously, but even they were subjected to the tyranny of test = grade.&lt;br /&gt;&lt;br /&gt;The running theme that school threw at both my daughter and myself is this: Pass the test. The more mistakes you make, the worse you "do" in the class, regardless of what skills you learn. Measuring knowledge or understanding is not happening, only test-taking ability is being measured. To prepare for a test, one crams, regurgitates, and forgets. Next year, the teacher has to re-explain the basics supposedly learned the previous year before starting any new material.&lt;br /&gt;&lt;br /&gt;Outside of schools, making mistakes is a tool that increases your understanding of the world around you. When learning a new skill, you will be very error-prone at first as your brain and body try to cope with something they have never done before. When you first learn to play the piano, you can't make it through a piece error-free to save your life. Eventually the smaller skills that make a musician get mastered: sight-reading music, hand separation, hearing the piece in your head, finger strength and speed, passion.&lt;br /&gt;&lt;br /&gt;Any junior level software developer tasked with solving a new problem will tell you this story: "I took the problem statement and started coding for it. Once I figured out what I was doing wrong, I better understood the nature of the problem. Then I started over and wrote a better program." A more advanced developer will tell you the real value of tests is in failing them. In fact, the Test Driven Development model is exactly that: Write a test for the requirement before you write any code, a test that is guaranteed to fail out of the gate. Run the test and watch it fail. (If it doesn't fail, your test is flawed). Code for the new test, then run all the tests again, until nothing fails. (There's more to it than that outside the scope of this screed, and if you're interested you can get more info &lt;a href="http://books.google.com/books?id=gFgnde_vwMAC&amp;amp;lpg=PP1&amp;amp;dq=kent%20beck&amp;amp;pg=PP1#v=onepage&amp;amp;q&amp;amp;f=false"&gt;here&lt;/a&gt;.)&lt;br /&gt;&lt;br /&gt;In my job, tests are for tuning functionality, and if you don't fail a bunch of tests in the process of writing your program, you're either a damned genius or you're writing something simplistic and boring. In school, tests immediately serve to bring down your grade in the class, so the students must concentrate not on learning skills, but on passing tests. Will this be on the test? What's the answer the teacher wants?&lt;br /&gt;&lt;br /&gt;This is all ass-backwards on its face, and judging by my daughter Stacey's experiences 20 years after my own, schools are still being run the same way. There is advocacy for change, by the likes of &lt;a href="http://www.ted.com/talks/lang/eng/dan_meyer_math_curriculum_makeover.html"&gt;Dan Meyer&lt;/a&gt; and &lt;a href="http://www.ted.com/talks/view/id/66"&gt;Ken Robinson&lt;/a&gt;, but change is slow in coming.&lt;br /&gt;&lt;br /&gt;My solution? Grade all classes the way arts classes are graded, with the three Ps: Participation, passion, and projects. In drama class, a play can demonstrate the skills of memorization, timing, getting into character. In drawing classes, projects can demonstrate understanding of perspective, observation, different mediums.&lt;br /&gt;&lt;br /&gt;In math classes, is it important that students can calculate by rote dozens of times in a row? No, unless they are yearning for assembly line work. Instead, how about projects demonstrating the desired skills? Look for a &lt;b&gt;real life&lt;/b&gt; problem that can be measured and have math principles applied to it. Mom and Dad each have cars with different MPGs, and they work different distances from home. How can they save gas? Dad's credit cards are maxed out, and he has $40 extra dollars a month dedicated to paying them off. Each card has a different balance and interest rate. In what order should he apply the $40 to pay them off the quickest?&lt;br /&gt;&lt;br /&gt;Math class would be the easiest to reform, since I think everyone would agree it's the most broken. Other classes would be harder (by me, anyway) to modernize, but I believe similar project-based approaches are possible for them as well. I also believe schools should no longer be aligned with the needs of the business world. They should export thinkers, not workers. Businesses can take care of their own needs, and will find other ways to make drones when they no longer have the explicit consent of public education.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11885757-5396732055206039059?l=cautery.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cautery.blogspot.com/feeds/5396732055206039059/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://cautery.blogspot.com/2011/03/success-through-embracing-mistakes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/5396732055206039059'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/5396732055206039059'/><link rel='alternate' type='text/html' href='http://cautery.blogspot.com/2011/03/success-through-embracing-mistakes.html' title='Success through embracing mistakes'/><author><name>Curtis Autery</name><uri>https://profiles.google.com/107677530285177731535</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/--J3C_khtLqQ/AAAAAAAAAAI/AAAAAAAADT4/e2Qa5ncfAMk/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11885757.post-2797651215583651036</id><published>2011-01-21T07:42:00.001-05:00</published><updated>2011-01-21T20:23:53.435-05:00</updated><title type='text'>4,046</title><content type='html'>I've disabled this blog's Google Analytics feed. The feed assures me that there were 4,046 visits here over the past year, most of which occurred after a swell of visits in August '10 when I started posting about various coding experiments I was working on. From that time forward, there were over 100 visits per week to the site, most of which turned out not to be loyal fans, but rather one time visits referred here by search engines.&lt;br /&gt;&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_YH1HTjXGzNU/TTl-5R4r7sI/AAAAAAAADLQ/NhnaHCiTA1s/s1600/visitors1.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="127" src="http://4.bp.blogspot.com/_YH1HTjXGzNU/TTl-5R4r7sI/AAAAAAAADLQ/NhnaHCiTA1s/s320/visitors1.PNG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;It turns out that Google was ranking me fairly high on some search terms, and when I noticed the increased traffic, I tried to leverage that a couple different ways. First, I succumbed briefly to temptation and put Adwords advertisements on the site for a couple weeks. Now, 4,046 is a nice number for a lone blogger who started out just writing about his kid, but it's not enough to pay the bills on click-throughs. So I took them down when my Adwords balance slowly crawled to the 7 cent mark.&lt;br /&gt;&lt;br /&gt;Next, I put up a couple different attempts to solicit feedback from visitors, which was about as popular with visitors as the ads. I got a total of 4 responses, one of which was just a smartass comment from a friend I work with, another was not honest feedback, but a solicitation to help grow a content farm.&lt;br /&gt;&lt;br /&gt;So I've taken down the "feedback" link, and turned off analytics, as it never really bought me anything other than some nebulous insight into what people search for, and how hard it is to get the attention of people looking for homework help, job interview answers, or instructions on gaming Facebook's PuzzleMaster coding puzzles... not that I look down on any of that. If you see how I solved a problem, maybe something will click and you'll be better off. If your goal is to cheat an assignment or test, well, good luck with that, but I doubt I'm improving anyone's chances of passing a class they weren't meant to. For now, "The Sky" is back to being just a plain old blog, where I write about whatever suits me, and visitors are welcome, but not the focus.&lt;br /&gt;&lt;br /&gt;Before turning off analytics, my most popular pages were:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_YH1HTjXGzNU/TTl_AKvvFJI/AAAAAAAADLU/Vq_YI7bMt68/s1600/visitors2.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="170" src="http://1.bp.blogspot.com/_YH1HTjXGzNU/TTl_AKvvFJI/AAAAAAAADLU/Vq_YI7bMt68/s320/visitors2.PNG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;"Quest for Interesting" is a whimsical post that became popular only because it contains an image I created in MS Paint in about 10 minutes, which shows how to cross-multiply to compare fractions. For whatever reason, that image was for a few months the number one hit on Google Images for "cross multiplication". It currently fluctuates between 2nd and 3rd place, and still drives traffic here.&lt;br /&gt;&lt;br /&gt;"Solving the Facebook Gattaca Puzzle" is one of my solutions to a Facebook puzzle on their "careers" page. They use interesting puzzles involving optimization and datasets as a filtering tool for potential coders, which I think is a good idea. The number of people attempting to use search engines to game the system is phenomenal. To illustrate, here are the top 5 search terms used to find any page on my site:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_YH1HTjXGzNU/TTl_FYPQexI/AAAAAAAADLY/J0Du-w1YZM8/s1600/visitors3.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="137" src="http://3.bp.blogspot.com/_YH1HTjXGzNU/TTl_FYPQexI/AAAAAAAADLY/J0Du-w1YZM8/s320/visitors3.PNG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;"Oldschool Mainframe/COBOL geek-out" is me going on at length about mainframe topics like RPF scripts in ROSCOE, compiling and linking from JCL, why EBCDIC is even a thing, and how no one "plays" on mainframes.&lt;br /&gt;&lt;br /&gt;The last, "Creating an Archimedean Spiral generator in Java using the NetBeans IDE" is one of several quick hacks of mine, this one attempting to be a basic introduction to using NetBeans, the basics of painting and the Java2D library, and polar math vs. Euclidean. Because it's fun. And I'm a geek who despairs not taking Calculus in high school, and not paying more attention in the math classes I did take.&lt;br /&gt;&lt;br /&gt;So, I have dismissed my Joab from his census-taking duties, before being punished by the almighty for my pride. Now it's back to just writing about stuff, without the marketing angle.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11885757-2797651215583651036?l=cautery.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cautery.blogspot.com/feeds/2797651215583651036/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://cautery.blogspot.com/2011/01/4046.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/2797651215583651036'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/2797651215583651036'/><link rel='alternate' type='text/html' href='http://cautery.blogspot.com/2011/01/4046.html' title='4,046'/><author><name>Curtis Autery</name><uri>https://profiles.google.com/107677530285177731535</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/--J3C_khtLqQ/AAAAAAAAAAI/AAAAAAAADT4/e2Qa5ncfAMk/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_YH1HTjXGzNU/TTl-5R4r7sI/AAAAAAAADLQ/NhnaHCiTA1s/s72-c/visitors1.PNG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11885757.post-1654675462909664176</id><published>2011-01-16T10:16:00.003-05:00</published><updated>2011-01-16T10:23:24.657-05:00</updated><title type='text'>OSU Math Placement B-test, 1 of ???</title><content type='html'>A little experiment with Google Docs, Wikipedia's TeX engine for rendering math equations, and trying to help my wife pass her college math requirements.&lt;br /&gt;&lt;br /&gt;Where's that Check 21 2 of 2 I promised for yesterday? Still coming, I just need to get my inspiration back after a few, um, let's call them "challenging" weeks at my day job. Anyway, enjoy!&lt;br /&gt;&lt;br /&gt;&lt;a href="https://docs.google.com/document/d/1vnKHq4XlMU8lcXECH2QpqlEK8CUYZ09Nb0lUV0yp1_U/edit?hl=en"&gt;B Test study guide, question 1a&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11885757-1654675462909664176?l=cautery.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cautery.blogspot.com/feeds/1654675462909664176/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://cautery.blogspot.com/2011/01/osu-math-placement-b-test-1-of.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/1654675462909664176'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/1654675462909664176'/><link rel='alternate' type='text/html' href='http://cautery.blogspot.com/2011/01/osu-math-placement-b-test-1-of.html' title='OSU Math Placement B-test, 1 of ???'/><author><name>Curtis Autery</name><uri>https://profiles.google.com/107677530285177731535</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/--J3C_khtLqQ/AAAAAAAAAAI/AAAAAAAADT4/e2Qa5ncfAMk/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11885757.post-5526076001566885243</id><published>2011-01-09T18:21:00.001-05:00</published><updated>2011-01-09T18:21:37.418-05:00</updated><title type='text'>Adventures in Barretting</title><content type='html'>In an attempt to be funny, I made up the term “Barretting” to describe the act of driving to Tennessee to see my friend Chris Barrett.  My wife, Liberty, and I had some fun throughout the week using the term whenever it would fit.  “Well, we don’t need to stop at the store on Friday, we can get to that when we’re back from Barretting.”&lt;br /&gt;&lt;br /&gt;Chris introduced us to the “Flying Saucer” pub last year, which has a giant wall full of taps (possibly 20 or 30), as well as friendly wait-staff, not too intolerable prices, and a 100-beer tour that gets you some sort of free party there and your name on a plate if you finish it.  Liberty and I went once with Chris to the Memphis location, and have been twice to the one in Nashville while taking an impromptu “let’s see where this road takes us” vacation.&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;Chris used to live in Columbus like we do, but now works in western North Carolina.  Nashville is a good midpoint between us, so we planned to meet up this weekend and catch up for a few hours, and go our separate ways.  We did so, adding beers 10 through 12 to our tours (16 to 18 for Chris) and a good time was had by all.  But something happened on the way down that trumps that story.&lt;br /&gt;&lt;br /&gt;On Saturday morning we started our drive down, and by mid-afternoon, with the sun starting to dip low in preparation for nightfall, we found ourselves on I-65, a little South of Louisville Kentucky.  There was this idyllic moment as we drove down a stretch of road with rock structures on either side.  There were a couple clouds visible, contrasting the darkening blue sky, a flock of birds crossed the road in front of us, first horizontal, then swirling to a vertical diamond-shape as the crossed the opposite rock facing.  Liberty was sitting beside me, engrossed in knitting a new creation, and a local radio station was playing the Zeppelin song “In My Time of Dying”.&lt;br /&gt;&lt;br /&gt;And there it was.  Our life and responsibilities back home - to kids, house, school, and job - was a fiction that neither of us believed in.  The truth was the road, the song, the shawl, the birds, and the setting sun.  And the real truth: each other.&lt;br /&gt;&lt;br /&gt;I felt a sense of overwhelming bliss just driving around with the woman I love.  No matter what happened after we decided our fiction back home was real again, Liberty would be with me still, and hence, the world would be less bleak.&lt;br /&gt;&lt;br /&gt;In 71 days we will have been married for three years.  When we look at each other, we both know we found the right person.  The house may collapse, my job may give me the boot, the mounting school debt may be a beast difficult to slay, but that will all be illusion.  The real world will continue to be the birds serenading us before sunset, as we head down the road together.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11885757-5526076001566885243?l=cautery.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cautery.blogspot.com/feeds/5526076001566885243/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://cautery.blogspot.com/2011/01/adventures-in-barretting.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/5526076001566885243'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/5526076001566885243'/><link rel='alternate' type='text/html' href='http://cautery.blogspot.com/2011/01/adventures-in-barretting.html' title='Adventures in Barretting'/><author><name>Curtis Autery</name><uri>https://profiles.google.com/107677530285177731535</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/--J3C_khtLqQ/AAAAAAAAAAI/AAAAAAAADT4/e2Qa5ncfAMk/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11885757.post-2654143109774715052</id><published>2010-12-28T21:21:00.000-05:00</published><updated>2010-12-28T21:21:27.461-05:00</updated><title type='text'>Check 21 Java app - 1 of 2</title><content type='html'>Extracting data and images from Image Cash Letter files  &lt;p class="section"&gt;Background &lt;/p&gt;&lt;p&gt;There are many terms relating to Image Cash Letter files: Check 21, DSTU X9.37, X9.100-187, and check truncation, to name a few. &lt;/p&gt;&lt;p&gt;"Check 21" refers to an act passed in 2003. From Wikipedia's "Check 21 Act" article: &lt;/p&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;blockquote&gt;&lt;p&gt;The Check Clearing for the 21st Century Act (or Check 21 Act) is a United States federal law, Pub.L. 108-100 ... The law allows the recipient of the original paper check to create a digital version of the original check—called a "substitute check," thereby eliminating the need for further handling of the physical document... &lt;/p&gt;&lt;p&gt;...Recently, Check 21 software providers have developed a "Virtual Check 21" system which allows online and offline merchants to create and submit demand draft documents to the bank of deposit. This process which combines remotely created checks (RCC) and Check 21 X9.37 files enables merchants to benefit from direct merchant-to-bank relationships, lower NSFs, and lower chargebacks.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;The last paragraph bears some resemblance to reality, but the article's footnote refers to just one of many companies capitalizing on the Check 21 act, and the lofty goal of direct merchant-to-bank relationships is not met due to the very fact of requiring a middle-man's software to manage the relationship. &lt;/p&gt;&lt;p&gt;The text of the act itself is available at &lt;a href="http://origin.www.gpo.gov/fdsys/pkg/PLAW-108publ100/pdf/PLAW-108publ100.pdf"&gt;this page&lt;/a&gt; on gpo.gov, the opening paragraph being: &lt;/p&gt;&lt;blockquote&gt;To facilitate check truncation by authorizing substitute checks, to foster innovation in the check collection system without mandating receipt of checks in electronic form, and to improve the overall efficiency of the Nation's payments system, and for other purposes.&lt;/blockquote&gt;&lt;p&gt;My interpretation is that the act clearly states that no one is forcing banks to receive checks electronically, but new law is being written allowing banks to use electronic copies (or photocopies, or re-prints) of checks in place of the originals at their discretion. Later text in the act provides for a future study to see how banks are adopting it, whether their profits are affected, whether it's useful, etc. &lt;/p&gt;&lt;p&gt;When the act was passed, ANSI published DSTU X9.37 "for Electronic Exchange of Check and Image Data". "DSTU" stands for "Draft Standard for Trial Use". "X9" is the banking arm of ANSI (where "X12" is the EDI arm). So basically in 2003 a trial standard was published for exchanging check images, with an evaluation of the standard to come later. That came in 2008, when ANSI published X9.100-180 for Canadian use, and X9.100-187 for use in the states, with minor alterations from the original standard. &lt;/p&gt;&lt;p class="section"&gt;Background on the file format&lt;/p&gt;&lt;p&gt;An image cash letter is designed for mainframe use. It is record-based, with a 4-byte word at the beginning of each record indicating its length. It contains mixed text and image data, with the text part being in the EBCDIC character set, and the image part being TIFF data. If you are a small business that happens to have a mainframe laying around, this is good news. For merchants living in the real world, not so much. &lt;/p&gt;&lt;p&gt;The file format poses a number of challenges for Windows, Mac, and Unix programmers. Unless you are versed in the mainframe/AS400 world, variable length records with length bytes and the EBCDIC character set are probably unfamiliar to you. Once you figure out EBCDIC translation, you then need to tackle converting the record-length header to a number, which, unless you are in the habit of programming at a "bits on the wire" level (checksums, for instance), you've probably never needed to do before. &lt;/p&gt;&lt;p&gt;Once you tackle record lengths and EBCDIC and start playing with the image data, you'll quickly realize a simple fact that you never noticed before: nothing supports TIFF images. Your web browser doesn't display them, and your programming language doesn't have support for them in its native image library. You either need to invest more research time into finding a TIFF library and learning its API, or just dump image data to individual files each time you come across it, leaving your end-user with a large collection of files to open by hand. This would lead to the following uncomfortable conversation: &lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;User: "So I'll have a bunch of image files representing checks that I have to click on one at a time to view?" &lt;/p&gt;&lt;p&gt;You: "Right." &lt;/p&gt;&lt;p&gt;User: "And there's no way to correlate those back to the text data?" &lt;/p&gt;&lt;p&gt;You: "Right." &lt;/p&gt;&lt;p&gt;User: "Well, do I at least get the front and back of checks in the same image?" &lt;/p&gt;&lt;p&gt;You: "Um, well... no." &lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Because of these mild but unfamiliar technical hurdles, the third-party app that supports Check21 files looks more attractive to a CTO than watching the internal IT team bumble around trying to build an app. In fact, an industry has popped up around these files, costing companies money in vendor lock-in that they tried to save by converting from ACH files and mailing checks, all in the name of getting money to the bank a little faster. Not a good situation. &lt;/p&gt;&lt;p class="section"&gt;Impetus for this entry&lt;/p&gt;&lt;p&gt;In July of '09, I published a &lt;a href="http://www.perlmonks.org/?node_id=784982"&gt;perl script&lt;/a&gt; that does just what I described above. It takes a Check 21 file and prints its ASCII-translated text to STDOUT, and saves the image data into individual TIFF files. It was intended only as a quick experiment with handling the Check21 file format, but its Google rank grew until it was on the front page for searches like "x9.37 parse". This is odd because the script is a quick hack (in fact the first comment on it complains about its lack of exception handling) that I threw together in about 30 minutes, so it's possible that there aren't many "open" apps available that handle this file type. &lt;/p&gt;&lt;p&gt;Recently someone asked me for help with a problem using the extractor. Between my script's unexpected high search rank, and the fact that questions about my tech posts are pretty rare, one can reasonably assume that Check21 files are currently a big deal in "the wild", and knowledge about them is pretty slim. Assuming that to be the case, this post is the first in a two-part Check21 java series exploring the file format, and concerns with parsing, displaying, and creating Check21 files. This first post shows how to write an extractor similar to my perl script, but in Java. &lt;/p&gt;&lt;p class="section"&gt;Bits on the wire&lt;/p&gt;&lt;p&gt;Let's start by opening a file in a hex editor to see what it looks like. The file I'm using is available on &lt;a href="http://www.x937.com/SampleX937File.htm"&gt;this page&lt;/a&gt; on x937.com, a private site run by software developer Norman Graham. &lt;/p&gt;&lt;p&gt;&lt;img src="http://lh6.ggpht.com/_YH1HTjXGzNU/TQ4jAJnvgDI/AAAAAAAADKQ/ebvq2ttara4/s800/chk21HexDump.PNG"&gt;&lt;/p&gt;&lt;p&gt;To the untrained eye, this looks like so much garbage. To those more mainframe-savvy, the top section peppered with at-signs and letters with diacritics means you're probably looking at EBCDIC rendered with an ASCII viewer. To the image geeks, the II* on line 210h is indicative of the beginning of TIFF data. &lt;/p&gt;&lt;p&gt;The first four bytes combine as one hex number: 0x00000050, or decimal 80, meaning the next 80 bytes constitute a record. The next few bytes (F0, F1, F0, F3) are EBCDIC representations of numeric digits, as EBCDIC places 0 through 9 in hex F0 through hex F9 (where ASCII has them at hex 30 through 39), so the first four characters of the record should be "0103". &lt;/p&gt;&lt;p class="section"&gt;Tracing through the JRE&lt;/p&gt;&lt;p&gt;With those basic assumptions, let's throw some code at it and see what we get. The record length header can be turned into a number with very little effort. The Java class javax.imageio.stream.ImageInputStreamImpl provides the following method: &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;public int readInt() throws IOException {&lt;br /&gt;    if (read(byteBuf, 0, 4) &amp;lt; 0) {&lt;br /&gt;    throw new EOFException();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if (byteOrder == ByteOrder.BIG_ENDIAN) {&lt;br /&gt;        return&lt;br /&gt;            (((byteBuf[0] &amp;amp; 0xff) &amp;lt;&amp;lt; 24) | ((byteBuf[1] &amp;amp; 0xff) &amp;lt;&amp;lt; 16) |&lt;br /&gt;             ((byteBuf[2] &amp;amp; 0xff) &amp;lt;&amp;lt;  8) | ((byteBuf[3] &amp;amp; 0xff) &amp;lt;&amp;lt;  0));&lt;br /&gt;    } else {&lt;br /&gt;        return&lt;br /&gt;            (((byteBuf[3] &amp;amp; 0xff) &amp;lt;&amp;lt; 24) | ((byteBuf[2] &amp;amp; 0xff) &amp;lt;&amp;lt; 16) |&lt;br /&gt;             ((byteBuf[1] &amp;amp; 0xff) &amp;lt;&amp;lt;  8) | ((byteBuf[0] &amp;amp; 0xff) &amp;lt;&amp;lt;  0));&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;The variable "byteBuf" is a byte array. Four bytes are read into it, and using bitwise math, a single 32-bit integer is returned. This is a less processor heavy version of looping through the byte array, multiplying by 256, and adding the next byte. &lt;/p&gt;&lt;p&gt;So if I open the file as an ImageInputStream, I can use readInt() to grab record lengths and move forward in the file. Next, the EBCDIC to ASCII translation. The java.lang.String class has a constructor that accepts a string input declaring the character set: &lt;/p&gt;&lt;p&gt;public String(byte bytes[], String charsetName) &lt;/p&gt;&lt;p&gt;This is ultimately a convenience method for java.lang.StringCoding.decode(), which looks up a CharSet class and returns a new String by converting each byte using a translation table. For EBCDIC translation, specify "Cp1047" as the character set name, and Java will find the class sun.nio.cs.ext.IBM1047, which contains this table: &lt;/p&gt;&lt;pre&gt;&lt;br /&gt; private final static String byteToCharTable =&lt;br /&gt; &lt;br /&gt;     "\u00D8\u0061\u0062\u0063\u0064\u0065\u0066\u0067" +     // 0x80 - 0x87&lt;br /&gt;     "\u0068\u0069\u00AB\u00BB\u00F0\u00FD\u00FE\u00B1" +     // 0x88 - 0x8F&lt;br /&gt;     "\u00B0\u006A\u006B\u006C\u006D\u006E\u006F\u0070" +     // 0x90 - 0x97&lt;br /&gt;     "\u0071\u0072\u00AA\u00BA\u00E6\u00B8\u00C6\u00A4" +     // 0x98 - 0x9F&lt;br /&gt;     "\u00B5\u007E\u0073\u0074\u0075\u0076\u0077\u0078" +     // 0xA0 - 0xA7&lt;br /&gt;     "\u0079\u007A\u00A1\u00BF\u00D0\u005B\u00DE\u00AE" +     // 0xA8 - 0xAF&lt;br /&gt;     "\u00AC\u00A3\u00A5\u00B7\u00A9\u00A7\u00B6\u00BC" +     // 0xB0 - 0xB7&lt;br /&gt;     "\u00BD\u00BE\u00DD\u00A8\u00AF\u005D\u00B4\u00D7" +     // 0xB8 - 0xBF&lt;br /&gt;     "\u007B\u0041\u0042\u0043\u0044\u0045\u0046\u0047" +     // 0xC0 - 0xC7&lt;br /&gt;     "\u0048\u0049\u00AD\u00F4\u00F6\u00F2\u00F3\u00F5" +     // 0xC8 - 0xCF&lt;br /&gt;     "\u007D\u004A\u004B\u004C\u004D\u004E\u004F\u0050" +     // 0xD0 - 0xD7&lt;br /&gt;     "\u0051\u0052\u00B9\u00FB\u00FC\u00F9\u00FA\u00FF" +     // 0xD8 - 0xDF&lt;br /&gt;     "\\\u00F7\u0053\u0054\u0055\u0056\u0057\u0058" +     // 0xE0 - 0xE7&lt;br /&gt;     "\u0059\u005A\u00B2\u00D4\u00D6\u00D2\u00D3\u00D5" +     // 0xE8 - 0xEF&lt;br /&gt;     "\u0030\u0031\u0032\u0033\u0034\u0035\u0036\u0037" +     // 0xF0 - 0xF7&lt;br /&gt;     "\u0038\u0039\u00B3\u00DB\u00DC\u00D9\u00DA\u009F" +     // 0xF8 - 0xFF&lt;br /&gt;     "\u0000\u0001\u0002\u0003\u009C\t\u0086\u007F" +     // 0x00 - 0x07&lt;br /&gt;     "\u0097\u008D\u008E\u000B\f\r\u000E\u000F" +     // 0x08 - 0x0F&lt;br /&gt;     "\u0010\u0011\u0012\u0013\u009D\n\b\u0087" +     // 0x10 - 0x17&lt;br /&gt;     "\u0018\u0019\u0092\u008F\u001C\u001D\u001E\u001F" +     // 0x18 - 0x1F&lt;br /&gt;     "\u0080\u0081\u0082\u0083\u0084\u0085\u0017\u001B" +     // 0x20 - 0x27&lt;br /&gt;     "\u0088\u0089\u008A\u008B\u008C\u0005\u0006\u0007" +     // 0x28 - 0x2F&lt;br /&gt;     "\u0090\u0091\u0016\u0093\u0094\u0095\u0096\u0004" +     // 0x30 - 0x37&lt;br /&gt;     "\u0098\u0099\u009A\u009B\u0014\u0015\u009E\u001A" +     // 0x38 - 0x3F&lt;br /&gt;     "\u0020\u00A0\u00E2\u00E4\u00E0\u00E1\u00E3\u00E5" +     // 0x40 - 0x47&lt;br /&gt;     "\u00E7\u00F1\u00A2\u002E\u003C\u0028\u002B\u007C" +     // 0x48 - 0x4F&lt;br /&gt;     "\u0026\u00E9\u00EA\u00EB\u00E8\u00ED\u00EE\u00EF" +     // 0x50 - 0x57&lt;br /&gt;     "\u00EC\u00DF\u0021\u0024\u002A\u0029\u003B\u005E" +     // 0x58 - 0x5F&lt;br /&gt;     "\u002D\u002F\u00C2\u00C4\u00C0\u00C1\u00C3\u00C5" +     // 0x60 - 0x67&lt;br /&gt;     "\u00C7\u00D1\u00A6\u002C\u0025\u005F\u003E\u003F" +     // 0x68 - 0x6F&lt;br /&gt;     "\u00F8\u00C9\u00CA\u00CB\u00C8\u00CD\u00CE\u00CF" +     // 0x70 - 0x77&lt;br /&gt;     "\u00CC\u0060\u003A\u0023\u0040\'\u003D\"";     // 0x78 - 0x7F&lt;br /&gt; &lt;/pre&gt;&lt;p class="section"&gt;Client code&lt;/p&gt;&lt;p&gt;Here is a quick test class to open the file as an ImageInputStream, and attempt to find the first record's length, read that many bytes, and translate to ASCII. &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;package com.cea.check21;&lt;br /&gt;&lt;br /&gt;import java.io.File;&lt;br /&gt;import java.io.IOException;&lt;br /&gt;import javax.imageio.stream.FileImageInputStream;&lt;br /&gt;&lt;br /&gt;public class Test {&lt;br /&gt;  public static void main(String[] args) throws IOException {&lt;br /&gt;    FileImageInputStream is = new FileImageInputStream(new File("one.x9"));&lt;br /&gt;    int recLen = is.readInt();&lt;br /&gt;    System.out.println("Record length: " + recLen);&lt;br /&gt;    byte[] rec = new byte[recLen];&lt;br /&gt;    is.read(rec);&lt;br /&gt;    System.out.println(new String(rec, "Cp1047"));&lt;br /&gt;    is.close();&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;After running that, the following output is displayed: &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;Record length: 80&lt;br /&gt;0103T113000609111012822200408052030NUS BANKO NORM     First Bank of NormAUS     &lt;br /&gt;&lt;/pre&gt;&lt;p&gt;This looks good. 80 matches the record length we calculated from the hex dump, and the first four characters are "0103" as we expected. The rest of the line looks like numbers and semi-readable text, so we're definitely on the right track. &lt;/p&gt;&lt;p&gt;Now let's flesh out the class a little by iterating over each record and see what happens. The new class: &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;package com.cea.check21;&lt;br /&gt;&lt;br /&gt;import java.io.File;&lt;br /&gt;import java.io.IOException;&lt;br /&gt;import javax.imageio.stream.FileImageInputStream;&lt;br /&gt;&lt;br /&gt;public class Test {&lt;br /&gt;  public static void main(String[] args) throws IOException {&lt;br /&gt;    FileImageInputStream is = new FileImageInputStream(new File("one.x9"));&lt;br /&gt;    int recLen;&lt;br /&gt;    while ((recLen = is.readInt()) &amp;gt; 0) {&lt;br /&gt;      System.out.println("Record length: " + recLen);&lt;br /&gt;      byte[] rec = new byte[recLen];&lt;br /&gt;      is.read(rec);&lt;br /&gt;      System.out.println(new String(rec, "Cp1047"));&lt;br /&gt;    }&lt;br /&gt;    is.close();&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;The output: &lt;/p&gt;&lt;p&gt;&lt;img src="http://lh6.ggpht.com/_YH1HTjXGzNU/TRoN1oNduyI/AAAAAAAADKs/h-2u2EAkg2E/s800/chk21RawTranslate.PNG"/&gt;&lt;/p&gt;&lt;p&gt;...and finally: &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;Exception in thread "main" java.io.EOFException&lt;br /&gt; at javax.imageio.stream.ImageInputStreamImpl.readInt(ImageInputStreamImpl.java:237)&lt;br /&gt; at com.cea.check21.Test.main(Test.java:11)&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;OK, so a closer inspection of the API would have shown that readInt() throws an exception when it reads past the end of the file, but other than that, we're good up to the point where the image data is encountered. The image data occurs where the spec says it will: on the 52 record, at column 118. &lt;/p&gt;&lt;p&gt;So to finish up text conversion, we need to do two things. First, handle EOF more gracefully, and second, print only the first 117 characters of 52 records. &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;package com.cea.check21;&lt;br /&gt;&lt;br /&gt;import java.io.File;&lt;br /&gt;import java.io.IOException;&lt;br /&gt;import javax.imageio.stream.FileImageInputStream;&lt;br /&gt;&lt;br /&gt;public class Test {&lt;br /&gt;  public static void main(String[] args) throws IOException {&lt;br /&gt;    File file = new File("one.x9");&lt;br /&gt;    FileImageInputStream is = new FileImageInputStream(file);&lt;br /&gt;    &lt;br /&gt;    while (is.getStreamPosition() &amp;lt; file.length()) {&lt;br /&gt;      int recLen = is.readInt();&lt;br /&gt;      byte[] rec = new byte[recLen];&lt;br /&gt;      is.read(rec);&lt;br /&gt;      String recNum = new String(rec, 0, 2, "Cp1047");&lt;br /&gt;      if (recNum.equals("52")) System.out.println(new String(rec, 0, 117, "Cp1047"));&lt;br /&gt;      else System.out.println(new String(rec, "Cp1047"));&lt;br /&gt;    }&lt;br /&gt;    is.close();&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Which outputs: &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;0103T113000609111012822200408052030NUS BANKO NORM     First Bank of NormAUS     &lt;br /&gt;100111300060911101282220060109200601092030FG16410001nfg MANAGEMENTxxxxxxxxxxC0  &lt;br /&gt;200109100002211101282220070315200703150020300001000104053000196                 &lt;br /&gt;25           1104 113000609    123456789012345/00000004320999987267040  G01Y000 &lt;br /&gt;50111101282220060109000002206260000                     0                       &lt;br /&gt;5211101282220060109040991400001                                                 &lt;br /&gt;    0                0000000000018628&lt;br /&gt;50111101282220060109000002206261000                     0                       &lt;br /&gt;5211101282220060109040991400001                                                 &lt;br /&gt;    0                0000000000023720&lt;br /&gt;70000100000000043200000000043200001                                             &lt;br /&gt;900000010000000100000000000432000000001 l NORMPOINTE BANK20060109               &lt;br /&gt;9900000100000001000000010000000000000432NORMAN AGEMENT2145085900                &lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Success! &lt;/p&gt;&lt;p&gt;The last step for a simple extractor is to dump TIFF data into files. We'll iterate a counter for each 52 record, and name the files img(count).tiff. Additionally, I've added some handling for specifying file names on the commandline, and finding their working directories. Lastly the class name has been changed to something more descriptive than "Test". &lt;/p&gt;&lt;p&gt;The final code: &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;package com.cea.check21;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;import java.io.File;&lt;br /&gt;import java.io.IOException;&lt;br /&gt;&lt;br /&gt;import javax.imageio.stream.FileImageInputStream;&lt;br /&gt;import javax.imageio.stream.FileImageOutputStream;&lt;br /&gt;&lt;br /&gt;public class Extractor {&lt;br /&gt;  public static void main(String[] args) throws IOException {&lt;br /&gt;    &lt;br /&gt;    if (args.length &amp;lt; 1) {&lt;br /&gt;      System.out.println("Usage: java Extractor &amp;lt;checkImageFile&amp;gt;");&lt;br /&gt;      System.exit(0);&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    File file = new File(args[0]);&lt;br /&gt;    FileImageInputStream is = new FileImageInputStream(file);&lt;br /&gt;    int tiffCount = 0;&lt;br /&gt;    String workDir = file.getParent();&lt;br /&gt;    if (workDir == null) workDir = ".";&lt;br /&gt;    String sep = File.separator;&lt;br /&gt;    &lt;br /&gt;    while(is.getStreamPosition() &amp;lt; file.length()) {&lt;br /&gt;      int recLen = is.readInt();&lt;br /&gt;      byte[] rec = new byte[recLen];&lt;br /&gt;      is.read(rec);&lt;br /&gt;      String recNum = new String(rec, 0, 2, "Cp1047");&lt;br /&gt;      if (recNum.equals("52")) {&lt;br /&gt;        System.out.println(new String(rec, 0, 117, "Cp1047"));&lt;br /&gt;        tiffCount++;&lt;br /&gt;        String numberPart = String.valueOf(tiffCount);&lt;br /&gt;        while (numberPart.length() &amp;lt; 4) numberPart = "0" + numberPart;&lt;br /&gt;        String fileName = workDir + sep + "img" + numberPart + ".tiff";&lt;br /&gt;        FileImageOutputStream out = new FileImageOutputStream(new File(fileName));&lt;br /&gt;        out.write(rec, 117, rec.length - 117);&lt;br /&gt;        out.close();&lt;br /&gt;      } else System.out.println(new String(rec, "Cp1047"));&lt;br /&gt;    }&lt;br /&gt;    is.close();&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;The text output is the same, and two image files are created in the directory containing one.x9: &lt;/p&gt;&lt;p&gt;&lt;img src="http://lh4.ggpht.com/_YH1HTjXGzNU/TRoa22tGPoI/AAAAAAAADK0/RzeKdnL83M0/s800/check21DirList.PNG"/&gt;&lt;/p&gt;&lt;p&gt;And they look like this: &lt;/p&gt;&lt;p&gt;&lt;img src="http://lh6.ggpht.com/_YH1HTjXGzNU/TQ4eukHF7KI/AAAAAAAADKE/_BUkalQKXy0/s640/chk21TestFront.PNG"/&gt;&lt;br/&gt;&lt;img src="http://lh6.ggpht.com/_YH1HTjXGzNU/TQ4eu28ELjI/AAAAAAAADKI/hQAhs8jAk8I/s640/chk21TestBack.PNG"/&gt; &lt;p class="section"&gt;Next steps&lt;/p&gt;&lt;p&gt;This Java class is useful only so far as exploring the Check 21 file format, but provides very little real-world utility. What's needed is an app that can display check information more intelligently, including breaking down the record information into something meaningful, and displaying the front and back of a check alongside that information. &lt;/p&gt;&lt;p&gt;To do that, we'll need to figure out how to turn TIFF data into a Java Image object, and to explore the X9.100-187 record layouts in a little more detail. &lt;/p&gt;&lt;p&gt;I'm giving myself an arbitrary deadline of January 15, 2011 to post my progress with that app. Tune in then! &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11885757-2654143109774715052?l=cautery.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cautery.blogspot.com/feeds/2654143109774715052/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://cautery.blogspot.com/2010/12/check-21-java-app-1-of-2.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/2654143109774715052'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/2654143109774715052'/><link rel='alternate' type='text/html' href='http://cautery.blogspot.com/2010/12/check-21-java-app-1-of-2.html' title='Check 21 Java app - 1 of 2'/><author><name>Curtis Autery</name><uri>https://profiles.google.com/107677530285177731535</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/--J3C_khtLqQ/AAAAAAAAAAI/AAAAAAAADT4/e2Qa5ncfAMk/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_YH1HTjXGzNU/TQ4jAJnvgDI/AAAAAAAADKQ/ebvq2ttara4/s72-c/chk21HexDump.PNG' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11885757.post-6951546880157654499</id><published>2010-12-16T18:29:00.005-05:00</published><updated>2010-12-16T22:30:40.558-05:00</updated><title type='text'>Java greyscale conversion</title><content type='html'>&lt;p&gt;Using Java, how do you convert a color image to greyscale? The most straightforward answer I've found was on &lt;a href="http://blog.codebeach.com/2008/03/convert-color-image-to-gray-scale-image.html"&gt;Code Beach&lt;/a&gt;, and is as follows: &lt;/p&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;pre&gt;&lt;br /&gt;BufferedImage image = new BufferedImage(width, height,  &lt;br /&gt;    BufferedImage.TYPE_BYTE_GRAY);  &lt;br /&gt;Graphics g = image.getGraphics();  &lt;br /&gt;g.drawImage(colorImage, 0, 0, null);  &lt;br /&gt;g.dispose();&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Create a BufferedImage of type TYPE_BYTE_GRAY, and grab its Graphics object. Draw the color image onto it. Fin. &lt;/p&gt;&lt;p&gt;The described method uses a small amount of client code for a fast, good quality greyscale conversion, but a lot goes on under the hood to make this happen in the Java runtime jar. Tracing through the code, eventually you arrive at the getDataElements method of java.awt.image.IndexColorModel, and the following line is executed over every pixel in the image: &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;int gray = (int) (red*77 + green*150 + blue*29 + 128)/256;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;This takes the red, green, and blue components of a pixel's composite color, and calculates its relative brightness (on a scale here that is, oddly, between 0.5 and 1.5), and later uses this value to mix a grey color of the same brightness for the replacement pixel. &lt;/p&gt;&lt;p class=section&gt;A quick (and admittedly non-expert) course on color theory as it relates to computers: &lt;/p&gt;&lt;p&gt;Your computer screen does not have pixels that can change color. For every perceived pixel, there are three "lights" (for simplicity's sake) very close together that are the primary colors red, green, and blue. When all three lights are off, you see black. When they are all turned on at full brightness, you see white. Mixing the lights at different power levels produces very close to the full range of colors that our eyes can perceive. &lt;/p&gt;&lt;p&gt;The lights have 256 power levels, for a total color space of 16,777,216 colors (256 cubed). Black is seen when red, green, and blue are all 0; white when they are all 255. There are also 254 shades of grey, seen when the red, green, and blue values all match and are between 1 and 254. This brings us back to the brightness equation above: find a color's brightness, scale it between 0 and 255, and you can make a grey with the same brightness by setting the red, green, and blue of the pixel to that value. Repeat for all the pixels in an image and you have a greyscale copy of it. &lt;/p&gt;&lt;p class=section&gt;Whence the 77/150/29 ratio? &lt;/p&gt;&lt;p&gt;In 1982, when I was 11 years old and a holy terror on my 6th grade teachers, the International Telecommunication Union published Recommendation 601 for transmitting video signals digitally. In it the following luminance (brightness) equation is mentioned in section 2.1: &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;E'&lt;sub&gt;Y&lt;/sub&gt; = 0.299 E'&lt;sub&gt;R&lt;/sub&gt; + 0.587 E'&lt;sub&gt;G&lt;/sub&gt; + 0.114 E'&lt;sub&gt;B&lt;/sub&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;These numbers add up to 1, where 77, 150, and 29 add up to 256. Dividing each of those by 256 gives a close approximation to the Rec 601 ratios, with the added benefit of using only integers and dividing by a power of 2, which computer processors are very good at. These specific ratios of red, green, and blue to determine luminance can be traced back to the XYZ color space, created by the International Commission on Illumination (CIE) in 1931, which in turn references work by James Clerk Maxwell (Experiments on colour, as perceived by the eye, with remarks on colour-blindness [1855]) which itself references work done by none other than Isaac Newton in the book Opticks (1704) which talks about breaking light into its component parts using prisms, discussing compound vs. homogeneal light, building lenses and telescopes, etc. &lt;/p&gt;&lt;p&gt;I won't attempt a full analysis of all these works to trace the source of the numbers, but suffice to say in the 19th century, people stared at colored lights and twisted knobs to match colors, and scientists wrote down the final settings. After some math and repeated experiments, it was determined that green light looks pretty damned bright to us, red a little less, and blue less than that. &lt;/p&gt;&lt;p class=section&gt;Are there better ratios to create a crisper greyscale image? &lt;/p&gt;&lt;p&gt;In 1993, the ITU published Rec 709, a standard for modern HDTV systems. In section 4.2, the recommended luminance formula for the 1250/50/2:1 scanning standard used the old Rec 601 values. For 1125/60/2:1 (1080i) scanning, new values are recommended: &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;E'&lt;sub&gt;Y&lt;/sub&gt; = 0.2126 E'&lt;sub&gt;R&lt;/sub&gt; + 0.7152 E'&lt;sub&gt;G&lt;/sub&gt; + 0.0722 E'&lt;sub&gt;B&lt;/sub&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;That section's footnote says "The coefficients for the equations have been calculated following the rules laid down in SMPTE RP177-1993." This refers to a 1993 publication called "Derivation of Basic Television Color Equations" by the Society of Motion Picture and Television Engineers. &lt;/p&gt;&lt;p&gt;...and for the low cost of $50, I can buy the paper and see what their math was. From what I gather from other sources, the new calculations change when Gamma levels are applied, with the result being values better lined up with the 1931 XYZ color space. Finding out more isn't worth $50 to me. Some hoodoo is done with the gamma to produce a better luminance value - I'll take their word for it. &lt;/p&gt;&lt;p class=section&gt;Can I use the new values to greyscale an image in Java. &lt;/p&gt;&lt;p&gt;Yes. Instead of using Graphics.drawImage and letting Java figure out what to do with the pixels, you have to get your hands a little dirtier and work with PixelGrabbers, bitwise operators and integer arrays. But it turns out to not be that difficult. &lt;/p&gt;&lt;p&gt;Colors are defined in Java as 32-bit integers in four octets: alpha(opacity), red, green, and blue. For example, 0xff007f00 would be an opaque hunter-green, with the alpha set to ff(255) and the green set to 7f(127), with red and blue at 0. To take this integer value and pull out only the green part, you can either create a Color object and call its getGreen() method, or not waste the construction overhead and just do the math: right-shift 8 bits, then bitwise "and" the value to 0xff to zero out all but the last octet, with a statement like this: &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;int g = (color &amp;gt;&amp;gt;  8) &amp;amp; 0xff;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Getting the red value is similar, just bitshift 16 places instead 8, and with blue no bitshift is needed, just the bitwise "and". &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;int r = (color &amp;gt;&amp;gt; 16) &amp;amp; 0xff;&lt;br /&gt;int g = (color &amp;gt;&amp;gt;  8) &amp;amp; 0xff;&lt;br /&gt;int b = (color      ) &amp;amp; 0xff;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;These values can then be used to construct a luminance value by plugging them into the Rec 709 numbers: &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;int lum = (int) ((double)r * 0.2126 + (double)g * 0.7152 + (double)b * 0.0722);&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;And finally a grey can be constructed by creating an integer whose red, green, and blue values all match the luminance number. This can be done with little overhead by left-shifting and using the bitwise "or" function: &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;int greyColor = (lum &amp;lt;&amp;lt; 16) | (lum &amp;lt;&amp;lt; 8) | lum;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;The sample code below is a method that can be called specifying which luminance standard to use. A PixelGrabber grabs all the RGB values and sticks them into an integer array. Then the array is iterated over, converting all the colors to matching greys, and finally updating a BufferedImage with the new pixels: &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;private Image greyScale(int mode, Image sourceImage) {&lt;br /&gt;  double redLum, greenLum, blueLum;&lt;br /&gt;  switch(mode) {&lt;br /&gt;  case 601:&lt;br /&gt;    redLum   = 0.299;&lt;br /&gt;    greenLum = 0.587;&lt;br /&gt;    blueLum  = 0.114;&lt;br /&gt;    break;&lt;br /&gt;  case 709:&lt;br /&gt;    redLum   = 0.2126;&lt;br /&gt;    greenLum = 0.7152;&lt;br /&gt;    blueLum  = 0.0722;&lt;br /&gt;    break;&lt;br /&gt;  default: return null;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  int w = sourceImage.getWidth(null);&lt;br /&gt;  int h = sourceImage.getHeight(null);&lt;br /&gt;  int[] pixels = new int[w * h];&lt;br /&gt;  &lt;br /&gt;  PixelGrabber pg = new PixelGrabber(sourceImage, 0, 0, w, h, pixels, 0, w);&lt;br /&gt;  try {&lt;br /&gt;    pg.grabPixels();&lt;br /&gt;  } catch (InterruptedException e) {&lt;br /&gt;    e.printStackTrace();&lt;br /&gt;    return null;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  BufferedImage greyImage = new BufferedImage(w, h, BufferedImage.TYPE_3BYTE_BGR);&lt;br /&gt;&lt;br /&gt;  int offset = 0;&lt;br /&gt;  for(int y = 0; y &amp;lt; h; y++) {&lt;br /&gt;    for (int x = 0; x &amp;lt; w; x++) {&lt;br /&gt;      int color = pixels[offset++];&lt;br /&gt;      int r = (color &amp;gt;&amp;gt; 16) &amp;amp; 0xff;&lt;br /&gt;      int g = (color &amp;gt;&amp;gt;  8) &amp;amp; 0xff;&lt;br /&gt;      int b = (color      ) &amp;amp; 0xff;&lt;br /&gt;      int lum = (int) ((double)r * redLum + (double)g * greenLum + (double)b * blueLum);&lt;br /&gt;      int greyColor = (lum &amp;lt;&amp;lt; 16) | (lum &amp;lt;&amp;lt; 8) | lum;&lt;br /&gt;      greyImage.setRGB(x, y, greyColor);&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;  return greyImage;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Here are a couple screengrabs from an app using this method to compare the original and greyscaled images. &lt;/p&gt;&lt;p&gt;First using the 601 standard:&lt;br/&gt;&lt;img src="http://lh3.ggpht.com/_YH1HTjXGzNU/TQpoCrWuiUI/AAAAAAAADJs/n12ue6OBzWo/s800/greyscale_601.PNG"&gt;&lt;/p&gt;&lt;p&gt;Then the 709:&lt;br/&gt;&lt;img src="http://lh3.ggpht.com/_YH1HTjXGzNU/TQpoDDwoKXI/AAAAAAAADJw/XJ3-u7TSy9c/s800/greyscale_709.PNG"&gt;&lt;/p&gt;&lt;p&gt;The difference is subtle, but the print on Scout's dress is a little darker and better defined in the 709 image. And with that anecdotal and completely subjective comparison, I declare the 709 formula the better of the two. On a whim, I shot Oracle an email about the IndexColorModel class using the outdated formula, showing a simple change to use the updated one: &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;int gray = (int) (red*55 + green*183 + blue*18 + 128)/256;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;I doubt that will come to anything, but, you know, it was worth at least mentioning it to them. If I get the added bonus of my line of code in the official rt.jar, so much the better.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11885757-6951546880157654499?l=cautery.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cautery.blogspot.com/feeds/6951546880157654499/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://cautery.blogspot.com/2010/12/java-greyscale-conversion.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/6951546880157654499'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/6951546880157654499'/><link rel='alternate' type='text/html' href='http://cautery.blogspot.com/2010/12/java-greyscale-conversion.html' title='Java greyscale conversion'/><author><name>Curtis Autery</name><uri>https://profiles.google.com/107677530285177731535</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/--J3C_khtLqQ/AAAAAAAAAAI/AAAAAAAADT4/e2Qa5ncfAMk/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_YH1HTjXGzNU/TQpoCrWuiUI/AAAAAAAADJs/n12ue6OBzWo/s72-c/greyscale_601.PNG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11885757.post-5930073477840759254</id><published>2010-11-20T09:04:00.006-05:00</published><updated>2010-11-20T09:13:22.157-05:00</updated><title type='text'>Roman numerals redux</title><content type='html'>&lt;p&gt;A simple JavaScript function to validate Roman numerals, convert them to Arabic numbers, and back again. &lt;/p&gt;&lt;p&gt;I checked Google Analytics this morning and noticed I've been getting a lot of hits on my &lt;a href="http://cautery.blogspot.com/2010/10/javascript-roman-numeral-calculator.html"&gt;October 9 entry&lt;/a&gt; on JavaScript Roman numeral conversion. In brief, I wrote a simple function to take a number and build its Roman numeral equivalent. While I was mulling it over this morning, I spontaneously thought of a method to validate and parse a Roman numeral and turn it back into Arabic numbers using regular expressions. &lt;/p&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;blockquote&gt;&lt;form action=# onSubmit="this.flip.value=translate(this.flip.value, this.strict.checked); return false"&gt;&lt;b&gt;Input a Roman numeral or an integer between 1 and 3999:&lt;/b&gt;&lt;br/&gt;&lt;input type=text name=flip /&gt;&lt;input type=submit value=Translate /&gt;&lt;input type=checkbox name=strict&gt; Strict &lt;/form&gt;&lt;/blockquote&gt;&lt;p class=section&gt;Step 1: Validating&lt;/p&gt;&lt;script&gt;var isInt  = /^\d+$/; var isRom  = /^[IVXLCDM]+$/i; var valid  = /^M{0,3}(D?C{0,4}|C[MD])(L?X{0,4}|X[CL])(V?I{0,4}|I[XV])$/; var strict = /^M{0,3}(D?C{0,3}|C[MD])(L?X{0,3}|X[CL])(V?I{0,3}|I[XV])$/; var word   = /(M|CM|D|CD|C|XC|L|XL|X|IX|V|IV|I)/g; var value  = {I:1,IV:4,V:5,IX:9,X:10,XL:40,L:50,XC:90,C:100,CD:400,D:500,CM:900,M:1000};   function translate(input, isStrict) {   if (input == null || input == "") {     alert("Please enter a value.");     return input;   }    var output;   if (input.match(isRom)) output = getInt(input.toUpperCase(), isStrict);   else if (input.match(isInt)) output = getRom(input);   else alert(input + " is not a Roman numeral or integer value.");    return output == null ? input : output; }  function getInt(input, isStrict) {   var matcher = isStrict ? strict : valid;   if (input.match(matcher) == null) {     alert(input + " is not a valid Roman numeral.");     return;   }    var s = 0;   var words = input.match(word);   for (var i = 0; i &lt; words.length; i++) {     s += value[words[i]];   }    return s; }  function getRom(input) {   var num = parseInt(input, 10);    if (num &lt; 1 || num &gt; 3999) {     alert("Integer must be between 1 and 3999.");     return;   }    var s = "";   while (num &gt;= 1000) { num -= 1000; s +=  "M"; }   if    (num &gt;=  900) { num -=  900; s += "CM"; }   if    (num &gt;=  500) { num -=  500; s +=  "D"; }   if    (num &gt;=  400) { num -=  400; s += "CD"; }   while (num &gt;=  100) { num -=  100; s +=  "C"; }   if    (num &gt;=   90) { num -=   90; s += "XC"; }   if    (num &gt;=   50) { num -=   50; s +=  "L"; }   if    (num &gt;=   40) { num -=   40; s += "XL"; }   while (num &gt;=   10) { num -=   10; s +=  "X"; }   if    (num &gt;=    9) { num -=    9; s += "IX"; }   if    (num &gt;=    5) { num -=    5; s +=  "V"; }   if    (num &gt;=    4) { num -=    4; s += "IV"; }   while (num &gt;=    1) { num -=    1; s +=  "I"; }   return s; } &lt;/script&gt;&lt;p&gt;What contitutes a "valid" Roman numeral is ambiguous. For example, referring to 4 as IV instead of IIII has more of a spotty history than I imagined. The Wikipedia article on roman numerals has an &lt;a href="http://en.wikipedia.org/wiki/Roman_numerals#IIII_and_IV"&gt;interesting section on this&lt;/a&gt;, discussing the use of IIII on clock faces, and MDCCCC on 20th century buildings instead of MCM, and some instances of using VV to represent 10. I decided not to support VV, and to add a flag that sets whether to reject IIII, XXXX, and CCCC. &lt;/p&gt;&lt;p&gt;Assuming IIII, VIIII, IV, and IX are all valid, here are all the possible ones place Roman numerals: &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;I&lt;br /&gt;II&lt;br /&gt;III&lt;br /&gt;IV or IIII&lt;br /&gt;V&lt;br /&gt;VI&lt;br /&gt;VII&lt;br /&gt;VIII&lt;br /&gt;IX or VIIII&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;These can be divided into two classes: IX and IV, and everything else. If the numeral contains IX or IV, you're done with the ones place. If it doesn't contain either of those, the numeral can have a V or not followed by 0 to 4 I characters (0 to 3 if we're being strict). Expressing that concept in regular expression speak is surprisingly simple, and can be built from three basic rules. I'll describe what each rule means, for those not familiar with regex. &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;I[XV]  - This means 'I' followed by either 'X' or 'V'.&lt;br /&gt;V?     - 0 or 1 V characters&lt;br /&gt;I{0,4} - 0 to 4 I characters&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Now we just need to put the optional V before the optional I's, and specify either-or to the choice types by using the pipe character, making the rule: &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;V?I{0,4}|I[XV]&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Next, the same rule needs to be applied to the tens and hundreds places, and each rule wrapped in parentheses to keep the piped choices from interfering with each other: &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;(D?C{0,4}|C[MD])(L?X{0,4}|X[CL])(V?I{0,4}|I[XV])&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Lastly, the thousands, and binding to the start and end of the string. The beginning of the string is marked with the carat symbol, the end with the dollar sign. There can be 0 to 3 thousands at the beginning of the string, followed by the regex above, followed by the end of the string. This makes the complete regex: &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;^M{0,3}(D?C{0,4}|C[MD])(L?X{0,4}|X[CL])(V?I{0,4}|I[XV])$&lt;br /&gt;&lt;/pre&gt;&lt;p class=section&gt;Step 2: Evaluating &lt;/p&gt;&lt;p&gt;Once we're sure the string is valid, we need to break it down into tokens and add up their values. Fortunately, every letter has a set value, and only the exceptions for subtraction notation (IX, IV, etc.) need to be worried about. Regular Expressions can help us out again, as the piped list of choices uses a first match rule. We just need a list of choices that finds the subtraction notation options before it finds the individual letters: &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;M|CM|D|CD|C|XC|L|XL|X|IX|V|IV|I&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Note that IX and IV are found before just plain 'I'. Next, assign each list option a value, and write a function to iterate over all the matches and add up the values: &lt;/p&gt;&lt;pre&gt;&lt;br /&gt;var word   = /(M|CM|D|CD|C|XC|L|XL|X|IX|V|IV|I)/g;&lt;br /&gt;var value  = {I:1,IV:4,V:5,IX:9,X:10,XL:40,L:50,XC:90,C:100,CD:400,D:500,CM:900,M:1000};&lt;br /&gt;&lt;br /&gt;function getInt(input) {&lt;br /&gt;  var s = 0;&lt;br /&gt;  var words = input.match(word);&lt;br /&gt;  for (var i = 0; i &amp;lt; words.length; i++) {&lt;br /&gt;    s += value[words[i]];&lt;br /&gt;  }&lt;br /&gt;  return s;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p class=section&gt;Putting it all together &lt;/p&gt;&lt;p&gt;Using those basic concepts, and borrowing from my previous code that built a Roman numeral based on an Arabic number, I wrote a smallish function that can take either an Arabic number or Roman numeral, and convert it to the other. &lt;/p&gt;The source code: &lt;pre&gt;&lt;br /&gt;var isInt  = /^\d+$/;&lt;br /&gt;var isRom  = /^[IVXLCDM]+$/i;&lt;br /&gt;var valid  = /^M{0,3}(D?C{0,4}|C[MD])(L?X{0,4}|X[CL])(V?I{0,4}|I[XV])$/;&lt;br /&gt;var strict = /^M{0,3}(D?C{0,3}|C[MD])(L?X{0,3}|X[CL])(V?I{0,3}|I[XV])$/;&lt;br /&gt;var word   = /(M|CM|D|CD|C|XC|L|XL|X|IX|V|IV|I)/g;&lt;br /&gt;var value  = {I:1,IV:4,V:5,IX:9,X:10,XL:40,L:50,XC:90,C:100,CD:400,D:500,CM:900,M:1000};&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;function translate(input, isStrict) {&lt;br /&gt;  if (input == null || input == "") {&lt;br /&gt;    alert("Please enter a value.");&lt;br /&gt;    return input;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  var output;&lt;br /&gt;  if (input.match(isRom)) output = getInt(input.toUpperCase(), isStrict);&lt;br /&gt;  else if (input.match(isInt)) output = getRom(input);&lt;br /&gt;  else alert(input + " is not a Roman numeral or integer value.");&lt;br /&gt;&lt;br /&gt;  return output == null ? input : output;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function getInt(input, isStrict) {&lt;br /&gt;  var matcher = isStrict ? strict : valid;&lt;br /&gt;  if (input.match(matcher) == null) {&lt;br /&gt;    alert(input + " is not a valid Roman numeral.");&lt;br /&gt;    return;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  var s = 0;&lt;br /&gt;  var words = input.match(word);&lt;br /&gt;  for (var i = 0; i &amp;lt; words.length; i++) {&lt;br /&gt;    s += value[words[i]];&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  return s;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function getRom(input) {&lt;br /&gt;  var num = parseInt(input, 10);&lt;br /&gt;&lt;br /&gt;  if (num &amp;lt; 1 || num &amp;gt; 3999) {&lt;br /&gt;    alert("Integer must be between 1 and 3999.");&lt;br /&gt;    return;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  var s = "";&lt;br /&gt;  while (num &amp;gt;= 1000) { num -= 1000; s +=  "M"; }&lt;br /&gt;  if    (num &amp;gt;=  900) { num -=  900; s += "CM"; }&lt;br /&gt;  if    (num &amp;gt;=  500) { num -=  500; s +=  "D"; }&lt;br /&gt;  if    (num &amp;gt;=  400) { num -=  400; s += "CD"; }&lt;br /&gt;  while (num &amp;gt;=  100) { num -=  100; s +=  "C"; }&lt;br /&gt;  if    (num &amp;gt;=   90) { num -=   90; s += "XC"; }&lt;br /&gt;  if    (num &amp;gt;=   50) { num -=   50; s +=  "L"; }&lt;br /&gt;  if    (num &amp;gt;=   40) { num -=   40; s += "XL"; }&lt;br /&gt;  while (num &amp;gt;=   10) { num -=   10; s +=  "X"; }&lt;br /&gt;  if    (num &amp;gt;=    9) { num -=    9; s += "IX"; }&lt;br /&gt;  if    (num &amp;gt;=    5) { num -=    5; s +=  "V"; }&lt;br /&gt;  if    (num &amp;gt;=    4) { num -=    4; s += "IV"; }&lt;br /&gt;  while (num &amp;gt;=    1) { num -=    1; s +=  "I"; }&lt;br /&gt;  return s;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11885757-5930073477840759254?l=cautery.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cautery.blogspot.com/feeds/5930073477840759254/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://cautery.blogspot.com/2010/11/roman-numerals-redux.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/5930073477840759254'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/5930073477840759254'/><link rel='alternate' type='text/html' href='http://cautery.blogspot.com/2010/11/roman-numerals-redux.html' title='Roman numerals redux'/><author><name>Curtis Autery</name><uri>https://profiles.google.com/107677530285177731535</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/--J3C_khtLqQ/AAAAAAAAAAI/AAAAAAAADT4/e2Qa5ncfAMk/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11885757.post-5439384927112673223</id><published>2010-11-15T19:55:00.000-05:00</published><updated>2010-11-15T19:55:06.570-05:00</updated><title type='text'>The crazy geometry of basketball courts</title><content type='html'>I saw an interesting question on &lt;a href="http://blog.mrmeyer.com/?p=8450&amp;utm_source=feedburner&amp;utm_medium=feed&amp;utm_campaign=Feed:+dydan1+(dy/dan+posts+%2B+lessons)"&gt;dy/dan&lt;/a&gt; today about posing basketball-related math questions to students. One of the reader suggestions was to talk open-endedly about the geometry of the court itself, to which Dan suggested writing a program that would draw a court given two mouse clicks to denote the baseline. That sounded right up my alley, so I wrote one.&lt;br /&gt;&lt;br /&gt;Before starting to code, I had to learn about the measurements of a basketball court, and I was a little surprised by what I found. First and foremost, every league has its own sizes for every piece of the court, most differing by a foot or less. The biggest discrepancy is with the length of the court, which is 10 feet less for high school than for NCAA and above, or about 2 running steps. Naturally the FIBA league had measurements rounded to meters where all the US leagues are rounded to feet.&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;A couple other things struck me as odd. First, the backboard is 4 feet from the baseline - inside the court. I always assumed it was flush with the baseline. A second bad assumption of mine was that the three-point line was a conic section, like a parabola or hyperbola. It's not. It's a semi-circle at the top, and straight lines at the bottom, like a horseshoe. The rules imply this shape, but only refer to the three-point line as an arc.&lt;br /&gt;&lt;br /&gt;The last organized basketball game I went to was with my daughter and my mentee, and we watched the Ohio State women's team trounce an unranked opponent from the comfort of the AEP suite at the Schottenstein center. As a nod to both of them, and to the AEP mentoring program which scored me the free tickets, all the measurements below are regulation NCAA women's court measurements. And I can assure you those players are capable of shooting from further out than their ridiculously truncated three-point line. And playing with the same ball their male counterparts use: two ounces heavier and one inch more in circumference. I honestly didn't start writing this as a feminist entry; the discrepancies just upset me after I thought about them for a while. Anyway, back to the code.&lt;br /&gt;&lt;br /&gt;Java applet to draw a court:&lt;br /&gt;&lt;applet style="background:#ccc;padding:5px;" archive="https://sites.google.com/site/ceauterytest/Home/drawCourt.jar" code="cea/demos/drawCourt/DrawCourt.class" width=600 height=600&gt;&lt;br /&gt;&lt;/applet&gt;&lt;br /&gt;Source code:&lt;br /&gt;&lt;pre&gt;package cea.demos.drawCourt;&lt;br /&gt;import java.applet.Applet;&lt;br /&gt;import java.awt.BasicStroke;&lt;br /&gt;import java.awt.Color;&lt;br /&gt;import java.awt.Graphics;&lt;br /&gt;import java.awt.Graphics2D;&lt;br /&gt;import java.awt.Point;&lt;br /&gt;import java.awt.RenderingHints;&lt;br /&gt;import java.awt.Shape;&lt;br /&gt;import java.awt.Stroke;&lt;br /&gt;import java.awt.event.MouseAdapter;&lt;br /&gt;import java.awt.event.MouseEvent;&lt;br /&gt;import java.awt.geom.AffineTransform;&lt;br /&gt;import java.awt.geom.Arc2D;&lt;br /&gt;import java.awt.geom.Ellipse2D;&lt;br /&gt;import java.awt.geom.GeneralPath;&lt;br /&gt;import java.awt.geom.Rectangle2D;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;public class DrawCourt extends Applet {&lt;br /&gt;  private static final long serialVersionUID = 1L;&lt;br /&gt;  // Paths describing the court lines, and the bottom-most free-throw separators, which are filled in and 1' foot thick&lt;br /&gt;  GeneralPath court, fill;&lt;br /&gt;  Shape courtTransformed, fillTransformed; // The same shapes after an affineTransform is applied to them&lt;br /&gt;  Stroke stroke; // How thick of a line to draw the court with. Most lines are 2" thick (relative to court size)&lt;br /&gt;  // Applet has three draw/input modes: Getting the upper-left point, the upper-right point, and drawing the court&lt;br /&gt;  enum Mode {GET_UL_POINT, GET_UR_POINT, PAINT_COURT}&lt;br /&gt;  Mode mode;&lt;br /&gt;  Point upperLeft;&lt;br /&gt;&lt;br /&gt;  public void init() {&lt;br /&gt;    mode = Mode.GET_UL_POINT;&lt;br /&gt;    addMouseListener(new GetClick());&lt;br /&gt;&lt;br /&gt;    // Initialize court shape object&lt;br /&gt;    court = new GeneralPath();&lt;br /&gt;    fill = new GeneralPath();&lt;br /&gt;&lt;br /&gt;    // Build the court shape. Comments describe what each line is, and the rectangle, ellipse, and arc&lt;br /&gt;    // objects describe the bounding rectangles of the lines&lt;br /&gt;    &lt;br /&gt;    // Out-of-bounds rectangle, 50' by 94'&lt;br /&gt;    court.append(new Rectangle2D.Double(0, 0, 50, 94), false);&lt;br /&gt;    &lt;br /&gt;    // Coaching box markers, 28' from baseline, three feet long, on both sides of court &lt;br /&gt;    court.append(new Rectangle2D.Double( 0, 28, 3, 0), false);&lt;br /&gt;    court.append(new Rectangle2D.Double(47, 28, 3, 0), false);&lt;br /&gt;    court.append(new Rectangle2D.Double( 0, 66, 3, 0), false);&lt;br /&gt;    court.append(new Rectangle2D.Double(47, 66, 3, 0), false);&lt;br /&gt;    &lt;br /&gt;    // Center-court line, 47' from baseline (94 / 2 = 47), all the way across court (50')&lt;br /&gt;    court.append(new Rectangle2D.Double(0, 47, 50, 0), false);&lt;br /&gt;    &lt;br /&gt;    // Restraining circle and center circle, 2' and 6' radii from middle of center-court line&lt;br /&gt;    court.append(new Ellipse2D.Double(23, 45,  4,  4), false);&lt;br /&gt;    court.append(new Ellipse2D.Double(19, 41, 12, 12), false);&lt;br /&gt;    &lt;br /&gt;    // Back-boards and baskets&lt;br /&gt;    // Back-boards are 4' inside court from baseline, centered, and 6' wide&lt;br /&gt;    court.append(new Rectangle2D.Double(22,  4, 6, 0), false);&lt;br /&gt;    court.append(new Rectangle2D.Double(22, 90, 6, 0), false);&lt;br /&gt;    // Basket are 18" circles mounted 6" from backboard&lt;br /&gt;    court.append(new Ellipse2D.Double(24.25,  4.5, 1.5, 1.5), false);&lt;br /&gt;    court.append(new Ellipse2D.Double(24.25, 88.0, 1.5, 1.5), false);&lt;br /&gt;    &lt;br /&gt;    // NCAA women's 3-point lines are 19'9" from basket's center, until 5'3" from court's side,&lt;br /&gt;    // then straight down to baseline. The rules describing court layouts are ambiguous about this,&lt;br /&gt;    // but this appears to be how they're laid out in reality.&lt;br /&gt;    //  top&lt;br /&gt;    court.append(new Arc2D.Double(5.25, -14.5, 39.5, 39.5, 0, -180, Arc2D.OPEN), false);&lt;br /&gt;    court.append(new Rectangle2D.Double( 5.25, 0, 0, 5.25), false);&lt;br /&gt;    court.append(new Rectangle2D.Double(44.75, 0, 0, 5.25), false);&lt;br /&gt;    // bottom&lt;br /&gt;    court.append(new Arc2D.Double(5.25, 69, 39.5, 39.5, 0, 180, Arc2D.OPEN), false);&lt;br /&gt;    court.append(new Rectangle2D.Double( 5.25, 88.75, 0, 5.25), false);&lt;br /&gt;    court.append(new Rectangle2D.Double(44.75, 88.75, 0, 5.25), false);&lt;br /&gt;    &lt;br /&gt;    // "The Paint", 12' by 19' rectangle, centered and touching baseline&lt;br /&gt;    court.append(new Rectangle2D.Double(19,  0, 12, 19), false);&lt;br /&gt;    court.append(new Rectangle2D.Double(19, 75, 12, 19), false);&lt;br /&gt;    &lt;br /&gt;    // Free-throw circles, the top of The Paint (the free-throw line) is the circle's diameter&lt;br /&gt;    court.append(new Ellipse2D.Double(19, 13, 12, 12), false);&lt;br /&gt;    court.append(new Ellipse2D.Double(19, 69, 12, 12), false);&lt;br /&gt;    &lt;br /&gt;    // Free-throw bottom separators (need to be filled in), are 5' from baseline, 8" wide, 1' long&lt;br /&gt;    // and adjacent to The Paint&lt;br /&gt;    fill.append(new Rectangle2D.Double(19.0d - 2.0d/3, 7, 2.0d/3, 1), false);&lt;br /&gt;    fill.append(new Rectangle2D.Double(31, 7, 2.0d/3, 1), false);&lt;br /&gt;    fill.append(new Rectangle2D.Double(19.0d - 2.0d/3, 86, 2.0d/3, 1), false);&lt;br /&gt;    fill.append(new Rectangle2D.Double(31, 86, 2.0d/3, 1), false);&lt;br /&gt;    &lt;br /&gt;    // Other free-throw separators, 3' between edges, also 8" wide and adjacent to The Paint,&lt;br /&gt;    // but only 2" long&lt;br /&gt;    // top-left&lt;br /&gt;    court.append(new Rectangle2D.Double(19.0d - 2.0d/3, 11, 2.0d/3, 0), false);&lt;br /&gt;    court.append(new Rectangle2D.Double(19.0d - 2.0d/3, 14.0d + 1.0d/6, 2.0d/3, 0), false);&lt;br /&gt;    court.append(new Rectangle2D.Double(19.0d - 2.0d/3, 17.0d + 1.0d/3, 2.0d/3, 0), false);&lt;br /&gt;    // top-right&lt;br /&gt;    court.append(new Rectangle2D.Double(31, 11, 2.0d/3, 0), false);&lt;br /&gt;    court.append(new Rectangle2D.Double(31, 14.0d + 1.0d/6, 2.0d/3, 0), false);&lt;br /&gt;    court.append(new Rectangle2D.Double(31, 17.0d + 1.0d/3, 2.0d/3, 0), false);&lt;br /&gt;    // bottom-left&lt;br /&gt;    court.append(new Rectangle2D.Double(19.0d - 2.0d/3, 83, 2.0d/3, 0), false);&lt;br /&gt;    court.append(new Rectangle2D.Double(19.0d - 2.0d/3, 80.0d - 1.0d/6, 2.0d/3, 0), false);&lt;br /&gt;    court.append(new Rectangle2D.Double(19.0d - 2.0d/3, 77.0d - 1.0d/3, 2.0d/3, 0), false);&lt;br /&gt;    // bottom-right&lt;br /&gt;    court.append(new Rectangle2D.Double(31, 83, 2.0d/3, 0), false);&lt;br /&gt;    court.append(new Rectangle2D.Double(31, 80.0d - 1.0d/6, 2.0d/3, 0), false);&lt;br /&gt;    court.append(new Rectangle2D.Double(31, 77.0d - 1.0d/3, 2.0d/3, 0), false);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  // This method creates transformed shapes of the court shape archetypes.&lt;br /&gt;  public void scaleCourt(Point left, Point right) {&lt;br /&gt;    double radians;&lt;br /&gt;    if (left.x == right.x) radians = left.y &amp;lt; right.y ? Math.PI/2 : -Math.PI/2; // Avoid divide by 0 error&lt;br /&gt;    else radians = Math.atan((float)(right.y - left.y)/(right.x - left.x));&lt;br /&gt;    if (right.x &amp;lt; left.x)radians += Math.PI; // Fix angle if in quadrants 2 or 3&lt;br /&gt;&lt;br /&gt;    /* "factor" bears some explanation. The default size of the court shape is 1 pixel per foot. Two points&lt;br /&gt;     * on the screen are clicked, representing corners of the baseline: 50' across. So, the factor to scale the shape&lt;br /&gt;     * will be the real distance between the corner points divided by the default size of 50.&lt;br /&gt;     */&lt;br /&gt;    float factor = (float) (left.distance(right)/50);&lt;br /&gt;    stroke = new BasicStroke(factor * 2.0f / 12); // Default stroke = 2 inches relative to court size&lt;br /&gt;    AffineTransform tx = new AffineTransform();&lt;br /&gt;    tx.setToScale(factor, factor);&lt;br /&gt;    tx.rotate(radians);&lt;br /&gt;    courtTransformed = tx.createTransformedShape(court);&lt;br /&gt;    fillTransformed = tx.createTransformedShape(fill);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  public void paint(Graphics g1) {&lt;br /&gt;    Graphics2D g = (Graphics2D)g1;&lt;br /&gt;    g.setColor(Color.BLACK);&lt;br /&gt;    switch(mode) {&lt;br /&gt;    case GET_UL_POINT:&lt;br /&gt;      g.drawString("Click where the upper-left corner of the court will be.", 50, 50);&lt;br /&gt;      break;&lt;br /&gt;    case GET_UR_POINT:&lt;br /&gt;      g.fillOval(upperLeft.x - 4, upperLeft.y - 4, 8, 8);&lt;br /&gt;      g.drawString("Now click where the upper-right corner should be", 50, 50);&lt;br /&gt;      break;&lt;br /&gt;    case PAINT_COURT:&lt;br /&gt;      g.drawString("Click again to start over", 50, 50);&lt;br /&gt;      g.setStroke(stroke);&lt;br /&gt;      g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);&lt;br /&gt;      g.translate(upperLeft.x, upperLeft.y);&lt;br /&gt;      g.draw(courtTransformed);&lt;br /&gt;      g.fill(fillTransformed);&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  class GetClick extends MouseAdapter {&lt;br /&gt;    @Override&lt;br /&gt;    public void mouseClicked(MouseEvent e) {&lt;br /&gt;      switch (mode) {&lt;br /&gt;      case GET_UL_POINT:&lt;br /&gt;        upperLeft = e.getPoint();&lt;br /&gt;        mode = Mode.GET_UR_POINT;&lt;br /&gt;        repaint();&lt;br /&gt;        break;&lt;br /&gt;      case GET_UR_POINT:&lt;br /&gt;        mode = Mode.PAINT_COURT;&lt;br /&gt;        scaleCourt(upperLeft, e.getPoint());&lt;br /&gt;        repaint();&lt;br /&gt;        break;&lt;br /&gt;      case PAINT_COURT:&lt;br /&gt;        mode = Mode.GET_UL_POINT;&lt;br /&gt;        repaint();&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11885757-5439384927112673223?l=cautery.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cautery.blogspot.com/feeds/5439384927112673223/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://cautery.blogspot.com/2010/11/crazy-geometry-of-basketball-courts.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/5439384927112673223'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/5439384927112673223'/><link rel='alternate' type='text/html' href='http://cautery.blogspot.com/2010/11/crazy-geometry-of-basketball-courts.html' title='The crazy geometry of basketball courts'/><author><name>Curtis Autery</name><uri>https://profiles.google.com/107677530285177731535</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/--J3C_khtLqQ/AAAAAAAAAAI/AAAAAAAADT4/e2Qa5ncfAMk/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11885757.post-1418854516356189852</id><published>2010-11-11T17:54:00.004-05:00</published><updated>2010-11-11T17:59:12.629-05:00</updated><title type='text'>Jury Duty</title><content type='html'>On Wednesday, when I was up walking around to limber up after reading in a chair for a few hours, I came across the bulletin board in the jury pool waiting room. The board had several local newspaper op-ed pieces on jury service that may as well have been written by a chatbot, randomly generating from a dictionary of truisms and catch-phrases. "Ten Reasons I'm Glad I Served. 1: To see the inner-workings of the law. 2: To meet new friends..." Hence this post, a gritty look at my experience being on jury duty. The management summary: my experience was interesting, but the process is flawed. Like Randy Pees used to say, "Our legal system is terrible. The only one worse than ours is everyone else's."&lt;br /&gt;&lt;br /&gt;About two weeks prior to my reading of the platitude-laden corkboard, I received a summons in the mail to report for jury duty. I tried to get out of it by replying with a letter claiming a child-care burden, as I pick up Scout from school on Tuesdays and Thursdays so that Liberty can attend later classes on those days. I got a phone call the next day telling me basically to suck it up and make other arrangements. Conveniently, this did not prove to be an actual problem: On Tuesday we were released before 5pm, and the courthouse was closed today for Veteran's Day.&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;On Monday, the summons instructed me to report at 8am, an hour before any trial could conceivably start. I spent most of that hour in a hot and crowded room waiting in line with a two page questionnaire asking me, among other things, whether I knew any police officers, if I had ever seen the inside of a courtroom before, or was involved in a lawsuit or related to anyone who had. My answers -- which were yes, yes, and yes -- would be handed directly to the lawyers of any case I would be assigned to later.&lt;br /&gt;&lt;br /&gt;The rest of the hour was spent in an auditorium watching a film showing people dressed in Middle Ages period garb performing a trial by ordeal (tossing someone in the water to test their guilt -- float = guilty, drown = innocent), to show us how far we have come in these enlightened days, followed by a question and answer session by a septuagenarian judge whose cheerfulness and flamboyant mannerisms would have put Leo Buscaglia to shame. Oddly, the judge claimed that the process of trial by jury began with the Magna Carta, ignoring the Athenian's use of jurors some 1800 years earlier. Perhaps the 500 jurors of Socrates rings a bell, judge? No?&lt;br /&gt;&lt;br /&gt;A more credible fact brought up in the lecture was that of the 400 people summoned for this week's service, less than 200 showed up, which is about average. I've come up with two explanations for this, neither of which bode well for my country. First, companies are not required to pay you while you're on jury duty, and the courts only pay you a nominal wage ($20/day) meant to cover parking and lunch. Second, people consider themselves consumers and not citizens, and have no sense of civic duty.&lt;br /&gt;&lt;br /&gt;"But wait," you may be saying, "didn't you yourself try to get out of jury duty? Isn't it hypocritical to claim other people aren't civic-minded?" To answer, here is the text of the letter I sent to the jury commission:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Request for Curtis Autery being excused from jury duty for child care reasons&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Dear sirs,&lt;br /&gt;&lt;br /&gt;My wife, Liberty, has late classes at OSU on Tuesdays and Thursdays.  These classes run until 5:18pm.  On these days, I pick up my daughter, Scout, from school around 4pm so that she can have dinner and get started on her homework.&lt;br /&gt;&lt;br /&gt;If I were to serve jury duty, Scout would be required to stay in after-school care on these days, which is only available until 6pm.  The time it would take Liberty to get to her car and then fight rush-hour traffic to get to Scout’s school would typically have her arriving after 6pm.  This would place a financial burden on us in paying fines each day this happened (which would be most Tuesdays and Thursdays), and the disruption of Scout’s well-being as she would have a late dinner and not get started on her homework until she was tired in the evening.&lt;br /&gt;&lt;br /&gt;I respectfully request to be excused from this jury duty assignment.  With that said, I welcome the opportunity to serve, and each semester at OSU brings my wife a different schedule, so this disruption may not apply should I get summoned again in the future.&lt;br /&gt;&lt;br /&gt;Thank you very much.&lt;br /&gt;&lt;br /&gt;Curtis Autery&lt;br /&gt;[address, phone]&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;The letter mentions that I would like another chance to serve if they excused me this time, and when told to quit whining and show up like a man, that's exactly what I did.&lt;br /&gt;&lt;br /&gt;The $20/day and employers not being required to pay is more interesting, though. If you have a working class job that doesn't pay for jury service, you're probably living paycheck to paycheck already, and can't afford the time off, and hence can't serve. Many criminal cases involve defendants with working class jobs. How then, can they get a jury of their peers?&lt;br /&gt;&lt;br /&gt;Or let's take the racial angle: If you live in an area with rich white people and poor black people, and a black man is on trial, what are the jurors likely to be? White, because they can either afford the time off, or their employers pay their normal salary during jury service. Are they likely to be sympathetic to the black man on trial? No. Biased against? Yes.&lt;br /&gt;&lt;br /&gt;I don't consider myself to be especially political or an activist, but the way jury service is run is a clear disservice to my fellow man, perhaps explaining why there are so many black men in prison, many of which are later found not to be guilty of their accused crimes through the help of The Innocence Project.&lt;br /&gt;&lt;br /&gt;On with the story.&lt;br /&gt;&lt;br /&gt;Day 1 continued with waiting for a trial to start, which happened roughly 30 minutes later, and I was one of the 24 people called up to be potential jurors. The case was Zimara Ball v. Jessica Stark, involving (from the pretrial statement) "an automobile/pedestrian accident which occurred on June 3, 2006, when then­10-year­old Zimara Ball darted onto Brown Road ... As Zimara Ball did so, she ran into the passenger side front quarter panel of a vehicle being driven by Defendant Jessica Stark."&lt;br /&gt;&lt;br /&gt;Per directions from the court, I refrained from looking up anything about the case until I was discharged from jury service. Oddly, and despite being a seasoned data miner, I can find no mention of this incident in the news when it happened, or coverage of the current trial. Jessica's employer at the time, Maronda homes, has painstakingly expunged any reference to her from its website. News site searches for both parties reveals nothing other than Zimara making the 8th grade honor roll this year -- congratulations! The only information I could find about the case was on the court website itself, which is kind enough to supply scanned copies of all the motions and filings. &lt;br /&gt;&lt;br /&gt;The courtroom had a handful of people in it before I and my fellow potential jurors came in. The plaintiff's mom (effectively the real plaintiff) and her legal staff, Jessica and her legal staff, a lawyer representing Maronda Homes, the judge, the court reporter, and a couple random people with no apparent function to serve were all standing and waiting for us to come in and find our seats. After we were sworn in, the judge began to explain voir dire, the process of weeding out bad jurors.&lt;br /&gt;&lt;br /&gt;This was a civil trial, meaning there are 8 jurors and two alternates, and only a 3/4 majority is needed to decide guilt. The judge, and then the lawyers, would use our questionnaires, and direct and indirect questioning to determine if anyone shouldn't be on the jury. The reasons one wouldn't be appropriate to be on the jury would be having a bias against "the system", personally knowing any of the parties, having passable knowledge of anything expert witnesses would testify about (I have mixed feelings about this one), or having a similar personal experience to what was being tried.&lt;br /&gt;&lt;br /&gt;So around the room the judge went, and around the room the lawyers went, and in about an hour we found that two men had children that had been murdered, a mom had severe anxiety about child safety, a narcissistic woman habitually receives traffic tickets and distrusts any police testimony, I myself have been hit by a car while bicycling, and just about everyone had been in court for some reason before. The parents of the murdered children, crying-towel mom, and the spazzy driver were all let go, but for whatever reason they kept me on until the second day.&lt;br /&gt;&lt;br /&gt;Here is where some distasteful things happen. Here is where lawyer jokes come from. In fact, here's one now: Q) How do you save a lawyer from drowning? A) Take your foot off his head.&lt;br /&gt;&lt;br /&gt;The judge painstakingly explains why not discussing the case or drawing any conclusions early is important. One of the reasons he gives is the following example of two jurors, let's call them George and Bob, talking about the case over lunch...&lt;br /&gt;&lt;br /&gt;"Gee, Bob, I really didn't find that last witness convincing. I think he's lying." George has just committed to a point of view out loud, and for some people it's difficult to go against an opinion you've stated openly. If George now hears more evidence that supports the witness he thought was lying, he will be more hesitant to change his mind than if he had said nothing. Apparently saying "I may have been wrong before" is difficult for people. Or possibly nobody reads Emerson&lt;sub&gt;1&lt;/sub&gt; any more.&lt;br /&gt;&lt;br /&gt;On top of the admonition not to talk about the case, it was made clear that we weren't trying the case, or hearing any evidence in it yet. We were instead in a vague, nebulous discussion about issues that may come up during the trial and whether our personal biases would put objectivity in peril before any &lt;b&gt;real&lt;/b&gt; evidence was heard.&lt;br /&gt;&lt;br /&gt;The judge was specifically avoiding giving out information about the case with his questions, and avoiding questions leading us to profess a belief. The lawyers, however, had no such qualms. Objections flew, and the judge stopped the questioning on his own multiple times, as the lawyers jockeyed for position.&lt;br /&gt;&lt;br /&gt;The plaintiff's lawyer asked us all to commit, under oath, to the belief that everyone should always, under all circumstances, slow down when a child is anywhere near a road. This tells me two things: The defendant didn't slow down, and there is a reason that she didn't think she needed to. And the lawyer wanted me to say "oh yes, there can never be a reason not to instantaneously slow down when a kid is present." Having delivered pizza for two years, and being a father, I understand that kids have no peripheral vision, no understanding of physics or consequences, follow bouncing balls into the street like a moth to a flame, and can generally be assumed to be at least unpredictable, if not batshit crazy. None of that implies, though, that braking should be automatic whenever there are any kids anywhere. The question implied that there is some ambiguity about whether slowing was appropriate, and some of us already began to commit to a point of view we might want to reconsider later, exactly the type of thing the judge warned us not to do.&lt;br /&gt;&lt;br /&gt;He next asked us if we had ever hit anything in our car that we didn't see, and all who answered in the affirmative were later excused from the case. So the defendant probably claims to have not seen the girl darting into the road, and later the plaintiff's lawyer will claim this not to be possible.&lt;br /&gt;&lt;br /&gt;The defendant's lawyer had her turn then, and went on a rant about today's children looking older than they are, trying to get everyone to admit that they were bad judges of kids' ages, just like her client. And then the question of how old a kid should be before she should be considered competent to cross a street unassisted came up. We had already heard at this point that the accident happened when the girl was 10, a nice round number, and at least half of the remaining jurors put 10 as the age at which kids shouldn't be darting out into traffic any more. So the defendant may have seen the kid or may not, and if she did, then she thought the kid was older, but either way, believes that once you're 10 you shouldn't be doing anything stupid like that anyway. So there are lots of possible defenses in play, and the lawyer was getting a read on which one would work best.&lt;br /&gt;&lt;br /&gt;So that pretty much laid the whole trial out, right there in the voir dire proceeding, with at least two thirds of us committing to some solid point of view that the lawyers will be trying to leverage throughout the trial. This was all the exact opposite of what was supposed to be happening, and all the court officials played this theater of pretending nothing mistrial-worthy had just happened.&lt;br /&gt;&lt;br /&gt;I was sickened, and once the day's proceedings were over, was very glad to go home.&lt;br /&gt;&lt;br /&gt;Day 2 involved a lot of waiting, and none of the preceding day's ethical problems. I parked my car at my work's garage, hoofed it to the courthouse, put on my juror's badge to make me an un-person -- to warn off lawyers and case parties from engaging in conversation with me (strangers don't tend to seek out my conversation, so I wasn't very concerned about this) -- signed in at the jury pool waiting room, and headed up to the sixth floor where our courtroom was. We assembled at 9:30, entered the courtroom, and were asked a single question from the judge: "Did you hear the news story last night about the traffic accident?" We were then told to leave and re-assemble at 10. At 10:15, they finally called us back in, where they announced that the jury had been selected. Ten of our names were read. My name wasn't one of them.&lt;br /&gt;&lt;br /&gt;I spent the rest of my time in the insanely hot jury pool waiting room, reading "The Terror" by Dan Simmons. By day 3 I had finished the first 100 pages, and couldn't sit in the uncomfortable chairs any longer, so got up and meandered over to find the newspaper editorials, yellowed with age, espousing the awesomeness of jury duty, being a citizen, and America itself. I like America just fine, and the benefits of being a citizen, and I don't shirk the duties that come with that, but the duties aren't as rose-colored as puff-piece articles would lead one to believe.&lt;br /&gt;&lt;br /&gt;1 - From Ralph Waldo Emerson's "Self-Reliance": Speak what you think now in hard words, and to-morrow speak what to-morrow thinks in hard words again, though it contradict every thing you said to-day.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11885757-1418854516356189852?l=cautery.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cautery.blogspot.com/feeds/1418854516356189852/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://cautery.blogspot.com/2010/11/jury-duty.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/1418854516356189852'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/1418854516356189852'/><link rel='alternate' type='text/html' href='http://cautery.blogspot.com/2010/11/jury-duty.html' title='Jury Duty'/><author><name>Curtis Autery</name><uri>https://profiles.google.com/107677530285177731535</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/--J3C_khtLqQ/AAAAAAAAAAI/AAAAAAAADT4/e2Qa5ncfAMk/s512-c/photo.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11885757.post-1188827460075014484</id><published>2010-10-24T20:55:00.001-04:00</published><updated>2010-10-24T20:56:37.365-04:00</updated><title type='text'>Awesome Ted talks</title><content type='html'>(plus some David Byrne worship, because he rocks)&lt;br /&gt;(and Seth Godin at GEL, who also rocks)&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;David Byrne sings Nothing but Flowers&lt;br /&gt;&lt;object width="446" height="326"&gt;&lt;param name="movie" value="http://video.ted.com/assets/player/swf/EmbedPlayer.swf"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true" /&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;param name="bgColor" value="#ffffff"&gt;&lt;/param&gt;&lt;param name="flashvars" value="vu=http://video.ted.com/talks/dynamic/DavidByrne_FLOWERS_2010-medium.flv&amp;su=http://images.ted.com/images/ted/tedindex/embed-posters/DavidByrne-Flowers-2010.embed_thumbnail.jpg&amp;vw=432&amp;vh=240&amp;ap=0&amp;ti=988&amp;introDuration=15330&amp;adDuration=4000&amp;postAdDuration=830&amp;adKeys=talk=david_byrne_sings_nothing_but_flowers;year=2010;theme=spectacular_performance;theme=a_greener_future;theme=inspired_by_nature;theme=the_creative_spark;theme=a_taste_of_ted2010;event=TED2010;&amp;preAdTag=tconf.ted/embed;tile=1;sz=512x288;" /&gt;&lt;embed src="http://video.ted.com/assets/player/swf/EmbedPlayer.swf" pluginspace="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" wmode="transparent" bgColor="#ffffff" width="446" height="326" allowFullScreen="true" allowScriptAccess="always" flashvars="vu=http://video.ted.com/talks/dynamic/DavidByrne_FLOWERS_2010-medium.flv&amp;su=http://images.ted.com/images/ted/tedindex/embed-posters/DavidByrne-Flowers-2010.embed_thumbnail.jpg&amp;vw=432&amp;vh=240&amp;ap=0&amp;ti=988&amp;introDuration=15330&amp;adDuration=4000&amp;postAdDuration=830&amp;adKeys=talk=david_byrne_sings_nothing_but_flowers;year=2010;theme=spectacular_performance;theme=a_greener_future;theme=inspired_by_nature;theme=the_creative_spark;theme=a_taste_of_ted2010;event=TED2010;"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;How architecture helped music evolve&lt;br /&gt;&lt;object width="446" height="326"&gt;&lt;param name="movie" value="http://video.ted.com/assets/player/swf/EmbedPlayer.swf"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true" /&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;param name="bgColor" value="#ffffff"&gt;&lt;/param&gt;&lt;param name="flashvars" value="vu=http://video.ted.com/talks/dynamic/DavidByrne_2010-medium.flv&amp;su=http://images.ted.com/images/ted/tedindex/embed-posters/DavidByrne-2010.embed_thumbnail.jpg&amp;vw=432&amp;vh=240&amp;ap=0&amp;ti=883&amp;introDuration=15330&amp;adDuration=4000&amp;postAdDuration=830&amp;adKeys=talk=david_byrne_how_architecture_helped_music_evolve;year=2010;theme=unconventional_explanations;theme=art_unusual;theme=the_creative_spark;theme=a_taste_of_ted2010;theme=new_on_ted_com;event=TED2010;&amp;preAdTag=tconf.ted/embed;tile=1;sz=512x288;" /&gt;&lt;embed src="http://video.ted.com/assets/player/swf/EmbedPlayer.swf" pluginspace="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" wmode="transparent" bgColor="#ffffff" width="446" height="326" allowFullScreen="true" allowScriptAccess="always" flashvars="vu=http://video.ted.com/talks/dynamic/DavidByrne_2010-medium.flv&amp;su=http://images.ted.com/images/ted/tedindex/embed-posters/DavidByrne-2010.embed_thumbnail.jpg&amp;vw=432&amp;vh=240&amp;ap=0&amp;ti=883&amp;introDuration=15330&amp;adDuration=4000&amp;postAdDuration=830&amp;adKeys=talk=david_byrne_how_architecture_helped_music_evolve;year=2010;theme=unconventional_explanations;theme=art_unusual;theme=the_creative_spark;theme=a_taste_of_ted2010;theme=new_on_ted_com;event=TED2010;"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;How schools kill creativity&lt;br /&gt;&lt;object width="334" height="326"&gt;&lt;param name="movie" value="http://video.ted.com/assets/player/swf/EmbedPlayer.swf"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true" /&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;param name="bgColor" value="#ffffff"&gt;&lt;/param&gt;&lt;param name="flashvars" value="vu=http://video.ted.com/talks/dynamic/SirKenRobinson_2006-medium.flv&amp;su=http://images.ted.com/images/ted/tedindex/embed-posters/SirKenRobinson-2006.embed_thumbnail.jpg&amp;vw=320&amp;vh=240&amp;ap=0&amp;ti=66&amp;introDuration=15330&amp;adDuration=4000&amp;postAdDuration=830&amp;adKeys=talk=ken_robinson_says_schools_kill_creativity;year=2006;theme=top_10_tedtalks;theme=master_storytellers;theme=the_creative_spark;theme=how_the_mind_works;theme=bold_predictions_stern_warnings;theme=how_we_learn;event=TED2006;&amp;preAdTag=tconf.ted/embed;tile=1;sz=512x288;" /&gt;&lt;embed src="http://video.ted.com/assets/player/swf/EmbedPlayer.swf" pluginspace="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" wmode="transparent" bgColor="#ffffff" width="334" height="326" allowFullScreen="true" allowScriptAccess="always" flashvars="vu=http://video.ted.com/talks/dynamic/SirKenRobinson_2006-medium.flv&amp;su=http://images.ted.com/images/ted/tedindex/embed-posters/SirKenRobinson-2006.embed_thumbnail.jpg&amp;vw=320&amp;vh=240&amp;ap=0&amp;ti=66&amp;introDuration=15330&amp;adDuration=4000&amp;postAdDuration=830&amp;adKeys=talk=ken_robinson_says_schools_kill_creativity;year=2006;theme=top_10_tedtalks;theme=master_storytellers;theme=the_creative_spark;theme=how_the_mind_works;theme=bold_predictions_stern_warnings;theme=how_we_learn;event=TED2006;"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;Malcolm Gladwell on spaghetti sauce&lt;br /&gt;&lt;object width="446" height="326"&gt;&lt;param name="movie" value="http://video.ted.com/assets/player/swf/EmbedPlayer.swf"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true" /&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;param name="bgColor" value="#ffffff"&gt;&lt;/param&gt;&lt;param name="flashvars" value="vu=http://video.ted.com/talks/dynamic/MalcolmGladwell_2004-medium.flv&amp;su=http://images.ted.com/images/ted/tedindex/embed-posters/MalcolmGladwell-2004.embed_thumbnail.jpg&amp;vw=432&amp;vh=240&amp;ap=0&amp;ti=20&amp;introDuration=15330&amp;adDuration=4000&amp;postAdDuration=830&amp;adKeys=talk=malcolm_gladwell_on_spaghetti_sauce;year=2004;theme=not_business_as_usual;theme=tales_of_invention;theme=unconventional_explanations;theme=what_makes_us_happy;event=TED2004;&amp;preAdTag=tconf.ted/embed;tile=1;sz=512x288;" /&gt;&lt;embed src="http://video.ted.com/assets/player/swf/EmbedPlayer.swf" pluginspace="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" wmode="transparent" bgColor="#ffffff" width="446" height="326" allowFullScreen="true" allowScriptAccess="always" flashvars="vu=http://video.ted.com/talks/dynamic/MalcolmGladwell_2004-medium.flv&amp;su=http://images.ted.com/images/ted/tedindex/embed-posters/MalcolmGladwell-2004.embed_thumbnail.jpg&amp;vw=432&amp;vh=240&amp;ap=0&amp;ti=20&amp;introDuration=15330&amp;adDuration=4000&amp;postAdDuration=830&amp;adKeys=talk=malcolm_gladwell_on_spaghetti_sauce;year=2004;theme=not_business_as_usual;theme=tales_of_invention;theme=unconventional_explanations;theme=what_makes_us_happy;event=TED2004;"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;The child-driven education. If you only pick one to watch, pick this one.&lt;br /&gt;&lt;object width="446" height="326"&gt;&lt;param name="movie" value="http://video.ted.com/assets/player/swf/EmbedPlayer.swf"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true" /&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;param name="bgColor" value="#ffffff"&gt;&lt;/param&gt;&lt;param name="flashvars" value="vu=http://video.ted.com/talks/dynamic/SugataMitra_2010G-medium.flv&amp;su=http://images.ted.com/images/ted/tedindex/embed-posters/SugataMitra-2010G.embed_thumbnail.jpg&amp;vw=432&amp;vh=240&amp;ap=0&amp;ti=949&amp;introDuration=15330&amp;adDuration=4000&amp;postAdDuration=830&amp;adKeys=talk=sugata_mitra_the_child_driven_education;year=2010;theme=new_on_ted_com;theme=how_the_mind_works;theme=unconventional_explanations;theme=rethinking_poverty;theme=a_taste_of_tedglobal_2010;event=TEDGlobal+2010;&amp;preAdTag=tconf.ted/embed;tile=1;sz=512x288;" /&gt;&lt;embed src="http://video.ted.com/assets/player/swf/EmbedPlayer.swf" pluginspace="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" wmode="transparent" bgColor="#ffffff" width="446" height="326" allowFullScreen="true" allowScriptAccess="always" flashvars="vu=http://video.ted.com/talks/dynamic/SugataMitra_2010G-medium.flv&amp;su=http://images.ted.com/images/ted/tedindex/embed-posters/SugataMitra-2010G.embed_thumbnail.jpg&amp;vw=432&amp;vh=240&amp;ap=0&amp;ti=949&amp;introDuration=15330&amp;adDuration=4000&amp;postAdDuration=830&amp;adKeys=talk=sugata_mitra_the_child_driven_education;year=2010;theme=new_on_ted_com;theme=how_the_mind_works;theme=unconventional_explanations;theme=rethinking_poverty;theme=a_taste_of_tedglobal_2010;event=TEDGlobal+2010;"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;Economic reality check&lt;br /&gt;&lt;object width="446" height="326"&gt;&lt;param name="movie" value="http://video.ted.com/assets/player/swf/EmbedPlayer.swf"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true" /&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;param name="bgColor" value="#ffffff"&gt;&lt;/param&gt;&lt;param name="flashvars" value="vu=http://video.ted.com/talks/dynamic/TimJackson_2010G-medium.flv&amp;su=http://images.ted.com/images/ted/tedindex/embed-posters/TimJackson-2010G.embed_thumbnail.jpg&amp;vw=432&amp;vh=240&amp;ap=0&amp;ti=972&amp;introDuration=15330&amp;adDuration=4000&amp;postAdDuration=830&amp;adKeys=talk=tim_jackson_s_economic_reality_check;year=2010;theme=bold_predictions_stern_warnings;theme=new_on_ted_com;theme=rethinking_poverty;theme=a_greener_future;theme=a_taste_of_tedglobal_2010;theme=unconventional_explanations;theme=not_business_as_usual;event=TEDGlobal+2010;&amp;preAdTag=tconf.ted/embed;tile=1;sz=512x288;" /&gt;&lt;embed src="http://video.ted.com/assets/player/swf/EmbedPlayer.swf" pluginspace="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" wmode="transparent" bgColor="#ffffff" width="446" height="326" allowFullScreen="true" allowScriptAccess="always" flashvars="vu=http://video.ted.com/talks/dynamic/TimJackson_2010G-medium.flv&amp;su=http://images.ted.com/images/ted/tedindex/embed-posters/TimJackson-2010G.embed_thumbnail.jpg&amp;vw=432&amp;vh=240&amp;ap=0&amp;ti=972&amp;introDuration=15330&amp;adDuration=4000&amp;postAdDuration=830&amp;adKeys=talk=tim_jackson_s_economic_reality_check;year=2010;theme=bold_predictions_stern_warnings;theme=new_on_ted_com;theme=rethinking_poverty;theme=a_greener_future;theme=a_taste_of_tedglobal_2010;theme=unconventional_explanations;theme=not_business_as_usual;event=TEDGlobal+2010;"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;The good news of the decade. Wait out the odd opening for a kickin' conclusion.&lt;br /&gt;&lt;object width="334" height="326"&gt;&lt;param name="movie" value="http://video.ted.com/assets/player/swf/EmbedPlayer.swf"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true" /&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;param name="bgColor" value="#ffffff"&gt;&lt;/param&gt;&lt;param name="flashvars" value="vu=http://video.ted.com/talks/dynamic/HansRosling_2010X-medium.flv&amp;su=http://images.ted.com/images/ted/tedindex/embed-posters/HansRosling-2010X.embed_thumbnail.jpg&amp;vw=320&amp;vh=240&amp;ap=0&amp;ti=974&amp;introDuration=15330&amp;adDuration=4000&amp;postAdDuration=830&amp;adKeys=talk=hans_rosling_the_good_news_of_the_decade;year=2010;theme=medicine_without_borders;theme=rethinking_poverty;theme=a_greener_future;theme=unconventional_explanations;theme=a_taste_of_tedx;theme=bold_predictions_stern_warnings;theme=new_on_ted_com;event=TEDxChange;&amp;preAdTag=tconf.ted/embed;tile=1;sz=512x288;" /&gt;&lt;embed src="http://video.ted.com/assets/player/swf/EmbedPlayer.swf" pluginspace="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" wmode="transparent" bgColor="#ffffff" width="334" height="326" allowFullScreen="true" allowScriptAccess="always" flashvars="vu=http://video.ted.com/talks/dynamic/HansRosling_2010X-medium.flv&amp;su=http://images.ted.com/images/ted/tedindex/embed-posters/HansRosling-2010X.embed_thumbnail.jpg&amp;vw=320&amp;vh=240&amp;ap=0&amp;ti=974&amp;introDuration=15330&amp;adDuration=4000&amp;postAdDuration=830&amp;adKeys=talk=hans_rosling_the_good_news_of_the_decade;year=2010;theme=medicine_without_borders;theme=rethinking_poverty;theme=a_greener_future;theme=unconventional_explanations;theme=a_taste_of_tedx;theme=bold_predictions_stern_warnings;theme=new_on_ted_com;event=TEDxChange;"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;This is broken!&lt;br /&gt;&lt;iframe src="http://player.vimeo.com/video/4246943" width="400" height="300" frameborder="0"&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11885757-1188827460075014484?l=cautery.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cautery.blogspot.com/feeds/1188827460075014484/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://cautery.blogspot.com/2010/10/awesome-ted-talks.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/1188827460075014484'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/1188827460075014484'/><link rel='alternate' type='text/html' href='http://cautery.blogspot.com/2010/10/awesome-ted-talks.html' title='Awesome Ted talks'/><author><name>Curtis Autery</name><uri>https://profiles.google.com/107677530285177731535</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/--J3C_khtLqQ/AAAAAAAAAAI/AAAAAAAADT4/e2Qa5ncfAMk/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11885757.post-2402613362530408438</id><published>2010-10-23T10:20:00.004-04:00</published><updated>2010-10-23T10:23:40.722-04:00</updated><title type='text'>Fun music videos, mostly 80s</title><content type='html'>Some videos that are cool.  No reason.&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;object width="640" height="505"&gt;&lt;param name="movie" value="http://www.youtube.com/v/I1wg1DNHbNU?fs=1&amp;amp;hl=en_US&amp;amp;rel=0"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/I1wg1DNHbNU?fs=1&amp;amp;hl=en_US&amp;amp;rel=0" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="505"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;object width="640" height="385"&gt;&lt;param name="movie" value="http://www.youtube.com/v/mxfjSnMN88U?fs=1&amp;amp;hl=en_US&amp;amp;rel=0"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/mxfjSnMN88U?fs=1&amp;amp;hl=en_US&amp;amp;rel=0" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="385"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;object width="640" height="505"&gt;&lt;param name="movie" value="http://www.youtube.com/v/7movKfyTBII?fs=1&amp;amp;hl=en_US&amp;amp;rel=0"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/7movKfyTBII?fs=1&amp;amp;hl=en_US&amp;amp;rel=0" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="505"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;object width="640" height="385"&gt;&lt;param name="movie" value="http://www.youtube.com/v/_EXxMlIExpo?fs=1&amp;amp;hl=en_US&amp;amp;rel=0"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/_EXxMlIExpo?fs=1&amp;amp;hl=en_US&amp;amp;rel=0" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="385"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;object width="640" height="505"&gt;&lt;param name="movie" value="http://www.youtube.com/v/Be0H_AI1zys?fs=1&amp;amp;hl=en_US&amp;amp;rel=0"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/Be0H_AI1zys?fs=1&amp;amp;hl=en_US&amp;amp;rel=0" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="505"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;object width="640" height="505"&gt;&lt;param name="movie" value="http://www.youtube.com/v/PIb6AZdTr-A?fs=1&amp;amp;hl=en_US&amp;amp;rel=0"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/PIb6AZdTr-A?fs=1&amp;amp;hl=en_US&amp;amp;rel=0" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="505"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;object width="640" height="505"&gt;&lt;param name="movie" value="http://www.youtube.com/v/G1dlWmrRstc?fs=1&amp;amp;hl=en_US&amp;amp;rel=0"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/G1dlWmrRstc?fs=1&amp;amp;hl=en_US&amp;amp;rel=0" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="505"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11885757-2402613362530408438?l=cautery.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cautery.blogspot.com/feeds/2402613362530408438/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://cautery.blogspot.com/2010/10/fun-videos-mostly-80s.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/2402613362530408438'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/2402613362530408438'/><link rel='alternate' type='text/html' href='http://cautery.blogspot.com/2010/10/fun-videos-mostly-80s.html' title='Fun music videos, mostly 80s'/><author><name>Curtis Autery</name><uri>https://profiles.google.com/107677530285177731535</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/--J3C_khtLqQ/AAAAAAAAAAI/AAAAAAAADT4/e2Qa5ncfAMk/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11885757.post-757497807665613101</id><published>2010-10-09T06:34:00.011-04:00</published><updated>2010-10-09T06:47:46.995-04:00</updated><title type='text'>JavaScript Roman numeral calculator</title><content type='html'>Yesterday I saw a homework question on a coding forum I frequent regarding turning Arabic numbers into Roman numerals. Homework questions are a strange breed. Most of the time the posters are blatantly cheating, some times they are up front that the question is for an assignment and they just want a push in the right direction. Responses range from helpful, following the Wikipedia "assume good faith" mantra, to cynical, to pretty damned rude. Forum admins enjoy flexing their dictatorial muscles in these cases, posting warnings, flames, and deleting posts.&lt;br /&gt;&lt;br /&gt;My mantra in these cases is simple: If the question is interesting, I try to answer it. If the poster isn't cut out for a programming career, getting my answer isn't going to change that. If he is, he's going to be asking his peers a lot of questions over his career, as no one is born with an innate gift at coding; it's a learned skill like anything else. The young "super hacker" is generally the geek equivalent of a bully - not as skilled/tough as he pretends.&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;I'm using "he" and "his" a lot here, which is deliberate. There are women coders, sure, but for whatever reason they don't frequent the programming forums. I can only assume they tackle problems more intelligently, like asking a trusted source they know personally, or using things like Google.&lt;br /&gt;&lt;br /&gt;End sidebar.&lt;br /&gt;&lt;br /&gt;Anyway, I was as familiar as most people with how Roman numerals worked, namely numbers less than 40 made sense, then they get strange with the Ls, Cs, Ds, and Ms. So, I did a little research to fill in my knowledge gap. As it turns out, the concept is pretty straightforward, and revolves around powers of 10. For each power of 10, there are 4 cases: 1-3, 4, 5-8, and 9. Observe:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&amp;nbsp; 1 = I     4 = IV   5 = V      9 = IX&lt;br /&gt;  2 = II             6 = VI  &lt;br /&gt;  3 = III            7 = VII &lt;br /&gt;                     8 = VIII&lt;br /&gt;           &lt;br /&gt; 10 = X    40 = XL  50 = L     90 = XC&lt;br /&gt; 20 = XX            60 = LX  &lt;br /&gt; 30 = XXX           70 = LXX &lt;br /&gt;                    80 = LXXX&lt;br /&gt;          &lt;br /&gt;100 = C   400 = CD 500 = D    900 = CM         &lt;br /&gt;200 = CC           600 = DC  &lt;br /&gt;300 = CCC          700 = DCC &lt;br /&gt;                   800 = DCCC&lt;/pre&gt;&lt;br /&gt;Not so daunting, after all. These can be pieced together to build any number under 1000. For numbers between 1000 and 3999, just prepend with one M for every thousand. After that it gets weird with overscores, where a line over a letter means its value is multiplied by 1000. There seems to be little support for fonts with overscores, so I stuck with numbers under 4000.&lt;br /&gt;&lt;br /&gt;I tackled conversion without using any fancy coding constructs, instead just walking an input number down to 0 while building up the Roman numeral string:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;var s = "";&lt;br /&gt;while (num &amp;gt;= 1000) { num -= 1000; s +=  "M"; }&lt;br /&gt;if    (num &amp;gt;=  900) { num -=  900; s += "CM"; }&lt;br /&gt;if    (num &amp;gt;=  500) { num -=  500; s +=  "D"; }&lt;br /&gt;if    (num &amp;gt;=  400) { num -=  400; s += "CD"; }&lt;br /&gt;while (num &amp;gt;=  100) { num -=  100; s +=  "C"; }&lt;br /&gt;if    (num &amp;gt;=   90) { num -=   90; s += "XC"; }&lt;br /&gt;if    (num &amp;gt;=   50) { num -=   50; s +=  "L"; }&lt;br /&gt;if    (num &amp;gt;=   40) { num -=   40; s += "XL"; }&lt;br /&gt;while (num &amp;gt;=   10) { num -=   10; s +=  "X"; }&lt;br /&gt;if    (num &amp;gt;=    9) { num -=    9; s += "IX"; }&lt;br /&gt;if    (num &amp;gt;=    5) { num -=    5; s +=  "V"; }&lt;br /&gt;if    (num &amp;gt;=    4) { num -=    4; s += "IV"; }&lt;br /&gt;while (num &amp;gt;=    1) { num -=    1; s +=  "I"; }&lt;br /&gt;return s;&lt;/pre&gt;&lt;br /&gt;Try it out:&lt;script&gt;function getRomanNumeral(num) {  if(num &lt;= 0 || num &gt; 3999) {    alert("Number must be between 1 and 3999");    return;  }  var s = "";  while (num &gt;= 1000) { num -= 1000; s +=  "M"; }  if    (num &gt;=  900) { num -=  900; s += "CM"; }  if    (num &gt;=  500) { num -=  500; s +=  "D"; }  if    (num &gt;=  400) { num -=  400; s += "CD"; }  while (num &gt;=  100) { num -=  100; s +=  "C"; }  if    (num &gt;=   90) { num -=   90; s += "XC"; }  if    (num &gt;=   50) { num -=   50; s +=  "L"; }  if    (num &gt;=   40) { num -=   40; s += "XL"; }  while (num &gt;=   10) { num -=   10; s +=  "X"; }  if    (num &gt;=    9) { num -=    9; s += "IX"; }  if    (num &gt;=    5) { num -=    5; s +=  "V"; }  if    (num &gt;=    4) { num -=    4; s += "IV"; }  while (num &gt;=    1) { num -=    1; s +=  "I"; }  return s;}function getSingle() {  var retval = getRomanNumeral(document.getElementById("romanIn").value);  document.getElementById("romanOut").innerHTML = retval;}&lt;/script&gt;&lt;br /&gt;&lt;style&gt;td { padding-right=10px; }&lt;/style&gt;&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;td&gt;Enter a number between 1 and 3999: &lt;/td&gt;&lt;td&gt;&lt;input type=text size=15 id=romanIn&gt;&lt;/td&gt;&lt;td&gt;&lt;input type=button onclick=getSingle() value="Convert"&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td valign=top style=text-align:right;&gt;Roman numeral:&lt;/td&gt;&lt;td&gt;&lt;span id=romanOut&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;Also, there aren't any good lists of Roman numeral sequences on the Internet. They either stop at 100 and explain continuation rules, or are space-delimited with no associated Arabic numbers, or use the HTML "ordered list" trick, where you can bullet-point list items with Roman numerals that, sadly, can't be copied to your clipboard.&lt;br /&gt;&lt;br /&gt;To correct that oversight, here is a simple, copyable, well-formatted list of Roman numerals between 1 and 3999:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&amp;nbsp;  1 = I&lt;br /&gt;   2 = II&lt;br /&gt;   3 = III&lt;br /&gt;   4 = IV&lt;br /&gt;   5 = V&lt;br /&gt;   6 = VI&lt;br /&gt;   7 = VII&lt;br /&gt;   8 = VIII&lt;br /&gt;   9 = IX&lt;br /&gt;  10 = X&lt;br /&gt;  11 = XI&lt;br /&gt;  12 = XII&lt;br /&gt;  13 = XIII&lt;br /&gt;  14 = XIV&lt;br /&gt;  15 = XV&lt;br /&gt;  16 = XVI&lt;br /&gt;  17 = XVII&lt;br /&gt;  18 = XVIII&lt;br /&gt;  19 = XIX&lt;br /&gt;  20 = XX&lt;br /&gt;  21 = XXI&lt;br /&gt;  22 = XXII&lt;br /&gt;  23 = XXIII&lt;br /&gt;  24 = XXIV&lt;br /&gt;  25 = XXV&lt;br /&gt;  26 = XXVI&lt;br /&gt;  27 = XXVII&lt;br /&gt;  28 = XXVIII&lt;br /&gt;  29 = XXIX&lt;br /&gt;  30 = XXX&lt;br /&gt;  31 = XXXI&lt;br /&gt;  32 = XXXII&lt;br /&gt;  33 = XXXIII&lt;br /&gt;  34 = XXXIV&lt;br /&gt;  35 = XXXV&lt;br /&gt;  36 = XXXVI&lt;br /&gt;  37 = XXXVII&lt;br /&gt;  38 = XXXVIII&lt;br /&gt;  39 = XXXIX&lt;br /&gt;  40 = XL&lt;br /&gt;  41 = XLI&lt;br /&gt;  42 = XLII&lt;br /&gt;  43 = XLIII&lt;br /&gt;  44 = XLIV&lt;br /&gt;  45 = XLV&lt;br /&gt;  46 = XLVI&lt;br /&gt;  47 = XLVII&lt;br /&gt;  48 = XLVIII&lt;br /&gt;  49 = XLIX&lt;br /&gt;  50 = L&lt;br /&gt;  51 = LI&lt;br /&gt;  52 = LII&lt;br /&gt;  53 = LIII&lt;br /&gt;  54 = LIV&lt;br /&gt;  55 = LV&lt;br /&gt;  56 = LVI&lt;br /&gt;  57 = LVII&lt;br /&gt;  58 = LVIII&lt;br /&gt;  59 = LIX&lt;br /&gt;  60 = LX&lt;br /&gt;  61 = LXI&lt;br /&gt;  62 = LXII&lt;br /&gt;  63 = LXIII&lt;br /&gt;  64 = LXIV&lt;br /&gt;  65 = LXV&lt;br /&gt;  66 = LXVI&lt;br /&gt;  67 = LXVII&lt;br /&gt;  68 = LXVIII&lt;br /&gt;  69 = LXIX&lt;br /&gt;  70 = LXX&lt;br /&gt;  71 = LXXI&lt;br /&gt;  72 = LXXII&lt;br /&gt;  73 = LXXIII&lt;br /&gt;  74 = LXXIV&lt;br /&gt;  75 = LXXV&lt;br /&gt;  76 = LXXVI&lt;br /&gt;  77 = LXXVII&lt;br /&gt;  78 = LXXVIII&lt;br /&gt;  79 = LXXIX&lt;br /&gt;  80 = LXXX&lt;br /&gt;  81 = LXXXI&lt;br /&gt;  82 = LXXXII&lt;br /&gt;  83 = LXXXIII&lt;br /&gt;  84 = LXXXIV&lt;br /&gt;  85 = LXXXV&lt;br /&gt;  86 = LXXXVI&lt;br /&gt;  87 = LXXXVII&lt;br /&gt;  88 = LXXXVIII&lt;br /&gt;  89 = LXXXIX&lt;br /&gt;  90 = XC&lt;br /&gt;  91 = XCI&lt;br /&gt;  92 = XCII&lt;br /&gt;  93 = XCIII&lt;br /&gt;  94 = XCIV&lt;br /&gt;  95 = XCV&lt;br /&gt;  96 = XCVI&lt;br /&gt;  97 = XCVII&lt;br /&gt;  98 = XCVIII&lt;br /&gt;  99 = XCIX&lt;br /&gt; 100 = C&lt;br /&gt; 101 = CI&lt;br /&gt; 102 = CII&lt;br /&gt; 103 = CIII&lt;br /&gt; 104 = CIV&lt;br /&gt; 105 = CV&lt;br /&gt; 106 = CVI&lt;br /&gt; 107 = CVII&lt;br /&gt; 108 = CVIII&lt;br /&gt; 109 = CIX&lt;br /&gt; 110 = CX&lt;br /&gt; 111 = CXI&lt;br /&gt; 112 = CXII&lt;br /&gt; 113 = CXIII&lt;br /&gt; 114 = CXIV&lt;br /&gt; 115 = CXV&lt;br /&gt; 116 = CXVI&lt;br /&gt; 117 = CXVII&lt;br /&gt; 118 = CXVIII&lt;br /&gt; 119 = CXIX&lt;br /&gt; 120 = CXX&lt;br /&gt; 121 = CXXI&lt;br /&gt; 122 = CXXII&lt;br /&gt; 123 = CXXIII&lt;br /&gt; 124 = CXXIV&lt;br /&gt; 125 = CXXV&lt;br /&gt; 126 = CXXVI&lt;br /&gt; 127 = CXXVII&lt;br /&gt; 128 = CXXVIII&lt;br /&gt; 129 = CXXIX&lt;br /&gt; 130 = CXXX&lt;br /&gt; 131 = CXXXI&lt;br /&gt; 132 = CXXXII&lt;br /&gt; 133 = CXXXIII&lt;br /&gt; 134 = CXXXIV&lt;br /&gt; 135 = CXXXV&lt;br /&gt; 136 = CXXXVI&lt;br /&gt; 137 = CXXXVII&lt;br /&gt; 138 = CXXXVIII&lt;br /&gt; 139 = CXXXIX&lt;br /&gt; 140 = CXL&lt;br /&gt; 141 = CXLI&lt;br /&gt; 142 = CXLII&lt;br /&gt; 143 = CXLIII&lt;br /&gt; 144 = CXLIV&lt;br /&gt; 145 = CXLV&lt;br /&gt; 146 = CXLVI&lt;br /&gt; 147 = CXLVII&lt;br /&gt; 148 = CXLVIII&lt;br /&gt; 149 = CXLIX&lt;br /&gt; 150 = CL&lt;br /&gt; 151 = CLI&lt;br /&gt; 152 = CLII&lt;br /&gt; 153 = CLIII&lt;br /&gt; 154 = CLIV&lt;br /&gt; 155 = CLV&lt;br /&gt; 156 = CLVI&lt;br /&gt; 157 = CLVII&lt;br /&gt; 158 = CLVIII&lt;br /&gt; 159 = CLIX&lt;br /&gt; 160 = CLX&lt;br /&gt; 161 = CLXI&lt;br /&gt; 162 = CLXII&lt;br /&gt; 163 = CLXIII&lt;br /&gt; 164 = CLXIV&lt;br /&gt; 165 = CLXV&lt;br /&gt; 166 = CLXVI&lt;br /&gt; 167 = CLXVII&lt;br /&gt; 168 = CLXVIII&lt;br /&gt; 169 = CLXIX&lt;br /&gt; 170 = CLXX&lt;br /&gt; 171 = CLXXI&lt;br /&gt; 172 = CLXXII&lt;br /&gt; 173 = CLXXIII&lt;br /&gt; 174 = CLXXIV&lt;br /&gt; 175 = CLXXV&lt;br /&gt; 176 = CLXXVI&lt;br /&gt; 177 = CLXXVII&lt;br /&gt; 178 = CLXXVIII&lt;br /&gt; 179 = CLXXIX&lt;br /&gt; 180 = CLXXX&lt;br /&gt; 181 = CLXXXI&lt;br /&gt; 182 = CLXXXII&lt;br /&gt; 183 = CLXXXIII&lt;br /&gt; 184 = CLXXXIV&lt;br /&gt; 185 = CLXXXV&lt;br /&gt; 186 = CLXXXVI&lt;br /&gt; 187 = CLXXXVII&lt;br /&gt; 188 = CLXXXVIII&lt;br /&gt; 189 = CLXXXIX&lt;br /&gt; 190 = CXC&lt;br /&gt; 191 = CXCI&lt;br /&gt; 192 = CXCII&lt;br /&gt; 193 = CXCIII&lt;br /&gt; 194 = CXCIV&lt;br /&gt; 195 = CXCV&lt;br /&gt; 196 = CXCVI&lt;br /&gt; 197 = CXCVII&lt;br /&gt; 198 = CXCVIII&lt;br /&gt; 199 = CXCIX&lt;br /&gt; 200 = CC&lt;br /&gt; 201 = CCI&lt;br /&gt; 202 = CCII&lt;br /&gt; 203 = CCIII&lt;br /&gt; 204 = CCIV&lt;br /&gt; 205 = CCV&lt;br /&gt; 206 = CCVI&lt;br /&gt; 207 = CCVII&lt;br /&gt; 208 = CCVIII&lt;br /&gt; 209 = CCIX&lt;br /&gt; 210 = CCX&lt;br /&gt; 211 = CCXI&lt;br /&gt; 212 = CCXII&lt;br /&gt; 213 = CCXIII&lt;br /&gt; 214 = CCXIV&lt;br /&gt; 215 = CCXV&lt;br /&gt; 216 = CCXVI&lt;br /&gt; 217 = CCXVII&lt;br /&gt; 218 = CCXVIII&lt;br /&gt; 219 = CCXIX&lt;br /&gt; 220 = CCXX&lt;br /&gt; 221 = CCXXI&lt;br /&gt; 222 = CCXXII&lt;br /&gt; 223 = CCXXIII&lt;br /&gt; 224 = CCXXIV&lt;br /&gt; 225 = CCXXV&lt;br /&gt; 226 = CCXXVI&lt;br /&gt; 227 = CCXXVII&lt;br /&gt; 228 = CCXXVIII&lt;br /&gt; 229 = CCXXIX&lt;br /&gt; 230 = CCXXX&lt;br /&gt; 231 = CCXXXI&lt;br /&gt; 232 = CCXXXII&lt;br /&gt; 233 = CCXXXIII&lt;br /&gt; 234 = CCXXXIV&lt;br /&gt; 235 = CCXXXV&lt;br /&gt; 236 = CCXXXVI&lt;br /&gt; 237 = CCXXXVII&lt;br /&gt; 238 = CCXXXVIII&lt;br /&gt; 239 = CCXXXIX&lt;br /&gt; 240 = CCXL&lt;br /&gt; 241 = CCXLI&lt;br /&gt; 242 = CCXLII&lt;br /&gt; 243 = CCXLIII&lt;br /&gt; 244 = CCXLIV&lt;br /&gt; 245 = CCXLV&lt;br /&gt; 246 = CCXLVI&lt;br /&gt; 247 = CCXLVII&lt;br /&gt; 248 = CCXLVIII&lt;br /&gt; 249 = CCXLIX&lt;br /&gt; 250 = CCL&lt;br /&gt; 251 = CCLI&lt;br /&gt; 252 = CCLII&lt;br /&gt; 253 = CCLIII&lt;br /&gt; 254 = CCLIV&lt;br /&gt; 255 = CCLV&lt;br /&gt; 256 = CCLVI&lt;br /&gt; 257 = CCLVII&lt;br /&gt; 258 = CCLVIII&lt;br /&gt; 259 = CCLIX&lt;br /&gt; 260 = CCLX&lt;br /&gt; 261 = CCLXI&lt;br /&gt; 262 = CCLXII&lt;br /&gt; 263 = CCLXIII&lt;br /&gt; 264 = CCLXIV&lt;br /&gt; 265 = CCLXV&lt;br /&gt; 266 = CCLXVI&lt;br /&gt; 267 = CCLXVII&lt;br /&gt; 268 = CCLXVIII&lt;br /&gt; 269 = CCLXIX&lt;br /&gt; 270 = CCLXX&lt;br /&gt; 271 = CCLXXI&lt;br /&gt; 272 = CCLXXII&lt;br /&gt; 273 = CCLXXIII&lt;br /&gt; 274 = CCLXXIV&lt;br /&gt; 275 = CCLXXV&lt;br /&gt; 276 = CCLXXVI&lt;br /&gt; 277 = CCLXXVII&lt;br /&gt; 278 = CCLXXVIII&lt;br /&gt; 279 = CCLXXIX&lt;br /&gt; 280 = CCLXXX&lt;br /&gt; 281 = CCLXXXI&lt;br /&gt; 282 = CCLXXXII&lt;br /&gt; 283 = CCLXXXIII&lt;br /&gt; 284 = CCLXXXIV&lt;br /&gt; 285 = CCLXXXV&lt;br /&gt; 286 = CCLXXXVI&lt;br /&gt; 287 = CCLXXXVII&lt;br /&gt; 288 = CCLXXXVIII&lt;br /&gt; 289 = CCLXXXIX&lt;br /&gt; 290 = CCXC&lt;br /&gt; 291 = CCXCI&lt;br /&gt; 292 = CCXCII&lt;br /&gt; 293 = CCXCIII&lt;br /&gt; 294 = CCXCIV&lt;br /&gt; 295 = CCXCV&lt;br /&gt; 296 = CCXCVI&lt;br /&gt; 297 = CCXCVII&lt;br /&gt; 298 = CCXCVIII&lt;br /&gt; 299 = CCXCIX&lt;br /&gt; 300 = CCC&lt;br /&gt; 301 = CCCI&lt;br /&gt; 302 = CCCII&lt;br /&gt; 303 = CCCIII&lt;br /&gt; 304 = CCCIV&lt;br /&gt; 305 = CCCV&lt;br /&gt; 306 = CCCVI&lt;br /&gt; 307 = CCCVII&lt;br /&gt; 308 = CCCVIII&lt;br /&gt; 309 = CCCIX&lt;br /&gt; 310 = CCCX&lt;br /&gt; 311 = CCCXI&lt;br /&gt; 312 = CCCXII&lt;br /&gt; 313 = CCCXIII&lt;br /&gt; 314 = CCCXIV&lt;br /&gt; 315 = CCCXV&lt;br /&gt; 316 = CCCXVI&lt;br /&gt; 317 = CCCXVII&lt;br /&gt; 318 = CCCXVIII&lt;br /&gt; 319 = CCCXIX&lt;br /&gt; 320 = CCCXX&lt;br /&gt; 321 = CCCXXI&lt;br /&gt; 322 = CCCXXII&lt;br /&gt; 323 = CCCXXIII&lt;br /&gt; 324 = CCCXXIV&lt;br /&gt; 325 = CCCXXV&lt;br /&gt; 326 = CCCXXVI&lt;br /&gt; 327 = CCCXXVII&lt;br /&gt; 328 = CCCXXVIII&lt;br /&gt; 329 = CCCXXIX&lt;br /&gt; 330 = CCCXXX&lt;br /&gt; 331 = CCCXXXI&lt;br /&gt; 332 = CCCXXXII&lt;br /&gt; 333 = CCCXXXIII&lt;br /&gt; 334 = CCCXXXIV&lt;br /&gt; 335 = CCCXXXV&lt;br /&gt; 336 = CCCXXXVI&lt;br /&gt; 337 = CCCXXXVII&lt;br /&gt; 338 = CCCXXXVIII&lt;br /&gt; 339 = CCCXXXIX&lt;br /&gt; 340 = CCCXL&lt;br /&gt; 341 = CCCXLI&lt;br /&gt; 342 = CCCXLII&lt;br /&gt; 343 = CCCXLIII&lt;br /&gt; 344 = CCCXLIV&lt;br /&gt; 345 = CCCXLV&lt;br /&gt; 346 = CCCXLVI&lt;br /&gt; 347 = CCCXLVII&lt;br /&gt; 348 = CCCXLVIII&lt;br /&gt; 349 = CCCXLIX&lt;br /&gt; 350 = CCCL&lt;br /&gt; 351 = CCCLI&lt;br /&gt; 352 = CCCLII&lt;br /&gt; 353 = CCCLIII&lt;br /&gt; 354 = CCCLIV&lt;br /&gt; 355 = CCCLV&lt;br /&gt; 356 = CCCLVI&lt;br /&gt; 357 = CCCLVII&lt;br /&gt; 358 = CCCLVIII&lt;br /&gt; 359 = CCCLIX&lt;br /&gt; 360 = CCCLX&lt;br /&gt; 361 = CCCLXI&lt;br /&gt; 362 = CCCLXII&lt;br /&gt; 363 = CCCLXIII&lt;br /&gt; 364 = CCCLXIV&lt;br /&gt; 365 = CCCLXV&lt;br /&gt; 366 = CCCLXVI&lt;br /&gt; 367 = CCCLXVII&lt;br /&gt; 368 = CCCLXVIII&lt;br /&gt; 369 = CCCLXIX&lt;br /&gt; 370 = CCCLXX&lt;br /&gt; 371 = CCCLXXI&lt;br /&gt; 372 = CCCLXXII&lt;br /&gt; 373 = CCCLXXIII&lt;br /&gt; 374 = CCCLXXIV&lt;br /&gt; 375 = CCCLXXV&lt;br /&gt; 376 = CCCLXXVI&lt;br /&gt; 377 = CCCLXXVII&lt;br /&gt; 378 = CCCLXXVIII&lt;br /&gt; 379 = CCCLXXIX&lt;br /&gt; 380 = CCCLXXX&lt;br /&gt; 381 = CCCLXXXI&lt;br /&gt; 382 = CCCLXXXII&lt;br /&gt; 383 = CCCLXXXIII&lt;br /&gt; 384 = CCCLXXXIV&lt;br /&gt; 385 = CCCLXXXV&lt;br /&gt; 386 = CCCLXXXVI&lt;br /&gt; 387 = CCCLXXXVII&lt;br /&gt; 388 = CCCLXXXVIII&lt;br /&gt; 389 = CCCLXXXIX&lt;br /&gt; 390 = CCCXC&lt;br /&gt; 391 = CCCXCI&lt;br /&gt; 392 = CCCXCII&lt;br /&gt; 393 = CCCXCIII&lt;br /&gt; 394 = CCCXCIV&lt;br /&gt; 395 = CCCXCV&lt;br /&gt; 396 = CCCXCVI&lt;br /&gt; 397 = CCCXCVII&lt;br /&gt; 398 = CCCXCVIII&lt;br /&gt; 399 = CCCXCIX&lt;br /&gt; 400 = CD&lt;br /&gt; 401 = CDI&lt;br /&gt; 402 = CDII&lt;br /&gt; 403 = CDIII&lt;br /&gt; 404 = CDIV&lt;br /&gt; 405 = CDV&lt;br /&gt; 406 = CDVI&lt;br /&gt; 407 = CDVII&lt;br /&gt; 408 = CDVIII&lt;br /&gt; 409 = CDIX&lt;br /&gt; 410 = CDX&lt;br /&gt; 411 = CDXI&lt;br /&gt; 412 = CDXII&lt;br /&gt; 413 = CDXIII&lt;br /&gt; 414 = CDXIV&lt;br /&gt; 415 = CDXV&lt;br /&gt; 416 = CDXVI&lt;br /&gt; 417 = CDXVII&lt;br /&gt; 418 = CDXVIII&lt;br /&gt; 419 = CDXIX&lt;br /&gt; 420 = CDXX&lt;br /&gt; 421 = CDXXI&lt;br /&gt; 422 = CDXXII&lt;br /&gt; 423 = CDXXIII&lt;br /&gt; 424 = CDXXIV&lt;br /&gt; 425 = CDXXV&lt;br /&gt; 426 = CDXXVI&lt;br /&gt; 427 = CDXXVII&lt;br /&gt; 428 = CDXXVIII&lt;br /&gt; 429 = CDXXIX&lt;br /&gt; 430 = CDXXX&lt;br /&gt; 431 = CDXXXI&lt;br /&gt; 432 = CDXXXII&lt;br /&gt; 433 = CDXXXIII&lt;br /&gt; 434 = CDXXXIV&lt;br /&gt; 435 = CDXXXV&lt;br /&gt; 436 = CDXXXVI&lt;br /&gt; 437 = CDXXXVII&lt;br /&gt; 438 = CDXXXVIII&lt;br /&gt; 439 = CDXXXIX&lt;br /&gt; 440 = CDXL&lt;br /&gt; 441 = CDXLI&lt;br /&gt; 442 = CDXLII&lt;br /&gt; 443 = CDXLIII&lt;br /&gt; 444 = CDXLIV&lt;br /&gt; 445 = CDXLV&lt;br /&gt; 446 = CDXLVI&lt;br /&gt; 447 = CDXLVII&lt;br /&gt; 448 = CDXLVIII&lt;br /&gt; 449 = CDXLIX&lt;br /&gt; 450 = CDL&lt;br /&gt; 451 = CDLI&lt;br /&gt; 452 = CDLII&lt;br /&gt; 453 = CDLIII&lt;br /&gt; 454 = CDLIV&lt;br /&gt; 455 = CDLV&lt;br /&gt; 456 = CDLVI&lt;br /&gt; 457 = CDLVII&lt;br /&gt; 458 = CDLVIII&lt;br /&gt; 459 = CDLIX&lt;br /&gt; 460 = CDLX&lt;br /&gt; 461 = CDLXI&lt;br /&gt; 462 = CDLXII&lt;br /&gt; 463 = CDLXIII&lt;br /&gt; 464 = CDLXIV&lt;br /&gt; 465 = CDLXV&lt;br /&gt; 466 = CDLXVI&lt;br /&gt; 467 = CDLXVII&lt;br /&gt; 468 = CDLXVIII&lt;br /&gt; 469 = CDLXIX&lt;br /&gt; 470 = CDLXX&lt;br /&gt; 471 = CDLXXI&lt;br /&gt; 472 = CDLXXII&lt;br /&gt; 473 = CDLXXIII&lt;br /&gt; 474 = CDLXXIV&lt;br /&gt; 475 = CDLXXV&lt;br /&gt; 476 = CDLXXVI&lt;br /&gt; 477 = CDLXXVII&lt;br /&gt; 478 = CDLXXVIII&lt;br /&gt; 479 = CDLXXIX&lt;br /&gt; 480 = CDLXXX&lt;br /&gt; 481 = CDLXXXI&lt;br /&gt; 482 = CDLXXXII&lt;br /&gt; 483 = CDLXXXIII&lt;br /&gt; 484 = CDLXXXIV&lt;br /&gt; 485 = CDLXXXV&lt;br /&gt; 486 = CDLXXXVI&lt;br /&gt; 487 = CDLXXXVII&lt;br /&gt; 488 = CDLXXXVIII&lt;br /&gt; 489 = CDLXXXIX&lt;br /&gt; 490 = CDXC&lt;br /&gt; 491 = CDXCI&lt;br /&gt; 492 = CDXCII&lt;br /&gt; 493 = CDXCIII&lt;br /&gt; 494 = CDXCIV&lt;br /&gt; 495 = CDXCV&lt;br /&gt; 496 = CDXCVI&lt;br /&gt; 497 = CDXCVII&lt;br /&gt; 498 = CDXCVIII&lt;br /&gt; 499 = CDXCIX&lt;br /&gt; 500 = D&lt;br /&gt; 501 = DI&lt;br /&gt; 502 = DII&lt;br /&gt; 503 = DIII&lt;br /&gt; 504 = DIV&lt;br /&gt; 505 = DV&lt;br /&gt; 506 = DVI&lt;br /&gt; 507 = DVII&lt;br /&gt; 508 = DVIII&lt;br /&gt; 509 = DIX&lt;br /&gt; 510 = DX&lt;br /&gt; 511 = DXI&lt;br /&gt; 512 = DXII&lt;br /&gt; 513 = DXIII&lt;br /&gt; 514 = DXIV&lt;br /&gt; 515 = DXV&lt;br /&gt; 516 = DXVI&lt;br /&gt; 517 = DXVII&lt;br /&gt; 518 = DXVIII&lt;br /&gt; 519 = DXIX&lt;br /&gt; 520 = DXX&lt;br /&gt; 521 = DXXI&lt;br /&gt; 522 = DXXII&lt;br /&gt; 523 = DXXIII&lt;br /&gt; 524 = DXXIV&lt;br /&gt; 525 = DXXV&lt;br /&gt; 526 = DXXVI&lt;br /&gt; 527 = DXXVII&lt;br /&gt; 528 = DXXVIII&lt;br /&gt; 529 = DXXIX&lt;br /&gt; 530 = DXXX&lt;br /&gt; 531 = DXXXI&lt;br /&gt; 532 = DXXXII&lt;br /&gt; 533 = DXXXIII&lt;br /&gt; 534 = DXXXIV&lt;br /&gt; 535 = DXXXV&lt;br /&gt; 536 = DXXXVI&lt;br /&gt; 537 = DXXXVII&lt;br /&gt; 538 = DXXXVIII&lt;br /&gt; 539 = DXXXIX&lt;br /&gt; 540 = DXL&lt;br /&gt; 541 = DXLI&lt;br /&gt; 542 = DXLII&lt;br /&gt; 543 = DXLIII&lt;br /&gt; 544 = DXLIV&lt;br /&gt; 545 = DXLV&lt;br /&gt; 546 = DXLVI&lt;br /&gt; 547 = DXLVII&lt;br /&gt; 548 = DXLVIII&lt;br /&gt; 549 = DXLIX&lt;br /&gt; 550 = DL&lt;br /&gt; 551 = DLI&lt;br /&gt; 552 = DLII&lt;br /&gt; 553 = DLIII&lt;br /&gt; 554 = DLIV&lt;br /&gt; 555 = DLV&lt;br /&gt; 556 = DLVI&lt;br /&gt; 557 = DLVII&lt;br /&gt; 558 = DLVIII&lt;br /&gt; 559 = DLIX&lt;br /&gt; 560 = DLX&lt;br /&gt; 561 = DLXI&lt;br /&gt; 562 = DLXII&lt;br /&gt; 563 = DLXIII&lt;br /&gt; 564 = DLXIV&lt;br /&gt; 565 = DLXV&lt;br /&gt; 566 = DLXVI&lt;br /&gt; 567 = DLXVII&lt;br /&gt; 568 = DLXVIII&lt;br /&gt; 569 = DLXIX&lt;br /&gt; 570 = DLXX&lt;br /&gt; 571 = DLXXI&lt;br /&gt; 572 = DLXXII&lt;br /&gt; 573 = DLXXIII&lt;br /&gt; 574 = DLXXIV&lt;br /&gt; 575 = DLXXV&lt;br /&gt; 576 = DLXXVI&lt;br /&gt; 577 = DLXXVII&lt;br /&gt; 578 = DLXXVIII&lt;br /&gt; 579 = DLXXIX&lt;br /&gt; 580 = DLXXX&lt;br /&gt; 581 = DLXXXI&lt;br /&gt; 582 = DLXXXII&lt;br /&gt; 583 = DLXXXIII&lt;br /&gt; 584 = DLXXXIV&lt;br /&gt; 585 = DLXXXV&lt;br /&gt; 586 = DLXXXVI&lt;br /&gt; 587 = DLXXXVII&lt;br /&gt; 588 = DLXXXVIII&lt;br /&gt; 589 = DLXXXIX&lt;br /&gt; 590 = DXC&lt;br /&gt; 591 = DXCI&lt;br /&gt; 592 = DXCII&lt;br /&gt; 593 = DXCIII&lt;br /&gt; 594 = DXCIV&lt;br /&gt; 595 = DXCV&lt;br /&gt; 596 = DXCVI&lt;br /&gt; 597 = DXCVII&lt;br /&gt; 598 = DXCVIII&lt;br /&gt; 599 = DXCIX&lt;br /&gt; 600 = DC&lt;br /&gt; 601 = DCI&lt;br /&gt; 602 = DCII&lt;br /&gt; 603 = DCIII&lt;br /&gt; 604 = DCIV&lt;br /&gt; 605 = DCV&lt;br /&gt; 606 = DCVI&lt;br /&gt; 607 = DCVII&lt;br /&gt; 608 = DCVIII&lt;br /&gt; 609 = DCIX&lt;br /&gt; 610 = DCX&lt;br /&gt; 611 = DCXI&lt;br /&gt; 612 = DCXII&lt;br /&gt; 613 = DCXIII&lt;br /&gt; 614 = DCXIV&lt;br /&gt; 615 = DCXV&lt;br /&gt; 616 = DCXVI&lt;br /&gt; 617 = DCXVII&lt;br /&gt; 618 = DCXVIII&lt;br /&gt; 619 = DCXIX&lt;br /&gt; 620 = DCXX&lt;br /&gt; 621 = DCXXI&lt;br /&gt; 622 = DCXXII&lt;br /&gt; 623 = DCXXIII&lt;br /&gt; 624 = DCXXIV&lt;br /&gt; 625 = DCXXV&lt;br /&gt; 626 = DCXXVI&lt;br /&gt; 627 = DCXXVII&lt;br /&gt; 628 = DCXXVIII&lt;br /&gt; 629 = DCXXIX&lt;br /&gt; 630 = DCXXX&lt;br /&gt; 631 = DCXXXI&lt;br /&gt; 632 = DCXXXII&lt;br /&gt; 633 = DCXXXIII&lt;br /&gt; 634 = DCXXXIV&lt;br /&gt; 635 = DCXXXV&lt;br /&gt; 636 = DCXXXVI&lt;br /&gt; 637 = DCXXXVII&lt;br /&gt; 638 = DCXXXVIII&lt;br /&gt; 639 = DCXXXIX&lt;br /&gt; 640 = DCXL&lt;br /&gt; 641 = DCXLI&lt;br /&gt; 642 = DCXLII&lt;br /&gt; 643 = DCXLIII&lt;br /&gt; 644 = DCXLIV&lt;br /&gt; 645 = DCXLV&lt;br /&gt; 646 = DCXLVI&lt;br /&gt; 647 = DCXLVII&lt;br /&gt; 648 = DCXLVIII&lt;br /&gt; 649 = DCXLIX&lt;br /&gt; 650 = DCL&lt;br /&gt; 651 = DCLI&lt;br /&gt; 652 = DCLII&lt;br /&gt; 653 = DCLIII&lt;br /&gt; 654 = DCLIV&lt;br /&gt; 655 = DCLV&lt;br /&gt; 656 = DCLVI&lt;br /&gt; 657 = DCLVII&lt;br /&gt; 658 = DCLVIII&lt;br /&gt; 659 = DCLIX&lt;br /&gt; 660 = DCLX&lt;br /&gt; 661 = DCLXI&lt;br /&gt; 662 = DCLXII&lt;br /&gt; 663 = DCLXIII&lt;br /&gt; 664 = DCLXIV&lt;br /&gt; 665 = DCLXV&lt;br /&gt; 666 = DCLXVI&lt;br /&gt; 667 = DCLXVII&lt;br /&gt; 668 = DCLXVIII&lt;br /&gt; 669 = DCLXIX&lt;br /&gt; 670 = DCLXX&lt;br /&gt; 671 = DCLXXI&lt;br /&gt; 672 = DCLXXII&lt;br /&gt; 673 = DCLXXIII&lt;br /&gt; 674 = DCLXXIV&lt;br /&gt; 675 = DCLXXV&lt;br /&gt; 676 = DCLXXVI&lt;br /&gt; 677 = DCLXXVII&lt;br /&gt; 678 = DCLXXVIII&lt;br /&gt; 679 = DCLXXIX&lt;br /&gt; 680 = DCLXXX&lt;br /&gt; 681 = DCLXXXI&lt;br /&gt; 682 = DCLXXXII&lt;br /&gt; 683 = DCLXXXIII&lt;br /&gt; 684 = DCLXXXIV&lt;br /&gt; 685 = DCLXXXV&lt;br /&gt; 686 = DCLXXXVI&lt;br /&gt; 687 = DCLXXXVII&lt;br /&gt; 688 = DCLXXXVIII&lt;br /&gt; 689 = DCLXXXIX&lt;br /&gt; 690 = DCXC&lt;br /&gt; 691 = DCXCI&lt;br /&gt; 692 = DCXCII&lt;br /&gt; 693 = DCXCIII&lt;br /&gt; 694 = DCXCIV&lt;br /&gt; 695 = DCXCV&lt;br /&gt; 696 = DCXCVI&lt;br /&gt; 697 = DCXCVII&lt;br /&gt; 698 = DCXCVIII&lt;br /&gt; 699 = DCXCIX&lt;br /&gt; 700 = DCC&lt;br /&gt; 701 = DCCI&lt;br /&gt; 702 = DCCII&lt;br /&gt; 703 = DCCIII&lt;br /&gt; 704 = DCCIV&lt;br /&gt; 705 = DCCV&lt;br /&gt; 706 = DCCVI&lt;br /&gt; 707 = DCCVII&lt;br /&gt; 708 = DCCVIII&lt;br /&gt; 709 = DCCIX&lt;br /&gt; 710 = DCCX&lt;br /&gt; 711 = DCCXI&lt;br /&gt; 712 = DCCXII&lt;br /&gt; 713 = DCCXIII&lt;br /&gt; 714 = DCCXIV&lt;br /&gt; 715 = DCCXV&lt;br /&gt; 716 = DCCXVI&lt;br /&gt; 717 = DCCXVII&lt;br /&gt; 718 = DCCXVIII&lt;br /&gt; 719 = DCCXIX&lt;br /&gt; 720 = DCCXX&lt;br /&gt; 721 = DCCXXI&lt;br /&gt; 722 = DCCXXII&lt;br /&gt; 723 = DCCXXIII&lt;br /&gt; 724 = DCCXXIV&lt;br /&gt; 725 = DCCXXV&lt;br /&gt; 726 = DCCXXVI&lt;br /&gt; 727 = DCCXXVII&lt;br /&gt; 728 = DCCXXVIII&lt;br /&gt; 729 = DCCXXIX&lt;br /&gt; 730 = DCCXXX&lt;br /&gt; 731 = DCCXXXI&lt;br /&gt; 732 = DCCXXXII&lt;br /&gt; 733 = DCCXXXIII&lt;br /&gt; 734 = DCCXXXIV&lt;br /&gt; 735 = DCCXXXV&lt;br /&gt; 736 = DCCXXXVI&lt;br /&gt; 737 = DCCXXXVII&lt;br /&gt; 738 = DCCXXXVIII&lt;br /&gt; 739 = DCCXXXIX&lt;br /&gt; 740 = DCCXL&lt;br /&gt; 741 = DCCXLI&lt;br /&gt; 742 = DCCXLII&lt;br /&gt; 743 = DCCXLIII&lt;br /&gt; 744 = DCCXLIV&lt;br /&gt; 745 = DCCXLV&lt;br /&gt; 746 = DCCXLVI&lt;br /&gt; 747 = DCCXLVII&lt;br /&gt; 748 = DCCXLVIII&lt;br /&gt; 749 = DCCXLIX&lt;br /&gt; 750 = DCCL&lt;br /&gt; 751 = DCCLI&lt;br /&gt; 752 = DCCLII&lt;br /&gt; 753 = DCCLIII&lt;br /&gt; 754 = DCCLIV&lt;br /&gt; 755 = DCCLV&lt;br /&gt; 756 = DCCLVI&lt;br /&gt; 757 = DCCLVII&lt;br /&gt; 758 = DCCLVIII&lt;br /&gt; 759 = DCCLIX&lt;br /&gt; 760 = DCCLX&lt;br /&gt; 761 = DCCLXI&lt;br /&gt; 762 = DCCLXII&lt;br /&gt; 763 = DCCLXIII&lt;br /&gt; 764 = DCCLXIV&lt;br /&gt; 765 = DCCLXV&lt;br /&gt; 766 = DCCLXVI&lt;br /&gt; 767 = DCCLXVII&lt;br /&gt; 768 = DCCLXVIII&lt;br /&gt; 769 = DCCLXIX&lt;br /&gt; 770 = DCCLXX&lt;br /&gt; 771 = DCCLXXI&lt;br /&gt; 772 = DCCLXXII&lt;br /&gt; 773 = DCCLXXIII&lt;br /&gt; 774 = DCCLXXIV&lt;br /&gt; 775 = DCCLXXV&lt;br /&gt; 776 = DCCLXXVI&lt;br /&gt; 777 = DCCLXXVII&lt;br /&gt; 778 = DCCLXXVIII&lt;br /&gt; 779 = DCCLXXIX&lt;br /&gt; 780 = DCCLXXX&lt;br /&gt; 781 = DCCLXXXI&lt;br /&gt; 782 = DCCLXXXII&lt;br /&gt; 783 = DCCLXXXIII&lt;br /&gt; 784 = DCCLXXXIV&lt;br /&gt; 785 = DCCLXXXV&lt;br /&gt; 786 = DCCLXXXVI&lt;br /&gt; 787 = DCCLXXXVII&lt;br /&gt; 788 = DCCLXXXVIII&lt;br /&gt; 789 = DCCLXXXIX&lt;br /&gt; 790 = DCCXC&lt;br /&gt; 791 = DCCXCI&lt;br /&gt; 792 = DCCXCII&lt;br /&gt; 793 = DCCXCIII&lt;br /&gt; 794 = DCCXCIV&lt;br /&gt; 795 = DCCXCV&lt;br /&gt; 796 = DCCXCVI&lt;br /&gt; 797 = DCCXCVII&lt;br /&gt; 798 = DCCXCVIII&lt;br /&gt; 799 = DCCXCIX&lt;br /&gt; 800 = DCCC&lt;br /&gt; 801 = DCCCI&lt;br /&gt; 802 = DCCCII&lt;br /&gt; 803 = DCCCIII&lt;br /&gt; 804 = DCCCIV&lt;br /&gt; 805 = DCCCV&lt;br /&gt; 806 = DCCCVI&lt;br /&gt; 807 = DCCCVII&lt;br /&gt; 808 = DCCCVIII&lt;br /&gt; 809 = DCCCIX&lt;br /&gt; 810 = DCCCX&lt;br /&gt; 811 = DCCCXI&lt;br /&gt; 812 = DCCCXII&lt;br /&gt; 813 = DCCCXIII&lt;br /&gt; 814 = DCCCXIV&lt;br /&gt; 815 = DCCCXV&lt;br /&gt; 816 = DCCCXVI&lt;br /&gt; 817 = DCCCXVII&lt;br /&gt; 818 = DCCCXVIII&lt;br /&gt; 819 = DCCCXIX&lt;br /&gt; 820 = DCCCXX&lt;br /&gt; 821 = DCCCXXI&lt;br /&gt; 822 = DCCCXXII&lt;br /&gt; 823 = DCCCXXIII&lt;br /&gt; 824 = DCCCXXIV&lt;br /&gt; 825 = DCCCXXV&lt;br /&gt; 826 = DCCCXXVI&lt;br /&gt; 827 = DCCCXXVII&lt;br /&gt; 828 = DCCCXXVIII&lt;br /&gt; 829 = DCCCXXIX&lt;br /&gt; 830 = DCCCXXX&lt;br /&gt; 831 = DCCCXXXI&lt;br /&gt; 832 = DCCCXXXII&lt;br /&gt; 833 = DCCCXXXIII&lt;br /&gt; 834 = DCCCXXXIV&lt;br /&gt; 835 = DCCCXXXV&lt;br /&gt; 836 = DCCCXXXVI&lt;br /&gt; 837 = DCCCXXXVII&lt;br /&gt; 838 = DCCCXXXVIII&lt;br /&gt; 839 = DCCCXXXIX&lt;br /&gt; 840 = DCCCXL&lt;br /&gt; 841 = DCCCXLI&lt;br /&gt; 842 = DCCCXLII&lt;br /&gt; 843 = DCCCXLIII&lt;br /&gt; 844 = DCCCXLIV&lt;br /&gt; 845 = DCCCXLV&lt;br /&gt; 846 = DCCCXLVI&lt;br /&gt; 847 = DCCCXLVII&lt;br /&gt; 848 = DCCCXLVIII&lt;br /&gt; 849 = DCCCXLIX&lt;br /&gt; 850 = DCCCL&lt;br /&gt; 851 = DCCCLI&lt;br /&gt; 852 = DCCCLII&lt;br /&gt; 853 = DCCCLIII&lt;br /&gt; 854 = DCCCLIV&lt;br /&gt; 855 = DCCCLV&lt;br /&gt; 856 = DCCCLVI&lt;br /&gt; 857 = DCCCLVII&lt;br /&gt; 858 = DCCCLVIII&lt;br /&gt; 859 = DCCCLIX&lt;br /&gt; 860 = DCCCLX&lt;br /&gt; 861 = DCCCLXI&lt;br /&gt; 862 = DCCCLXII&lt;br /&gt; 863 = DCCCLXIII&lt;br /&gt; 864 = DCCCLXIV&lt;br /&gt; 865 = DCCCLXV&lt;br /&gt; 866 = DCCCLXVI&lt;br /&gt; 867 = DCCCLXVII&lt;br /&gt; 868 = DCCCLXVIII&lt;br /&gt; 869 = DCCCLXIX&lt;br /&gt; 870 = DCCCLXX&lt;br /&gt; 871 = DCCCLXXI&lt;br /&gt; 872 = DCCCLXXII&lt;br /&gt; 873 = DCCCLXXIII&lt;br /&gt; 874 = DCCCLXXIV&lt;br /&gt; 875 = DCCCLXXV&lt;br /&gt; 876 = DCCCLXXVI&lt;br /&gt; 877 = DCCCLXXVII&lt;br /&gt; 878 = DCCCLXXVIII&lt;br /&gt; 879 = DCCCLXXIX&lt;br /&gt; 880 = DCCCLXXX&lt;br /&gt; 881 = DCCCLXXXI&lt;br /&gt; 882 = DCCCLXXXII&lt;br /&gt; 883 = DCCCLXXXIII&lt;br /&gt; 884 = DCCCLXXXIV&lt;br /&gt; 885 = DCCCLXXXV&lt;br /&gt; 886 = DCCCLXXXVI&lt;br /&gt; 887 = DCCCLXXXVII&lt;br /&gt; 888 = DCCCLXXXVIII&lt;br /&gt; 889 = DCCCLXXXIX&lt;br /&gt; 890 = DCCCXC&lt;br /&gt; 891 = DCCCXCI&lt;br /&gt; 892 = DCCCXCII&lt;br /&gt; 893 = DCCCXCIII&lt;br /&gt; 894 = DCCCXCIV&lt;br /&gt; 895 = DCCCXCV&lt;br /&gt; 896 = DCCCXCVI&lt;br /&gt; 897 = DCCCXCVII&lt;br /&gt; 898 = DCCCXCVIII&lt;br /&gt; 899 = DCCCXCIX&lt;br /&gt; 900 = CM&lt;br /&gt; 901 = CMI&lt;br /&gt; 902 = CMII&lt;br /&gt; 903 = CMIII&lt;br /&gt; 904 = CMIV&lt;br /&gt; 905 = CMV&lt;br /&gt; 906 = CMVI&lt;br /&gt; 907 = CMVII&lt;br /&gt; 908 = CMVIII&lt;br /&gt; 909 = CMIX&lt;br /&gt; 910 = CMX&lt;br /&gt; 911 = CMXI&lt;br /&gt; 912 = CMXII&lt;br /&gt; 913 = CMXIII&lt;br /&gt; 914 = CMXIV&lt;br /&gt; 915 = CMXV&lt;br /&gt; 916 = CMXVI&lt;br /&gt; 917 = CMXVII&lt;br /&gt; 918 = CMXVIII&lt;br /&gt; 919 = CMXIX&lt;br /&gt; 920 = CMXX&lt;br /&gt; 921 = CMXXI&lt;br /&gt; 922 = CMXXII&lt;br /&gt; 923 = CMXXIII&lt;br /&gt; 924 = CMXXIV&lt;br /&gt; 925 = CMXXV&lt;br /&gt; 926 = CMXXVI&lt;br /&gt; 927 = CMXXVII&lt;br /&gt; 928 = CMXXVIII&lt;br /&gt; 929 = CMXXIX&lt;br /&gt; 930 = CMXXX&lt;br /&gt; 931 = CMXXXI&lt;br /&gt; 932 = CMXXXII&lt;br /&gt; 933 = CMXXXIII&lt;br /&gt; 934 = CMXXXIV&lt;br /&gt; 935 = CMXXXV&lt;br /&gt; 936 = CMXXXVI&lt;br /&gt; 937 = CMXXXVII&lt;br /&gt; 938 = CMXXXVIII&lt;br /&gt; 939 = CMXXXIX&lt;br /&gt; 940 = CMXL&lt;br /&gt; 941 = CMXLI&lt;br /&gt; 942 = CMXLII&lt;br /&gt; 943 = CMXLIII&lt;br /&gt; 944 = CMXLIV&lt;br /&gt; 945 = CMXLV&lt;br /&gt; 946 = CMXLVI&lt;br /&gt; 947 = CMXLVII&lt;br /&gt; 948 = CMXLVIII&lt;br /&gt; 949 = CMXLIX&lt;br /&gt; 950 = CML&lt;br /&gt; 951 = CMLI&lt;br /&gt; 952 = CMLII&lt;br /&gt; 953 = CMLIII&lt;br /&gt; 954 = CMLIV&lt;br /&gt; 955 = CMLV&lt;br /&gt; 956 = CMLVI&lt;br /&gt; 957 = CMLVII&lt;br /&gt; 958 = CMLVIII&lt;br /&gt; 959 = CMLIX&lt;br /&gt; 960 = CMLX&lt;br /&gt; 961 = CMLXI&lt;br /&gt; 962 = CMLXII&lt;br /&gt; 963 = CMLXIII&lt;br /&gt; 964 = CMLXIV&lt;br /&gt; 965 = CMLXV&lt;br /&gt; 966 = CMLXVI&lt;br /&gt; 967 = CMLXVII&lt;br /&gt; 968 = CMLXVIII&lt;br /&gt; 969 = CMLXIX&lt;br /&gt; 970 = CMLXX&lt;br /&gt; 971 = CMLXXI&lt;br /&gt; 972 = CMLXXII&lt;br /&gt; 973 = CMLXXIII&lt;br /&gt; 974 = CMLXXIV&lt;br /&gt; 975 = CMLXXV&lt;br /&gt; 976 = CMLXXVI&lt;br /&gt; 977 = CMLXXVII&lt;br /&gt; 978 = CMLXXVIII&lt;br /&gt; 979 = CMLXXIX&lt;br /&gt; 980 = CMLXXX&lt;br /&gt; 981 = CMLXXXI&lt;br /&gt; 982 = CMLXXXII&lt;br /&gt; 983 = CMLXXXIII&lt;br /&gt; 984 = CMLXXXIV&lt;br /&gt; 985 = CMLXXXV&lt;br /&gt; 986 = CMLXXXVI&lt;br /&gt; 987 = CMLXXXVII&lt;br /&gt; 988 = CMLXXXVIII&lt;br /&gt; 989 = CMLXXXIX&lt;br /&gt; 990 = CMXC&lt;br /&gt; 991 = CMXCI&lt;br /&gt; 992 = CMXCII&lt;br /&gt; 993 = CMXCIII&lt;br /&gt; 994 = CMXCIV&lt;br /&gt; 995 = CMXCV&lt;br /&gt; 996 = CMXCVI&lt;br /&gt; 997 = CMXCVII&lt;br /&gt; 998 = CMXCVIII&lt;br /&gt; 999 = CMXCIX&lt;br /&gt;1000 = M&lt;br /&gt;1001 = MI&lt;br /&gt;1002 = MII&lt;br /&gt;1003 = MIII&lt;br /&gt;1004 = MIV&lt;br /&gt;1005 = MV&lt;br /&gt;1006 = MVI&lt;br /&gt;1007 = MVII&lt;br /&gt;1008 = MVIII&lt;br /&gt;1009 = MIX&lt;br /&gt;1010 = MX&lt;br /&gt;1011 = MXI&lt;br /&gt;1012 = MXII&lt;br /&gt;1013 = MXIII&lt;br /&gt;1014 = MXIV&lt;br /&gt;1015 = MXV&lt;br /&gt;1016 = MXVI&lt;br /&gt;1017 = MXVII&lt;br /&gt;1018 = MXVIII&lt;br /&gt;1019 = MXIX&lt;br /&gt;1020 = MXX&lt;br /&gt;1021 = MXXI&lt;br /&gt;1022 = MXXII&lt;br /&gt;1023 = MXXIII&lt;br /&gt;1024 = MXXIV&lt;br /&gt;1025 = MXXV&lt;br /&gt;1026 = MXXVI&lt;br /&gt;1027 = MXXVII&lt;br /&gt;1028 = MXXVIII&lt;br /&gt;1029 = MXXIX&lt;br /&gt;1030 = MXXX&lt;br /&gt;1031 = MXXXI&lt;br /&gt;1032 = MXXXII&lt;br /&gt;1033 = MXXXIII&lt;br /&gt;1034 = MXXXIV&lt;br /&gt;1035 = MXXXV&lt;br /&gt;1036 = MXXXVI&lt;br /&gt;1037 = MXXXVII&lt;br /&gt;1038 = MXXXVIII&lt;br /&gt;1039 = MXXXIX&lt;br /&gt;1040 = MXL&lt;br /&gt;1041 = MXLI&lt;br /&gt;1042 = MXLII&lt;br /&gt;1043 = MXLIII&lt;br /&gt;1044 = MXLIV&lt;br /&gt;1045 = MXLV&lt;br /&gt;1046 = MXLVI&lt;br /&gt;1047 = MXLVII&lt;br /&gt;1048 = MXLVIII&lt;br /&gt;1049 = MXLIX&lt;br /&gt;1050 = ML&lt;br /&gt;1051 = MLI&lt;br /&gt;1052 = MLII&lt;br /&gt;1053 = MLIII&lt;br /&gt;1054 = MLIV&lt;br /&gt;1055 = MLV&lt;br /&gt;1056 = MLVI&lt;br /&gt;1057 = MLVII&lt;br /&gt;1058 = MLVIII&lt;br /&gt;1059 = MLIX&lt;br /&gt;1060 = MLX&lt;br /&gt;1061 = MLXI&lt;br /&gt;1062 = MLXII&lt;br /&gt;1063 = MLXIII&lt;br /&gt;1064 = MLXIV&lt;br /&gt;1065 = MLXV&lt;br /&gt;1066 = MLXVI&lt;br /&gt;1067 = MLXVII&lt;br /&gt;1068 = MLXVIII&lt;br /&gt;1069 = MLXIX&lt;br /&gt;1070 = MLXX&lt;br /&gt;1071 = MLXXI&lt;br /&gt;1072 = MLXXII&lt;br /&gt;1073 = MLXXIII&lt;br /&gt;1074 = MLXXIV&lt;br /&gt;1075 = MLXXV&lt;br /&gt;1076 = MLXXVI&lt;br /&gt;1077 = MLXXVII&lt;br /&gt;1078 = MLXXVIII&lt;br /&gt;1079 = MLXXIX&lt;br /&gt;1080 = MLXXX&lt;br /&gt;1081 = MLXXXI&lt;br /&gt;1082 = MLXXXII&lt;br /&gt;1083 = MLXXXIII&lt;br /&gt;1084 = MLXXXIV&lt;br /&gt;1085 = MLXXXV&lt;br /&gt;1086 = MLXXXVI&lt;br /&gt;1087 = MLXXXVII&lt;br /&gt;1088 = MLXXXVIII&lt;br /&gt;1089 = MLXXXIX&lt;br /&gt;1090 = MXC&lt;br /&gt;1091 = MXCI&lt;br /&gt;1092 = MXCII&lt;br /&gt;1093 = MXCIII&lt;br /&gt;1094 = MXCIV&lt;br /&gt;1095 = MXCV&lt;br /&gt;1096 = MXCVI&lt;br /&gt;1097 = MXCVII&lt;br /&gt;1098 = MXCVIII&lt;br /&gt;1099 = MXCIX&lt;br /&gt;1100 = MC&lt;br /&gt;1101 = MCI&lt;br /&gt;1102 = MCII&lt;br /&gt;1103 = MCIII&lt;br /&gt;1104 = MCIV&lt;br /&gt;1105 = MCV&lt;br /&gt;1106 = MCVI&lt;br /&gt;1107 = MCVII&lt;br /&gt;1108 = MCVIII&lt;br /&gt;1109 = MCIX&lt;br /&gt;1110 = MCX&lt;br /&gt;1111 = MCXI&lt;br /&gt;1112 = MCXII&lt;br /&gt;1113 = MCXIII&lt;br /&gt;1114 = MCXIV&lt;br /&gt;1115 = MCXV&lt;br /&gt;1116 = MCXVI&lt;br /&gt;1117 = MCXVII&lt;br /&gt;1118 = MCXVIII&lt;br /&gt;1119 = MCXIX&lt;br /&gt;1120 = MCXX&lt;br /&gt;1121 = MCXXI&lt;br /&gt;1122 = MCXXII&lt;br /&gt;1123 = MCXXIII&lt;br /&gt;1124 = MCXXIV&lt;br /&gt;1125 = MCXXV&lt;br /&gt;1126 = MCXXVI&lt;br /&gt;1127 = MCXXVII&lt;br /&gt;1128 = MCXXVIII&lt;br /&gt;1129 = MCXXIX&lt;br /&gt;1130 = MCXXX&lt;br /&gt;1131 = MCXXXI&lt;br /&gt;1132 = MCXXXII&lt;br /&gt;1133 = MCXXXIII&lt;br /&gt;1134 = MCXXXIV&lt;br /&gt;1135 = MCXXXV&lt;br /&gt;1136 = MCXXXVI&lt;br /&gt;1137 = MCXXXVII&lt;br /&gt;1138 = MCXXXVIII&lt;br /&gt;1139 = MCXXXIX&lt;br /&gt;1140 = MCXL&lt;br /&gt;1141 = MCXLI&lt;br /&gt;1142 = MCXLII&lt;br /&gt;1143 = MCXLIII&lt;br /&gt;1144 = MCXLIV&lt;br /&gt;1145 = MCXLV&lt;br /&gt;1146 = MCXLVI&lt;br /&gt;1147 = MCXLVII&lt;br /&gt;1148 = MCXLVIII&lt;br /&gt;1149 = MCXLIX&lt;br /&gt;1150 = MCL&lt;br /&gt;1151 = MCLI&lt;br /&gt;1152 = MCLII&lt;br /&gt;1153 = MCLIII&lt;br /&gt;1154 = MCLIV&lt;br /&gt;1155 = MCLV&lt;br /&gt;1156 = MCLVI&lt;br /&gt;1157 = MCLVII&lt;br /&gt;1158 = MCLVIII&lt;br /&gt;1159 = MCLIX&lt;br /&gt;1160 = MCLX&lt;br /&gt;1161 = MCLXI&lt;br /&gt;1162 = MCLXII&lt;br /&gt;1163 = MCLXIII&lt;br /&gt;1164 = MCLXIV&lt;br /&gt;1165 = MCLXV&lt;br /&gt;1166 = MCLXVI&lt;br /&gt;1167 = MCLXVII&lt;br /&gt;1168 = MCLXVIII&lt;br /&gt;1169 = MCLXIX&lt;br /&gt;1170 = MCLXX&lt;br /&gt;1171 = MCLXXI&lt;br /&gt;1172 = MCLXXII&lt;br /&gt;1173 = MCLXXIII&lt;br /&gt;1174 = MCLXXIV&lt;br /&gt;1175 = MCLXXV&lt;br /&gt;1176 = MCLXXVI&lt;br /&gt;1177 = MCLXXVII&lt;br /&gt;1178 = MCLXXVIII&lt;br /&gt;1179 = MCLXXIX&lt;br /&gt;1180 = MCLXXX&lt;br /&gt;1181 = MCLXXXI&lt;br /&gt;1182 = MCLXXXII&lt;br /&gt;1183 = MCLXXXIII&lt;br /&gt;1184 = MCLXXXIV&lt;br /&gt;1185 = MCLXXXV&lt;br /&gt;1186 = MCLXXXVI&lt;br /&gt;1187 = MCLXXXVII&lt;br /&gt;1188 = MCLXXXVIII&lt;br /&gt;1189 = MCLXXXIX&lt;br /&gt;1190 = MCXC&lt;br /&gt;1191 = MCXCI&lt;br /&gt;1192 = MCXCII&lt;br /&gt;1193 = MCXCIII&lt;br /&gt;1194 = MCXCIV&lt;br /&gt;1195 = MCXCV&lt;br /&gt;1196 = MCXCVI&lt;br /&gt;1197 = MCXCVII&lt;br /&gt;1198 = MCXCVIII&lt;br /&gt;1199 = MCXCIX&lt;br /&gt;1200 = MCC&lt;br /&gt;1201 = MCCI&lt;br /&gt;1202 = MCCII&lt;br /&gt;1203 = MCCIII&lt;br /&gt;1204 = MCCIV&lt;br /&gt;1205 = MCCV&lt;br /&gt;1206 = MCCVI&lt;br /&gt;1207 = MCCVII&lt;br /&gt;1208 = MCCVIII&lt;br /&gt;1209 = MCCIX&lt;br /&gt;1210 = MCCX&lt;br /&gt;1211 = MCCXI&lt;br /&gt;1212 = MCCXII&lt;br /&gt;1213 = MCCXIII&lt;br /&gt;1214 = MCCXIV&lt;br /&gt;1215 = MCCXV&lt;br /&gt;1216 = MCCXVI&lt;br /&gt;1217 = MCCXVII&lt;br /&gt;1218 = MCCXVIII&lt;br /&gt;1219 = MCCXIX&lt;br /&gt;1220 = MCCXX&lt;br /&gt;1221 = MCCXXI&lt;br /&gt;1222 = MCCXXII&lt;br /&gt;1223 = MCCXXIII&lt;br /&gt;1224 = MCCXXIV&lt;br /&gt;1225 = MCCXXV&lt;br /&gt;1226 = MCCXXVI&lt;br /&gt;1227 = MCCXXVII&lt;br /&gt;1228 = MCCXXVIII&lt;br /&gt;1229 = MCCXXIX&lt;br /&gt;1230 = MCCXXX&lt;br /&gt;1231 = MCCXXXI&lt;br /&gt;1232 = MCCXXXII&lt;br /&gt;1233 = MCCXXXIII&lt;br /&gt;1234 = MCCXXXIV&lt;br /&gt;1235 = MCCXXXV&lt;br /&gt;1236 = MCCXXXVI&lt;br /&gt;1237 = MCCXXXVII&lt;br /&gt;1238 = MCCXXXVIII&lt;br /&gt;1239 = MCCXXXIX&lt;br /&gt;1240 = MCCXL&lt;br /&gt;1241 = MCCXLI&lt;br /&gt;1242 = MCCXLII&lt;br /&gt;1243 = MCCXLIII&lt;br /&gt;1244 = MCCXLIV&lt;br /&gt;1245 = MCCXLV&lt;br /&gt;1246 = MCCXLVI&lt;br /&gt;1247 = MCCXLVII&lt;br /&gt;1248 = MCCXLVIII&lt;br /&gt;1249 = MCCXLIX&lt;br /&gt;1250 = MCCL&lt;br /&gt;1251 = MCCLI&lt;br /&gt;1252 = MCCLII&lt;br /&gt;1253 = MCCLIII&lt;br /&gt;1254 = MCCLIV&lt;br /&gt;1255 = MCCLV&lt;br /&gt;1256 = MCCLVI&lt;br /&gt;1257 = MCCLVII&lt;br /&gt;1258 = MCCLVIII&lt;br /&gt;1259 = MCCLIX&lt;br /&gt;1260 = MCCLX&lt;br /&gt;1261 = MCCLXI&lt;br /&gt;1262 = MCCLXII&lt;br /&gt;1263 = MCCLXIII&lt;br /&gt;1264 = MCCLXIV&lt;br /&gt;1265 = MCCLXV&lt;br /&gt;1266 = MCCLXVI&lt;br /&gt;1267 = MCCLXVII&lt;br /&gt;1268 = MCCLXVIII&lt;br /&gt;1269 = MCCLXIX&lt;br /&gt;1270 = MCCLXX&lt;br /&gt;1271 = MCCLXXI&lt;br /&gt;1272 = MCCLXXII&lt;br /&gt;1273 = MCCLXXIII&lt;br /&gt;1274 = MCCLXXIV&lt;br /&gt;1275 = MCCLXXV&lt;br /&gt;1276 = MCCLXXVI&lt;br /&gt;1277 = MCCLXXVII&lt;br /&gt;1278 = MCCLXXVIII&lt;br /&gt;1279 = MCCLXXIX&lt;br /&gt;1280 = MCCLXXX&lt;br /&gt;1281 = MCCLXXXI&lt;br /&gt;1282 = MCCLXXXII&lt;br /&gt;1283 = MCCLXXXIII&lt;br /&gt;1284 = MCCLXXXIV&lt;br /&gt;1285 = MCCLXXXV&lt;br /&gt;1286 = MCCLXXXVI&lt;br /&gt;1287 = MCCLXXXVII&lt;br /&gt;1288 = MCCLXXXVIII&lt;br /&gt;1289 = MCCLXXXIX&lt;br /&gt;1290 = MCCXC&lt;br /&gt;1291 = MCCXCI&lt;br /&gt;1292 = MCCXCII&lt;br /&gt;1293 = MCCXCIII&lt;br /&gt;1294 = MCCXCIV&lt;br /&gt;1295 = MCCXCV&lt;br /&gt;1296 = MCCXCVI&lt;br /&gt;1297 = MCCXCVII&lt;br /&gt;1298 = MCCXCVIII&lt;br /&gt;1299 = MCCXCIX&lt;br /&gt;1300 = MCCC&lt;br /&gt;1301 = MCCCI&lt;br /&gt;1302 = MCCCII&lt;br /&gt;1303 = MCCCIII&lt;br /&gt;1304 = MCCCIV&lt;br /&gt;1305 = MCCCV&lt;br /&gt;1306 = MCCCVI&lt;br /&gt;1307 = MCCCVII&lt;br /&gt;1308 = MCCCVIII&lt;br /&gt;1309 = MCCCIX&lt;br /&gt;1310 = MCCCX&lt;br /&gt;1311 = MCCCXI&lt;br /&gt;1312 = MCCCXII&lt;br /&gt;1313 = MCCCXIII&lt;br /&gt;1314 = MCCCXIV&lt;br /&gt;1315 = MCCCXV&lt;br /&gt;1316 = MCCCXVI&lt;br /&gt;1317 = MCCCXVII&lt;br /&gt;1318 = MCCCXVIII&lt;br /&gt;1319 = MCCCXIX&lt;br /&gt;1320 = MCCCXX&lt;br /&gt;1321 = MCCCXXI&lt;br /&gt;1322 = MCCCXXII&lt;br /&gt;1323 = MCCCXXIII&lt;br /&gt;1324 = MCCCXXIV&lt;br /&gt;1325 = MCCCXXV&lt;br /&gt;1326 = MCCCXXVI&lt;br /&gt;1327 = MCCCXXVII&lt;br /&gt;1328 = MCCCXXVIII&lt;br /&gt;1329 = MCCCXXIX&lt;br /&gt;1330 = MCCCXXX&lt;br /&gt;1331 = MCCCXXXI&lt;br /&gt;1332 = MCCCXXXII&lt;br /&gt;1333 = MCCCXXXIII&lt;br /&gt;1334 = MCCCXXXIV&lt;br /&gt;1335 = MCCCXXXV&lt;br /&gt;1336 = MCCCXXXVI&lt;br /&gt;1337 = MCCCXXXVII&lt;br /&gt;1338 = MCCCXXXVIII&lt;br /&gt;1339 = MCCCXXXIX&lt;br /&gt;1340 = MCCCXL&lt;br /&gt;1341 = MCCCXLI&lt;br /&gt;1342 = MCCCXLII&lt;br /&gt;1343 = MCCCXLIII&lt;br /&gt;1344 = MCCCXLIV&lt;br /&gt;1345 = MCCCXLV&lt;br /&gt;1346 = MCCCXLVI&lt;br /&gt;1347 = MCCCXLVII&lt;br /&gt;1348 = MCCCXLVIII&lt;br /&gt;1349 = MCCCXLIX&lt;br /&gt;1350 = MCCCL&lt;br /&gt;1351 = MCCCLI&lt;br /&gt;1352 = MCCCLII&lt;br /&gt;1353 = MCCCLIII&lt;br /&gt;1354 = MCCCLIV&lt;br /&gt;1355 = MCCCLV&lt;br /&gt;1356 = MCCCLVI&lt;br /&gt;1357 = MCCCLVII&lt;br /&gt;1358 = MCCCLVIII&lt;br /&gt;1359 = MCCCLIX&lt;br /&gt;1360 = MCCCLX&lt;br /&gt;1361 = MCCCLXI&lt;br /&gt;1362 = MCCCLXII&lt;br /&gt;1363 = MCCCLXIII&lt;br /&gt;1364 = MCCCLXIV&lt;br /&gt;1365 = MCCCLXV&lt;br /&gt;1366 = MCCCLXVI&lt;br /&gt;1367 = MCCCLXVII&lt;br /&gt;1368 = MCCCLXVIII&lt;br /&gt;1369 = MCCCLXIX&lt;br /&gt;1370 = MCCCLXX&lt;br /&gt;1371 = MCCCLXXI&lt;br /&gt;1372 = MCCCLXXII&lt;br /&gt;1373 = MCCCLXXIII&lt;br /&gt;1374 = MCCCLXXIV&lt;br /&gt;1375 = MCCCLXXV&lt;br /&gt;1376 = MCCCLXXVI&lt;br /&gt;1377 = MCCCLXXVII&lt;br /&gt;1378 = MCCCLXXVIII&lt;br /&gt;1379 = MCCCLXXIX&lt;br /&gt;1380 = MCCCLXXX&lt;br /&gt;1381 = MCCCLXXXI&lt;br /&gt;1382 = MCCCLXXXII&lt;br /&gt;1383 = MCCCLXXXIII&lt;br /&gt;1384 = MCCCLXXXIV&lt;br /&gt;1385 = MCCCLXXXV&lt;br /&gt;1386 = MCCCLXXXVI&lt;br /&gt;1387 = MCCCLXXXVII&lt;br /&gt;1388 = MCCCLXXXVIII&lt;br /&gt;1389 = MCCCLXXXIX&lt;br /&gt;1390 = MCCCXC&lt;br /&gt;1391 = MCCCXCI&lt;br /&gt;1392 = MCCCXCII&lt;br /&gt;1393 = MCCCXCIII&lt;br /&gt;1394 = MCCCXCIV&lt;br /&gt;1395 = MCCCXCV&lt;br /&gt;1396 = MCCCXCVI&lt;br /&gt;1397 = MCCCXCVII&lt;br /&gt;1398 = MCCCXCVIII&lt;br /&gt;1399 = MCCCXCIX&lt;br /&gt;1400 = MCD&lt;br /&gt;1401 = MCDI&lt;br /&gt;1402 = MCDII&lt;br /&gt;1403 = MCDIII&lt;br /&gt;1404 = MCDIV&lt;br /&gt;1405 = MCDV&lt;br /&gt;1406 = MCDVI&lt;br /&gt;1407 = MCDVII&lt;br /&gt;1408 = MCDVIII&lt;br /&gt;1409 = MCDIX&lt;br /&gt;1410 = MCDX&lt;br /&gt;1411 = MCDXI&lt;br /&gt;1412 = MCDXII&lt;br /&gt;1413 = MCDXIII&lt;br /&gt;1414 = MCDXIV&lt;br /&gt;1415 = MCDXV&lt;br /&gt;1416 = MCDXVI&lt;br /&gt;1417 = MCDXVII&lt;br /&gt;1418 = MCDXVIII&lt;br /&gt;1419 = MCDXIX&lt;br /&gt;1420 = MCDXX&lt;br /&gt;1421 = MCDXXI&lt;br /&gt;1422 = MCDXXII&lt;br /&gt;1423 = MCDXXIII&lt;br /&gt;1424 = MCDXXIV&lt;br /&gt;1425 = MCDXXV&lt;br /&gt;1426 = MCDXXVI&lt;br /&gt;1427 = MCDXXVII&lt;br /&gt;1428 = MCDXXVIII&lt;br /&gt;1429 = MCDXXIX&lt;br /&gt;1430 = MCDXXX&lt;br /&gt;1431 = MCDXXXI&lt;br /&gt;1432 = MCDXXXII&lt;br /&gt;1433 = MCDXXXIII&lt;br /&gt;1434 = MCDXXXIV&lt;br /&gt;1435 = MCDXXXV&lt;br /&gt;1436 = MCDXXXVI&lt;br /&gt;1437 = MCDXXXVII&lt;br /&gt;1438 = MCDXXXVIII&lt;br /&gt;1439 = MCDXXXIX&lt;br /&gt;1440 = MCDXL&lt;br /&gt;1441 = MCDXLI&lt;br /&gt;1442 = MCDXLII&lt;br /&gt;1443 = MCDXLIII&lt;br /&gt;1444 = MCDXLIV&lt;br /&gt;1445 = MCDXLV&lt;br /&gt;1446 = MCDXLVI&lt;br /&gt;1447 = MCDXLVII&lt;br /&gt;1448 = MCDXLVIII&lt;br /&gt;1449 = MCDXLIX&lt;br /&gt;1450 = MCDL&lt;br /&gt;1451 = MCDLI&lt;br /&gt;1452 = MCDLII&lt;br /&gt;1453 = MCDLIII&lt;br /&gt;1454 = MCDLIV&lt;br /&gt;1455 = MCDLV&lt;br /&gt;1456 = MCDLVI&lt;br /&gt;1457 = MCDLVII&lt;br /&gt;1458 = MCDLVIII&lt;br /&gt;1459 = MCDLIX&lt;br /&gt;1460 = MCDLX&lt;br /&gt;1461 = MCDLXI&lt;br /&gt;1462 = MCDLXII&lt;br /&gt;1463 = MCDLXIII&lt;br /&gt;1464 = MCDLXIV&lt;br /&gt;1465 = MCDLXV&lt;br /&gt;1466 = MCDLXVI&lt;br /&gt;1467 = MCDLXVII&lt;br /&gt;1468 = MCDLXVIII&lt;br /&gt;1469 = MCDLXIX&lt;br /&gt;1470 = MCDLXX&lt;br /&gt;1471 = MCDLXXI&lt;br /&gt;1472 = MCDLXXII&lt;br /&gt;1473 = MCDLXXIII&lt;br /&gt;1474 = MCDLXXIV&lt;br /&gt;1475 = MCDLXXV&lt;br /&gt;1476 = MCDLXXVI&lt;br /&gt;1477 = MCDLXXVII&lt;br /&gt;1478 = MCDLXXVIII&lt;br /&gt;1479 = MCDLXXIX&lt;br /&gt;1480 = MCDLXXX&lt;br /&gt;1481 = MCDLXXXI&lt;br /&gt;1482 = MCDLXXXII&lt;br /&gt;1483 = MCDLXXXIII&lt;br /&gt;1484 = MCDLXXXIV&lt;br /&gt;1485 = MCDLXXXV&lt;br /&gt;1486 = MCDLXXXVI&lt;br /&gt;1487 = MCDLXXXVII&lt;br /&gt;1488 = MCDLXXXVIII&lt;br /&gt;1489 = MCDLXXXIX&lt;br /&gt;1490 = MCDXC&lt;br /&gt;1491 = MCDXCI&lt;br /&gt;1492 = MCDXCII&lt;br /&gt;1493 = MCDXCIII&lt;br /&gt;1494 = MCDXCIV&lt;br /&gt;1495 = MCDXCV&lt;br /&gt;1496 = MCDXCVI&lt;br /&gt;1497 = MCDXCVII&lt;br /&gt;1498 = MCDXCVIII&lt;br /&gt;1499 = MCDXCIX&lt;br /&gt;1500 = MD&lt;br /&gt;1501 = MDI&lt;br /&gt;1502 = MDII&lt;br /&gt;1503 = MDIII&lt;br /&gt;1504 = MDIV&lt;br /&gt;1505 = MDV&lt;br /&gt;1506 = MDVI&lt;br /&gt;1507 = MDVII&lt;br /&gt;1508 = MDVIII&lt;br /&gt;1509 = MDIX&lt;br /&gt;1510 = MDX&lt;br /&gt;1511 = MDXI&lt;br /&gt;1512 = MDXII&lt;br /&gt;1513 = MDXIII&lt;br /&gt;1514 = MDXIV&lt;br /&gt;1515 = MDXV&lt;br /&gt;1516 = MDXVI&lt;br /&gt;1517 = MDXVII&lt;br /&gt;1518 = MDXVIII&lt;br /&gt;1519 = MDXIX&lt;br /&gt;1520 = MDXX&lt;br /&gt;1521 = MDXXI&lt;br /&gt;1522 = MDXXII&lt;br /&gt;1523 = MDXXIII&lt;br /&gt;1524 = MDXXIV&lt;br /&gt;1525 = MDXXV&lt;br /&gt;1526 = MDXXVI&lt;br /&gt;1527 = MDXXVII&lt;br /&gt;1528 = MDXXVIII&lt;br /&gt;1529 = MDXXIX&lt;br /&gt;1530 = MDXXX&lt;br /&gt;1531 = MDXXXI&lt;br /&gt;1532 = MDXXXII&lt;br /&gt;1533 = MDXXXIII&lt;br /&gt;1534 = MDXXXIV&lt;br /&gt;1535 = MDXXXV&lt;br /&gt;1536 = MDXXXVI&lt;br /&gt;1537 = MDXXXVII&lt;br /&gt;1538 = MDXXXVIII&lt;br /&gt;1539 = MDXXXIX&lt;br /&gt;1540 = MDXL&lt;br /&gt;1541 = MDXLI&lt;br /&gt;1542 = MDXLII&lt;br /&gt;1543 = MDXLIII&lt;br /&gt;1544 = MDXLIV&lt;br /&gt;1545 = MDXLV&lt;br /&gt;1546 = MDXLVI&lt;br /&gt;1547 = MDXLVII&lt;br /&gt;1548 = MDXLVIII&lt;br /&gt;1549 = MDXLIX&lt;br /&gt;1550 = MDL&lt;br /&gt;1551 = MDLI&lt;br /&gt;1552 = MDLII&lt;br /&gt;1553 = MDLIII&lt;br /&gt;1554 = MDLIV&lt;br /&gt;1555 = MDLV&lt;br /&gt;1556 = MDLVI&lt;br /&gt;1557 = MDLVII&lt;br /&gt;1558 = MDLVIII&lt;br /&gt;1559 = MDLIX&lt;br /&gt;1560 = MDLX&lt;br /&gt;1561 = MDLXI&lt;br /&gt;1562 = MDLXII&lt;br /&gt;1563 = MDLXIII&lt;br /&gt;1564 = MDLXIV&lt;br /&gt;1565 = MDLXV&lt;br /&gt;1566 = MDLXVI&lt;br /&gt;1567 = MDLXVII&lt;br /&gt;1568 = MDLXVIII&lt;br /&gt;1569 = MDLXIX&lt;br /&gt;1570 = MDLXX&lt;br /&gt;1571 = MDLXXI&lt;br /&gt;1572 = MDLXXII&lt;br /&gt;1573 = MDLXXIII&lt;br /&gt;1574 = MDLXXIV&lt;br /&gt;1575 = MDLXXV&lt;br /&gt;1576 = MDLXXVI&lt;br /&gt;1577 = MDLXXVII&lt;br /&gt;1578 = MDLXXVIII&lt;br /&gt;1579 = MDLXXIX&lt;br /&gt;1580 = MDLXXX&lt;br /&gt;1581 = MDLXXXI&lt;br /&gt;1582 = MDLXXXII&lt;br /&gt;1583 = MDLXXXIII&lt;br /&gt;1584 = MDLXXXIV&lt;br /&gt;1585 = MDLXXXV&lt;br /&gt;1586 = MDLXXXVI&lt;br /&gt;1587 = MDLXXXVII&lt;br /&gt;1588 = MDLXXXVIII&lt;br /&gt;1589 = MDLXXXIX&lt;br /&gt;1590 = MDXC&lt;br /&gt;1591 = MDXCI&lt;br /&gt;1592 = MDXCII&lt;br /&gt;1593 = MDXCIII&lt;br /&gt;1594 = MDXCIV&lt;br /&gt;1595 = MDXCV&lt;br /&gt;1596 = MDXCVI&lt;br /&gt;1597 = MDXCVII&lt;br /&gt;1598 = MDXCVIII&lt;br /&gt;1599 = MDXCIX&lt;br /&gt;1600 = MDC&lt;br /&gt;1601 = MDCI&lt;br /&gt;1602 = MDCII&lt;br /&gt;1603 = MDCIII&lt;br /&gt;1604 = MDCIV&lt;br /&gt;1605 = MDCV&lt;br /&gt;1606 = MDCVI&lt;br /&gt;1607 = MDCVII&lt;br /&gt;1608 = MDCVIII&lt;br /&gt;1609 = MDCIX&lt;br /&gt;1610 = MDCX&lt;br /&gt;1611 = MDCXI&lt;br /&gt;1612 = MDCXII&lt;br /&gt;1613 = MDCXIII&lt;br /&gt;1614 = MDCXIV&lt;br /&gt;1615 = MDCXV&lt;br /&gt;1616 = MDCXVI&lt;br /&gt;1617 = MDCXVII&lt;br /&gt;1618 = MDCXVIII&lt;br /&gt;1619 = MDCXIX&lt;br /&gt;1620 = MDCXX&lt;br /&gt;1621 = MDCXXI&lt;br /&gt;1622 = MDCXXII&lt;br /&gt;1623 = MDCXXIII&lt;br /&gt;1624 = MDCXXIV&lt;br /&gt;1625 = MDCXXV&lt;br /&gt;1626 = MDCXXVI&lt;br /&gt;1627 = MDCXXVII&lt;br /&gt;1628 = MDCXXVIII&lt;br /&gt;1629 = MDCXXIX&lt;br /&gt;1630 = MDCXXX&lt;br /&gt;1631 = MDCXXXI&lt;br /&gt;1632 = MDCXXXII&lt;br /&gt;1633 = MDCXXXIII&lt;br /&gt;1634 = MDCXXXIV&lt;br /&gt;1635 = MDCXXXV&lt;br /&gt;1636 = MDCXXXVI&lt;br /&gt;1637 = MDCXXXVII&lt;br /&gt;1638 = MDCXXXVIII&lt;br /&gt;1639 = MDCXXXIX&lt;br /&gt;1640 = MDCXL&lt;br /&gt;1641 = MDCXLI&lt;br /&gt;1642 = MDCXLII&lt;br /&gt;1643 = MDCXLIII&lt;br /&gt;1644 = MDCXLIV&lt;br /&gt;1645 = MDCXLV&lt;br /&gt;1646 = MDCXLVI&lt;br /&gt;1647 = MDCXLVII&lt;br /&gt;1648 = MDCXLVIII&lt;br /&gt;1649 = MDCXLIX&lt;br /&gt;1650 = MDCL&lt;br /&gt;1651 = MDCLI&lt;br /&gt;1652 = MDCLII&lt;br /&gt;1653 = MDCLIII&lt;br /&gt;1654 = MDCLIV&lt;br /&gt;1655 = MDCLV&lt;br /&gt;1656 = MDCLVI&lt;br /&gt;1657 = MDCLVII&lt;br /&gt;1658 = MDCLVIII&lt;br /&gt;1659 = MDCLIX&lt;br /&gt;1660 = MDCLX&lt;br /&gt;1661 = MDCLXI&lt;br /&gt;1662 = MDCLXII&lt;br /&gt;1663 = MDCLXIII&lt;br /&gt;1664 = MDCLXIV&lt;br /&gt;1665 = MDCLXV&lt;br /&gt;1666 = MDCLXVI&lt;br /&gt;1667 = MDCLXVII&lt;br /&gt;1668 = MDCLXVIII&lt;br /&gt;1669 = MDCLXIX&lt;br /&gt;1670 = MDCLXX&lt;br /&gt;1671 = MDCLXXI&lt;br /&gt;1672 = MDCLXXII&lt;br /&gt;1673 = MDCLXXIII&lt;br /&gt;1674 = MDCLXXIV&lt;br /&gt;1675 = MDCLXXV&lt;br /&gt;1676 = MDCLXXVI&lt;br /&gt;1677 = MDCLXXVII&lt;br /&gt;1678 = MDCLXXVIII&lt;br /&gt;1679 = MDCLXXIX&lt;br /&gt;1680 = MDCLXXX&lt;br /&gt;1681 = MDCLXXXI&lt;br /&gt;1682 = MDCLXXXII&lt;br /&gt;1683 = MDCLXXXIII&lt;br /&gt;1684 = MDCLXXXIV&lt;br /&gt;1685 = MDCLXXXV&lt;br /&gt;1686 = MDCLXXXVI&lt;br /&gt;1687 = MDCLXXXVII&lt;br /&gt;1688 = MDCLXXXVIII&lt;br /&gt;1689 = MDCLXXXIX&lt;br /&gt;1690 = MDCXC&lt;br /&gt;1691 = MDCXCI&lt;br /&gt;1692 = MDCXCII&lt;br /&gt;1693 = MDCXCIII&lt;br /&gt;1694 = MDCXCIV&lt;br /&gt;1695 = MDCXCV&lt;br /&gt;1696 = MDCXCVI&lt;br /&gt;1697 = MDCXCVII&lt;br /&gt;1698 = MDCXCVIII&lt;br /&gt;1699 = MDCXCIX&lt;br /&gt;1700 = MDCC&lt;br /&gt;1701 = MDCCI&lt;br /&gt;1702 = MDCCII&lt;br /&gt;1703 = MDCCIII&lt;br /&gt;1704 = MDCCIV&lt;br /&gt;1705 = MDCCV&lt;br /&gt;1706 = MDCCVI&lt;br /&gt;1707 = MDCCVII&lt;br /&gt;1708 = MDCCVIII&lt;br /&gt;1709 = MDCCIX&lt;br /&gt;1710 = MDCCX&lt;br /&gt;1711 = MDCCXI&lt;br /&gt;1712 = MDCCXII&lt;br /&gt;1713 = MDCCXIII&lt;br /&gt;1714 = MDCCXIV&lt;br /&gt;1715 = MDCCXV&lt;br /&gt;1716 = MDCCXVI&lt;br /&gt;1717 = MDCCXVII&lt;br /&gt;1718 = MDCCXVIII&lt;br /&gt;1719 = MDCCXIX&lt;br /&gt;1720 = MDCCXX&lt;br /&gt;1721 = MDCCXXI&lt;br /&gt;1722 = MDCCXXII&lt;br /&gt;1723 = MDCCXXIII&lt;br /&gt;1724 = MDCCXXIV&lt;br /&gt;1725 = MDCCXXV&lt;br /&gt;1726 = MDCCXXVI&lt;br /&gt;1727 = MDCCXXVII&lt;br /&gt;1728 = MDCCXXVIII&lt;br /&gt;1729 = MDCCXXIX&lt;br /&gt;1730 = MDCCXXX&lt;br /&gt;1731 = MDCCXXXI&lt;br /&gt;1732 = MDCCXXXII&lt;br /&gt;1733 = MDCCXXXIII&lt;br /&gt;1734 = MDCCXXXIV&lt;br /&gt;1735 = MDCCXXXV&lt;br /&gt;1736 = MDCCXXXVI&lt;br /&gt;1737 = MDCCXXXVII&lt;br /&gt;1738 = MDCCXXXVIII&lt;br /&gt;1739 = MDCCXXXIX&lt;br /&gt;1740 = MDCCXL&lt;br /&gt;1741 = MDCCXLI&lt;br /&gt;1742 = MDCCXLII&lt;br /&gt;1743 = MDCCXLIII&lt;br /&gt;1744 = MDCCXLIV&lt;br /&gt;1745 = MDCCXLV&lt;br /&gt;1746 = MDCCXLVI&lt;br /&gt;1747 = MDCCXLVII&lt;br /&gt;1748 = MDCCXLVIII&lt;br /&gt;1749 = MDCCXLIX&lt;br /&gt;1750 = MDCCL&lt;br /&gt;1751 = MDCCLI&lt;br /&gt;1752 = MDCCLII&lt;br /&gt;1753 = MDCCLIII&lt;br /&gt;1754 = MDCCLIV&lt;br /&gt;1755 = MDCCLV&lt;br /&gt;1756 = MDCCLVI&lt;br /&gt;1757 = MDCCLVII&lt;br /&gt;1758 = MDCCLVIII&lt;br /&gt;1759 = MDCCLIX&lt;br /&gt;1760 = MDCCLX&lt;br /&gt;1761 = MDCCLXI&lt;br /&gt;1762 = MDCCLXII&lt;br /&gt;1763 = MDCCLXIII&lt;br /&gt;1764 = MDCCLXIV&lt;br /&gt;1765 = MDCCLXV&lt;br /&gt;1766 = MDCCLXVI&lt;br /&gt;1767 = MDCCLXVII&lt;br /&gt;1768 = MDCCLXVIII&lt;br /&gt;1769 = MDCCLXIX&lt;br /&gt;1770 = MDCCLXX&lt;br /&gt;1771 = MDCCLXXI&lt;br /&gt;1772 = MDCCLXXII&lt;br /&gt;1773 = MDCCLXXIII&lt;br /&gt;1774 = MDCCLXXIV&lt;br /&gt;1775 = MDCCLXXV&lt;br /&gt;1776 = MDCCLXXVI&lt;br /&gt;1777 = MDCCLXXVII&lt;br /&gt;1778 = MDCCLXXVIII&lt;br /&gt;1779 = MDCCLXXIX&lt;br /&gt;1780 = MDCCLXXX&lt;br /&gt;1781 = MDCCLXXXI&lt;br /&gt;1782 = MDCCLXXXII&lt;br /&gt;1783 = MDCCLXXXIII&lt;br /&gt;1784 = MDCCLXXXIV&lt;br /&gt;1785 = MDCCLXXXV&lt;br /&gt;1786 = MDCCLXXXVI&lt;br /&gt;1787 = MDCCLXXXVII&lt;br /&gt;1788 = MDCCLXXXVIII&lt;br /&gt;1789 = MDCCLXXXIX&lt;br /&gt;1790 = MDCCXC&lt;br /&gt;1791 = MDCCXCI&lt;br /&gt;1792 = MDCCXCII&lt;br /&gt;1793 = MDCCXCIII&lt;br /&gt;1794 = MDCCXCIV&lt;br /&gt;1795 = MDCCXCV&lt;br /&gt;1796 = MDCCXCVI&lt;br /&gt;1797 = MDCCXCVII&lt;br /&gt;1798 = MDCCXCVIII&lt;br /&gt;1799 = MDCCXCIX&lt;br /&gt;1800 = MDCCC&lt;br /&gt;1801 = MDCCCI&lt;br /&gt;1802 = MDCCCII&lt;br /&gt;1803 = MDCCCIII&lt;br /&gt;1804 = MDCCCIV&lt;br /&gt;1805 = MDCCCV&lt;br /&gt;1806 = MDCCCVI&lt;br /&gt;1807 = MDCCCVII&lt;br /&gt;1808 = MDCCCVIII&lt;br /&gt;1809 = MDCCCIX&lt;br /&gt;1810 = MDCCCX&lt;br /&gt;1811 = MDCCCXI&lt;br /&gt;1812 = MDCCCXII&lt;br /&gt;1813 = MDCCCXIII&lt;br /&gt;1814 = MDCCCXIV&lt;br /&gt;1815 = MDCCCXV&lt;br /&gt;1816 = MDCCCXVI&lt;br /&gt;1817 = MDCCCXVII&lt;br /&gt;1818 = MDCCCXVIII&lt;br /&gt;1819 = MDCCCXIX&lt;br /&gt;1820 = MDCCCXX&lt;br /&gt;1821 = MDCCCXXI&lt;br /&gt;1822 = MDCCCXXII&lt;br /&gt;1823 = MDCCCXXIII&lt;br /&gt;1824 = MDCCCXXIV&lt;br /&gt;1825 = MDCCCXXV&lt;br /&gt;1826 = MDCCCXXVI&lt;br /&gt;1827 = MDCCCXXVII&lt;br /&gt;1828 = MDCCCXXVIII&lt;br /&gt;1829 = MDCCCXXIX&lt;br /&gt;1830 = MDCCCXXX&lt;br /&gt;1831 = MDCCCXXXI&lt;br /&gt;1832 = MDCCCXXXII&lt;br /&gt;1833 = MDCCCXXXIII&lt;br /&gt;1834 = MDCCCXXXIV&lt;br /&gt;1835 = MDCCCXXXV&lt;br /&gt;1836 = MDCCCXXXVI&lt;br /&gt;1837 = MDCCCXXXVII&lt;br /&gt;1838 = MDCCCXXXVIII&lt;br /&gt;1839 = MDCCCXXXIX&lt;br /&gt;1840 = MDCCCXL&lt;br /&gt;1841 = MDCCCXLI&lt;br /&gt;1842 = MDCCCXLII&lt;br /&gt;1843 = MDCCCXLIII&lt;br /&gt;1844 = MDCCCXLIV&lt;br /&gt;1845 = MDCCCXLV&lt;br /&gt;1846 = MDCCCXLVI&lt;br /&gt;1847 = MDCCCXLVII&lt;br /&gt;1848 = MDCCCXLVIII&lt;br /&gt;1849 = MDCCCXLIX&lt;br /&gt;1850 = MDCCCL&lt;br /&gt;1851 = MDCCCLI&lt;br /&gt;1852 = MDCCCLII&lt;br /&gt;1853 = MDCCCLIII&lt;br /&gt;1854 = MDCCCLIV&lt;br /&gt;1855 = MDCCCLV&lt;br /&gt;1856 = MDCCCLVI&lt;br /&gt;1857 = MDCCCLVII&lt;br /&gt;1858 = MDCCCLVIII&lt;br /&gt;1859 = MDCCCLIX&lt;br /&gt;1860 = MDCCCLX&lt;br /&gt;1861 = MDCCCLXI&lt;br /&gt;1862 = MDCCCLXII&lt;br /&gt;1863 = MDCCCLXIII&lt;br /&gt;1864 = MDCCCLXIV&lt;br /&gt;1865 = MDCCCLXV&lt;br /&gt;1866 = MDCCCLXVI&lt;br /&gt;1867 = MDCCCLXVII&lt;br /&gt;1868 = MDCCCLXVIII&lt;br /&gt;1869 = MDCCCLXIX&lt;br /&gt;1870 = MDCCCLXX&lt;br /&gt;1871 = MDCCCLXXI&lt;br /&gt;1872 = MDCCCLXXII&lt;br /&gt;1873 = MDCCCLXXIII&lt;br /&gt;1874 = MDCCCLXXIV&lt;br /&gt;1875 = MDCCCLXXV&lt;br /&gt;1876 = MDCCCLXXVI&lt;br /&gt;1877 = MDCCCLXXVII&lt;br /&gt;1878 = MDCCCLXXVIII&lt;br /&gt;1879 = MDCCCLXXIX&lt;br /&gt;1880 = MDCCCLXXX&lt;br /&gt;1881 = MDCCCLXXXI&lt;br /&gt;1882 = MDCCCLXXXII&lt;br /&gt;1883 = MDCCCLXXXIII&lt;br /&gt;1884 = MDCCCLXXXIV&lt;br /&gt;1885 = MDCCCLXXXV&lt;br /&gt;1886 = MDCCCLXXXVI&lt;br /&gt;1887 = MDCCCLXXXVII&lt;br /&gt;1888 = MDCCCLXXXVIII&lt;br /&gt;1889 = MDCCCLXXXIX&lt;br /&gt;1890 = MDCCCXC&lt;br /&gt;1891 = MDCCCXCI&lt;br /&gt;1892 = MDCCCXCII&lt;br /&gt;1893 = MDCCCXCIII&lt;br /&gt;1894 = MDCCCXCIV&lt;br /&gt;1895 = MDCCCXCV&lt;br /&gt;1896 = MDCCCXCVI&lt;br /&gt;1897 = MDCCCXCVII&lt;br /&gt;1898 = MDCCCXCVIII&lt;br /&gt;1899 = MDCCCXCIX&lt;br /&gt;1900 = MCM&lt;br /&gt;1901 = MCMI&lt;br /&gt;1902 = MCMII&lt;br /&gt;1903 = MCMIII&lt;br /&gt;1904 = MCMIV&lt;br /&gt;1905 = MCMV&lt;br /&gt;1906 = MCMVI&lt;br /&gt;1907 = MCMVII&lt;br /&gt;1908 = MCMVIII&lt;br /&gt;1909 = MCMIX&lt;br /&gt;1910 = MCMX&lt;br /&gt;1911 = MCMXI&lt;br /&gt;1912 = MCMXII&lt;br /&gt;1913 = MCMXIII&lt;br /&gt;1914 = MCMXIV&lt;br /&gt;1915 = MCMXV&lt;br /&gt;1916 = MCMXVI&lt;br /&gt;1917 = MCMXVII&lt;br /&gt;1918 = MCMXVIII&lt;br /&gt;1919 = MCMXIX&lt;br /&gt;1920 = MCMXX&lt;br /&gt;1921 = MCMXXI&lt;br /&gt;1922 = MCMXXII&lt;br /&gt;1923 = MCMXXIII&lt;br /&gt;1924 = MCMXXIV&lt;br /&gt;1925 = MCMXXV&lt;br /&gt;1926 = MCMXXVI&lt;br /&gt;1927 = MCMXXVII&lt;br /&gt;1928 = MCMXXVIII&lt;br /&gt;1929 = MCMXXIX&lt;br /&gt;1930 = MCMXXX&lt;br /&gt;1931 = MCMXXXI&lt;br /&gt;1932 = MCMXXXII&lt;br /&gt;1933 = MCMXXXIII&lt;br /&gt;1934 = MCMXXXIV&lt;br /&gt;1935 = MCMXXXV&lt;br /&gt;1936 = MCMXXXVI&lt;br /&gt;1937 = MCMXXXVII&lt;br /&gt;1938 = MCMXXXVIII&lt;br /&gt;1939 = MCMXXXIX&lt;br /&gt;1940 = MCMXL&lt;br /&gt;1941 = MCMXLI&lt;br /&gt;1942 = MCMXLII&lt;br /&gt;1943 = MCMXLIII&lt;br /&gt;1944 = MCMXLIV&lt;br /&gt;1945 = MCMXLV&lt;br /&gt;1946 = MCMXLVI&lt;br /&gt;1947 = MCMXLVII&lt;br /&gt;1948 = MCMXLVIII&lt;br /&gt;1949 = MCMXLIX&lt;br /&gt;1950 = MCML&lt;br /&gt;1951 = MCMLI&lt;br /&gt;1952 = MCMLII&lt;br /&gt;1953 = MCMLIII&lt;br /&gt;1954 = MCMLIV&lt;br /&gt;1955 = MCMLV&lt;br /&gt;1956 = MCMLVI&lt;br /&gt;1957 = MCMLVII&lt;br /&gt;1958 = MCMLVIII&lt;br /&gt;1959 = MCMLIX&lt;br /&gt;1960 = MCMLX&lt;br /&gt;1961 = MCMLXI&lt;br /&gt;1962 = MCMLXII&lt;br /&gt;1963 = MCMLXIII&lt;br /&gt;1964 = MCMLXIV&lt;br /&gt;1965 = MCMLXV&lt;br /&gt;1966 = MCMLXVI&lt;br /&gt;1967 = MCMLXVII&lt;br /&gt;1968 = MCMLXVIII&lt;br /&gt;1969 = MCMLXIX&lt;br /&gt;1970 = MCMLXX&lt;br /&gt;1971 = MCMLXXI&lt;br /&gt;1972 = MCMLXXII&lt;br /&gt;1973 = MCMLXXIII&lt;br /&gt;1974 = MCMLXXIV&lt;br /&gt;1975 = MCMLXXV&lt;br /&gt;1976 = MCMLXXVI&lt;br /&gt;1977 = MCMLXXVII&lt;br /&gt;1978 = MCMLXXVIII&lt;br /&gt;1979 = MCMLXXIX&lt;br /&gt;1980 = MCMLXXX&lt;br /&gt;1981 = MCMLXXXI&lt;br /&gt;1982 = MCMLXXXII&lt;br /&gt;1983 = MCMLXXXIII&lt;br /&gt;1984 = MCMLXXXIV&lt;br /&gt;1985 = MCMLXXXV&lt;br /&gt;1986 = MCMLXXXVI&lt;br /&gt;1987 = MCMLXXXVII&lt;br /&gt;1988 = MCMLXXXVIII&lt;br /&gt;1989 = MCMLXXXIX&lt;br /&gt;1990 = MCMXC&lt;br /&gt;1991 = MCMXCI&lt;br /&gt;1992 = MCMXCII&lt;br /&gt;1993 = MCMXCIII&lt;br /&gt;1994 = MCMXCIV&lt;br /&gt;1995 = MCMXCV&lt;br /&gt;1996 = MCMXCVI&lt;br /&gt;1997 = MCMXCVII&lt;br /&gt;1998 = MCMXCVIII&lt;br /&gt;1999 = MCMXCIX&lt;br /&gt;2000 = MM&lt;br /&gt;2001 = MMI&lt;br /&gt;2002 = MMII&lt;br /&gt;2003 = MMIII&lt;br /&gt;2004 = MMIV&lt;br /&gt;2005 = MMV&lt;br /&gt;2006 = MMVI&lt;br /&gt;2007 = MMVII&lt;br /&gt;2008 = MMVIII&lt;br /&gt;2009 = MMIX&lt;br /&gt;2010 = MMX&lt;br /&gt;2011 = MMXI&lt;br /&gt;2012 = MMXII&lt;br /&gt;2013 = MMXIII&lt;br /&gt;2014 = MMXIV&lt;br /&gt;2015 = MMXV&lt;br /&gt;2016 = MMXVI&lt;br /&gt;2017 = MMXVII&lt;br /&gt;2018 = MMXVIII&lt;br /&gt;2019 = MMXIX&lt;br /&gt;2020 = MMXX&lt;br /&gt;2021 = MMXXI&lt;br /&gt;2022 = MMXXII&lt;br /&gt;2023 = MMXXIII&lt;br /&gt;2024 = MMXXIV&lt;br /&gt;2025 = MMXXV&lt;br /&gt;2026 = MMXXVI&lt;br /&gt;2027 = MMXXVII&lt;br /&gt;2028 = MMXXVIII&lt;br /&gt;2029 = MMXXIX&lt;br /&gt;2030 = MMXXX&lt;br /&gt;2031 = MMXXXI&lt;br /&gt;2032 = MMXXXII&lt;br /&gt;2033 = MMXXXIII&lt;br /&gt;2034 = MMXXXIV&lt;br /&gt;2035 = MMXXXV&lt;br /&gt;2036 = MMXXXVI&lt;br /&gt;2037 = MMXXXVII&lt;br /&gt;2038 = MMXXXVIII&lt;br /&gt;2039 = MMXXXIX&lt;br /&gt;2040 = MMXL&lt;br /&gt;2041 = MMXLI&lt;br /&gt;2042 = MMXLII&lt;br /&gt;2043 = MMXLIII&lt;br /&gt;2044 = MMXLIV&lt;br /&gt;2045 = MMXLV&lt;br /&gt;2046 = MMXLVI&lt;br /&gt;2047 = MMXLVII&lt;br /&gt;2048 = MMXLVIII&lt;br /&gt;2049 = MMXLIX&lt;br /&gt;2050 = MML&lt;br /&gt;2051 = MMLI&lt;br /&gt;2052 = MMLII&lt;br /&gt;2053 = MMLIII&lt;br /&gt;2054 = MMLIV&lt;br /&gt;2055 = MMLV&lt;br /&gt;2056 = MMLVI&lt;br /&gt;2057 = MMLVII&lt;br /&gt;2058 = MMLVIII&lt;br /&gt;2059 = MMLIX&lt;br /&gt;2060 = MMLX&lt;br /&gt;2061 = MMLXI&lt;br /&gt;2062 = MMLXII&lt;br /&gt;2063 = MMLXIII&lt;br /&gt;2064 = MMLXIV&lt;br /&gt;2065 = MMLXV&lt;br /&gt;2066 = MMLXVI&lt;br /&gt;2067 = MMLXVII&lt;br /&gt;2068 = MMLXVIII&lt;br /&gt;2069 = MMLXIX&lt;br /&gt;2070 = MMLXX&lt;br /&gt;2071 = MMLXXI&lt;br /&gt;2072 = MMLXXII&lt;br /&gt;2073 = MMLXXIII&lt;br /&gt;2074 = MMLXXIV&lt;br /&gt;2075 = MMLXXV&lt;br /&gt;2076 = MMLXXVI&lt;br /&gt;2077 = MMLXXVII&lt;br /&gt;2078 = MMLXXVIII&lt;br /&gt;2079 = MMLXXIX&lt;br /&gt;2080 = MMLXXX&lt;br /&gt;2081 = MMLXXXI&lt;br /&gt;2082 = MMLXXXII&lt;br /&gt;2083 = MMLXXXIII&lt;br /&gt;2084 = MMLXXXIV&lt;br /&gt;2085 = MMLXXXV&lt;br /&gt;2086 = MMLXXXVI&lt;br /&gt;2087 = MMLXXXVII&lt;br /&gt;2088 = MMLXXXVIII&lt;br /&gt;2089 = MMLXXXIX&lt;br /&gt;2090 = MMXC&lt;br /&gt;2091 = MMXCI&lt;br /&gt;2092 = MMXCII&lt;br /&gt;2093 = MMXCIII&lt;br /&gt;2094 = MMXCIV&lt;br /&gt;2095 = MMXCV&lt;br /&gt;2096 = MMXCVI&lt;br /&gt;2097 = MMXCVII&lt;br /&gt;2098 = MMXCVIII&lt;br /&gt;2099 = MMXCIX&lt;br /&gt;2100 = MMC&lt;br /&gt;2101 = MMCI&lt;br /&gt;2102 = MMCII&lt;br /&gt;2103 = MMCIII&lt;br /&gt;2104 = MMCIV&lt;br /&gt;2105 = MMCV&lt;br /&gt;2106 = MMCVI&lt;br /&gt;2107 = MMCVII&lt;br /&gt;2108 = MMCVIII&lt;br /&gt;2109 = MMCIX&lt;br /&gt;2110 = MMCX&lt;br /&gt;2111 = MMCXI&lt;br /&gt;2112 = MMCXII&lt;br /&gt;2113 = MMCXIII&lt;br /&gt;2114 = MMCXIV&lt;br /&gt;2115 = MMCXV&lt;br /&gt;2116 = MMCXVI&lt;br /&gt;2117 = MMCXVII&lt;br /&gt;2118 = MMCXVIII&lt;br /&gt;2119 = MMCXIX&lt;br /&gt;2120 = MMCXX&lt;br /&gt;2121 = MMCXXI&lt;br /&gt;2122 = MMCXXII&lt;br /&gt;2123 = MMCXXIII&lt;br /&gt;2124 = MMCXXIV&lt;br /&gt;2125 = MMCXXV&lt;br /&gt;2126 = MMCXXVI&lt;br /&gt;2127 = MMCXXVII&lt;br /&gt;2128 = MMCXXVIII&lt;br /&gt;2129 = MMCXXIX&lt;br /&gt;2130 = MMCXXX&lt;br /&gt;2131 = MMCXXXI&lt;br /&gt;2132 = MMCXXXII&lt;br /&gt;2133 = MMCXXXIII&lt;br /&gt;2134 = MMCXXXIV&lt;br /&gt;2135 = MMCXXXV&lt;br /&gt;2136 = MMCXXXVI&lt;br /&gt;2137 = MMCXXXVII&lt;br /&gt;2138 = MMCXXXVIII&lt;br /&gt;2139 = MMCXXXIX&lt;br /&gt;2140 = MMCXL&lt;br /&gt;2141 = MMCXLI&lt;br /&gt;2142 = MMCXLII&lt;br /&gt;2143 = MMCXLIII&lt;br /&gt;2144 = MMCXLIV&lt;br /&gt;2145 = MMCXLV&lt;br /&gt;2146 = MMCXLVI&lt;br /&gt;2147 = MMCXLVII&lt;br /&gt;2148 = MMCXLVIII&lt;br /&gt;2149 = MMCXLIX&lt;br /&gt;2150 = MMCL&lt;br /&gt;2151 = MMCLI&lt;br /&gt;2152 = MMCLII&lt;br /&gt;2153 = MMCLIII&lt;br /&gt;2154 = MMCLIV&lt;br /&gt;2155 = MMCLV&lt;br /&gt;2156 = MMCLVI&lt;br /&gt;2157 = MMCLVII&lt;br /&gt;2158 = MMCLVIII&lt;br /&gt;2159 = MMCLIX&lt;br /&gt;2160 = MMCLX&lt;br /&gt;2161 = MMCLXI&lt;br /&gt;2162 = MMCLXII&lt;br /&gt;2163 = MMCLXIII&lt;br /&gt;2164 = MMCLXIV&lt;br /&gt;2165 = MMCLXV&lt;br /&gt;2166 = MMCLXVI&lt;br /&gt;2167 = MMCLXVII&lt;br /&gt;2168 = MMCLXVIII&lt;br /&gt;2169 = MMCLXIX&lt;br /&gt;2170 = MMCLXX&lt;br /&gt;2171 = MMCLXXI&lt;br /&gt;2172 = MMCLXXII&lt;br /&gt;2173 = MMCLXXIII&lt;br /&gt;2174 = MMCLXXIV&lt;br /&gt;2175 = MMCLXXV&lt;br /&gt;2176 = MMCLXXVI&lt;br /&gt;2177 = MMCLXXVII&lt;br /&gt;2178 = MMCLXXVIII&lt;br /&gt;2179 = MMCLXXIX&lt;br /&gt;2180 = MMCLXXX&lt;br /&gt;2181 = MMCLXXXI&lt;br /&gt;2182 = MMCLXXXII&lt;br /&gt;2183 = MMCLXXXIII&lt;br /&gt;2184 = MMCLXXXIV&lt;br /&gt;2185 = MMCLXXXV&lt;br /&gt;2186 = MMCLXXXVI&lt;br /&gt;2187 = MMCLXXXVII&lt;br /&gt;2188 = MMCLXXXVIII&lt;br /&gt;2189 = MMCLXXXIX&lt;br /&gt;2190 = MMCXC&lt;br /&gt;2191 = MMCXCI&lt;br /&gt;2192 = MMCXCII&lt;br /&gt;2193 = MMCXCIII&lt;br /&gt;2194 = MMCXCIV&lt;br /&gt;2195 = MMCXCV&lt;br /&gt;2196 = MMCXCVI&lt;br /&gt;2197 = MMCXCVII&lt;br /&gt;2198 = MMCXCVIII&lt;br /&gt;2199 = MMCXCIX&lt;br /&gt;2200 = MMCC&lt;br /&gt;2201 = MMCCI&lt;br /&gt;2202 = MMCCII&lt;br /&gt;2203 = MMCCIII&lt;br /&gt;2204 = MMCCIV&lt;br /&gt;2205 = MMCCV&lt;br /&gt;2206 = MMCCVI&lt;br /&gt;2207 = MMCCVII&lt;br /&gt;2208 = MMCCVIII&lt;br /&gt;2209 = MMCCIX&lt;br /&gt;2210 = MMCCX&lt;br /&gt;2211 = MMCCXI&lt;br /&gt;2212 = MMCCXII&lt;br /&gt;2213 = MMCCXIII&lt;br /&gt;2214 = MMCCXIV&lt;br /&gt;2215 = MMCCXV&lt;br /&gt;2216 = MMCCXVI&lt;br /&gt;2217 = MMCCXVII&lt;br /&gt;2218 = MMCCXVIII&lt;br /&gt;2219 = MMCCXIX&lt;br /&gt;2220 = MMCCXX&lt;br /&gt;2221 = MMCCXXI&lt;br /&gt;2222 = MMCCXXII&lt;br /&gt;2223 = MMCCXXIII&lt;br /&gt;2224 = MMCCXXIV&lt;br /&gt;2225 = MMCCXXV&lt;br /&gt;2226 = MMCCXXVI&lt;br /&gt;2227 = MMCCXXVII&lt;br /&gt;2228 = MMCCXXVIII&lt;br /&gt;2229 = MMCCXXIX&lt;br /&gt;2230 = MMCCXXX&lt;br /&gt;2231 = MMCCXXXI&lt;br /&gt;2232 = MMCCXXXII&lt;br /&gt;2233 = MMCCXXXIII&lt;br /&gt;2234 = MMCCXXXIV&lt;br /&gt;2235 = MMCCXXXV&lt;br /&gt;2236 = MMCCXXXVI&lt;br /&gt;2237 = MMCCXXXVII&lt;br /&gt;2238 = MMCCXXXVIII&lt;br /&gt;2239 = MMCCXXXIX&lt;br /&gt;2240 = MMCCXL&lt;br /&gt;2241 = MMCCXLI&lt;br /&gt;2242 = MMCCXLII&lt;br /&gt;2243 = MMCCXLIII&lt;br /&gt;2244 = MMCCXLIV&lt;br /&gt;2245 = MMCCXLV&lt;br /&gt;2246 = MMCCXLVI&lt;br /&gt;2247 = MMCCXLVII&lt;br /&gt;2248 = MMCCXLVIII&lt;br /&gt;2249 = MMCCXLIX&lt;br /&gt;2250 = MMCCL&lt;br /&gt;2251 = MMCCLI&lt;br /&gt;2252 = MMCCLII&lt;br /&gt;2253 = MMCCLIII&lt;br /&gt;2254 = MMCCLIV&lt;br /&gt;2255 = MMCCLV&lt;br /&gt;2256 = MMCCLVI&lt;br /&gt;2257 = MMCCLVII&lt;br /&gt;2258 = MMCCLVIII&lt;br /&gt;2259 = MMCCLIX&lt;br /&gt;2260 = MMCCLX&lt;br /&gt;2261 = MMCCLXI&lt;br /&gt;2262 = MMCCLXII&lt;br /&gt;2263 = MMCCLXIII&lt;br /&gt;2264 = MMCCLXIV&lt;br /&gt;2265 = MMCCLXV&lt;br /&gt;2266 = MMCCLXVI&lt;br /&gt;2267 = MMCCLXVII&lt;br /&gt;2268 = MMCCLXVIII&lt;br /&gt;2269 = MMCCLXIX&lt;br /&gt;2270 = MMCCLXX&lt;br /&gt;2271 = MMCCLXXI&lt;br /&gt;2272 = MMCCLXXII&lt;br /&gt;2273 = MMCCLXXIII&lt;br /&gt;2274 = MMCCLXXIV&lt;br /&gt;2275 = MMCCLXXV&lt;br /&gt;2276 = MMCCLXXVI&lt;br /&gt;2277 = MMCCLXXVII&lt;br /&gt;2278 = MMCCLXXVIII&lt;br /&gt;2279 = MMCCLXXIX&lt;br /&gt;2280 = MMCCLXXX&lt;br /&gt;2281 = MMCCLXXXI&lt;br /&gt;2282 = MMCCLXXXII&lt;br /&gt;2283 = MMCCLXXXIII&lt;br /&gt;2284 = MMCCLXXXIV&lt;br /&gt;2285 = MMCCLXXXV&lt;br /&gt;2286 = MMCCLXXXVI&lt;br /&gt;2287 = MMCCLXXXVII&lt;br /&gt;2288 = MMCCLXXXVIII&lt;br /&gt;2289 = MMCCLXXXIX&lt;br /&gt;2290 = MMCCXC&lt;br /&gt;2291 = MMCCXCI&lt;br /&gt;2292 = MMCCXCII&lt;br /&gt;2293 = MMCCXCIII&lt;br /&gt;2294 = MMCCXCIV&lt;br /&gt;2295 = MMCCXCV&lt;br /&gt;2296 = MMCCXCVI&lt;br /&gt;2297 = MMCCXCVII&lt;br /&gt;2298 = MMCCXCVIII&lt;br /&gt;2299 = MMCCXCIX&lt;br /&gt;2300 = MMCCC&lt;br /&gt;2301 = MMCCCI&lt;br /&gt;2302 = MMCCCII&lt;br /&gt;2303 = MMCCCIII&lt;br /&gt;2304 = MMCCCIV&lt;br /&gt;2305 = MMCCCV&lt;br /&gt;2306 = MMCCCVI&lt;br /&gt;2307 = MMCCCVII&lt;br /&gt;2308 = MMCCCVIII&lt;br /&gt;2309 = MMCCCIX&lt;br /&gt;2310 = MMCCCX&lt;br /&gt;2311 = MMCCCXI&lt;br /&gt;2312 = MMCCCXII&lt;br /&gt;2313 = MMCCCXIII&lt;br /&gt;2314 = MMCCCXIV&lt;br /&gt;2315 = MMCCCXV&lt;br /&gt;2316 = MMCCCXVI&lt;br /&gt;2317 = MMCCCXVII&lt;br /&gt;2318 = MMCCCXVIII&lt;br /&gt;2319 = MMCCCXIX&lt;br /&gt;2320 = MMCCCXX&lt;br /&gt;2321 = MMCCCXXI&lt;br /&gt;2322 = MMCCCXXII&lt;br /&gt;2323 = MMCCCXXIII&lt;br /&gt;2324 = MMCCCXXIV&lt;br /&gt;2325 = MMCCCXXV&lt;br /&gt;2326 = MMCCCXXVI&lt;br /&gt;2327 = MMCCCXXVII&lt;br /&gt;2328 = MMCCCXXVIII&lt;br /&gt;2329 = MMCCCXXIX&lt;br /&gt;2330 = MMCCCXXX&lt;br /&gt;2331 = MMCCCXXXI&lt;br /&gt;2332 = MMCCCXXXII&lt;br /&gt;2333 = MMCCCXXXIII&lt;br /&gt;2334 = MMCCCXXXIV&lt;br /&gt;2335 = MMCCCXXXV&lt;br /&gt;2336 = MMCCCXXXVI&lt;br /&gt;2337 = MMCCCXXXVII&lt;br /&gt;2338 = MMCCCXXXVIII&lt;br /&gt;2339 = MMCCCXXXIX&lt;br /&gt;2340 = MMCCCXL&lt;br /&gt;2341 = MMCCCXLI&lt;br /&gt;2342 = MMCCCXLII&lt;br /&gt;2343 = MMCCCXLIII&lt;br /&gt;2344 = MMCCCXLIV&lt;br /&gt;2345 = MMCCCXLV&lt;br /&gt;2346 = MMCCCXLVI&lt;br /&gt;2347 = MMCCCXLVII&lt;br /&gt;2348 = MMCCCXLVIII&lt;br /&gt;2349 = MMCCCXLIX&lt;br /&gt;2350 = MMCCCL&lt;br /&gt;2351 = MMCCCLI&lt;br /&gt;2352 = MMCCCLII&lt;br /&gt;2353 = MMCCCLIII&lt;br /&gt;2354 = MMCCCLIV&lt;br /&gt;2355 = MMCCCLV&lt;br /&gt;2356 = MMCCCLVI&lt;br /&gt;2357 = MMCCCLVII&lt;br /&gt;2358 = MMCCCLVIII&lt;br /&gt;2359 = MMCCCLIX&lt;br /&gt;2360 = MMCCCLX&lt;br /&gt;2361 = MMCCCLXI&lt;br /&gt;2362 = MMCCCLXII&lt;br /&gt;2363 = MMCCCLXIII&lt;br /&gt;2364 = MMCCCLXIV&lt;br /&gt;2365 = MMCCCLXV&lt;br /&gt;2366 = MMCCCLXVI&lt;br /&gt;2367 = MMCCCLXVII&lt;br /&gt;2368 = MMCCCLXVIII&lt;br /&gt;2369 = MMCCCLXIX&lt;br /&gt;2370 = MMCCCLXX&lt;br /&gt;2371 = MMCCCLXXI&lt;br /&gt;2372 = MMCCCLXXII&lt;br /&gt;2373 = MMCCCLXXIII&lt;br /&gt;2374 = MMCCCLXXIV&lt;br /&gt;2375 = MMCCCLXXV&lt;br /&gt;2376 = MMCCCLXXVI&lt;br /&gt;2377 = MMCCCLXXVII&lt;br /&gt;2378 = MMCCCLXXVIII&lt;br /&gt;2379 = MMCCCLXXIX&lt;br /&gt;2380 = MMCCCLXXX&lt;br /&gt;2381 = MMCCCLXXXI&lt;br /&gt;2382 = MMCCCLXXXII&lt;br /&gt;2383 = MMCCCLXXXIII&lt;br /&gt;2384 = MMCCCLXXXIV&lt;br /&gt;2385 = MMCCCLXXXV&lt;br /&gt;2386 = MMCCCLXXXVI&lt;br /&gt;2387 = MMCCCLXXXVII&lt;br /&gt;2388 = MMCCCLXXXVIII&lt;br /&gt;2389 = MMCCCLXXXIX&lt;br /&gt;2390 = MMCCCXC&lt;br /&gt;2391 = MMCCCXCI&lt;br /&gt;2392 = MMCCCXCII&lt;br /&gt;2393 = MMCCCXCIII&lt;br /&gt;2394 = MMCCCXCIV&lt;br /&gt;2395 = MMCCCXCV&lt;br /&gt;2396 = MMCCCXCVI&lt;br /&gt;2397 = MMCCCXCVII&lt;br /&gt;2398 = MMCCCXCVIII&lt;br /&gt;2399 = MMCCCXCIX&lt;br /&gt;2400 = MMCD&lt;br /&gt;2401 = MMCDI&lt;br /&gt;2402 = MMCDII&lt;br /&gt;2403 = MMCDIII&lt;br /&gt;2404 = MMCDIV&lt;br /&gt;2405 = MMCDV&lt;br /&gt;2406 = MMCDVI&lt;br /&gt;2407 = MMCDVII&lt;br /&gt;2408 = MMCDVIII&lt;br /&gt;2409 = MMCDIX&lt;br /&gt;2410 = MMCDX&lt;br /&gt;2411 = MMCDXI&lt;br /&gt;2412 = MMCDXII&lt;br /&gt;2413 = MMCDXIII&lt;br /&gt;2414 = MMCDXIV&lt;br /&gt;2415 = MMCDXV&lt;br /&gt;2416 = MMCDXVI&lt;br /&gt;2417 = MMCDXVII&lt;br /&gt;2418 = MMCDXVIII&lt;br /&gt;2419 = MMCDXIX&lt;br /&gt;2420 = MMCDXX&lt;br /&gt;2421 = MMCDXXI&lt;br /&gt;2422 = MMCDXXII&lt;br /&gt;2423 = MMCDXXIII&lt;br /&gt;2424 = MMCDXXIV&lt;br /&gt;2425 = MMCDXXV&lt;br /&gt;2426 = MMCDXXVI&lt;br /&gt;2427 = MMCDXXVII&lt;br /&gt;2428 = MMCDXXVIII&lt;br /&gt;2429 = MMCDXXIX&lt;br /&gt;2430 = MMCDXXX&lt;br /&gt;2431 = MMCDXXXI&lt;br /&gt;2432 = MMCDXXXII&lt;br /&gt;2433 = MMCDXXXIII&lt;br /&gt;2434 = MMCDXXXIV&lt;br /&gt;2435 = MMCDXXXV&lt;br /&gt;2436 = MMCDXXXVI&lt;br /&gt;2437 = MMCDXXXVII&lt;br /&gt;2438 = MMCDXXXVIII&lt;br /&gt;2439 = MMCDXXXIX&lt;br /&gt;2440 = MMCDXL&lt;br /&gt;2441 = MMCDXLI&lt;br /&gt;2442 = MMCDXLII&lt;br /&gt;2443 = MMCDXLIII&lt;br /&gt;2444 = MMCDXLIV&lt;br /&gt;2445 = MMCDXLV&lt;br /&gt;2446 = MMCDXLVI&lt;br /&gt;2447 = MMCDXLVII&lt;br /&gt;2448 = MMCDXLVIII&lt;br /&gt;2449 = MMCDXLIX&lt;br /&gt;2450 = MMCDL&lt;br /&gt;2451 = MMCDLI&lt;br /&gt;2452 = MMCDLII&lt;br /&gt;2453 = MMCDLIII&lt;br /&gt;2454 = MMCDLIV&lt;br /&gt;2455 = MMCDLV&lt;br /&gt;2456 = MMCDLVI&lt;br /&gt;2457 = MMCDLVII&lt;br /&gt;2458 = MMCDLVIII&lt;br /&gt;2459 = MMCDLIX&lt;br /&gt;2460 = MMCDLX&lt;br /&gt;2461 = MMCDLXI&lt;br /&gt;2462 = MMCDLXII&lt;br /&gt;2463 = MMCDLXIII&lt;br /&gt;2464 = MMCDLXIV&lt;br /&gt;2465 = MMCDLXV&lt;br /&gt;2466 = MMCDLXVI&lt;br /&gt;2467 = MMCDLXVII&lt;br /&gt;2468 = MMCDLXVIII&lt;br /&gt;2469 = MMCDLXIX&lt;br /&gt;2470 = MMCDLXX&lt;br /&gt;2471 = MMCDLXXI&lt;br /&gt;2472 = MMCDLXXII&lt;br /&gt;2473 = MMCDLXXIII&lt;br /&gt;2474 = MMCDLXXIV&lt;br /&gt;2475 = MMCDLXXV&lt;br /&gt;2476 = MMCDLXXVI&lt;br /&gt;2477 = MMCDLXXVII&lt;br /&gt;2478 = MMCDLXXVIII&lt;br /&gt;2479 = MMCDLXXIX&lt;br /&gt;2480 = MMCDLXXX&lt;br /&gt;2481 = MMCDLXXXI&lt;br /&gt;2482 = MMCDLXXXII&lt;br /&gt;2483 = MMCDLXXXIII&lt;br /&gt;2484 = MMCDLXXXIV&lt;br /&gt;2485 = MMCDLXXXV&lt;br /&gt;2486 = MMCDLXXXVI&lt;br /&gt;2487 = MMCDLXXXVII&lt;br /&gt;2488 = MMCDLXXXVIII&lt;br /&gt;2489 = MMCDLXXXIX&lt;br /&gt;2490 = MMCDXC&lt;br /&gt;2491 = MMCDXCI&lt;br /&gt;2492 = MMCDXCII&lt;br /&gt;2493 = MMCDXCIII&lt;br /&gt;2494 = MMCDXCIV&lt;br /&gt;2495 = MMCDXCV&lt;br /&gt;2496 = MMCDXCVI&lt;br /&gt;2497 = MMCDXCVII&lt;br /&gt;2498 = MMCDXCVIII&lt;br /&gt;2499 = MMCDXCIX&lt;br /&gt;2500 = MMD&lt;br /&gt;2501 = MMDI&lt;br /&gt;2502 = MMDII&lt;br /&gt;2503 = MMDIII&lt;br /&gt;2504 = MMDIV&lt;br /&gt;2505 = MMDV&lt;br /&gt;2506 = MMDVI&lt;br /&gt;2507 = MMDVII&lt;br /&gt;2508 = MMDVIII&lt;br /&gt;2509 = MMDIX&lt;br /&gt;2510 = MMDX&lt;br /&gt;2511 = MMDXI&lt;br /&gt;2512 = MMDXII&lt;br /&gt;2513 = MMDXIII&lt;br /&gt;2514 = MMDXIV&lt;br /&gt;2515 = MMDXV&lt;br /&gt;2516 = MMDXVI&lt;br /&gt;2517 = MMDXVII&lt;br /&gt;2518 = MMDXVIII&lt;br /&gt;2519 = MMDXIX&lt;br /&gt;2520 = MMDXX&lt;br /&gt;2521 = MMDXXI&lt;br /&gt;2522 = MMDXXII&lt;br /&gt;2523 = MMDXXIII&lt;br /&gt;2524 = MMDXXIV&lt;br /&gt;2525 = MMDXXV&lt;br /&gt;2526 = MMDXXVI&lt;br /&gt;2527 = MMDXXVII&lt;br /&gt;2528 = MMDXXVIII&lt;br /&gt;2529 = MMDXXIX&lt;br /&gt;2530 = MMDXXX&lt;br /&gt;2531 = MMDXXXI&lt;br /&gt;2532 = MMDXXXII&lt;br /&gt;2533 = MMDXXXIII&lt;br /&gt;2534 = MMDXXXIV&lt;br /&gt;2535 = MMDXXXV&lt;br /&gt;2536 = MMDXXXVI&lt;br /&gt;2537 = MMDXXXVII&lt;br /&gt;2538 = MMDXXXVIII&lt;br /&gt;2539 = MMDXXXIX&lt;br /&gt;2540 = MMDXL&lt;br /&gt;2541 = MMDXLI&lt;br /&gt;2542 = MMDXLII&lt;br /&gt;2543 = MMDXLIII&lt;br /&gt;2544 = MMDXLIV&lt;br /&gt;2545 = MMDXLV&lt;br /&gt;2546 = MMDXLVI&lt;br /&gt;2547 = MMDXLVII&lt;br /&gt;2548 = MMDXLVIII&lt;br /&gt;2549 = MMDXLIX&lt;br /&gt;2550 = MMDL&lt;br /&gt;2551 = MMDLI&lt;br /&gt;2552 = MMDLII&lt;br /&gt;2553 = MMDLIII&lt;br /&gt;2554 = MMDLIV&lt;br /&gt;2555 = MMDLV&lt;br /&gt;2556 = MMDLVI&lt;br /&gt;2557 = MMDLVII&lt;br /&gt;2558 = MMDLVIII&lt;br /&gt;2559 = MMDLIX&lt;br /&gt;2560 = MMDLX&lt;br /&gt;2561 = MMDLXI&lt;br /&gt;2562 = MMDLXII&lt;br /&gt;2563 = MMDLXIII&lt;br /&gt;2564 = MMDLXIV&lt;br /&gt;2565 = MMDLXV&lt;br /&gt;2566 = MMDLXVI&lt;br /&gt;2567 = MMDLXVII&lt;br /&gt;2568 = MMDLXVIII&lt;br /&gt;2569 = MMDLXIX&lt;br /&gt;2570 = MMDLXX&lt;br /&gt;2571 = MMDLXXI&lt;br /&gt;2572 = MMDLXXII&lt;br /&gt;2573 = MMDLXXIII&lt;br /&gt;2574 = MMDLXXIV&lt;br /&gt;2575 = MMDLXXV&lt;br /&gt;2576 = MMDLXXVI&lt;br /&gt;2577 = MMDLXXVII&lt;br /&gt;2578 = MMDLXXVIII&lt;br /&gt;2579 = MMDLXXIX&lt;br /&gt;2580 = MMDLXXX&lt;br /&gt;2581 = MMDLXXXI&lt;br /&gt;2582 = MMDLXXXII&lt;br /&gt;2583 = MMDLXXXIII&lt;br /&gt;2584 = MMDLXXXIV&lt;br /&gt;2585 = MMDLXXXV&lt;br /&gt;2586 = MMDLXXXVI&lt;br /&gt;2587 = MMDLXXXVII&lt;br /&gt;2588 = MMDLXXXVIII&lt;br /&gt;2589 = MMDLXXXIX&lt;br /&gt;2590 = MMDXC&lt;br /&gt;2591 = MMDXCI&lt;br /&gt;2592 = MMDXCII&lt;br /&gt;2593 = MMDXCIII&lt;br /&gt;2594 = MMDXCIV&lt;br /&gt;2595 = MMDXCV&lt;br /&gt;2596 = MMDXCVI&lt;br /&gt;2597 = MMDXCVII&lt;br /&gt;2598 = MMDXCVIII&lt;br /&gt;2599 = MMDXCIX&lt;br /&gt;2600 = MMDC&lt;br /&gt;2601 = MMDCI&lt;br /&gt;2602 = MMDCII&lt;br /&gt;2603 = MMDCIII&lt;br /&gt;2604 = MMDCIV&lt;br /&gt;2605 = MMDCV&lt;br /&gt;2606 = MMDCVI&lt;br /&gt;2607 = MMDCVII&lt;br /&gt;2608 = MMDCVIII&lt;br /&gt;2609 = MMDCIX&lt;br /&gt;2610 = MMDCX&lt;br /&gt;2611 = MMDCXI&lt;br /&gt;2612 = MMDCXII&lt;br /&gt;2613 = MMDCXIII&lt;br /&gt;2614 = MMDCXIV&lt;br /&gt;2615 = MMDCXV&lt;br /&gt;2616 = MMDCXVI&lt;br /&gt;2617 = MMDCXVII&lt;br /&gt;2618 = MMDCXVIII&lt;br /&gt;2619 = MMDCXIX&lt;br /&gt;2620 = MMDCXX&lt;br /&gt;2621 = MMDCXXI&lt;br /&gt;2622 = MMDCXXII&lt;br /&gt;2623 = MMDCXXIII&lt;br /&gt;2624 = MMDCXXIV&lt;br /&gt;2625 = MMDCXXV&lt;br /&gt;2626 = MMDCXXVI&lt;br /&gt;2627 = MMDCXXVII&lt;br /&gt;2628 = MMDCXXVIII&lt;br /&gt;2629 = MMDCXXIX&lt;br /&gt;2630 = MMDCXXX&lt;br /&gt;2631 = MMDCXXXI&lt;br /&gt;2632 = MMDCXXXII&lt;br /&gt;2633 = MMDCXXXIII&lt;br /&gt;2634 = MMDCXXXIV&lt;br /&gt;2635 = MMDCXXXV&lt;br /&gt;2636 = MMDCXXXVI&lt;br /&gt;2637 = MMDCXXXVII&lt;br /&gt;2638 = MMDCXXXVIII&lt;br /&gt;2639 = MMDCXXXIX&lt;br /&gt;2640 = MMDCXL&lt;br /&gt;2641 = MMDCXLI&lt;br /&gt;2642 = MMDCXLII&lt;br /&gt;2643 = MMDCXLIII&lt;br /&gt;2644 = MMDCXLIV&lt;br /&gt;2645 = MMDCXLV&lt;br /&gt;2646 = MMDCXLVI&lt;br /&gt;2647 = MMDCXLVII&lt;br /&gt;2648 = MMDCXLVIII&lt;br /&gt;2649 = MMDCXLIX&lt;br /&gt;2650 = MMDCL&lt;br /&gt;2651 = MMDCLI&lt;br /&gt;2652 = MMDCLII&lt;br /&gt;2653 = MMDCLIII&lt;br /&gt;2654 = MMDCLIV&lt;br /&gt;2655 = MMDCLV&lt;br /&gt;2656 = MMDCLVI&lt;br /&gt;2657 = MMDCLVII&lt;br /&gt;2658 = MMDCLVIII&lt;br /&gt;2659 = MMDCLIX&lt;br /&gt;2660 = MMDCLX&lt;br /&gt;2661 = MMDCLXI&lt;br /&gt;2662 = MMDCLXII&lt;br /&gt;2663 = MMDCLXIII&lt;br /&gt;2664 = MMDCLXIV&lt;br /&gt;2665 = MMDCLXV&lt;br /&gt;2666 = MMDCLXVI&lt;br /&gt;2667 = MMDCLXVII&lt;br /&gt;2668 = MMDCLXVIII&lt;br /&gt;2669 = MMDCLXIX&lt;br /&gt;2670 = MMDCLXX&lt;br /&gt;2671 = MMDCLXXI&lt;br /&gt;2672 = MMDCLXXII&lt;br /&gt;2673 = MMDCLXXIII&lt;br /&gt;2674 = MMDCLXXIV&lt;br /&gt;2675 = MMDCLXXV&lt;br /&gt;2676 = MMDCLXXVI&lt;br /&gt;2677 = MMDCLXXVII&lt;br /&gt;2678 = MMDCLXXVIII&lt;br /&gt;2679 = MMDCLXXIX&lt;br /&gt;2680 = MMDCLXXX&lt;br /&gt;2681 = MMDCLXXXI&lt;br /&gt;2682 = MMDCLXXXII&lt;br /&gt;2683 = MMDCLXXXIII&lt;br /&gt;2684 = MMDCLXXXIV&lt;br /&gt;2685 = MMDCLXXXV&lt;br /&gt;2686 = MMDCLXXXVI&lt;br /&gt;2687 = MMDCLXXXVII&lt;br /&gt;2688 = MMDCLXXXVIII&lt;br /&gt;2689 = MMDCLXXXIX&lt;br /&gt;2690 = MMDCXC&lt;br /&gt;2691 = MMDCXCI&lt;br /&gt;2692 = MMDCXCII&lt;br /&gt;2693 = MMDCXCIII&lt;br /&gt;2694 = MMDCXCIV&lt;br /&gt;2695 = MMDCXCV&lt;br /&gt;2696 = MMDCXCVI&lt;br /&gt;2697 = MMDCXCVII&lt;br /&gt;2698 = MMDCXCVIII&lt;br /&gt;2699 = MMDCXCIX&lt;br /&gt;2700 = MMDCC&lt;br /&gt;2701 = MMDCCI&lt;br /&gt;2702 = MMDCCII&lt;br /&gt;2703 = MMDCCIII&lt;br /&gt;2704 = MMDCCIV&lt;br /&gt;2705 = MMDCCV&lt;br /&gt;2706 = MMDCCVI&lt;br /&gt;2707 = MMDCCVII&lt;br /&gt;2708 = MMDCCVIII&lt;br /&gt;2709 = MMDCCIX&lt;br /&gt;2710 = MMDCCX&lt;br /&gt;2711 = MMDCCXI&lt;br /&gt;2712 = MMDCCXII&lt;br /&gt;2713 = MMDCCXIII&lt;br /&gt;2714 = MMDCCXIV&lt;br /&gt;2715 = MMDCCXV&lt;br /&gt;2716 = MMDCCXVI&lt;br /&gt;2717 = MMDCCXVII&lt;br /&gt;2718 = MMDCCXVIII&lt;br /&gt;2719 = MMDCCXIX&lt;br /&gt;2720 = MMDCCXX&lt;br /&gt;2721 = MMDCCXXI&lt;br /&gt;2722 = MMDCCXXII&lt;br /&gt;2723 = MMDCCXXIII&lt;br /&gt;2724 = MMDCCXXIV&lt;br /&gt;2725 = MMDCCXXV&lt;br /&gt;2726 = MMDCCXXVI&lt;br /&gt;2727 = MMDCCXXVII&lt;br /&gt;2728 = MMDCCXXVIII&lt;br /&gt;2729 = MMDCCXXIX&lt;br /&gt;2730 = MMDCCXXX&lt;br /&gt;2731 = MMDCCXXXI&lt;br /&gt;2732 = MMDCCXXXII&lt;br /&gt;2733 = MMDCCXXXIII&lt;br /&gt;2734 = MMDCCXXXIV&lt;br /&gt;2735 = MMDCCXXXV&lt;br /&gt;2736 = MMDCCXXXVI&lt;br /&gt;2737 = MMDCCXXXVII&lt;br /&gt;2738 = MMDCCXXXVIII&lt;br /&gt;2739 = MMDCCXXXIX&lt;br /&gt;2740 = MMDCCXL&lt;br /&gt;2741 = MMDCCXLI&lt;br /&gt;2742 = MMDCCXLII&lt;br /&gt;2743 = MMDCCXLIII&lt;br /&gt;2744 = MMDCCXLIV&lt;br /&gt;2745 = MMDCCXLV&lt;br /&gt;2746 = MMDCCXLVI&lt;br /&gt;2747 = MMDCCXLVII&lt;br /&gt;2748 = MMDCCXLVIII&lt;br /&gt;2749 = MMDCCXLIX&lt;br /&gt;2750 = MMDCCL&lt;br /&gt;2751 = MMDCCLI&lt;br /&gt;2752 = MMDCCLII&lt;br /&gt;2753 = MMDCCLIII&lt;br /&gt;2754 = MMDCCLIV&lt;br /&gt;2755 = MMDCCLV&lt;br /&gt;2756 = MMDCCLVI&lt;br /&gt;2757 = MMDCCLVII&lt;br /&gt;2758 = MMDCCLVIII&lt;br /&gt;2759 = MMDCCLIX&lt;br /&gt;2760 = MMDCCLX&lt;br /&gt;2761 = MMDCCLXI&lt;br /&gt;2762 = MMDCCLXII&lt;br /&gt;2763 = MMDCCLXIII&lt;br /&gt;2764 = MMDCCLXIV&lt;br /&gt;2765 = MMDCCLXV&lt;br /&gt;2766 = MMDCCLXVI&lt;br /&gt;2767 = MMDCCLXVII&lt;br /&gt;2768 = MMDCCLXVIII&lt;br /&gt;2769 = MMDCCLXIX&lt;br /&gt;2770 = MMDCCLXX&lt;br /&gt;2771 = MMDCCLXXI&lt;br /&gt;2772 = MMDCCLXXII&lt;br /&gt;2773 = MMDCCLXXIII&lt;br /&gt;2774 = MMDCCLXXIV&lt;br /&gt;2775 = MMDCCLXXV&lt;br /&gt;2776 = MMDCCLXXVI&lt;br /&gt;2777 = MMDCCLXXVII&lt;br /&gt;2778 = MMDCCLXXVIII&lt;br /&gt;2779 = MMDCCLXXIX&lt;br /&gt;2780 = MMDCCLXXX&lt;br /&gt;2781 = MMDCCLXXXI&lt;br /&gt;2782 = MMDCCLXXXII&lt;br /&gt;2783 = MMDCCLXXXIII&lt;br /&gt;2784 = MMDCCLXXXIV&lt;br /&gt;2785 = MMDCCLXXXV&lt;br /&gt;2786 = MMDCCLXXXVI&lt;br /&gt;2787 = MMDCCLXXXVII&lt;br /&gt;2788 = MMDCCLXXXVIII&lt;br /&gt;2789 = MMDCCLXXXIX&lt;br /&gt;2790 = MMDCCXC&lt;br /&gt;2791 = MMDCCXCI&lt;br /&gt;2792 = MMDCCXCII&lt;br /&gt;2793 = MMDCCXCIII&lt;br /&gt;2794 = MMDCCXCIV&lt;br /&gt;2795 = MMDCCXCV&lt;br /&gt;2796 = MMDCCXCVI&lt;br /&gt;2797 = MMDCCXCVII&lt;br /&gt;2798 = MMDCCXCVIII&lt;br /&gt;2799 = MMDCCXCIX&lt;br /&gt;2800 = MMDCCC&lt;br /&gt;2801 = MMDCCCI&lt;br /&gt;2802 = MMDCCCII&lt;br /&gt;2803 = MMDCCCIII&lt;br /&gt;2804 = MMDCCCIV&lt;br /&gt;2805 = MMDCCCV&lt;br /&gt;2806 = MMDCCCVI&lt;br /&gt;2807 = MMDCCCVII&lt;br /&gt;2808 = MMDCCCVIII&lt;br /&gt;2809 = MMDCCCIX&lt;br /&gt;2810 = MMDCCCX&lt;br /&gt;2811 = MMDCCCXI&lt;br /&gt;2812 = MMDCCCXII&lt;br /&gt;2813 = MMDCCCXIII&lt;br /&gt;2814 = MMDCCCXIV&lt;br /&gt;2815 = MMDCCCXV&lt;br /&gt;2816 = MMDCCCXVI&lt;br /&gt;2817 = MMDCCCXVII&lt;br /&gt;2818 = MMDCCCXVIII&lt;br /&gt;2819 = MMDCCCXIX&lt;br /&gt;2820 = MMDCCCXX&lt;br /&gt;2821 = MMDCCCXXI&lt;br /&gt;2822 = MMDCCCXXII&lt;br /&gt;2823 = MMDCCCXXIII&lt;br /&gt;2824 = MMDCCCXXIV&lt;br /&gt;2825 = MMDCCCXXV&lt;br /&gt;2826 = MMDCCCXXVI&lt;br /&gt;2827 = MMDCCCXXVII&lt;br /&gt;2828 = MMDCCCXXVIII&lt;br /&gt;2829 = MMDCCCXXIX&lt;br /&gt;2830 = MMDCCCXXX&lt;br /&gt;2831 = MMDCCCXXXI&lt;br /&gt;2832 = MMDCCCXXXII&lt;br /&gt;2833 = MMDCCCXXXIII&lt;br /&gt;2834 = MMDCCCXXXIV&lt;br /&gt;2835 = MMDCCCXXXV&lt;br /&gt;2836 = MMDCCCXXXVI&lt;br /&gt;2837 = MMDCCCXXXVII&lt;br /&gt;2838 = MMDCCCXXXVIII&lt;br /&gt;2839 = MMDCCCXXXIX&lt;br /&gt;2840 = MMDCCCXL&lt;br /&gt;2841 = MMDCCCXLI&lt;br /&gt;2842 = MMDCCCXLII&lt;br /&gt;2843 = MMDCCCXLIII&lt;br /&gt;2844 = MMDCCCXLIV&lt;br /&gt;2845 = MMDCCCXLV&lt;br /&gt;2846 = MMDCCCXLVI&lt;br /&gt;2847 = MMDCCCXLVII&lt;br /&gt;2848 = MMDCCCXLVIII&lt;br /&gt;2849 = MMDCCCXLIX&lt;br /&gt;2850 = MMDCCCL&lt;br /&gt;2851 = MMDCCCLI&lt;br /&gt;2852 = MMDCCCLII&lt;br /&gt;2853 = MMDCCCLIII&lt;br /&gt;2854 = MMDCCCLIV&lt;br /&gt;2855 = MMDCCCLV&lt;br /&gt;2856 = MMDCCCLVI&lt;br /&gt;2857 = MMDCCCLVII&lt;br /&gt;2858 = MMDCCCLVIII&lt;br /&gt;2859 = MMDCCCLIX&lt;br /&gt;2860 = MMDCCCLX&lt;br /&gt;2861 = MMDCCCLXI&lt;br /&gt;2862 = MMDCCCLXII&lt;br /&gt;2863 = MMDCCCLXIII&lt;br /&gt;2864 = MMDCCCLXIV&lt;br /&gt;2865 = MMDCCCLXV&lt;br /&gt;2866 = MMDCCCLXVI&lt;br /&gt;2867 = MMDCCCLXVII&lt;br /&gt;2868 = MMDCCCLXVIII&lt;br /&gt;2869 = MMDCCCLXIX&lt;br /&gt;2870 = MMDCCCLXX&lt;br /&gt;2871 = MMDCCCLXXI&lt;br /&gt;2872 = MMDCCCLXXII&lt;br /&gt;2873 = MMDCCCLXXIII&lt;br /&gt;2874 = MMDCCCLXXIV&lt;br /&gt;2875 = MMDCCCLXXV&lt;br /&gt;2876 = MMDCCCLXXVI&lt;br /&gt;2877 = MMDCCCLXXVII&lt;br /&gt;2878 = MMDCCCLXXVIII&lt;br /&gt;2879 = MMDCCCLXXIX&lt;br /&gt;2880 = MMDCCCLXXX&lt;br /&gt;2881 = MMDCCCLXXXI&lt;br /&gt;2882 = MMDCCCLXXXII&lt;br /&gt;2883 = MMDCCCLXXXIII&lt;br /&gt;2884 = MMDCCCLXXXIV&lt;br /&gt;2885 = MMDCCCLXXXV&lt;br /&gt;2886 = MMDCCCLXXXVI&lt;br /&gt;2887 = MMDCCCLXXXVII&lt;br /&gt;2888 = MMDCCCLXXXVIII&lt;br /&gt;2889 = MMDCCCLXXXIX&lt;br /&gt;2890 = MMDCCCXC&lt;br /&gt;2891 = MMDCCCXCI&lt;br /&gt;2892 = MMDCCCXCII&lt;br /&gt;2893 = MMDCCCXCIII&lt;br /&gt;2894 = MMDCCCXCIV&lt;br /&gt;2895 = MMDCCCXCV&lt;br /&gt;2896 = MMDCCCXCVI&lt;br /&gt;2897 = MMDCCCXCVII&lt;br /&gt;2898 = MMDCCCXCVIII&lt;br /&gt;2899 = MMDCCCXCIX&lt;br /&gt;2900 = MMCM&lt;br /&gt;2901 = MMCMI&lt;br /&gt;2902 = MMCMII&lt;br /&gt;2903 = MMCMIII&lt;br /&gt;2904 = MMCMIV&lt;br /&gt;2905 = MMCMV&lt;br /&gt;2906 = MMCMVI&lt;br /&gt;2907 = MMCMVII&lt;br /&gt;2908 = MMCMVIII&lt;br /&gt;2909 = MMCMIX&lt;br /&gt;2910 = MMCMX&lt;br /&gt;2911 = MMCMXI&lt;br /&gt;2912 = MMCMXII&lt;br /&gt;2913 = MMCMXIII&lt;br /&gt;2914 = MMCMXIV&lt;br /&gt;2915 = MMCMXV&lt;br /&gt;2916 = MMCMXVI&lt;br /&gt;2917 = MMCMXVII&lt;br /&gt;2918 = MMCMXVIII&lt;br /&gt;2919 = MMCMXIX&lt;br /&gt;2920 = MMCMXX&lt;br /&gt;2921 = MMCMXXI&lt;br /&gt;2922 = MMCMXXII&lt;br /&gt;2923 = MMCMXXIII&lt;br /&gt;2924 = MMCMXXIV&lt;br /&gt;2925 = MMCMXXV&lt;br /&gt;2926 = MMCMXXVI&lt;br /&gt;2927 = MMCMXXVII&lt;br /&gt;2928 = MMCMXXVIII&lt;br /&gt;2929 = MMCMXXIX&lt;br /&gt;2930 = MMCMXXX&lt;br /&gt;2931 = MMCMXXXI&lt;br /&gt;2932 = MMCMXXXII&lt;br /&gt;2933 = MMCMXXXIII&lt;br /&gt;2934 = MMCMXXXIV&lt;br /&gt;2935 = MMCMXXXV&lt;br /&gt;2936 = MMCMXXXVI&lt;br /&gt;2937 = MMCMXXXVII&lt;br /&gt;2938 = MMCMXXXVIII&lt;br /&gt;2939 = MMCMXXXIX&lt;br /&gt;2940 = MMCMXL&lt;br /&gt;2941 = MMCMXLI&lt;br /&gt;2942 = MMCMXLII&lt;br /&gt;2943 = MMCMXLIII&lt;br /&gt;2944 = MMCMXLIV&lt;br /&gt;2945 = MMCMXLV&lt;br /&gt;2946 = MMCMXLVI&lt;br /&gt;2947 = MMCMXLVII&lt;br /&gt;2948 = MMCMXLVIII&lt;br /&gt;2949 = MMCMXLIX&lt;br /&gt;2950 = MMCML&lt;br /&gt;2951 = MMCMLI&lt;br /&gt;2952 = MMCMLII&lt;br /&gt;2953 = MMCMLIII&lt;br /&gt;2954 = MMCMLIV&lt;br /&gt;2955 = MMCMLV&lt;br /&gt;2956 = MMCMLVI&lt;br /&gt;2957 = MMCMLVII&lt;br /&gt;2958 = MMCMLVIII&lt;br /&gt;2959 = MMCMLIX&lt;br /&gt;2960 = MMCMLX&lt;br /&gt;2961 = MMCMLXI&lt;br /&gt;2962 = MMCMLXII&lt;br /&gt;2963 = MMCMLXIII&lt;br /&gt;2964 = MMCMLXIV&lt;br /&gt;2965 = MMCMLXV&lt;br /&gt;2966 = MMCMLXVI&lt;br /&gt;2967 = MMCMLXVII&lt;br /&gt;2968 = MMCMLXVIII&lt;br /&gt;2969 = MMCMLXIX&lt;br /&gt;2970 = MMCMLXX&lt;br /&gt;2971 = MMCMLXXI&lt;br /&gt;2972 = MMCMLXXII&lt;br /&gt;2973 = MMCMLXXIII&lt;br /&gt;2974 = MMCMLXXIV&lt;br /&gt;2975 = MMCMLXXV&lt;br /&gt;2976 = MMCMLXXVI&lt;br /&gt;2977 = MMCMLXXVII&lt;br /&gt;2978 = MMCMLXXVIII&lt;br /&gt;2979 = MMCMLXXIX&lt;br /&gt;2980 = MMCMLXXX&lt;br /&gt;2981 = MMCMLXXXI&lt;br /&gt;2982 = MMCMLXXXII&lt;br /&gt;2983 = MMCMLXXXIII&lt;br /&gt;2984 = MMCMLXXXIV&lt;br /&gt;2985 = MMCMLXXXV&lt;br /&gt;2986 = MMCMLXXXVI&lt;br /&gt;2987 = MMCMLXXXVII&lt;br /&gt;2988 = MMCMLXXXVIII&lt;br /&gt;2989 = MMCMLXXXIX&lt;br /&gt;2990 = MMCMXC&lt;br /&gt;2991 = MMCMXCI&lt;br /&gt;2992 = MMCMXCII&lt;br /&gt;2993 = MMCMXCIII&lt;br /&gt;2994 = MMCMXCIV&lt;br /&gt;2995 = MMCMXCV&lt;br /&gt;2996 = MMCMXCVI&lt;br /&gt;2997 = MMCMXCVII&lt;br /&gt;2998 = MMCMXCVIII&lt;br /&gt;2999 = MMCMXCIX&lt;br /&gt;3000 = MMM&lt;br /&gt;3001 = MMMI&lt;br /&gt;3002 = MMMII&lt;br /&gt;3003 = MMMIII&lt;br /&gt;3004 = MMMIV&lt;br /&gt;3005 = MMMV&lt;br /&gt;3006 = MMMVI&lt;br /&gt;3007 = MMMVII&lt;br /&gt;3008 = MMMVIII&lt;br /&gt;3009 = MMMIX&lt;br /&gt;3010 = MMMX&lt;br /&gt;3011 = MMMXI&lt;br /&gt;3012 = MMMXII&lt;br /&gt;3013 = MMMXIII&lt;br /&gt;3014 = MMMXIV&lt;br /&gt;3015 = MMMXV&lt;br /&gt;3016 = MMMXVI&lt;br /&gt;3017 = MMMXVII&lt;br /&gt;3018 = MMMXVIII&lt;br /&gt;3019 = MMMXIX&lt;br /&gt;3020 = MMMXX&lt;br /&gt;3021 = MMMXXI&lt;br /&gt;3022 = MMMXXII&lt;br /&gt;3023 = MMMXXIII&lt;br /&gt;3024 = MMMXXIV&lt;br /&gt;3025 = MMMXXV&lt;br /&gt;3026 = MMMXXVI&lt;br /&gt;3027 = MMMXXVII&lt;br /&gt;3028 = MMMXXVIII&lt;br /&gt;3029 = MMMXXIX&lt;br /&gt;3030 = MMMXXX&lt;br /&gt;3031 = MMMXXXI&lt;br /&gt;3032 = MMMXXXII&lt;br /&gt;3033 = MMMXXXIII&lt;br /&gt;3034 = MMMXXXIV&lt;br /&gt;3035 = MMMXXXV&lt;br /&gt;3036 = MMMXXXVI&lt;br /&gt;3037 = MMMXXXVII&lt;br /&gt;3038 = MMMXXXVIII&lt;br /&gt;3039 = MMMXXXIX&lt;br /&gt;3040 = MMMXL&lt;br /&gt;3041 = MMMXLI&lt;br /&gt;3042 = MMMXLII&lt;br /&gt;3043 = MMMXLIII&lt;br /&gt;3044 = MMMXLIV&lt;br /&gt;3045 = MMMXLV&lt;br /&gt;3046 = MMMXLVI&lt;br /&gt;3047 = MMMXLVII&lt;br /&gt;3048 = MMMXLVIII&lt;br /&gt;3049 = MMMXLIX&lt;br /&gt;3050 = MMML&lt;br /&gt;3051 = MMMLI&lt;br /&gt;3052 = MMMLII&lt;br /&gt;3053 = MMMLIII&lt;br /&gt;3054 = MMMLIV&lt;br /&gt;3055 = MMMLV&lt;br /&gt;3056 = MMMLVI&lt;br /&gt;3057 = MMMLVII&lt;br /&gt;3058 = MMMLVIII&lt;br /&gt;3059 = MMMLIX&lt;br /&gt;3060 = MMMLX&lt;br /&gt;3061 = MMMLXI&lt;br /&gt;3062 = MMMLXII&lt;br /&gt;3063 = MMMLXIII&lt;br /&gt;3064 = MMMLXIV&lt;br /&gt;3065 = MMMLXV&lt;br /&gt;3066 = MMMLXVI&lt;br /&gt;3067 = MMMLXVII&lt;br /&gt;3068 = MMMLXVIII&lt;br /&gt;3069 = MMMLXIX&lt;br /&gt;3070 = MMMLXX&lt;br /&gt;3071 = MMMLXXI&lt;br /&gt;3072 = MMMLXXII&lt;br /&gt;3073 = MMMLXXIII&lt;br /&gt;3074 = MMMLXXIV&lt;br /&gt;3075 = MMMLXXV&lt;br /&gt;3076 = MMMLXXVI&lt;br /&gt;3077 = MMMLXXVII&lt;br /&gt;3078 = MMMLXXVIII&lt;br /&gt;3079 = MMMLXXIX&lt;br /&gt;3080 = MMMLXXX&lt;br /&gt;3081 = MMMLXXXI&lt;br /&gt;3082 = MMMLXXXII&lt;br /&gt;3083 = MMMLXXXIII&lt;br /&gt;3084 = MMMLXXXIV&lt;br /&gt;3085 = MMMLXXXV&lt;br /&gt;3086 = MMMLXXXVI&lt;br /&gt;3087 = MMMLXXXVII&lt;br /&gt;3088 = MMMLXXXVIII&lt;br /&gt;3089 = MMMLXXXIX&lt;br /&gt;3090 = MMMXC&lt;br /&gt;3091 = MMMXCI&lt;br /&gt;3092 = MMMXCII&lt;br /&gt;3093 = MMMXCIII&lt;br /&gt;3094 = MMMXCIV&lt;br /&gt;3095 = MMMXCV&lt;br /&gt;3096 = MMMXCVI&lt;br /&gt;3097 = MMMXCVII&lt;br /&gt;3098 = MMMXCVIII&lt;br /&gt;3099 = MMMXCIX&lt;br /&gt;3100 = MMMC&lt;br /&gt;3101 = MMMCI&lt;br /&gt;3102 = MMMCII&lt;br /&gt;3103 = MMMCIII&lt;br /&gt;3104 = MMMCIV&lt;br /&gt;3105 = MMMCV&lt;br /&gt;3106 = MMMCVI&lt;br /&gt;3107 = MMMCVII&lt;br /&gt;3108 = MMMCVIII&lt;br /&gt;3109 = MMMCIX&lt;br /&gt;3110 = MMMCX&lt;br /&gt;3111 = MMMCXI&lt;br /&gt;3112 = MMMCXII&lt;br /&gt;3113 = MMMCXIII&lt;br /&gt;3114 = MMMCXIV&lt;br /&gt;3115 = MMMCXV&lt;br /&gt;3116 = MMMCXVI&lt;br /&gt;3117 = MMMCXVII&lt;br /&gt;3118 = MMMCXVIII&lt;br /&gt;3119 = MMMCXIX&lt;br /&gt;3120 = MMMCXX&lt;br /&gt;3121 = MMMCXXI&lt;br /&gt;3122 = MMMCXXII&lt;br /&gt;3123 = MMMCXXIII&lt;br /&gt;3124 = MMMCXXIV&lt;br /&gt;3125 = MMMCXXV&lt;br /&gt;3126 = MMMCXXVI&lt;br /&gt;3127 = MMMCXXVII&lt;br /&gt;3128 = MMMCXXVIII&lt;br /&gt;3129 = MMMCXXIX&lt;br /&gt;3130 = MMMCXXX&lt;br /&gt;3131 = MMMCXXXI&lt;br /&gt;3132 = MMMCXXXII&lt;br /&gt;3133 = MMMCXXXIII&lt;br /&gt;3134 = MMMCXXXIV&lt;br /&gt;3135 = MMMCXXXV&lt;br /&gt;3136 = MMMCXXXVI&lt;br /&gt;3137 = MMMCXXXVII&lt;br /&gt;3138 = MMMCXXXVIII&lt;br /&gt;3139 = MMMCXXXIX&lt;br /&gt;3140 = MMMCXL&lt;br /&gt;3141 = MMMCXLI&lt;br /&gt;3142 = MMMCXLII&lt;br /&gt;3143 = MMMCXLIII&lt;br /&gt;3144 = MMMCXLIV&lt;br /&gt;3145 = MMMCXLV&lt;br /&gt;3146 = MMMCXLVI&lt;br /&gt;3147 = MMMCXLVII&lt;br /&gt;3148 = MMMCXLVIII&lt;br /&gt;3149 = MMMCXLIX&lt;br /&gt;3150 = MMMCL&lt;br /&gt;3151 = MMMCLI&lt;br /&gt;3152 = MMMCLII&lt;br /&gt;3153 = MMMCLIII&lt;br /&gt;3154 = MMMCLIV&lt;br /&gt;3155 = MMMCLV&lt;br /&gt;3156 = MMMCLVI&lt;br /&gt;3157 = MMMCLVII&lt;br /&gt;3158 = MMMCLVIII&lt;br /&gt;3159 = MMMCLIX&lt;br /&gt;3160 = MMMCLX&lt;br /&gt;3161 = MMMCLXI&lt;br /&gt;3162 = MMMCLXII&lt;br /&gt;3163 = MMMCLXIII&lt;br /&gt;3164 = MMMCLXIV&lt;br /&gt;3165 = MMMCLXV&lt;br /&gt;3166 = MMMCLXVI&lt;br /&gt;3167 = MMMCLXVII&lt;br /&gt;3168 = MMMCLXVIII&lt;br /&gt;3169 = MMMCLXIX&lt;br /&gt;3170 = MMMCLXX&lt;br /&gt;3171 = MMMCLXXI&lt;br /&gt;3172 = MMMCLXXII&lt;br /&gt;3173 = MMMCLXXIII&lt;br /&gt;3174 = MMMCLXXIV&lt;br /&gt;3175 = MMMCLXXV&lt;br /&gt;3176 = MMMCLXXVI&lt;br /&gt;3177 = MMMCLXXVII&lt;br /&gt;3178 = MMMCLXXVIII&lt;br /&gt;3179 = MMMCLXXIX&lt;br /&gt;3180 = MMMCLXXX&lt;br /&gt;3181 = MMMCLXXXI&lt;br /&gt;3182 = MMMCLXXXII&lt;br /&gt;3183 = MMMCLXXXIII&lt;br /&gt;3184 = MMMCLXXXIV&lt;br /&gt;3185 = MMMCLXXXV&lt;br /&gt;3186 = MMMCLXXXVI&lt;br /&gt;3187 = MMMCLXXXVII&lt;br /&gt;3188 = MMMCLXXXVIII&lt;br /&gt;3189 = MMMCLXXXIX&lt;br /&gt;3190 = MMMCXC&lt;br /&gt;3191 = MMMCXCI&lt;br /&gt;3192 = MMMCXCII&lt;br /&gt;3193 = MMMCXCIII&lt;br /&gt;3194 = MMMCXCIV&lt;br /&gt;3195 = MMMCXCV&lt;br /&gt;3196 = MMMCXCVI&lt;br /&gt;3197 = MMMCXCVII&lt;br /&gt;3198 = MMMCXCVIII&lt;br /&gt;3199 = MMMCXCIX&lt;br /&gt;3200 = MMMCC&lt;br /&gt;3201 = MMMCCI&lt;br /&gt;3202 = MMMCCII&lt;br /&gt;3203 = MMMCCIII&lt;br /&gt;3204 = MMMCCIV&lt;br /&gt;3205 = MMMCCV&lt;br /&gt;3206 = MMMCCVI&lt;br /&gt;3207 = MMMCCVII&lt;br /&gt;3208 = MMMCCVIII&lt;br /&gt;3209 = MMMCCIX&lt;br /&gt;3210 = MMMCCX&lt;br /&gt;3211 = MMMCCXI&lt;br /&gt;3212 = MMMCCXII&lt;br /&gt;3213 = MMMCCXIII&lt;br /&gt;3214 = MMMCCXIV&lt;br /&gt;3215 = MMMCCXV&lt;br /&gt;3216 = MMMCCXVI&lt;br /&gt;3217 = MMMCCXVII&lt;br /&gt;3218 = MMMCCXVIII&lt;br /&gt;3219 = MMMCCXIX&lt;br /&gt;3220 = MMMCCXX&lt;br /&gt;3221 = MMMCCXXI&lt;br /&gt;3222 = MMMCCXXII&lt;br /&gt;3223 = MMMCCXXIII&lt;br /&gt;3224 = MMMCCXXIV&lt;br /&gt;3225 = MMMCCXXV&lt;br /&gt;3226 = MMMCCXXVI&lt;br /&gt;3227 = MMMCCXXVII&lt;br /&gt;3228 = MMMCCXXVIII&lt;br /&gt;3229 = MMMCCXXIX&lt;br /&gt;3230 = MMMCCXXX&lt;br /&gt;3231 = MMMCCXXXI&lt;br /&gt;3232 = MMMCCXXXII&lt;br /&gt;3233 = MMMCCXXXIII&lt;br /&gt;3234 = MMMCCXXXIV&lt;br /&gt;3235 = MMMCCXXXV&lt;br /&gt;3236 = MMMCCXXXVI&lt;br /&gt;3237 = MMMCCXXXVII&lt;br /&gt;3238 = MMMCCXXXVIII&lt;br /&gt;3239 = MMMCCXXXIX&lt;br /&gt;3240 = MMMCCXL&lt;br /&gt;3241 = MMMCCXLI&lt;br /&gt;3242 = MMMCCXLII&lt;br /&gt;3243 = MMMCCXLIII&lt;br /&gt;3244 = MMMCCXLIV&lt;br /&gt;3245 = MMMCCXLV&lt;br /&gt;3246 = MMMCCXLVI&lt;br /&gt;3247 = MMMCCXLVII&lt;br /&gt;3248 = MMMCCXLVIII&lt;br /&gt;3249 = MMMCCXLIX&lt;br /&gt;3250 = MMMCCL&lt;br /&gt;3251 = MMMCCLI&lt;br /&gt;3252 = MMMCCLII&lt;br /&gt;3253 = MMMCCLIII&lt;br /&gt;3254 = MMMCCLIV&lt;br /&gt;3255 = MMMCCLV&lt;br /&gt;3256 = MMMCCLVI&lt;br /&gt;3257 = MMMCCLVII&lt;br /&gt;3258 = MMMCCLVIII&lt;br /&gt;3259 = MMMCCLIX&lt;br /&gt;3260 = MMMCCLX&lt;br /&gt;3261 = MMMCCLXI&lt;br /&gt;3262 = MMMCCLXII&lt;br /&gt;3263 = MMMCCLXIII&lt;br /&gt;3264 = MMMCCLXIV&lt;br /&gt;3265 = MMMCCLXV&lt;br /&gt;3266 = MMMCCLXVI&lt;br /&gt;3267 = MMMCCLXVII&lt;br /&gt;3268 = MMMCCLXVIII&lt;br /&gt;3269 = MMMCCLXIX&lt;br /&gt;3270 = MMMCCLXX&lt;br /&gt;3271 = MMMCCLXXI&lt;br /&gt;3272 = MMMCCLXXII&lt;br /&gt;3273 = MMMCCLXXIII&lt;br /&gt;3274 = MMMCCLXXIV&lt;br /&gt;3275 = MMMCCLXXV&lt;br /&gt;3276 = MMMCCLXXVI&lt;br /&gt;3277 = MMMCCLXXVII&lt;br /&gt;3278 = MMMCCLXXVIII&lt;br /&gt;3279 = MMMCCLXXIX&lt;br /&gt;3280 = MMMCCLXXX&lt;br /&gt;3281 = MMMCCLXXXI&lt;br /&gt;3282 = MMMCCLXXXII&lt;br /&gt;3283 = MMMCCLXXXIII&lt;br /&gt;3284 = MMMCCLXXXIV&lt;br /&gt;3285 = MMMCCLXXXV&lt;br /&gt;3286 = MMMCCLXXXVI&lt;br /&gt;3287 = MMMCCLXXXVII&lt;br /&gt;3288 = MMMCCLXXXVIII&lt;br /&gt;3289 = MMMCCLXXXIX&lt;br /&gt;3290 = MMMCCXC&lt;br /&gt;3291 = MMMCCXCI&lt;br /&gt;3292 = MMMCCXCII&lt;br /&gt;3293 = MMMCCXCIII&lt;br /&gt;3294 = MMMCCXCIV&lt;br /&gt;3295 = MMMCCXCV&lt;br /&gt;3296 = MMMCCXCVI&lt;br /&gt;3297 = MMMCCXCVII&lt;br /&gt;3298 = MMMCCXCVIII&lt;br /&gt;3299 = MMMCCXCIX&lt;br /&gt;3300 = MMMCCC&lt;br /&gt;3301 = MMMCCCI&lt;br /&gt;3302 = MMMCCCII&lt;br /&gt;3303 = MMMCCCIII&lt;br /&gt;3304 = MMMCCCIV&lt;br /&gt;3305 = MMMCCCV&lt;br /&gt;3306 = MMMCCCVI&lt;br /&gt;3307 = MMMCCCVII&lt;br /&gt;3308 = MMMCCCVIII&lt;br /&gt;3309 = MMMCCCIX&lt;br /&gt;3310 = MMMCCCX&lt;br /&gt;3311 = MMMCCCXI&lt;br /&gt;3312 = MMMCCCXII&lt;br /&gt;3313 = MMMCCCXIII&lt;br /&gt;3314 = MMMCCCXIV&lt;br /&gt;3315 = MMMCCCXV&lt;br /&gt;3316 = MMMCCCXVI&lt;br /&gt;3317 = MMMCCCXVII&lt;br /&gt;3318 = MMMCCCXVIII&lt;br /&gt;3319 = MMMCCCXIX&lt;br /&gt;3320 = MMMCCCXX&lt;br /&gt;3321 = MMMCCCXXI&lt;br /&gt;3322 = MMMCCCXXII&lt;br /&gt;3323 = MMMCCCXXIII&lt;br /&gt;3324 = MMMCCCXXIV&lt;br /&gt;3325 = MMMCCCXXV&lt;br /&gt;3326 = MMMCCCXXVI&lt;br /&gt;3327 = MMMCCCXXVII&lt;br /&gt;3328 = MMMCCCXXVIII&lt;br /&gt;3329 = MMMCCCXXIX&lt;br /&gt;3330 = MMMCCCXXX&lt;br /&gt;3331 = MMMCCCXXXI&lt;br /&gt;3332 = MMMCCCXXXII&lt;br /&gt;3333 = MMMCCCXXXIII&lt;br /&gt;3334 = MMMCCCXXXIV&lt;br /&gt;3335 = MMMCCCXXXV&lt;br /&gt;3336 = MMMCCCXXXVI&lt;br /&gt;3337 = MMMCCCXXXVII&lt;br /&gt;3338 = MMMCCCXXXVIII&lt;br /&gt;3339 = MMMCCCXXXIX&lt;br /&gt;3340 = MMMCCCXL&lt;br /&gt;3341 = MMMCCCXLI&lt;br /&gt;3342 = MMMCCCXLII&lt;br /&gt;3343 = MMMCCCXLIII&lt;br /&gt;3344 = MMMCCCXLIV&lt;br /&gt;3345 = MMMCCCXLV&lt;br /&gt;3346 = MMMCCCXLVI&lt;br /&gt;3347 = MMMCCCXLVII&lt;br /&gt;3348 = MMMCCCXLVIII&lt;br /&gt;3349 = MMMCCCXLIX&lt;br /&gt;3350 = MMMCCCL&lt;br /&gt;3351 = MMMCCCLI&lt;br /&gt;3352 = MMMCCCLII&lt;br /&gt;3353 = MMMCCCLIII&lt;br /&gt;3354 = MMMCCCLIV&lt;br /&gt;3355 = MMMCCCLV&lt;br /&gt;3356 = MMMCCCLVI&lt;br /&gt;3357 = MMMCCCLVII&lt;br /&gt;3358 = MMMCCCLVIII&lt;br /&gt;3359 = MMMCCCLIX&lt;br /&gt;3360 = MMMCCCLX&lt;br /&gt;3361 = MMMCCCLXI&lt;br /&gt;3362 = MMMCCCLXII&lt;br /&gt;3363 = MMMCCCLXIII&lt;br /&gt;3364 = MMMCCCLXIV&lt;br /&gt;3365 = MMMCCCLXV&lt;br /&gt;3366 = MMMCCCLXVI&lt;br /&gt;3367 = MMMCCCLXVII&lt;br /&gt;3368 = MMMCCCLXVIII&lt;br /&gt;3369 = MMMCCCLXIX&lt;br /&gt;3370 = MMMCCCLXX&lt;br /&gt;3371 = MMMCCCLXXI&lt;br /&gt;3372 = MMMCCCLXXII&lt;br /&gt;3373 = MMMCCCLXXIII&lt;br /&gt;3374 = MMMCCCLXXIV&lt;br /&gt;3375 = MMMCCCLXXV&lt;br /&gt;3376 = MMMCCCLXXVI&lt;br /&gt;3377 = MMMCCCLXXVII&lt;br /&gt;3378 = MMMCCCLXXVIII&lt;br /&gt;3379 = MMMCCCLXXIX&lt;br /&gt;3380 = MMMCCCLXXX&lt;br /&gt;3381 = MMMCCCLXXXI&lt;br /&gt;3382 = MMMCCCLXXXII&lt;br /&gt;3383 = MMMCCCLXXXIII&lt;br /&gt;3384 = MMMCCCLXXXIV&lt;br /&gt;3385 = MMMCCCLXXXV&lt;br /&gt;3386 = MMMCCCLXXXVI&lt;br /&gt;3387 = MMMCCCLXXXVII&lt;br /&gt;3388 = MMMCCCLXXXVIII&lt;br /&gt;3389 = MMMCCCLXXXIX&lt;br /&gt;3390 = MMMCCCXC&lt;br /&gt;3391 = MMMCCCXCI&lt;br /&gt;3392 = MMMCCCXCII&lt;br /&gt;3393 = MMMCCCXCIII&lt;br /&gt;3394 = MMMCCCXCIV&lt;br /&gt;3395 = MMMCCCXCV&lt;br /&gt;3396 = MMMCCCXCVI&lt;br /&gt;3397 = MMMCCCXCVII&lt;br /&gt;3398 = MMMCCCXCVIII&lt;br /&gt;3399 = MMMCCCXCIX&lt;br /&gt;3400 = MMMCD&lt;br /&gt;3401 = MMMCDI&lt;br /&gt;3402 = MMMCDII&lt;br /&gt;3403 = MMMCDIII&lt;br /&gt;3404 = MMMCDIV&lt;br /&gt;3405 = MMMCDV&lt;br /&gt;3406 = MMMCDVI&lt;br /&gt;3407 = MMMCDVII&lt;br /&gt;3408 = MMMCDVIII&lt;br /&gt;3409 = MMMCDIX&lt;br /&gt;3410 = MMMCDX&lt;br /&gt;3411 = MMMCDXI&lt;br /&gt;3412 = MMMCDXII&lt;br /&gt;3413 = MMMCDXIII&lt;br /&gt;3414 = MMMCDXIV&lt;br /&gt;3415 = MMMCDXV&lt;br /&gt;3416 = MMMCDXVI&lt;br /&gt;3417 = MMMCDXVII&lt;br /&gt;3418 = MMMCDXVIII&lt;br /&gt;3419 = MMMCDXIX&lt;br /&gt;3420 = MMMCDXX&lt;br /&gt;3421 = MMMCDXXI&lt;br /&gt;3422 = MMMCDXXII&lt;br /&gt;3423 = MMMCDXXIII&lt;br /&gt;3424 = MMMCDXXIV&lt;br /&gt;3425 = MMMCDXXV&lt;br /&gt;3426 = MMMCDXXVI&lt;br /&gt;3427 = MMMCDXXVII&lt;br /&gt;3428 = MMMCDXXVIII&lt;br /&gt;3429 = MMMCDXXIX&lt;br /&gt;3430 = MMMCDXXX&lt;br /&gt;3431 = MMMCDXXXI&lt;br /&gt;3432 = MMMCDXXXII&lt;br /&gt;3433 = MMMCDXXXIII&lt;br /&gt;3434 = MMMCDXXXIV&lt;br /&gt;3435 = MMMCDXXXV&lt;br /&gt;3436 = MMMCDXXXVI&lt;br /&gt;3437 = MMMCDXXXVII&lt;br /&gt;3438 = MMMCDXXXVIII&lt;br /&gt;3439 = MMMCDXXXIX&lt;br /&gt;3440 = MMMCDXL&lt;br /&gt;3441 = MMMCDXLI&lt;br /&gt;3442 = MMMCDXLII&lt;br /&gt;3443 = MMMCDXLIII&lt;br /&gt;3444 = MMMCDXLIV&lt;br /&gt;3445 = MMMCDXLV&lt;br /&gt;3446 = MMMCDXLVI&lt;br /&gt;3447 = MMMCDXLVII&lt;br /&gt;3448 = MMMCDXLVIII&lt;br /&gt;3449 = MMMCDXLIX&lt;br /&gt;3450 = MMMCDL&lt;br /&gt;3451 = MMMCDLI&lt;br /&gt;3452 = MMMCDLII&lt;br /&gt;3453 = MMMCDLIII&lt;br /&gt;3454 = MMMCDLIV&lt;br /&gt;3455 = MMMCDLV&lt;br /&gt;3456 = MMMCDLVI&lt;br /&gt;3457 = MMMCDLVII&lt;br /&gt;3458 = MMMCDLVIII&lt;br /&gt;3459 = MMMCDLIX&lt;br /&gt;3460 = MMMCDLX&lt;br /&gt;3461 = MMMCDLXI&lt;br /&gt;3462 = MMMCDLXII&lt;br /&gt;3463 = MMMCDLXIII&lt;br /&gt;3464 = MMMCDLXIV&lt;br /&gt;3465 = MMMCDLXV&lt;br /&gt;3466 = MMMCDLXVI&lt;br /&gt;3467 = MMMCDLXVII&lt;br /&gt;3468 = MMMCDLXVIII&lt;br /&gt;3469 = MMMCDLXIX&lt;br /&gt;3470 = MMMCDLXX&lt;br /&gt;3471 = MMMCDLXXI&lt;br /&gt;3472 = MMMCDLXXII&lt;br /&gt;3473 = MMMCDLXXIII&lt;br /&gt;3474 = MMMCDLXXIV&lt;br /&gt;3475 = MMMCDLXXV&lt;br /&gt;3476 = MMMCDLXXVI&lt;br /&gt;3477 = MMMCDLXXVII&lt;br /&gt;3478 = MMMCDLXXVIII&lt;br /&gt;3479 = MMMCDLXXIX&lt;br /&gt;3480 = MMMCDLXXX&lt;br /&gt;3481 = MMMCDLXXXI&lt;br /&gt;3482 = MMMCDLXXXII&lt;br /&gt;3483 = MMMCDLXXXIII&lt;br /&gt;3484 = MMMCDLXXXIV&lt;br /&gt;3485 = MMMCDLXXXV&lt;br /&gt;3486 = MMMCDLXXXVI&lt;br /&gt;3487 = MMMCDLXXXVII&lt;br /&gt;3488 = MMMCDLXXXVIII&lt;br /&gt;3489 = MMMCDLXXXIX&lt;br /&gt;3490 = MMMCDXC&lt;br /&gt;3491 = MMMCDXCI&lt;br /&gt;3492 = MMMCDXCII&lt;br /&gt;3493 = MMMCDXCIII&lt;br /&gt;3494 = MMMCDXCIV&lt;br /&gt;3495 = MMMCDXCV&lt;br /&gt;3496 = MMMCDXCVI&lt;br /&gt;3497 = MMMCDXCVII&lt;br /&gt;3498 = MMMCDXCVIII&lt;br /&gt;3499 = MMMCDXCIX&lt;br /&gt;3500 = MMMD&lt;br /&gt;3501 = MMMDI&lt;br /&gt;3502 = MMMDII&lt;br /&gt;3503 = MMMDIII&lt;br /&gt;3504 = MMMDIV&lt;br /&gt;3505 = MMMDV&lt;br /&gt;3506 = MMMDVI&lt;br /&gt;3507 = MMMDVII&lt;br /&gt;3508 = MMMDVIII&lt;br /&gt;3509 = MMMDIX&lt;br /&gt;3510 = MMMDX&lt;br /&gt;3511 = MMMDXI&lt;br /&gt;3512 = MMMDXII&lt;br /&gt;3513 = MMMDXIII&lt;br /&gt;3514 = MMMDXIV&lt;br /&gt;3515 = MMMDXV&lt;br /&gt;3516 = MMMDXVI&lt;br /&gt;3517 = MMMDXVII&lt;br /&gt;3518 = MMMDXVIII&lt;br /&gt;3519 = MMMDXIX&lt;br /&gt;3520 = MMMDXX&lt;br /&gt;3521 = MMMDXXI&lt;br /&gt;3522 = MMMDXXII&lt;br /&gt;3523 = MMMDXXIII&lt;br /&gt;3524 = MMMDXXIV&lt;br /&gt;3525 = MMMDXXV&lt;br /&gt;3526 = MMMDXXVI&lt;br /&gt;3527 = MMMDXXVII&lt;br /&gt;3528 = MMMDXXVIII&lt;br /&gt;3529 = MMMDXXIX&lt;br /&gt;3530 = MMMDXXX&lt;br /&gt;3531 = MMMDXXXI&lt;br /&gt;3532 = MMMDXXXII&lt;br /&gt;3533 = MMMDXXXIII&lt;br /&gt;3534 = MMMDXXXIV&lt;br /&gt;3535 = MMMDXXXV&lt;br /&gt;3536 = MMMDXXXVI&lt;br /&gt;3537 = MMMDXXXVII&lt;br /&gt;3538 = MMMDXXXVIII&lt;br /&gt;3539 = MMMDXXXIX&lt;br /&gt;3540 = MMMDXL&lt;br /&gt;3541 = MMMDXLI&lt;br /&gt;3542 = MMMDXLII&lt;br /&gt;3543 = MMMDXLIII&lt;br /&gt;3544 = MMMDXLIV&lt;br /&gt;3545 = MMMDXLV&lt;br /&gt;3546 = MMMDXLVI&lt;br /&gt;3547 = MMMDXLVII&lt;br /&gt;3548 = MMMDXLVIII&lt;br /&gt;3549 = MMMDXLIX&lt;br /&gt;3550 = MMMDL&lt;br /&gt;3551 = MMMDLI&lt;br /&gt;3552 = MMMDLII&lt;br /&gt;3553 = MMMDLIII&lt;br /&gt;3554 = MMMDLIV&lt;br /&gt;3555 = MMMDLV&lt;br /&gt;3556 = MMMDLVI&lt;br /&gt;3557 = MMMDLVII&lt;br /&gt;3558 = MMMDLVIII&lt;br /&gt;3559 = MMMDLIX&lt;br /&gt;3560 = MMMDLX&lt;br /&gt;3561 = MMMDLXI&lt;br /&gt;3562 = MMMDLXII&lt;br /&gt;3563 = MMMDLXIII&lt;br /&gt;3564 = MMMDLXIV&lt;br /&gt;3565 = MMMDLXV&lt;br /&gt;3566 = MMMDLXVI&lt;br /&gt;3567 = MMMDLXVII&lt;br /&gt;3568 = MMMDLXVIII&lt;br /&gt;3569 = MMMDLXIX&lt;br /&gt;3570 = MMMDLXX&lt;br /&gt;3571 = MMMDLXXI&lt;br /&gt;3572 = MMMDLXXII&lt;br /&gt;3573 = MMMDLXXIII&lt;br /&gt;3574 = MMMDLXXIV&lt;br /&gt;3575 = MMMDLXXV&lt;br /&gt;3576 = MMMDLXXVI&lt;br /&gt;3577 = MMMDLXXVII&lt;br /&gt;3578 = MMMDLXXVIII&lt;br /&gt;3579 = MMMDLXXIX&lt;br /&gt;3580 = MMMDLXXX&lt;br /&gt;3581 = MMMDLXXXI&lt;br /&gt;3582 = MMMDLXXXII&lt;br /&gt;3583 = MMMDLXXXIII&lt;br /&gt;3584 = MMMDLXXXIV&lt;br /&gt;3585 = MMMDLXXXV&lt;br /&gt;3586 = MMMDLXXXVI&lt;br /&gt;3587 = MMMDLXXXVII&lt;br /&gt;3588 = MMMDLXXXVIII&lt;br /&gt;3589 = MMMDLXXXIX&lt;br /&gt;3590 = MMMDXC&lt;br /&gt;3591 = MMMDXCI&lt;br /&gt;3592 = MMMDXCII&lt;br /&gt;3593 = MMMDXCIII&lt;br /&gt;3594 = MMMDXCIV&lt;br /&gt;3595 = MMMDXCV&lt;br /&gt;3596 = MMMDXCVI&lt;br /&gt;3597 = MMMDXCVII&lt;br /&gt;3598 = MMMDXCVIII&lt;br /&gt;3599 = MMMDXCIX&lt;br /&gt;3600 = MMMDC&lt;br /&gt;3601 = MMMDCI&lt;br /&gt;3602 = MMMDCII&lt;br /&gt;3603 = MMMDCIII&lt;br /&gt;3604 = MMMDCIV&lt;br /&gt;3605 = MMMDCV&lt;br /&gt;3606 = MMMDCVI&lt;br /&gt;3607 = MMMDCVII&lt;br /&gt;3608 = MMMDCVIII&lt;br /&gt;3609 = MMMDCIX&lt;br /&gt;3610 = MMMDCX&lt;br /&gt;3611 = MMMDCXI&lt;br /&gt;3612 = MMMDCXII&lt;br /&gt;3613 = MMMDCXIII&lt;br /&gt;3614 = MMMDCXIV&lt;br /&gt;3615 = MMMDCXV&lt;br /&gt;3616 = MMMDCXVI&lt;br /&gt;3617 = MMMDCXVII&lt;br /&gt;3618 = MMMDCXVIII&lt;br /&gt;3619 = MMMDCXIX&lt;br /&gt;3620 = MMMDCXX&lt;br /&gt;3621 = MMMDCXXI&lt;br /&gt;3622 = MMMDCXXII&lt;br /&gt;3623 = MMMDCXXIII&lt;br /&gt;3624 = MMMDCXXIV&lt;br /&gt;3625 = MMMDCXXV&lt;br /&gt;3626 = MMMDCXXVI&lt;br /&gt;3627 = MMMDCXXVII&lt;br /&gt;3628 = MMMDCXXVIII&lt;br /&gt;3629 = MMMDCXXIX&lt;br /&gt;3630 = MMMDCXXX&lt;br /&gt;3631 = MMMDCXXXI&lt;br /&gt;3632 = MMMDCXXXII&lt;br /&gt;3633 = MMMDCXXXIII&lt;br /&gt;3634 = MMMDCXXXIV&lt;br /&gt;3635 = MMMDCXXXV&lt;br /&gt;3636 = MMMDCXXXVI&lt;br /&gt;3637 = MMMDCXXXVII&lt;br /&gt;3638 = MMMDCXXXVIII&lt;br /&gt;3639 = MMMDCXXXIX&lt;br /&gt;3640 = MMMDCXL&lt;br /&gt;3641 = MMMDCXLI&lt;br /&gt;3642 = MMMDCXLII&lt;br /&gt;3643 = MMMDCXLIII&lt;br /&gt;3644 = MMMDCXLIV&lt;br /&gt;3645 = MMMDCXLV&lt;br /&gt;3646 = MMMDCXLVI&lt;br /&gt;3647 = MMMDCXLVII&lt;br /&gt;3648 = MMMDCXLVIII&lt;br /&gt;3649 = MMMDCXLIX&lt;br /&gt;3650 = MMMDCL&lt;br /&gt;3651 = MMMDCLI&lt;br /&gt;3652 = MMMDCLII&lt;br /&gt;3653 = MMMDCLIII&lt;br /&gt;3654 = MMMDCLIV&lt;br /&gt;3655 = MMMDCLV&lt;br /&gt;3656 = MMMDCLVI&lt;br /&gt;3657 = MMMDCLVII&lt;br /&gt;3658 = MMMDCLVIII&lt;br /&gt;3659 = MMMDCLIX&lt;br /&gt;3660 = MMMDCLX&lt;br /&gt;3661 = MMMDCLXI&lt;br /&gt;3662 = MMMDCLXII&lt;br /&gt;3663 = MMMDCLXIII&lt;br /&gt;3664 = MMMDCLXIV&lt;br /&gt;3665 = MMMDCLXV&lt;br /&gt;3666 = MMMDCLXVI&lt;br /&gt;3667 = MMMDCLXVII&lt;br /&gt;3668 = MMMDCLXVIII&lt;br /&gt;3669 = MMMDCLXIX&lt;br /&gt;3670 = MMMDCLXX&lt;br /&gt;3671 = MMMDCLXXI&lt;br /&gt;3672 = MMMDCLXXII&lt;br /&gt;3673 = MMMDCLXXIII&lt;br /&gt;3674 = MMMDCLXXIV&lt;br /&gt;3675 = MMMDCLXXV&lt;br /&gt;3676 = MMMDCLXXVI&lt;br /&gt;3677 = MMMDCLXXVII&lt;br /&gt;3678 = MMMDCLXXVIII&lt;br /&gt;3679 = MMMDCLXXIX&lt;br /&gt;3680 = MMMDCLXXX&lt;br /&gt;3681 = MMMDCLXXXI&lt;br /&gt;3682 = MMMDCLXXXII&lt;br /&gt;3683 = MMMDCLXXXIII&lt;br /&gt;3684 = MMMDCLXXXIV&lt;br /&gt;3685 = MMMDCLXXXV&lt;br /&gt;3686 = MMMDCLXXXVI&lt;br /&gt;3687 = MMMDCLXXXVII&lt;br /&gt;3688 = MMMDCLXXXVIII&lt;br /&gt;3689 = MMMDCLXXXIX&lt;br /&gt;3690 = MMMDCXC&lt;br /&gt;3691 = MMMDCXCI&lt;br /&gt;3692 = MMMDCXCII&lt;br /&gt;3693 = MMMDCXCIII&lt;br /&gt;3694 = MMMDCXCIV&lt;br /&gt;3695 = MMMDCXCV&lt;br /&gt;3696 = MMMDCXCVI&lt;br /&gt;3697 = MMMDCXCVII&lt;br /&gt;3698 = MMMDCXCVIII&lt;br /&gt;3699 = MMMDCXCIX&lt;br /&gt;3700 = MMMDCC&lt;br /&gt;3701 = MMMDCCI&lt;br /&gt;3702 = MMMDCCII&lt;br /&gt;3703 = MMMDCCIII&lt;br /&gt;3704 = MMMDCCIV&lt;br /&gt;3705 = MMMDCCV&lt;br /&gt;3706 = MMMDCCVI&lt;br /&gt;3707 = MMMDCCVII&lt;br /&gt;3708 = MMMDCCVIII&lt;br /&gt;3709 = MMMDCCIX&lt;br /&gt;3710 = MMMDCCX&lt;br /&gt;3711 = MMMDCCXI&lt;br /&gt;3712 = MMMDCCXII&lt;br /&gt;3713 = MMMDCCXIII&lt;br /&gt;3714 = MMMDCCXIV&lt;br /&gt;3715 = MMMDCCXV&lt;br /&gt;3716 = MMMDCCXVI&lt;br /&gt;3717 = MMMDCCXVII&lt;br /&gt;3718 = MMMDCCXVIII&lt;br /&gt;3719 = MMMDCCXIX&lt;br /&gt;3720 = MMMDCCXX&lt;br /&gt;3721 = MMMDCCXXI&lt;br /&gt;3722 = MMMDCCXXII&lt;br /&gt;3723 = MMMDCCXXIII&lt;br /&gt;3724 = MMMDCCXXIV&lt;br /&gt;3725 = MMMDCCXXV&lt;br /&gt;3726 = MMMDCCXXVI&lt;br /&gt;3727 = MMMDCCXXVII&lt;br /&gt;3728 = MMMDCCXXVIII&lt;br /&gt;3729 = MMMDCCXXIX&lt;br /&gt;3730 = MMMDCCXXX&lt;br /&gt;3731 = MMMDCCXXXI&lt;br /&gt;3732 = MMMDCCXXXII&lt;br /&gt;3733 = MMMDCCXXXIII&lt;br /&gt;3734 = MMMDCCXXXIV&lt;br /&gt;3735 = MMMDCCXXXV&lt;br /&gt;3736 = MMMDCCXXXVI&lt;br /&gt;3737 = MMMDCCXXXVII&lt;br /&gt;3738 = MMMDCCXXXVIII&lt;br /&gt;3739 = MMMDCCXXXIX&lt;br /&gt;3740 = MMMDCCXL&lt;br /&gt;3741 = MMMDCCXLI&lt;br /&gt;3742 = MMMDCCXLII&lt;br /&gt;3743 = MMMDCCXLIII&lt;br /&gt;3744 = MMMDCCXLIV&lt;br /&gt;3745 = MMMDCCXLV&lt;br /&gt;3746 = MMMDCCXLVI&lt;br /&gt;3747 = MMMDCCXLVII&lt;br /&gt;3748 = MMMDCCXLVIII&lt;br /&gt;3749 = MMMDCCXLIX&lt;br /&gt;3750 = MMMDCCL&lt;br /&gt;3751 = MMMDCCLI&lt;br /&gt;3752 = MMMDCCLII&lt;br /&gt;3753 = MMMDCCLIII&lt;br /&gt;3754 = MMMDCCLIV&lt;br /&gt;3755 = MMMDCCLV&lt;br /&gt;3756 = MMMDCCLVI&lt;br /&gt;3757 = MMMDCCLVII&lt;br /&gt;3758 = MMMDCCLVIII&lt;br /&gt;3759 = MMMDCCLIX&lt;br /&gt;3760 = MMMDCCLX&lt;br /&gt;3761 = MMMDCCLXI&lt;br /&gt;3762 = MMMDCCLXII&lt;br /&gt;3763 = MMMDCCLXIII&lt;br /&gt;3764 = MMMDCCLXIV&lt;br /&gt;3765 = MMMDCCLXV&lt;br /&gt;3766 = MMMDCCLXVI&lt;br /&gt;3767 = MMMDCCLXVII&lt;br /&gt;3768 = MMMDCCLXVIII&lt;br /&gt;3769 = MMMDCCLXIX&lt;br /&gt;3770 = MMMDCCLXX&lt;br /&gt;3771 = MMMDCCLXXI&lt;br /&gt;3772 = MMMDCCLXXII&lt;br /&gt;3773 = MMMDCCLXXIII&lt;br /&gt;3774 = MMMDCCLXXIV&lt;br /&gt;3775 = MMMDCCLXXV&lt;br /&gt;3776 = MMMDCCLXXVI&lt;br /&gt;3777 = MMMDCCLXXVII&lt;br /&gt;3778 = MMMDCCLXXVIII&lt;br /&gt;3779 = MMMDCCLXXIX&lt;br /&gt;3780 = MMMDCCLXXX&lt;br /&gt;3781 = MMMDCCLXXXI&lt;br /&gt;3782 = MMMDCCLXXXII&lt;br /&gt;3783 = MMMDCCLXXXIII&lt;br /&gt;3784 = MMMDCCLXXXIV&lt;br /&gt;3785 = MMMDCCLXXXV&lt;br /&gt;3786 = MMMDCCLXXXVI&lt;br /&gt;3787 = MMMDCCLXXXVII&lt;br /&gt;3788 = MMMDCCLXXXVIII&lt;br /&gt;3789 = MMMDCCLXXXIX&lt;br /&gt;3790 = MMMDCCXC&lt;br /&gt;3791 = MMMDCCXCI&lt;br /&gt;3792 = MMMDCCXCII&lt;br /&gt;3793 = MMMDCCXCIII&lt;br /&gt;3794 = MMMDCCXCIV&lt;br /&gt;3795 = MMMDCCXCV&lt;br /&gt;3796 = MMMDCCXCVI&lt;br /&gt;3797 = MMMDCCXCVII&lt;br /&gt;3798 = MMMDCCXCVIII&lt;br /&gt;3799 = MMMDCCXCIX&lt;br /&gt;3800 = MMMDCCC&lt;br /&gt;3801 = MMMDCCCI&lt;br /&gt;3802 = MMMDCCCII&lt;br /&gt;3803 = MMMDCCCIII&lt;br /&gt;3804 = MMMDCCCIV&lt;br /&gt;3805 = MMMDCCCV&lt;br /&gt;3806 = MMMDCCCVI&lt;br /&gt;3807 = MMMDCCCVII&lt;br /&gt;3808 = MMMDCCCVIII&lt;br /&gt;3809 = MMMDCCCIX&lt;br /&gt;3810 = MMMDCCCX&lt;br /&gt;3811 = MMMDCCCXI&lt;br /&gt;3812 = MMMDCCCXII&lt;br /&gt;3813 = MMMDCCCXIII&lt;br /&gt;3814 = MMMDCCCXIV&lt;br /&gt;3815 = MMMDCCCXV&lt;br /&gt;3816 = MMMDCCCXVI&lt;br /&gt;3817 = MMMDCCCXVII&lt;br /&gt;3818 = MMMDCCCXVIII&lt;br /&gt;3819 = MMMDCCCXIX&lt;br /&gt;3820 = MMMDCCCXX&lt;br /&gt;3821 = MMMDCCCXXI&lt;br /&gt;3822 = MMMDCCCXXII&lt;br /&gt;3823 = MMMDCCCXXIII&lt;br /&gt;3824 = MMMDCCCXXIV&lt;br /&gt;3825 = MMMDCCCXXV&lt;br /&gt;3826 = MMMDCCCXXVI&lt;br /&gt;3827 = MMMDCCCXXVII&lt;br /&gt;3828 = MMMDCCCXXVIII&lt;br /&gt;3829 = MMMDCCCXXIX&lt;br /&gt;3830 = MMMDCCCXXX&lt;br /&gt;3831 = MMMDCCCXXXI&lt;br /&gt;3832 = MMMDCCCXXXII&lt;br /&gt;3833 = MMMDCCCXXXIII&lt;br /&gt;3834 = MMMDCCCXXXIV&lt;br /&gt;3835 = MMMDCCCXXXV&lt;br /&gt;3836 = MMMDCCCXXXVI&lt;br /&gt;3837 = MMMDCCCXXXVII&lt;br /&gt;3838 = MMMDCCCXXXVIII&lt;br /&gt;3839 = MMMDCCCXXXIX&lt;br /&gt;3840 = MMMDCCCXL&lt;br /&gt;3841 = MMMDCCCXLI&lt;br /&gt;3842 = MMMDCCCXLII&lt;br /&gt;3843 = MMMDCCCXLIII&lt;br /&gt;3844 = MMMDCCCXLIV&lt;br /&gt;3845 = MMMDCCCXLV&lt;br /&gt;3846 = MMMDCCCXLVI&lt;br /&gt;3847 = MMMDCCCXLVII&lt;br /&gt;3848 = MMMDCCCXLVIII&lt;br /&gt;3849 = MMMDCCCXLIX&lt;br /&gt;3850 = MMMDCCCL&lt;br /&gt;3851 = MMMDCCCLI&lt;br /&gt;3852 = MMMDCCCLII&lt;br /&gt;3853 = MMMDCCCLIII&lt;br /&gt;3854 = MMMDCCCLIV&lt;br /&gt;3855 = MMMDCCCLV&lt;br /&gt;3856 = MMMDCCCLVI&lt;br /&gt;3857 = MMMDCCCLVII&lt;br /&gt;3858 = MMMDCCCLVIII&lt;br /&gt;3859 = MMMDCCCLIX&lt;br /&gt;3860 = MMMDCCCLX&lt;br /&gt;3861 = MMMDCCCLXI&lt;br /&gt;3862 = MMMDCCCLXII&lt;br /&gt;3863 = MMMDCCCLXIII&lt;br /&gt;3864 = MMMDCCCLXIV&lt;br /&gt;3865 = MMMDCCCLXV&lt;br /&gt;3866 = MMMDCCCLXVI&lt;br /&gt;3867 = MMMDCCCLXVII&lt;br /&gt;3868 = MMMDCCCLXVIII&lt;br /&gt;3869 = MMMDCCCLXIX&lt;br /&gt;3870 = MMMDCCCLXX&lt;br /&gt;3871 = MMMDCCCLXXI&lt;br /&gt;3872 = MMMDCCCLXXII&lt;br /&gt;3873 = MMMDCCCLXXIII&lt;br /&gt;3874 = MMMDCCCLXXIV&lt;br /&gt;3875 = MMMDCCCLXXV&lt;br /&gt;3876 = MMMDCCCLXXVI&lt;br /&gt;3877 = MMMDCCCLXXVII&lt;br /&gt;3878 = MMMDCCCLXXVIII&lt;br /&gt;3879 = MMMDCCCLXXIX&lt;br /&gt;3880 = MMMDCCCLXXX&lt;br /&gt;3881 = MMMDCCCLXXXI&lt;br /&gt;3882 = MMMDCCCLXXXII&lt;br /&gt;3883 = MMMDCCCLXXXIII&lt;br /&gt;3884 = MMMDCCCLXXXIV&lt;br /&gt;3885 = MMMDCCCLXXXV&lt;br /&gt;3886 = MMMDCCCLXXXVI&lt;br /&gt;3887 = MMMDCCCLXXXVII&lt;br /&gt;3888 = MMMDCCCLXXXVIII&lt;br /&gt;3889 = MMMDCCCLXXXIX&lt;br /&gt;3890 = MMMDCCCXC&lt;br /&gt;3891 = MMMDCCCXCI&lt;br /&gt;3892 = MMMDCCCXCII&lt;br /&gt;3893 = MMMDCCCXCIII&lt;br /&gt;3894 = MMMDCCCXCIV&lt;br /&gt;3895 = MMMDCCCXCV&lt;br /&gt;3896 = MMMDCCCXCVI&lt;br /&gt;3897 = MMMDCCCXCVII&lt;br /&gt;3898 = MMMDCCCXCVIII&lt;br /&gt;3899 = MMMDCCCXCIX&lt;br /&gt;3900 = MMMCM&lt;br /&gt;3901 = MMMCMI&lt;br /&gt;3902 = MMMCMII&lt;br /&gt;3903 = MMMCMIII&lt;br /&gt;3904 = MMMCMIV&lt;br /&gt;3905 = MMMCMV&lt;br /&gt;3906 = MMMCMVI&lt;br /&gt;3907 = MMMCMVII&lt;br /&gt;3908 = MMMCMVIII&lt;br /&gt;3909 = MMMCMIX&lt;br /&gt;3910 = MMMCMX&lt;br /&gt;3911 = MMMCMXI&lt;br /&gt;3912 = MMMCMXII&lt;br /&gt;3913 = MMMCMXIII&lt;br /&gt;3914 = MMMCMXIV&lt;br /&gt;3915 = MMMCMXV&lt;br /&gt;3916 = MMMCMXVI&lt;br /&gt;3917 = MMMCMXVII&lt;br /&gt;3918 = MMMCMXVIII&lt;br /&gt;3919 = MMMCMXIX&lt;br /&gt;3920 = MMMCMXX&lt;br /&gt;3921 = MMMCMXXI&lt;br /&gt;3922 = MMMCMXXII&lt;br /&gt;3923 = MMMCMXXIII&lt;br /&gt;3924 = MMMCMXXIV&lt;br /&gt;3925 = MMMCMXXV&lt;br /&gt;3926 = MMMCMXXVI&lt;br /&gt;3927 = MMMCMXXVII&lt;br /&gt;3928 = MMMCMXXVIII&lt;br /&gt;3929 = MMMCMXXIX&lt;br /&gt;3930 = MMMCMXXX&lt;br /&gt;3931 = MMMCMXXXI&lt;br /&gt;3932 = MMMCMXXXII&lt;br /&gt;3933 = MMMCMXXXIII&lt;br /&gt;3934 = MMMCMXXXIV&lt;br /&gt;3935 = MMMCMXXXV&lt;br /&gt;3936 = MMMCMXXXVI&lt;br /&gt;3937 = MMMCMXXXVII&lt;br /&gt;3938 = MMMCMXXXVIII&lt;br /&gt;3939 = MMMCMXXXIX&lt;br /&gt;3940 = MMMCMXL&lt;br /&gt;3941 = MMMCMXLI&lt;br /&gt;3942 = MMMCMXLII&lt;br /&gt;3943 = MMMCMXLIII&lt;br /&gt;3944 = MMMCMXLIV&lt;br /&gt;3945 = MMMCMXLV&lt;br /&gt;3946 = MMMCMXLVI&lt;br /&gt;3947 = MMMCMXLVII&lt;br /&gt;3948 = MMMCMXLVIII&lt;br /&gt;3949 = MMMCMXLIX&lt;br /&gt;3950 = MMMCML&lt;br /&gt;3951 = MMMCMLI&lt;br /&gt;3952 = MMMCMLII&lt;br /&gt;3953 = MMMCMLIII&lt;br /&gt;3954 = MMMCMLIV&lt;br /&gt;3955 = MMMCMLV&lt;br /&gt;3956 = MMMCMLVI&lt;br /&gt;3957 = MMMCMLVII&lt;br /&gt;3958 = MMMCMLVIII&lt;br /&gt;3959 = MMMCMLIX&lt;br /&gt;3960 = MMMCMLX&lt;br /&gt;3961 = MMMCMLXI&lt;br /&gt;3962 = MMMCMLXII&lt;br /&gt;3963 = MMMCMLXIII&lt;br /&gt;3964 = MMMCMLXIV&lt;br /&gt;3965 = MMMCMLXV&lt;br /&gt;3966 = MMMCMLXVI&lt;br /&gt;3967 = MMMCMLXVII&lt;br /&gt;3968 = MMMCMLXVIII&lt;br /&gt;3969 = MMMCMLXIX&lt;br /&gt;3970 = MMMCMLXX&lt;br /&gt;3971 = MMMCMLXXI&lt;br /&gt;3972 = MMMCMLXXII&lt;br /&gt;3973 = MMMCMLXXIII&lt;br /&gt;3974 = MMMCMLXXIV&lt;br /&gt;3975 = MMMCMLXXV&lt;br /&gt;3976 = MMMCMLXXVI&lt;br /&gt;3977 = MMMCMLXXVII&lt;br /&gt;3978 = MMMCMLXXVIII&lt;br /&gt;3979 = MMMCMLXXIX&lt;br /&gt;3980 = MMMCMLXXX&lt;br /&gt;3981 = MMMCMLXXXI&lt;br /&gt;3982 = MMMCMLXXXII&lt;br /&gt;3983 = MMMCMLXXXIII&lt;br /&gt;3984 = MMMCMLXXXIV&lt;br /&gt;3985 = MMMCMLXXXV&lt;br /&gt;3986 = MMMCMLXXXVI&lt;br /&gt;3987 = MMMCMLXXXVII&lt;br /&gt;3988 = MMMCMLXXXVIII&lt;br /&gt;3989 = MMMCMLXXXIX&lt;br /&gt;3990 = MMMCMXC&lt;br /&gt;3991 = MMMCMXCI&lt;br /&gt;3992 = MMMCMXCII&lt;br /&gt;3993 = MMMCMXCIII&lt;br /&gt;3994 = MMMCMXCIV&lt;br /&gt;3995 = MMMCMXCV&lt;br /&gt;3996 = MMMCMXCVI&lt;br /&gt;3997 = MMMCMXCVII&lt;br /&gt;3998 = MMMCMXCVIII&lt;br /&gt;3999 = MMMCMXCIX&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11885757-757497807665613101?l=cautery.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cautery.blogspot.com/feeds/757497807665613101/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://cautery.blogspot.com/2010/10/javascript-roman-numeral-calculator.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/757497807665613101'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/757497807665613101'/><link rel='alternate' type='text/html' href='http://cautery.blogspot.com/2010/10/javascript-roman-numeral-calculator.html' title='JavaScript Roman numeral calculator'/><author><name>Curtis Autery</name><uri>https://profiles.google.com/107677530285177731535</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/--J3C_khtLqQ/AAAAAAAAAAI/AAAAAAAADT4/e2Qa5ncfAMk/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11885757.post-2096171650018831301</id><published>2010-10-07T20:30:00.002-04:00</published><updated>2010-10-10T05:49:49.717-04:00</updated><title type='text'>Korn shell hack of the day</title><content type='html'>or, "Scope creep and you, a typical example of the modern IT project"&lt;br /&gt;&lt;br /&gt;Sometimes I find myself knee deep in a complicated shell script that probably would have been better off written in perl or Java. Today was one of those days. What started as a simple script I wrote for managing sftp traffic to a couple vendors has been transmogrified to handle calling Glub to do an ftps transfer (the "other" secure FTP) from a vendor, then delivering the files to an internal Windows share drive. So far so good, but feature bloat ended up straining my creativity to tackle each new problem, and ultimately saddled me with a workable solution that, while interesting, is sort of a stinker.&lt;br /&gt;&lt;br /&gt;The connection to the Windows share was supposed to be via a mounted drive. I would copy the files to a Unix directory, and Unix would manage the SMB transfer transparently. This turned out to be unsupported by our data services group unless the Windows server in question was virtual. It was not. So suddenly I'm on the hook for adding SMB support to the process.&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;A quick search revealed the JCIFS library, which I was able to turn into a Java class that takes commandline inputs for destination server and path, and reads credentials from a config file. Just call "java ToShare" instead of Unix's "cp", and Bob's your uncle. Of course, the script has to grow a little bit to handle the extra config variables, where to find java, and what the classpath should be.&lt;br /&gt;&lt;br /&gt;Second, the Windows guy was having problems automating unzipping the files before feeding them to his app. For whatever reason, the approach we settled on was to have my script unzip the files, and send him the artifacts AND the original .zip files. So the script needed to grow in complexity, managing unzipping and iterating through the unzipped artifacts, and the source archives, and sending each over my java SMB hack. Which looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;# Simple log function. Echo the date and passed message to the logfile&lt;br /&gt;logit(){&lt;br /&gt;  echo "`date` $1" &amp;gt;&amp;gt; $LOGFILE&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;# If there's an error, call this, which sends a notification email and exits&lt;br /&gt;error_handler() {&lt;br /&gt;  echo "$1" | mailx -s"FTPS receive script failure" $ERROR_EMAIL_ADDRESS&lt;br /&gt;  logit "$1"&lt;br /&gt;  exit 1&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;# Error checker which run after most commands, if the return code from the previous command&lt;br /&gt;# isn't 0, give the error message specified to error_handler.&lt;br /&gt;check_error() {&lt;br /&gt;  if [ $? -gt 0 ]&lt;br /&gt;  then&lt;br /&gt;    error_handler "$1"&lt;br /&gt;  fi&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;# Find all the files we downloaded, and unzip them, sending output to the logfile&lt;br /&gt;find $LOCAL_DIR/* -prune -name "$REMOTE_FILE_PATTERN" -exec unzip -d $LOCAL_DIR {} &amp;gt;&amp;gt; $LOGFILE \;&lt;br /&gt;check_error "unzip failed"&lt;br /&gt;&lt;br /&gt;# Output from unzip will contain either "inflating" or "extracting" for each file in the archive.&lt;br /&gt;# Look for these messages in the log file, find the filename part, and iterate over them&lt;br /&gt;for file in `grep -e inflating: -e extracting: $LOGFILE | awk '{print $2}'`&lt;br /&gt;do&lt;br /&gt;  # Run the SMB program to send the file to the Windows share...&lt;br /&gt;  $SMB_CMDLINE ToShare $file $SMB_SERVER $SMB_PATH&lt;br /&gt;  check_error "Failed to copy $file to $SMB_SERVER"&lt;br /&gt;  # ...and then delete it. This is fine because the original zipped files are untouched.&lt;br /&gt;  rm $file&lt;br /&gt;  check_error "Failed to delete $file"&lt;br /&gt;done&lt;br /&gt;&lt;br /&gt;# Next, do the same thing for the zipped files themselves...&lt;br /&gt;for file in `find $LOCAL_DIR/* -prune -name "$REMOTE_FILE_PATTERN"`&lt;br /&gt;do&lt;br /&gt;  $SMB_CMDLINE ToShare $file $SMB_SERVER $SMB_PATH&lt;br /&gt;  check_error "Failed to copy $file to $SMB_SERVER"&lt;br /&gt;  # ...except just move the files to an archive directory&lt;br /&gt;  mv $file $LOCAL_ARCHIVE_DIR&lt;br /&gt;check_error "Failed to archive $file"&lt;br /&gt;done&lt;br /&gt;logit "Files successfully copied to $SMB_SERVER, moving files on remote server to archive directory"&lt;/pre&gt;&lt;br /&gt;After adding this functionality, I was cursing my desire to do this in shell instead of writing a real program. But as these things go, the project's timeline was short, and starting over was out of the question. Plus, as I'm wont to do, I gave a lot of assurances that a file transfer script was a no-brainer before I had all the facts - one of the facts being that the vendor was using ftps, not sftp as advertised, the whole reason I chose this script template in the first place.&lt;br /&gt;&lt;br /&gt;Third, the vendor requested that after downloading files, that they be moved to an archive directory on the vendor's ftps server. Normally it's polite to delete a file after you download it from a vendor, as it saves them space requirements, and can also let them know at a glance what files have been pulled. Moving a file to another directory is asked for rarely, but usually isn't a problem. For this process, however, multiple files would be available at once, all of which had timestamps in the filename instead of fixed names. A tolerable approach would have been to download and delete using mget and mdel, but there is no facility in standard ftp clients for batch renames on the remote server.&lt;br /&gt;&lt;br /&gt;Had I started with perl, I could have played with named pipes and searching logfiles for filenames to build a set of rename commands to print to the pipe. Had I started with Java, I could have used the Glub bean and managed the ftps session on the fly, getting a file list and iterating over it with RETR and RNFR/RNTO commands. And there wasn't time to do either. And the Unix "expect" program wasn't installed, so I couldn't manage the ftps session that way. No, I was unfortunately going to have to do this in &lt;b&gt;two&lt;/b&gt; sessions. Workable, but ugly, and it's generally considered bad mojo to log on to a server twice in the same process. But that's what I did.&lt;br /&gt;&lt;br /&gt;Fortunately, Glub logs all the server RETR commands, giving me something simple to grep for with which to build a list:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;# Build the multiple rename (mren) string. For each logfile line starting with "RETR",&lt;br /&gt;# print out a corresponding line that says "rename (file) archive/(file)", save as $MREN&lt;br /&gt;export MREN=`perl -lne 'if (/^RETR /){s!RETR (.+)!rename $1 $ENV{REMOTE_ARCHIVE_DIR}/$1!;print}' $LOGFILE`&lt;br /&gt;&lt;br /&gt;# Log on to remote ftps server, execute $MREN lines&lt;br /&gt;$JAVA -Dglub.user.dir=$HOME -Duser.dir=$FTPS -jar $FTPS/secureftp2.jar &amp;lt;&amp;lt;EOF&lt;br /&gt;log $LOGFILE&lt;br /&gt;open $FTPS_HOST $FTPS_PORT&lt;br /&gt;user $FTPS_USER $FTPS_PASS&lt;br /&gt;cd $REMOTE_DIR&lt;br /&gt;$MREN&lt;br /&gt;bye&lt;br /&gt;EOF&lt;br /&gt;check_error "ftps archive session failed"&lt;br /&gt;&lt;br /&gt;logit "Session successful"&lt;/pre&gt;&lt;br /&gt;So eventually I'll be able to circle around and write this in a more sensible manner, or better yet, convince the vendor that they're better off if I just delete the files, and the Windows people that unzipping is really a breeze. The good news to all this madness is that I added about 10% to my commandline Unix bag of tricks, and you really can do a lot of neat stuff with shell scripts.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11885757-2096171650018831301?l=cautery.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cautery.blogspot.com/feeds/2096171650018831301/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://cautery.blogspot.com/2010/10/korn-shell-hack-of-day.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/2096171650018831301'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/2096171650018831301'/><link rel='alternate' type='text/html' href='http://cautery.blogspot.com/2010/10/korn-shell-hack-of-day.html' title='Korn shell hack of the day'/><author><name>Curtis Autery</name><uri>https://profiles.google.com/107677530285177731535</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/--J3C_khtLqQ/AAAAAAAAAAI/AAAAAAAADT4/e2Qa5ncfAMk/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11885757.post-638561017284763313</id><published>2010-10-03T08:13:00.003-04:00</published><updated>2010-10-03T08:23:39.061-04:00</updated><title type='text'>Picnic with the missus</title><content type='html'>Liberty got this cool wicker picnic basket on eBay a while ago, and we decided to take it out for a spin yesterday. One of the better side effects of "bill week" (when your bills all come due at once, and your budget spreadsheet looks a little scary) is that you can find fun money savers that double as relationship builders.&lt;br /&gt;&lt;br /&gt;Instead of spending $20 on a movie and snacks just to sit in the dark and be quiet, let's go out for a walk in the sunshine and talk to each other... for free. Instead of stopping for greasy fast food somewhere, or spending more at a better restaurant, let's cook up some food for lunch, and take it with us somewhere. In this case, "some food" was steak cut into strips and fried up with pepper, sweet Italian mini bread, cheddar cheese cut into slices, some green onion, and a refreshing carbonated beverage (the basket has a cool separate area for bottles), and "somewhere" was Highbanks park.&lt;br /&gt;&lt;br /&gt;When we got there, we found a long trail that didn't seem to have a lot of people on it, and proceeded to hike around looking for unofficial exit points: Good places to hang out that are accessible, hidden from the trail, but without signs saying not to go there. What we found was here:&lt;br /&gt;&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;iframe frameborder="0" height="350" marginheight="0" marginwidth="0" scrolling="no" src="http://maps.google.com/maps?q=40.154587,-83.033053&amp;amp;num=1&amp;amp;t=h&amp;amp;sll=40.126174,-82.92907&amp;amp;sspn=0.068271,0.128059&amp;amp;ie=UTF8&amp;amp;ll=40.154589,-83.032949&amp;amp;spn=0.001367,0.00284&amp;amp;z=14&amp;amp;output=embed" width="425"&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;small&gt;&lt;a href="http://maps.google.com/maps?q=40.154587,-83.033053&amp;amp;num=1&amp;amp;t=h&amp;amp;sll=40.126174,-82.92907&amp;amp;sspn=0.068271,0.128059&amp;amp;ie=UTF8&amp;amp;ll=40.154589,-83.032949&amp;amp;spn=0.001367,0.00284&amp;amp;z=14&amp;amp;source=embed" style="color: blue; text-align: left;"&gt;View Larger Map&lt;/a&gt;&lt;/small&gt;&lt;br /&gt;&lt;br /&gt;Although the spot wasn't visible from the main trail (Dripping Rock, I believe), another trail frequented with dog walkers came close to it, and there was an occasional group of walkers coming near enough to see us, had they been paying attention to their surroundings. I think a couple people noticed us, but most people walked right by, oblivious.&lt;br /&gt;&lt;br /&gt;At one point, a ranger came driving by in one of their little Jeeps, who was for all appearances looking for people hiding in the woods. He happened to turn his head the other way as he drove by - twice! Once on the way out from his station, once on the way back to it. Funny, but, I mean, come on dude! At any rate, we spread our blanket, ate our makeshift steak sandwiches, chatted, watched the clouds, and left the area as we found it - minus a few burrs, that is.&lt;br /&gt;&lt;br /&gt;While hiking and rescuing the occasional woolly worm, we also people-watched. We had higher hopes for our fellow man there. Since we were in the woods, people should be healthier and less mainstream, no? "The Game" was on, so clearly the people at the park that day shouldn't be uber-consumer sports fans, and they should mostly be healthier and not couch potatoes. So one would think, but not the case. No matter how far we got from the main non-trail area, we would still hear the occasional yawp of joy as some sort of praiseworthy action from the game was reported on the radio. For some the exercise of walking up the trail's first hill was clearly the most punishment they had given their body in some time. There was also the occasional person walking on the trail while talking on their cellphone, forgivable, but lame. One of the families walking had an indifferent dad who busied himself with looking at trees or fields, making sure to keep himself a few feet away from his wife and kids. Why are you out with your family, exactly? If you don't like them, cut the cord now and lessen the pain on everyone. Don't put on the thin facade of just being stoic when your family can feel the vacuum where your love is supposed to be. Asshole. That part was the worst.&lt;br /&gt;&lt;br /&gt;All was not lost, though. Most of the groups were clearly happy to be both together and out trekking through the woods. Most of the people were, indeed, healthy. There was this 50-something woman running with a practiced pace, listening to her iPod, and looking like she could confidently stave off attacks from local bears or mountain lions... I'm fairly certain we have neither, but still, when the fight goes down, I want granny on my side.&lt;br /&gt;&lt;br /&gt;Lastly, there was a family whose mom or eldest daughter (I couldn't tell her age very well) was clearly recovering from cancer treatments, as she had the telltale wig, missing eyebrows, and extra lipstick, and was more fatigued than the rest of her group. But still out building up strength, building strong family bonds, and looking forward. When you hike the trail despite feeling bad, you're looking forward. When you let your family bring you to the park for the "fresh air" and just sit at a picnic table, you're waiting to die. She was looking forward, as was her family, who wasn't treating her as though she were fragile. That part was the best.&lt;br /&gt;&lt;br /&gt;We had a lot of fun on the cheap. Despite the few stinkers, most of the people ranged from tolerable to downright enjoyable. And although next weekend I should have some actual disposable income, maybe we'll just bank it and do something free and outside instead.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11885757-638561017284763313?l=cautery.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cautery.blogspot.com/feeds/638561017284763313/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://cautery.blogspot.com/2010/10/picnic-with-missus.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/638561017284763313'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/638561017284763313'/><link rel='alternate' type='text/html' href='http://cautery.blogspot.com/2010/10/picnic-with-missus.html' title='Picnic with the missus'/><author><name>Curtis Autery</name><uri>https://profiles.google.com/107677530285177731535</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/--J3C_khtLqQ/AAAAAAAAAAI/AAAAAAAADT4/e2Qa5ncfAMk/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11885757.post-1143739936616131668</id><published>2010-09-30T06:27:00.003-04:00</published><updated>2010-09-30T06:38:39.392-04:00</updated><title type='text'>Bezier Curves as Ellipses</title><content type='html'>A couple weeks ago, I was exploring the source code for the Java runtime classes, trying to figure out exactly how Java draws a circle, and was surprised at what I found. A circle can be defined as an instance of the java.awt.geom.Ellipse2D class with equal width and height. Graphics2D attempts to draw the Ellipse2D shape by calling for its PathIterator. A PathIterator returns segments of the shape in the form of SEG_MOVETO, SEG_LINETO, SEG_QUADTO (quadratic Bezier curve), SEG_CUBICTO (cubic Bezier curve), or SEG_CLOSE. An Ellipse2D contains an initial MOVETO, four CUBICTO segments, and a final CLOSE.&lt;br /&gt;&lt;br /&gt;I eventually got my head around what that meant and its implication: The standard 2D graphics library doesn't concern itself with center points and radii, or foci, or pi. In fact, it doesn't even render a &lt;em&gt;real&lt;/em&gt; circle, but a very close approximation. It renders four cubic Bezier curves representing 90 degree arcs of the circle. I found this discovery strange at the time, but on reflection it made sense.&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;First, turning the radius and angle into Cartesian coordinates requires using sine and cosine functions. Java doesn't contain its own sine calculator or lookup table, it delegates to a native library. Second, once all the Bezier control points are established, no expensive division or square roots need to be done in order to calculate the curve. Only addition, subtraction, and multiplication. Third, while conic sections can all be represented by Bezier curves, the reverse is not true, so if you had to pick one, Bezier would be it. Lastly, applying affine transforms to curves is as easy as applying the transforms to the control points and redrawing. So basically these curves look the same to the naked eye as a circle, and are easier on the processor to render. Whether or not that's why the Java developers went that direction, I have no idea.&lt;br /&gt;&lt;br /&gt;So, what's a Bezier curve, anyway?&lt;br /&gt;&lt;br /&gt;A Quadratic Bezier curve is a distortion to a straight line with a single "control point" that has influence over it, acting like a sort of gravity well. The closer a point on the line would be to the control point, the more the curve is distorted from the line.&lt;br /&gt;&lt;br /&gt;Plotting the curve is surprisingly simple. Start with a line between the start and control points, and another between the control and end points.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://lh5.ggpht.com/_YH1HTjXGzNU/TKO-CtF73wI/AAAAAAAADF0/fCm6KB5WMNk/s800/BezierPre.PNG" /&gt;&lt;br /&gt;&lt;br /&gt;Next, pick a percentage, that we'll call "t". Plot a point t% between start and control, and another t% between control and end. Draw a line between these points. On this ancillary line, the point at t% gets added to the curve.&lt;br /&gt;&lt;br /&gt;That's it. Repeat this for all possible "t"s, and you have your curve. Below is a simplified example, showing t at 25%, 50%, and 75%:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://lh6.ggpht.com/_YH1HTjXGzNU/TKO-C70LofI/AAAAAAAADF4/d6wBNwexzDs/s800/Bezier25.PNG" /&gt; &lt;img src="http://lh5.ggpht.com/_YH1HTjXGzNU/TKO-DGZNlQI/AAAAAAAADF8/Gy7GGeqhTgg/s800/Bezier50.PNG" /&gt;&lt;br /&gt;&lt;img src="http://lh3.ggpht.com/_YH1HTjXGzNU/TKO-DpTpQjI/AAAAAAAADGA/OTPFGKtX5oc/s800/Bezier75.PNG" /&gt; &lt;img src="http://lh3.ggpht.com/_YH1HTjXGzNU/TKO-DgIdr8I/AAAAAAAADGE/TulLsJiJMxA/s800/Bezier100.PNG" /&gt;&lt;br /&gt;&lt;br /&gt;This shows the same curve at 5% iterations instead of in quarters, showing more detail of the curved shape:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://lh5.ggpht.com/_YH1HTjXGzNU/TKPBn5Se04I/AAAAAAAADGM/tgclboPX14g/s800/BezierPoints.PNG" /&gt;&lt;br /&gt;&lt;br /&gt;A Cubic Bezier curve functions on the same basic principle, except there is an additional control point distorting the curve. Plotting them out is similar, but you have two ancillary lines instead of one, which you draw an... ancillarier? tertiary? line between, as illustrated here:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://lh6.ggpht.com/_YH1HTjXGzNU/TKPPuKQaQ4I/AAAAAAAADGU/H_zCQ_KvtO4/s800/Cubic25.PNG" /&gt; &lt;img src="http://lh5.ggpht.com/_YH1HTjXGzNU/TKPPuP0pAWI/AAAAAAAADGY/YbiIhWiZ6y8/s800/Cubic50.PNG" /&gt; &lt;img src="http://lh4.ggpht.com/_YH1HTjXGzNU/TKPPuQOToqI/AAAAAAAADGc/PxMTRk_88TQ/s800/Cubic75.PNG" /&gt;&lt;br /&gt;&lt;br /&gt;You can make fancier shapes with a cubic curve, such as moving one control point on the opposite side of the start/end line to make an s-shape:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://lh4.ggpht.com/_YH1HTjXGzNU/TKRY0Z520kI/AAAAAAAADGo/s5ML0k3gN3M/s800/CubicS.PNG" /&gt;&lt;br /&gt;&lt;br /&gt;Neat, but doesn't help us draw a circle. What does, however, is the equation for kappa, &lt;img src="http://lh5.ggpht.com/_YH1HTjXGzNU/TKRgWD1sZUI/AAAAAAAADG4/0mR9rZ9oMfA/s800/kappa.png" /&gt;, which G. Adam Stanislav derives for us &lt;a href="http://www.whizkidtech.redprince.net/bezier/circle/kappa/"&gt;here&lt;/a&gt;. If the start and end points are on opposite corners of a square, and control points are on perpendicular lines, each kappa * side away from a termination point, a circular arc is drawn:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://lh3.ggpht.com/_YH1HTjXGzNU/TKRgWFkCSqI/AAAAAAAADGw/lPeKcawzweE/s800/arc50.PNG" /&gt; &lt;img src="http://lh3.ggpht.com/_YH1HTjXGzNU/TKRgWMtKrKI/AAAAAAAADG0/k_dT3yfFzUo/s800/arc100.PNG" /&gt;&lt;br /&gt;&lt;br /&gt;...which is the way Java does it. The equation for kappa evaluates to roughly .5522847498307933, which Java has as a static variable in the java.awt.geom.EllipseIterator class, to avoid needing to calculate a square root every time a circle is drawn.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;public static final double CtrlVal = 0.5522847498307933;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11885757-1143739936616131668?l=cautery.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cautery.blogspot.com/feeds/1143739936616131668/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://cautery.blogspot.com/2010/09/bezier-curves-as-ellipses.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/1143739936616131668'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/11885757/posts/default/1143739936616131668'/><link rel='alternate' type='text/html' href='http://cautery.blogspot.com/2010/09/bezier-curves-as-ellipses.html' title='Bezier Curves as Ellipses'/><author><name>Curtis Autery</name><uri>https://profiles.google.com/107677530285177731535</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/--J3C_khtLqQ/AAAAAAAAAAI/AAAAAAAADT4/e2Qa5ncfAMk/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_YH1HTjXGzNU/TKO-CtF73wI/AAAAAAAADF0/fCm6KB5WMNk/s72-c/BezierPre.PNG' height='72' width='72'/><thr:total>1</thr:total></entry></feed>
