Geo-Lab / engine /script_engine.py
HANSOL
Fix landform animations: barchan, U-valley, volcanoes, lava plateau; add Lab page, zone overlay
857bbdd
import numpy as np
import math
from .grid import WorldGrid
from .fluids import HydroKernel
from .erosion_process import ErosionProcess
class ScriptExecutor:
"""
์‚ฌ์šฉ์ž ์ •์˜ ์Šคํฌ๋ฆฝํŠธ ์‹คํ–‰ ์—”์ง„
๋ณด์•ˆ์„ ์œ„ํ•ด ์ œํ•œ๋œ ํ™˜๊ฒฝ์—์„œ Python ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
"""
def __init__(self, grid: WorldGrid):
self.grid = grid
self.hydro = HydroKernel(grid)
self.erosion = ErosionProcess(grid)
def execute(self, script: str, dt: float = 1.0, allowed_modules: list = ['numpy', 'math']):
"""
์Šคํฌ๋ฆฝํŠธ ์‹คํ–‰
Args:
script: ์‹คํ–‰ํ•  Python ์ฝ”๋“œ ๋ฌธ์ž์—ด
dt: ์‹œ๊ฐ„ ๊ฐ„๊ฒฉ (Time Step)
allowed_modules: ํ—ˆ์šฉํ•  ๋ชจ๋“ˆ ๋ฆฌ์ŠคํŠธ (๊ธฐ๋ณธ: numpy, math)
Available Variables in Context:
- grid: WorldGrid ๊ฐ์ฒด
- elevation: grid.elevation (Numpy Array)
- bedrock: grid.bedrock
- sediment: grid.sediment
- water_depth: grid.water_depth
- dt: Delta Time
- np: numpy module
- math: math module
- hydro: HydroKernel ๊ฐ์ฒด
- erosion: ErosionProcess ๊ฐ์ฒด
"""
# 1. ์‹คํ–‰ ์ปจํ…์ŠคํŠธ(Namespace) ์ค€๋น„
context = {
'grid': self.grid,
'elevation': self.grid.elevation,
'bedrock': self.grid.bedrock,
'sediment': self.grid.sediment,
'water_depth': self.grid.water_depth,
'dt': dt,
'np': np,
'math': math,
'hydro': self.hydro,
'erosion': self.erosion,
# Helper functions
'max': max,
'min': min,
'abs': abs,
'pow': pow,
'print': print, # ๋””๋ฒ„๊น…์šฉ
'range': range,
'len': len,
'int': int,
'float': float,
'round': round,
'sum': sum,
'enumerate': enumerate,
'zip': zip,
'list': list,
'tuple': tuple,
'dict': dict,
'set': set,
'str': str,
'bool': bool,
'True': True,
'False': False,
'None': None,
}
# 2. ๊ธˆ์ง€๋œ ํ‚ค์›Œ๋“œ ์ฒดํฌ (๊ธฐ๋ณธ์ ์ธ ๋ณด์•ˆ)
# ์™„๋ฒฝํ•œ ์ƒŒ๋“œ๋ฐ•์Šค๋Š” ์•„๋‹ˆ์ง€๋งŒ, ์‹ค์ˆ˜ ๋ฐฉ์ง€์šฉ
forbidden = ['import os', 'import sys', 'open(', 'exec(', 'eval(', '__import__']
for bad in forbidden:
if bad in script:
raise ValueError(f"๋ณด์•ˆ ๊ฒฝ๊ณ : ํ—ˆ์šฉ๋˜์ง€ ์•Š๋Š” ํ‚ค์›Œ๋“œ '{bad}'๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.")
# 3. ์ฝ”๋“œ ์‹คํ–‰
try:
exec(script, {"__builtins__": {}}, context)
# 4. ๋ณ€๊ฒฝ ์‚ฌํ•ญ ๋ฐ˜์˜ (Elevation์€ derived property์ง€๋งŒ, ์ง์ ‘ ์ˆ˜์ •ํ–ˆ์„ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ)
# ์‚ฌ์šฉ์ž๊ฐ€ elevation์„ ์ˆ˜์ •ํ–ˆ๋‹ค๋ฉด bedrock/sediment ์—…๋ฐ์ดํŠธ๊ฐ€ ๋ชจํ˜ธํ•ด์ง.
# Grid ํด๋ž˜์Šค์˜ update_elevation()์€ bedrock+sediment -> elevation์ด๋ฏ€๋กœ,
# ์‚ฌ์šฉ์ž๊ฐ€ elevation์„ ์ˆ˜์ •ํ•˜๋ฉด ๋ฌด์‹œ๋  ์ˆ˜ ์žˆ์Œ.
# ๊ฐ€์ด๋“œ: "bedrock"์ด๋‚˜ "sediment"๋ฅผ ์ˆ˜์ •ํ•˜์„ธ์š”.
# ํ•˜์ง€๋งŒ ํŽธ์˜๋ฅผ ์œ„ํ•ด elevation์ด ๋ฐ”๋€Œ์—ˆ์œผ๋ฉด bedrock์— ๋ฐ˜์˜ํ•˜๋Š” ๋กœ์ง ์ถ”๊ฐ€
# ๋ณ€๊ฒฝ ์ „ elevation๊ณผ ๋น„๊ตํ•ด์•ผ ํ•˜๋‚˜?
# ์ผ๋‹จ grid.update_elevation()์„ ํ˜ธ์ถœํ•˜์—ฌ ๋™๊ธฐํ™”
# (๋งŒ์•ฝ ์‚ฌ์šฉ์ž๊ฐ€ bedrock์„ ๋ฐ”๊ฟจ๋‹ค๋ฉด ๋ฐ˜์˜๋จ)
self.grid.update_elevation()
return True, "์‹คํ–‰ ์„ฑ๊ณต"
except Exception as e:
return False, f"์‹คํ–‰ ์˜ค๋ฅ˜: {str(e)}"