diff --git a/config/template.json b/config/template.json index 0071cc56a..a921278ea 100644 --- a/config/template.json +++ b/config/template.json @@ -1961,6 +1961,41 @@ "Storage": {} } }, + "IslandBusiness": { + "Scheduler": { + "Enable": false, + "NextRun": "2020-01-01 00:00:00", + "Command": "IslandBusiness", + "SuccessInterval": 0, + "FailureInterval": 120, + "ServerUpdate": "00:00" + }, + "IslandRestaurant": { + "KoiGrade": "bronze", + "KoiWaitress1": "any", + "KoiWaitress2": "none", + "KoiMenu": "{}", + "BearGrade": "bronze", + "BearWaitress1": "any", + "BearWaitress2": "none", + "BearMenu": "{}", + "EateryGrade": "bronze", + "EateryWaitress1": "any", + "EateryWaitress2": "none", + "EateryMenu": "{}", + "GrillGrade": "bronze", + "GrillWaitress1": "any", + "GrillWaitress2": "none", + "GrillMenu": "{}", + "CafeGrade": "bronze", + "CafeWaitress1": "any", + "CafeWaitress2": "none", + "CafeMenu": "{}" + }, + "Storage": { + "Storage": {} + } + }, "Daemon": { "Daemon": { "EnterMap": true diff --git a/module/config/argument/args.json b/module/config/argument/args.json index 402c5cf97..c1b2d8ed3 100644 --- a/module/config/argument/args.json +++ b/module/config/argument/args.json @@ -9466,6 +9466,229 @@ } } }, + "IslandBusiness": { + "Scheduler": { + "Enable": { + "type": "checkbox", + "value": false, + "option": [ + true, + false + ] + }, + "NextRun": { + "type": "datetime", + "value": "2020-01-01 00:00:00", + "validate": "datetime" + }, + "Command": { + "type": "input", + "value": "IslandBusiness", + "display": "hide" + }, + "SuccessInterval": { + "type": "input", + "value": 0, + "display": "hide" + }, + "FailureInterval": { + "type": "input", + "value": 120, + "display": "hide" + }, + "ServerUpdate": { + "type": "input", + "value": "00:00", + "display": "hide" + } + }, + "IslandRestaurant": { + "KoiGrade": { + "type": "select", + "value": "bronze", + "option": [ + "bronze", + "silver", + "gold", + "diamond" + ] + }, + "KoiWaitress1": { + "type": "select", + "value": "any", + "option": [ + "none", + "any", + "Chao_Ho", + "Chang_Feng" + ] + }, + "KoiWaitress2": { + "type": "select", + "value": "none", + "option": [ + "none", + "any", + "Chao_Ho", + "Chang_Feng" + ] + }, + "KoiMenu": { + "type": "textarea", + "value": "{}" + }, + "BearGrade": { + "type": "select", + "value": "bronze", + "option": [ + "bronze", + "silver", + "gold", + "diamond" + ] + }, + "BearWaitress1": { + "type": "select", + "value": "any", + "option": [ + "none", + "any", + "Cheshire", + "Chang_Feng" + ] + }, + "BearWaitress2": { + "type": "select", + "value": "none", + "option": [ + "none", + "any", + "Cheshire", + "Chang_Feng" + ] + }, + "BearMenu": { + "type": "textarea", + "value": "{}" + }, + "EateryGrade": { + "type": "select", + "value": "bronze", + "option": [ + "bronze", + "silver", + "gold", + "diamond" + ] + }, + "EateryWaitress1": { + "type": "select", + "value": "any", + "option": [ + "none", + "any", + "Helena", + "Prinz_Eugen", + "Chang_Feng" + ] + }, + "EateryWaitress2": { + "type": "select", + "value": "none", + "option": [ + "none", + "any", + "Helena", + "Prinz_Eugen", + "Chang_Feng" + ] + }, + "EateryMenu": { + "type": "textarea", + "value": "{}" + }, + "GrillGrade": { + "type": "select", + "value": "bronze", + "option": [ + "bronze", + "silver", + "gold", + "diamond" + ] + }, + "GrillWaitress1": { + "type": "select", + "value": "any", + "option": [ + "none", + "any", + "August_von_Parseval", + "Prinz_Eugen", + "Chang_Feng" + ] + }, + "GrillWaitress2": { + "type": "select", + "value": "none", + "option": [ + "none", + "any", + "August_von_Parseval", + "Prinz_Eugen", + "Chang_Feng" + ] + }, + "GrillMenu": { + "type": "textarea", + "value": "{}" + }, + "CafeGrade": { + "type": "select", + "value": "bronze", + "option": [ + "bronze", + "silver", + "gold", + "diamond" + ] + }, + "CafeWaitress1": { + "type": "select", + "value": "any", + "option": [ + "none", + "any", + "Cheshire", + "Belfast", + "Chang_Feng" + ] + }, + "CafeWaitress2": { + "type": "select", + "value": "none", + "option": [ + "none", + "any", + "Cheshire", + "Belfast", + "Chang_Feng" + ] + }, + "CafeMenu": { + "type": "textarea", + "value": "{}" + } + }, + "Storage": { + "Storage": { + "type": "storage", + "value": {}, + "valuetype": "ignore", + "display": "disabled" + } + } + }, "Daemon": { "Daemon": { "EnterMap": { diff --git a/module/config/argument/argument.yaml b/module/config/argument/argument.yaml index 3eaf0086c..b2eecc0e9 100644 --- a/module/config/argument/argument.yaml +++ b/module/config/argument/argument.yaml @@ -748,6 +748,72 @@ OpsiHazard1Leveling: # =================== Island ==================== IslandFreebie: Share: true +IslandRestaurant: + KoiGrade: + value: bronze + option: [ bronze, silver, gold, diamond ] + KoiWaitress1: &KoiWaitressSlot + value: any + option: &KoiWaitressOptions [ none, any, Chao_Ho, Chang_Feng ] + KoiWaitress2: + <<: *KoiWaitressSlot + value: none + KoiMenu: + type: textarea + value: |- + {} + BearGrade: + value: bronze + option: [ bronze, silver, gold, diamond ] + BearWaitress1: &BearWaitressSlot + value: any + option: &BearWaitressOptions [ none, any, Cheshire, Chang_Feng ] + BearWaitress2: + <<: *BearWaitressSlot + value: none + BearMenu: + type: textarea + value: |- + {} + EateryGrade: + value: bronze + option: [ bronze, silver, gold, diamond ] + EateryWaitress1: &EateryWaitressSlot + value: any + option: &EateryWaitressOptions [ none, any, Helena, Prinz_Eugen, Chang_Feng ] + EateryWaitress2: + <<: *EateryWaitressSlot + value: none + EateryMenu: + type: textarea + value: |- + {} + GrillGrade: + value: bronze + option: [ bronze, silver, gold, diamond ] + GrillWaitress1: &GrillWaitressSlot + value: any + option: &GrillWaitressOptions [ none, any, August_von_Parseval, Prinz_Eugen, Chang_Feng ] + GrillWaitress2: + <<: *GrillWaitressSlot + value: none + GrillMenu: + type: textarea + value: |- + {} + CafeGrade: + value: bronze + option: [ bronze, silver, gold, diamond ] + CafeWaitress1: &CafeWaitressSlot + value: any + option: &CafeWaitressOptions [ none, any, Cheshire, Belfast, Chang_Feng ] + CafeWaitress2: + <<: *CafeWaitressSlot + value: none + CafeMenu: + type: textarea + value: |- + {} IslandSeasonTask: TaskTarget: type: textarea diff --git a/module/config/argument/menu.json b/module/config/argument/menu.json index 97c18d7b1..c55b15e94 100644 --- a/module/config/argument/menu.json +++ b/module/config/argument/menu.json @@ -101,7 +101,8 @@ "tasks": [ "IslandFreebie", "IslandCollect", - "IslandSeasonTask" + "IslandSeasonTask", + "IslandBusiness" ] }, "Tool": { diff --git a/module/config/argument/task.yaml b/module/config/argument/task.yaml index f4f7d3610..223090424 100644 --- a/module/config/argument/task.yaml +++ b/module/config/argument/task.yaml @@ -338,6 +338,9 @@ Island: IslandSeasonTask: - Scheduler - IslandSeasonTask + IslandBusiness: + - Scheduler + - IslandRestaurant # ==================== Tool ==================== diff --git a/module/config/config_generated.py b/module/config/config_generated.py index b63bebfc2..9f8dac71b 100644 --- a/module/config/config_generated.py +++ b/module/config/config_generated.py @@ -442,6 +442,28 @@ class GeneratedConfig: # Group `IslandFreebie` IslandFreebie_Share = True + # Group `IslandRestaurant` + IslandRestaurant_KoiGrade = 'bronze' # bronze, silver, gold, diamond + IslandRestaurant_KoiWaitress1 = 'any' # none, any, Chao_Ho, Chang_Feng + IslandRestaurant_KoiWaitress2 = 'none' # none, any, Chao_Ho, Chang_Feng + IslandRestaurant_KoiMenu = '{}' + IslandRestaurant_BearGrade = 'bronze' # bronze, silver, gold, diamond + IslandRestaurant_BearWaitress1 = 'any' # none, any, Cheshire, Chang_Feng + IslandRestaurant_BearWaitress2 = 'none' # none, any, Cheshire, Chang_Feng + IslandRestaurant_BearMenu = '{}' + IslandRestaurant_EateryGrade = 'bronze' # bronze, silver, gold, diamond + IslandRestaurant_EateryWaitress1 = 'any' # none, any, Helena, Prinz_Eugen, Chang_Feng + IslandRestaurant_EateryWaitress2 = 'none' # none, any, Helena, Prinz_Eugen, Chang_Feng + IslandRestaurant_EateryMenu = '{}' + IslandRestaurant_GrillGrade = 'bronze' # bronze, silver, gold, diamond + IslandRestaurant_GrillWaitress1 = 'any' # none, any, August_von_Parseval, Prinz_Eugen, Chang_Feng + IslandRestaurant_GrillWaitress2 = 'none' # none, any, August_von_Parseval, Prinz_Eugen, Chang_Feng + IslandRestaurant_GrillMenu = '{}' + IslandRestaurant_CafeGrade = 'bronze' # bronze, silver, gold, diamond + IslandRestaurant_CafeWaitress1 = 'any' # none, any, Cheshire, Belfast, Chang_Feng + IslandRestaurant_CafeWaitress2 = 'none' # none, any, Cheshire, Belfast, Chang_Feng + IslandRestaurant_CafeMenu = '{}' + # Group `IslandSeasonTask` IslandSeasonTask_TaskTarget = '{}' diff --git a/module/config/i18n/en-US.json b/module/config/i18n/en-US.json index db0110116..f49e448a5 100644 --- a/module/config/i18n/en-US.json +++ b/module/config/i18n/en-US.json @@ -266,6 +266,10 @@ "name": "Island Season Task", "help": "" }, + "IslandBusiness": { + "name": "Restaurant Management", + "help": "" + }, "Daemon": { "name": "Normal Semi-auto", "help": "" @@ -2601,6 +2605,158 @@ "help": "" } }, + "IslandRestaurant": { + "_info": { + "name": "Restaurant Management", + "help": "" + }, + "KoiGrade": { + "name": "Golden Koi Restaurant Grade", + "help": "", + "bronze": "Bronze", + "silver": "Silver", + "gold": "Gold", + "diamond": "Diamond" + }, + "KoiWaitress1": { + "name": "Golden Koi Restaurant Waitress 1", + "help": "Two waitress slots are unordered. None leaves this slot empty; both None disables the restaurant. Any chooses the highest-management free character. Named choices are processed first and duplicate named choices are cleared.", + "none": "None", + "any": "Any", + "Chao_Ho": "Chao Ho", + "Chang_Feng": "Chang Feng" + }, + "KoiWaitress2": { + "name": "Golden Koi Restaurant Waitress 2", + "help": "Two waitress slots are unordered. None leaves this slot empty; both None disables the restaurant. Any chooses the highest-management free character. Named choices are processed first and duplicate named choices are cleared.", + "none": "None", + "any": "Any", + "Chao_Ho": "Chao Ho", + "Chang_Feng": "Chang Feng" + }, + "KoiMenu": { + "name": "Golden Koi Restaurant Menu", + "help": "Will only sell from these dishes.\nAutomatically generated by Island Production Planner in Tools." + }, + "BearGrade": { + "name": "Polar Bear Teahouse Grade", + "help": "", + "bronze": "Bronze", + "silver": "Silver", + "gold": "Gold", + "diamond": "Diamond" + }, + "BearWaitress1": { + "name": "Polar Bear Teahouse Waitress 1", + "help": "Two waitress slots are unordered. None leaves this slot empty; both None disables the restaurant. Any chooses the highest-management free character. Named choices are processed first and duplicate named choices are cleared.", + "none": "None", + "any": "Any", + "Cheshire": "HMS Cheshire", + "Chang_Feng": "Chang Feng" + }, + "BearWaitress2": { + "name": "Polar Bear Teahouse Waitress 2", + "help": "Two waitress slots are unordered. None leaves this slot empty; both None disables the restaurant. Any chooses the highest-management free character. Named choices are processed first and duplicate named choices are cleared.", + "none": "None", + "any": "Any", + "Cheshire": "HMS Cheshire", + "Chang_Feng": "Chang Feng" + }, + "BearMenu": { + "name": "Polar Bear Teahouse Menu", + "help": "Will only sell from these dishes.\nAutomatically generated by Island Production Planner in Tools." + }, + "EateryGrade": { + "name": "Manjuu Eatery Grade", + "help": "", + "bronze": "Bronze", + "silver": "Silver", + "gold": "Gold", + "diamond": "Diamond" + }, + "EateryWaitress1": { + "name": "Manjuu Eatery Waitress 1", + "help": "Two waitress slots are unordered. None leaves this slot empty; both None disables the restaurant. Any chooses the highest-management free character. Named choices are processed first and duplicate named choices are cleared.", + "none": "None", + "any": "Any", + "Helena": "USS Helena", + "Prinz_Eugen": "KMS Prinz Eugen", + "Chang_Feng": "Chang Feng" + }, + "EateryWaitress2": { + "name": "Manjuu Eatery Waitress 2", + "help": "Two waitress slots are unordered. None leaves this slot empty; both None disables the restaurant. Any chooses the highest-management free character. Named choices are processed first and duplicate named choices are cleared.", + "none": "None", + "any": "Any", + "Helena": "USS Helena", + "Prinz_Eugen": "KMS Prinz Eugen", + "Chang_Feng": "Chang Feng" + }, + "EateryMenu": { + "name": "Manjuu Eatery Menu", + "help": "Will only sell from these dishes.\nAutomatically generated by Island Production Planner in Tools." + }, + "GrillGrade": { + "name": "Fin-'n'-Feather Grill Grade", + "help": "", + "bronze": "Bronze", + "silver": "Silver", + "gold": "Gold", + "diamond": "Diamond" + }, + "GrillWaitress1": { + "name": "Fin-'n'-Feather Grill Waitress 1", + "help": "Two waitress slots are unordered. None leaves this slot empty; both None disables the restaurant. Any chooses the highest-management free character. Named choices are processed first and duplicate named choices are cleared.", + "none": "None", + "any": "Any", + "August_von_Parseval": "KMS August von Parseval", + "Prinz_Eugen": "KMS Prinz Eugen", + "Chang_Feng": "Chang Feng" + }, + "GrillWaitress2": { + "name": "Fin-'n'-Feather Grill Waitress 2", + "help": "Two waitress slots are unordered. None leaves this slot empty; both None disables the restaurant. Any chooses the highest-management free character. Named choices are processed first and duplicate named choices are cleared.", + "none": "None", + "any": "Any", + "August_von_Parseval": "KMS August von Parseval", + "Prinz_Eugen": "KMS Prinz Eugen", + "Chang_Feng": "Chang Feng" + }, + "GrillMenu": { + "name": "Fin-'n'-Feather Grill Menu", + "help": "Will only sell from these dishes.\nAutomatically generated by Island Production Planner in Tools." + }, + "CafeGrade": { + "name": "Café Manjuu Grade", + "help": "", + "bronze": "Bronze", + "silver": "Silver", + "gold": "Gold", + "diamond": "Diamond" + }, + "CafeWaitress1": { + "name": "Café Manjuu Waitress 1", + "help": "Two waitress slots are unordered. None leaves this slot empty; both None disables the restaurant. Any chooses the highest-management free character. Named choices are processed first and duplicate named choices are cleared.", + "none": "None", + "any": "Any", + "Cheshire": "HMS Cheshire", + "Belfast": "HMS Belfast", + "Chang_Feng": "Chang Feng" + }, + "CafeWaitress2": { + "name": "Café Manjuu Waitress 2", + "help": "Two waitress slots are unordered. None leaves this slot empty; both None disables the restaurant. Any chooses the highest-management free character. Named choices are processed first and duplicate named choices are cleared.", + "none": "None", + "any": "Any", + "Cheshire": "HMS Cheshire", + "Belfast": "HMS Belfast", + "Chang_Feng": "Chang Feng" + }, + "CafeMenu": { + "name": "Café Manjuu Menu", + "help": "Will only sell from these dishes.\nAutomatically generated by Island Production Planner in Tools." + } + }, "IslandSeasonTask": { "_info": { "name": "Island Season Task", diff --git a/module/config/i18n/ja-JP.json b/module/config/i18n/ja-JP.json index 21276a3fc..5f252b0f1 100644 --- a/module/config/i18n/ja-JP.json +++ b/module/config/i18n/ja-JP.json @@ -266,6 +266,10 @@ "name": "開発計画", "help": "" }, + "IslandBusiness": { + "name": "店舗経営", + "help": "" + }, "Daemon": { "name": "半自動クリック", "help": "" @@ -2601,6 +2605,158 @@ "help": "" } }, + "IslandRestaurant": { + "_info": { + "name": "グルメ運営", + "help": "" + }, + "KoiGrade": { + "name": "有魚飯店のランク", + "help": "", + "bronze": "ブロンズ", + "silver": "シルバー", + "gold": "ゴールド", + "diamond": "ダイヤモンド" + }, + "KoiWaitress1": { + "name": "有魚飯店の給仕1", + "help": "2つの給仕スロットに順序はありません。無は空きスロット、両方が無ならレストランを停止します。任意は管理レベルが最も高い空きキャラクターを選びます。指定キャラクターを優先し、重複した指定は消去します。", + "none": "無", + "any": "任意", + "Chao_Ho": "肇和", + "Chang_Feng": "長風" + }, + "KoiWaitress2": { + "name": "有魚飯店の給仕2", + "help": "2つの給仕スロットに順序はありません。無は空きスロット、両方が無ならレストランを停止します。任意は管理レベルが最も高い空きキャラクターを選びます。指定キャラクターを優先し、重複した指定は消去します。", + "none": "無", + "any": "任意", + "Chao_Ho": "肇和", + "Chang_Feng": "長風" + }, + "KoiMenu": { + "name": "有魚飯店のメニュー", + "help": "メニュー以外のものは販売されません。\nツールの離島生産ソルバーで自動生成されます。" + }, + "BearGrade": { + "name": "白クマ茶房のランク", + "help": "", + "bronze": "ブロンズ", + "silver": "シルバー", + "gold": "ゴールド", + "diamond": "ダイヤモンド" + }, + "BearWaitress1": { + "name": "白クマ茶房の給仕1", + "help": "2つの給仕スロットに順序はありません。無は空きスロット、両方が無ならレストランを停止します。任意は管理レベルが最も高い空きキャラクターを選びます。指定キャラクターを優先し、重複した指定は消去します。", + "none": "無", + "any": "任意", + "Cheshire": "チェシャー", + "Chang_Feng": "長風" + }, + "BearWaitress2": { + "name": "白クマ茶房の給仕2", + "help": "2つの給仕スロットに順序はありません。無は空きスロット、両方が無ならレストランを停止します。任意は管理レベルが最も高い空きキャラクターを選びます。指定キャラクターを優先し、重複した指定は消去します。", + "none": "無", + "any": "任意", + "Cheshire": "チェシャー", + "Chang_Feng": "長風" + }, + "BearMenu": { + "name": "白クマ茶房のメニュー", + "help": "メニュー以外のものは販売されません。\nツールの離島生産ソルバーで自動生成されます。" + }, + "EateryGrade": { + "name": "饅頭軽食のランク", + "help": "", + "bronze": "ブロンズ", + "silver": "シルバー", + "gold": "ゴールド", + "diamond": "ダイヤモンド" + }, + "EateryWaitress1": { + "name": "饅頭軽食の給仕1", + "help": "2つの給仕スロットに順序はありません。無は空きスロット、両方が無ならレストランを停止します。任意は管理レベルが最も高い空きキャラクターを選びます。指定キャラクターを優先し、重複した指定は消去します。", + "none": "無", + "any": "任意", + "Helena": "ヘレナ", + "Prinz_Eugen": "プリンツ・オイゲン", + "Chang_Feng": "長風" + }, + "EateryWaitress2": { + "name": "饅頭軽食の給仕2", + "help": "2つの給仕スロットに順序はありません。無は空きスロット、両方が無ならレストランを停止します。任意は管理レベルが最も高い空きキャラクターを選びます。指定キャラクターを優先し、重複した指定は消去します。", + "none": "無", + "any": "任意", + "Helena": "ヘレナ", + "Prinz_Eugen": "プリンツ・オイゲン", + "Chang_Feng": "長風" + }, + "EateryMenu": { + "name": "饅頭軽食のメニュー", + "help": "メニュー以外のものは販売されません。\nツールの離島生産ソルバーで自動生成されます。" + }, + "GrillGrade": { + "name": "烏魚焼肉のランク", + "help": "", + "bronze": "ブロンズ", + "silver": "シルバー", + "gold": "ゴールド", + "diamond": "ダイヤモンド" + }, + "GrillWaitress1": { + "name": "烏魚焼肉の給仕1", + "help": "2つの給仕スロットに順序はありません。無は空きスロット、両方が無ならレストランを停止します。任意は管理レベルが最も高い空きキャラクターを選びます。指定キャラクターを優先し、重複した指定は消去します。", + "none": "無", + "any": "任意", + "August_von_Parseval": "アウグスト・フォン・パーセヴァル", + "Prinz_Eugen": "プリンツ・オイゲン", + "Chang_Feng": "長風" + }, + "GrillWaitress2": { + "name": "烏魚焼肉の給仕2", + "help": "2つの給仕スロットに順序はありません。無は空きスロット、両方が無ならレストランを停止します。任意は管理レベルが最も高い空きキャラクターを選びます。指定キャラクターを優先し、重複した指定は消去します。", + "none": "無", + "any": "任意", + "August_von_Parseval": "アウグスト・フォン・パーセヴァル", + "Prinz_Eugen": "プリンツ・オイゲン", + "Chang_Feng": "長風" + }, + "GrillMenu": { + "name": "烏魚焼肉のメニュー", + "help": "メニュー以外のものは販売されません。\nツールの離島生産ソルバーで自動生成されます。" + }, + "CafeGrade": { + "name": "饅頭カフェのランク", + "help": "", + "bronze": "ブロンズ", + "silver": "シルバー", + "gold": "ゴールド", + "diamond": "ダイヤモンド" + }, + "CafeWaitress1": { + "name": "饅頭カフェの給仕1", + "help": "2つの給仕スロットに順序はありません。無は空きスロット、両方が無ならレストランを停止します。任意は管理レベルが最も高い空きキャラクターを選びます。指定キャラクターを優先し、重複した指定は消去します。", + "none": "無", + "any": "任意", + "Cheshire": "チェシャー", + "Belfast": "ベルファスト", + "Chang_Feng": "長風" + }, + "CafeWaitress2": { + "name": "饅頭カフェの給仕2", + "help": "2つの給仕スロットに順序はありません。無は空きスロット、両方が無ならレストランを停止します。任意は管理レベルが最も高い空きキャラクターを選びます。指定キャラクターを優先し、重複した指定は消去します。", + "none": "無", + "any": "任意", + "Cheshire": "チェシャー", + "Belfast": "ベルファスト", + "Chang_Feng": "長風" + }, + "CafeMenu": { + "name": "饅頭カフェのメニュー", + "help": "メニュー以外のものは販売されません。\nツールの離島生産ソルバーで自動生成されます。" + } + }, "IslandSeasonTask": { "_info": { "name": "開発計画", diff --git a/module/config/i18n/zh-CN.json b/module/config/i18n/zh-CN.json index d81e6ef4a..46e0b28f2 100644 --- a/module/config/i18n/zh-CN.json +++ b/module/config/i18n/zh-CN.json @@ -266,6 +266,10 @@ "name": "开发计划", "help": "" }, + "IslandBusiness": { + "name": "店铺经营", + "help": "" + }, "Daemon": { "name": "半自动点击", "help": "" @@ -2601,6 +2605,158 @@ "help": "" } }, + "IslandRestaurant": { + "_info": { + "name": "餐厅管理", + "help": "" + }, + "KoiGrade": { + "name": "有鱼餐馆等级", + "help": "", + "bronze": "青铜", + "silver": "白银", + "gold": "黄金", + "diamond": "钻石" + }, + "KoiWaitress1": { + "name": "有鱼餐馆服务员1", + "help": "两个服务员槽位无顺序。无表示空槽位,两个槽位都为无时停用餐厅;任意会选择管理等级最高的空闲角色。命名角色优先选择,重复的命名角色会被清空。", + "none": "无", + "any": "任意", + "Chao_Ho": "肇和", + "Chang_Feng": "长风" + }, + "KoiWaitress2": { + "name": "有鱼餐馆服务员2", + "help": "两个服务员槽位无顺序。无表示空槽位,两个槽位都为无时停用餐厅;任意会选择管理等级最高的空闲角色。命名角色优先选择,重复的命名角色会被清空。", + "none": "无", + "any": "任意", + "Chao_Ho": "肇和", + "Chang_Feng": "长风" + }, + "KoiMenu": { + "name": "有鱼餐馆菜单", + "help": "只销售菜单里指定的菜品。\n通过工具中的岛屿生产规划器自动生成" + }, + "BearGrade": { + "name": "白熊饮品等级", + "help": "", + "bronze": "青铜", + "silver": "白银", + "gold": "黄金", + "diamond": "钻石" + }, + "BearWaitress1": { + "name": "白熊饮品服务员1", + "help": "两个服务员槽位无顺序。无表示空槽位,两个槽位都为无时停用餐厅;任意会选择管理等级最高的空闲角色。命名角色优先选择,重复的命名角色会被清空。", + "none": "无", + "any": "任意", + "Cheshire": "柴郡", + "Chang_Feng": "长风" + }, + "BearWaitress2": { + "name": "白熊饮品服务员2", + "help": "两个服务员槽位无顺序。无表示空槽位,两个槽位都为无时停用餐厅;任意会选择管理等级最高的空闲角色。命名角色优先选择,重复的命名角色会被清空。", + "none": "无", + "any": "任意", + "Cheshire": "柴郡", + "Chang_Feng": "长风" + }, + "BearMenu": { + "name": "白熊饮品菜单", + "help": "只销售菜单里指定的菜品。\n通过工具中的岛屿生产规划器自动生成" + }, + "EateryGrade": { + "name": "啾啾简餐等级", + "help": "", + "bronze": "青铜", + "silver": "白银", + "gold": "黄金", + "diamond": "钻石" + }, + "EateryWaitress1": { + "name": "啾啾简餐服务员1", + "help": "两个服务员槽位无顺序。无表示空槽位,两个槽位都为无时停用餐厅;任意会选择管理等级最高的空闲角色。命名角色优先选择,重复的命名角色会被清空。", + "none": "无", + "any": "任意", + "Helena": "海伦娜", + "Prinz_Eugen": "欧根亲王", + "Chang_Feng": "长风" + }, + "EateryWaitress2": { + "name": "啾啾简餐服务员2", + "help": "两个服务员槽位无顺序。无表示空槽位,两个槽位都为无时停用餐厅;任意会选择管理等级最高的空闲角色。命名角色优先选择,重复的命名角色会被清空。", + "none": "无", + "any": "任意", + "Helena": "海伦娜", + "Prinz_Eugen": "欧根亲王", + "Chang_Feng": "长风" + }, + "EateryMenu": { + "name": "啾啾简餐菜单", + "help": "只销售菜单里指定的菜品。\n通过工具中的岛屿生产规划器自动生成" + }, + "GrillGrade": { + "name": "乌鱼烤肉等级", + "help": "", + "bronze": "青铜", + "silver": "白银", + "gold": "黄金", + "diamond": "钻石" + }, + "GrillWaitress1": { + "name": "乌鱼烤肉服务员1", + "help": "两个服务员槽位无顺序。无表示空槽位,两个槽位都为无时停用餐厅;任意会选择管理等级最高的空闲角色。命名角色优先选择,重复的命名角色会被清空。", + "none": "无", + "any": "任意", + "August_von_Parseval": "奥古斯特·冯·帕塞瓦尔", + "Prinz_Eugen": "欧根亲王", + "Chang_Feng": "长风" + }, + "GrillWaitress2": { + "name": "乌鱼烤肉服务员2", + "help": "两个服务员槽位无顺序。无表示空槽位,两个槽位都为无时停用餐厅;任意会选择管理等级最高的空闲角色。命名角色优先选择,重复的命名角色会被清空。", + "none": "无", + "any": "任意", + "August_von_Parseval": "奥古斯特·冯·帕塞瓦尔", + "Prinz_Eugen": "欧根亲王", + "Chang_Feng": "长风" + }, + "GrillMenu": { + "name": "乌鱼烤肉菜单", + "help": "只销售菜单里指定的菜品。\n通过工具中的岛屿生产规划器自动生成" + }, + "CafeGrade": { + "name": "啾咖啡等级", + "help": "", + "bronze": "青铜", + "silver": "白银", + "gold": "黄金", + "diamond": "钻石" + }, + "CafeWaitress1": { + "name": "啾咖啡服务员1", + "help": "两个服务员槽位无顺序。无表示空槽位,两个槽位都为无时停用餐厅;任意会选择管理等级最高的空闲角色。命名角色优先选择,重复的命名角色会被清空。", + "none": "无", + "any": "任意", + "Cheshire": "柴郡", + "Belfast": "贝尔法斯特", + "Chang_Feng": "长风" + }, + "CafeWaitress2": { + "name": "啾咖啡服务员2", + "help": "两个服务员槽位无顺序。无表示空槽位,两个槽位都为无时停用餐厅;任意会选择管理等级最高的空闲角色。命名角色优先选择,重复的命名角色会被清空。", + "none": "无", + "any": "任意", + "Cheshire": "柴郡", + "Belfast": "贝尔法斯特", + "Chang_Feng": "长风" + }, + "CafeMenu": { + "name": "啾咖啡菜单", + "help": "只销售菜单里指定的菜品。\n通过工具中的岛屿生产规划器自动生成" + } + }, "IslandSeasonTask": { "_info": { "name": "开发计划", diff --git a/module/config/i18n/zh-TW.json b/module/config/i18n/zh-TW.json index e936f3b33..48e928ac8 100644 --- a/module/config/i18n/zh-TW.json +++ b/module/config/i18n/zh-TW.json @@ -266,6 +266,10 @@ "name": "開發計劃", "help": "" }, + "IslandBusiness": { + "name": "店鋪經營", + "help": "" + }, "Daemon": { "name": "半自動點擊", "help": "" @@ -2601,6 +2605,158 @@ "help": "" } }, + "IslandRestaurant": { + "_info": { + "name": "餐廳管理", + "help": "" + }, + "KoiGrade": { + "name": "有魚餐館等級", + "help": "", + "bronze": "青銅", + "silver": "白銀", + "gold": "黃金", + "diamond": "鑽石" + }, + "KoiWaitress1": { + "name": "有魚餐館服務員1", + "help": "兩個服務員槽位沒有順序。無表示空槽位,兩個槽位都是無時停用餐廳;任意會選擇管理等級最高的空閒角色。命名角色優先選擇,重複的命名角色會被清除。", + "none": "無", + "any": "任意", + "Chao_Ho": "肇和", + "Chang_Feng": "長風" + }, + "KoiWaitress2": { + "name": "有魚餐館服務員2", + "help": "兩個服務員槽位沒有順序。無表示空槽位,兩個槽位都是無時停用餐廳;任意會選擇管理等級最高的空閒角色。命名角色優先選擇,重複的命名角色會被清除。", + "none": "無", + "any": "任意", + "Chao_Ho": "肇和", + "Chang_Feng": "長風" + }, + "KoiMenu": { + "name": "有魚餐館菜單", + "help": "只銷售菜單裡指定的菜品。\n通過工具中的離島生產規劃器自動生成" + }, + "BearGrade": { + "name": "白熊飲品等級", + "help": "", + "bronze": "青銅", + "silver": "白銀", + "gold": "黃金", + "diamond": "鑽石" + }, + "BearWaitress1": { + "name": "白熊飲品服務員1", + "help": "兩個服務員槽位沒有順序。無表示空槽位,兩個槽位都是無時停用餐廳;任意會選擇管理等級最高的空閒角色。命名角色優先選擇,重複的命名角色會被清除。", + "none": "無", + "any": "任意", + "Cheshire": "柴郡", + "Chang_Feng": "長風" + }, + "BearWaitress2": { + "name": "白熊飲品服務員2", + "help": "兩個服務員槽位沒有順序。無表示空槽位,兩個槽位都是無時停用餐廳;任意會選擇管理等級最高的空閒角色。命名角色優先選擇,重複的命名角色會被清除。", + "none": "無", + "any": "任意", + "Cheshire": "柴郡", + "Chang_Feng": "長風" + }, + "BearMenu": { + "name": "白熊飲品菜單", + "help": "只銷售菜單裡指定的饮品。\n通過工具中的離島生產規劃器自動生成" + }, + "EateryGrade": { + "name": "啾啾簡餐等級", + "help": "", + "bronze": "青銅", + "silver": "白銀", + "gold": "黃金", + "diamond": "鑽石" + }, + "EateryWaitress1": { + "name": "啾啾簡餐服務員1", + "help": "兩個服務員槽位沒有順序。無表示空槽位,兩個槽位都是無時停用餐廳;任意會選擇管理等級最高的空閒角色。命名角色優先選擇,重複的命名角色會被清除。", + "none": "無", + "any": "任意", + "Helena": "海倫娜", + "Prinz_Eugen": "歐根親王", + "Chang_Feng": "長風" + }, + "EateryWaitress2": { + "name": "啾啾簡餐服務員2", + "help": "兩個服務員槽位沒有順序。無表示空槽位,兩個槽位都是無時停用餐廳;任意會選擇管理等級最高的空閒角色。命名角色優先選擇,重複的命名角色會被清除。", + "none": "無", + "any": "任意", + "Helena": "海倫娜", + "Prinz_Eugen": "歐根親王", + "Chang_Feng": "長風" + }, + "EateryMenu": { + "name": "啾啾簡餐菜單", + "help": "只銷售菜單裡指定的菜品。\n通過工具中的離島生產規劃器自動生成" + }, + "GrillGrade": { + "name": "烏魚烤肉等級", + "help": "", + "bronze": "青銅", + "silver": "白銀", + "gold": "黃金", + "diamond": "鑽石" + }, + "GrillWaitress1": { + "name": "烏魚烤肉服務員1", + "help": "兩個服務員槽位沒有順序。無表示空槽位,兩個槽位都是無時停用餐廳;任意會選擇管理等級最高的空閒角色。命名角色優先選擇,重複的命名角色會被清除。", + "none": "無", + "any": "任意", + "August_von_Parseval": "奧古斯特·馮·帕塞瓦爾", + "Prinz_Eugen": "歐根親王", + "Chang_Feng": "長風" + }, + "GrillWaitress2": { + "name": "烏魚烤肉服務員2", + "help": "兩個服務員槽位沒有順序。無表示空槽位,兩個槽位都是無時停用餐廳;任意會選擇管理等級最高的空閒角色。命名角色優先選擇,重複的命名角色會被清除。", + "none": "無", + "any": "任意", + "August_von_Parseval": "奧古斯特·馮·帕塞瓦爾", + "Prinz_Eugen": "歐根親王", + "Chang_Feng": "長風" + }, + "GrillMenu": { + "name": "烏魚烤肉菜單", + "help": "只銷售菜單裡指定的菜品。\n通過工具中的離島生產規劃器自動生成" + }, + "CafeGrade": { + "name": "啾咖啡等級", + "help": "", + "bronze": "青銅", + "silver": "白銀", + "gold": "黃金", + "diamond": "鑽石" + }, + "CafeWaitress1": { + "name": "啾咖啡服務員1", + "help": "兩個服務員槽位沒有順序。無表示空槽位,兩個槽位都是無時停用餐廳;任意會選擇管理等級最高的空閒角色。命名角色優先選擇,重複的命名角色會被清除。", + "none": "無", + "any": "任意", + "Cheshire": "柴郡", + "Belfast": "貝爾法斯特", + "Chang_Feng": "長風" + }, + "CafeWaitress2": { + "name": "啾咖啡服務員2", + "help": "兩個服務員槽位沒有順序。無表示空槽位,兩個槽位都是無時停用餐廳;任意會選擇管理等級最高的空閒角色。命名角色優先選擇,重複的命名角色會被清除。", + "none": "無", + "any": "任意", + "Cheshire": "柴郡", + "Belfast": "貝爾法斯特", + "Chang_Feng": "長風" + }, + "CafeMenu": { + "name": "啾咖啡菜單", + "help": "只銷售菜單裡指定的菜品。\n通過工具中的離島生產規劃器自動生成" + } + }, "IslandSeasonTask": { "_info": { "name": "開發計劃", diff --git a/module/island_handler/restaurant_config.py b/module/island_handler/restaurant_config.py new file mode 100644 index 000000000..52b8290b9 --- /dev/null +++ b/module/island_handler/restaurant_config.py @@ -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)