ELF - Elfish Log Factory
“Commercial traffic shouldn’t be this hard”
Overview
ELF (Elfish Log Factory) is a modern, web-based commercial traffic scheduling system designed specifically for broadcast radio stations. It provides comprehensive tools for managing advertisers, campaigns, commercials, and daily schedules with seamless integration to Rivendell Radio Automation.
The project was created to provide small and medium-sized radio stations with a free, professional-grade traffic scheduling solution that can be self-hosted or offered as a cloud-based SaaS service. ELF handles the complete workflow from campaign creation through auto-scheduling to exporting logs in Rivendell-compatible formats.
Key Capabilities:
Multi-station management with separate configurations
Advertiser and campaign management
Intelligent auto-scheduling with rotation and separation rules
Rivendell cart inventory synchronization
Export logs in column-aligned
ASCII format for Rivendell import
Daypart-based scheduling (Morning Drive, Midday, etc.)
Competitive separation rules to prevent conflicts
RESTful
API for all operations
Status
| Item | Value |
| Current Phase | Active Development (MVP Phase 1) |
| Platform | Cross-platform (Linux primary, Ubuntu 24.04 recommended) |
| Backend Language | Python 3.11+ (Django 5.0) |
| Frontend Language | JavaScript (React 18) |
| Database | PostgreSQL 16 |
| License | MIT (intended for open-source release) |
| Version | 1.0.0-alpha |
| Primary Integration | Rivendell Radio Automation |
Goals
Primary Goals
Free Traffic System: Provide small/medium radio stations with professional traffic scheduling at no cost
Rivendell Integration: Seamless bi-directional integration with Rivendell automation systems
Ease of Use: Modern, intuitive web interface requiring minimal training
Multi-Station Support: Single installation can manage multiple radio stations
Secondary Goals
Auto-Scheduling Intelligence: Smart algorithms for optimal commercial placement
Separation Rules: Automatic enforcement of competitive separation policies
Hybrid Deployment: Support both self-hosted and cloud-based SaaS models
Extensibility: Plugin architecture for additional music schedulers and automation systems
Long-Term Goals
Network Scheduling: Chain-wide campaign management across multiple markets
Advanced Analytics: Performance reporting and business intelligence
Music Scheduler Integration: Support for MusicMaster, Selector, and other systems
Mobile Applications: Native iOS/Android apps for on-the-go management
AI-Powered Optimization: Machine learning for schedule optimization and recommendations
Architecture
System Design
ELF follows a modern, decoupled three-tier architecture:
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ React │─────▶│ Django │─────▶│ PostgreSQL │
│ Frontend │ HTTP │ REST API │ SQL │ Database │
│ (Port 5173)│◀─────│ (Port 9000) │◀─────│ │
└─────────────┘ JSON └──────────────┘ └─────────────┘
│
│ MySQL
▼
┌──────────────┐
│ Rivendell │
│ Database │
└──────────────┘
│
▼
┌──────────────┐
│ Export Logs │
│ (ASCII) │
└──────────────┘
Technology Stack
Backend:
Framework: Django 5.0 with Django REST Framework
Database: PostgreSQL 16 (primary), MySQL client (Rivendell sync)
Authentication: JWT tokens with session fallback
Server: Gunicorn (production), Django dev server (development)
API Documentation: DRF Spectacular (OpenAPI/Swagger)
Frontend:
Framework: React 18 with Vite build tool
UI Library: Tailwind
CSS for styling
Routing: React Router DOM
State Management: TanStack Query (React Query)
HTTP Client: Axios
Infrastructure:
Web Server: Nginx (reverse proxy)
Containerization: Docker & Docker Compose
OS: Ubuntu 24.04 LTS (primary target)
Deployment: Rumble Cloud (planned for SaaS)
Database Schema
Core Models:
Station: Radio station configuration, Rivendell connection settings
Advertiser: Client/agency information, industry categorization
Campaign: Flight dates, spot count, contract tracking
Commercial: Individual spots with cart numbers and lengths
DayPart: Time segments (Morning Drive, Midday, etc.)
DailySchedule: Container for each day's schedule
ScheduledSpot: Individual spot placements with times
RivendellCart: Synced cart inventory from Rivendell
SchedulingRule: Auto-scheduling rules (daypart, separation)
SeparationRule: Competitive separation policies
API Structure
RESTful Endpoints:
Stations: /api/stations/
Advertisers: /api/advertisers/
Campaigns: /api/campaigns/
Commercials: /api/commercials/
DayParts: /api/dayparts/
Daily Schedules: /api/daily-schedules/
Scheduled Spots: /api/scheduled-spots/
Rivendell Carts: /api/rivendell-carts/
Separation Rules: /api/separation-rules/
Custom Actions:
POST /api/sync-rivendell/ - Sync cart inventory
POST /api/export-log/ - Export daily log
POST /api/auto-schedule/ - Auto-schedule campaign
Rivendell Integration
Cart Synchronization:
Connects to Rivendell MySQL database
Reads CART table for commercial inventory
Syncs cart numbers, titles, lengths, groups
Can filter by group (e.g., “COMM” for commercials)
Export Format (Column-Aligned ASCII):
HH:MM:SS CCCCCC TITLE_60_CHARS_WIDE MM:SS
08:15:00 001234 Joe's Pizza - February Special 00:30
08:47:00 001235 Smith Auto - Winter Clearance Sale 01:00
09:23:00 001236 Main Street Restaurant - Lunch Special 00:30
Import Process:
ELF exports to configured path (e.g., /var/elf/exports/20240208.txt)
Rivendell's RDLogManager imports via configured template
Merges with music schedule from RDLibrary
Development
Prerequisites
System Requirements:
Optional:
Quick Start
Clone and Setup:
# Clone repository
git clone <repository-url>
cd elf-project
# Run quick start script
chmod +x quickstart.sh
./quickstart.sh
# Start backend (Terminal 1)
cd backend
source venv/bin/activate
python manage.py runserver 0.0.0.0:9000
# Start frontend (Terminal 2)
cd frontend
npm run dev
Access Points:
Development Setup
Backend Setup:
cd backend
# Create virtual environment
python3 -m venv venv
source venv/bin/activate
# Install dependencies
pip install -r requirements.txt
# Configure database
cp .env.example .env
# Edit .env with your settings
# Initialize database
python manage.py migrate
python manage.py createsuperuser
python manage.py collectstatic --noinput
Frontend Setup:
cd frontend
# Install dependencies
npm install
# Configure API endpoint
echo "VITE_API_URL=http://localhost:9000/api" > .env.local
# Start development server
npm run dev
Project Structure
elf-project/
├── backend/ # Django backend
│ ├── config/ # Django configuration
│ │ ├── settings.py # Application settings
│ │ ├── urls.py # URL routing
│ │ └── wsgi.py # WSGI configuration
│ ├── elf/ # Main application
│ │ ├── models.py # Database models
│ │ ├── api/ # REST API layer
│ │ │ ├── serializers.py # Data serialization
│ │ │ └── views.py # API endpoints
│ │ └── services/ # Business logic
│ │ ├── rivendell_service.py # Rivendell sync
│ │ ├── export_service.py # Log export
│ │ └── scheduling_service.py # Auto-scheduler
│ ├── requirements.txt # Python dependencies
│ └── manage.py # Django CLI
├── frontend/ # React frontend
│ ├── src/
│ │ ├── components/ # Reusable components
│ │ ├── pages/ # Page components
│ │ ├── services/ # API client
│ │ └── App.jsx # Main application
│ ├── package.json # Node dependencies
│ └── vite.config.js # Build configuration
├── docker-compose.yml # Docker orchestration
├── README.md # Project overview
├── SETUP_GUIDE.md # Installation guide
├── DEVELOPMENT_GUIDE.md # Developer documentation
└── TODO.md # Development roadmap
Coding Standards
Python (Backend):
Follow PEP 8 style guide
Use type hints for function parameters and returns
Docstrings for all classes and public methods
Maximum line length: 100 characters
Use Django ORM best practices (select_related, prefetch_related)
JavaScript (Frontend):
ES6+ syntax with modern features
Functional components with React Hooks
Descriptive variable names (camelCase)
Component files use PascalCase
Use async/await for asynchronous operations
Database:
Always create migrations for model changes
Use database indexes for frequently queried fields
Foreign keys with appropriate on_delete behavior
Unique constraints where applicable
Testing
Backend Tests:
# Run all tests
python manage.py test
# Run specific test
python manage.py test elf.tests.test_models
# With coverage
coverage run manage.py test
coverage report
Frontend Tests:
# Run tests
npm run test
# Run with coverage
npm run test:coverage
Common Commands
Database Management:
# Create migrations
python manage.py makemigrations
# Apply migrations
python manage.py migrate
# Access database shell
python manage.py dbshell
Rivendell Integration:
# Sync cart inventory
python manage.py sync_rivendell_carts --station 1 --group-name COMM
# Export daily log
python manage.py export_log --date 2024-02-08 --station 1
Roadmap
Phase 1: MVP Foundation (Current)
Status: In Progress
[✓] Core database models (11 models)
[✓] RESTful
API with full CRUD operations
[✓] Rivendell cart synchronization
[✓] Log export service (column-aligned
ASCII)
[✓] Basic auto-scheduling algorithm
[✓] Django admin interface
[✓] React frontend structure
[✓]
API client and routing
[ ] Complete UI implementation
[ ] User authentication system
[ ] Comprehensive
API tests
Phase 2: Core Features (Next 2 Months)
Status: Planned
Scheduling Enhancements:
Advanced rotation algorithms
Hourly spot limits
Fixed-position spots (ROS vs. fixed time)
Makegood tracking and automatic rescheduling
Schedule conflict detection and resolution
User Interface:
Full CRUD interfaces for all entities
Drag-and-drop schedule editor
Calendar-based schedule view
Real-time validation
Dashboard analytics
Integration:
Multiple Rivendell import format support
Two-way sync (import as-played data)
Music scheduler integration prep
Phase 3: Advanced Features (Months 3-6)
Status: Planned
Business Features:
Multi-user roles and permissions
Agency portal access
Rate card management
Automated billing integration
Contract and proposal generation
Reporting:
Scheduling Intelligence:
Multi-station scheduling from single campaign
Network-wide campaign management
Inventory forecasting
AI-powered optimization suggestions
Phase 4: Cloud & SaaS (Months 6-12)
Status: Future
Infrastructure:
Multi-tenancy architecture
Rumble Cloud deployment
Auto-scaling configuration
Comprehensive monitoring (Prometheus/Grafana)
Automated backup and disaster recovery
SaaS Features:
Subscription management system
Payment processing (Stripe integration)
Usage-based billing
Station onboarding wizard
Self-service customer portal
Support ticketing system
Mobile:
Future Enhancements
Additional Integrations:
Advanced Features:
Voice recognition for commercial detection
Real-time collaboration features
Slack/Teams notifications
API webhooks for third-party integration
Machine learning for schedule optimization
Predictive analytics for inventory management
Notes
Design Decisions
Why Django + React?
Django: Mature, “batteries included” framework with excellent ORM and admin interface. Strong security features and extensive ecosystem.
React: Component-based architecture perfect for complex UIs. Large community and extensive library ecosystem.
Decoupled Architecture: Allows independent scaling and development of frontend/backend. Enables future mobile apps using same
API.
Why PostgreSQL?
Advanced query capabilities for complex scheduling logic
Better support for concurrent writes than SQLite
JSON field support for flexible data structures
Excellent performance for reporting queries
Industry standard for web applications
Why Column-Aligned ASCII Export?
Standard format supported by Rivendell and legacy systems
Human-readable for debugging and verification
Easy to parse by various import tools
Compatible with older radio automation systems
Auto-Scheduling Algorithm:
Technical Constraints
Database Connections:
Rivendell MySQL connection is read-only by default for safety
Cart sync runs on-demand, not real-time, to minimize database load
Connection pooling configured for optimal performance
Port Configuration:
Backend uses port 9000 (configurable in settings)
Frontend dev server uses port 5173 (Vite default)
Avoids conflicts with other common services
File System:
Export path must be accessible by both ELF and Rivendell
Recommend shared network mount or direct file system access
Exports use date-based filenames (YYYYMMDD.txt)
Historical Context
Project Origin:
Created to address lack of affordable traffic systems for small stations
Inspired by proprietary systems costing $10,000+ per station
Designed specifically for Rivendell users (open-source automation)
Intended for free self-hosted use or affordable SaaS offering
Development Philosophy:
Open-source community benefit
User-driven feature development
Professional quality for zero cost
Extensible architecture for future growth
Known Issues
Current Limitations:
Auto-scheduler uses basic algorithm (sophisticated version planned)
No actual authentication implemented yet (security risk in current state)
Separation rules partially implemented
Export path validation needed
Time zone handling requires additional testing
No multi-user concurrency protection yet
Workarounds:
Run behind firewall until authentication completed
Use Django admin for user management temporarily
Manual schedule review before export recommended
Test exports thoroughly before going live
Contributing
How to Contribute:
Fork the repository on GitHub
Create feature branch from main
Follow coding standards outlined above
Write tests for new features
Submit pull request with detailed description
Update documentation as needed
Priority Areas:
Frontend UI implementation
Test coverage improvements
Documentation and tutorials
Additional import/export formats
Mobile-responsive design enhancements
Project Resources:
-
Documentation: See SETUP_GUIDE.md and DEVELOPMENT_GUIDE.md
Issue Tracking: GitHub Issues (when repository public)
Email: [contact information]
Related Projects:
References
Documentation:
Standards:
PEP 8 - Python Style Guide
REST
API Design Best Practices
PostgreSQL Best Practices
React Hooks Best Practices
Last Updated: February 19, 2024
Version: 1.0.0-alpha
Maintainer: Rich Lawrence