๐๏ธ Fly-in Architecture¶
Understanding how the project components interact and why the system is separated into multiple responsibilities.
๐ Table of Contents¶
- Why an Architecture?
- High-Level Overview
- MapParser
- Simulator
- PathFinder
- Visualizer
- ImageGenerator
- Data Flow
- Why Separate Classes?
- Single Responsibility Principle
- Benefits of the Architecture
- Mental Model
1๏ธโฃ Why an Architecture?¶
As projects grow, putting everything into a single file quickly becomes difficult to maintain.
Instead of creating one massive class responsible for:
- parsing
- pathfinding
- simulation
- visualization
- rendering
Fly-in separates each responsibility into dedicated systems.
This makes the project:
โ easier to understand
โ easier to debug
โ easier to extend
โ easier to test
2๏ธโฃ High-Level Overview¶
Map File (.txt)
โ
โผ
โโโโโโโโโโโโโโโโโโโ
โ MapParser โ
โโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโ
โ Simulator โ
โโโโโโโโโโโโโโโโโโโ
โ
โ
โผ
โโโโโโโโโโโโโโโโโโโ
โ PathFinder โ
โโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโบ Visualizer
โ โ
โ โผ
โ Terminal Output
โผ
โโโโโโโโโโโโโโโโโโโ
โ ImageGenerator โ
โโโโโโโโโโโโโโโโโโโ
โ
โผ
Frames + GIF
3๏ธโฃ MapParser¶
Responsibility¶
The parser transforms the map file into Python objects that can be used by the simulation.
Input:
connection: A-B
Output:
Connection("A", "B")
What it validates¶
The parser verifies:
- syntax correctness
- duplicated zones
- duplicated connections
- invalid metadata
- invalid coordinates
- invalid capacities
- missing start/end zones
What it creates¶
zones
connections
start_zone
end_zone
nb_drones
Everything else in the project depends on this data.
4๏ธโฃ Simulator¶
Responsibility¶
The Simulator is the heart of the project.
It decides:
Who moves
When they move
Whether movement is valid
Tracks¶
occupied_zones
occupied_links
current_turn
turn_states
Handles¶
- drone movement
- zone capacities
- link capacities
- waiting turns
- restricted zones
- delivery tracking
- turn progression
Think of it as¶
Air Traffic Control
The Simulator controls movement but does not calculate routes.
5๏ธโฃ PathFinder¶
Responsibility¶
The PathFinder answers one question:
What is the best route?
Uses¶
Dijkstra Algorithm
heapq Priority Queue
Considers¶
- movement costs
- restricted zones
- blocked zones
- priority zones
- occupied areas
Returns¶
[
"start",
"hub",
"corridor",
"goal"
]
The Simulator then decides whether that route can be used.
6๏ธโฃ Visualizer¶
Responsibility¶
The Visualizer displays the simulation in the terminal.
It converts raw simulation data into a format that humans can easily understand.
Input¶
The Visualizer receives:
simul_result
Example:
{
1: ["D1-hub", "D2-hub"],
2: ["D1-corridor", "D3-hub"]
}
Output¶
Turn 1
๐ธ D1 โค hub
๐ธ D2 โค hub
Turn 2
๐ธ D1 โค corridor
๐ธ D3 โค hub
Responsibilities¶
The Visualizer:
- displays turn-by-turn movements
- formats terminal output
- generates reports
- improves readability
- assists debugging
Final Report¶
Example:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
FLY-IN DRONE SIMULATION
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Total drones: 25
Delivered drones: 25
Total turns: 41
Maximum turns allowed: 45
Simulation Status: SUCCESS
Why a Separate Class?¶
Displaying information is not part of simulation logic.
Separating responsibilities makes future output systems easier to create:
Terminal Output
JSON Output
Web Output
GUI Output
7๏ธโฃ ImageGenerator¶
Responsibility¶
The ImageGenerator creates a visual representation of the simulation.
Generates¶
๐ธ Individual Frames
frame_000.png
frame_001.png
frame_002.png
...
๐ฌ Final GIF
simulation.gif
Uses¶
Pillow
to render:
- zones
- connections
- drone distribution
- turn information
- simulation statistics
Purpose¶
The ImageGenerator is not required for the simulation itself.
It was developed to:
- improve user experience
- provide visual debugging
- better understand drone movement
- practice Pillow outside the project's requirements
8๏ธโฃ Data Flow¶
Complete execution flow:
Map File
โ
MapParser
โ
Zones + Connections
โ
Simulator
โโโโ Visualizer
โ โ
โ Terminal Output
โ
โโโโ PathFinder
โ
Movement Decisions
โ
Turn States
โ
ImageGenerator
โ
Frames + GIF
9๏ธโฃ Why Separate Classes?¶
A common question during evaluations is:
Why not put everything inside Simulator?¶
Because it would create a massive class responsible for:
- parsing
- pathfinding
- simulation
- terminal output
- image generation
This violates the:
Single Responsibility Principle
and makes maintenance harder.
Example¶
If a bug exists in:
Map Parsing
the fix belongs in:
MapParser
not inside the Simulator.
๐ Single Responsibility Principle¶
One class.
One responsibility.
MapParser¶
Reads and validates input
Simulator¶
Controls simulation rules
PathFinder¶
Calculates optimal routes
Visualizer¶
Displays terminal output
ImageGenerator¶
Creates visual output
This separation keeps the codebase clean and maintainable.
1๏ธโฃ1๏ธโฃ Benefits of the Architecture¶
Because responsibilities are isolated:
โ easier debugging
โ easier testing
โ easier maintenance
โ easier feature development
โ lower coupling between systems
Example¶
Want to replace Dijkstra with A*?
Only:
PathFinder.py
requires significant changes.
The rest of the project remains untouched.
1๏ธโฃ2๏ธโฃ Mental Model¶
Think of the project as an airport.
๐งพ MapParser¶
Airport Construction Team
Builds the airport layout.
๐งญ PathFinder¶
GPS Navigation System
Calculates routes.
๐ฎ Simulator¶
Air Traffic Control
Controls movement rules.
๐บ Visualizer¶
Control Tower Screens
Displays what is happening in real time.
๐ฌ ImageGenerator¶
Security Cameras
Records and visualizes the entire simulation.
Each component has a clear purpose and communicates only the information required for the next stage of the simulation.