mirror of
https://github.com/ArchipelagoMW/Archipelago.git
synced 2026-03-07 15:13:52 -08:00
Launcher: generate templates for option presets (#5062)
This commit is contained in:
48
Options.py
48
Options.py
@@ -1747,8 +1747,10 @@ def generate_yaml_templates(target_folder: typing.Union[str, "pathlib.Path"], ge
|
|||||||
from Utils import local_path, __version__
|
from Utils import local_path, __version__
|
||||||
|
|
||||||
full_path: str
|
full_path: str
|
||||||
|
preset_folder = os.path.join(target_folder, "Presets")
|
||||||
|
|
||||||
os.makedirs(target_folder, exist_ok=True)
|
os.makedirs(target_folder, exist_ok=True)
|
||||||
|
os.makedirs(preset_folder, exist_ok=True)
|
||||||
|
|
||||||
# clean out old
|
# clean out old
|
||||||
for file in os.listdir(target_folder):
|
for file in os.listdir(target_folder):
|
||||||
@@ -1756,11 +1758,16 @@ def generate_yaml_templates(target_folder: typing.Union[str, "pathlib.Path"], ge
|
|||||||
if os.path.isfile(full_path) and full_path.endswith(".yaml"):
|
if os.path.isfile(full_path) and full_path.endswith(".yaml"):
|
||||||
os.unlink(full_path)
|
os.unlink(full_path)
|
||||||
|
|
||||||
def dictify_range(option: Range):
|
for file in os.listdir(preset_folder):
|
||||||
data = {option.default: 50}
|
full_path = os.path.join(preset_folder, file)
|
||||||
|
if os.path.isfile(full_path) and full_path.endswith(".yaml"):
|
||||||
|
os.unlink(full_path)
|
||||||
|
|
||||||
|
def dictify_range(option: Range, option_val: int | str):
|
||||||
|
data = {option_val: 50}
|
||||||
for sub_option in ["random", "random-low", "random-high",
|
for sub_option in ["random", "random-low", "random-high",
|
||||||
f"random-range-{option.range_start}-{option.range_end}"]:
|
f"random-range-{option.range_start}-{option.range_end}"]:
|
||||||
if sub_option != option.default:
|
if sub_option != option_val:
|
||||||
data[sub_option] = 0
|
data[sub_option] = 0
|
||||||
notes = {
|
notes = {
|
||||||
"random-low": "random value weighted towards lower values",
|
"random-low": "random value weighted towards lower values",
|
||||||
@@ -1773,6 +1780,8 @@ def generate_yaml_templates(target_folder: typing.Union[str, "pathlib.Path"], ge
|
|||||||
if number in data:
|
if number in data:
|
||||||
data[name] = data[number]
|
data[name] = data[number]
|
||||||
del data[number]
|
del data[number]
|
||||||
|
elif name in data:
|
||||||
|
pass
|
||||||
else:
|
else:
|
||||||
data[name] = 0
|
data[name] = 0
|
||||||
|
|
||||||
@@ -1788,20 +1797,27 @@ def generate_yaml_templates(target_folder: typing.Union[str, "pathlib.Path"], ge
|
|||||||
|
|
||||||
for game_name, world in AutoWorldRegister.world_types.items():
|
for game_name, world in AutoWorldRegister.world_types.items():
|
||||||
if not world.hidden or generate_hidden:
|
if not world.hidden or generate_hidden:
|
||||||
|
presets = world.web.options_presets.copy()
|
||||||
|
presets.update({"": {}})
|
||||||
|
|
||||||
option_groups = get_option_groups(world)
|
option_groups = get_option_groups(world)
|
||||||
|
for name, preset in presets.items():
|
||||||
res = template.render(
|
res = template.render(
|
||||||
option_groups=option_groups,
|
option_groups=option_groups,
|
||||||
__version__=__version__,
|
__version__=__version__,
|
||||||
game=game_name,
|
game=game_name,
|
||||||
world_version=world.world_version.as_simple_string(),
|
world_version=world.world_version.as_simple_string(),
|
||||||
yaml_dump=yaml_dump_scalar,
|
yaml_dump=yaml_dump_scalar,
|
||||||
dictify_range=dictify_range,
|
dictify_range=dictify_range,
|
||||||
cleandoc=cleandoc,
|
cleandoc=cleandoc,
|
||||||
)
|
preset_name=name,
|
||||||
|
preset=preset,
|
||||||
with open(os.path.join(target_folder, get_file_safe_name(game_name) + ".yaml"), "w", encoding="utf-8-sig") as f:
|
)
|
||||||
f.write(res)
|
preset_name = f" - {name}" if name else ""
|
||||||
|
with open(os.path.join(preset_folder if name else target_folder,
|
||||||
|
get_file_safe_name(game_name + preset_name) + ".yaml"),
|
||||||
|
"w", encoding="utf-8-sig") as f:
|
||||||
|
f.write(res)
|
||||||
|
|
||||||
|
|
||||||
def dump_player_options(multiworld: MultiWorld) -> None:
|
def dump_player_options(multiworld: MultiWorld) -> None:
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
name: Player{number}
|
name: Player{number}
|
||||||
|
|
||||||
# Used to describe your yaml. Useful if you have multiple files.
|
# Used to describe your yaml. Useful if you have multiple files.
|
||||||
description: {{ yaml_dump("Default %s Template" % game) }}
|
description: {{ yaml_dump("%s Preset for %s" % (preset_name, game)) if preset_name else yaml_dump("Default %s Template" % game) }}
|
||||||
|
|
||||||
game: {{ yaml_dump(game) }}
|
game: {{ yaml_dump(game) }}
|
||||||
requires:
|
requires:
|
||||||
@@ -38,11 +38,11 @@ requires:
|
|||||||
{{ yaml_dump(game) }}: {{ world_version }} # Version of the world required for this yaml to work as expected.
|
{{ yaml_dump(game) }}: {{ world_version }} # Version of the world required for this yaml to work as expected.
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
{%- macro range_option(option) %}
|
{%- macro range_option(option, option_val) %}
|
||||||
# You can define additional values between the minimum and maximum values.
|
# You can define additional values between the minimum and maximum values.
|
||||||
# Minimum value is {{ option.range_start }}
|
# Minimum value is {{ option.range_start }}
|
||||||
# Maximum value is {{ option.range_end }}
|
# Maximum value is {{ option.range_end }}
|
||||||
{%- set data, notes = dictify_range(option) %}
|
{%- set data, notes = dictify_range(option, option_val) %}
|
||||||
{%- for entry, default in data.items() %}
|
{%- for entry, default in data.items() %}
|
||||||
{{ entry }}: {{ default }}{% if notes[entry] %} # {{ notes[entry] }}{% endif %}
|
{{ entry }}: {{ default }}{% if notes[entry] %} # {{ notes[entry] }}{% endif %}
|
||||||
{%- endfor -%}
|
{%- endfor -%}
|
||||||
@@ -56,6 +56,10 @@ requires:
|
|||||||
|
|
||||||
{%- for option_key, option in group_options.items() %}
|
{%- for option_key, option in group_options.items() %}
|
||||||
{{ option_key }}:
|
{{ option_key }}:
|
||||||
|
{%- set option_val = option.default %}
|
||||||
|
{%- if option_key in preset %}
|
||||||
|
{%- set option_val = preset[option_key] %}
|
||||||
|
{%- endif -%}
|
||||||
{%- if option.__doc__ %}
|
{%- if option.__doc__ %}
|
||||||
# {{ cleandoc(option.__doc__)
|
# {{ cleandoc(option.__doc__)
|
||||||
| trim
|
| trim
|
||||||
@@ -69,25 +73,25 @@ requires:
|
|||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
|
|
||||||
{%- if option.range_start is defined and option.range_start is number %}
|
{%- if option.range_start is defined and option.range_start is number %}
|
||||||
{{- range_option(option) -}}
|
{{- range_option(option, option_val) -}}
|
||||||
|
|
||||||
{%- elif option.options -%}
|
{%- elif option.options -%}
|
||||||
{%- for suboption_option_id, sub_option_name in option.name_lookup.items() %}
|
{%- for suboption_option_id, sub_option_name in option.name_lookup.items() %}
|
||||||
{{ yaml_dump(sub_option_name) }}: {% if suboption_option_id == option.default %}50{% else %}0{% endif %}
|
{{ yaml_dump(sub_option_name) }}: {% if suboption_option_id == option_val or sub_option_name == option_val %}50{% else %}0{% endif %}
|
||||||
{%- endfor -%}
|
{%- endfor -%}
|
||||||
|
|
||||||
{%- if option.name_lookup[option.default] not in option.options %}
|
{%- if option.name_lookup[option_val] not in option.options and option_val not in option.options %}
|
||||||
{{ yaml_dump(option.default) }}: 50
|
{{ yaml_dump(option_val) }}: 50
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
|
|
||||||
{%- elif option.default is string %}
|
{%- elif option_val is string %}
|
||||||
{{ yaml_dump(option.default) }}: 50
|
{{ yaml_dump(option_val) }}: 50
|
||||||
|
|
||||||
{%- elif option.default is iterable and option.default is not mapping %}
|
{%- elif option_val is iterable and option_val is not mapping %}
|
||||||
{{ option.default | list }}
|
{{ option_val | list }}
|
||||||
|
|
||||||
{%- else %}
|
{%- else %}
|
||||||
{{ yaml_dump(option.default) | indent(4, first=false) }}
|
{{ yaml_dump(option_val) | indent(4, first=false) }}
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
{{ "\n" }}
|
{{ "\n" }}
|
||||||
{%- endfor %}
|
{%- endfor %}
|
||||||
|
|||||||
@@ -25,31 +25,41 @@ class TestGenerateYamlTemplates(unittest.TestCase):
|
|||||||
if "World: with colon" in worlds.AutoWorld.AutoWorldRegister.world_types:
|
if "World: with colon" in worlds.AutoWorld.AutoWorldRegister.world_types:
|
||||||
del worlds.AutoWorld.AutoWorldRegister.world_types["World: with colon"]
|
del worlds.AutoWorld.AutoWorldRegister.world_types["World: with colon"]
|
||||||
|
|
||||||
|
|
||||||
def test_name_with_colon(self) -> None:
|
def test_name_with_colon(self) -> None:
|
||||||
from Options import generate_yaml_templates
|
from Options import generate_yaml_templates
|
||||||
from worlds.AutoWorld import AutoWorldRegister
|
from worlds.AutoWorld import AutoWorldRegister
|
||||||
from worlds.AutoWorld import World
|
from worlds.AutoWorld import World, WebWorld
|
||||||
|
|
||||||
|
class WebWorldWithColon(WebWorld):
|
||||||
|
options_presets = {
|
||||||
|
"Generic": {
|
||||||
|
"progression_balancing": "disabled",
|
||||||
|
"accessibility": "minimal",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class WorldWithColon(World):
|
class WorldWithColon(World):
|
||||||
game = "World: with colon"
|
game = "World: with colon"
|
||||||
item_name_to_id = {}
|
item_name_to_id = {}
|
||||||
location_name_to_id = {}
|
location_name_to_id = {}
|
||||||
|
web = WebWorldWithColon()
|
||||||
|
|
||||||
AutoWorldRegister.world_types = {WorldWithColon.game: WorldWithColon}
|
AutoWorldRegister.world_types = {WorldWithColon.game: WorldWithColon}
|
||||||
with TemporaryDirectory(f"archipelago_{__name__}") as temp_dir:
|
with TemporaryDirectory(f"archipelago_{__name__}") as temp_dir:
|
||||||
generate_yaml_templates(temp_dir)
|
generate_yaml_templates(temp_dir)
|
||||||
path: Path
|
path: Path
|
||||||
for path in Path(temp_dir).iterdir():
|
for path in Path(temp_dir).rglob("*"):
|
||||||
self.assertTrue(path.is_file())
|
if path.is_file():
|
||||||
self.assertTrue(path.suffix == ".yaml")
|
self.assertTrue(path.suffix == ".yaml")
|
||||||
with path.open(encoding="utf-8") as f:
|
with path.open(encoding="utf-8") as f:
|
||||||
try:
|
try:
|
||||||
data = parse_yaml(f)
|
data = parse_yaml(f)
|
||||||
except:
|
except:
|
||||||
f.seek(0)
|
f.seek(0)
|
||||||
print(f"Error in {path.name}:\n{f.read()}")
|
print(f"Error in {path.name}:\n{f.read()}")
|
||||||
raise
|
raise
|
||||||
self.assertIn("game", data)
|
self.assertIn("game", data)
|
||||||
self.assertIn(":", data["game"])
|
self.assertIn(":", data["game"])
|
||||||
self.assertIn(data["game"], data)
|
self.assertIn(data["game"], data)
|
||||||
self.assertIsInstance(data[data["game"]], dict)
|
self.assertIsInstance(data[data["game"]], dict)
|
||||||
|
|||||||
Reference in New Issue
Block a user