comprehensive_demo/
comprehensive_demo.rs

1use spatio::{Point, SetOptions, Spatio};
2use std::time::Duration;
3
4fn main() -> Result<(), Box<dyn std::error::Error>> {
5    println!("Spatio - Comprehensive Demo");
6    println!("===========================");
7
8    // Create an in-memory database
9    let db = Spatio::memory()?;
10    println!("Created in-memory database");
11
12    // === BASIC KEY-VALUE OPERATIONS ===
13    println!("\nBasic Key-Value Operations");
14
15    // Simple string storage
16    db.insert("app:name", b"Spatio Demo App", None)?;
17    db.insert("app:version", b"1.0.0", None)?;
18    db.insert("app:author", b"Spatio Team", None)?;
19
20    // Retrieve and display
21    let app_name = db.get("app:name")?.unwrap();
22    println!("  App: {}", String::from_utf8_lossy(&app_name));
23
24    // === TTL (TIME-TO-LIVE) OPERATIONS ===
25    println!("\nTTL (Time-to-Live) Operations");
26
27    // Short-lived session data
28    let session_opts = SetOptions::with_ttl(Duration::from_secs(10));
29    db.insert("session:user123", b"active", Some(session_opts))?;
30    println!("  Created session with 10-second TTL");
31
32    // Cache data with different TTL
33    let cache_opts = SetOptions::with_ttl(Duration::from_secs(300)); // 5 minutes
34    db.insert("cache:weather", b"sunny, 22C", Some(cache_opts.clone()))?;
35    db.insert(
36        "cache:news",
37        b"Latest tech news...",
38        Some(cache_opts.clone()),
39    )?;
40    println!("  Cached data with 5-minute TTL");
41
42    // === ATOMIC BATCH OPERATIONS ===
43    println!("\nAtomic Batch Operations");
44
45    // User profile creation (all-or-nothing)
46    db.atomic(|batch| {
47        batch.insert("user:123:name", b"Alice Johnson", None)?;
48        batch.insert("user:123:email", b"alice@example.com", None)?;
49        batch.insert("user:123:role", b"admin", None)?;
50        batch.insert("user:123:created", b"2024-01-01", None)?;
51        Ok(())
52    })?;
53    println!("  Created user profile atomically");
54
55    // Sensor data batch insert
56    db.atomic(|batch| {
57        batch.insert("sensor:temp", b"23.5", None)?;
58        batch.insert("sensor:humidity", b"68", None)?;
59        batch.insert("sensor:pressure", b"1013.2", None)?;
60        batch.insert("sensor:timestamp", b"1640995200", None)?;
61        Ok(())
62    })?;
63    println!("  Recorded sensor readings atomically");
64
65    // === SPATIAL POINT OPERATIONS ===
66    println!("\nSpatial Point Operations");
67
68    // Major world cities
69    let cities = vec![
70        ("New York", Point::new(40.7128, -74.0060)),
71        ("London", Point::new(51.5074, -0.1278)),
72        ("Tokyo", Point::new(35.6762, 139.6503)),
73        ("Paris", Point::new(48.8566, 2.3522)),
74        ("Sydney", Point::new(-33.8688, 151.2093)),
75        ("São Paulo", Point::new(-23.5505, -46.6333)),
76        ("Mumbai", Point::new(19.0760, 72.8777)),
77        ("Cairo", Point::new(30.0444, 31.2357)),
78    ];
79
80    // Insert cities with automatic spatial indexing
81    for (name, point) in &cities {
82        db.insert_point("cities", point, name.as_bytes(), None)?;
83    }
84    println!(
85        "  Added {} cities with automatic spatial indexing",
86        cities.len()
87    );
88
89    // Calculate distances between cities
90    let london = Point::new(51.5074, -0.1278);
91    let paris = Point::new(48.8566, 2.3522);
92    let distance_km = london.distance_to(&paris) / 1000.0;
93    println!("  London ↔ Paris: {:.0} km", distance_km);
94
95    // Find cities near London (within 1000km)
96    let nearby_london = db.find_nearby("cities", &london, 1_000_000.0, 5)?;
97    println!("  Cities within 1000km of London:");
98    for (point, data) in &nearby_london {
99        let city_name = String::from_utf8_lossy(data);
100        let distance = london.distance_to(point) / 1000.0;
101        println!("    - {} ({:.0} km)", city_name, distance);
102    }
103
104    // === RESTAURANT/POI DATA ===
105    println!("\nPoints of Interest");
106
107    let london_restaurants = vec![
108        ("The Shard Restaurant", Point::new(51.5045, -0.0865)),
109        ("Sketch", Point::new(51.5115, -0.1442)),
110        ("Dishoom", Point::new(51.5145, -0.1270)),
111        ("Borough Market", Point::new(51.5055, -0.0931)),
112    ];
113
114    for (name, point) in &london_restaurants {
115        db.insert_point("london_food", point, name.as_bytes(), None)?;
116    }
117    println!("  Added {} London restaurants", london_restaurants.len());
118
119    // Find restaurants near a specific location (Covent Garden)
120    let covent_garden = Point::new(51.5118, -0.1226);
121    let nearby_food = db.find_nearby("london_food", &covent_garden, 2000.0, 10)?;
122    println!("  Restaurants within 2km of Covent Garden:");
123    for (point, data) in &nearby_food {
124        let restaurant_name = String::from_utf8_lossy(data);
125        let distance = covent_garden.distance_to(point);
126        println!("    - {} ({:.0}m away)", restaurant_name, distance);
127    }
128
129    // === TRAJECTORY TRACKING ===
130    println!("\nTrajectory Tracking");
131
132    // Delivery truck route through London
133    let delivery_route = vec![
134        (Point::new(51.5074, -0.1278), 1640995200), // Start: London center
135        (Point::new(51.5055, -0.0931), 1640995260), // Stop 1: Borough Market (1 min)
136        (Point::new(51.5045, -0.0865), 1640995320), // Stop 2: The Shard (2 min)
137        (Point::new(51.4994, -0.1245), 1640995380), // Stop 3: Big Ben (3 min)
138        (Point::new(51.5014, -0.1419), 1640995440), // Stop 4: Buckingham Palace (4 min)
139        (Point::new(51.5118, -0.1226), 1640995500), // End: Covent Garden (5 min)
140    ];
141
142    db.insert_trajectory("delivery:truck001", &delivery_route, None)?;
143    println!(
144        "  Stored delivery truck trajectory ({} waypoints)",
145        delivery_route.len()
146    );
147
148    // Taxi route
149    let taxi_route = vec![
150        (Point::new(51.4700, -0.4543), 1640995200), // Heathrow Airport
151        (Point::new(51.4900, -0.1743), 1640995800), // Kensington (10 min)
152        (Point::new(51.5074, -0.1278), 1640996100), // Central London (15 min)
153    ];
154
155    db.insert_trajectory("taxi:cab042", &taxi_route, None)?;
156    println!("  Stored taxi trajectory ({} waypoints)", taxi_route.len());
157
158    // Query trajectories for specific time ranges
159    let truck_morning = db.query_trajectory("delivery:truck001", 1640995200, 1640995380)?;
160    println!(
161        "  Truck trajectory (first 3 minutes): {} points",
162        truck_morning.len()
163    );
164
165    let taxi_full = db.query_trajectory("taxi:cab042", 1640995200, 1640996200)?;
166    println!("  Full taxi journey: {} points", taxi_full.len());
167
168    // === SENSOR NETWORK SIMULATION ===
169    println!("\nIoT Sensor Network");
170
171    // Simulate temperature sensors across London
172    let sensors = vec![
173        ("sensor001", Point::new(51.5074, -0.1278), "22.5°C"), // Central
174        ("sensor002", Point::new(51.5200, -0.1000), "21.8°C"), // North
175        ("sensor003", Point::new(51.4900, -0.1500), "23.1°C"), // South
176        ("sensor004", Point::new(51.5100, -0.0800), "22.9°C"), // East
177        ("sensor005", Point::new(51.5000, -0.1800), "21.5°C"), // West
178    ];
179
180    for (sensor_id, point, reading) in &sensors {
181        db.insert_point(
182            "sensors",
183            point,
184            format!("{}:{}", sensor_id, reading).as_bytes(),
185            None,
186        )?;
187    }
188    println!("  Deployed {} temperature sensors", sensors.len());
189
190    // Find sensors near a specific location
191    let monitoring_center = Point::new(51.5100, -0.1200);
192    let nearby_sensors = db.find_nearby("sensors", &monitoring_center, 5000.0, 10)?;
193    println!("  Sensors within 5km of monitoring center:");
194    for (point, data) in &nearby_sensors {
195        let sensor_info = String::from_utf8_lossy(data);
196        let distance = monitoring_center.distance_to(point);
197        println!("    - {} ({:.0}m away)", sensor_info, distance);
198    }
199
200    // === REAL-TIME UPDATES ===
201    println!("\nReal-time Updates");
202
203    // Simulate updating sensor readings
204    db.insert_point(
205        "sensors",
206        &Point::new(51.5074, -0.1278),
207        b"sensor001:24.2C",
208        None,
209    )?;
210    println!("  Updated sensor001 reading");
211
212    // Add new vehicle to tracking
213    let bus_route = vec![
214        (Point::new(51.5155, -0.0922), 1640995600), // Liverpool Street
215        (Point::new(51.5074, -0.1278), 1640995660), // Central London
216    ];
217    db.insert_trajectory("bus:route25", &bus_route, None)?;
218    println!("  Added new bus to tracking system");
219
220    // === DATABASE STATISTICS ===
221    println!("\nDatabase Statistics");
222
223    let stats = db.stats()?;
224    println!("  Total keys: {}", stats.key_count);
225    println!("  Operations performed: {}", stats.operations_count);
226
227    // Count items by namespace
228    let mut namespace_counts = std::collections::HashMap::new();
229    // This is a simplified count - in practice you'd query by prefix
230    namespace_counts.insert("cities", cities.len());
231    namespace_counts.insert("restaurants", london_restaurants.len());
232    namespace_counts.insert("sensors", sensors.len());
233    namespace_counts.insert("trajectories", 3); // truck, taxi, bus
234
235    println!("  Data distribution:");
236    for (namespace, count) in &namespace_counts {
237        println!("    - {}: {} items", namespace, count);
238    }
239
240    // === CLEANUP DEMONSTRATION ===
241    println!("\nCleanup & TTL Demo");
242
243    // Check if session has expired (it should have by now)
244    if let Some(_session) = db.get("session:user123")? {
245        println!("  Session still active");
246    } else {
247        println!("  Session expired as expected");
248    }
249
250    // Delete specific items
251    db.delete("app:version")?;
252    println!("  Removed app version info");
253
254    // Final statistics
255    let final_stats = db.stats()?;
256    println!("  Final key count: {}", final_stats.key_count);
257
258    println!("\nComprehensive demo completed successfully!");
259    println!("\nFeatures demonstrated:");
260    println!("- Key-value storage with TTL");
261    println!("- Atomic batch operations");
262    println!("- Automatic spatial indexing");
263    println!("- Geographic point queries");
264    println!("- Distance calculations");
265    println!("- Trajectory tracking");
266    println!("- Multi-namespace organization");
267    println!("- Real-time updates");
268    println!("- Data expiration");
269
270    Ok(())
271}