@clusterio/plugin-subspace_storage
Version:
Clusterio plugin for sharing storage between Factorio servers
164 lines (144 loc) • 4.51 kB
text/typescript
// Sigmoids...
function sigmoid0(x: number): number {
return x / (1 + Math.abs(x));
}
function sigmoid1(x: number): number {
if (x >= 0.0) {
return 1.0;
}
return 0.0;
}
function sigmoid2(x: number): number {
if (x >= 0.0) {
return x;
}
return 0.0;
}
function sigmoid3(x: number) {
return x;
}
// DOSE - Doses items for item X instance Y
// Numreq - number of items that are requested for item X for instance Y
// Instore - number of items for item X in controller gauge (currently)
// store_last_tick -
// Number of items for item X in controller gauge at time of last tick
// dole - Current dole for item X
// carry - carry for item X instance Y
// prev_req - Numreq for previous request for item X instance Y
// * doleinfo_last -
// Object with 2 values for last "tick period": numreq - total number or
// requests for item, numinstance - number of instances requesting that item
// debt - debt for item X instance Y
// Returns: Array of 4 elements
// 0.Number of items to give in that dose
// 1.New dole for item X
// 2.New carry for item X instance Y
// 3.New debt
export function dose(
numreq: number,
instore: number,
store_last_tick: number,
dole: number,
carry: number,
prev_req: number,
numreq_total_adj: number,
debt: number,
): [number, number, number, number] {
numreq = Number(numreq);
instore = Number(instore);
let instore_adj = instore;
if (instore_adj === 0) {
instore_adj = 0.1;
}
let b = Math.trunc(prev_req / instore_adj * numreq);
let inp1 = [numreq, instore_adj, store_last_tick / numreq, dole, carry]; // 0..4
let inp2 = [
prev_req / numreq,
numreq / numreq_total_adj,
store_last_tick / numreq_total_adj,
prev_req/instore_adj,
b,
numreq_total_adj,
store_last_tick,
debt,
]; // 5..12
let inputs = inp1.concat(inp2);
let outputs = [0, 0, 0, 0];
// NN: Please don't touch :), code is generated
outputs[0] = inputs[7] * 0.8058582544;
outputs[0] = sigmoid2(outputs[0]);
outputs[1] = sigmoid0(outputs[1]);
outputs[2] = sigmoid0(outputs[2]);
outputs[3] = inputs[6] * 0.2294657379;
outputs[3] = sigmoid0(outputs[3]);
debt = debt || 0;
if (outputs[0] > 0.99) {
outputs[0]=1.0;
}
let res1 = Number(outputs[0]) * numreq + outputs[3] + debt;
let res_capped = Math.round(res1);
if (res_capped > numreq) { res_capped = numreq; }
if (res_capped > instore) { res_capped = instore; }
if (res_capped < 0) { res_capped = 0; }
res1 = res1 || 0;
res_capped = res_capped || 0; // Safeguard against wrong values
debt = res1 - res_capped;
let debt_cap = Math.round(numreq * 1.5) + 5;
if (debt > debt_cap) {
debt = debt_cap;
}
carry = sigmoid0(outputs[2] * carry + outputs[0]) || 0;
return [res_capped, dole + outputs[1], carry, debt];
}
// TICK -
// Updates values for item X, should be called once for each item for
// each round of all instances requesting that item Instore - number of
// items for item X in controller gauge (currently)
// dole - Current dole for item X
// store_last_tick -
// Number of items for item X in controller gauge at time of last tick (not this one)
// * doleinfo_last -
// Object with 2 values for last "tick period": numreq - total number or
// requests for item, numinstance - number of instances requesting that item
//
// * doleinfo_new -
// Object with 2 values for new "tick period": numreq - total number or
// requests for item, numinstance - number of instances requesting that item
// Returns: Array of 2 elements
// 0.New dole for item X
// 1.Guessed percentage average of items supplied in last 10 ticks
export function tick(
instore: number,
dole: number,
store_last_tick: number,
numreq_total_adj: number,
): [number, number] {
let instore_adj = instore;
if (instore_adj === 0) {
instore_adj = 0.1;
}
let inputs = [
instore,
dole,
store_last_tick / instore_adj,
store_last_tick / numreq_total_adj,
store_last_tick,
numreq_total_adj,
];
let outputs = [0, 0];
// NN: Please don't touch :), code is generated
outputs[0] = inputs[3] * 0.9364774823;
outputs[0] = outputs[0] * 0.4590721726;
outputs[0] = sigmoid2(outputs[0]);
outputs[1] = outputs[0] * 1.828422785;
outputs[1] = sigmoid3(outputs[1]);
let avg = outputs[1];
if (numreq_total_adj < 0.11) {
// When no item's are requested, result is 0.1; In that case there is
// no deficit, so return 1 = 100% demand fulfilled
avg = 1;
}
if (avg > 1) { avg=1; }
if (avg < 0) { avg=0; }
return [sigmoid0(outputs[0]), avg];
}