예전 프로그램 이름 표기 정리: 실행 파일 이름을 start-spipe.bat, stop-spipe.bat로 변경
- README, 예제 설명, 코드 주석, CSS 머리말, 시험 임시 폴더 접두어의 예전 이름 정리 - 브라우저 저장 키·세션 DB 이름은 저장된 설정 보존을 위해 유지
This commit is contained in:
1 parent
eb153f61e1
commit
14f07181db
13 files changed
+28
-22
No files matched your search
@@ -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`.
|
||||
|
||||
수동 실행:
|
||||
|
||||
|
||||
@@ -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 이름, 복사·붙여넣기 표시의 예전 접두어. 바꾸면 사용자의 저장된 설정·세션이 초기화되므로 이전(마이그레이션) 방식을 정한 뒤 변경
|
||||
@@ -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]`), 규칙 기반이 아닌 시간/수위 조건 제어
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -699,7 +699,7 @@ export const FullAttributeTableModal: React.FC<FullAttributeTableModalProps> = (
|
||||
);
|
||||
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, {
|
||||
|
||||
@@ -489,7 +489,7 @@ export const OptionEditor: React.FC<OptionEditorProps> = ({
|
||||
);
|
||||
};
|
||||
|
||||
/** 고급 해석 옵션: the rest of EPANET's [OPTIONS] (GISpipe 수리 설정 parity). */
|
||||
/** 고급 해석 옵션: the rest of EPANET's [OPTIONS] (상용 관망 프로그램 수리 설정 parity). */
|
||||
const AdvancedOptions: React.FC<{
|
||||
options: InpOptions;
|
||||
patternIds: string[];
|
||||
|
||||
@@ -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 (읽기 전용: 현재 미지원)' },
|
||||
|
||||
+1
-1
@@ -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
|
||||
============================================================================= */
|
||||
|
||||
+2
-2
@@ -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
|
||||
|
||||
+1
-1
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
File renamed without changes.
@@ -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');
|
||||
|
||||
Reference in new issue
Block a user