mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-12 07:04:52 +09:00
Convert dole code to follow project style
This commit is contained in:
1 parent
8586dfb95f
commit
ceade431ef
2 files changed
+172
-127
No files matched your search
@@ -6,7 +6,8 @@ const { Gauge } = require("@clusterio/lib/prometheus");
|
||||
|
||||
const prometheusNNDoleGauge = new Gauge(
|
||||
"clusterio_subspace_storage_nn_dole_gauge",
|
||||
"Current demand being supplied by Neural Network ; 1 means all demand covered, 0.5 means about half of each supply is covered, 0 means no items are given",
|
||||
"Current demand being supplied by Neural Network ; 1 means all demand covered, "+
|
||||
"0.5 means about half of each supply is covered, 0 means no items are given",
|
||||
{ labels: ["resource"] }
|
||||
);
|
||||
const prometheusDoleFactorGauge = new Gauge(
|
||||
@@ -16,24 +17,24 @@ const prometheusDoleFactorGauge = new Gauge(
|
||||
);
|
||||
|
||||
class NeuralDole {
|
||||
|
||||
getRequestStats(itemname,samples)
|
||||
{
|
||||
var sum=0;
|
||||
samples=Math.min(samples,(this.stats[itemname] || []).length-1);
|
||||
if (samples<1) return 0.1;
|
||||
for (var i = 1; i <= samples; i++) {
|
||||
sum+=this.stats[itemname][i].req;
|
||||
getRequestStats(itemname, samples) {
|
||||
let sum = 0;
|
||||
samples = Math.min(samples, (this.stats[itemname] || []).length - 1);
|
||||
if (samples < 1) {
|
||||
return 0.1;
|
||||
}
|
||||
for (let i = 1; i <= samples; i++) {
|
||||
sum += this.stats[itemname][i].req;
|
||||
}
|
||||
if (sum === 0) {
|
||||
return 0.1;
|
||||
}
|
||||
return sum/samples;
|
||||
return sum / samples;
|
||||
}
|
||||
|
||||
constructor({
|
||||
items,
|
||||
}){
|
||||
}) {
|
||||
// Set some storage variables for the dole divider
|
||||
this.items = items;
|
||||
this.itemsLastTick = new Map(items._items);
|
||||
@@ -50,11 +51,13 @@ class NeuralDole {
|
||||
count,
|
||||
this.dole[name],
|
||||
this.itemsLastTick.get(name),
|
||||
this.getRequestStats(name,5)
|
||||
this.getRequestStats(name, 5)
|
||||
);
|
||||
this.stats[name]=this.stats[name] || [];
|
||||
this.stats[name].unshift({ req: 0, given: 0 });//stats[name][0] is the one we currently collect
|
||||
if (this.stats[name].length>10) this.stats[name].pop();//remove if too many samples in stats
|
||||
this.stats[name] = this.stats[name] || [];
|
||||
this.stats[name].unshift({ req: 0, given: 0 }); // stats[name][0] is the one we currently collect
|
||||
if (this.stats[name].length>10) {
|
||||
this.stats[name].pop(); // remove if too many samples in stats
|
||||
}
|
||||
|
||||
this.dole[name] = magicData[0];
|
||||
// DONE handle magicData[1] for graphing for our users
|
||||
@@ -69,23 +72,22 @@ class NeuralDole {
|
||||
this.items.getItemCount(object.name),
|
||||
this.itemsLastTick.get(object.name) || 0,
|
||||
this.dole[object.name],
|
||||
this.carry[object.name+" "+object.instanceID] || 0,
|
||||
this.lastRequest[object.name+"_"+object.instanceID+"_"+object.instanceName] || 0,
|
||||
this.getRequestStats(object.name,5),
|
||||
this.debt[object.name+" "+object.instanceID] || 0
|
||||
this.carry[`${object.name} ${object.instanceID}`] || 0,
|
||||
this.lastRequest[`${object.name}_${object.instanceID}_${object.instanceName}`] || 0,
|
||||
this.getRequestStats(object.name, 5),
|
||||
this.debt[`${object.name} ${object.instanceID}`] || 0
|
||||
);
|
||||
if ((this.stats[object.name] || []).length>0)
|
||||
{
|
||||
this.stats[object.name][0].req+=Number(object.count);
|
||||
this.stats[object.name][0].given+=Number(magicData[0]);
|
||||
if ((this.stats[object.name] || []).length > 0) {
|
||||
this.stats[object.name][0].req += Number(object.count);
|
||||
this.stats[object.name][0].given += Number(magicData[0]);
|
||||
}
|
||||
this.lastRequest[object.name+"_"+object.instanceID+"_"+object.instanceName] = object.count;
|
||||
//0.Number of items to give in that dose
|
||||
//1.New dole for item X
|
||||
//2.New carry for item X slave Y
|
||||
this.lastRequest[`${object.name}_${object.instanceID}_${object.instanceName}`] = object.count;
|
||||
// 0. Number of items to give in that dose
|
||||
// 1. New dole for item X
|
||||
// 2. New carry for item X slave Y
|
||||
this.dole[object.name] = magicData[1];
|
||||
this.carry[object.name+" "+object.instanceID] = magicData[2];
|
||||
this.debt[object.name+" "+object.instanceID] = magicData[3];
|
||||
this.carry[`${object.name} ${object.instanceID}`] = magicData[2];
|
||||
this.debt[`${object.name} ${object.instanceID}`] = magicData[3];
|
||||
|
||||
// Remove item from DB and send it
|
||||
this.items.removeItem(object.name, magicData[0]);
|
||||
@@ -94,39 +96,50 @@ class NeuralDole {
|
||||
}
|
||||
}
|
||||
|
||||
// If the server regularly can't fulfill requests, this number grows until it can. Then it slowly shrinks back down.
|
||||
// If the server regularly can't fulfill requests, this number grows until
|
||||
// it can. Then it slowly shrinks back down.
|
||||
let _doleDivisionFactor = {};
|
||||
function doleDivider({
|
||||
object,
|
||||
items,
|
||||
logItemTransfers,
|
||||
}){
|
||||
}) {
|
||||
let itemCount = items.getItemCount(object.name);
|
||||
const doleDivisionRetardation = 10; //lower rates will equal more dramatic swings
|
||||
const maxDoleDivision = 250; //a higher cap will divide the store more ways, but will take longer to recover as supplies increase
|
||||
// lower rates will equal more dramatic swings
|
||||
const doleDivisionRetardation = 10;
|
||||
// a higher cap will divide the store more ways, but will take longer to
|
||||
// recover as supplies increase
|
||||
const maxDoleDivision = 250;
|
||||
|
||||
const originalCount = Number(object.count) || 0;
|
||||
object.count /= ((_doleDivisionFactor[object.name]||0)+doleDivisionRetardation)/doleDivisionRetardation;
|
||||
object.count /= ((_doleDivisionFactor[object.name] || 0) + doleDivisionRetardation) / doleDivisionRetardation;
|
||||
object.count = Math.round(object.count);
|
||||
if (logItemTransfers) {
|
||||
console.info(`Serving ${object.count}/${originalCount} ${object.name} from ${itemCount} ${object.name} with dole division factor ${(_doleDivisionFactor[object.name]||0)} (real=${((_doleDivisionFactor[object.name]||0)+doleDivisionRetardation)/doleDivisionRetardation}), item is ${itemCount > object.count?"stocked":"short"}.`);
|
||||
console.info(
|
||||
`Serving ${object.count}/${originalCount} ${object.name} from ${itemCount} ${object.name} `+
|
||||
`with dole division factor ${(_doleDivisionFactor[object.name]||0)} `+
|
||||
`(real=${((_doleDivisionFactor[object.name] || 0) + doleDivisionRetardation) / doleDivisionRetardation}), `+
|
||||
`item is ${itemCount > object.count?"stocked":"short"}.`
|
||||
);
|
||||
}
|
||||
|
||||
// Update existing items if item name already exists
|
||||
if (itemCount > object.count) {
|
||||
//If successful, increase dole
|
||||
_doleDivisionFactor[object.name] = Math.max((_doleDivisionFactor[object.name]||0)||1, 1) - 1;
|
||||
// If successful, increase dole
|
||||
_doleDivisionFactor[object.name] = Math.max((_doleDivisionFactor[object.name] || 0) || 1, 1) - 1;
|
||||
items.removeItem(object.name, object.count);
|
||||
|
||||
prometheusDoleFactorGauge.labels(object.name).set(_doleDivisionFactor[object.name] || 0);
|
||||
return object.count;
|
||||
} else {
|
||||
// if we didn't have enough, attempt giving out a smaller amount next time
|
||||
_doleDivisionFactor[object.name] = Math.min(maxDoleDivision, Math.max((_doleDivisionFactor[object.name]||0)||1, 1) * 2);
|
||||
prometheusDoleFactorGauge.labels(object.name).set(_doleDivisionFactor[object.name] || 0);
|
||||
return 0;
|
||||
//console.log('failure out of ' + object.name + " | " + object.count + " from " + object.instanceID + " ("+object.instanceName+")");
|
||||
}
|
||||
|
||||
// if we didn't have enough, attempt giving out a smaller amount next time
|
||||
_doleDivisionFactor[object.name] = Math.min(
|
||||
maxDoleDivision, Math.max((_doleDivisionFactor[object.name] || 0) || 1, 1) * 2
|
||||
);
|
||||
prometheusDoleFactorGauge.labels(object.name).set(_doleDivisionFactor[object.name] || 0);
|
||||
return 0;
|
||||
// console.log(`failure out of ${object.name}/${object.count} from ${object.instanceID} (${object.instanceName})`);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
@@ -1,122 +1,154 @@
|
||||
//Sigmoids...
|
||||
// Sigmoids...
|
||||
|
||||
"use strict";
|
||||
function sigmoid0(x)
|
||||
{
|
||||
return x/(1+Math.abs(x));
|
||||
function sigmoid0(x) {
|
||||
return x / (1 + Math.abs(x));
|
||||
}
|
||||
function sigmoid1(x)
|
||||
{
|
||||
if (x>=0.0) {
|
||||
|
||||
function sigmoid1(x) {
|
||||
if (x >= 0.0) {
|
||||
return 1.0;
|
||||
} else {
|
||||
return 0.0;
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
function sigmoid2(x)
|
||||
{
|
||||
if (x>=0.0){
|
||||
|
||||
function sigmoid2(x) {
|
||||
if (x >= 0.0) {
|
||||
return x;
|
||||
} else {
|
||||
return 0.0;
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
function sigmoid3(x)
|
||||
{
|
||||
|
||||
function sigmoid3(x) {
|
||||
return x;
|
||||
}
|
||||
|
||||
//DOSE - Doses items for item X slave Y
|
||||
//Numreq - number of items that are requested for item X for slave Y
|
||||
//Instore - number of items for item X in master gauge (currently)
|
||||
//store_last_tick - Number of items for item X in master gauge at time of last tick
|
||||
//dole - Current dole for item X
|
||||
//carry - carry for item X slave Y
|
||||
//prev_req - Numreq for previous request for item X slave Y
|
||||
//* doleinfo_last - Object with 2 values for last "tick period": numreq - total number or requests for item, numslave - number of slaves requesting that item
|
||||
//debt - debt for item X slave Y
|
||||
// DOSE - Doses items for item X slave Y
|
||||
// Numreq - number of items that are requested for item X for slave Y
|
||||
// Instore - number of items for item X in master gauge (currently)
|
||||
// store_last_tick -
|
||||
// Number of items for item X in master gauge at time of last tick
|
||||
// dole - Current dole for item X
|
||||
// carry - carry for item X slave Y
|
||||
// prev_req - Numreq for previous request for item X slave Y
|
||||
// * doleinfo_last -
|
||||
// Object with 2 values for last "tick period": numreq - total number or
|
||||
// requests for item, numslave - number of slaves requesting that item
|
||||
// debt - debt for item X slave Y
|
||||
|
||||
//Returns: Array of 3 elements
|
||||
//0.Number of items to give in that dose
|
||||
//1.New dole for item X
|
||||
//2.New carry for item X slave Y
|
||||
//3.New debt
|
||||
// Returns: Array of 3 elements
|
||||
// 0.Number of items to give in that dose
|
||||
// 1.New dole for item X
|
||||
// 2.New carry for item X slave Y
|
||||
// 3.New debt
|
||||
function dose(numreq, instore, store_last_tick, dole, carry, prev_req, numreq_total_adj, debt) {
|
||||
numreq=Number(numreq);
|
||||
instore=Number(instore);
|
||||
var instore_adj=instore;
|
||||
numreq = Number(numreq);
|
||||
instore = Number(instore);
|
||||
let instore_adj = instore;
|
||||
if (instore_adj === 0) {
|
||||
instore_adj = 0.1;
|
||||
}
|
||||
|
||||
var b=Math.trunc(prev_req/instore_adj*numreq);
|
||||
var inp1=[numreq,instore_adj,store_last_tick/numreq,dole,carry];//0..4
|
||||
var 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
|
||||
var inputs=inp1.concat(inp2);
|
||||
var internal=new Array(20).fill(0);
|
||||
var outputs=[0,0,0,0];
|
||||
//NN: Please don't touch :), code is generated
|
||||
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 internal = new Array(20).fill(0);
|
||||
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]);
|
||||
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;
|
||||
debt = debt || 0;
|
||||
if (outputs[0] > 0.99) {
|
||||
outputs[0]=1.0;
|
||||
}
|
||||
|
||||
var res1=Number(outputs[0])*numreq+outputs[3]+debt;
|
||||
var res_capped=Math.round(res1);
|
||||
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;
|
||||
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;
|
||||
debt_cap=Math.round(numreq*1.5)+5;
|
||||
if (debt>debt_cap) debt=debt_cap;
|
||||
res1 = res1 || 0;
|
||||
res_capped = res_capped || 0; // Safeguard against wrong values
|
||||
debt = res1 - res_capped;
|
||||
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];
|
||||
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 slaves requesting that item
|
||||
//Instore - number of items for item X in master gauge (currently)
|
||||
//dole - Current dole for item X
|
||||
//store_last_tick - Number of items for item X in master 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, numslave - number of slaves requesting that item
|
||||
//* doleinfo_new - Object with 2 values for new "tick period": numreq - total number or requests for item, numslave - number of slaves requesting that item
|
||||
// TICK -
|
||||
// Updates values for item X, should be called once for each item for
|
||||
// each round of all slaves requesting that item Instore - number of
|
||||
// items for item X in master gauge (currently)
|
||||
// dole - Current dole for item X
|
||||
// store_last_tick -
|
||||
// Number of items for item X in master 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, numslave - number of slaves requesting that item
|
||||
//
|
||||
// * doleinfo_new -
|
||||
// Object with 2 values for new "tick period": numreq - total number or
|
||||
// requests for item, numslave - number of slaves 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
|
||||
// Returns: Array of 2 elements
|
||||
// 0.New dole for item X
|
||||
// 1.Guessed percentage average of items supplied in last 10 ticks
|
||||
function tick(instore, dole, store_last_tick, numreq_total_adj) {
|
||||
var instore_adj=instore;
|
||||
let instore_adj = instore;
|
||||
if (instore_adj === 0) {
|
||||
instore_adj = 0.1;
|
||||
}
|
||||
var inputs=[instore,dole,store_last_tick/instore_adj,store_last_tick/numreq_total_adj,store_last_tick,numreq_total_adj];
|
||||
var internal=new Array(10).fill(0);
|
||||
var outputs=[0,0];
|
||||
//NN: Please don't touch :), code is generated
|
||||
let inputs = [
|
||||
instore,
|
||||
dole,
|
||||
store_last_tick / instore_adj,
|
||||
store_last_tick / numreq_total_adj,
|
||||
store_last_tick,
|
||||
numreq_total_adj,
|
||||
];
|
||||
let internal = new Array(10).fill(0);
|
||||
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]);
|
||||
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]);
|
||||
|
||||
avg=outputs[1];
|
||||
if (numreq_total_adj<0.11) avg=1;//When no item's are requested, result is 0.1 ; In that case there is no deficit, so return 1 = 100% demand fulfilled
|
||||
if (avg>1) avg=1;
|
||||
if (avg<0) avg=0;
|
||||
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];
|
||||
return [sigmoid0(outputs[0]), avg];
|
||||
}
|
||||
|
||||
module.exports = { dose, tick };
|
||||
Reference in new issue
Block a user