161 lines
5.0 KiB
JavaScript
161 lines
5.0 KiB
JavaScript
const CellStates = require("../Organism/Cell/CellStates");
|
|
const SerializeHelper = require("../Utils/SerializeHelper");
|
|
const Species = require("./Species");
|
|
|
|
const FossilRecord = {
|
|
init: function(){
|
|
this.extant_species = {};
|
|
this.extinct_species = {};
|
|
|
|
// if an organism has fewer than this cumulative pop, discard them on extinction
|
|
this.min_discard = 10;
|
|
|
|
this.record_size_limit = 500; // store this many data points
|
|
},
|
|
|
|
setEnv: function(env) {
|
|
this.env = env;
|
|
this.setData();
|
|
},
|
|
|
|
addSpecies: function(org, ancestor) {
|
|
var new_species = new Species(org.anatomy, ancestor, this.env.total_ticks);
|
|
this.extant_species[new_species.name] = new_species;
|
|
org.species = new_species;
|
|
return new_species;
|
|
},
|
|
|
|
addSpeciesObj: function(species) {
|
|
if (this.extant_species[species.name]) {
|
|
console.warn('Tried to add already existing species. Add failed.');
|
|
return;
|
|
}
|
|
this.extant_species[species.name] = species;
|
|
return species;
|
|
},
|
|
|
|
numExtantSpecies() {return Object.values(this.extant_species).length},
|
|
numExtinctSpecies() {return Object.values(this.extinct_species).length},
|
|
speciesIsExtant(species_name) {return !!this.extant_species[species_name]},
|
|
|
|
fossilize: function(species) {
|
|
if (!this.extant_species[species.name]) {
|
|
console.warn('Tried to fossilize non existing species.');
|
|
return false;
|
|
}
|
|
species.end_tick = this.env.total_ticks;
|
|
species.ancestor = undefined; // garbage collect ancestors
|
|
delete this.extant_species[species.name];
|
|
if (species.cumulative_pop >= this.min_discard) {
|
|
// TODO: store as extinct species
|
|
return true;
|
|
}
|
|
return false;
|
|
},
|
|
|
|
resurrect: function(species) {
|
|
if (species.extinct) {
|
|
species.extinct = false;
|
|
this.extant_species[species.name] = species;
|
|
delete this.extinct_species[species.name];
|
|
}
|
|
},
|
|
|
|
setData() {
|
|
// all parallel arrays
|
|
this.tick_record = [];
|
|
this.pop_counts = [];
|
|
this.species_counts = [];
|
|
this.av_mut_rates = [];
|
|
this.av_cells = [];
|
|
this.av_cell_counts = [];
|
|
this.updateData();
|
|
},
|
|
|
|
updateData() {
|
|
var tick = this.env.total_ticks;
|
|
this.tick_record.push(tick);
|
|
this.pop_counts.push(this.env.organisms.length);
|
|
this.species_counts.push(this.numExtantSpecies());
|
|
this.av_mut_rates.push(this.env.averageMutability());
|
|
this.calcCellCountAverages();
|
|
while (this.tick_record.length > this.record_size_limit) {
|
|
this.tick_record.shift();
|
|
this.pop_counts.shift();
|
|
this.species_counts.shift();
|
|
this.av_mut_rates.shift();
|
|
this.av_cells.shift();
|
|
this.av_cell_counts.shift();
|
|
}
|
|
},
|
|
|
|
calcCellCountAverages() {
|
|
var total_org = 0;
|
|
var cell_counts = {};
|
|
for (let c of CellStates.living) {
|
|
cell_counts[c.name] = 0;
|
|
}
|
|
var first=true;
|
|
for (let s of Object.values(this.extant_species)) {
|
|
if (!first && this.numExtantSpecies() > 10 && s.cumulative_pop < this.min_discard){
|
|
continue;
|
|
}
|
|
for (let name in s.cell_counts) {
|
|
cell_counts[name] += s.cell_counts[name] * s.population;
|
|
}
|
|
total_org += s.population;
|
|
first=false;
|
|
}
|
|
if (total_org == 0) {
|
|
this.av_cells.push(0);
|
|
this.av_cell_counts.push(cell_counts);
|
|
return;
|
|
}
|
|
|
|
var total_cells = 0;
|
|
for (let c in cell_counts) {
|
|
total_cells += cell_counts[c];
|
|
cell_counts[c] /= total_org;
|
|
}
|
|
this.av_cells.push(total_cells / total_org);
|
|
this.av_cell_counts.push(cell_counts);
|
|
},
|
|
|
|
clear_record() {
|
|
this.extant_species = [];
|
|
this.extinct_species = [];
|
|
this.setData();
|
|
},
|
|
|
|
serialize() {
|
|
this.updateData();
|
|
let record = SerializeHelper.copyNonObjects(this);
|
|
record.records = {
|
|
tick_record:this.tick_record,
|
|
pop_counts:this.pop_counts,
|
|
species_counts:this.species_counts,
|
|
av_mut_rates:this.av_mut_rates,
|
|
av_cells:this.av_cells,
|
|
av_cell_counts:this.av_cell_counts,
|
|
};
|
|
let species = {};
|
|
for (let s of Object.values(this.extant_species)) {
|
|
species[s.name] = SerializeHelper.copyNonObjects(s);
|
|
delete species[s.name].name; // the name will be used as the key, so remove it from the value
|
|
}
|
|
record.species = species;
|
|
return record;
|
|
},
|
|
|
|
loadRaw(record) {
|
|
SerializeHelper.overwriteNonObjects(record, this);
|
|
for (let key in record.records) {
|
|
this[key] = record.records[key];
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
FossilRecord.init();
|
|
|
|
module.exports = FossilRecord; |