Skip to content

Instantly share code, notes, and snippets.

@Pinacolada64
Last active May 14, 2024 13:38
Show Gist options
  • Save Pinacolada64/299ec94b96c6839cc7a643f4079e740c to your computer and use it in GitHub Desktop.
Save Pinacolada64/299ec94b96c6839cc7a643f4079e740c to your computer and use it in GitHub Desktop.
Flag operations using Enum
import logging
from enum import Enum
from dataclasses import dataclass, field
from typing import Tuple
import doctest
@dataclass
class PlayerFlagTypes(str, Enum):
YESNO: str = "yes/no"
TRUEFALSE: str = "true/false"
ONOFF: str = "on/off"
class PlayerFlag(tuple, Enum):
# (display_name, flag_type, default_flag_status: bool)
ARCHITECT = ("Architect", PlayerFlagTypes.YESNO, False)
DUNGEON_MASTER = ("Dungeon Master", PlayerFlagTypes.YESNO, False)
# a speaker on a chat channel/in an amphitheater (public chat room):
ORATOR = ("Orator", PlayerFlagTypes.YESNO, False)
# guild stuff:
GUILD_AUTODUEL = ("Guild Autoduel", PlayerFlagTypes.ONOFF, False)
GUILD_FOLLOW_MODE = ("Guild Follow Mode", PlayerFlagTypes.ONOFF, False)
GUILD_MEMBER = ("Guild Member", PlayerFlagTypes.YESNO, False)
# toggles:
EXPERT_MODE = ("Expert Mode", PlayerFlagTypes.ONOFF, False)
HOURGLASS = ("Hourglass", PlayerFlagTypes.ONOFF, True)
MORE_PROMPT = ("More Prompt", PlayerFlagTypes.ONOFF, True)
ROOM_DESCRIPTIONS = ("Room Descriptions", PlayerFlagTypes.ONOFF, True)
# health:
DISEASE = ("Diseased", PlayerFlagTypes.YESNO, False)
HUNGER = ("Hungry", PlayerFlagTypes.YESNO, False)
POISON = ("Poisoned", PlayerFlagTypes.YESNO, False)
THIRST = ("Thirsty", PlayerFlagTypes.YESNO, False)
TIRED = ("Tired", PlayerFlagTypes.YESNO, False)
UNCONSCIOUS = ("Unconscious", PlayerFlagTypes.YESNO, False)
# horse:
HAS_HORSE = ("Has horse", PlayerFlagTypes.YESNO, False)
MOUNTED = ("Mounted on horse", PlayerFlagTypes.YESNO, False)
@dataclass
class Flag(object):
flag_name: str
# should Flag introspect the flag type from PlayerFlagTypes in order to
# avoid repeating 'flag_type' here from PlayerFlagTypes?
flag_type: PlayerFlagTypes
flag_status: bool
@dataclass
class Player(object):
name: str
bad_hombre_rating: int
"""
suggested by gemini:
flags: list[PlayerFlag] = field(default_factory=lambda: [
PlayerFlag(flag.name, PlayerFlagTypes[flag.value.split()[1]])
for flag in PlayerFlagNames
"""
# Initialize flags on object creation:
flags: list[Flag] = field(default_factory=lambda: [Flag(flag_name=flag_element[0], flag_type=flag_element[1], flag_status=flag_element[2])
for flag_element in PlayerFlag])
def clear_flag(self, flag_name: str):
for flag in self.flags:
if flag.flag_name == flag_name:
flag.flag_status = False
return # Flag found and cleared, exit the loop
def set_flag(self, flag_name: PlayerFlag):
for flag in self.flags:
if flag.flag_name == flag_name:
flag.flag_status = True
# Flag found and set, exit the loop
return
def show_flag(self, flag: PlayerFlag, dot_leader=False, lead_number=None) -> str:
"""
display the flag status using the proper string based on the type of flag it is
:param flag: name of flag to display
:param dot_leader: True lists the flag prefixed with a number, "...:" and the status
:returns: str
"""
try:
name = flag.flag_name # lowercased version of Enum string
status = flag.flag_status
flag_type = flag.flag_type
logging.info(f"{name=}, {status=}, {flag_type=}")
if flag.flag_type is PlayerFlagTypes.YESNO:
result = "Yes" if flag.flag_status else "No"
elif flag.flag_type is PlayerFlagTypes.ONOFF:
result = "On" if flag.flag_status else "Off"
elif flag.flag_type is PlayerFlagTypes.TRUEFALSE:
result = "True" if flag.flag_status else "False"
else:
result = "N/A"
if dot_leader:
print(f"{lead_number:>2}. {name:.<20}: {result}")
else:
print(f"{name}: {result}")
except ValueError:
logging.warning(f"Can't show unknown flag: {flag}")
""""
def toggle_flag(self, flag: Flag):
try:
if flag.flag_name:
flag.flag_status = not flag.flag_status
except ValueError:
logging.warning(f"Can't toggle unknown flag: {flag}")
"""
if __name__ == '__main__':
# set up logging:
logging.basicConfig(level=logging.DEBUG)
# set up doctest:
doctest.testmod(verbose=True)
# understand some things:
"""
for i in PlayerFlag:
# i[0] = title case name, i[1] = True/False, Yes/No, On/Off, i[2] = True/False
print(i[0], i[1], i[2])
"""
test = PlayerFlag.UNCONSCIOUS
print(f'Name: {test[0]}, Type: {test[1]}, Value: {test[2]}')
"""
>>> test_player = Player(name="test", bad_hombre_rating=100)
>>> print(test_player.show_flag(PlayerFlag.UNCONSCIOUS))
Unconscious: No
"""
rulan = Player(name="Rulan", bad_hombre_rating=100)
print("Show bare flags:")
for flag in rulan.flags:
rulan.show_flag(flag)
print("Show dot leaders and flags:")
for number, flag in enumerate(rulan.flags, start=1):
rulan.show_flag(flag, dot_leader=True, lead_number=number)
# rulan.show_flag(rulan.flags[UNCONSCIOUS])
# rulan.toggle_flag(flag=PlayerFlag.UNCONSCIOUS)
# rulan.show_flag(flag=PlayerFlagNames.UNCONSCIOUS)
"""
jasmine = Player(name="Jasmine", bad_hombre_rating=20
# flags=[PlayerFlag(flag_name=PlayerFlags.EXPERT_MODE,
# flag_type=PlayerFlagTypes.TRUEFALSE,
# flag_status=True)]
)
# logging.basicConfig(level=logging.DEBUG, format=f'[{levelname}] | {message}')
logging.basicConfig(level=logging.DEBUG, format='[%(levelname)s] | %(message)s')
# https://www.reddit.com/r/learnpython/comments/z56z3m/how_can_i_create_key_value_dictionary_from_list/
# data = dict(next(iter(d.items())) for d in features)
# 1) show_flag(flag_name) -> str
print()
print(rulan.show_flag(PlayerFlag.DUNGEON_MASTER))
# Dungeon Master: Yes
print()
print("Menu format:")
print(rulan.show_flag(Flag.DUNGEON_MASTER, dot_leader=True, lead_number=1))
# 1. Dungeon Master......: Yes
print()
print("Short format:")
print(jasmine.show_flag(Flag.HUNGER))
# Hungry: No
print()
print("Show all four flag states:")
print(rulan.show_flag(Flag.THIRST))
# Thirsty: Yes
print(rulan.show_flag(Flag.HUNGER))
# Hungry: No
print(rulan.show_flag(Flag.ROOM_DESCRIPTIONS))
# Room Descriptions: On
print(rulan.show_flag(PlayerFlag.HOURGLASS))
# Hourglass: Off
# print("Deliberate error:")
# print(rulan.show_flag(PlayerFlag.BUNK))
# <<error>>
print()
print("toggle_flag():")
"""
"""
>>> print(jasmine.show_flag(PlayerFlag.UNCONSCIOUS))
Unconscious: Yes
>>> jasmine.toggle_flag(PlayerFlag.UNCONSCIOUS)
>>> print(jasmine.show_flag(PlayerFlag.UNCONSCIOUS))
Unconscious: No
"""
"""
print()
print("List all Jasmine's flags:")
count = 0
for i, v in enumerate(jasmine.flags):
print(jasmine.show_flag(v, dot_leader=True))
"""
@Pinacolada64
Copy link
Author

Unconscious, yes/no, False
ARCHITECT: None
DUNGEON_MASTER: None
ORATOR: None
GUILD_AUTODUEL: None
GUILD_FOLLOW_MODE: None
GUILD_MEMBER: None
EXPERT_MODE: None
HOURGLASS: None
MORE_PROMPT: None
ROOM_DESCRIPTIONS: None
DISEASE: None
HUNGER: None
POISON: None
THIRST: None
TIRED: None
UNCONSCIOUS: None
HAS_HORSE: None
MOUNTED: None

@Pinacolada64
Copy link
Author

Pinacolada64 commented May 1, 2024

Much closer to expected output!

16 items had no tests:
    __main__
    __main__.Flag
    __main__.Flag.__eq__
    __main__.Flag.__init__
    __main__.Flag.__repr__
    __main__.Player
    __main__.Player.__eq__
    __main__.Player.__init__
    __main__.Player.__repr__
    __main__.Player.clear_flag
    __main__.Player.set_flag
    __main__.Player.show_flag
    __main__.PlayerFlag
    __main__.PlayerFlagTypes
    __main__.PlayerFlagTypes.__eq__
    __main__.PlayerFlagTypes.__init__
0 tests in 16 items.
0 passed and 0 failed.
Test passed.
Name: Unconscious, Type: yes/no, Value: False
Architect: No
None
Dungeon Master: No
None
Orator: No
None
Guild Autoduel: Off
None
Guild Follow Mode: Off
None
Guild Member: No
None
Expert Mode: Off
None
Hourglass: On
None
More Prompt: On
None
Room Descriptions: On
None
Diseased: No
None
Hungry: No
None
Poisoned: No
None
Thirsty: No
None
Tired: No
None
Unconscious: No
None
Has horse: No
None
Mounted on horse: No
None

@Pinacolada64
Copy link
Author

Pinacolada64 commented May 14, 2024

16 items had no tests:
    __main__
    __main__.Flag
    __main__.Flag.__eq__
    __main__.Flag.__init__
    __main__.Flag.__repr__
    __main__.Player
    __main__.Player.__eq__
    __main__.Player.__init__
    __main__.Player.__repr__
    __main__.Player.clear_flag
    __main__.Player.set_flag
    __main__.Player.show_flag
    __main__.PlayerFlag
    __main__.PlayerFlagTypes
    __main__.PlayerFlagTypes.__eq__
    __main__.PlayerFlagTypes.__init__
0 tests in 16 items.
0 passed and 0 failed.
Test passed.
Name: Unconscious, Type: yes/no, Value: False
Show bare flags:
Architect: No
Dungeon Master: No
Orator: No
Guild Autoduel: Off
Guild Follow Mode: Off
Guild Member: No
Expert Mode: Off
Hourglass: On
More Prompt: On
Room Descriptions: On
Diseased: No
Hungry: No
Poisoned: No
Thirsty: No
Tired: No
Unconscious: No
Has horse: No
Mounted on horse: No
Show dot leaders and flags:
 1. Architect...........: No
 2. Dungeon Master......: No
 3. Orator..............: No
 4. Guild Autoduel......: Off
 5. Guild Follow Mode...: Off
 6. Guild Member........: No
 7. Expert Mode.........: Off
 8. Hourglass...........: On
 9. More Prompt.........: On
10. Room Descriptions...: On
11. Diseased............: No
12. Hungry..............: No
13. Poisoned............: No
14. Thirsty.............: No
15. Tired...............: No
16. Unconscious.........: No
17. Has horse...........: No
18. Mounted on horse....: No

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment