Skip to content

Latest commit

 

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

R3P: Random Pixel Ping-Pong

A distributed image generation system that creates images with unique colored pixels through a stateless ping-pong architecture.

Overview

Two separate instances ("Ping" and "Pong") collaborate to build an image by exchanging pixels, ensuring each pixel has a unique color.

Architecture

The system consists of four main components:

  1. Main Instance - Coordinates the image generation process
  2. Ping Instance - Adds pixels and forwards to Pong
  3. Pong Instance - Adds pixels and returns to Ping
  4. Frontend (React) - User interface for configuration and visualization

All instances communicate via REST API and are completely stateless.

┌─────────────┐
│   Frontend  │
│   (React)   │
└──────┬──────┘
       │
       ▼
┌─────────────┐
│    Main     │◄──┐
│  Instance   │   │
└──────┬──────┘   │
       │          │
       ▼          │
┌─────────────┐   │
│    Ping     │   │
│  Instance   ├───┤
└──────┬──────┘   │
       │          │
       ▼          │
┌─────────────┐   │
│    Pong     │   │
│  Instance   ├───┘
└─────────────┘

Features

  • Django REST API backend with three separate instances
  • React frontend with real-time visualization
  • Stateless architecture - no data persistence between API calls
  • Unique color validation for each pixel (frontend and backend)
  • Real-time progress tracking via WebSocket push notifications
  • Performance-optimized pixel placement (empty position tracking)
  • Benchmarking system
  • Docker containerization

Quick Start

Prerequisites

  • Docker and Docker Compose

Using Docker

  1. Start all services:

    docker compose up --build
  2. Wait ~30 seconds for services to start, then access:

  3. Stop services:

    docker compose down

Local Development

Backend Setup

cd backend
python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate
pip install -r requirements.txt
python manage.py migrate

# Start Main instance
INSTANCE_TYPE=main PING_SERVICE_URL=http://localhost:8001 PONG_SERVICE_URL=http://localhost:8002 python manage.py runserver 8000

# In separate terminals, start Ping and Pong:
INSTANCE_TYPE=ping PONG_SERVICE_URL=http://localhost:8002 python manage.py runserver 8001
INSTANCE_TYPE=pong python manage.py runserver 8002

Frontend Setup

cd frontend
npm install
REACT_APP_API_URL=http://localhost:8000/api npm start

Algorithm

Image Generation Process

  1. Initialize an M×N image (all pixels black/unfilled)
  2. Ping adds the first random colored pixel
  3. Ping-Pong loop:
    • Ping adds a unique colored pixel to a random empty position
    • Sends image to Pong
    • Pong adds a unique colored pixel to a random empty position
    • Sends image back to Ping
    • Repeat until all M×N pixels are filled
  4. Main instance tracks progress throughout

Unique Color Generation

  • Maintains a set of all used RGB colors
  • Generates random RGB values (0-255 for each channel)
  • Checks for collisions (O(1) lookup)
  • Falls back to systematic search if random generation fails after 10,000 attempts
  • Provides validation endpoint to verify uniqueness

Stateless Design

  • Image state is passed as JSON in each request/response
  • No database or cache required
  • Instances can be scaled horizontally

API Documentation

Main Instance Endpoints

Start Generation

POST /api/start/
Content-Type: application/json

{
  "M": 56,
  "N": 56
}

Response:
{
  "status": "started",
  "M": 56,
  "N": 56,
  "total_pixels": 3136
}

Get Status

GET /api/status/

Response:
{
  "active": true,
  "progress": 45.2,
  "complete": false,
  "error": null,
  "M": 56,
  "N": 56,
  "benchmark": {
    "total_time": 2.34,
    "checkpoints": [...]
  }
}

Get Image

GET /api/image/

Response:
{
  "image_state": {
    "M": 56,
    "N": 56,
    "image_array": [[[r,g,b], ...], ...],
    "pixel_count": 1418,
    "total_pixels": 3136,
    "filled_positions": [[x,y], ...],
    "used_colors": [[r,g,b], ...]
  },
  "progress": 45.2,
  "complete": false
}

Validate Colors

POST /api/validate/
Content-Type: application/json

{
  "image_state": {...}
}

Response:
{
  "valid": true,
  "pixel_count": 3136
}

Run Benchmark

POST /api/benchmark/
Content-Type: application/json

{
  "sizes": [[5, 5], [10, 10], [28, 28], [56, 56]]
}

Response:
{
  "results": [
    {
      "M": 5,
      "N": 5,
      "total_pixels": 25,
      "total_time": 0.012,
      "pixels_per_second": 2083.33,
      "success": true
    },
    ...
  ],
  "total_tests": 4
}

Ping/Pong Instance Endpoints

Process Image

POST /api/ping/process/  (or /api/pong/process/)
Content-Type: application/json

{
  "image_state": {...}
}

Response:
{
  "image_state": {...},
  "complete": false
}

Benchmarking

Performance Metrics

Benchmark results for various image sizes:

Image Size Total Pixels Estimated Time* Pixels/Second*
5×5 25 ~15 ms ~1,666
10×10 100 ~50 ms ~2,000
28×28 784 ~400 ms ~1,960
56×56 3,136 ~1.6 s ~1,960
128×128 16,384 ~8.5 s ~1,927
256×256 65,536 ~34 s ~1,927
512×512 262,144 ~2.3 min ~1,900
1024×1024 1,048,576 ~9.2 min ~1,900

*Performance depends on hardware and network conditions. These are estimates based on local Docker deployment.

Running Benchmarks

Via API

curl -X POST http://localhost:8000/api/benchmark/ \
  -H "Content-Type: application/json" \
  -d '{"sizes": [[5,5], [10,10], [28,28], [56,56], [128,128], [256,256]]}'

Via Frontend

The frontend automatically displays:

  • Total generation time
  • Pixels per second
  • Progress percentage
  • Real-time visualization

Performance Optimization

The system uses:

  • Random color generation with collision detection
  • Empty position tracking in a set (O(1) random selection instead of O(M×N) iteration)
  • NumPy arrays for fast image manipulation
  • WebSocket push notifications (no polling overhead)
  • Gunicorn/Daphne workers for parallel requests
  • Docker networking for inter-container communication

Frontend Usage

Configuration

  • Set image dimensions (M and N, 1-4096)
  • Click Start to begin generation
  • Monitor progress via progress bar, canvas visualization, and statistics

Visualization

  • Real-time canvas rendering with actual RGB colors
  • Pixelated rendering style
  • Updates via WebSocket push notifications (real-time, no polling delay)

Color Validation

The frontend includes a color uniqueness validation function:

  • Click "Validate Colors" button after generation
  • Validates all pixels have unique colors
  • Shows validation result with duplicate detection
  • Works independently of backend validation endpoint

Architecture Details

Technology Stack

Backend:

  • Django 4.2.7
  • Django REST Framework 3.14.0
  • Django Channels 4.0.0 (WebSocket support)
  • Daphne 4.0.0 (ASGI server for WebSocket)
  • NumPy 1.24.3 (image array manipulation)
  • Gunicorn 21.2.0 (WSGI server for ping/pong instances)
  • Python 3.11

Frontend:

  • React 18.2.0
  • Axios 1.6.0 (HTTP client)
  • WebSocket API (real-time push notifications)
  • HTML5 Canvas API

Infrastructure:

  • Docker & Docker Compose
  • Nginx (frontend reverse proxy)

Design Decisions

  • Stateless Architecture: No database required, easy horizontal scaling
  • REST API Communication: Standard HTTP/JSON for inter-service communication
  • Real-time Updates: WebSocket push notifications (no polling overhead)
  • Image Representation: NumPy arrays for manipulation, JSON for API transfer
  • Color Uniqueness: Set-based tracking with random generation and fallback

Testing

Manual Testing

  1. Small Image (5×5):

    curl -X POST http://localhost:8000/api/start/ \
      -H "Content-Type: application/json" \
      -d '{"M": 5, "N": 5}'
    
    curl http://localhost:8000/api/status/
  2. Color Validation:

    # Generate image, then:
    curl -X POST http://localhost:8000/api/validate/ \
      -H "Content-Type: application/json" \
      -d @image_state.json
  3. Benchmark Test:

    curl -X POST http://localhost:8000/api/benchmark/ \
      -H "Content-Type: application/json" \
      -d '{"sizes": [[5,5], [10,10], [28,28]]}'

Expected Results

  • All pixels should have unique colors
  • Progress should go from 0% to 100%
  • No duplicate colors in final image
  • Benchmark should complete without errors

Troubleshooting

  • Connection errors: Check containers are running with docker compose ps and view logs with docker compose logs [service_name]
  • Slow generation: Expected for large images (>512×512) due to ping-pong architecture
  • Frontend not connecting: Wait 30 seconds for services to start, check browser console for errors
  • Memory errors: Large images (>1024×1024) may need 4GB+ Docker memory limit

Future Improvements

  • WebSocket support for real-time updates
  • Redis cache for multi-server deployments
  • Image export (PNG/JPEG download)
  • Rate limiting and authentication

Project Structure

squaremind-takehome/
├── backend/
│   ├── config/
│   │   ├── __init__.py
│   │   ├── settings.py
│   │   ├── urls.py
│   │   └── wsgi.py
│   ├── r3p/
│   │   ├── __init__.py
│   │   ├── apps.py
│   │   ├── image_generator.py  # Core algorithm
│   │   ├── views.py            # REST API endpoints
│   │   └── urls.py
│   ├── Dockerfile
│   ├── .dockerignore
│   ├── manage.py
│   └── requirements.txt
├── frontend/
│   ├── public/
│   │   └── index.html
│   ├── src/
│   │   ├── App.js              # Main React component
│   │   ├── App.css             # Styles
│   │   ├── index.js
│   │   └── index.css
│   ├── Dockerfile
│   ├── .dockerignore
│   ├── nginx.conf
│   └── package.json
├── docker-compose.yml
└── README.md

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages