From 14f07181dbac334791f18fb7c99217f8b25e5fb1 Mon Sep 17 00:00:00 2001 From: tpstn23 Date: Fri, 30 Oct 2026 11:07:14 +0900 Subject: [PATCH] =?UTF-8?q?=EC=98=88=EC=A0=84=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EB=9E=A8=20=EC=9D=B4=EB=A6=84=20=ED=91=9C=EA=B8=B0=20?= =?UTF-8?q?=EC=A0=95=EB=A6=AC:=20=EC=8B=A4=ED=96=89=20=ED=8C=8C=EC=9D=BC?= =?UTF-8?q?=20=EC=9D=B4=EB=A6=84=EC=9D=84=20start-spipe.bat,=20stop-spipe.?= =?UTF-8?q?bat=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - README, 예제 설명, 코드 주석, CSS 머리말, 시험 임시 폴더 접두어의 예전 이름 정리 - 브라우저 저장 키·세션 DB 이름은 저장된 설정 보존을 위해 유지 --- README.md | 4 ++-- _worklog.md | 6 ++++++ public/EXAMPLE_NETWORKS.md | 6 +++--- src/CurveEditorModal.tsx | 2 +- src/FullAttributeTableModal.tsx | 2 +- src/OptionEditor.tsx | 2 +- src/attributeTableValidation.ts | 2 +- src/index.css | 2 +- src/inpModel.ts | 4 ++-- src/unitSystem.ts | 2 +- start-gispipe.bat => start-spipe.bat | 2 +- stop-gispipe.bat => stop-spipe.bat | 0 tests/regression.test.ts | 16 ++++++++-------- 13 files changed, 28 insertions(+), 22 deletions(-) rename start-gispipe.bat => start-spipe.bat (94%) rename stop-gispipe.bat => stop-spipe.bat (100%) diff --git a/README.md b/README.md index 4e57298..35dcf9d 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ EPANET 2.3.5 엔진으로 관망을 해석하고, GIS·DEM·자산 정보를 한 ### 기존 운영 방식 -설치형 프로그램(EPANET, GISpipe 등)을 PC마다 설치하고, 관망 파일·GIS 자료·DEM·엑셀 자료를 파일 단위로 주고받으며 작업하는 구조. +설치형 관망해석 프로그램(EPANET 등)을 PC마다 설치하고, 관망 파일·GIS 자료·DEM·엑셀 자료를 파일 단위로 주고받으며 작업하는 구조. ### 기존 문제 @@ -97,7 +97,7 @@ py -3.12 -m venv .venv .\.venv\Scripts\python.exe -m pip install -r backend\requirements.txt pytest httpx ``` -가장 간단한 실행 방법은 `start-gispipe.bat` 더블클릭입니다. 해석 API(8000)와 웹 개발 서버(5173)를 함께 띄우고 브라우저를 엽니다. 종료는 `stop-gispipe.bat`. +가장 간단한 실행 방법은 `start-spipe.bat` 더블클릭입니다. 해석 API(8000)와 웹 개발 서버(5173)를 함께 띄우고 브라우저를 엽니다. 종료는 `stop-spipe.bat`. 수동 실행: diff --git a/_worklog.md b/_worklog.md index d4d59d0..1e03b49 100644 --- a/_worklog.md +++ b/_worklog.md @@ -11,3 +11,9 @@ - README: 원본 README에 데모 v2 서버 업데이트 순서를 추가하고, 저장소에 없는 문서 목차를 정리 - 서버 반영: 기존 폴더에 덮어쓰기(`.venv`·`node_modules`·`data`·`.env.local` 유지) → `pip install -r backend\requirements.txt` → `start-lan.ps1 -Rebuild` - 남은 일: 서버 PC IP 확정 시 카카오 JavaScript SDK 도메인에 `http://<서버 IP>:8080` 추가 + +## 2026-10-30 예전 프로그램 이름 표기 정리 + +- 실행 파일 이름을 `start-spipe.bat`, `stop-spipe.bat`로 변경 (README·실행 안내 문구 함께 수정) +- README, `public/EXAMPLE_NETWORKS.md`, 코드 주석, CSS 머리말, 시험 임시 폴더 접두어의 예전 이름을 SPipe 또는 "상용 관망 프로그램"으로 변경 +- 그대로 둔 것: 브라우저 저장 키, 세션 DB 이름, 복사·붙여넣기 표시의 예전 접두어. 바꾸면 사용자의 저장된 설정·세션이 초기화되므로 이전(마이그레이션) 방식을 정한 뒤 변경 diff --git a/public/EXAMPLE_NETWORKS.md b/public/EXAMPLE_NETWORKS.md index 4bc7455..7e6780c 100644 --- a/public/EXAMPLE_NETWORKS.md +++ b/public/EXAMPLE_NETWORKS.md @@ -1,8 +1,8 @@ # 예제 관망 출처 및 라이선스 (Example Network Sources & License) -이 폴더의 `Net1.inp`, `Net2.inp`, `Net3.inp`는 GISPipe가 자체 제작한 데이터가 아니라, +이 폴더의 `Net1.inp`, `Net2.inp`, `Net3.inp`는 SPipe가 자체 제작한 데이터가 아니라, **Open Water Analytics(OWA)가 관리하는 공식 EPANET 오픈소스 저장소**에 포함된 표준 예제 -관망 파일을 그대로 가져온 것이다. 상용 GISPipe 또는 그 외 상용 관망해석 소프트웨어의 +관망 파일을 그대로 가져온 것이다. 상용 관망해석 소프트웨어의 샘플 데이터는 어떤 형태로도 사용하지 않았다. ## 출처 (Source) @@ -25,7 +25,7 @@ Open Water Analytics의 EPANET 저장소는 원본 USEPA(미국 환경보호청) ## 용도 -GISPipe의 Native(OWA-EPANET 2.3.5 C DLL)/WASM(epanet-js) 듀얼 엔진 해석 및 INP +SPipe의 Native(OWA-EPANET 2.3.5 C DLL)/WASM(epanet-js) 듀얼 엔진 해석 및 INP 파싱·재생성(round-trip) 신뢰성 회귀 테스트(`tests/regression.test.ts`)와 앱 UI의 "예제 로드" 선택 기능(Net1/Net2/Net3)에 사용된다. Net2/Net3는 각각 확장 EPS 지속시간, 다중 수요 패턴, 펌프 곡선(`[CURVES]`), 규칙 기반이 아닌 시간/수위 조건 제어 diff --git a/src/CurveEditorModal.tsx b/src/CurveEditorModal.tsx index cf7e0bf..5d0945c 100644 --- a/src/CurveEditorModal.tsx +++ b/src/CurveEditorModal.tsx @@ -1,5 +1,5 @@ // 곡선 편집: pump / efficiency / volume / headloss curves with a point table -// and a chart (GISpipe 커브 편집 parity). Edits are applied in one undoable step. +// and a chart (상용 관망 프로그램 커브 편집 parity). Edits are applied in one undoable step. import React, { useMemo, useState } from 'react'; import { X, Plus, Trash2 } from 'lucide-react'; import { addCurve, deleteCurve, getNextCurveId, type InpCurve, type NetworkModel } from './inpModel'; diff --git a/src/FullAttributeTableModal.tsx b/src/FullAttributeTableModal.tsx index ff5ef11..5280ab3 100644 --- a/src/FullAttributeTableModal.tsx +++ b/src/FullAttributeTableModal.tsx @@ -699,7 +699,7 @@ export const FullAttributeTableModal: React.FC = ( ); const tsv = [headers, ...lines].join('\n'); - // Also build GISPipe structured JSON if network elements + // Also build SPipe structured JSON if network elements let jsonString = ''; if (model && !category.startsWith('gis_')) { const payload = createNetworkClipboardPayload(model, selectedTarget, { diff --git a/src/OptionEditor.tsx b/src/OptionEditor.tsx index bcb59a8..ec7116c 100644 --- a/src/OptionEditor.tsx +++ b/src/OptionEditor.tsx @@ -489,7 +489,7 @@ export const OptionEditor: React.FC = ({ ); }; -/** 고급 해석 옵션: the rest of EPANET's [OPTIONS] (GISpipe 수리 설정 parity). */ +/** 고급 해석 옵션: the rest of EPANET's [OPTIONS] (상용 관망 프로그램 수리 설정 parity). */ const AdvancedOptions: React.FC<{ options: InpOptions; patternIds: string[]; diff --git a/src/attributeTableValidation.ts b/src/attributeTableValidation.ts index 2f504b4..fa0d0c1 100644 --- a/src/attributeTableValidation.ts +++ b/src/attributeTableValidation.ts @@ -87,7 +87,7 @@ export const PUMP_COLUMNS: ColumnDef[] = [ { key: 'parameters', label: 'Pump Curve', width: '120px', align: 'left', description: '펌프 특성 곡선 (HEAD Curve ID 또는 POWER/SPEED)' }, // pattern/status/tag/description are not yet parsed into any structured // pump field (status lives only in the raw-preserved [STATUS] section, and - // GISPipe never parses a per-pump pattern/tag/description at all), so + // SPipe never parses a per-pump pattern/tag/description at all), so // editing them here would silently do nothing -- read-only until that // parsing exists. { key: 'pattern', label: 'Pattern', width: '85px', align: 'left', readOnly: true, description: '가동 스케줄 패턴 ID (읽기 전용: 현재 미지원)' }, diff --git a/src/index.css b/src/index.css index e645a7f..4beb830 100644 --- a/src/index.css +++ b/src/index.css @@ -1,7 +1,7 @@ @import './styles/tokens.css'; /* ============================================================================= - GISPipe Workstation UI Styles + SPipe Workstation UI Styles High-density QGIS / Figma / Rhino / Linear style layout Uses tokens from src/styles/tokens.css ============================================================================= */ diff --git a/src/inpModel.ts b/src/inpModel.ts index 498b19e..69da632 100644 --- a/src/inpModel.ts +++ b/src/inpModel.ts @@ -589,7 +589,7 @@ export function deleteValve(model: NetworkModel, valveId: string): NetworkModel /** * [DEMANDS]/[QUALITY]/[SOURCES]/[EMITTERS]/[STATUS] are preserved as raw text - * (GISPipe does not parse them into the structured model -- see the matching + * (SPipe does not parse them into the structured model -- see the matching * blocks in checkUnitConversion), so a rename must still rewrite the leading * ID token of each raw line in those sections, or a renamed node/link would * leave those sections silently pointing at an ID that no longer exists. @@ -835,7 +835,7 @@ export function renamePump(model: NetworkModel, oldId: string, newId: string): N } /** - * True if a node has one or more raw [DEMANDS] category rows. GISPipe does + * True if a node has one or more raw [DEMANDS] category rows. SPipe does * not parse [DEMANDS] into the structured model (multi-category demands are * summed with the [JUNCTIONS] base demand by EPANET at solve time -- see * checkUnitConversion's DEMANDS block for the same rationale), so silently diff --git a/src/unitSystem.ts b/src/unitSystem.ts index b8d7e92..67ed900 100644 --- a/src/unitSystem.ts +++ b/src/unitSystem.ts @@ -382,7 +382,7 @@ function sectionHasData(model: NetworkModel, secName: string): boolean { /** * Verifies if the network model can be safely converted to the target unit. * Never allows a partial conversion: any construct this module cannot itself - * rewrite (because GISPipe does not parse it into the model) must block the + * rewrite (because SPipe does not parse it into the model) must block the * entire conversion with an explicit reason, rather than silently leaving it * un-converted while other values are scaled. */ diff --git a/start-gispipe.bat b/start-spipe.bat similarity index 94% rename from start-gispipe.bat rename to start-spipe.bat index 9d834c1..40e1249 100644 --- a/start-gispipe.bat +++ b/start-spipe.bat @@ -83,7 +83,7 @@ echo ======================================================== echo * Backend API : http://127.0.0.1:8000 echo * Web Frontend : http://127.0.0.1:5173 echo. -echo * To stop servers, double-click: stop-gispipe.bat +echo * To stop servers, double-click: stop-spipe.bat echo ======================================================== echo. pause diff --git a/stop-gispipe.bat b/stop-spipe.bat similarity index 100% rename from stop-gispipe.bat rename to stop-spipe.bat diff --git a/tests/regression.test.ts b/tests/regression.test.ts index c7cc6c3..ac88916 100644 --- a/tests/regression.test.ts +++ b/tests/regression.test.ts @@ -832,7 +832,7 @@ Full Synthesis Engine Test assert.ok(regen.trim().endsWith('[END]'), 'Must terminate with [END]'); assert.ok(regen.includes('[PIPES]'), 'Must include [PIPES]'); - const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gispipe_test_')); + const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'spipe_test_')); const inpPath = path.join(tmpDir, 'test_regen.inp'); const rptPath = path.join(tmpDir, 'test_regen.rpt'); const outPath = path.join(tmpDir, 'test_regen.out'); @@ -1197,7 +1197,7 @@ test('21. OFFICIAL EXAMPLE NETWORKS (Net1/Net2/Net3): parse -> generateInp -> re { name: 'Net3', path: 'public/Net3.inp', expectedNodes: 97, expectedLinks: 119 }, ]; - const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gispipe_examples_')); + const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'spipe_examples_')); try { for (const net of networks) { const raw = fs.readFileSync(net.path, 'utf-8'); @@ -1477,7 +1477,7 @@ test('23. GIS IMPORT & MULTILINESTRING: GeoJSON conversion with material roughne assert.ok(regen.includes('[PIPES]'), 'Regenerated INP must contain [PIPES]'); assert.ok(regen.trim().endsWith('[END]'), 'Regenerated INP must terminate with [END]'); - const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gispipe_geojson_')); + const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'spipe_geojson_')); try { const inpPath = path.join(tmpDir, 'gis_imported.inp'); const rptPath = path.join(tmpDir, 'gis_imported.rpt'); @@ -1529,7 +1529,7 @@ test('24. WATER QUALITY SIMULATION: execute Chlorine, Fluoride and Source Trace { name: 'Net3', path: 'public/Net3.inp', expectedType: 3, expectedChem: 'TRACE', expectedUnits: '% from' }, ]; - const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gispipe_qual_')); + const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'spipe_qual_')); try { for (const net of networks) { const pythonExe = path.resolve('.venv/Scripts/python.exe'); @@ -1619,7 +1619,7 @@ print('EPANET_QUALITY_OK') test('25. PUMP ENERGY & POWER ANALYSIS: compute kWh, peak kW, and efficiency in EPANET 2.3.5 C DLL', () => { // Verifies real-time power (kW), total energy (kWh), and efficiency (%) calculations // on pumps in Net1 (single pump) using actual variable time-step intervals. - const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gispipe_energy_')); + const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'spipe_energy_')); try { const pythonExe = path.resolve('.venv/Scripts/python.exe'); const pyFile = path.join(tmpDir, 'energy_runner.py'); @@ -1720,7 +1720,7 @@ print('EPANET_ENERGY_OK') }); test('26. BACKEND RUN_EPANET INTEGRATION: Net1 & Net3 pump energy integration, simultaneous peak, and returned series match', () => { const pythonExe = path.resolve('.venv/Scripts/python.exe'); - const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gispipe_be_energy_')); + const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'spipe_be_energy_')); try { const pyFile = path.join(tmpDir, 'test_be_energy.py'); fs.writeFileSync( @@ -1768,7 +1768,7 @@ print(json.dumps({ test('27. WATER QUALITY ERROR HANDLING: failed EN_runQ must flag status="failed" and not mask failure with zeros', () => { const pythonExe = path.resolve('.venv/Scripts/python.exe'); - const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gispipe_be_qual_')); + const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'spipe_be_qual_')); try { const pyFile = path.join(tmpDir, 'test_be_qual.py'); fs.writeFileSync( @@ -2009,7 +2009,7 @@ Table Edit Regeneration Test assert.ok(regen.includes('37.112233'), 'Regenerated INP must contain edited Y coordinate'); // Test solving in C DLL - const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gispipe_table_edit_')); + const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'spipe_table_edit_')); try { const inpPath = path.join(tmpDir, 'table_edited.inp'); const rptPath = path.join(tmpDir, 'table_edited.rpt');