Skip to content

Instantly share code, notes, and snippets.

@4Kaylum
Last active November 2, 2020 22:36
Show Gist options
  • Save 4Kaylum/cba60a63f3a26d24bb428e1595b1bac5 to your computer and use it in GitHub Desktop.
Save 4Kaylum/cba60a63f3a26d24bb428e1595b1bac5 to your computer and use it in GitHub Desktop.
Some kind of perks handler code for a thing I thought I would use
class flag_value(object):
"""
Define a flag value for the bot
"""
def __init__(self, func):
v = func(None)
flag_value, bit_offset = v
self.flag = flag_value << bit_offset
self.bit_offset = bit_offset
self.__doc__ = func.__doc__
def __get__(self, instance, owner):
if instance is None:
return self
return instance._has_flag(self.flag) >> self.bit_offset
def __set__(self, instance, value:int):
if value > (self.flag >> self.bit_offset):
raise ValueError(f"Can't set flag to a value higher than {self.flag >> self.bit_offset}")
if value < 0:
raise ValueError("Can't set flag to a value lower than 0")
instance._set_flag(self.flag, int(value) << self.bit_offset)
def fill_with_flags(cls):
"""
Fill the decorated class with values for each of the flags
"""
cls.VALID_FLAGS = {
name: value.flag
for name, value in cls.__dict__.items()
if isinstance(value, flag_value)
}
return cls
class BaseFlags(object):
def __init__(self, value:int=0):
self.value = value
def __or__(self, other):
"""
The bitwise or operator to add together the max values in each of the perm flags
"""
# Make sure it's the right type
if type(self) != type(other):
raise TypeError
if sorted(list(self.VALID_FLAGS)) != sorted(list(other.VALID_FLAGS)):
raise TypeError
# Add together the max flags
value = 0
for flag in self.VALID_FLAGS:
added_value = max([getattr(self, flag), getattr(other, flag)])
flag_object = getattr(self.__class__, flag)
value |= added_value << flag_object.bit_offset
return self.__class__(value)
def __repr__(self):
value_strings = [f"{i}={getattr(self, i)}" for i in self.VALID_FLAGS]
return f"<BaseFlags {' '.join(value_strings)}>"
@property
def all_permissions(self):
all_permissions = 0
for i in self.VALID_FLAGS.values():
all_permissions |= i
return all_permissions
def update(self, **kwargs):
for i, o in kwargs.items():
setattr(self, i, o)
def _has_flag(self, value):
return self.value & value
def _set_flag(self, flag_value, flag_bool):
self.value = self.value & (self.all_permissions ^ flag_value) | (flag_bool & flag_value)
def create_flags_class(perk_names_and_widths) -> BaseFlags:
"""
Creates a BaseFlags object for your given perk names in ascending order.
"""
@fill_with_flags
class CreatedFlags(BaseFlags):
pass
offset = 0
for pair in perk_names_and_widths:
try:
name, width = pair
except ValueError:
name, width = pair, 1
func = lambda x: ((2 ** width) - 1, offset,)
setattr(CreatedFlags, name, flag_value(func))
CreatedFlags.VALID_FLAGS[name] = ((2 ** width) - 1) << offset
offset += width
return CreatedFlags
if __name__ == "__main__":
PerkHandler = create_flags_class([
('max_children', 5,),
('max_partners', 5,),
('can_run_stupidtree', 1,),
('can_run_disownall', 1,),
('can_run_divorceall', 1,),
('tree_command_cooldown', 1,),
])
user_perks = PerkHandler()
user_perks.max_children = 30
user_perks.can_run_stupidtree = True # or 1, that works too
# store_in_database(user_perks.value)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment