Skip to main content

Separation of Concerns: EPANET vs ESRI Configuration

This document outlines the strategy for properly separating EPANET/backend configuration from ESRI/frontend configuration while maintaining necessary crossover functionality.

Core Principle

EPANET Configuration (Backend) = What the simulation engine needs to know ESRI Configuration (Frontend) = How to visualize the data

Analysis of Current Constants

🔵 EPANET/BACKEND CONFIGURATION (Should migrate to API)

These are simulation-specific and should be backend-driven:

1. Metrics & Units ✅ Already in seed data

// From metrics.json - EPANET simulation metrics
CHLORINE, TR1, CONDUCTIVITY, AGE, THM // Quality metrics
Head, Demand, Pressure, LeakageFlow // Node hydraulic metrics
Flow, Status, Headloss, Power // Link hydraulic metrics

2. Entity Properties ✅ Already in seed data

// From entity-types.json - EPANET model properties
TANK_PROPS = ['Id', 'Index', 'XCoord', 'YCoord', 'InitVolume', ...]
JUNCTION_PROPS = ['Id', 'Index', 'XCoord', 'YCoord', 'Elevation', ...]
PIPE_PROPS = ['Id', 'Index', 'FromNode', 'ToNode', 'Diameter', ...]

3. Aggregator Functions ✅ Already in seed data

// From metrics.json - How to aggregate simulation results
"aggregators": ["avg", "min", "max", "sum"]

4. Float Precision ✅ Already in seed data

// From metrics.json - How to format simulation results
"floatPrecision": 2

🟡 CROSSOVER CONFIGURATION (Needs careful handling)

These have both EPANET and ESRI aspects:

1. Attribute Mappings (EPANET → API → Frontend)

// This bridges EPANET field names to API field names
ATTRIBUTE_TO_API_FIELD = {
"LeakageFlow": "leakageFlow", // EPANET field → API field
"TankVolume": "tankVolume" // EPANET field → API field
}

Strategy: Keep in backend since it's about API field mapping, not visualization.

2. Entity Type Constants (Used by both)

// These are used for both EPANET validation and frontend type checking
TANK = "Tank"
JUNCTION = "Junction"
PIPE = "Pipe"
// etc.

Strategy: Keep in backend since they're fundamental to the data model.

🔴 PURELY ESRI/FRONTEND CONFIGURATION (Should stay in frontend)

These are purely visualization-specific:

1. ESRI Colors & Styling

ESRI_ENTITY_COLORS = {
tanks: 'red',
junctions: 'blue',
// etc.
}

2. Heatmap Visualization Configs

HEATMAP_COLOR_STOPS = {
"Flow": [0, 0.001, 0.3, 0.4, 1],
"Pressure": [0, 0.075, 0.6, 0.9, 1],
// etc.
}

HEATMAP_RENDERER_CONFIG = {
"Flow": { radius: 100, minWeight: 0, maxWeight: 1500, ... },
// etc.
}

3. ESRI FeatureLayer Attributes

ENTITY_ATTRIBUTES = {
SCADA: [
{ name: "id", type: "string" },
{ name: "AssetType", type: "string" },
// etc.
],
// etc.
}

Backend API Endpoints (EPANET Configuration)

// 1. Core EPANET configuration
GET /api/metrics // From metrics.json
GET /api/entity-types // From entity-types.json
GET /api/attribute-mappings // New: ATTRIBUTE_TO_API_FIELD
GET /api/constants // New: Entity type constants

// 2. Visualization configuration (but EPANET-derived)
GET /api/visualization-config // From visualization-config.json

Frontend Configuration Files (ESRI Configuration)

// 1. ESRI-specific styling
src/config/esri/colors.js // ESRI_ENTITY_COLORS
src/config/esri/basemaps.js // DEFAULT_ESRI_BASEMAP

// 2. ESRI FeatureLayer definitions
src/config/esri/featureLayerAttributes.js // ENTITY_ATTRIBUTES

// 3. Frontend-specific visualization
src/config/visualization/heatmapConfig.js // HEATMAP_COLOR_STOPS, HEATMAP_RENDERER_CONFIG

Implementation Strategy

Phase 1: Backend Migration (EPANET Configuration)

  1. Use existing seed data:

    • metrics.json/api/metrics
    • entity-types.json/api/entity-types
    • visualization-config.json/api/visualization-config
  2. Create new seed data:

    // attribute-mappings.json
    {
    "attributeMappings": {
    "LeakageFlow": "leakageFlow",
    "TankVolume": "tankVolume"
    }
    }

    // constants.json
    {
    "entityTypes": {
    "TANK": "Tank",
    "JUNCTION": "Junction",
    // etc.
    }
    }

Phase 2: Frontend Reorganization (ESRI Configuration)

  1. Create frontend config structure:

    src/config/
    ├── esri/
    │ ├── colors.js
    │ ├── basemaps.js
    │ └── featureLayerAttributes.js
    └── visualization/
    └── heatmapConfig.js
  2. Move ESRI-specific constants:

    // src/config/esri/colors.js
    export const ESRI_ENTITY_COLORS = {
    tanks: 'red',
    junctions: 'blue',
    // etc.
    };

    // src/config/esri/featureLayerAttributes.js
    export const ENTITY_ATTRIBUTES = {
    SCADA: [...],
    Junction: [...],
    // etc.
    };

Phase 3: Context Integration

  1. Update UnitsContext to fetch from API:

    // Fetch EPANET configuration from backend
    const { data: metrics } = await fetch('/api/metrics');
    const { data: entityTypes } = await fetch('/api/entity-types');
  2. Create ESRI-specific contexts if needed:

    // src/contexts/EsriConfigContext.jsx
    export const useEsriConfig = () => {
    // Load ESRI-specific configuration
    return { colors, featureLayerAttributes, heatmapConfig };
    };

Benefits of This Approach

Clean Separation

  • EPANET configuration is backend-driven and network-agnostic
  • ESRI configuration is frontend-specific and can be customized per deployment

Maintainability

  • Backend developers focus on simulation logic
  • Frontend developers focus on visualization
  • No ESRI dependencies in backend code

Flexibility

  • Different frontends can have different ESRI configurations
  • Same backend can serve multiple visualization clients
  • Easy to add new visualization types without backend changes

Performance

  • Frontend configs can be bundled and cached
  • Backend configs are loaded once and cached in context
  • No unnecessary API calls for visualization-specific data

Migration Checklist

Backend Tasks

  • Implement /api/metrics endpoint
  • Implement /api/entity-types endpoint
  • Implement /api/visualization-config endpoint
  • Create attribute-mappings.json seed data
  • Create constants.json seed data
  • Implement /api/attribute-mappings endpoint
  • Implement /api/constants endpoint

Frontend Tasks

  • Create src/config/esri/ directory structure
  • Move ESRI_ENTITY_COLORS to src/config/esri/colors.js
  • Move ENTITY_ATTRIBUTES to src/config/esri/featureLayerAttributes.js
  • Move HEATMAP_COLOR_STOPS to src/config/visualization/heatmapConfig.js
  • Move HEATMAP_RENDERER_CONFIG to src/config/visualization/heatmapConfig.js
  • Update imports throughout codebase
  • Update UnitsContext to fetch from new API endpoints
  • Remove migrated constants from src/constants.jsx

Conclusion

This approach maintains a clean separation between EPANET simulation configuration (backend) and ESRI visualization configuration (frontend), while properly handling the crossover areas that need to be shared. The backend focuses on what the simulation needs to know, while the frontend focuses on how to display it.