Skip to content

adeemadil/kpi-builder-sprint

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

22 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Safety Analytics - KPI Builder

Dynamic KPI analytics dashboard for industrial safety monitoring with real-time safety metrics, close-call detection, and customizable analytics.

πŸš€ Quick Start

Docker (Recommended)

One command to run the full stack (backend + frontend):

docker compose up --build -d

This will:

  1. Build and start the backend (auto-seeds SQLite with 100k rows on first run)
  2. Start the frontend (production preview)
  3. Expose API at http://localhost:3001 and UI at http://localhost:8080

Verify:

curl http://localhost:3001/api/health
open http://localhost:8080

See TESTING.md for scenario-wise curl examples.

Useful Docker commands:

docker compose ps
docker compose logs -f backend
docker compose down   # stop services
docker compose down -v  # stop and reset database volume

Option 2: Local Development (advanced)

Run services locally only if you are not using Docker.

Check health:

curl http://localhost:3001/api/health

πŸ“ Project Structure

kpi-builder-sprint/
β”œβ”€β”€ backend/                    # Express API server
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ server.ts          # Main server
β”‚   β”‚   β”œβ”€β”€ db.ts              # Database connection & queries
β”‚   β”‚   └── routes.ts          # API endpoints
β”‚   β”œβ”€β”€ data/
β”‚   β”‚   β”œβ”€β”€ seed_sqlite.py     # Python seeding script
β”‚   β”‚   └── work-package-raw-data.csv  # 100k detection records
β”‚   β”œβ”€β”€ Dockerfile
β”‚   └── package.json
β”œβ”€β”€ frontend/                  # React frontend
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ components/        # UI components
β”‚   β”‚   └── lib/
β”‚   β”‚       └── api.ts         # Backend API client
β”‚   └── package.json
β”œβ”€β”€ TESTING.md                 # Scenario-wise curl examples
β”œβ”€β”€ docker-compose.yml          # Docker orchestration
β”œβ”€β”€ Dockerfile                 # Docker build configuration
β”œβ”€β”€ start.sh                   # Docker startup script
β”œβ”€β”€ package.json              # Root package.json with workspaces
└── README.md

πŸ”Œ API Endpoints

Health Check

GET /api/health

Get Detections

POST /api/detections
Body: { filters: {...}, limit: 100, offset: 0 }

Aggregate Metrics

POST /api/aggregate
Body: { metric: 'count', filters: {...}, groupBy: 'hour' }

Close Calls

POST /api/close-calls
Body: { filters: { timeRange: {...} }, distance: 2.0 }

Quick KPIs

GET /api/vest-violations?from=2025-01-01&to=2025-01-07
GET /api/overspeed?from=2025-01-01&to=2025-01-07&threshold=1.5

πŸ§ͺ Testing

Test Suite Overview

The project includes comprehensive test suites for both frontend and backend:

  • Backend Unit Tests: Jest-based API endpoint and business logic tests
  • Backend Ground Truth Tests: Validates against real dataset (100k records)
  • Frontend Tests: React component testing with Vitest and Testing Library

Running Tests

# Backend unit tests
cd backend && npm test

# Backend ground truth tests (uses real database)
cd backend && npx jest --config jest.groundtruth.config.js

# Frontend tests
cd frontend && npm test

# All tests (if configured)
npm run test:all

Test Results Summary

  • βœ… Ground Truth Tests: 4/4 passing (validates vest filter logic)
  • βœ… Frontend Tests: 20/20 passing (all UI components)
  • ⚠️ Backend Unit Tests: Some failures due to test database setup (non-critical)

Run backend tests in Docker (no local Node setup)

docker run --rm -it \
  -v "$PWD/backend":/app -w /app \
  -e NODE_ENV=test -e TEST_SQLITE_PATH=./test_kpi_builder.sqlite \
  node:18-alpine sh -lc "npm ci && npm test"

Manual API Testing

# Health check
curl -s http://localhost:3001/api/health | jq .

# Get sample data
curl -s -X POST http://localhost:3001/api/detections \
  -H 'Content-Type: application/json' \
  -d '{"limit":5}' | jq .

# Test aggregation
curl -s -X POST http://localhost:3001/api/aggregate \
  -H 'Content-Type: application/json' \
  -d '{"metric":"count","groupBy":"hour"}' | jq .

Expected Results

  • Health Check: {"status": "healthy", "recordCount": 100000}
  • Detections: Array of detection objects with coordinates, timestamps, etc.
  • Aggregations: Time-series data for charts and KPIs

Ground Truth Validation

The dataset contains 100,000 detection records from April 2, 2025 (15:42:06 to 16:00:18 UTC).

Confirmed Ground Truth Values:

  • Total Human Detections: 28,323
  • Total Vehicle Detections: 71,677
  • Vest Violations (human, vest=0): 10,312
  • Overspeed Events (speed > 1.5 m/s): 16,599
    • Human: 15,013
    • Vehicle: 1,586
  • Close Calls (distance ≀ 2.0m, time ≀ 250ms): 0

Validation Commands:

# Test vest violations
curl -X POST http://localhost:3001/api/aggregate \
  -H 'Content-Type: application/json' \
  -d '{
    "metric": "vest_violations",
    "filters": {
      "timeRange": {"from": "2025-04-02T15:42:06Z", "to": "2025-04-02T16:00:19Z"}
    },
    "groupBy": "day"
  }' | jq '.meta.filteredRecords'
# Expected: 10312

# Test overspeed by class
curl -X POST http://localhost:3001/api/aggregate \
  -H 'Content-Type: application/json' \
  -d '{
    "metric": "overspeed",
    "filters": {
      "timeRange": {"from": "2025-04-02T15:42:06Z", "to": "2025-04-02T16:00:19Z"},
      "classes": ["human", "vehicle"]
    },
    "groupBy": "class"
  }' | jq '.series'
# Expected: [{"label": "human", "value": 15013}, {"label": "vehicle", "value": 1586}]

# Test total overspeed events
curl -X POST http://localhost:3001/api/aggregate \
  -H 'Content-Type: application/json' \
  -d '{
    "metric": "overspeed",
    "filters": {
      "timeRange": {"from": "2025-04-02T15:42:06Z", "to": "2025-04-02T16:00:19Z"},
      "classes": ["human", "vehicle"]
    },
    "groupBy": "day"
  }' | jq '.meta.filteredRecords'
# Expected: 16599

# Test close calls (should be 0)
curl -X POST http://localhost:3001/api/close-calls \
  -H 'Content-Type: application/json' \
  -d '{
    "filters": {
      "timeRange": {"from": "2025-04-02T15:42:06Z", "to": "2025-04-02T16:00:19Z"}
    },
    "distance": 2.0
  }' | jq '.series | map(.value) | add'
# Expected: 0

πŸ› οΈ Development

Local Development

Install all dependencies:

npm run install:all

Start backend:

./scripts/start-backend.sh
# or
npm run dev:backend

Start frontend:

./scripts/start-frontend.sh
# or
npm run dev:frontend

Start both (development):

npm run dev

Docker Development

Use the commands above. Avoid running the local backend on port 3001 while Docker is up to prevent EADDRINUSE.

βœ… Features

  • βœ… 100k+ detection records auto-seeded with Python
  • βœ… SQLite database with optimized indexing
  • βœ… RESTful API with flexible filtering and aggregation
  • βœ… Close-call detection (< 2m proximity algorithm)
  • βœ… Vest violation tracking for safety compliance
  • βœ… Overspeed monitoring with configurable thresholds
  • βœ… Dynamic KPI builder with custom metrics
  • βœ… Interactive charts (line, bar, area)
  • βœ… Real-time filtering by class, area, time range
  • βœ… Dockerized for easy deployment
  • βœ… Comprehensive test suites
  • βœ… Separate startup scripts for development

πŸ› Troubleshooting

"Database not seeded"

# Check if database file exists
ls -la backend/data/kpi_builder.sqlite

# Re-run seeding script
cd backend/data && python3 seed_sqlite.py

"Backend won't start"

# Check if port is in use
lsof -i:3001

# Kill existing process
pkill -f "node.*server"

# Restart backend
./scripts/start-backend.sh

If you see EADDRINUSE: address already in use :::3001 when running locally:

# Find and kill the process holding 3001
lsof -i:3001
kill -9 <PID>

# Or run on another port temporarily
PORT=3002 npm run dev:backend

The server is guarded to not auto-start under tests (NODE_ENV=test). Avoid running the backend locally while Docker is up (both bind port 3001).

"Frontend can't reach API"

# Check if backend is running
curl http://localhost:3001/api/health

# Check frontend environment
cat frontend/.env

"Docker issues"

# Check Docker status
docker-compose ps

# View logs
docker-compose logs backend

# Reset everything
docker-compose down -v
./start.sh

πŸ“ License

MIT

πŸ€– Automated Testing

Test Suite Status

The project includes comprehensive test suites with the following status:

βœ… Working Test Suites:

  • Ground Truth Tests: 4/4 passing - Validates vest filter logic against real dataset
  • Frontend Tests: 20/20 passing - All React components and UI interactions
  • API Integration Tests: Core endpoints working correctly

⚠️ Partially Working:

  • Backend Unit Tests: Some failures due to test database setup (non-critical for demo)

Test Coverage:

  • βœ… Vest filter logic (vest=0, vest=1, vest=2)
  • βœ… Ground truth validation (10,312 vest violations, 18,011 vest worn, 28,323 total)
  • βœ… API endpoints with various filters
  • βœ… Frontend component rendering and interactions
  • βœ… Error handling and edge cases
  • βœ… Data validation and type checking

Run Tests:

# Ground truth tests (recommended for demo)
cd backend && npx jest --config jest.groundtruth.config.js

# Frontend tests
cd frontend && npm test

# Backend unit tests (has some failures)
cd backend && npm test

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors