A full-stack application for optimizing team compositions by minimizing overlap from past collaborations.
When forming new teams, how do you minimize the number of people who have worked together previously? This ensures fresh collaborations and diverse team dynamics.
This application uses exhaustive search to find optimal team assignments that minimize historical overlap. It evaluates all possible team combinations and returns the best solutions.
- Exhaustive Search Algorithm: Guaranteed optimal solution for small-to-medium groups (up to ~20 people)
- Symmetry Breaking Optimization: Eliminates duplicate partitions, providing 6-120x speedup depending on team configuration
- Conflict Matrix: Track how many times each pair has worked together
- Multiple Solutions: Returns all equally-optimal assignments
- Performance Metrics: Shows combinations checked and execution time
- Interactive UI: Two-screen interface with navigation tabs
- Collaboration History (Home): Upload and visualize team history with interactive graph
- Optimize Teams: Select available candidates, configure desired number of teams, run optimization
- Force-Directed Graph Visualization:
- Upload JSON files with team history data
- Drag-and-drop nodes to reposition contributors
- Mouse wheel zoom (0.1x to 5x)
- Click-and-drag background to pan the view
- Edge thickness and labels show collaboration frequency
- Node size proportional to total collaborations
- Toggle labels on/off for cleaner views
- Regenerate layout button for new force simulation
- Persistent state across tab navigation
- TypeScript: Type-safe implementation
- Express: REST API
- CORS: Cross-origin support
- SvelteKit: Reactive UI framework
- TypeScript: Type-safe components
- Vite: Fast development and building
- Node.js 18+
- npm or pnpm
# Install backend dependencies
cd backend
npm install
# Install frontend dependencies
cd ../frontend
npm installTerminal 1 - Backend:
cd backend
npm run devServer runs on http://localhost:3001
Terminal 2 - Frontend:
cd frontend
npm run devUI runs on http://localhost:5173
- Open http://localhost:5173 in your browser
- Click "Upload Team History" to load a JSON file with historical team data
- Example data: See frontend/static/fac31-team-data.json for a template
- This example file contains real data harvested from FAC-31 GitHub repositories on 8 November 2025
- View the interactive graph visualization showing:
- Contributors as nodes (blue circles)
- Collaboration frequency as edge thickness and labels
- Node size proportional to total collaborations
- Interact with the graph:
- Zoom: Scroll mouse wheel to zoom in/out
- Pan: Click and drag background to move around
- Reposition: Click and drag individual nodes
- Toggle Labels: Use checkbox to show/hide names
- Reset View: Return to default zoom and position
- Regenerate Layout: Run force-directed algorithm again with new random positions
Interactive force-directed graph showing collaboration frequency between team members
- Navigate to the "Optimize Teams" tab (requires team history data loaded first)
- Select candidates who are available for the next team composition
- All team members are selected by default
- Use checkboxes to deselect unavailable members
- Use "Select All" / "Deselect All" for bulk operations
- Configure desired number of teams (e.g., 3, 4, 5)
- System automatically calculates team sizes to distribute people as evenly as possible
- Example: 10 people divided into 3 teams → teams of [4, 3, 3]
- Example: 15 people divided into 4 teams → teams of [4, 4, 4, 3]
- Click "Optimize Teams" to find the best team assignments
- View results showing:
- Minimum conflict score
- All optimal team configurations
- Detailed conflict breakdowns per team
- Performance metrics (combinations checked, execution time)
Optimization results showing optimal team assignments with minimal conflict scores
This project includes real team history data from the FAC-31 GitHub organization:
An example team history file is provided for reference:
- frontend/static/fac31-team-data.json - Example data template
- Contains real data harvested from FAC-31 GitHub repositories on 8 November 2025
- 17 contributors with complete collaboration history
- 24 past team compositions
- Pre-calculated conflict matrix
- Use this as a template for formatting your own team history data
The scripts/ directory contains tools to fetch and prepare real team data:
cd scripts
node fetchTeamHistory.jsThis generates:
- fac31-team-data.json - Complete team history with 15 contributors across 24 past team compositions
- candidates.json - Editable list of candidates for next team formation
- Open scripts/candidates.json
- Set
"available": falsefor anyone who has left the program - Update the desired number of teams based on available candidates
- Use this filtered data in the optimizer
Current FAC-31 Data:
- 15 unique contributors (17 including bots)
- 24 past team compositions from GitHub repositories
- Conflict matrix showing collaboration frequencies
- Top collaborations: chrislush & nchua3012 (6 times), arecouz & Jaz-spec (5 times)
People: Array of individuals with IDs and names
[
{ id: '1', name: 'Alice' },
{ id: '2', name: 'Bob' },
...
]Team Sizes: Desired composition
[3, 3, 3, 3] // Four teams of 3 people eachConflict Matrix: Historical collaborations
{
'1': { '2': 2, '3': 1 }, // Alice worked with Bob 2x, Charlie 1x
'2': { '1': 2, '4': 2 }, // Bob worked with Alice 2x, Diana 2x
...
}The optimizer uses exhaustive search with symmetry breaking:
- Generates all possible ways to partition people into specified team sizes
- Optimization: When multiple teams have the same size, eliminates duplicate partitions by enforcing canonical ordering (minimum person ID in each team must be ascending)
- Calculates conflict score for each partition (sum of all pairwise conflicts within teams)
- Returns the partition(s) with minimum conflict score
Symmetry Breaking Impact:
- For 4 teams of size 3: 24x speedup (reduces 369K combinations to ~15K)
- For 3 teams of size 4: 6x speedup
- Makes problems up to 20 people feasible with exhaustive search
For 12 people in 4 teams of 3:
- Naive combinations: ~369,600
- With optimization: ~15,400 (24x reduction)
- Runtime: < 1 second
- Guaranteed: Optimal solution
Optimize team assignments.
Request:
{
"people": [
{ "id": "1", "name": "Alice" },
{ "id": "2", "name": "Bob" }
],
"teamSizes": [3, 3],
"conflictMatrix": {
"1": { "2": 2 }
}
}Response:
{
"bestAssignments": [
{
"teams": [
{ "members": [{ "id": "1", "name": "Alice" }, ...] }
],
"conflictScore": 15
}
],
"totalCombinationsChecked": 369600,
"executionTimeMs": 1234
}Health check endpoint.
Response:
{ "status": "ok" }team-optimiser/
├── backend/
│ ├── src/
│ │ ├── index.ts # Express server & API endpoints
│ │ ├── teamOptimizer.ts # Core optimization algorithm
│ │ └── types.ts # TypeScript interfaces
│ ├── package.json
│ └── tsconfig.json
│
├── frontend/
│ ├── src/
│ │ ├── routes/
│ │ │ ├── +layout.svelte # Navigation layout with tabs
│ │ │ ├── +page.svelte # Collaboration history screen (home)
│ │ │ └── optimize/
│ │ │ └── +page.svelte # Team optimization screen
│ │ ├── lib/
│ │ │ └── stores/
│ │ │ └── historyStore.ts # Persistent state for graph data
│ │ └── app.html
│ ├── package.json
│ ├── svelte.config.js
│ └── vite.config.ts
│
├── scripts/
│ ├── fetchTeamHistory.js # Fetch team data from GitHub
│ ├── generateCandidatesList.js # Create editable candidates list
│ ├── fac31-team-data.json # Complete FAC-31 team history
│ └── candidates.json # Editable candidate availability
│
├── PLANNING.md # Detailed architecture & algorithm docs
└── README.md # This file
cd backend
# Run with hot reload
npm run dev
# Build for production
npm run build
# Run production build
npm startcd frontend
# Run dev server
npm run dev
# Build for production
npm run build
# Preview production build
npm run preview
# Type checking
npm run checkWith symmetry breaking optimization:
| People | Teams | Optimized Combinations | Expected Time |
|---|---|---|---|
| 9 | 3×3 | ~47 | < 1ms |
| 12 | 4×3 | ~15K | < 1s |
| 15 | 5×3 | ~6.25M | 10-60s |
| 16 | 4×4 | ~2.6M | 5-30s |
| 20 | 5×4 | ~83M | 1-10min |
Note: With symmetry breaking, exhaustive search is feasible up to ~20 people. Beyond 20-25 people, heuristic algorithms (simulated annealing, genetic algorithms) may be beneficial for faster results.
See PLANNING.md for detailed roadmap, including:
- Branch & bound pruning for faster search
- Parallel processing across CPU cores
- Heuristic methods for large groups (20+ people)
- Weighted conflicts (recent collaborations weighted higher)
- Skill balancing and diversity metrics
- Hard constraints and preferred pairings
- ✅
Historical tracking and visualization(Implemented) - Save/load custom graph layouts
- Export graph as image
- Filter graph by collaboration threshold
- Highlight specific collaboration paths
- Workshop/Training: Form diverse learning groups
- Team Rotations: Spread knowledge across organization
- Project Assignments: Balance experience and fresh perspectives
- Event Planning: Optimize networking opportunities
- Research Collaborations: Encourage cross-pollination of ideas
MIT
Contributions welcome! Please read PLANNING.md for architecture details before submitting PRs.
See PLANNING.md for detailed algorithm explanation and design decisions.