/*
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
}
}
// ----------------------------------------------------------------