-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.js
More file actions
158 lines (133 loc) · 4.73 KB
/
Copy pathserver.js
File metadata and controls
158 lines (133 loc) · 4.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
import { WebSocketServer } from "ws";
import { v4 as uuidv4 } from "uuid";
const wss = new WebSocketServer({ port: 3000 });
console.log("Server running on ws://localhost:3000");
const rooms = {}; // { roomId: { host: ws, viewers: [] } }
// ============================================================================
// FLIGHT DATA SIMULATION (NEW FEATURE)
// ============================================================================
let flightData = {
flightNumber: "AA42",
altitude: 32000,
speed: 540,
timeToDestination: "2h 15m"
};
// Function to simulate realistic flight data changes
function simulateFlightData() {
// Altitude fluctuation: ±50 feet
const altitudeChange = Math.floor(Math.random() * 101) - 50;
flightData.altitude = Math.max(30000, Math.min(35000, flightData.altitude + altitudeChange));
// Speed fluctuation: ±5 mph
const speedChange = Math.floor(Math.random() * 11) - 5;
flightData.speed = Math.max(520, Math.min(560, flightData.speed + speedChange));
// Time to destination countdown (simplified)
const timeParts = flightData.timeToDestination.split(/[hm\s]+/).filter(Boolean);
let hours = parseInt(timeParts[0]) || 0;
let minutes = parseInt(timeParts[1]) || 0;
// Decrease by 1 minute every update (5 seconds in real time)
minutes -= 1;
if (minutes < 0) {
hours -= 1;
minutes = 59;
}
if (hours < 0) {
hours = 0;
minutes = 0;
}
flightData.timeToDestination = `${hours}h ${minutes}m`;
return flightData;
}
// Broadcast flight data every 5 seconds to all connected clients
setInterval(() => {
const updatedFlightData = simulateFlightData();
const message = JSON.stringify({ type: "flight_data_update", data: updatedFlightData });
wss.clients.forEach(client => {
if (client.readyState === 1) { // WebSocket.OPEN
client.send(message);
}
});
console.log('[Flight Data]', updatedFlightData);
}, 5000);
// ============================================================================
wss.on("connection", (ws) => {
// Send initial flight data to new connections
ws.send(JSON.stringify({ type: "flight_data_update", data: flightData }));
ws.on("message", (msg) => {
const data = JSON.parse(msg);
switch (data.type) {
case "create-room": {
const roomId = uuidv4();
rooms[roomId] = { host: ws, viewers: [] };
ws.roomId = roomId;
ws.isHost = true;
ws.send(JSON.stringify({ type: "created", room: roomId }));
broadcastRoomList();
break;
}
case "list-rooms": {
const roomList = Object.keys(rooms);
ws.send(JSON.stringify({ type: "room-list", rooms: roomList }));
break;
}
case "join-room": {
const room = rooms[data.roomId];
if (room) {
room.viewers.push(ws);
ws.roomId = data.roomId;
ws.isHost = false;
// Notify host and viewer
room.host.send(JSON.stringify({ type: "joined", room: data.roomId }));
ws.send(JSON.stringify({ type: "joined", room: data.roomId }));
}
break;
}
case "offer":
// send offer to all viewers
const hostRoom = rooms[ws.roomId];
if (hostRoom && ws.isHost) {
hostRoom.viewers.forEach(v => v.send(JSON.stringify({ type: "offer", offer: data.offer })));
}
break;
case "answer":
// send answer to host
const viewerRoom = rooms[ws.roomId];
if (viewerRoom && !ws.isHost) {
viewerRoom.host.send(JSON.stringify({ type: "answer", answer: data.answer }));
}
break;
case "ice-candidate":
// relay ICE candidate
const roomRef = rooms[ws.roomId];
if (!roomRef) return;
if (ws.isHost) {
// send to all viewers
roomRef.viewers.forEach(v => v.send(JSON.stringify({ type: "ice-candidate", candidate: data.candidate })));
} else {
// send to host
roomRef.host.send(JSON.stringify({ type: "ice-candidate", candidate: data.candidate }));
}
break;
}
});
ws.on("close", () => {
// remove from room
if (ws.roomId && rooms[ws.roomId]) {
const room = rooms[ws.roomId];
if (ws.isHost) {
// notify viewers room is closed
room.viewers.forEach(v => v.send(JSON.stringify({ type: "room-closed", roomId: ws.roomId })));
delete rooms[ws.roomId];
} else {
room.viewers = room.viewers.filter(v => v !== ws);
}
broadcastRoomList();
}
});
});
function broadcastRoomList() {
const list = Object.keys(rooms);
wss.clients.forEach(ws => {
ws.send(JSON.stringify({ type: "room-list", rooms: list }));
});
}
console.log('✈️ Flight data simulation enabled - broadcasting every 5 seconds');