@sailboat-computer/data-storage
Version:
Shared data storage library for sailboat computer v3
218 lines (197 loc) • 8 kB
text/typescript
/**
* Integration tests for the downsampling pipeline
*/
import { createDownsamplingEngine } from '../../src/downsampling/engine';
import { createTimeBasedDownsampler } from '../../src/downsampling/strategies/time-based';
import { createGeospatialDownsampler } from '../../src/downsampling/strategies/geospatial';
import { createCycleBasedDownsampler } from '../../src/downsampling/strategies/cycle-based';
import { createMaintenanceBasedDownsampler } from '../../src/downsampling/strategies/maintenance-based';
import { createGeotemporalGridDownsampler } from '../../src/downsampling/strategies/geotemporal-grid';
import {
generateMockEnvironmentalData,
generateMockNavigationData,
generateMockEngineData,
generateMockEquipmentData
} from '../setup';
import {
createWeatherDataGrid,
createWeatherTimeSeries,
createStormWeatherDataPoint
} from '../fixtures/weather-data';
import {
createSeaStateDataGrid,
createSeaStateTimeSeries,
createRoughSeaStateDataPoint
} from '../fixtures/sea-state-data';
describe('Downsampling Pipeline Integration', () => {
// Create downsampling engine
const downsamplingEngine = createDownsamplingEngine();
// Register all downsamplers
beforeAll(() => {
downsamplingEngine.registerDownsampler(createTimeBasedDownsampler());
downsamplingEngine.registerDownsampler(createGeospatialDownsampler());
downsamplingEngine.registerDownsampler(createCycleBasedDownsampler());
downsamplingEngine.registerDownsampler(createMaintenanceBasedDownsampler());
downsamplingEngine.registerDownsampler(createGeotemporalGridDownsampler());
});
describe('Downsampling Engine with GeotemporalGridDownsampler', () => {
it('should initialize with geotemporal grid strategy', () => {
// Initialize with weather rule
downsamplingEngine.initialize([
{
id: 'weather-rule',
name: 'Weather Data Downsampling',
dataType: 'weather.data',
strategy: {
type: 'geotemporal-grid',
baseGridSize: 1.0,
adaptiveGridLevels: 3,
temporalHierarchy: {
recent: { maxAge: 7, resolution: 1 },
mediumTerm: { maxAge: 30, resolution: 6 },
longTerm: { maxAge: 90, resolution: 24 },
historical: { maxAge: 365, resolution: 168 },
seasonal: { resolution: 720 }
},
vesselPosition: { latitude: 37.7749, longitude: -122.4194 },
criticalFeatureThresholds: {
pressureChangeRate: 1.0,
windSpeed: 25,
waveHeight: 2.5,
temperatureGradient: 5.0
}
}
}
]);
// We can't directly verify the rules, but we can test functionality
// by downsampling data and checking the results
});
it('should downsample weather data using the engine', async () => {
// Generate test data
const weatherData = createWeatherDataGrid(37.7749, -122.4194, 1.0, 10, new Date());
// Run downsampling
const result = await downsamplingEngine.downsample(weatherData);
// Verify results
expect(result.length).toBeLessThan(weatherData.length);
expect(result[0].metadata.tags.downsampled).toBe('true');
expect(result[0].metadata.tags.downsamplingStrategy).toBe('geotemporal-grid');
});
it('should initialize with multiple rules including geotemporal grid', () => {
// Initialize with multiple rules
downsamplingEngine.initialize([
{
id: 'environmental-rule',
name: 'Environmental Data Downsampling',
dataType: 'environmental.readings',
strategy: {
type: 'time-based',
levels: [
{
ageThreshold: 1,
interval: '1m',
aggregations: [{ function: 'avg', field: 'temperature' }]
}
]
}
},
{
id: 'navigation-rule',
name: 'Navigation Data Downsampling',
dataType: 'navigation.position',
strategy: {
type: 'geospatial',
simplificationTolerance: 10,
preserveDirectionChanges: true,
minAngleChange: 30,
preserveKeyPoints: true
}
},
{
id: 'weather-rule',
name: 'Weather Data Downsampling',
dataType: 'weather.data',
strategy: {
type: 'geotemporal-grid',
baseGridSize: 1.0,
adaptiveGridLevels: 3,
temporalHierarchy: {
recent: { maxAge: 7, resolution: 1 },
mediumTerm: { maxAge: 30, resolution: 6 },
longTerm: { maxAge: 90, resolution: 24 },
historical: { maxAge: 365, resolution: 168 },
seasonal: { resolution: 720 }
}
}
},
{
id: 'sea-state-rule',
name: 'Sea State Data Downsampling',
dataType: 'sea.state',
strategy: {
type: 'geotemporal-grid',
baseGridSize: 0.5,
adaptiveGridLevels: 3,
temporalHierarchy: {
recent: { maxAge: 3, resolution: 1 },
mediumTerm: { maxAge: 14, resolution: 3 },
longTerm: { maxAge: 60, resolution: 12 },
historical: { maxAge: 180, resolution: 72 },
seasonal: { resolution: 720 }
}
}
}
]);
// We can't directly verify the rules, but we can test functionality
// by downsampling data and checking the results
});
it('should downsample different types of data', async () => {
// Generate test data
const environmentalData = generateMockEnvironmentalData(100).map(item => {
item.metadata.category = 'environmental.readings';
return item;
});
const navigationData = generateMockNavigationData(100).map(item => {
item.metadata.category = 'navigation.position';
return item;
});
const weatherData = createWeatherDataGrid(37.7749, -122.4194, 1.0, 10, new Date()).map(item => {
item.metadata.category = 'weather.data';
return item;
});
const seaStateData = createSeaStateDataGrid(37.8, -122.5, 0.5, 10, new Date()).map(item => {
item.metadata.category = 'sea.state';
return item;
});
// Combine all data
const allData = [
...environmentalData,
...navigationData,
...weatherData,
...seaStateData
];
// Run downsampling
const result = await downsamplingEngine.downsample(allData);
// Verify results
expect(result.length).toBeLessThan(allData.length);
// Group results by category
const resultsByCategory = result.reduce((acc, item) => {
const category = item.metadata.category;
if (!acc[category]) {
acc[category] = [];
}
acc[category].push(item);
return acc;
}, {} as Record<string, any[]>);
// Verify each category has results
expect(resultsByCategory['environmental.readings']).toBeDefined();
expect(resultsByCategory['navigation.position']).toBeDefined();
expect(resultsByCategory['weather.data']).toBeDefined();
expect(resultsByCategory['sea.state']).toBeDefined();
// Verify correct strategies were applied
expect(resultsByCategory['environmental.readings'][0].metadata.tags.downsamplingStrategy).toBe('time-based');
expect(resultsByCategory['navigation.position'][0].metadata.tags.downsamplingStrategy).toBe('geospatial');
expect(resultsByCategory['weather.data'][0].metadata.tags.downsamplingStrategy).toBe('geotemporal-grid');
expect(resultsByCategory['sea.state'][0].metadata.tags.downsamplingStrategy).toBe('geotemporal-grid');
});
});
});