mirror of
https://github.com/sui-feng-cb/AzurLaneAutoScript1.git
synced 2026-08-15 11:43:08 +08:00
Add: config for island business and restaurant
This commit is contained in:
190
module/island_handler/restaurant_config.py
Normal file
190
module/island_handler/restaurant_config.py
Normal file
@@ -0,0 +1,190 @@
|
||||
"""Shared restaurant configuration and waitress helpers.
|
||||
|
||||
This module intentionally has no device or UI dependencies so it can be used by
|
||||
the restaurant runner, IslandBusiness, the production planner, and config
|
||||
migration code alike.
|
||||
"""
|
||||
|
||||
from collections import OrderedDict
|
||||
|
||||
from module.exception import RequestHumanTakeover
|
||||
|
||||
|
||||
WAITRESS_NONE = 'none'
|
||||
WAITRESS_ANY = 'any'
|
||||
|
||||
|
||||
# Keep the option/bonus data in one place. ``waitress_effects`` values are
|
||||
# ``(capacity_delta, sales_bonus)`` and bonuses are only applied for explicitly
|
||||
# selected named waitresses, matching the previous behaviour.
|
||||
RESTAURANT_CONFIG = OrderedDict({
|
||||
601: {
|
||||
'name': 'Koi',
|
||||
'grade_key': 'KoiGrade',
|
||||
'waitress_keys': ('KoiWaitress1', 'KoiWaitress2'),
|
||||
'legacy_waitress_key': 'KoiWaitress',
|
||||
'menu_key': 'KoiMenu',
|
||||
'waitress_options': ('Chao_Ho', 'Chang_Feng'),
|
||||
'waitress_effects': {
|
||||
'Chao_Ho': (1, 0.10),
|
||||
'Chang_Feng': (1, 0),
|
||||
},
|
||||
},
|
||||
602: {
|
||||
'name': 'Bear',
|
||||
'grade_key': 'BearGrade',
|
||||
'waitress_keys': ('BearWaitress1', 'BearWaitress2'),
|
||||
'legacy_waitress_key': 'BearWaitress',
|
||||
'menu_key': 'BearMenu',
|
||||
'waitress_options': ('Cheshire', 'Chang_Feng'),
|
||||
'waitress_effects': {
|
||||
'Cheshire': (1, 0.05),
|
||||
'Chang_Feng': (1, 0),
|
||||
},
|
||||
},
|
||||
603: {
|
||||
'name': 'Eatery',
|
||||
'grade_key': 'EateryGrade',
|
||||
'waitress_keys': ('EateryWaitress1', 'EateryWaitress2'),
|
||||
'legacy_waitress_key': 'EateryWaitress',
|
||||
'menu_key': 'EateryMenu',
|
||||
'waitress_options': ('Helena', 'Prinz_Eugen', 'Chang_Feng'),
|
||||
'waitress_effects': {
|
||||
'Helena': (1, 0.10),
|
||||
'Prinz_Eugen': (0, 0.10),
|
||||
'Chang_Feng': (1, 0),
|
||||
},
|
||||
},
|
||||
604: {
|
||||
'name': 'Grill',
|
||||
'grade_key': 'GrillGrade',
|
||||
'waitress_keys': ('GrillWaitress1', 'GrillWaitress2'),
|
||||
'legacy_waitress_key': 'GrillWaitress',
|
||||
'menu_key': 'GrillMenu',
|
||||
'waitress_options': ('August_von_Parseval', 'Prinz_Eugen', 'Chang_Feng'),
|
||||
'waitress_effects': {
|
||||
'August_von_Parseval': (1, 0.10),
|
||||
'Prinz_Eugen': (0, 0.10),
|
||||
'Chang_Feng': (1, 0),
|
||||
},
|
||||
},
|
||||
901: {
|
||||
'name': 'Cafe',
|
||||
'grade_key': 'CafeGrade',
|
||||
'waitress_keys': ('CafeWaitress1', 'CafeWaitress2'),
|
||||
'legacy_waitress_key': 'CafeWaitress',
|
||||
'menu_key': 'CafeMenu',
|
||||
'waitress_options': ('Cheshire', 'Belfast', 'Chang_Feng'),
|
||||
'waitress_effects': {
|
||||
'Cheshire': (1, 0.05),
|
||||
'Belfast': (0, 0.10),
|
||||
'Chang_Feng': (1, 0),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
RESTAURANT_IDS = tuple(RESTAURANT_CONFIG.keys())
|
||||
ISLAND_RESTAURANT_CONFIG_PREFIX = 'IslandBusiness.IslandRestaurant.'
|
||||
|
||||
|
||||
def get_restaurant_config(restaurant_id):
|
||||
return RESTAURANT_CONFIG[restaurant_id]
|
||||
|
||||
|
||||
def get_config_key(restaurant_id, key):
|
||||
return ISLAND_RESTAURANT_CONFIG_PREFIX + key
|
||||
|
||||
|
||||
def get_waitress_options(restaurant_id):
|
||||
return (WAITRESS_NONE, WAITRESS_ANY) + tuple(
|
||||
get_restaurant_config(restaurant_id)['waitress_options']
|
||||
)
|
||||
|
||||
|
||||
def _waitress_sort_key(restaurant_id, value):
|
||||
config = get_restaurant_config(restaurant_id)
|
||||
if value == WAITRESS_NONE:
|
||||
return (2, 0)
|
||||
if value == WAITRESS_ANY:
|
||||
return (1, 0)
|
||||
try:
|
||||
index = config['waitress_options'].index(value)
|
||||
except ValueError:
|
||||
index = len(config['waitress_options'])
|
||||
return (0, index)
|
||||
|
||||
|
||||
def normalize_waitress_slots(restaurant_id, values):
|
||||
"""Validate and return a canonical, unordered pair of waitress values.
|
||||
|
||||
Slot order is canonicalized because the two slots are unordered. Invalid
|
||||
combinations are not repaired: they require human intervention.
|
||||
"""
|
||||
allowed = set(get_waitress_options(restaurant_id))
|
||||
values = list(values or [])
|
||||
cleaned = []
|
||||
seen_named = set()
|
||||
for value in values:
|
||||
if value is None:
|
||||
value = WAITRESS_NONE
|
||||
if value not in allowed:
|
||||
raise RequestHumanTakeover(
|
||||
f'Invalid waitress value for restaurant {restaurant_id}: {value}'
|
||||
)
|
||||
if value not in (WAITRESS_NONE, WAITRESS_ANY):
|
||||
if value in seen_named:
|
||||
raise RequestHumanTakeover(
|
||||
f'Duplicate named waitress for restaurant {restaurant_id}: {value}'
|
||||
)
|
||||
seen_named.add(value)
|
||||
cleaned.append(value)
|
||||
|
||||
if len(cleaned) > 2:
|
||||
raise RequestHumanTakeover(
|
||||
f'Restaurant {restaurant_id} has more than two waitress slots'
|
||||
)
|
||||
|
||||
cleaned.sort(key=lambda value: _waitress_sort_key(restaurant_id, value))
|
||||
cleaned.extend([WAITRESS_NONE] * (2 - len(cleaned)))
|
||||
return tuple(cleaned)
|
||||
|
||||
|
||||
def get_waitress_slots(config, restaurant_id):
|
||||
config_data = get_restaurant_config(restaurant_id)
|
||||
values = [
|
||||
config.cross_get(get_config_key(restaurant_id, key), default=None)
|
||||
for key in config_data['waitress_keys']
|
||||
]
|
||||
return normalize_waitress_slots(restaurant_id, values)
|
||||
|
||||
|
||||
def is_restaurant_enabled(slots):
|
||||
return any(value != WAITRESS_NONE for value in slots)
|
||||
|
||||
|
||||
def get_selected_named_waitresses(slots):
|
||||
return {
|
||||
value for value in slots
|
||||
if value not in (WAITRESS_NONE, WAITRESS_ANY)
|
||||
}
|
||||
|
||||
|
||||
def get_waitress_effect(restaurant_id, slots):
|
||||
slots = normalize_waitress_slots(restaurant_id, slots)
|
||||
capacity_delta = 0
|
||||
sales_bonus = 0
|
||||
effects = get_restaurant_config(restaurant_id)['waitress_effects']
|
||||
for waitress in get_selected_named_waitresses(slots):
|
||||
capacity, sales = effects.get(waitress, (0, 0))
|
||||
capacity_delta += capacity
|
||||
sales_bonus += sales
|
||||
return capacity_delta, sales_bonus
|
||||
|
||||
|
||||
def legacy_waitress_to_slots(value, restaurant_id):
|
||||
"""Convert an old ``name+name`` waitress value into two new slots."""
|
||||
if not isinstance(value, str):
|
||||
values = []
|
||||
else:
|
||||
values = value.split('+')
|
||||
return normalize_waitress_slots(restaurant_id, values)
|
||||
Reference in New Issue
Block a user