@@ -10,10 +10,16 @@ use clap::Parser;
10
10
use log:: LevelFilter ;
11
11
use sim_lib:: {
12
12
cln:: ClnNode , lnd:: LndNode , ActivityDefinition , LightningError , LightningNode , NodeConnection ,
13
- NodeId , SimParams , Simulation ,
13
+ NodeId , SimParams , Simulation , WriteResults ,
14
14
} ;
15
15
use simple_logger:: SimpleLogger ;
16
16
17
+ /// The default directory where the simulation files are stored and where the results will be written to.
18
+ pub const DEFAULT_DATA_DIR : & str = "." ;
19
+
20
+ /// The default simulation file to be used by the simulator.
21
+ pub const DEFAULT_SIM_FILE : & str = "sim.json" ;
22
+
17
23
/// The default expected payment amount for the simulation, around ~$10 at the time of writing.
18
24
pub const EXPECTED_PAYMENT_AMOUNT : u64 = 3_800_000 ;
19
25
@@ -42,8 +48,12 @@ fn deserialize_f64_greater_than_zero(x: String) -> Result<f64, String> {
42
48
#[ derive( Parser ) ]
43
49
#[ command( version, about) ]
44
50
struct Cli {
51
+ /// Path to a directory containing simulation files, and where simulation results will be stored
52
+ #[ clap( long, short, default_value = DEFAULT_DATA_DIR ) ]
53
+ data_dir : PathBuf ,
45
54
/// Path to the simulation file to be used by the simulator
46
- #[ clap( index = 1 ) ]
55
+ /// This can either be an absolute path, or relative path with respect to data_dir
56
+ #[ clap( long, short, default_value = DEFAULT_SIM_FILE ) ]
47
57
sim_file : PathBuf ,
48
58
/// Total time the simulator will be running
49
59
#[ clap( long, short) ]
@@ -77,8 +87,9 @@ async fn main() -> anyhow::Result<()> {
77
87
. init ( )
78
88
. unwrap ( ) ;
79
89
90
+ let sim_path = read_sim_path ( cli. data_dir . clone ( ) , cli. sim_file ) . await ?;
80
91
let SimParams { nodes, activity } =
81
- serde_json:: from_str ( & std:: fs:: read_to_string ( cli . sim_file ) ?)
92
+ serde_json:: from_str ( & std:: fs:: read_to_string ( sim_path ) ?)
82
93
. map_err ( |e| anyhow ! ( "Could not deserialize node connection data or activity description from simulation file (line {}, col {})." , e. line( ) , e. column( ) ) ) ?;
83
94
84
95
let mut clients: HashMap < PublicKey , Arc < Mutex < dyn LightningNode + Send > > > = HashMap :: new ( ) ;
@@ -179,14 +190,22 @@ async fn main() -> anyhow::Result<()> {
179
190
} ) ;
180
191
}
181
192
193
+ let write_results = if !cli. no_results {
194
+ Some ( WriteResults {
195
+ results_dir : mkdir ( cli. data_dir . join ( "results" ) ) . await ?,
196
+ batch_size : cli. print_batch_size ,
197
+ } )
198
+ } else {
199
+ None
200
+ } ;
201
+
182
202
let sim = Simulation :: new (
183
203
clients,
184
204
validated_activities,
185
205
cli. total_time ,
186
- cli. print_batch_size ,
187
206
cli. expected_pmt_amt ,
188
207
cli. capacity_multiplier ,
189
- cli . no_results ,
208
+ write_results ,
190
209
) ;
191
210
let sim2 = sim. clone ( ) ;
192
211
@@ -199,3 +218,55 @@ async fn main() -> anyhow::Result<()> {
199
218
200
219
Ok ( ( ) )
201
220
}
221
+
222
+ async fn read_sim_path ( data_dir : PathBuf , sim_file : PathBuf ) -> anyhow:: Result < PathBuf > {
223
+ let sim_path = if sim_file. is_relative ( ) {
224
+ data_dir. join ( sim_file)
225
+ } else {
226
+ sim_file
227
+ } ;
228
+
229
+ if sim_path. exists ( ) {
230
+ Ok ( sim_path)
231
+ } else {
232
+ log:: info!( "Simulation file '{}' does not exist." , sim_path. display( ) ) ;
233
+ select_sim_file ( data_dir) . await
234
+ }
235
+ }
236
+
237
+ async fn select_sim_file ( data_dir : PathBuf ) -> anyhow:: Result < PathBuf > {
238
+ let sim_files = std:: fs:: read_dir ( data_dir. clone ( ) ) ?
239
+ . filter_map ( |f| {
240
+ f. ok ( ) . and_then ( |f| {
241
+ if f. path ( ) . extension ( ) ?. to_str ( ) ? == "json" {
242
+ f. file_name ( ) . into_string ( ) . ok ( )
243
+ } else {
244
+ None
245
+ }
246
+ } )
247
+ } )
248
+ . collect :: < Vec < _ > > ( ) ;
249
+
250
+ if sim_files. is_empty ( ) {
251
+ anyhow:: bail!(
252
+ "no simulation files found in {}" ,
253
+ data_dir. canonicalize( ) ?. display( )
254
+ ) ;
255
+ }
256
+
257
+ let selection = dialoguer:: Select :: new ( )
258
+ . with_prompt ( format ! (
259
+ "Select a simulation file. Found these in {}" ,
260
+ data_dir. canonicalize( ) ?. display( )
261
+ ) )
262
+ . items ( & sim_files)
263
+ . default ( 0 )
264
+ . interact ( ) ?;
265
+
266
+ Ok ( data_dir. join ( sim_files[ selection] . clone ( ) ) )
267
+ }
268
+
269
+ async fn mkdir ( dir : PathBuf ) -> anyhow:: Result < PathBuf > {
270
+ tokio:: fs:: create_dir_all ( & dir) . await ?;
271
+ Ok ( dir)
272
+ }
0 commit comments