2020
2121_DELAY_SUFFIX_RE = re .compile (r'-(\d+|[pP])$' )
2222_SIMPLIFY_CN_RE = re .compile (r'^[0-9]*[ -]*([A-Z][0-9]+)' )
23+ _TEXTUAL_DELAY_VALUE_MAP = {
24+ 'S' : 6.0 ,
25+ 'M' : 10.0 ,
26+ 'L' : 14.0 ,
27+ }
2328
2429
2530def ensure_curve_starts_at_zero (points ):
@@ -37,6 +42,28 @@ def curve_signature(points):
3742 return tuple ((round (time_s , 6 ), round (thrust_n , 6 )) for time_s , thrust_n in points )
3843
3944
45+ def normalize_delay_token (token ):
46+ """Canonicalize known textual delay tokens."""
47+ normalized = str (token ).strip ()
48+ upper = normalized .upper ()
49+ if upper in ('P' , 'PLUGGED' , 'NE' ):
50+ return 'P'
51+ return upper
52+
53+
54+ def delay_token_to_seconds (token ):
55+ """Map known textual delay tokens to representative numeric values."""
56+ normalized = normalize_delay_token (token )
57+ if normalized in _TEXTUAL_DELAY_VALUE_MAP :
58+ return _TEXTUAL_DELAY_VALUE_MAP [normalized ]
59+ return float (normalized )
60+
61+
62+ def normalize_delay_field (raw_value ):
63+ """Convert a raw delay field into canonical comma-separated form."""
64+ return merge_delays (raw_value )
65+
66+
4067def parse_delays (delays ):
4168 """Normalize delay representations into a unique ordered list."""
4269 if delays is None :
@@ -59,7 +86,7 @@ def parse_delays(delays):
5986 token = part .strip ()
6087 if not token :
6188 continue
62- normalized = 'P' if token . upper () == 'P' else token
89+ normalized = normalize_delay_token ( token )
6390 if normalized not in seen :
6491 tokens .append (normalized )
6592 seen .add (normalized )
@@ -80,13 +107,16 @@ def merge_delays(*delay_values):
80107 if not merged :
81108 return None
82109
83- numeric = sorted (
84- (token for token in merged if token != 'P' ),
85- key = lambda token : (float (token ), token ),
86- )
87- if 'P' in seen :
88- numeric .append ('P' )
89- return ',' .join (numeric )
110+ numeric = []
111+ textual = []
112+ for token in merged :
113+ try :
114+ numeric .append ((delay_token_to_seconds (token ), token ))
115+ except ValueError :
116+ textual .append (token )
117+
118+ ordered_numeric = [token for _ , token in sorted (numeric , key = lambda item : (item [0 ], item [1 ]))]
119+ return ',' .join (ordered_numeric + textual )
90120
91121
92122def normalize_designation (designation ):
@@ -416,13 +446,7 @@ def parse_rasp(filepath):
416446
417447 try :
418448 delays_raw = parts [3 ]
419- if delays_raw .upper () == 'P' :
420- delays = 'P'
421- elif delays_raw .strip () == '' :
422- delays = None
423- else :
424- delay_parts = [d .strip () for d in re .split (r'[-,]+' , delays_raw ) if d .strip ()]
425- delays = ',' .join (delay_parts ) if delay_parts else None
449+ delays = normalize_delay_field (delays_raw )
426450
427451 # RASP weights are in kg, convert to grams for DB consistency
428452 prop_weight_kg = float (parts [4 ])
@@ -490,13 +514,7 @@ def parse_rse(filepath):
490514
491515 # Extract Metadata
492516 delays_raw = engine .get ('delays' , '' )
493- if delays_raw .upper () == 'P' :
494- delays = 'P'
495- elif not delays_raw .strip ():
496- delays = None
497- else :
498- delay_parts = [d .strip () for d in re .split (r'[-,]+' , delays_raw ) if d .strip ()]
499- delays = ',' .join (delay_parts ) if delay_parts else None
517+ delays = normalize_delay_field (delays_raw )
500518
501519 designation = engine .get ('code' , 'Unknown' )
502520 # Extract common name from designation (strip propellant suffix letters)
@@ -643,14 +661,7 @@ def try_header(parts):
643661 return None
644662 try :
645663 raw_delays = parts [3 ]
646- if raw_delays .upper () == 'P' :
647- delays = 'P'
648- elif raw_delays .strip () == '' :
649- delays = None
650- else :
651- # Normalize dash-separated to comma-separated
652- delay_parts = [d .strip () for d in re .split (r'[-,]+' , raw_delays ) if d .strip ()]
653- delays = ',' .join (delay_parts ) if delay_parts else None
664+ delays = normalize_delay_field (raw_delays )
654665 return {
655666 'common_name' : parts [0 ], 'designation' : parts [0 ],
656667 'diameter' : float (parts [1 ]), 'length' : float (parts [2 ]),
@@ -737,13 +748,7 @@ def parse_rse_all(filepath):
737748 tree = ET .parse (filepath )
738749 for engine in tree .getroot ().findall (".//engine" ):
739750 raw_delays = engine .get ('delays' , '' )
740- if raw_delays .upper () == 'P' :
741- delays = 'P'
742- elif raw_delays .strip () == '' :
743- delays = None
744- else :
745- delay_parts = [d .strip () for d in re .split (r'[-,]+' , raw_delays ) if d .strip ()]
746- delays = ',' .join (delay_parts ) if delay_parts else None
751+ delays = normalize_delay_field (raw_delays )
747752 designation = engine .get ('code' , 'Unknown' )
748753 cn_match = re .match (r'^([A-Z][0-9]+)' , designation )
749754 meta = {
0 commit comments