@unitn-asa/deliveroo-js-sdk 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,316 @@
1
+ import { Socket } from 'socket.io';
2
+
3
+ /**
4
+ * @typedef {import("../types/IOAgent.js").IOAgent} IOAgent
5
+ * @typedef {import("../types/IOParcel.js").IOParcel} IOParcel
6
+ * @typedef {import("../types/IOTile.js").IOTile} IOTile
7
+ * @typedef {import("../types/IOConfig.js").IOConfig} IOConfig
8
+ * @typedef {import("../types/IOInfo.js").IOInfo} IOInfo
9
+ *
10
+ * @typedef {import("../types/IOSocketEvents.js").IOSensing} IOSensing
11
+ * @typedef {import("../types/IOSocketEvents.js").IOClientEvents} IOClientEvents on the client side these are to be emitted with .emit
12
+ * @typedef {import("../types/IOSocketEvents.js").IOServerEvents} IOServerEvents on the client side these are to be listened with .on
13
+ */
14
+
15
+
16
+
17
+ /**
18
+ * @class
19
+ * @extends { Socket<IOClientEvents, IOServerEvents> }
20
+ */
21
+ export class DjsServerSocket extends Socket {
22
+
23
+ warnings = new Array();
24
+
25
+ // /**
26
+ // * @template {keyof IOClientEvents} K
27
+ // * @param {K} event
28
+ // * @param {IOClientEvents[K]} listener
29
+ // * @returns {void}
30
+ // */
31
+ on ( event, listener ) {
32
+ return super.on( event, (...args) => {
33
+ try {
34
+ return listener.apply( this, args );
35
+ } catch (error) {
36
+ console.error( `WARN Socket ${this.id} on( ${String(event)}, ${args.slice(0,-1).join(', ')} ).`, error );
37
+ // this.warnings.push( {
38
+ // msg: `WARN Socket ${this.id} on( ${String(event)}, ${args.slice(0,-1).join(', ')} ).`,
39
+ // error: error
40
+ // } );
41
+ }
42
+ });
43
+ }
44
+
45
+ /**
46
+ * @param { function() : void } callback
47
+ */
48
+ onDisconnect ( callback ) {
49
+ this.on( 'disconnect', callback);
50
+ }
51
+
52
+ /**
53
+ * @param { IOConfig } config
54
+ */
55
+ emitConfig ( config ) {
56
+ super.emit( 'config', config );
57
+ }
58
+
59
+ /**
60
+ * @param { number } width
61
+ * @param { number } height
62
+ * @param { IOTile [] } tiles
63
+ */
64
+ emitMap ( width, height, tiles ) {
65
+ super.emit( 'map', width, height, tiles );
66
+ }
67
+
68
+ /**
69
+ * @param { IOTile } tile
70
+ * @param { IOInfo } info
71
+ */
72
+ emitTile ( { x, y, type }, info ) {
73
+ super.emit( 'tile', {x, y, type}, info );
74
+ }
75
+
76
+ /**
77
+ * @param { 'connected'|'disconnected' } status
78
+ * @param { Parameters<IOServerEvents['controller']>[1] } agent
79
+ */
80
+ emitController ( status, {id, name, teamId, teamName, score} ) {
81
+ super.emit( 'controller', status, {id, name, teamId, teamName, score} );
82
+ }
83
+
84
+ /**
85
+ * @param { IOAgent } you
86
+ * @param { IOInfo } info
87
+ */
88
+ emitYou ( {id, name, teamId, teamName, x, y, score, penalty}, info ) {
89
+ super.emit( 'you', {id, name, teamId, teamName, x, y, score, penalty}, info );
90
+ }
91
+
92
+ /**
93
+ * @param { IOSensing [] } agents
94
+ * @param { IOInfo } info
95
+ */
96
+ emitAgentsSensing ( agents, info ) {
97
+ super.emit( 'agents sensing', agents, info );
98
+ }
99
+
100
+ /**
101
+ * @param { IOSensing [] } parcels
102
+ * @param { IOInfo } info
103
+ */
104
+ emitParcelSensing ( parcels, info ) {
105
+ super.emit( 'parcels sensing', parcels, info );
106
+ }
107
+
108
+ /**
109
+ * @param { IOSensing [] } crates
110
+ * @param { IOInfo } info
111
+ */
112
+ emitCrateSensing ( crates, info ) {
113
+ super.emit( 'crates sensing', crates, info );
114
+ }
115
+
116
+
117
+
118
+ /**
119
+ * @callback onMoveCallback
120
+ * @param { 'up' | 'right' | 'left' | 'down' | { x:number, y:number } } directionOrXy
121
+ * @param { function( { x:number, y:number } | false ) : void } replyAcknowledgmentCallback ( reply )
122
+ */
123
+ /**
124
+ * @param { onMoveCallback } callback ( direction, acknowledgementCallback )
125
+ */
126
+ onMove ( callback ) {
127
+ this.on( 'move', callback );
128
+ }
129
+
130
+ /**
131
+ * @callback onPickupCallback
132
+ * @param { function( { id:string } [] ) : void } acknowledgementCallback
133
+ */
134
+ /**
135
+ * @param { onPickupCallback } callback ( acknowledgementCallback )
136
+ */
137
+ onPickup ( callback ) {
138
+ this.on( 'pickup', callback );
139
+ }
140
+
141
+ /**
142
+ * @callback onPutdownCallback
143
+ * @param { string [] } selected ids of parcels to drop
144
+ * @param { function( { id:string } [] ) : void } acknowledgementCallback
145
+ */
146
+ /**
147
+ * @param { onPutdownCallback } callback ( selected, acknowledgementCallback )
148
+ */
149
+ onPutdown ( callback ) {
150
+ this.on( 'putdown', callback );
151
+ }
152
+
153
+
154
+
155
+ /**
156
+ * @param { function ( string, any, function ( 'successful' ) : void ) : void } callback ( toId, msg, ack )
157
+ */
158
+ onSay ( callback ) {
159
+ this.on( 'say', callback );
160
+ }
161
+
162
+ /**
163
+ * @param { function ( string, any, function ( any ) : void ) : void } callback ( toId, msg, ack(reply) )
164
+ */
165
+ onAsk ( callback ) {
166
+ this.on( 'ask', callback );
167
+ }
168
+
169
+ /**
170
+ * @param { function ( any, function ( any ) : void ) : void } callback ( msg, ack(reply) )
171
+ */
172
+ onShout ( callback ) {
173
+ this.on( 'shout', callback );
174
+ }
175
+
176
+ /**
177
+ * @param { IOAgent } me
178
+ * @param { string } toId
179
+ * @param { {} } msg
180
+ * @returns { Promise < any > } reply
181
+ */
182
+ async emitMsg ( me, toId, msg ) {
183
+ return super.to( "agent:" + toId ).emit( 'msg', me.id, me.name, msg );
184
+ }
185
+
186
+ /**
187
+ * @param { IOAgent } me
188
+ * @param { string } toId
189
+ * @param { {} } msg
190
+ * @returns { Promise < any > } reply
191
+ */
192
+ async emitAsk ( me, toId, msg ) {
193
+
194
+ // Currently, acks is awaited from all clients when .emit(), otherwise callback gets an error
195
+ // https://github.com/socketio/socket.io/discussions/5062
196
+ const sockets = await super.to( "agent:" + toId ).fetchSockets();
197
+ const emissionPromises = sockets.map( socket => {
198
+ return new Promise( (res) => {
199
+ socket.timeout(1000).emit( 'msg', me.id, me.name, msg, (err, response) => {
200
+ if (err)
201
+ res('timeout');
202
+ else
203
+ res(response);
204
+ } );
205
+ } );
206
+ } );
207
+
208
+ // wait for first promise to resolve and ensure a timeout resolution in case all the responses are invalid
209
+ const response = await Promise.race(
210
+ emissionPromises.concat(new Promise(res => setTimeout(() => res('timeout'), 1000)))
211
+ );
212
+
213
+ return response;
214
+ }
215
+
216
+ /**
217
+ * @param { any } msg
218
+ * @returns { void } reply
219
+ */
220
+ broadcastMsg ( me, msg ) {
221
+ super.broadcast.emit( 'msg', me.id, me.name, msg );
222
+ }
223
+
224
+ /**
225
+ * @param { function ( ...any ) : void } callback ( ...msgArgs )
226
+ */
227
+ onLog ( callback ) {
228
+ this.on( 'log', callback );
229
+ }
230
+
231
+ /**
232
+ * @param { string } myId
233
+ * @param { string } myName
234
+ * @param { 'server' | { socket:string, id:string, name:string } } src - 'server' or client
235
+ * @param { IOInfo } info
236
+ * @param { ...any } message
237
+ */
238
+ broadcastLog ( myId, myName, src, info, ...message ) {
239
+ super.broadcast.emit( 'log', src, info, ...message );
240
+ }
241
+
242
+
243
+
244
+ /**
245
+ * Process request for creating a parcel on x, y or disposing or setting its reward given the id
246
+ * @param { function ( 'create' | 'dispose' | 'set', {id:string, x:number, y:number, reward:number} ) : void } callback
247
+ */
248
+ onParcel ( callback ) {
249
+ this.on( 'parcel', callback );
250
+ }
251
+
252
+ /**
253
+ * Process request for creating a tile on x, y or setting its type
254
+ * @param { function ( IOTile ) : void } callback
255
+ */
256
+ onTile ( callback ) {
257
+ this.on( 'tile', callback );
258
+ }
259
+
260
+ /**
261
+ * Process request for restarting the game
262
+ * @param { function () : void } callback
263
+ */
264
+ onRestart ( callback ) {
265
+ this.on( 'restart', callback );
266
+ }
267
+
268
+
269
+
270
+ /**
271
+ * Enhance a Socket.io Socket into a DjsSocket
272
+ * @param { Socket } socket
273
+ * @returns { DjsServerSocket }
274
+ */
275
+ static enhance(socket) {
276
+
277
+ /**
278
+ * Mixin function to copy methods from a class prototype to an object
279
+ */
280
+ function applyMixin(target, MixinClass) {
281
+
282
+ let proto = MixinClass.prototype;
283
+
284
+ const descriptors = Object.getOwnPropertyDescriptors(proto);
285
+ delete descriptors.constructor;
286
+
287
+ Object.defineProperties(target, descriptors);
288
+
289
+ return target;
290
+ }
291
+ applyMixin(socket, DjsServerSocket);
292
+
293
+ /**
294
+ * Original socket enhanced with ClientSocketEnhancer methods casted as EnhancedSocket
295
+ * @type { DjsServerSocket }
296
+ */
297
+ // @ts-ignore
298
+ return socket;
299
+
300
+ }
301
+
302
+ }
303
+
304
+
305
+
306
+
307
+ // import { Server } from 'socket.io';
308
+ // const ioserver = new Server();
309
+ // ioserver.listen( 3000 );
310
+ // ioserver.on( 'connection', ( socket ) => {
311
+ // const enhancedSocket = enhanceServerSocket( socket );
312
+ // enhancedSocket.onMove( ( direction ) => {
313
+ // console.log( `Client ${enhancedSocket.id} moved ${direction}` );
314
+ // return { success: true };
315
+ // } );
316
+ // } );
@@ -0,0 +1,21 @@
1
+
2
+ /**
3
+ * @typedef {import("../types/IOConfig.js").IOConfig} IOConfig
4
+ * @typedef {import("../types/IOGameOptions.js").IOGameOptions} IOGameOptions
5
+ *
6
+ * @typedef {import("../types/IOClockEvent.js").IOClockEvent} IOClockEvent
7
+ *
8
+ * @typedef {import("../types/IOAgent.js").IOAgent} IOAgent
9
+ * @typedef {import("../types/IOParcel.js").IOParcel} IOParcel
10
+ * @typedef {import("../types/IOTile.js").IOTile} IOTile
11
+ *
12
+ * @typedef {import("../types/IOIdentity.js").IOIdentity} IOIdentity
13
+ * @typedef {import("../types/IOInfo.js").IOInfo} IOInfo
14
+ * @typedef {import("../types/IOSensing.js").IOSensing} IOSensing
15
+ *
16
+ * @typedef {import("../types/IOSocketEvents.js").IOClientEvents} IOClientEvents
17
+ * @typedef {import("../types/IOSocketEvents.js").IOServerEvents} IOServerEvents
18
+ */
19
+
20
+ export { DjsServerSocket } from './DjsServerSocket.js';
21
+ export { DjsServer } from './DjsServer.js';
@@ -0,0 +1,14 @@
1
+
2
+ /**
3
+ * @typedef IOAgent
4
+ * @property {string} id
5
+ * @property {string} name
6
+ * @property {string} teamId
7
+ * @property {string} teamName
8
+ * @property {number} x
9
+ * @property {number} y
10
+ * @property {number} score
11
+ * @property {number} penalty
12
+ */
13
+
14
+ export { };
@@ -0,0 +1,21 @@
1
+
2
+ /**
3
+ * @typedef { 'frame' | '1s' | '2s' | '5s' | '10s' | 'infinite' } IOClockEvent
4
+ * @export
5
+ */
6
+
7
+
8
+
9
+ /**
10
+ * @param { string } event
11
+ * @returns { IOClockEvent }
12
+ */
13
+ function parseClockEvent ( event ) {
14
+ if ( event == 'frame' || event == '1s' || event == '2s' || event == '5s' || event == '10s' || event == 'infinite' )
15
+ return event;
16
+ else
17
+ console.warn( `IOClockEvent: invalid event '${event}', defaulting to '1s'` );
18
+ return '1s';
19
+ }
20
+
21
+ export { parseClockEvent };
@@ -0,0 +1,17 @@
1
+
2
+ /**
3
+ * @typedef { import("./IOGameOptions.js").IOGameOptions } IOGameOptions
4
+ */
5
+
6
+ /**
7
+ * @typedef IOConfig
8
+ *
9
+ * config.js
10
+ * @property {Number} CLOCK Game clock event name
11
+ * @property {Number} PENALTY Penalty for wrong moves
12
+ * @property {Number} AGENT_TIMEOUT Player/Controller timeout
13
+ * @property {Boolean} BROADCAST_LOGS Whether to broadcast logs to clients
14
+ * @property {IOGameOptions} GAME Game options
15
+ */
16
+
17
+ export { };
@@ -0,0 +1,9 @@
1
+
2
+ /**
3
+ * @typedef IOCrate
4
+ * @property {string} id
5
+ * @property {number} x
6
+ * @property {number} y
7
+ */
8
+
9
+ export { };
@@ -0,0 +1,54 @@
1
+
2
+ /** @typedef { import("./IOClockEvent.js").IOClockEvent } IOClockEvent */
3
+ /** @typedef { import("./IOTile.js").IOTileType } IOTileType */
4
+
5
+ /**
6
+ * @typedef IOGameOptions
7
+ *
8
+ * config.js
9
+ * @property {string} title Game title
10
+ * @property {string} description Game description
11
+ * @property {IOMapOptions} map Map configuration
12
+ * @property {number} maxPlayers Maximum number of players
13
+ * @property {IONpcsOptions[]} npcs Array of NPC configurations
14
+ * @property {IOParcelsOptions} parcels Parcels configuration
15
+ * @property {IOPlayerOptions} player Player configuration *
16
+ */
17
+
18
+ /**
19
+ * @typedef IOMapOptions
20
+ * @property {number} width Map width in tiles
21
+ * @property {number} height Map height in tiles
22
+ * @property {IOTileType[][]} tiles 2D array of tile types
23
+ */
24
+
25
+ /**
26
+ * @typedef IONpcsOptions
27
+ * NPC configuration object
28
+ * @property {IOClockEvent} moving_event Event whenever the NPC moves
29
+ * @property {string} type NPC type (random, collector, etc.)
30
+ * @property {number} count Number of NPCs of this type
31
+ * @property {number} capacity Capacity (for collector NPCs)
32
+ */
33
+
34
+ /**
35
+ * @typedef IOParcelsOptions
36
+ * Parcels configuration object
37
+ * @property {IOClockEvent} generation_event Event for parcels generation
38
+ * @property {IOClockEvent} decaying_event Event for parcel decaying
39
+ * @property {number} max Maximum number of parcels in the grid
40
+ * @property {number} reward_avg Reward average
41
+ * @property {number} reward_variance Reward variance
42
+ */
43
+
44
+ /**
45
+ * @typedef IOPlayerOptions
46
+ * Player configuration object
47
+ * @property {string} agent_type Agent class
48
+ * @property {number} movement_duration Duration of each movement in ms
49
+ * @property {number} agents_observation_distance Observation distance for agents
50
+ * @property {number} parcels_observation_distance Observation distance for parcels
51
+ * @property {number} capacity Capacity
52
+ */
53
+
54
+ export { };
@@ -0,0 +1,12 @@
1
+
2
+ /**
3
+ * @typedef IOIdentity
4
+ * @type {{
5
+ * id: string,
6
+ * name: string,
7
+ * teamId: string,
8
+ * teamName: string
9
+ * }}
10
+ */
11
+
12
+ export {};
@@ -0,0 +1,11 @@
1
+
2
+ /**
3
+ * @typedef IOInfo
4
+ * @property {number} ms
5
+ * @property {number} frame
6
+ * @property {number} fps
7
+ * @property {number} heapUsed
8
+ * @property {number} heapTotal
9
+ */
10
+
11
+ export { };
@@ -0,0 +1,11 @@
1
+
2
+ /**
3
+ * @typedef IOParcel
4
+ * @property {string} id
5
+ * @property {number} x
6
+ * @property {number} y
7
+ * @property {string=} carriedBy
8
+ * @property {number} reward
9
+ */
10
+
11
+ export { };
@@ -0,0 +1,15 @@
1
+
2
+ /** @typedef {import('./IOAgent.js').IOAgent} IOAgent */
3
+ /** @typedef {import('./IOParcel.js').IOParcel} IOParcel */
4
+ /** @typedef {import('./IOCrate.js').IOCrate} IOCrate */
5
+
6
+ /**
7
+ * @typedef IOSensing
8
+ * @property {number} x
9
+ * @property {number} y
10
+ * @property {IOAgent=} agent
11
+ * @property {IOParcel=} parcel
12
+ * @property {IOCrate=} crate
13
+ */
14
+
15
+ export { };
@@ -0,0 +1,44 @@
1
+
2
+ /** @typedef {import('./IOAgent.js').IOAgent} IOAgent */
3
+ /** @typedef {import('./IOTile.js').IOTile} IOTile */
4
+ /** @typedef {import('./IOInfo.js').IOInfo} IOInfo */
5
+ /** @typedef {import('./IOSensing.js').IOSensing} IOSensing */
6
+
7
+ /**
8
+ * Client -> Server events. Emitted by the client and listened by the server.
9
+ * @typedef {{
10
+ * 'disconnect': function () : void,
11
+ * 'move': function ( 'up' | 'right' | 'left' | 'down' | { x:number, y:number }, function ( { x:number, y:number } | false ) : void = ) : { x:number, y:number } | false,
12
+ * 'pickup': function ( function ( { id:string } [] ) : void = ) : { id:string } [],
13
+ * 'putdown': function ( string [] =, function ( { id:string } [] ) : void = ) : { id:string } [],
14
+ * 'say': function ( string, any, function( 'successful' ) : void ) : void,
15
+ * 'ask': function ( string, any, function( any ) : void ) : void,
16
+ * 'shout': function ( any, function( any ) : void ) : void,
17
+ * 'parcel': function ( 'create' | 'dispose' | 'set', { x:number, y:number } | { id:string, reward?:number } ) : void,
18
+ * 'crate': function ( 'create' | 'dispose', { x:number, y:number } ) : void,
19
+ * 'restart': function () : void,
20
+ * 'tile': function ( IOTile ) : void,
21
+ * 'log': function ( ...any ) : void
22
+ * }} IOClientEvents
23
+ */
24
+
25
+ /**
26
+ * Server -> Client events. Emitted by the server and listened by the client.
27
+ * @typedef {{
28
+ * 'connect': function () : void,
29
+ * 'disconnect': function () : void,
30
+ * 'token': function ( string ) : void,
31
+ * 'config': function ( any ) : void,
32
+ * 'map': function ( number, number, IOTile[] ) : void,
33
+ * 'tile': function ( IOTile, IOInfo ) : void,
34
+ * 'controller': function ( 'connected' | 'disconnected', {id:string, name:string, teamId:string, teamName:string, score:number} ) : void,
35
+ * 'you': function ( IOAgent, IOInfo ) : void,
36
+ * 'agents sensing': function ( IOSensing[], IOInfo ) : void,
37
+ * 'parcels sensing': function ( IOSensing[], IOInfo ) : void,
38
+ * 'crates sensing': function ( IOSensing[], IOInfo ) : void,
39
+ * 'msg': function ( string, string, Object, function ( Object ) : void = ) : Object,
40
+ * 'log': function ( 'server' | { socket:string, id:string, name:string }, IOInfo, ...any ) : void
41
+ * }} IOServerEvents
42
+ */
43
+
44
+ export { };
@@ -0,0 +1,28 @@
1
+
2
+ /**
3
+ * @typedef IOTileType
4
+ * Tile type representation (string)
5
+ * @type { '0' | '1' | '2' | '3' | '4' | '5' | '5!' | '←' | '↑' | '→' | '↓' }
6
+ */
7
+
8
+ /**
9
+ * @typedef IOTile
10
+ * @property {number} x
11
+ * @property {number} y
12
+ * @property {IOTileType} type - Tile type: '0' (wall), '1' (parcel spawner), '2' (delivery), '3' (walkable), '4' (base), '5' (crate sliding tile), '5!' (crate spawner), or directional arrows '↑', '→', '↓', '←'
13
+ */
14
+
15
+ /**
16
+ * @param {number | string} typeStr
17
+ * @returns {IOTileType}
18
+ */
19
+ export function parseIOTileType(typeStr) {
20
+ typeStr = String(typeStr);
21
+ const validTypes = ['0', '1', '2', '3', '4', '5', '5!', '←', '↑', '→', '↓'];
22
+ if ( validTypes.includes(typeStr[0]) && typeStr[1] == '!' || typeStr.length === 1 ) {
23
+ return /** @type {IOTileType} */ (typeStr);
24
+ } else {
25
+ console.warn(`Invalid IOTileType: ${typeStr}, defaulting to '0'`);
26
+ return '0';
27
+ }
28
+ }
@@ -0,0 +1,17 @@
1
+
2
+ /** @typedef {import("./IOClockEvent.js").IOClockEvent} IOClockEvent */
3
+
4
+
5
+
6
+ /**
7
+ * @param { string } event
8
+ * @returns { IOClockEvent }
9
+ */
10
+ function parseClockEvent ( event ) {
11
+ if ( event == 'frame' || event == '1s' || event == '2s' || event == '5s' || event == '10s' )
12
+ return event;
13
+ else
14
+ throw new Error( `IOClockEvent: invalid event '${event}'` );
15
+ }
16
+
17
+ export { parseClockEvent };