You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tobspr_shapez.io/src/js/game/production_analytics.js

135 lines
4.1 KiB

import { GameRoot } from "./root";
import { ShapeDefinition } from "./shape_definition";
import { globalConfig } from "../core/config";
import { BaseItem } from "./base_item";
import { ShapeItem } from "./items/shape_item";
import { BasicSerializableObject } from "../savegame/serialization";
/** @enum {string} */
export const enumAnalyticsDataSource = {
produced: "produced",
stored: "stored",
delivered: "delivered",
};
export class ProductionAnalytics extends BasicSerializableObject {
static getId() {
return "ProductionAnalytics";
}
/**
* @param {GameRoot} root
*/
constructor(root) {
super();
this.root = root;
this.history = {
[enumAnalyticsDataSource.produced]: [],
[enumAnalyticsDataSource.stored]: [],
[enumAnalyticsDataSource.delivered]: [],
};
for (let i = 0; i < globalConfig.statisticsGraphSlices; ++i) {
this.startNewSlice();
}
this.root.signals.shapeDelivered.add(this.onShapeDelivered, this);
this.root.signals.itemProduced.add(this.onItemProduced, this);
this.lastAnalyticsSlice = 0;
}
/**
* @param {ShapeDefinition} definition
*/
onShapeDelivered(definition) {
const key = definition.getHash();
const entry = this.history[enumAnalyticsDataSource.delivered];
entry[entry.length - 1][key] = (entry[entry.length - 1][key] || 0) + 1;
}
/**
* @param {BaseItem} item
*/
onItemProduced(item) {
if (item.getItemType() === "shape") {
const definition = /** @type {ShapeItem} */ (item).definition;
const key = definition.getHash();
const entry = this.history[enumAnalyticsDataSource.produced];
entry[entry.length - 1][key] = (entry[entry.length - 1][key] || 0) + 1;
}
}
/**
* Starts a new time slice
*/
startNewSlice() {
for (const key in this.history) {
if (key === enumAnalyticsDataSource.stored) {
// Copy stored data
this.history[key].push(Object.assign({}, this.root.hubGoals.storedShapes));
} else {
this.history[key].push({});
}
while (this.history[key].length > globalConfig.statisticsGraphSlices) {
this.history[key].shift();
}
}
}
/**
* Returns the current rate of a given shape
* @param {enumAnalyticsDataSource} dataSource
* @param {ShapeDefinition} definition
*/
getCurrentShapeRateRaw(dataSource, definition) {
const slices = this.history[dataSource];
return slices[slices.length - 2][definition.getHash()] || 0;
}
/**
* Returns the rate of a given shape, <historyOffset> frames ago
* @param {enumAnalyticsDataSource} dataSource
* @param {ShapeDefinition} definition
* @param {number} historyOffset
*/
getPastShapeRate(dataSource, definition, historyOffset) {
assertAlways(
historyOffset >= 0 && historyOffset < globalConfig.statisticsGraphSlices - 1,
"Invalid slice offset: " + historyOffset
);
const slices = this.history[dataSource];
return slices[slices.length - 2 - historyOffset][definition.getHash()] || 0;
}
/**
* Returns the rates of all shapes
* @param {enumAnalyticsDataSource} dataSource
*/
getCurrentShapeRatesRaw(dataSource) {
const slices = this.history[dataSource];
// First, copy current slice
const baseValues = Object.assign({}, slices[slices.length - 2]);
// Add past values
for (let i = 0; i < 10; ++i) {
const pastValues = slices[slices.length - i - 3];
for (const key in pastValues) {
baseValues[key] = baseValues[key] || 0;
}
}
return baseValues;
}
update() {
if (this.root.time.now() - this.lastAnalyticsSlice > globalConfig.analyticsSliceDurationSeconds) {
this.lastAnalyticsSlice = this.root.time.now();
this.startNewSlice();
}
}
}