Factorio Fluid Model Proposal 2

Simulator for multiple Factorio Fluid Proposals

by TheYeast

HTML

<div id="main">
  <table class="layout">
  <tr>
    <td>
       <div id="grid"></div>
    </td>
    <td>
      <div id="toolbar"></div>
      <div id="globalStats">
        <div>UPS: <span id="upsDisplay"></span> FPS: <span id="fpsDisplay"></span></div>    
      </div>
      <div id="entityConfig" class="config">
        <h2>Entity configuration</h2>        
        <div id="cfgEntity" class="controls"></div>      
      </div>
      <div id="modelConfig" class="config">
        <h2>Model configuration</h2>
        <h3>Pressure model: <select id="selPressureModel"></select></h3>
        <div id="cfgPressureModel" class="controls"></div>
        <h3>Clamp model: <select id="selClampModel"></select></h3>
        <div id="cfgClampModel" class="controls"></div>
      </div>      
      <div id="globalConfig" class="config">  
        <h2>Global configuration</h2>
      </div>        
    </td>
  </tr>
  </table>
  <div id="exchangeOptions">
    <button id="importBtn">Import</button>
    <button id="exportBtn">Export</button>
  </div>
  <textarea id="exchangeBox" placeholder="export string"></textarea>
</div>

CSS

body {
  background: #20262E;
  padding: 20px;
  color: #eee;
  font-family: sans-serif;
  font-size: 10px;
  width: 1600px;
}

table.layout td {
  vertical-align: top;
}

#exchangeOptions button {
  color: #ffc;
  border: 1px solid #999;
  background: #445;
}

#exchangeOptions {
  padding: 5px;
}

#exchangeBox {
  width: 620px;
  min-height: 200px;
  margin: 3px;
  color: #bba;
  font-size: 12px;
  border: 1px solid #999;
  background: transparent;
}

#upsDisplay, #fpsDisplay {
  padding-right: 10px;
  font-family: monospace;
}

.display.resetBtn:hover {
    cursor: pointer; 
    background: #07a;
}

.tool {
  display: inline-block;
  width: 30px;
  height: 30px;
  background: radial-gradient(#909090,#6b6b6c);
  background-color: rgba(0, 0, 0, 0);
  border-top: 1px solid #CCC;
  border-left: 1px solid #CCC;
  border-right: 1px solid #2A2A2A;
  border-bottom: 1px solid #2A2A2A;
}

.tool.selected {
  background: radial-gradient(#505050,#3b3b3c);
  border-top: 1px solid #2A2A2A;
  border-left: 1px solid #2A2A2A;
  border-right: 1px solid #CCC;
  border-bottom: 1px solid #CCC;
}

.tool .image {
  width: 30px;
  height: 30px;
  background-size: 25px;
  background-position: 50% 50%;
  background-repeat: no-repeat;
}

.tool.pipe .image {
  background-image: url("https://wiki.factorio.com/images/Pipe.png");
}

.tool.source .image {
  background-image: url("https://wiki.factorio.com/images/Pumpjack.png");
}

.tool.sink .image {
  background-image: url("https://wiki.factorio.com/images/Oil_refinery.png");
}

.tool.tank .image {
  background-image: url("https://wiki.factorio.com/images/Storage_tank.png");
}

.tool.edit .image {
  background-image: url("https://wiki.factorio.com/images/Repair_pack.png");
}

#grid {
  display: block;
  user-select: none;
  -webkit-user-select: none;
  padding-bottom: 1px;
  border-bottom: 1px solid #000;
  border-right: 1px solid #000;
}

.config .desc {
  font-style: italic;
  margin: 0 0 15px 0px;
}

.config .controls {
  margin: 0 0 15px...

JavaScript

var width = 20;
var height = 20;
var ups = 60; // updates per second

var bufferSize = 1; // multiple of production/consumption that a entity can store

var modelSelection = {
		pressureModel : null,
    clampModel: null
}

var globalConfig = {
    displayThroughput: {
    	value: false,
      desc: "Display source/sink throughput"
    },
    smoothThroughput: {
    	value: true,
      desc: "Smooth source output/sink input over time"
    }
}

var pressureModelDef = {
	"Wave Equation": {
    desc: "Wave equation with linear pressure.",
  	flowFn: function(t0, t1, f) {
    	var cfg = this.config;
      f += (this.pressureFn(t0) - this.pressureFn(t1)) * cfg.cSquared.value;
      f *= 1 - cfg.friction.value;
      return f;
    },
    pressureFn: function(t) {
    	return t.content / t.maxContent * 100;
    },
    config: {
      cSquared: {
      	value: 0.01,
        range: [0, 1],
        desc: "C-Squared"
      },
      friction: {
      	value: 0.001,
        range: [0, 1],
        desc: "Friction"
      }
    }
  },
  "Wave Equation, Non-Linear Pressure": {
    desc: "Wave equation with non-linear pressure.",
  	flowFn: function(t0, t1, f) {
    	var cfg = this.config;
      f += (this.pressureFn(t0) - this.pressureFn(t1)) * cfg.cSquared.value;
      f *= 1 - cfg.friction.value;
      return f;
    },
    pressureFn: function(t) {
      var p = t.content / t.maxContent * 100;
  		return p <= 60 ? p : 60 + (p-60) * 10;	      
    },
    config: {
      cSquared: {
      	value: 0.01,
        range: [0, 1],        
        desc: "C-Squared"
      },
      friction: {
      	value: 0.001,
        range: [0, 1],        
        desc: "Friction"
      }
    }    
  },
  "Wave Equation with damping": {
    desc: "Model that can quickly eliminate waves without relying on friction.",
  	flowFn: function(t0, t1, f) {
    	var cfg = this.config;
      var dp = this.pressureFn(t0) - this.pressureFn(t1);
      var c;
      if (sign(f) == sign(dp)) c = cfg.cSquared.value;
...