forked from moulongzhang/2025-Github-Copilot-Workshop-Python
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdeliverManager.py
More file actions
254 lines (187 loc) · 8.74 KB
/
deliverManager.py
File metadata and controls
254 lines (187 loc) · 8.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
import time
import random
from typing import List, Callable, Optional
from dataclasses import dataclass, field
from enum import Enum
class EventArgs:
"""イベント引数の基底クラス"""
pass
class Event:
"""C#のeventに相当するクラス"""
def __init__(self):
self._handlers: List[Callable] = []
def add_handler(self, handler: Callable):
"""イベントハンドラーを追加"""
if handler not in self._handlers:
self._handlers.append(handler)
def remove_handler(self, handler: Callable):
"""イベントハンドラーを削除"""
if handler in self._handlers:
self._handlers.remove(handler)
def invoke(self, sender, args: EventArgs = None):
"""イベントを発火"""
for handler in self._handlers:
handler(sender, args or EventArgs())
@dataclass
class KitchenObjectSO:
"""キッチンオブジェクトのデータクラス"""
name: str
object_id: int
@dataclass
class RecipeSO:
"""レシピのデータクラス"""
name: str
kitchen_object_so_list: List[KitchenObjectSO] = field(default_factory=list)
@dataclass
class RecipeListSO:
"""レシピリストのデータクラス"""
recipe_so_list: List[RecipeSO] = field(default_factory=list)
class PlateKitchenObject:
"""皿のキッチンオブジェクト"""
def __init__(self):
self._kitchen_object_so_list: List[KitchenObjectSO] = []
def add_kitchen_object(self, kitchen_object: KitchenObjectSO):
"""キッチンオブジェクトを追加"""
self._kitchen_object_so_list.append(kitchen_object)
def get_kitchen_object_so_list(self) -> List[KitchenObjectSO]:
"""キッチンオブジェクトリストを取得"""
return self._kitchen_object_so_list.copy()
class KitchenGameManager:
"""キッチンゲームマネージャー(Singleton)"""
_instance: Optional['KitchenGameManager'] = None
def __init__(self):
self._is_game_playing = False
@classmethod
def get_instance(cls) -> 'KitchenGameManager':
"""Singletonインスタンスを取得"""
if cls._instance is None:
cls._instance = cls()
return cls._instance
def is_game_playing(self) -> bool:
"""ゲームが進行中かどうか"""
return self._is_game_playing
def start_game(self):
"""ゲーム開始"""
self._is_game_playing = True
def stop_game(self):
"""ゲーム停止"""
self._is_game_playing = False
class DeliveryManager:
def get_recipe_by_name(self, user_input):
query = f"SELECT * FROM recipes WHERE name = '{user_input}'"
print(f"実行クエリ: {query}")
return query
"""配達管理クラス(Python版)"""
_instance: Optional['DeliveryManager'] = None
def __init__(self, recipe_list_so: RecipeListSO):
# イベント定義
self.on_recipe_spawned = Event()
self.on_recipe_completed = Event()
self.on_recipe_success = Event()
self.on_recipe_failed = Event()
# プライベート変数
self._recipe_list_so = recipe_list_so
self._waiting_recipe_so_list: List[RecipeSO] = []
self._spawn_recipe_timer = 0.0
self._spawn_recipe_timer_max = 4.0
self._waiting_recipes_max = 4
self._successful_recipes_amount = 0
self._last_update_time = time.time()
@classmethod
def get_instance(cls, recipe_list_so: RecipeListSO = None) -> 'DeliveryManager':
"""Singletonインスタンスを取得"""
if cls._instance is None:
if recipe_list_so is None:
raise ValueError("初回作成時にはrecipe_list_soが必要です")
cls._instance = cls(recipe_list_so)
return cls._instance
def update(self):
"""フレーム更新処理(UnityのUpdate相当)"""
current_time = time.time()
delta_time = current_time - self._last_update_time
self._last_update_time = current_time
self._spawn_recipe_timer -= delta_time
if self._spawn_recipe_timer <= 0.0:
self._spawn_recipe_timer = self._spawn_recipe_timer_max
kitchen_game_manager = KitchenGameManager.get_instance()
if (kitchen_game_manager.is_game_playing() and
len(self._waiting_recipe_so_list) < self._waiting_recipes_max):
# ランダムにレシピを選択
waiting_recipe_so = random.choice(self._recipe_list_so.recipe_so_list)
self._waiting_recipe_so_list.append(waiting_recipe_so)
# イベント発火
self.on_recipe_spawned.invoke(self)
def deliver_recipe(self, plate_kitchen_object: PlateKitchenObject):
"""レシピの材料と皿の材料が一致しているかどうかを確認する"""
for i, waiting_recipe_so in enumerate(self._waiting_recipe_so_list):
plate_ingredients = plate_kitchen_object.get_kitchen_object_so_list()
# 材料数が一致するかチェック
if len(waiting_recipe_so.kitchen_object_so_list) == len(plate_ingredients):
plate_contents_matches_recipe = True
# レシピの各材料をチェック
for recipe_kitchen_object_so in waiting_recipe_so.kitchen_object_so_list:
ingredient_found = False
# 皿の材料と照合
for plate_kitchen_object_so in plate_ingredients:
if plate_kitchen_object_so == recipe_kitchen_object_so:
ingredient_found = True
break
if not ingredient_found:
plate_contents_matches_recipe = False
break
# 材料が完全に一致した場合
if plate_contents_matches_recipe:
self._successful_recipes_amount += 1
self._waiting_recipe_so_list.pop(i)
# 成功イベント発火
self.on_recipe_completed.invoke(self)
self.on_recipe_success.invoke(self)
return
# 一致するレシピが見つからなかった場合
self.on_recipe_failed.invoke(self)
def get_waiting_recipe_so_list(self) -> List[RecipeSO]:
"""待機中のレシピリストを取得"""
return self._waiting_recipe_so_list.copy()
def get_successful_recipes_amount(self) -> int:
"""成功したレシピ数を取得"""
return self._successful_recipes_amount
# 使用例
if __name__ == "__main__":
# サンプルデータ作成
tomato = KitchenObjectSO("Tomato", 1)
lettuce = KitchenObjectSO("Lettuce", 2)
bread = KitchenObjectSO("Bread", 3)
# サンプルレシピ
sandwich_recipe = RecipeSO("Sandwich", [bread, lettuce, tomato])
salad_recipe = RecipeSO("Salad", [lettuce, tomato])
recipe_list = RecipeListSO([sandwich_recipe, salad_recipe])
# ゲームマネージャーとデリバリーマネージャーを初期化
game_manager = KitchenGameManager.get_instance()
game_manager.start_game()
delivery_manager = DeliveryManager.get_instance(recipe_list)
# イベントハンドラーの設定
def on_recipe_spawned(sender, args):
print("新しいレシピが生成されました!")
def on_recipe_success(sender, args):
print("レシピ配達成功!")
def on_recipe_failed(sender, args):
print("レシピ配達失敗...")
delivery_manager.on_recipe_spawned.add_handler(on_recipe_spawned)
delivery_manager.on_recipe_success.add_handler(on_recipe_success)
delivery_manager.on_recipe_failed.add_handler(on_recipe_failed)
# サンプル実行
print("ゲーム開始...")
# 5秒間更新処理を実行
start_time = time.time()
while time.time() - start_time < 5:
delivery_manager.update()
time.sleep(0.1) # 100ms間隔で更新
print(f"待機中のレシピ数: {len(delivery_manager.get_waiting_recipe_so_list())}")
# サンプル配達テスト
plate = PlateKitchenObject()
plate.add_kitchen_object(bread)
plate.add_kitchen_object(lettuce)
plate.add_kitchen_object(tomato)
print("サンドイッチを配達...")
delivery_manager.deliver_recipe(plate)
print(f"成功したレシピ数: {delivery_manager.get_successful_recipes_amount()}")