Files
Pier_v1/수량산출/export.ts
T

38 lines
3.5 KiB
TypeScript

import {straightCopingFormulas} from './coping-formulas.ts';
import {FormulaBook,cellKey,type Overrides} from './formula.ts';
import {template,templateHash} from './template-data.ts';
import {DETAIL,INPUTS,extraNumbers,specifications} from './schema.ts';
export type ExportRequest={project:{name:string;bridge:string};pier:string;overrides:Overrides;specs:Record<string,unknown>;reviewed:boolean;copingMode?:'straight';templateHash:string;planPng?:string};
export function exportEdits(request:ExportRequest){
if(request.templateHash!==templateHash||!request.reviewed)throw new Error('원본 산식 적용 확인 후 다시 계산하세요.');
const edits:Record<string,Record<string,{value?:string|number|null;cached?:number|string;formula?:string}>>={},evaluation:Overrides={...request.overrides};
const value=(sheet:string,cell:string,v:string|number|null)=>{(edits[sheet]??={})[cell]={value:v};evaluation[cellKey(sheet,cell)]=v??0;};
for(let r=18;r<=46;r++){
const raw=request.overrides[cellKey(INPUTS,'N'+r)];if(raw!==null&&(typeof raw!=='number'||!Number.isFinite(raw)))throw new Error('입력값 누락 N'+r);
value(INPUTS,'N'+r,request.copingMode==='straight'&&r===30?null:raw as number|null);
}
for(const v of extraNumbers){const n=request.overrides[cellKey(DETAIL,v.cell)];if(typeof n!=='number'||!Number.isFinite(n)||n<0)throw new Error(v.name+' 입력을 확인하세요.');value(DETAIL,v.cell,n);}
for(const v of specifications){const s=request.specs[v.key];if(typeof s!=='string'||!s.trim())throw new Error(v.name+'을 확인하세요.');value(DETAIL,v.cell,s);}
for(let i=2;i<=6;i++){
const sheet='3.3 수량산출_P'+i;
for(const [cell,c]of Object.entries(template[sheet]))if(typeof c.value==='number'||typeof c.value==='string'&&c.value.startsWith('='))value(sheet,cell,null);
value(sheet,'F2','(미사용)');value(sheet,'BG5','미사용');
const col=['P','R','T','V','X'][i-2];for(let r=18;r<=46;r++)value(INPUTS,col+r,null);value(INPUTS,col+'17','미사용');
value('1. 수량집계',['Q','T','W','Z','AC'][i-2]+'4','미사용');
}
// The example sheet must stay a source example, not follow the active pier's straight R.
for(let r=6;r<=34;r++){const c=template['3.3 수량산출_ex)']['BG'+r];if(c&&typeof c.cached==='number')value('3.3 수량산출_ex)','BG'+r,c.cached);}
value(INPUTS,'N17',request.pier);value(DETAIL,'F2','('+request.pier+')');value(DETAIL,'BG5',request.pier);value('1. 수량집계','N4',request.pier);
value('표지및목차','A6',request.project.name);value('표지및목차','A14',request.project.bridge+' · '+request.pier);value('표지및목차','A24',new Date().toISOString().slice(0,10));
const formulas=request.copingMode==='straight'?straightCopingFormulas:{};
for(const [key,formula]of Object.entries(formulas)){const pos=key.lastIndexOf('!');(edits[key.slice(0,pos)]??={})[key.slice(pos+1)]={formula};}
const book=new FormulaBook(evaluation,template,formulas);
for(const [sheet,cells]of Object.entries(template))for(const [cell,c]of Object.entries(cells)){
if(typeof c.value!=='string'||(!c.value.startsWith('=')||c.value.length===1)||edits[sheet]?.[cell]&&Object.hasOwn(edits[sheet][cell],'value'))continue;
const n=book.cell(sheet,cell);if(typeof n!=='number'||!Number.isFinite(n))throw new Error('출력 수식 검증 실패 '+sheet+'!'+cell);
(edits[sheet]??={})[cell]={...edits[sheet]?.[cell],cached:n};
}
if(request.planPng&&(!/^[A-Za-z0-9+/=]+$/.test(request.planPng)||request.planPng.length>1500000))throw new Error('평면도 이미지 형식을 확인하세요.');
return {templateHash,edits,planPng:request.planPng};
}