exafunction--windsurf-demo
1b66bc97c4
- Fix missing DECAY_SIZE_FACTOR import in utils.test.js - Fix inconsistent decay calculation in tests (use power function instead of sqrt) - Remove unused DECAY_ENABLED import from utils.test.js - Improve DECAY_THRESHOLD documentation for clarity
148 行
4.6 KiB
JavaScript
148 行
4.6 KiB
JavaScript
import * as utils from '../utils.js';
|
|
import * as config from '../config.js';
|
|
|
|
describe('decay mechanics', () => {
|
|
// Mock Date.now() to return a consistent value for tests
|
|
const NOW = 1621234567890; // Fixed timestamp for testing
|
|
let originalDateNow;
|
|
// Setup and teardown for each test
|
|
beforeEach(() => {
|
|
// Mock the config values directly
|
|
config.DECAY_ENABLED = true;
|
|
config.DECAY_RATE = 0.05;
|
|
config.DECAY_THRESHOLD = 50;
|
|
config.DECAY_MOVEMENT_MULTIPLIER = 1.5;
|
|
config.DECAY_SIZE_FACTOR = 0.2;
|
|
config.DECAY_STARVATION_THRESHOLD = 10;
|
|
config.DECAY_STARVATION_MULTIPLIER = 2;
|
|
|
|
// Mock Date.now
|
|
originalDateNow = Date.now;
|
|
Date.now = jest.fn(() => NOW);
|
|
});
|
|
|
|
afterEach(() => {
|
|
// Restore all mocks
|
|
jest.restoreAllMocks();
|
|
Date.now = originalDateNow;
|
|
});
|
|
|
|
test('should not decay below threshold', () => {
|
|
const entity = { score: config.DECAY_THRESHOLD };
|
|
utils.applyDecay(entity, 1000);
|
|
expect(entity.score).toBe(config.DECAY_THRESHOLD);
|
|
});
|
|
|
|
test('should decay proportionally to time passed', () => {
|
|
const entity = { score: 100 };
|
|
const expectedDecayFactor = Math.pow(entity.score, config.DECAY_SIZE_FACTOR) / 10;
|
|
const expectedDecayAmount = config.DECAY_RATE * expectedDecayFactor * 1; // 1 second
|
|
|
|
utils.applyDecay(entity, 1000); // 1 second
|
|
|
|
expect(entity.score).toBeCloseTo(100 - expectedDecayAmount, 5);
|
|
});
|
|
|
|
test('should decay more for higher scores', () => {
|
|
const smallEntity = { score: 100 };
|
|
const largeEntity = { score: 400 };
|
|
|
|
// Apply same time decay to both
|
|
utils.applyDecay(smallEntity, 1000);
|
|
utils.applyDecay(largeEntity, 1000);
|
|
|
|
// Calculate expected decay
|
|
const smallDecayFactor = Math.pow(100, config.DECAY_SIZE_FACTOR) / 10;
|
|
const largeDecayFactor = Math.pow(400, config.DECAY_SIZE_FACTOR) / 10;
|
|
|
|
// Verify larger entity decayed more
|
|
expect(largeDecayFactor).toBeGreaterThan(smallDecayFactor);
|
|
expect(100 - smallEntity.score).toBeLessThan(400 - largeEntity.score);
|
|
});
|
|
|
|
test('should not decay when disabled', () => {
|
|
// Temporarily disable decay for this test
|
|
const originalDecayEnabled = config.DECAY_ENABLED;
|
|
config.DECAY_ENABLED = false;
|
|
|
|
const entity = { score: 100 };
|
|
utils.applyDecay(entity, 1000);
|
|
|
|
// Restore original value
|
|
config.DECAY_ENABLED = originalDecayEnabled;
|
|
|
|
expect(entity.score).toBe(100);
|
|
});
|
|
|
|
test('should handle very large time deltas gracefully', () => {
|
|
const entity = { score: 200 };
|
|
|
|
// Apply a very large time delta (10 seconds)
|
|
utils.applyDecay(entity, 10000);
|
|
|
|
// Should not go below threshold
|
|
expect(entity.score).toBeGreaterThanOrEqual(config.DECAY_THRESHOLD);
|
|
});
|
|
|
|
test('should apply movement-based decay', () => {
|
|
// Entity with velocity
|
|
const entity = {
|
|
score: 100,
|
|
velocityX: 2,
|
|
velocityY: 2
|
|
};
|
|
|
|
// Entity with no velocity
|
|
const staticEntity = {
|
|
score: 100,
|
|
velocityX: 0,
|
|
velocityY: 0
|
|
};
|
|
|
|
utils.applyDecay(entity, 1000);
|
|
utils.applyDecay(staticEntity, 1000);
|
|
|
|
// Moving entity should decay more
|
|
expect(entity.score).toBeLessThan(staticEntity.score);
|
|
});
|
|
|
|
test('should apply starvation decay', () => {
|
|
// Entity that just ate
|
|
const recentlyFedEntity = {
|
|
score: 100,
|
|
lastFoodTime: NOW
|
|
};
|
|
|
|
// Entity that hasn't eaten in a while
|
|
const starvingEntity = {
|
|
score: 100,
|
|
lastFoodTime: NOW - (config.DECAY_STARVATION_THRESHOLD * 1000 + 5000) // Past threshold
|
|
};
|
|
|
|
utils.applyDecay(recentlyFedEntity, 1000);
|
|
utils.applyDecay(starvingEntity, 1000);
|
|
|
|
// Starving entity should decay more
|
|
expect(starvingEntity.score).toBeLessThan(recentlyFedEntity.score);
|
|
});
|
|
|
|
test('should apply size-based decay using power function', () => {
|
|
const smallEntity = { score: 100 };
|
|
const largeEntity = { score: 400 };
|
|
|
|
// Calculate expected decay with power function
|
|
const smallDecayFactor = Math.pow(smallEntity.score, config.DECAY_SIZE_FACTOR) / 10;
|
|
const largeDecayFactor = Math.pow(largeEntity.score, config.DECAY_SIZE_FACTOR) / 10;
|
|
|
|
// Verify power function gives different results than sqrt
|
|
expect(largeDecayFactor / smallDecayFactor).not.toBeCloseTo(2); // sqrt would be 2
|
|
|
|
utils.applyDecay(smallEntity, 1000);
|
|
utils.applyDecay(largeEntity, 1000);
|
|
|
|
// Larger entity should decay more, but by a different factor than with sqrt
|
|
expect(largeEntity.score).toBeLessThan(400);
|
|
expect(smallEntity.score).toBeLessThan(100);
|
|
});
|
|
});
|