Update
This commit is contained in:
		
							parent
							
								
									717a389a22
								
							
						
					
					
						commit
						35a0c40d14
					
				
					 8 changed files with 3359 additions and 0 deletions
				
			
		
							
								
								
									
										19
									
								
								rust/cargo_check.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								rust/cargo_check.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,19 @@ | ||||||
|  | import toml | ||||||
|  | import subprocess as SP | ||||||
|  | import os | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def set_version(rev=None): | ||||||
|  |     with open("Cargo.toml") as fh: | ||||||
|  |         cargo = toml.loads(fh.read()) | ||||||
|  |     cargo["dependencies"]["pyo3"]["rev"] = rev | ||||||
|  |     if rev is None: | ||||||
|  |         del cargo["dependencies"]["pyo3"]["rev"] | ||||||
|  |     with open("Cargo.toml", "w") as fh: | ||||||
|  |         toml.dump(cargo, fh) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | for commit in open("ch.txt").readlines(): | ||||||
|  |     set_version(commit.strip()) | ||||||
|  |     if os.system("cargo check") == 0: | ||||||
|  |         break | ||||||
							
								
								
									
										2203
									
								
								rust/ch.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2203
									
								
								rust/ch.txt
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										19
									
								
								rust/rustup_check.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								rust/rustup_check.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,19 @@ | ||||||
|  | import subprocess as SP | ||||||
|  | import os | ||||||
|  | from datetime import timedelta | ||||||
|  | from datetime import datetime | ||||||
|  | 
 | ||||||
|  | dt = timedelta(days=1) | ||||||
|  | d = datetime.today().date() | ||||||
|  | 
 | ||||||
|  | while True: | ||||||
|  |     toolchain="nightly-{}".format(d.isoformat()) | ||||||
|  |     ret = os.system( | ||||||
|  |         f"rustup default {toolchain}" | ||||||
|  |     ) | ||||||
|  |     if ret==0: | ||||||
|  |         os.system("cargo +{} clean".format(toolchain)) | ||||||
|  |         if os.system("cargo +{} check".format(toolchain))==0: | ||||||
|  |             print(d) | ||||||
|  |             break | ||||||
|  |     d = d - dt | ||||||
							
								
								
									
										289
									
								
								rust/src/data.json
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										289
									
								
								rust/src/data.json
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,289 @@ | ||||||
|  | { | ||||||
|  |     "timestamp": "2019-09-25T21:29:51Z", | ||||||
|  |     "event": "Loadout", | ||||||
|  |     "Ship": "asp", | ||||||
|  |     "ShipID": 0, | ||||||
|  |     "ShipName": "Nightmaregreen_N", | ||||||
|  |     "ShipIdent": "NMGR_N", | ||||||
|  |     "HullValue": 6144793, | ||||||
|  |     "ModulesValue": 33042643, | ||||||
|  |     "HullHealth": 1.000000, | ||||||
|  |     "UnladenMass": 347.200012, | ||||||
|  |     "CargoCapacity": 0, | ||||||
|  |     "MaxJumpRange": 56.372398, | ||||||
|  |     "FuelCapacity": { | ||||||
|  |         "Main": 64.000000, | ||||||
|  |         "Reserve": 0.630000 | ||||||
|  |     }, | ||||||
|  |     "Rebuy": 1959374, | ||||||
|  |     "Modules": [ | ||||||
|  |         { | ||||||
|  |             "Slot": "ShipCockpit", | ||||||
|  |             "Item": "asp_cockpit", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 1, | ||||||
|  |             "Health": 1.000000 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "CargoHatch", | ||||||
|  |             "Item": "modularcargobaydoor", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 0, | ||||||
|  |             "Health": 1.000000 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "TinyHardpoint1", | ||||||
|  |             "Item": "hpt_heatsinklauncher_turret_tiny", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 0, | ||||||
|  |             "AmmoInClip": 1, | ||||||
|  |             "AmmoInHopper": 2, | ||||||
|  |             "Health": 1.000000 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "TinyHardpoint2", | ||||||
|  |             "Item": "hpt_heatsinklauncher_turret_tiny", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 0, | ||||||
|  |             "AmmoInClip": 1, | ||||||
|  |             "AmmoInHopper": 2, | ||||||
|  |             "Health": 1.000000 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "TinyHardpoint3", | ||||||
|  |             "Item": "hpt_heatsinklauncher_turret_tiny", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 0, | ||||||
|  |             "AmmoInClip": 1, | ||||||
|  |             "AmmoInHopper": 2, | ||||||
|  |             "Health": 1.000000 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "TinyHardpoint4", | ||||||
|  |             "Item": "hpt_heatsinklauncher_turret_tiny", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 0, | ||||||
|  |             "AmmoInClip": 1, | ||||||
|  |             "AmmoInHopper": 2, | ||||||
|  |             "Health": 1.000000 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "PaintJob", | ||||||
|  |             "Item": "paintjob_asp_operator_red", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 1, | ||||||
|  |             "Health": 1.000000 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "Armour", | ||||||
|  |             "Item": "asp_armour_grade1", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 1, | ||||||
|  |             "Health": 1.000000 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "PowerPlant", | ||||||
|  |             "Item": "int_powerplant_size5_class2", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 1, | ||||||
|  |             "Health": 1.000000 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "MainEngines", | ||||||
|  |             "Item": "int_engine_size4_class2", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 0, | ||||||
|  |             "Health": 1.000000 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "FrameShiftDrive", | ||||||
|  |             "Item": "int_hyperdrive_size5_class5", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 0, | ||||||
|  |             "Health": 1.000000, | ||||||
|  |             "Engineering": { | ||||||
|  |                 "Engineer": "Felicity Farseer", | ||||||
|  |                 "EngineerID": 300100, | ||||||
|  |                 "BlueprintID": 128673694, | ||||||
|  |                 "BlueprintName": "FSD_LongRange", | ||||||
|  |                 "Level": 5, | ||||||
|  |                 "Quality": 1.000000, | ||||||
|  |                 "ExperimentalEffect": "special_fsd_heavy", | ||||||
|  |                 "ExperimentalEffect_Localised": "Mass Manager", | ||||||
|  |                 "Modifiers": [ | ||||||
|  |                     { | ||||||
|  |                         "Label": "Mass", | ||||||
|  |                         "Value": 26.000000, | ||||||
|  |                         "OriginalValue": 20.000000, | ||||||
|  |                         "LessIsGood": 1 | ||||||
|  |                     }, | ||||||
|  |                     { | ||||||
|  |                         "Label": "Integrity", | ||||||
|  |                         "Value": 93.840004, | ||||||
|  |                         "OriginalValue": 120.000000, | ||||||
|  |                         "LessIsGood": 0 | ||||||
|  |                     }, | ||||||
|  |                     { | ||||||
|  |                         "Label": "PowerDraw", | ||||||
|  |                         "Value": 0.690000, | ||||||
|  |                         "OriginalValue": 0.600000, | ||||||
|  |                         "LessIsGood": 1 | ||||||
|  |                     }, | ||||||
|  |                     { | ||||||
|  |                         "Label": "FSDOptimalMass", | ||||||
|  |                         "Value": 1692.599976, | ||||||
|  |                         "OriginalValue": 1050.000000, | ||||||
|  |                         "LessIsGood": 0 | ||||||
|  |                     } | ||||||
|  |                 ] | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "LifeSupport", | ||||||
|  |             "Item": "int_lifesupport_size4_class2", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 0, | ||||||
|  |             "Health": 1.000000 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "PowerDistributor", | ||||||
|  |             "Item": "int_powerdistributor_size4_class2", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 0, | ||||||
|  |             "Health": 1.000000 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "Radar", | ||||||
|  |             "Item": "int_sensors_size5_class2", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 0, | ||||||
|  |             "Health": 1.000000 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "FuelTank", | ||||||
|  |             "Item": "int_fueltank_size5_class3", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 1, | ||||||
|  |             "Health": 1.000000 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "Decal1", | ||||||
|  |             "Item": "decal_explorer_starblazer", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 1, | ||||||
|  |             "Health": 1.000000 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "Decal2", | ||||||
|  |             "Item": "decal_explorer_starblazer", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 1, | ||||||
|  |             "Health": 1.000000 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "Decal3", | ||||||
|  |             "Item": "decal_explorer_starblazer", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 1, | ||||||
|  |             "Health": 1.000000 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "ShipName0", | ||||||
|  |             "Item": "nameplate_shipname_white", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 1, | ||||||
|  |             "Health": 1.000000 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "ShipName1", | ||||||
|  |             "Item": "nameplate_shipname_white", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 1, | ||||||
|  |             "Health": 1.000000 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "ShipID0", | ||||||
|  |             "Item": "nameplate_shipid_white", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 1, | ||||||
|  |             "Health": 1.000000 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "ShipID1", | ||||||
|  |             "Item": "nameplate_shipid_white", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 1, | ||||||
|  |             "Health": 1.000000 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "Slot01_Size6", | ||||||
|  |             "Item": "int_fuelscoop_size6_class5", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 0, | ||||||
|  |             "Health": 1.000000 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "Slot02_Size5", | ||||||
|  |             "Item": "int_fueltank_size5_class3", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 1, | ||||||
|  |             "Health": 1.000000 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "Slot03_Size3", | ||||||
|  |             "Item": "int_repairer_size3_class5", | ||||||
|  |             "On": false, | ||||||
|  |             "Priority": 0, | ||||||
|  |             "Health": 1.000000 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "Slot04_Size3", | ||||||
|  |             "Item": "int_shieldgenerator_size3_class2", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 0, | ||||||
|  |             "Health": 1.000000 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "Slot05_Size3", | ||||||
|  |             "Item": "int_buggybay_size2_class2", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 0, | ||||||
|  |             "Health": 1.000000 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "Slot06_Size2", | ||||||
|  |             "Item": "int_detailedsurfacescanner_tiny", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 0, | ||||||
|  |             "Health": 1.000000 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "Slot07_Size2", | ||||||
|  |             "Item": "int_dockingcomputer_standard", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 0, | ||||||
|  |             "Health": 1.000000 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "Slot08_Size1", | ||||||
|  |             "Item": "int_supercruiseassist", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 0, | ||||||
|  |             "Health": 1.000000 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "PlanetaryApproachSuite", | ||||||
|  |             "Item": "int_planetapproachsuite", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 1, | ||||||
|  |             "Health": 1.000000 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "VesselVoice", | ||||||
|  |             "Item": "voicepack_eden", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 1, | ||||||
|  |             "Health": 1.000000 | ||||||
|  |         } | ||||||
|  |     ] | ||||||
|  | } | ||||||
							
								
								
									
										193
									
								
								rust/src/data_guardian.json
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								rust/src/data_guardian.json
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,193 @@ | ||||||
|  | { | ||||||
|  |     "timestamp": "2019-09-25T21:29:51Z", | ||||||
|  |     "event": "Loadout", | ||||||
|  |     "Ship": "asp", | ||||||
|  |     "ShipName": "Nightmaregreen_G", | ||||||
|  |     "ShipIdent": "NMGR_G", | ||||||
|  |     "HullValue": 6144793, | ||||||
|  |     "ModulesValue": 33181682, | ||||||
|  |     "UnladenMass": 348.500061, | ||||||
|  |     "CargoCapacity": 0, | ||||||
|  |     "MaxJumpRange": 60.164637, | ||||||
|  |     "FuelCapacity": { | ||||||
|  |         "Main": 64, | ||||||
|  |         "Reserve": 0.63 | ||||||
|  |     }, | ||||||
|  |     "Rebuy": 1966323, | ||||||
|  |     "Modules": [ | ||||||
|  |         { | ||||||
|  |             "Slot": "CargoHatch", | ||||||
|  |             "Item": "modularcargobaydoor", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 0 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "TinyHardpoint1", | ||||||
|  |             "Item": "hpt_heatsinklauncher_turret_tiny", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 0, | ||||||
|  |             "Value": 3071 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "TinyHardpoint2", | ||||||
|  |             "Item": "hpt_heatsinklauncher_turret_tiny", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 0, | ||||||
|  |             "Value": 3071 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "TinyHardpoint3", | ||||||
|  |             "Item": "hpt_heatsinklauncher_turret_tiny", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 0, | ||||||
|  |             "Value": 3071 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "TinyHardpoint4", | ||||||
|  |             "Item": "hpt_heatsinklauncher_turret_tiny", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 0, | ||||||
|  |             "Value": 3071 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "Armour", | ||||||
|  |             "Item": "asp_armour_grade1", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 1, | ||||||
|  |             "Value": 0 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "PowerPlant", | ||||||
|  |             "Item": "int_powerplant_size5_class2", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 1, | ||||||
|  |             "Value": 140523 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "MainEngines", | ||||||
|  |             "Item": "int_engine_size4_class2", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 0, | ||||||
|  |             "Value": 52325 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "FrameShiftDrive", | ||||||
|  |             "Item": "int_hyperdrive_size5_class5", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 0, | ||||||
|  |             "Value": 4478716, | ||||||
|  |             "Engineering": { | ||||||
|  |                 "BlueprintName": "FSD_LongRange", | ||||||
|  |                 "Level": 5, | ||||||
|  |                 "Quality": 1, | ||||||
|  |                 "ExperimentalEffect": "special_fsd_heavy", | ||||||
|  |                 "Modifiers": [ | ||||||
|  |                     { | ||||||
|  |                         "Label": "Mass", | ||||||
|  |                         "Value": 26.000061, | ||||||
|  |                         "OriginalValue": 20 | ||||||
|  |                     }, | ||||||
|  |                     { | ||||||
|  |                         "Label": "Integrity", | ||||||
|  |                         "Value": 93.839832, | ||||||
|  |                         "OriginalValue": 120 | ||||||
|  |                     }, | ||||||
|  |                     { | ||||||
|  |                         "Label": "PowerDraw", | ||||||
|  |                         "Value": 0.690001, | ||||||
|  |                         "OriginalValue": 0.6 | ||||||
|  |                     }, | ||||||
|  |                     { | ||||||
|  |                         "Label": "FSDOptimalMass", | ||||||
|  |                         "Value": 1692.58667, | ||||||
|  |                         "OriginalValue": 1050 | ||||||
|  |                     } | ||||||
|  |                 ] | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "LifeSupport", | ||||||
|  |             "Item": "int_lifesupport_size4_class2", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 0, | ||||||
|  |             "Value": 24895 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "PowerDistributor", | ||||||
|  |             "Item": "int_powerdistributor_size4_class2", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 0, | ||||||
|  |             "Value": 24895 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "Radar", | ||||||
|  |             "Item": "int_sensors_size5_class2", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 0, | ||||||
|  |             "Value": 69709 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "FuelTank", | ||||||
|  |             "Item": "int_fueltank_size5_class3", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 1, | ||||||
|  |             "Value": 85776 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "Slot01_Size6", | ||||||
|  |             "Item": "int_fuelscoop_size6_class5", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 0, | ||||||
|  |             "Value": 25240068 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "Slot02_Size5", | ||||||
|  |             "Item": "int_fueltank_size5_class3", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 1, | ||||||
|  |             "Value": 85776 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "Slot03_Size3", | ||||||
|  |             "Item": "int_repairer_size3_class5", | ||||||
|  |             "On": false, | ||||||
|  |             "Priority": 0, | ||||||
|  |             "Value": 2302911 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "Slot04_Size3", | ||||||
|  |             "Item": "int_shieldgenerator_size3_class2", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 0, | ||||||
|  |             "Value": 16506 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "Slot05_Size3", | ||||||
|  |             "Item": "int_buggybay_size2_class2", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 0, | ||||||
|  |             "Value": 18954 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "Slot06_Size2", | ||||||
|  |             "Item": "int_detailedsurfacescanner_tiny", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 0, | ||||||
|  |             "Value": 219375 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "Slot07_Size2", | ||||||
|  |             "Item": "int_dockingcomputer_standard", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 0, | ||||||
|  |             "Value": 3949 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "Slot": "Slot08_Size1", | ||||||
|  |             "Item": "int_guardianfsdbooster_size1", | ||||||
|  |             "On": true, | ||||||
|  |             "Priority": 0, | ||||||
|  |             "Value": 405020 | ||||||
|  |         } | ||||||
|  |     ] | ||||||
|  | } | ||||||
							
								
								
									
										196
									
								
								rust/src/edsm.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										196
									
								
								rust/src/edsm.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,196 @@ | ||||||
|  | use crate::common::get_mult; | ||||||
|  | use crate::common::SystemSerde; | ||||||
|  | use fnv::FnvHashMap; | ||||||
|  | use pyo3::prelude::*; | ||||||
|  | use serde::Deserialize; | ||||||
|  | use serde_json::Result; | ||||||
|  | use std::fs::File; | ||||||
|  | use std::io::Seek; | ||||||
|  | use std::io::{BufRead, BufReader, BufWriter, SeekFrom}; | ||||||
|  | use std::path::PathBuf; | ||||||
|  | use std::str; | ||||||
|  | use std::time::Instant; | ||||||
|  | 
 | ||||||
|  | #[derive(Debug, Deserialize)] | ||||||
|  | #[allow(non_snake_case)] | ||||||
|  | struct Body { | ||||||
|  |     name: String, | ||||||
|  |     subType: String, | ||||||
|  |     #[serde(rename = "type")] | ||||||
|  |     body_type: String, | ||||||
|  |     systemId: i32, | ||||||
|  |     systemId64: i64, | ||||||
|  |     #[serde(rename = "distanceToArrival")] | ||||||
|  |     distance: f32, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Debug, Deserialize)] | ||||||
|  | struct Coords { | ||||||
|  |     x: f32, | ||||||
|  |     y: f32, | ||||||
|  |     z: f32, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Debug, Deserialize)] | ||||||
|  | struct System { | ||||||
|  |     id: i32, | ||||||
|  |     id64: i64, | ||||||
|  |     name: String, | ||||||
|  |     coords: Coords, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Debug)] | ||||||
|  | pub struct PreprocessState { | ||||||
|  |     pub file: String, | ||||||
|  |     pub message: String, | ||||||
|  |     pub total: u64, | ||||||
|  |     pub done: u64, | ||||||
|  |     pub count: usize, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn process( | ||||||
|  |     path: &PathBuf, | ||||||
|  |     func: &mut dyn for<'r> FnMut(&'r str) -> (), | ||||||
|  |     callback: &dyn Fn(&PreprocessState) -> PyResult<PyObject>, | ||||||
|  | ) -> std::io::Result<()> { | ||||||
|  |     let mut buffer = String::new(); | ||||||
|  |     let fh = File::open(path)?; | ||||||
|  |     let total_size = fh.metadata()?.len(); | ||||||
|  |     let mut t_last = Instant::now(); | ||||||
|  |     let mut reader = BufReader::new(fh); | ||||||
|  |     let mut state = PreprocessState { | ||||||
|  |         file: path.to_str().unwrap().to_owned(), | ||||||
|  |         total: total_size, | ||||||
|  |         done: 0, | ||||||
|  |         count: 0, | ||||||
|  |         message: format!("Processing {} ...", path.to_str().unwrap()), | ||||||
|  |     }; | ||||||
|  |     println!("Loading {} ...", path.to_str().unwrap()); | ||||||
|  |     while let Ok(n) = reader.read_line(&mut buffer) { | ||||||
|  |         if n == 0 { | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         buffer = buffer.trim_end().trim_end_matches(|c| c == ',').to_string(); | ||||||
|  |         if !buffer.is_empty() { | ||||||
|  |             func(&buffer); | ||||||
|  |         } | ||||||
|  |         let pos = reader.seek(SeekFrom::Current(0)).unwrap(); | ||||||
|  |         state.done = pos; | ||||||
|  |         state.count += 1; | ||||||
|  |         if t_last.elapsed().as_millis() > 100 { | ||||||
|  |             callback(&state)?; | ||||||
|  |             t_last = Instant::now(); | ||||||
|  |         } | ||||||
|  |         buffer.clear(); | ||||||
|  |     } | ||||||
|  |     Ok(()) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn process_systems( | ||||||
|  |     path: &PathBuf, | ||||||
|  |     callback: &dyn Fn(&PreprocessState) -> PyResult<PyObject>, | ||||||
|  | ) -> FnvHashMap<i32, System> { | ||||||
|  |     let mut ret = FnvHashMap::default(); | ||||||
|  |     process( | ||||||
|  |         path, | ||||||
|  |         &mut |line| { | ||||||
|  |             let sys_res: Result<System> = serde_json::from_str(&line); | ||||||
|  |             if let Ok(sys) = sys_res { | ||||||
|  |                 ret.insert(sys.id, sys); | ||||||
|  |             } else { | ||||||
|  |                 eprintln!("\nError parsing: {}\n\t{:?}\n", line, sys_res.unwrap_err()); | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         callback, | ||||||
|  |     ) | ||||||
|  |     .unwrap(); | ||||||
|  |     ret | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | pub fn build_index(path: &PathBuf) -> std::io::Result<()> { | ||||||
|  |     let mut wtr = BufWriter::new(File::create(path.with_extension("idx"))?); | ||||||
|  |     let mut idx: Vec<u64> = Vec::new(); | ||||||
|  |     let mut records = (csv::Reader::from_path(path)?).into_deserialize::<SystemSerde>(); | ||||||
|  |     loop { | ||||||
|  |         idx.push(records.reader().position().byte()); | ||||||
|  |         if records.next().is_none() { | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     bincode::serialize_into(&mut wtr, &idx).unwrap(); | ||||||
|  |     Ok(()) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn process_bodies( | ||||||
|  |     path: &PathBuf, | ||||||
|  |     out_path: &PathBuf, | ||||||
|  |     systems: &mut FnvHashMap<i32, System>, | ||||||
|  |     callback: &dyn Fn(&PreprocessState) -> PyResult<PyObject>, | ||||||
|  | ) -> std::io::Result<()> { | ||||||
|  |     println!( | ||||||
|  |         "Processing {} into {} ...", | ||||||
|  |         path.to_str().unwrap(), | ||||||
|  |         out_path.to_str().unwrap(), | ||||||
|  |     ); | ||||||
|  |     let mut n: u32 = 0; | ||||||
|  |     let mut wtr = csv::Writer::from_path(out_path)?; | ||||||
|  |     process( | ||||||
|  |         path, | ||||||
|  |         &mut |line| { | ||||||
|  |             if !line.contains("Star") { | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |             let body_res: Result<Body> = serde_json::from_str(&line); | ||||||
|  |             if let Ok(body) = body_res { | ||||||
|  |                 if !body.body_type.contains("Star") { | ||||||
|  |                     return; | ||||||
|  |                 } | ||||||
|  |                 if let Some(sys) = systems.get(&body.systemId) { | ||||||
|  |                     let sub_type = body.subType; | ||||||
|  |                     let mult = get_mult(&sub_type); | ||||||
|  |                     let sys_name = sys.name.clone(); | ||||||
|  |                     let rec = SystemSerde { | ||||||
|  |                         id: n, | ||||||
|  |                         star_type: sub_type, | ||||||
|  |                         system: sys_name, | ||||||
|  |                         body: body.name, | ||||||
|  |                         mult, | ||||||
|  |                         distance: body.distance, | ||||||
|  |                         x: sys.coords.x, | ||||||
|  |                         y: sys.coords.y, | ||||||
|  |                         z: sys.coords.z, | ||||||
|  |                     }; | ||||||
|  |                     wtr.serialize(rec).unwrap(); | ||||||
|  |                     n += 1; | ||||||
|  |                 }; | ||||||
|  |             } else { | ||||||
|  |                 eprintln!("\nError parsing: {}\n\t{:?}\n", line, body_res.unwrap_err()); | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         callback, | ||||||
|  |     ) | ||||||
|  |     .unwrap(); | ||||||
|  |     println!("Total Systems: {}", n); | ||||||
|  |     systems.clear(); | ||||||
|  |     Ok(()) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | pub fn preprocess_files( | ||||||
|  |     bodies: &PathBuf, | ||||||
|  |     systems: &PathBuf, | ||||||
|  |     out_path: &PathBuf, | ||||||
|  |     callback: &dyn Fn(&PreprocessState) -> PyResult<PyObject>, | ||||||
|  | ) -> std::io::Result<()> { | ||||||
|  |     if !out_path.exists() { | ||||||
|  |         let mut systems = process_systems(systems, &callback); | ||||||
|  |         process_bodies(bodies, out_path, &mut systems, &callback)?; | ||||||
|  |     } else { | ||||||
|  |         println!( | ||||||
|  |             "File '{}' exists, not overwriting it", | ||||||
|  |             out_path.to_str().unwrap() | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  |     println!("Building index..."); | ||||||
|  |     println!("Index result: {:?}", build_index(&out_path)); | ||||||
|  |     Ok(()) | ||||||
|  | } | ||||||
							
								
								
									
										169
									
								
								rust/src/journal.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								rust/src/journal.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,169 @@ | ||||||
|  | use crate::common::get_fsd_info; | ||||||
|  | use crate::ship::Ship; | ||||||
|  | 
 | ||||||
|  | use regex::Regex; | ||||||
|  | use serde::Deserialize; | ||||||
|  | use std::collections::HashMap; | ||||||
|  | 
 | ||||||
|  | #[derive(Clone, Debug, PartialEq, Deserialize)] | ||||||
|  | pub struct Event { | ||||||
|  |     #[serde(flatten)] | ||||||
|  |     pub event: EventData, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[serde(tag = "event")] | ||||||
|  | #[derive(Clone, Debug, PartialEq, Deserialize)] | ||||||
|  | pub enum EventData { | ||||||
|  |     Loadout(Loadout), | ||||||
|  |     #[serde(other)] | ||||||
|  |     Unknown, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[serde(rename_all = "PascalCase")] | ||||||
|  | #[derive(Clone, Debug, PartialEq, Deserialize)] | ||||||
|  | pub struct Modifier { | ||||||
|  |     label: String, | ||||||
|  |     value: f32, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[serde(rename_all = "PascalCase")] | ||||||
|  | #[derive(Clone, Debug, PartialEq, Deserialize)] | ||||||
|  | pub struct Engineering { | ||||||
|  |     modifiers: Vec<Modifier>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Clone, Debug, PartialEq, Deserialize)] | ||||||
|  | #[serde(rename_all = "PascalCase")] | ||||||
|  | pub struct Module { | ||||||
|  |     engineering: Option<Engineering>, | ||||||
|  |     item: String, | ||||||
|  |     slot: String, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Clone, Debug, PartialEq, Deserialize)] | ||||||
|  | #[serde(rename_all = "PascalCase")] | ||||||
|  | pub struct FuelCapacity { | ||||||
|  |     main: f32, | ||||||
|  |     reserve: f32, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Clone, Debug, PartialEq, Deserialize)] | ||||||
|  | #[serde(rename_all = "PascalCase")] | ||||||
|  | pub struct Loadout { | ||||||
|  |     #[serde(rename = "timestamp")] | ||||||
|  |     timestamp: String, | ||||||
|  |     ship: String, | ||||||
|  |     ship_name: String, | ||||||
|  |     ship_ident: String, | ||||||
|  |     fuel_capacity: FuelCapacity, | ||||||
|  |     unladen_mass: f32, | ||||||
|  |     modules: Vec<Module>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Engineering { | ||||||
|  |     fn to_hashmap(&self) -> HashMap<String, f32> { | ||||||
|  |         let mut h = HashMap::new(); | ||||||
|  |         for v in &self.modifiers { | ||||||
|  |             h.insert(v.label.clone(), v.value); | ||||||
|  |         } | ||||||
|  |         return h; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Loadout { | ||||||
|  |     fn get_booster(&self) -> Option<usize> { | ||||||
|  |         self.modules | ||||||
|  |             .iter() | ||||||
|  |             .cloned() | ||||||
|  |             .filter_map(|m| { | ||||||
|  |                 let Module { item, .. } = m; | ||||||
|  |                 if item.starts_with("int_guardianfsdbooster") { | ||||||
|  |                     return item | ||||||
|  |                         .chars() | ||||||
|  |                         .last() | ||||||
|  |                         .unwrap() | ||||||
|  |                         .to_digit(10) | ||||||
|  |                         .map(|v| v as usize); | ||||||
|  |                 } | ||||||
|  |                 return None; | ||||||
|  |             }) | ||||||
|  |             .next() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn get_fsd(&self) -> Option<(String, Option<Engineering>)> { | ||||||
|  |         self.modules | ||||||
|  |             .iter() | ||||||
|  |             .cloned() | ||||||
|  |             .filter_map(|m| { | ||||||
|  |                 let Module { | ||||||
|  |                     slot, | ||||||
|  |                     engineering, | ||||||
|  |                     item, | ||||||
|  |                 } = m; | ||||||
|  |                 if slot == "FrameShiftDrive" { | ||||||
|  |                     return Some((item, engineering)); | ||||||
|  |                 } | ||||||
|  |                 return None; | ||||||
|  |             }) | ||||||
|  |             .next() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn try_into_ship(self) -> Result<Ship, String> { | ||||||
|  |         let fsd = self.get_fsd().ok_or("No FSD found!")?; | ||||||
|  |         let booster = self.get_booster().unwrap_or(0); | ||||||
|  |         let fsd_type = Regex::new(r"^int_hyperdrive_size(\d+)_class(\d+)$") | ||||||
|  |             .unwrap() | ||||||
|  |             .captures(&fsd.0); | ||||||
|  |         let fsd_type: (usize, usize) = fsd_type | ||||||
|  |             .map(|m| { | ||||||
|  |                 let s = m.get(1)?.as_str().to_owned().parse().ok()?; | ||||||
|  |                 let c = m.get(2)?.as_str().to_owned().parse().ok()?; | ||||||
|  |                 return Some((c, s)); | ||||||
|  |             }) | ||||||
|  |             .flatten() | ||||||
|  |             .ok_or(format!("Invalid FSD found: {}", &fsd.0))?; | ||||||
|  |         let eng = fsd | ||||||
|  |             .1 | ||||||
|  |             .map(|eng| eng.to_hashmap()) | ||||||
|  |             .unwrap_or_else(HashMap::new); | ||||||
|  |         let mut fsd_info = get_fsd_info(fsd_type.0, fsd_type.1)?; | ||||||
|  |         let fsd_type = ( | ||||||
|  |             "_EDCBA" | ||||||
|  |                 .chars() | ||||||
|  |                 .nth(fsd_type.0) | ||||||
|  |                 .ok_or(format!("Invalid FSD found: {}", &fsd.0))?, | ||||||
|  |             fsd_type.1 as u8, | ||||||
|  |         ); | ||||||
|  |         fsd_info.extend(eng); | ||||||
|  |         let max_fuel = fsd_info | ||||||
|  |             .get("MaxFuel") | ||||||
|  |             .ok_or(format!("Unknwon MaxFuelPerJump for FSD: {}", &fsd.0))?; | ||||||
|  |         let opt_mass = fsd_info | ||||||
|  |             .get("FSDOptimalMass") | ||||||
|  |             .ok_or(format!("Unknwon FSDOptimalMass for FSD: {}", &fsd.0))?; | ||||||
|  |         return Ship::new( | ||||||
|  |             self.ship_name, | ||||||
|  |             self.ship_ident, | ||||||
|  |             self.ship, | ||||||
|  |             self.unladen_mass, | ||||||
|  |             self.fuel_capacity.main, | ||||||
|  |             self.fuel_capacity.main, | ||||||
|  |             fsd_type, | ||||||
|  |             *max_fuel, | ||||||
|  |             *opt_mass, | ||||||
|  |             booster, | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Event { | ||||||
|  |     pub fn get_loadout(self) -> Option<Loadout> { | ||||||
|  |         if let Event { | ||||||
|  |             event: EventData::Loadout(loadout), | ||||||
|  |         } = self | ||||||
|  |         { | ||||||
|  |             return Some(loadout); | ||||||
|  |         } | ||||||
|  |         None | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										271
									
								
								rust/src/ship.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										271
									
								
								rust/src/ship.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,271 @@ | ||||||
|  | use crate::common::get_fsd_booster_info; | ||||||
|  | use crate::journal::*; | ||||||
|  | use pyo3::conversion::ToPyObject; | ||||||
|  | use pyo3::prelude::*; | ||||||
|  | use pyo3::types::PyDict; | ||||||
|  | use regex::Regex; | ||||||
|  | use serde::{Deserialize, Serialize}; | ||||||
|  | use std::collections::HashMap; | ||||||
|  | use std::fs::File; | ||||||
|  | use std::io::{BufRead, BufReader}; | ||||||
|  | use std::path::PathBuf; | ||||||
|  | 
 | ||||||
|  | #[derive(Debug, Clone, Serialize, Deserialize)] | ||||||
|  | pub struct FSD { | ||||||
|  |     pub rating_val: f32, | ||||||
|  |     pub class_val: f32, | ||||||
|  |     pub opt_mass: f32, | ||||||
|  |     pub max_fuel: f32, | ||||||
|  |     pub boost: f32, | ||||||
|  |     pub guardian_booster: f32, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Debug, Clone, Serialize, Deserialize)] | ||||||
|  | pub struct Ship { | ||||||
|  |     pub name: String, | ||||||
|  |     pub ident: String, | ||||||
|  |     pub ship_type: String, | ||||||
|  |     pub base_mass: f32, | ||||||
|  |     pub fuel_mass: f32, | ||||||
|  |     pub fuel_capacity: f32, | ||||||
|  |     pub fsd: FSD, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Ship { | ||||||
|  |     pub fn new( | ||||||
|  |         name: String, | ||||||
|  |         ident: String, | ||||||
|  |         ship_type: String, | ||||||
|  |         base_mass: f32, | ||||||
|  |         fuel_mass: f32, | ||||||
|  |         fuel_capacity: f32, | ||||||
|  |         fsd_type: (char, u8), | ||||||
|  |         max_fuel: f32, | ||||||
|  |         opt_mass: f32, | ||||||
|  |         guardian_booster: usize, | ||||||
|  |     ) -> Result<Self, String> { | ||||||
|  |         let rating_val: f32 = match fsd_type.0 { | ||||||
|  |             'A' => 12.0, | ||||||
|  |             'B' => 10.0, | ||||||
|  |             'C' => 8.0, | ||||||
|  |             'D' => 10.0, | ||||||
|  |             'E' => 11.0, | ||||||
|  |             err => { | ||||||
|  |                 return Err(format!("Invalid rating: {}", err)); | ||||||
|  |             } | ||||||
|  |         }; | ||||||
|  |         if fsd_type.1 < 2 || fsd_type.1 > 8 { | ||||||
|  |             return Err(format!("Invalid class: {}", fsd_type.1)); | ||||||
|  |         }; | ||||||
|  |         
 | ||||||
|  |         if guardian_booster!=0 { | ||||||
|  |             return Err("Guardian booster not yet implemented!".to_owned()) | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         let ret = Self { | ||||||
|  |             name, | ||||||
|  |             ident, | ||||||
|  |             ship_type, | ||||||
|  |             fuel_capacity, | ||||||
|  |             fuel_mass, | ||||||
|  |             base_mass, | ||||||
|  |             fsd: FSD { | ||||||
|  |                 rating_val, | ||||||
|  |                 class_val: 2.0 + (0.15 * ((fsd_type.1 - 2) as f32)), | ||||||
|  |                 opt_mass, | ||||||
|  |                 max_fuel, | ||||||
|  |                 boost: 1.0, | ||||||
|  |                 guardian_booster: get_fsd_booster_info(guardian_booster)?, | ||||||
|  |             }, | ||||||
|  |         }; | ||||||
|  |         Ok(ret) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn new_from_json(data: &str) -> Result<Self, String> { | ||||||
|  |         match serde_json::from_str::<Event>(&data) { | ||||||
|  |             Ok(Event { | ||||||
|  |                 event: EventData::Unknown, | ||||||
|  |             }) => { | ||||||
|  |                 return Err(format!("Invalid Loadout event: {}", data)); | ||||||
|  |             } | ||||||
|  |             Ok(ev) => { | ||||||
|  |                 if let Some(loadout) = ev.get_loadout() { | ||||||
|  |                     return loadout.try_into_ship(); | ||||||
|  |                 } else { | ||||||
|  |                     return Err(format!("Invalid Loadout event: {}", data)); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             Err(msg) => { | ||||||
|  |                 return Err(format!("{}", msg)); | ||||||
|  |             } | ||||||
|  |         }; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn new_from_journal() -> Result<HashMap<String, Self>, String> { | ||||||
|  |         let mut ret = HashMap::new(); | ||||||
|  |         let re = Regex::new(r"^Journal\.\d{12}\.\d{2}\.log$").unwrap(); | ||||||
|  |         let mut journals: Vec<PathBuf> = Vec::new(); | ||||||
|  |         let mut userprofile = PathBuf::from(std::env::var("Userprofile").unwrap()); | ||||||
|  |         userprofile.push("Saved Games"); | ||||||
|  |         userprofile.push("Frontier Developments"); | ||||||
|  |         userprofile.push("Elite Dangerous"); | ||||||
|  |         if let Ok(iter) = userprofile.read_dir() { | ||||||
|  |             for entry in iter { | ||||||
|  |                 if let Ok(entry) = entry { | ||||||
|  |                     if re.is_match(&entry.file_name().to_string_lossy()) { | ||||||
|  |                         journals.push(entry.path()); | ||||||
|  |                     }; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         journals.sort(); | ||||||
|  | 
 | ||||||
|  |         for journal in &journals { | ||||||
|  |             let mut fh = BufReader::new(File::open(journal).unwrap()); | ||||||
|  |             let mut line = String::new(); | ||||||
|  |             while let Ok(n) = fh.read_line(&mut line) { | ||||||
|  |                 if n == 0 { | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |                 match serde_json::from_str::<Event>(&line) { | ||||||
|  |                     Ok(Event { | ||||||
|  |                         event: EventData::Unknown, | ||||||
|  |                     }) => {} | ||||||
|  |                     Ok(ev) => { | ||||||
|  |                         if let Some(loadout) = ev.get_loadout() { | ||||||
|  |                             let mut ship = loadout.try_into_ship()?; | ||||||
|  |                             if ship.name == "" { | ||||||
|  |                                 ship.name = "<NO NAME>".to_owned(); | ||||||
|  |                             } | ||||||
|  |                             let key = format!( | ||||||
|  |                                 "[{}] {} ({})", | ||||||
|  |                                 ship.ident, | ||||||
|  |                                 ship.name, | ||||||
|  |                                 ship.ship_type.to_ascii_lowercase() | ||||||
|  |                             ); | ||||||
|  |                             ret.insert(key, ship); | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                     Err(_) => {} | ||||||
|  |                 }; | ||||||
|  |                 line.clear(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         if ret.is_empty() { | ||||||
|  |             return Err("No ships loaded!".to_owned()); | ||||||
|  |         } | ||||||
|  |         return Ok(ret); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn can_jump(&self, d: f32) -> bool { | ||||||
|  |         self.fuel_cost(d) <= self.fsd.max_fuel.min(self.fuel_mass) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn boost(&mut self, boost: f32) { | ||||||
|  |         self.fsd.boost = boost; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn refuel(&mut self) { | ||||||
|  |         self.fuel_mass = self.fuel_capacity; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn make_jump(&mut self, d: f32) -> Option<f32> { | ||||||
|  |         let cost = self.fuel_cost(d); | ||||||
|  |         if cost > self.fsd.max_fuel.min(self.fuel_mass) { | ||||||
|  |             return None; | ||||||
|  |         } | ||||||
|  |         self.fuel_mass -= cost; | ||||||
|  |         self.fsd.boost = 1.0; | ||||||
|  |         Some(cost) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn jump_range(&self, fuel: f32, booster: bool) -> f32 { | ||||||
|  |         let mass = self.base_mass + fuel; | ||||||
|  |         let mut fuel = self.fsd.max_fuel.min(fuel); | ||||||
|  |         if booster { | ||||||
|  |             fuel *= self.boost_fuel_mult(); | ||||||
|  |         } | ||||||
|  |         let opt_mass = self.fsd.opt_mass * self.fsd.boost; | ||||||
|  |         return opt_mass * ((1000.0 * fuel) / self.fsd.rating_val).powf(self.fsd.class_val.recip()) | ||||||
|  |             / mass; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn max_range(&self) -> f32 { | ||||||
|  |         return self.jump_range(self.fsd.max_fuel, true); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn range(&self) -> f32 { | ||||||
|  |         return self.jump_range(self.fuel_mass, true); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn boost_fuel_mult(&self) -> f32 { | ||||||
|  |         if self.fsd.guardian_booster == 0.0 { | ||||||
|  |             return 1.0; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         let base_range = self.jump_range(self.fuel_mass, false); // current range without booster
 | ||||||
|  | 
 | ||||||
|  |         return ((base_range + self.fsd.guardian_booster) / base_range).powf(self.fsd.class_val); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn fuel_cost(&self, d: f32) -> f32 { | ||||||
|  |         if d == 0.0 { | ||||||
|  |             return 0.0; | ||||||
|  |         } | ||||||
|  |         let mass = self.base_mass + self.fuel_mass; | ||||||
|  |         let opt_mass = self.fsd.opt_mass * self.fsd.boost; | ||||||
|  |         let base_cost = (d * mass) / opt_mass; | ||||||
|  |         return (self.fsd.rating_val * 0.001 * base_cost.powf(self.fsd.class_val)) | ||||||
|  |             / self.boost_fuel_mult(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* | ||||||
|  | #[derive(Debug,Clone, Serialize, Deserialize, ToPyObject)] | ||||||
|  | pub struct FSD { | ||||||
|  |     pub rating_val: f32, | ||||||
|  |     pub class_val: f32, | ||||||
|  |     pub opt_mass: f32, | ||||||
|  |     pub max_fuel: f32, | ||||||
|  |     pub boost: f32, | ||||||
|  |     pub guardian_booster: f32, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Debug,Clone, Serialize, Deserialize, ToPyObject)] | ||||||
|  | pub struct Ship { | ||||||
|  |     pub name: String, | ||||||
|  |     pub ident: String, | ||||||
|  |     pub ship_type: String, | ||||||
|  |     pub base_mass: f32, | ||||||
|  |     pub fuel_mass: f32, | ||||||
|  |     pub fuel_capacity: f32, | ||||||
|  |     pub fsd: FSD, | ||||||
|  | } | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | impl FSD { | ||||||
|  |     pub fn to_object(&self, py: Python) -> PyResult<PyObject> { | ||||||
|  |         let elem = PyDict::new(py); | ||||||
|  |         elem.set_item("rating_val", self.rating_val)?; | ||||||
|  |         elem.set_item("class_val", self.class_val)?; | ||||||
|  |         elem.set_item("opt_mass", self.opt_mass)?; | ||||||
|  |         elem.set_item("max_fuel", self.max_fuel)?; | ||||||
|  |         elem.set_item("boost", self.boost)?; | ||||||
|  |         elem.set_item("guardian_booster", self.guardian_booster)?; | ||||||
|  |         Ok(elem.to_object(py)) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Ship { | ||||||
|  |     pub fn to_object(&self, py: Python) -> PyResult<PyObject> { | ||||||
|  |         let elem = PyDict::new(py); | ||||||
|  |         elem.set_item("name", self.name.clone())?; | ||||||
|  |         elem.set_item("ident", self.ident.clone())?; | ||||||
|  |         elem.set_item("ship_type", self.ship_type.clone())?; | ||||||
|  |         elem.set_item("base_mass", self.base_mass)?; | ||||||
|  |         elem.set_item("fuel_mass", self.fuel_mass)?; | ||||||
|  |         elem.set_item("fuel_capacity", self.fuel_capacity)?; | ||||||
|  |         elem.set_item("fsd", self.fsd.to_object(py)?)?; | ||||||
|  |         Ok(elem.to_object(py)) | ||||||
|  |     } | ||||||
|  | } | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue