@@ -24,22 +24,27 @@ class Option:
2424 ignore_value : bool
2525 values : list [str ]
2626 case_sensitive : bool
27+ scope : str
2728
28- def __init__ (self , key , values = [], ignore_value = False , case_sensitive = True ):
29+ def __init__ (self , key , values = [], ignore_value = False , case_sensitive = True , scope = 'player' ):
2930 self .key = key
3031 self .values = values
3132 self .ignore_value = ignore_value
3233 self .case_sensitive = case_sensitive
34+ self .scope = scope
3335
3436 def __eq__ (self , other : ParsedOption ):
35- if self .key != other .key :
36- return False
37- if self .ignore_value :
38- return True
39- if self .case_sensitive :
40- return other .value in self .values
41- else :
42- return other .value .lower () in self .values
37+ if isinstance (other , ParsedOption ):
38+ if self .key != other .key :
39+ return False
40+ if self .ignore_value :
41+ return True
42+ if self .case_sensitive :
43+ return other .value in self .values
44+ else :
45+ return other .value .lower () in self .values
46+ assert False
47+ return False
4348
4449class Options :
4550 options : list [Option ]
@@ -52,6 +57,10 @@ def __init__(self, *options):
5257 def __contains__ (self , other ):
5358 return other in self .options
5459
60+ def __iter__ (self ):
61+ for option in self .options :
62+ yield option
63+
5564# class (handled separately as value depends on filename)
5665SIMC_OPTIONS = Options (
5766 Option ('level' , ['90' ]),
@@ -96,14 +105,14 @@ def __contains__(self, other):
96105 Option ('warlock.default_pet' , ['sayaad' , 'succubus' , 'incubus' , 'felguard' ]),
97106)
98107HEADER_OPTIONS = Options (
99- Option ('desired_targets' , ignore_value = True ),
100- Option ('fight_style' , ['patchwerk' , 'castingpatchwerk' , 'dungeonslice' ]),
101- Option ('source' , ['default' ]),
102- Option ('potion' , ignore_value = True ),
103- Option ('flask' , ignore_value = True ),
104- Option ('food' , ignore_value = True ),
105- Option ('augmentation' , ignore_value = True ),
106- Option ('temporary_enchant' , ignore_value = True ),
108+ Option ('desired_targets' , ignore_value = True , scope = 'sim' ),
109+ Option ('fight_style' , ['patchwerk' , 'castingpatchwerk' , 'dungeonslice' ], scope = 'sim' ),
110+ Option ('source' , ['default' ], scope = 'player' ),
111+ Option ('potion' , ignore_value = True , scope = 'player' ),
112+ Option ('flask' , ignore_value = True , scope = 'player' ),
113+ Option ('food' , ignore_value = True , scope = 'player' ),
114+ Option ('augmentation' , ignore_value = True , scope = 'player' ),
115+ Option ('temporary_enchant' , ignore_value = True , scope = 'player' ),
107116)
108117
109118class Profile :
@@ -125,21 +134,26 @@ def validate(self):
125134 # <class_name>=<class_name>_<spec_name><unnamed>
126135 if not self .path .exists ():
127136 print (f'Path { self } does not exist.' )
128- return
137+ return False
129138
130139 class_name , trailing_fragment , spec_name = self .path_parts ()
140+ if not class_name and not trailing_fragment and not spec_name :
141+ return False
142+
131143 if class_name not in SPEC_NAMES .keys ():
132144 print (f'Profile { self } is not in a `profiles/<class>/` directory.' )
133- return
145+ return False
134146
135147 if spec_name not in SPEC_NAMES [class_name ]:
136- print (f'Profile { self } does not contain a valid specialization name. Try one of { ", " .join (SPEC_NAMES [class_name ])} .' )
137- return
148+ print (f'Profile { self } does not contain a valid specialization name. It should include one of { ", " .join (SPEC_NAMES [class_name ])} .' )
149+ return False
138150
139151 # python has no way to nicely test if a string contains only printable ascii characters :)
140152 if not all ((c in 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_' for c in trailing_fragment [len (spec_name ):])):
141153 print (f'Profile { self } trailing fragment { trailing_fragment [len (spec_name ):]} is not alphanumeric.' )
142- return
154+ return False
155+
156+ return True
143157
144158 def expected_name (self ):
145159 class_name , trailing_fragment , _ = self .path_parts ()
@@ -149,7 +163,7 @@ def path_parts(self):
149163 path_parts = PurePath .relative_to (self .path .resolve (), Path (__file__ ).resolve (), walk_up = True ).parts [2 :]
150164 if path_parts [0 ] != 'profiles' :
151165 print (f'Profile { self } is not in the `profiles/` directory.' )
152- return
166+ return False , False , False
153167
154168 trailing_fragment = path_parts [2 ].split ('.' )[:- 1 ][0 ]
155169 return path_parts [1 ], trailing_fragment , trailing_fragment .split ('_' )[0 ]
@@ -192,6 +206,9 @@ def __str__(self):
192206 return f'Invalid Option { self .key } '
193207 return f'{ self .key } { self .operator } { self .value } '
194208
209+ def scope (self , options : Options ):
210+ return next ((o for o in options if o == self )).scope
211+
195212 def validate_class (self , profile : Profile ):
196213 class_name , _ , _ = profile .path_parts ()
197214 return self .parsed and self .key == class_name
0 commit comments