Skip to content

Instantly share code, notes, and snippets.

@harjitmoe
Last active November 12, 2021 14:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save harjitmoe/6f0b218b79b0fd3eb559cb7038797d73 to your computer and use it in GitHub Desktop.
Save harjitmoe/6f0b218b79b0fd3eb559cb7038797d73 to your computer and use it in GitHub Desktop.
/*
* ReWild - Replacement for Wildfire.
* Copyright (c) 2016, 2018, 2020 HarJIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions
* of the Software.
*
* The origin of this software must not be misrepresented; you must not claim that you wrote the original
* software. If you use this software in a product, an acknowledgement in the product documentation would be
* appreciated but is not required.
*
* Altered versions of the Software shall not be misrepresented as being the original Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* ---
*
* As an alternative to the above, you may redistribute and/or modify the Software under the following terms:
*
* rewild.js 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 3 of the License, or (at your
* option) any later version.
*
* Additionally, rewild.js shall be subject to the following Section 7(c) permitted restrictions:
*
* The origin of this software must not be misrepresented; you must not claim that you wrote the original
* software. If you use this software in a product, an acknowledgement in the product documentation would be
* appreciated but is not required.
*
* Altered versions of the Software shall not be misrepresented as being the original Software.
*
*/
/*
* Directions: Include in a script tag (either sourced from external file or else included in the .html), after a
* <div id="rewild"></div> tag. Include Chart.js first if you want it (otherwise it will report in CSV).
*
* Don't transclude from Gist itself (it will fail in Chrome due to MIME mismatch).
*
* Avoiding older IE compatibility modes so as to use HTML5 features (sliders) is nice, hence you may wish to
* <meta http-equiv="X-UA-Compatible" content="IE=10,chrome=1" /> (or later compatibility strings)
*
*/
/*
* Included as the conditional of an empty if-statement so as to be reliably parsed as a called anonymous defn
* rather than borked on.
* Done like that in the first place so as not to clutter the global namespace, thus facilitating embedding.
*
*/
// @license magnet:?xt=urn:btih:1f739d935676111cfff4b4693e3816e664797050&dn=gpl-3.0.txt GPL-v3-or-Later
if(function(main_div){
var reset_params = function(){
/* Width in pixels. */
WIDTH=300;
/* Height in pixels. */
HEIGHT=200;
/* A number of individuals, expensive (makes app slow when too large). */
POPULATION=300;
/* Contagion during incubation period, between 0 and 1 */
CONTAG_IN=0.7;
/* Contagion when ill, between 0 and 1 */
CONTAG_CS=0.3;
/* Probability of death from one infection, between 0 and 1 */
FATALITY=0.7;
/* Can gain immunity: 1 (yes) or 0 (no) */
IMMUNISES=1;
/* Probability of genetic immunity, between 0 and 1 */
IMMUN_GENE=0.02;
/* Duration of incubation period, in frames. */
INCUBATION=80;
/* Duration of illness, in frames. */
COURSE=20;
/* Distance needed for infection, in pixels across and down, very expensive. */
PROXIMITY=5;
/* Minimum duration between exposures (set to zero to disable). */
REFRACTORY=10;
/*
* For reference, in the original Wildfire:
*
* Flu: Immunity, involuntary exposure, range 20 out of 50, infection on contact 30%, duration 7 days,
* mortality 1%.
* Measles: Immunity, involuntary exposure, range 10 out of 50, infection on contact 30%, duration 10 days,
* mortality 1%.
* Smallpox: Immunity, involuntary exposure, range 20 out of 50, infection on contact 20%, duration 10 days,
* mortality 30%.
* Satan bug: No immunity, involuntary exposure, range 40 out of 50, infection on contact 80%, duration 2 days,
* mortality 80%.
* AIDS: No immunity, voluntary exposure, 7 days between exposures, infection on contact 5%, duration 1000 days,
* mortality 99%.
*
*/
HEALTHY_C="#6200FF";
INCUBATION_C="#FF9F00";
EXPRESS_INCUBATION_C="#FF9F00";
SICK_C="#FC002A";
IMMUNE_C="#00D4B7";
DEAD_C="#000";
SIZE=PROXIMITY;
/*
* There is not need for the typical user to change anything below this line.
*
*/
};
var WIDTH;var HEIGHT;var POPULATION;var CONTAG_IN;
var CONTAG_CS;var FATALITY;var IMMUNISES;var IMMUN_GENE;
var INCUBATION;var COURSE;var PROXIMITY;var REFRACTORY;
var HEALTHY_C;var INCUBATION_C;var SICK_C;var IMMUNE_C;
var DEAD_C;var SIZE;var EXPRESS_INCUBATION_C;
/* Names used by WF itself (only it lists Immune after healthy)
var HEALTHY_LABEL="Healthy";
var INCUBATION_LABEL="Infected";
var SICK_LABEL="Sick";
var IMMUNE_LABEL="Immune";
var DEAD_LABEL="Dead";
*/
var HEALTHY_LABEL="Unaffected";
var INCUBATION_LABEL="Incubating";
var SICK_LABEL="Sick";
var IMMUNE_LABEL="Immune";
var DEAD_LABEL="Dead";
var FRAMES_LABEL_TITLE="Days: ";
var FRAMES_LABEL_UNIT=" days";
var FRAMES_LABEL_SINGULAR="Day ";
var USE_SVG=(typeof SVGRectElement != "undefined");
reset_params();
var myRemove = function(arra,item){
for(var i=0;i<arra.length;i+=1){
if(arra[i]===item){
arra.splice(i,1);
i-=1;
};
};
return -1;
};
var countsToCsv = function(counts){
var ret='"'+HEALTHY_LABEL+'","'+INCUBATION_LABEL+'","'+SICK_LABEL+'","'+IMMUNE_LABEL+'","'+DEAD_LABEL+'"\n';
for(var i=0;i<counts.length;i+=1){
var line="";
for(var j=0;j<counts[i].length;j+=1){
line+=counts[i][j]+",";
};
ret+=line.substr(0,line.length-1)+"\n";
};
return ret;
};
var countsToChart = function(counts){
var canv=MyCreateElement("canvas");
report.appendChild(canv);
var dnos=[];
for(var i=1;i<=counts.length;i+=1){
dnos[dnos.length]=FRAMES_LABEL_SINGULAR+i;
};
var labels=[HEALTHY_LABEL,INCUBATION_LABEL,SICK_LABEL,IMMUNE_LABEL,DEAD_LABEL];
var colours=[HEALTHY_C,EXPRESS_INCUBATION_C,SICK_C,IMMUNE_C,DEAD_C];
var ogdos=[];
if(!counts.length){
return canv;
};
for(var j=0;j<counts[0].length;j+=1){
ogdos[j]=[];
};
for(var i=0;i<counts.length;i+=1){
for(var j=0;j<counts[i].length;j+=1){
ogdos[j][i]=counts[i][j];
};
};
var datas=[];
for(var j=0;j<counts[0].length;j+=1){
datas[datas.length]={
label: labels[j],
fill: false,
borderColor: colours[j],
backgroundColor: colours[j], // for tooltips.
pointBorderColor: colours[j],
pointStrokeColor: colours[j],
pointStyle: "line",
data: ogdos[j]
};
};
canv.width="1000";
canv.height="700";
canv.style.display="block";
canv.style["margin-left"]="auto";
canv.style["margin-right"]="auto";
canv._rewild_chart=new Chart(canv.getContext("2d"), {
type: "line",
data: {"labels":dnos, "datasets":datas},
options: {
animation: {"duration":0},
elements: {"line": {"tension": 0}},
scales: {
yAxes: [{
scaleLabel: {
display: true,
labelString: '(+) count'
}
}]
}
}
});
return canv;
};
var set=function(bar,key,val){
tosvg = {"top": "y", "left": "x", "background": "fill"};
tocss = {"x": "left", "y": "top", "fill": "background"};
if (bar.nodeName.toLowerCase() == "div") {
bar.style.position = "absolute";
}
if (!key) {
return;
} else if (bar.nodeName.toLowerCase() == "rect" || bar.nodeName.toLowerCase() == "svg") {
bar.setAttribute(tosvg[key] || key, val);
} else if (bar.nodeName.toLowerCase() == "g") {
bar.setAttribute("data-" + (tosvg[key] || key), parseInt(val) + "");
var x = bar.getAttribute("data-x");
var y = bar.getAttribute("data-y");
if (x && y) {
bar.setAttribute("transform", "translate(" + x + " " + y + ")");
}
} else {
bar.style[tocss[key] || key] = val;
};
};
var MyCreateElement = function(name){
var namespace;
if (name == "svg" || name == "g" || name == "rect") {
namespace = "http://www.w3.org/2000/svg";
}
return (namespace)?(document.createElementNS(namespace, name)):(document.createElement(name));
}
var Cross=function(area,stack,WIDTH,HEIGHT,POPULATION,CONTAG_IN,CONTAG_CS,FATALITY,IMMUNISES,IMMUN_GENE,
INCUBATION,COURSE,PROXIMITY,REFRACTORY){
var thus=this;
this._countdown=-1;
this._intrinsic_randv=Math.random();
/**/
this.area=area;
this.stack=stack;
if (area.nodeName.toLowerCase() == "svg") {
this.groupel=MyCreateElement("g");
area.appendChild(this.groupel);
var downbar=MyCreateElement("rect");
this.groupel.appendChild(downbar);
var crossbar=MyCreateElement("rect");
this.groupel.appendChild(crossbar);
} else {
this.groupel=MyCreateElement("div");
area.appendChild(this.groupel);
var downbar=MyCreateElement("div");
this.groupel.appendChild(downbar);
var crossbar=MyCreateElement("div");
this.groupel.appendChild(crossbar);
}
set(this.groupel);
set(downbar, "top", "0");
set(downbar, "shape-rendering", "crispEdges");
downbar.style["margin"] = "0";
set(crossbar, "left", "0");
set(crossbar, "shape-rendering", "crispEdges");
crossbar.style["margin"] = "0";
/**/
this._set_zed = function(zed){
thus.groupel.style["z-index"] = zed;
if (stack.zed_indices != null && typeof stack.zed_indices[zed] != "undefined") {
stack.zed_indices[zed].appendChild(thus.groupel);
}
};
this._place=function(x,y){
thus.x=Math.floor(x);
set(thus.groupel, "left", this.x+"px");
thus.y=Math.floor(y);
set(thus.groupel, "top", this.y+"px");
stack.superstack[this.x][this.y][stack.superstack[this.x][this.y].length]=thus;
};
this.place=function(x,y){
myRemove(stack.superstack[thus.x][thus.y],thus);
this._place(x,y);
};
this.setSize=function(siz){
thus._size=siz;
set(thus.groupel, "width", siz+"px");
set(thus.groupel, "height", (2*siz)+"px");
set(crossbar, "width", siz+"px");
set(crossbar, "height", ((((siz%2)+1)%2)+1)+"px"); /* 2 if siz even else 1 */
set(crossbar, "top", Math.floor((siz-1)/2)+"px");
set(downbar, "width", ((((siz%2)+1)%2)+1)+"px"); /* 2 if siz even else 1 */
set(downbar, "height", siz+"px");
set(downbar, "left", Math.floor((siz-1)/2)+"px");
this._place(Math.random()*(WIDTH-siz-1),Math.random()*(HEIGHT-(2*siz)-1));
};
this.setSize(SIZE);
/**/
this._state="h"; /* Healthy */
this._set_zed("2");
set(downbar, "background", HEALTHY_C);
set(crossbar, "background", HEALTHY_C);
this.setState=function(state){
var save_state=thus.getState();
thus._state=state;
thus.stack.nt[state]+=1;
thus.stack.nt[save_state]-=1;
switch(state){
case "h": /* Healthy */
set(crossbar, "background", HEALTHY_C);
set(downbar, "background", HEALTHY_C);
set(downbar, "height", thus._size+"px");
thus._set_zed("2");
return;
case "c": /* inCubation */
set(crossbar, "background", INCUBATION_C);
set(downbar, "background", INCUBATION_C);
set(downbar, "height", thus._size+"px");
thus._countdown=INCUBATION;
thus._set_zed("4");
return;
case "s": /* Sick */
set(crossbar, "background", SICK_C);
set(downbar, "background", SICK_C);
set(downbar, "height", thus._size+"px");
thus._countdown=COURSE;
thus._set_zed("5");
return;
case "m": /* iMMune */
set(crossbar, "background", IMMUNE_C);
set(downbar, "background", IMMUNE_C);
set(downbar, "height", thus._size+"px");
thus._set_zed("3");
return;
case "d": /* Dead */
set(crossbar, "background", DEAD_C);
set(downbar, "background", DEAD_C);
set(downbar, "height", (thus._size*2)+"px");
thus._set_zed("1");
return;
case "r": /* Refractory */
set(crossbar, "background", HEALTHY_C);
set(downbar, "background", HEALTHY_C);
set(downbar, "height", thus._size+"px");
thus._countdown=REFRACTORY;
thus._set_zed("2");
return;
default:
thus._state=save_state;
this.stack.nt[save_state]+=1;
alert("Invalid state character: "+state);
}
}
this.getState=function(){
return thus._state;
}
/**/
this._laststep=-1;
this.step=function(){
var sst=thus.getState();
if(sst=="d"){ return; };
while(1){
var clik=Math.random()
if(this._laststep==-1){clik*=0.49;};
var y=thus.y;
var x=thus.x;
while(1){
if (clik<0.125) {
y=y+2;
break;
} else if (clik<0.25) {
y=y-2;
break;
} else if (clik<0.375) {
x=x+2;
break;
} else if (clik<0.5) {
x=x-2;
break;
} else {
clik=this._laststep;
};
};
if(clik<0.5){
this._laststep=clik;
};
if ( ((y+(thus._size*2))<=HEIGHT) && ((x+thus._size)<=WIDTH)
&& (y>=0) && (x>=0) ) {
break;
};
};
thus.place(x,y);
if (thus._intrinsic_randv<IMMUN_GENE) {
if(sst=="h"){ /* Should still be a valid seed, else difficulties. */
thus.setState("m");
};
};
if (sst=="h") {
var tryx=x-PROXIMITY;
while(tryx<0){ tryx+=1; };
while(1){
if ( (tryx>(WIDTH-thus._size)) || (tryx>(x+PROXIMITY)) ) {
break;
};
var tryy=y-PROXIMITY;
while(tryy<0){ tryy+=1; };
while(1){
if ( (tryy>(HEIGHT-thus._size)) || (tryy>(y+PROXIMITY)) ) {
break;
};
var substac=stack.superstack[tryx][tryy];
for(var i=0;i<substac.length;i+=1){
var other=substac[i];
var ost=other.getState();
if (ost=="s") {
var randv=Math.random();
if (randv<CONTAG_CS) {
thus.setState("c");
} else if (REFRACTORY) {
thus.setState("r");
};
} else if (ost=="c") {
var randv=Math.random();
if (randv<CONTAG_IN) {
thus.setState("c");
} else if (REFRACTORY) {
thus.setState("r");
};
};
};
tryy+=1;
};
tryx+=1;
};
} else if (sst=="r") {
thus._countdown-=1;
if(thus._countdown<=0){
thus.setState("h");
};
} else if (sst=="c") {
thus._countdown-=1;
if(thus._countdown<=0){
thus.setState("s");
};
} else if(sst=="s") {
thus._countdown-=1;
if(thus._countdown<=0){
var rand=Math.random();
if (rand<FATALITY) {
thus.setState("d");
} else {
if(IMMUNISES){
thus.setState("m");
} else {
thus.setState("h");
};
};
};
};
};
};
function Stack(main_div,WIDTH,HEIGHT,POPULATION,CONTAG_IN,CONTAG_CS,FATALITY,IMMUNISES,IMMUN_GENE,
INCUBATION,COURSE,PROXIMITY,REFRACTORY){
this.frame=1;
var thus=this;
this.closed=true;
this.frozen=true;
this.counts=[];
this.step=function(){
if(!thus.closed){
for(var i=0;i<thus.all.length;i+=1){
thus.all[i].step();
};
sample_h.span.removeChild(sample_h.span_t);
sample_h.span_t=document.createTextNode("| "+HEALTHY_LABEL+": "+(thus.nt.h+thus.nt.r)+" ");
sample_h.span.appendChild(sample_h.span_t);
sample_c.span.removeChild(sample_c.span_t);
sample_c.span_t=document.createTextNode("| "+INCUBATION_LABEL+": "+(thus.nt.c)+" ");
sample_c.span.appendChild(sample_c.span_t);
sample_s.span.removeChild(sample_s.span_t);
sample_s.span_t=document.createTextNode("| "+SICK_LABEL+": "+(thus.nt.s)+" ");
sample_s.span.appendChild(sample_s.span_t);
sample_m.span.removeChild(sample_m.span_t);
sample_m.span_t=document.createTextNode("| "+IMMUNE_LABEL+": "+(thus.nt.m)+" ");
sample_m.span.appendChild(sample_m.span_t);
sample_d.span.removeChild(sample_d.span_t);
sample_d.span_t=document.createTextNode("| "+DEAD_LABEL+": "+(thus.nt.d)+" ");
sample_d.span.appendChild(sample_d.span_t);
dayno_h.removeChild(dayno_h_t);
dayno_h_t=document.createTextNode(FRAMES_LABEL_TITLE+thus.frame+" ");
dayno_h.appendChild(dayno_h_t);
};
if(!thus.frozen){
thus.frame+=1;
thus.counts[thus.counts.length]=[thus.nt.h+thus.nt.r,thus.nt.c,thus.nt.s,thus.nt.m,thus.nt.d];
if( (thus.nt.c==0) && (thus.nt.s==0) ){
thus.frozen=true;
};
};
setTimeout(thus.step,5);
};
this.seed=function(){
/* Note: must be thus, not this, inside this func. */
var rand=Math.random();
thus.frozen=false;
thus.all[Math.floor(rand*thus.all.length)].setState("c");
};
this.report=function(){
/* Note: must be thus, not this, inside this func. */
configbox.style.display="none";
report.removeChild(report.textnode);
report.removeChild(report.canvnode);
if( (typeof Chart != "undefined") && (MyCreateElement("canvas").getContext) && (MyCreateElement("canvas").getContext("2d")) ){
report.textnode=document.createTextNode("Graph rendered using Chart.js, see https://github.com/chartjs/Chart.js");
report.appendChild(report.textnode);
report.canvnode=countsToChart(thus.counts);
}else{
report.textnode=document.createTextNode(countsToCsv(thus.counts));
report.appendChild(report.textnode);
report.canvnode=document.createTextNode("");
report.appendChild(report.canvnode);
};
};
this.reset=function(){
/* Note: must be thus, not this, inside this func. */
thus.frozen=true;
thus.closed=true;
for(var i=0;i<thus.all.length;i+=1){
thus.all[i].setState("m");
};
for(var i=0;i<thus.all.length;i+=1){
thus.all[i].setState("h");
};
thus.nt.h=POPULATION;
thus.nt.c=0;
thus.nt.s=0;
thus.nt.m=0;
thus.nt.d=0;
thus.nt.r=0;
thus.frame=1;
thus.counts=[];
thus.closed=false; /* Still frozen, though, as no infection. */
};
this.close=function(){
thus.frozen=true;
thus.closed=true;
thus.all=[];
main_div.removeChild(thus.area);
};
this.open=function(button, buttonr, buttonp){
button.onclick=thus.seed;
buttonr.onclick=thus.reset;
buttonp.onclick=thus.report;
thus.area=MyCreateElement((USE_SVG)?("svg"):("div"));
thus.zed_indices = null;
main_div.appendChild(thus.area);
set(thus.area, "width", WIDTH+"px");
set(thus.area, "height", HEIGHT+"px");
if (thus.area.nodeName.toLowerCase() != "svg") {
thus.area.style["margin-left"]="auto";
thus.area.style["margin-right"]="auto";
thus.area.style.position="relative";
} else {
// Z-index is determined differently in HTML versus SVG 1.1
thus.zed_indices = {};
thus.zed_indices["1"] = MyCreateElement("g");
thus.area.appendChild(thus.zed_indices["1"]);
thus.zed_indices["2"] = MyCreateElement("g");
thus.area.appendChild(thus.zed_indices["2"]);
thus.zed_indices["3"] = MyCreateElement("g");
thus.area.appendChild(thus.zed_indices["3"]);
thus.zed_indices["4"] = MyCreateElement("g");
thus.area.appendChild(thus.zed_indices["4"]);
thus.zed_indices["5"] = MyCreateElement("g");
thus.area.appendChild(thus.zed_indices["5"]);
}
for(var i=0;i<POPULATION;i+=1){
thus.all[thus.all.length]=new Cross(thus.area,thus,WIDTH,HEIGHT,POPULATION,CONTAG_IN,
CONTAG_CS,FATALITY,IMMUNISES,IMMUN_GENE,
INCUBATION,COURSE,PROXIMITY,REFRACTORY);
};
thus.all[0].setSize(SIZE*3);
thus.nt={};
thus.nt.h=POPULATION;
thus.nt.c=0;
thus.nt.s=0;
thus.nt.m=0;
thus.nt.d=0;
thus.nt.r=0;
thus.counts=[];
thus.closed=false;
}
this.all=[];
this.superstack=[];
for(var x=0;x<=WIDTH;x+=1){
this.superstack[x]=[];
for(var y=0;y<=HEIGHT;y+=1){
this.superstack[x][y]=[];
};
};
setTimeout(thus.step,50);
};
main_div.style["text-align"]="center";
var titl=MyCreateElement("h6");
titl.style["font-size"]="24px";
titl.style["margin"]="0";
main_div.appendChild(titl);
var titl_t=document.createTextNode("Replacement for Wildfire");
titl.appendChild(titl_t);
var subtitl=MyCreateElement("p");
subtitl.style["font-style"]="italic";
main_div.appendChild(subtitl);
var subtitl_t=document.createTextNode("By HarJIT");
subtitl.appendChild(subtitl_t);
var canv=MyCreateElement("div");
main_div.appendChild(canv);
function SetSample(colour,text){
this.span=MyCreateElement("span");
main_div.appendChild(this.span);
this.span.style.color=colour;
this.span_t=document.createTextNode(text);
this.span.appendChild(this.span_t);
}
var sample_h=new SetSample(HEALTHY_C, HEALTHY_LABEL+" | ");
var sample_c=new SetSample(INCUBATION_C, INCUBATION_LABEL+" | ");
var sample_s=new SetSample(SICK_C, SICK_LABEL+" | ");
var sample_m=new SetSample(IMMUNE_C, IMMUNE_LABEL+" | ");
var sample_d=new SetSample(DEAD_C, DEAD_LABEL+" | ");
main_div.appendChild(MyCreateElement("br"));
var dayno_h=MyCreateElement("span");
main_div.appendChild(dayno_h);
var dayno_h_t=document.createTextNode(" / ");
dayno_h.appendChild(dayno_h_t);
main_div.appendChild(MyCreateElement("br"));
var button=MyCreateElement("button");
main_div.appendChild(button);
button.setAttribute("type","button");
var button_t=document.createTextNode("Seed");
button.appendChild(button_t);
var buttonr=MyCreateElement("button");
main_div.appendChild(buttonr);
buttonr.setAttribute("type","button");
var buttonr_t=document.createTextNode("Reset");
buttonr.appendChild(buttonr_t);
var buttonp=MyCreateElement("button");
main_div.appendChild(buttonp);
buttonp.setAttribute("type","button");
var buttonp_t=document.createTextNode("Report");
buttonp.appendChild(buttonp_t);
/*
* Note: IE7/IE8 only allow setting type before adding to DOM.
* IE11 does it properly. IE7/IE8 don't support range
* input anyway (it falls back) but (a) trying to set
* after adding terminates the whole script with an
* exception, (b) it *does* support checkbox, and the
* API differences make it imperative that that one
* *does not* fall back.
*/
var Control=function(tbody,lab,lab2,typ,init_callback,onchange){
this.tr=MyCreateElement("tr");
tbody.appendChild(this.tr);
this.th=MyCreateElement("th");
this.th.style.height="4em";
this.tr.appendChild(this.th);
this.th.style.border="1px solid black";
this.th.style["text-align"]="right";
this.th.style["padding"]="2px";
this.td=MyCreateElement("td");
this.tr.appendChild(this.td);
this.td.style.border="1px solid black";
this.td2=MyCreateElement("td");
this.tr.appendChild(this.td2);
this.td2.style.border="1px solid black";
this.box_t=document.createTextNode(lab);
this.th.appendChild(this.box_t);
this.th.appendChild(MyCreateElement("br"));
this.box_t2=document.createTextNode(lab2);
this.box_t2s=MyCreateElement("span");
this.box_t2s.appendChild(this.box_t2);
this.box_t2s.style["font-weight"]=400;
this.box_t2s.style["font-size"]="smaller";
this.th.appendChild(this.box_t2s);
this.box=MyCreateElement("input");
this.box.setAttribute("type",typ);
this.td.appendChild(this.box);
this.box.control=this; /* cyclic ref */
init_callback(this.box);
this.box.onchange=onchange;
};
var expandlink=MyCreateElement("a");
main_div.appendChild(expandlink);
expandlink.appendChild(document.createTextNode("Show/hide parameters."));
expandlink.setAttribute("href","javascript:void(0);"); /* Format as link but don't navigate. */
expandlink.style.display="block";
var configbox=MyCreateElement("div");
main_div.appendChild(configbox);
configbox.style.display="none";
expandlink.onclick=function(){
configbox.style.display=(configbox.style.display=="none")?("block"):("none");
};
var ctable=MyCreateElement("table");
configbox.appendChild(ctable);
ctable.style.border="1px solid black";
ctable.style["border-collapse"]="collapse";
ctable.style["margin-left"]="auto";
ctable.style["margin-right"]="auto";
var ctbody=MyCreateElement("tbody");
ctable.appendChild(ctbody);
var notice_tr=MyCreateElement("tr");
ctbody.appendChild(notice_tr);
var notice_td=MyCreateElement("th");
notice_td.style.height="4em";
notice_tr.appendChild(notice_td);
notice_td.style.border="1px solid black";
notice_td.style.background="black";
notice_td.style.color="white";
notice_td.setAttribute("colspan",3);
notice_td.appendChild(document.createTextNode("Parameters."));
notice_td.appendChild(MyCreateElement("br"));
var notice_span=MyCreateElement("span");
notice_td.appendChild(notice_span);
notice_span.appendChild(document.createTextNode("(Note that changing the below resets the simulation.)"));
notice_span.style["font-weight"]=400;
notice_span.style["font-size"]="smaller";
var expbox_o=new Control(ctbody,"Incubation visible:","(can see if a non-sick (+) is infected)","checkbox",function(box){
box.setAttribute("value","unused");
box.setAttribute("checked",INCUBATION_C!=HEALTHY_C);
box.control.td2_t=document.createTextNode((INCUBATION_C!=HEALTHY_C)?("Yes"):("No"));
box.control.td2.appendChild(box.control.td2_t);
},function(){
INCUBATION_C=(this.checked)?(EXPRESS_INCUBATION_C):(HEALTHY_C);
restac2(buttonu);
this.control.td2.removeChild(this.control.td2_t);
this.control.td2_t=document.createTextNode((INCUBATION_C!=HEALTHY_C)?("Yes"):("No"));
this.control.td2.appendChild(this.control.td2_t);
});
var widslid_o=new Control(ctbody,"Width:","(width of area, affects population density)","range",function(box){
/* one more than minimum: freezes if both dimens are at minimum */
box.setAttribute("min",(SIZE*3)+2);
box.setAttribute("max",1000);
box.setAttribute("value",WIDTH);
box.control.td2_t=document.createTextNode(WIDTH+"px");
box.control.td2.appendChild(box.control.td2_t);
},function(){
/* Maybe a string in HTML4 - string coerce then atoi should work for both. */
WIDTH=parseInt(this.value+"",10);
restac2(buttonu);
this.control.td2.removeChild(this.control.td2_t);
this.control.td2_t=document.createTextNode(WIDTH+"px");
this.control.td2.appendChild(this.control.td2_t);
});
var heislid_o=new Control(ctbody,"Height:","(height of area, affects population density)","range",function(box){
box.setAttribute("min",(SIZE*6)+1);
box.setAttribute("max",700);
box.setAttribute("value",HEIGHT);
box.control.td2_t=document.createTextNode(HEIGHT+"px");
box.control.td2.appendChild(box.control.td2_t);
},function(){
/* Maybe a string in HTML4 - string coerce then atoi should work for both. */
HEIGHT=parseInt(this.value+"",10);
restac2(buttonu);
this.control.td2.removeChild(this.control.td2_t);
this.control.td2_t=document.createTextNode(HEIGHT+"px");
this.control.td2.appendChild(this.control.td2_t);
});
var popslid_o=new Control(ctbody,"Population:","(number of (+)s in area, affects population density)","range",function(box){
box.setAttribute("min",1);
box.setAttribute("max",800);
box.setAttribute("value",POPULATION);
box.control.td2_t=document.createTextNode(POPULATION+"");
box.control.td2.appendChild(box.control.td2_t);
},function(){
/* Maybe a string in HTML4 - string coerce then atoi should work for both. */
POPULATION=parseInt(this.value+"",10);
restac2(buttonu);
this.control.td2.removeChild(this.control.td2_t);
this.control.td2_t=document.createTextNode(POPULATION+"");
this.control.td2.appendChild(this.control.td2_t);
});
var contaginslid_o=new Control(ctbody,"Incubating contagion:","(likeliness to catch infection from an infected (+) not yet showing symptoms)","range",function(box){
box.setAttribute("min",0);
box.setAttribute("max",1);
box.setAttribute("step","0.01");
box.setAttribute("value",CONTAG_IN);
box.control.td2_t=document.createTextNode(Math.round(CONTAG_IN*100)+"%");
box.control.td2.appendChild(box.control.td2_t);
},function(){
/* Maybe a string in HTML4 - string coerce then atof should work for both. */
CONTAG_IN=parseFloat(this.value+"");
restac2(buttonu);
this.control.td2.removeChild(this.control.td2_t);
this.control.td2_t=document.createTextNode(Math.round(CONTAG_IN*100)+"%");
this.control.td2.appendChild(this.control.td2_t);
});
var contagcsslid_o=new Control(ctbody,"Contagion in course:","(likeliness to catch from a sick (+))","range",function(box){
box.setAttribute("min",0);
box.setAttribute("max",1);
box.setAttribute("step","0.01");
box.setAttribute("value",CONTAG_CS);
box.control.td2_t=document.createTextNode(Math.round(CONTAG_CS*100)+"%");
box.control.td2.appendChild(box.control.td2_t);
},function(){
/* Maybe a string in HTML4 - string coerce then atof should work for both. */
CONTAG_CS=parseFloat(this.value+"");
restac2(buttonu);
this.control.td2.removeChild(this.control.td2_t);
this.control.td2_t=document.createTextNode(Math.round(CONTAG_CS*100)+"%");
this.control.td2.appendChild(this.control.td2_t);
});
var fataslid_o=new Control(ctbody,"Fatality per infection:","(likeliness to die from an infection)","range",function(box){
box.setAttribute("min",0);
box.setAttribute("max",1);
box.setAttribute("step","0.01");
box.setAttribute("value",FATALITY);
box.control.td2_t=document.createTextNode(Math.round(FATALITY*100)+"%");
box.control.td2.appendChild(box.control.td2_t);
},function(){
/* Maybe a string in HTML4 - string coerce then atof should work for both. */
FATALITY=parseFloat(this.value+"");
restac2(buttonu);
this.control.td2.removeChild(this.control.td2_t);
this.control.td2_t=document.createTextNode(Math.round(FATALITY*100)+"%");
this.control.td2.appendChild(this.control.td2_t);
});
var immubox_o=new Control(ctbody,"Acquire immunity:","(after recovery, cannot catch again)","checkbox",function(box){
box.setAttribute("value","unused");
box.setAttribute("checked",IMMUNISES);
box.control.td2_t=document.createTextNode((IMMUNISES)?("Yes"):("No"));
box.control.td2.appendChild(box.control.td2_t);
},function(){
IMMUNISES=this.checked;
restac2(buttonu);
this.control.td2.removeChild(this.control.td2_t);
this.control.td2_t=document.createTextNode((IMMUNISES)?("Yes"):("No"));
this.control.td2.appendChild(this.control.td2_t);
});
var gimmuslid_o=new Control(ctbody,"Genetic immunity:","(probability of not being successfully infectable for genetic reasons)","range",function(box){
box.setAttribute("min",0);
box.setAttribute("max",1);
box.setAttribute("step","0.01");
box.setAttribute("value",IMMUN_GENE);
box.control.td2_t=document.createTextNode(Math.round(IMMUN_GENE*100)+"%");
box.control.td2.appendChild(box.control.td2_t);
},function(){
/* Maybe a string in HTML4 - string coerce then atof should work for both. */
IMMUN_GENE=parseFloat(this.value+"");
restac2(buttonu);
this.control.td2.removeChild(this.control.td2_t);
this.control.td2_t=document.createTextNode(Math.round(IMMUN_GENE*100)+"%");
this.control.td2.appendChild(this.control.td2_t);
});
var incuslid_o=new Control(ctbody,"Incubation period:","(duration after infection before showing symptoms)","range",function(box){
box.setAttribute("min",1);
box.setAttribute("max",300);
box.setAttribute("value",INCUBATION);
box.control.td2_t=document.createTextNode(INCUBATION+FRAMES_LABEL_UNIT);
box.control.td2.appendChild(box.control.td2_t);
},function(){
/* Maybe a string in HTML4 - string coerce then atoi should work for both. */
INCUBATION=parseInt(this.value+"",10);
restac2(buttonu);
this.control.td2.removeChild(this.control.td2_t);
this.control.td2_t=document.createTextNode(INCUBATION+FRAMES_LABEL_UNIT);
this.control.td2.appendChild(this.control.td2_t);
});
var courseslid_o=new Control(ctbody,"Illness duration:","(duration showing symptoms)","range",function(box){
box.setAttribute("min",1);
box.setAttribute("max",300);
box.setAttribute("value",COURSE);
box.control.td2_t=document.createTextNode(COURSE+FRAMES_LABEL_UNIT);
box.control.td2.appendChild(box.control.td2_t);
},function(){
/* Maybe a string in HTML4 - string coerce then atoi should work for both. */
COURSE=parseInt(this.value+"",10);
restac2(buttonu);
this.control.td2.removeChild(this.control.td2_t);
this.control.td2_t=document.createTextNode(COURSE+FRAMES_LABEL_UNIT);
this.control.td2.appendChild(this.control.td2_t);
});
var proxislid_o=new Control(ctbody,"Infection proximity:","(how near a (+) needs to be to catch infection)","range",function(box){
box.setAttribute("min",1);
box.setAttribute("max",20);
box.setAttribute("value",PROXIMITY);
box.control.td2_t=document.createTextNode(PROXIMITY+" pixels");
box.control.td2.appendChild(box.control.td2_t);
},function(){
/* Maybe a string in HTML4 - string coerce then atoi should work for both. */
PROXIMITY=parseInt(this.value+"",10);
restac2(buttonu);
this.control.td2.removeChild(this.control.td2_t);
this.control.td2_t=document.createTextNode(PROXIMITY+" pixels");
this.control.td2.appendChild(this.control.td2_t);
});
var refraslid_o=new Control(ctbody,"Minimum time between exposures:","(if exposure is an action which is not performed constantly, e.g. STIs)","range",function(box){
box.setAttribute("min",0);
box.setAttribute("max",300);
box.setAttribute("value",REFRACTORY);
box.control.td2_t=document.createTextNode(REFRACTORY+FRAMES_LABEL_UNIT);
box.control.td2.appendChild(box.control.td2_t);
},function(){
/* Maybe a string in HTML4 - string coerce then atoi should work for both. */
REFRACTORY=parseInt(this.value+"",10);
restac2(buttonu);
this.control.td2.removeChild(this.control.td2_t);
this.control.td2_t=document.createTextNode(REFRACTORY+FRAMES_LABEL_UNIT);
this.control.td2.appendChild(this.control.td2_t);
});
var report=MyCreateElement("pre");
main_div.appendChild(report);
report.textnode=document.createTextNode("");
report.appendChild(report.textnode);
report.canvnode=document.createTextNode("");
report.appendChild(report.canvnode);
var buttonu={};
buttonu.stac=new Stack(canv,WIDTH,HEIGHT,POPULATION,CONTAG_IN,CONTAG_CS,FATALITY,
IMMUNISES,IMMUN_GENE,INCUBATION,COURSE,PROXIMITY,REFRACTORY);
buttonu.stac.open(button, buttonr, buttonp);
var restac2=function(thus){
thus.stac.close();
thus.stac=new Stack(canv,WIDTH,HEIGHT,POPULATION,CONTAG_IN,CONTAG_CS,FATALITY,
IMMUNISES,IMMUN_GENE,INCUBATION,COURSE,PROXIMITY,REFRACTORY);
thus.stac.open(button, buttonr, buttonp);
};
}(document.getElementById("rewild"))){};
// @license-end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment