/* Web Automata version 1.1a, Copyright (C) 2005,2006 Tagata Akira This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ var title = 'Web Automata'; var copyright = '© 2005,2006 Tagata Akira'; var version = '1.1a'; // ---------------------------------------------------------------- function w3cdom() { return document.createElement && document.getElementsByTagName; } // ---------------------------------------------------------------- function automaton(uTickTack,opElmId) { if (!(this.w3cdom = w3cdom())) return; this.sleep || (this.sleep = 2.0); if (!this.stop) { this.stop = tickPause; this.showDebugInfo = showDebugInfo; this.eraseDebugInfo = eraseDebugInfo; } this.dbgMode || (this.dbgMode = 0); var opid = 'start-stop'; var dbgid = 'debug-info'; this.opid = opid; this.dbgid = dbgid var x = document.createElement('BUTTON'); x.id = this.opid; // x.type = 'button'; var d = document.createElement('SPAN'); d.id = this.dbgid; var y = document.getElementById(opElmId); y.appendChild(x); // append op y.appendChild(d); // append dbg this.opElm = document.getElementById(this.opid); this.dbgElm = document.getElementById(this.dbgid); this.tickStart = tickStart; this.tickStop = tickStop; this.tickTack = tickTack; this.uTickTack = uTickTack; // initialyze this.tick = 0; this.msec = 0; this.csec = 0; this.dsec = 0; this.sec = 0; // method this.msecChanged = msecChanged; this.csecChanged = csecChanged; this.dsecChanged = dsecChanged; this.secChanged = secChanged; this.second = second; // for interval optimization this.optimizing = 1; this.interval = 250; // init this.intervalPrev = this.interval; this.otick = 0; // init this.omsec = 0; // init this.trials = 1; // init this.trialMax = 8192; this.optTimeThreshold = 600; // 10 min. in sec this.intervalLowerLimit = 10; fakeobj = this; // set to global variable this.start = tickStart; } // ---------------------------------------------------------------- function tickStart() { var stopText = fakeobj.stopText || 'Stop'; var opNodee = document.getElementById(fakeobj.opid); opNodee.onclick = fakeobj.tickStop; if (opNodee.childNodes[0]) { opNodee.removeChild(opNodee.childNodes[0]); } opNodee.appendChild(document.createTextNode(stopText)); var C = Math.round(this.interval * (1 + 1/this.sleep)); this.msecNow = msec() - C; // initialyze fakeobj.tickTack(); } // ---------------------------------------------------------------- function tickStop(e) { if (!e) var e = window.event; window.clearTimeout(fakeobj.tid); var startText = fakeobj.startText || 'Start'; var opNodee = document.getElementById(fakeobj.opid); opNodee.onclick = fakeobj.tickStart; if (opNodee.childNodes[0]) { opNodee.removeChild(opNodee.childNodes[0]); } opNodee.appendChild(document.createTextNode(startText)); fakeobj.stop && fakeobj.stop(e); } // ---------------------------------------------------------------- function showDebugInfo() { var debug = 'sleep:'+this.sleep+', '+ 'tick:'+this.tick+', msec:'+this.msec+', sec:'+this.sec+', interval:'+this.interval+', trials:'+this.trials+', opt:'+this.optimizing; var debugInfo = document.createTextNode(debug); // var node = document.getElementById(this.dbgid); var node = this.dbgElm; if (node.childNodes[0]) { node.removeChild(node.childNodes[0]); } node.appendChild(debugInfo); } // ---------------------------------------------------------------- function eraseDebugInfo() { // var node = document.getElementById(this.dbgid); var node = this.dbgElm; if (node.childNodes[0]) { node.removeChild(node.childNodes[0]); } } // ---------------------------------------------------------------- function tickPause(e) { if (e.shiftKey) { this.dbgMode = 1; this.showDebugInfo(); } else { this.dbgMode = 0; this.eraseDebugInfo(); } } // ---------------------------------------------------------------- function fakeTickTack() { fakeobj.tickTack(); } // ---------------------------------------------------------------- function tickTack() { if (this.dbgMode && this.secChanged()) { this.showDebugInfo(); } if (this.optimizing) { if (this.otick < this.trials) { this.otick++; } else { var intervalTmp = ((this.msec - this.omsec)/this.otick - this.interval)*this.sleep; if (intervalTmp < 0) { // alert('msec:'+this.msec+', omsec:'+this.omsec+', otick:'+this.otick+', interval:'+this.interval); intervalTmp = this.intervalLowerLimit; } this.trials <<= 1; // duplicate if (this.trials < this.trialMax && (this.interval * this.otick / 1000) < this.optTimeThreshold) { if (this.interval > intervalTmp) { this.intervalPrev = this.interval; this.interval = intervalTmp; } this.otick = 0; this.omsec = this.msec; } else { // terminate optimization, and set largest one this.optimizing = 0; if (this.intervalPrev < intervalTmp) { this.interval = intervalTmp; } else { this.interval = this.intervalPrev; } } } } var msecLast = this.msecNow; this.msecNow = msec(); // get now msec from system ++this.tick; this.msecLast = this.msec; this.csecLast = this.csec; this.dsecLast = this.dsec; this.secLast = this.sec; // set msec this.msec += this.msecNow - msecLast; var sec1 = this.msec >> 4; // /16 var sec2 = sec1 >> 3; // /128 var sec3 = sec2 >> 3; // /1024 this.csec = sec1; this.dsec = sec2; this.sec = sec3; this.uTickTack(); // if (!resizing) { this.tid = window.setTimeout(fakeTickTack, this.interval); // } } // ---------------------------------------------------------------- function msec() { var time = new Date(); return time.getTime(); } // ---------------------------------------------------------------- function msecChanged() { return this.msec - this.msecLast; } // ---------------------------------------------------------------- function csecChanged() { return this.csec - this.csecLast; } // ---------------------------------------------------------------- function dsecChanged() { return this.dsec - this.dsecLast; } // ---------------------------------------------------------------- function secChanged() { return this.sec - this.secLast; } // ---------------------------------------------------------------- function second() { return this.msec / 1000; } // ---------------------------------------------------------------- //////////////////////////////////////////////////////////////// // ---------------------------------------------------------------- function hex2rgb(hex) { // hex: #rrggbb var r = '0x' + hex.substr(1,2); // rr var g = '0x' + hex.substr(3,2); // gg var b = '0x' + hex.substr(5,2); // bb this.r = new Number(r); this.g = new Number(g); this.b = new Number(b); } // ---------------------------------------------------------------- function rgb2color(rgb) { return 'rgb(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ')'; } // ---------------------------------------------------------------- function fromToRatio(from,to,ratio) { return from + Math.round((to - from) * ratio); } // ---------------------------------------------------------------- function rgbChange(rgbFrom,rgbTo,ratio) { this.r = fromToRatio(rgbFrom.r, rgbTo.r, ratio); this.g = fromToRatio(rgbFrom.g, rgbTo.g, ratio); this.b = fromToRatio(rgbFrom.b, rgbTo.b, ratio); } // ---------------------------------------------------------------- function oneOfRandom(array) { return array[Math.floor(Math.random()*array.length)]; } // ---------------------------------------------------------------- function deltaT() { if(this.csecChanged()) { var now = this.second() - this.sec0; var ratio = (now % this.iv) / this.iv; if (!this.endCopyrightMoving) { if (now < this.messageStartTime) { ; // bypass } else if (this.messageLeftEnd < this.messageLeft) { this.messageElement.style.fontSize = 'xx-small'; var msgMovingTime = now - this.messageStartTime; var speed = (this.messageLeftStart - this.messageLeftEnd) / 30; // unit per sec. var nextPos = this.messageLeftStart - speed * msgMovingTime; if (nextPos < this.messageLeft) { this.messageLeft = nextPos; this.messageElement.style.marginLeft = this.messageLeft + this.messageLeftUnit; } } else { this.endCopyrightMoving = 1; this.messageElement.style.backgroundColor = '#cccccc'; } } if (this.opt == 'bw') { // border width if (0 <= ratio && ratio < 0.5) { bw = this.bwFactor * ratio; } else { bw = this.bwFactor * (1 - ratio); } var lrWidth = (this.bwBase + (Math.round(bw * 100) / 100)); var tbWidth = '0'; this.titleElement.style.borderWidth = tbWidth + ' ' + lrWidth + this.bwUnit; } else if(this.opt == 'tc') { // title color var tcRatio = (0 <= ratio && ratio < 0.5)? 2*ratio: (2-2*ratio); var color = rgb2color(new rgbChange(this.tcFrom,this.tcTo,tcRatio)); if (this.color != color) { this.titleElement.style.color = this.color = color; } } else if(this.opt == 'bg') { // background var bgRatio = (0 <= ratio && ratio < 0.5)? 2*ratio: (2-2*ratio); var bg = rgb2color(new rgbChange(this.bgFrom,this.bgTo,bgRatio)); if (this.bg != bg) { this.bgElement.style.backgroundColor = this.bg = bg } } } } // ---------------------------------------------------------------- function webAutomata() { am = new automaton(deltaT,'op'); if (am.w3cdom) { // automaton properties for user interface am.stopText = 'STOP Automaton'; am.startText = 'START Automaton'; am.sleep = 10; // properties for deltaT am.sec0 = am.second(); am.iv = 30; // interval in sec var message1 = title+' version '+version+', Copyright '+copyright; var message2 = 'This site comes with ABSOLUTELY NO WARRANTY. All of these programs is free software, and you are welcome to redistribute it under the GNU General Public License.'; am.messageElement = document.getElementById('message'); am.messageElement.innerHTML = ''; am.messageElement.innerHTML = message1 + '
' + message2; am.messageStartTime = '10'; // in sec am.messageLeftUnit = '%'; am.messageLeftStart = 30; am.messageLeftEnd = 1; am.messageLeft = am.messageLeftStart; am.messageElement.style.fontSize = 'smaller'; am.messageElement.style.marginTop = '0.5em'; am.messageElement.style.marginRight = am.messageLeftEnd + am.messageLeftUnit; am.messageElement.style.marginBottom = '0.5em'; am.messageElement.style.marginLeft = am.messageLeftStart + am.messageLeftUnit; am.messageElement.style.padding = '0.2em 1em'; am.opt = oneOfRandom(['bw','bg','tc']); if (am.opt == 'bw') { am.titleElement = document.getElementById('title'); am.bwFactor = 1.5; // border width factor am.bwUnit = 'em'; am.bwBase = 0.5; } else if(am.opt == 'bg') { am.bgElement = document.getElementById('title'); am.bgFrom = new hex2rgb('#ffffff'); am.bgTo = new hex2rgb(oneOfRandom(['#cc9999','#99cc99','#9999cc','#cccc99','#99cccc'])); am.bg = am.bgFrom; } else if(am.opt == 'tc') { am.titleElement = document.getElementById('title'); am.tcFrom = new hex2rgb(oneOfRandom(['#000000','#330000','#003300','000033','#333300','#003333','#330033'])); am.tcTo = new hex2rgb(oneOfRandom(['#cccccc','#cc0000','#00cc00','0000cc','#cccc00','#00cccc'])); am.color = am.tcFrom; } am.start(); // start automaton } } // ----------------------------------------------------------------