Files
2026-02-HYUP2/report/연구실실습일지작성양식.typ

200 lines
11 KiB
Typst
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 연구실 실습일지 양식 (원본 docx 1페이지 복제 + 템플릿 함수)
// 원본: 연구실실습일지작성양식_컴퓨터소프트웨어실습HY-UP(실용연구실습)2_(1-15회차).docx
//
// 이 파일을 직접 컴파일하면 빈 양식이 나오고,
// #import "연구실실습일지작성양식.typ": 실습일지
// #실습일지(소속대학: "…", 일시: "…", 내용: […])
// 처럼 호출하면 채워진 실습일지 1페이지가 나온다 (예: day1.typ).
//
// 모든 요소는 절대 좌표(place) 배치 — 글꼴에 따라 줄이 바뀌지 않는다.
// 수치는 docx의 twips/EMU → pt 환산값:
// 페이지 595×841pt / 배경 이미지 (0, 30.8) 594.88×810.2
// 제목 상자 (45.35, 73.7) 504.35×42.6, 테두리 1.44pt
// 표: (46.1, 143.15) 폭 505.75, 높이 630.15 (4행 높이 34.6pt는 원본 그대로,
// 원본에선 '3시간'이 2줄로 접혀 늘어난 높이지만 렌더는 1줄로 한다)
// kr-font: report/fonts/ChosunSm.ttf = 조선신명조 풀 폰트(17,147 글리프).
// typst는 패밀리를 Mac 플랫폼(1/0) name 레코드로만 매칭하는데 원본은 이 레코드가
// 빈 문자열이라(Windows 레코드의 '조선신명조'는 무시됨) 폰트에 'ChosunSm'으로 기입해 둠.
// Regular face만 존재 — 굵게/기울임은 아래 show strong/emph에서 처리.
#let kr-font = ("ChosunSm", "NanumGothic")
// 코드 폰트: 한글 지원 모노스페이스 우선(주석 한글도 모노폭), 없는 글리프는 kr-font로 폴백
#let code-font = ("NanumGothicCoding", "DejaVu Sans Mono", "Liberation Mono")
#let X0 = 46.1pt // 표 왼쪽 (좌 여백 37 + 표 들여쓰기 9.1)
#let Y0 = 143.15pt // 표 위쪽 (외곽 테두리 기준)
#let BX = (0pt, 100.75pt, 264.35pt, 339.9pt, 362.45pt, 419.05pt, 433.2pt, 505.75pt) // 열 경계
#let RY = (0pt, 23.05pt, 43.25pt, 63.55pt, 98.15pt, 121.7pt, 533.9pt, 557.6pt, 630.15pt) // 행 경계
// 굵은 라벨 / 값 (10pt). trk = Word 자간(spc, twips→pt)
#let lab(body, trk: 0pt) = text(font: kr-font, size: 10pt, weight: "bold", tracking: trk, body)
#let val(body, trk: 0pt) = text(font: kr-font, size: 10pt, tracking: trk, body)
// 셀 안내선: 가는 내부선 0.5pt (Word sz=4), 굵은 선 1.5pt (Word sz=12)
#let hline(i, j, y, w) = place(dx: X0 + BX.at(i), dy: Y0 + y, line(length: BX.at(j) - BX.at(i), stroke: w * 1pt + black))
#let vline(x, y0, y1, w) = place(dx: X0 + x, dy: Y0 + y0, line(angle: 90deg, length: y1 - y0, stroke: w * 1pt + black))
// 셀 텍스트: (x0, x1) = 셀 좌우, r = 행 번호. 셀 정중앙 배치
#let cell-text(x0, x1, r, body, li: 5.4pt, ri: 5.4pt) = place(
dx: X0 + x0, dy: Y0 + RY.at(r),
box(width: x1 - x0, height: RY.at(r + 1) - RY.at(r),
inset: (top: 0pt, bottom: 0pt, left: li, right: ri),
align(center + horizon, body)))
#let cell-left(x0, x1, r, body, li: 5.4pt, ri: 5.4pt) = place(
dx: X0 + x0, dy: Y0 + RY.at(r),
box(width: x1 - x0, height: RY.at(r + 1) - RY.at(r),
inset: (top: 0pt, bottom: 0pt, left: li, right: ri),
align(left + horizon, body)))
// 날짜 칸의 탭 정지 토큰 (원본 탭: 1210/1810/2511/3909 twips, 문단 들여쓰기 611 기준 상대 위치)
// 오프셋 기준점 = 셀 왼쪽 + 셀 여백 5.4 + 문단 들여쓰기 30.55 = +35.95
#let date-token(r, x-offset, body) = place(
dx: X0 + 100.75pt + 35.95pt + x-offset, dy: Y0 + RY.at(r),
box(height: RY.at(r + 1) - RY.at(r), inset: (top: 0pt, bottom: 0pt, left: 0pt, right: 0pt),
align(horizon, body)))
// ── 템플릿 함수 ────────────────────────────────────────────────────
// 소속대학/소속학과/학번/성명/의견: 문자열(빈 값이면 원본처럼 빈 칸)
// 일시: none이면 빈 양식의 '년 월 일 시 부터 ~ 시 까지' 스캐폴드, 문자열이면 그대로 출력
// 내용: none이면 빈 칸, content/문자열이면 실습 내용 칸(왼쪽 위)에 출력
#let 실습일지(소속대학: "", 소속학과: "", 학번: "", 성명: "", 일시: none, 내용: none, 의견: "") = {
set page(width: 595pt, height: 841pt, margin: 0pt)
set par(spacing: 0pt)
set text(lang: "ko", cjk-latin-spacing: none)
// 코드 블록 스타일 (내용 칸의 ``` 코드): 둥근 박스 + 연한 배경 + 테두리
show raw.where(block: true): it => block(
width: 100%,
above: 6pt,
below: 6pt,
fill: rgb("#F6F8FA"),
stroke: 0.5pt + rgb("#C9D1D9"),
radius: 3pt,
inset: (x: 8pt, y: 6pt),
text(font: code-font + kr-font, size: 8.5pt, it))
// 인라인 코드: 옅은 배경만
show raw.where(block: false): it => box(
fill: rgb("#EEF1F4"),
inset: (x: 3pt, y: 0pt),
radius: 2pt,
text(font: code-font + kr-font, size: 9pt, it))
// *굵게*: 조선신명조엔 Bold face가 없으므로 같은 조선일보 서체 계열인
// 조선굵은명조(report/fonts/ChosunKm.ttf, name 테이블 동일 패치)로 렌더한다
show strong: it => text(font: ("ChosunKm",) + kr-font, it)
// box로 감싸지 않으면 skew가 문단을 분리해 par(spacing: 0pt) 하에서 줄이 겹친다
show emph: it => box(skew(ax: -12deg, text(font: ("Liberation Serif",) + kr-font, it)))
[
// 배경 (한양대 양식 이미지)
#place(dx: 0pt, dy: 30.8pt, image("hy-bg.png", width: 594.88pt, height: 810.2pt))
// 제목 상자
#place(dx: 45.35pt, dy: 73.7pt,
rect(width: 504.35pt, height: 42.6pt, stroke: 1.44pt + black, fill: none, inset: 0pt,
align(center + horizon,
text(font: kr-font, size: 25pt, weight: "bold")[연구실]
+ text(font: kr-font, size: 25pt, weight: "bold", tracking: 3pt)[ ]
+ text(font: kr-font, size: 25pt, weight: "bold", tracking: -0.2pt)[실습일지])))
// 표 테두리: 가로선 (바깥 1.5pt, 내부 0.5pt — 학번↔교과목명 경계만 1.5pt)
#hline(0, 7, 0pt, 1.5)
#hline(0, 7, 23.05pt, 0.5)
#hline(0, 7, 43.25pt, 1.5)
#hline(0, 7, 63.55pt, 0.5)
#hline(0, 7, 98.15pt, 0.5)
#hline(0, 7, 121.7pt, 0.5)
#hline(0, 7, 533.9pt, 0.5)
#hline(0, 7, 557.6pt, 0.5)
#hline(0, 7, 630.15pt, 1.5)
// 세로선: 셀 경계가 실제로 존재하는 구간만
#vline(0pt, 0pt, 630.15pt, 1.5) // 왼쪽 외곽
#vline(505.75pt, 0pt, 630.15pt, 1.5) // 오른쪽 외곽
#vline(100.75pt, 0pt, 630.15pt, 0.5) // 라벨 열 오른쪽 (전 행)
#vline(264.35pt, 0pt, 43.25pt, 0.5) // 소속대학 값 | 소속학과 (1–2행)
#vline(339.9pt, 0pt, 98.15pt, 0.5) // 소속학과 값 | 수업번호 열 (1–4행)
#vline(362.45pt, 557.6pt, 630.15pt, 0.5) // 의견 칸 | 담당 교수 확인 (8행)
#vline(419.05pt, 43.25pt, 98.15pt, 0.5) // 수업번호 칸 | 11725 칸 (3–4행)
#vline(433.2pt, 557.6pt, 630.15pt, 0.5) // 담당 교수 확인 | (인) (8행)
// 1행: 소속대학 / 소속학과
#cell-text(0pt, 100.75pt, 0, lab(trk: -0.2pt)[소속대학])
#cell-text(264.35pt, 339.9pt, 0, lab(trk: -0.2pt)[소속학과])
#if 소속대학 != "" [#cell-left(100.75pt, 264.35pt, 0, val(소속대학))]
#if 소속학과 != "" [#cell-left(339.9pt, 505.75pt, 0, val(소속학과))]
// 2행: 학번 / 성명
#cell-text(0pt, 100.75pt, 1, lab(trk: -0.25pt)[학번])
#cell-text(264.35pt, 339.9pt, 1, lab(trk: -0.25pt)[성명])
#if 학번 != "" [#cell-left(100.75pt, 264.35pt, 1, val(학번))]
#if 성명 != "" [#cell-left(339.9pt, 505.75pt, 1, val(성명))]
// 3행: 교과목명 / 컴퓨터소프트웨어실습… / 수업번호 / 11725
#cell-text(0pt, 100.75pt, 2, lab(trk: -0.2pt)[교과목명])
#cell-left(100.75pt, 339.9pt, 2,
val(trk: -0.1pt)[컴퓨터소프트웨어실습HY-UP(실용연구실습)2], li: 11pt)
#cell-text(339.9pt, 419.05pt, 2, lab(trk: -0.2pt)[수업번호])
#cell-left(419.05pt, 505.75pt, 2, val(trk: -0.1pt)[11725], li: 10.4pt)
// 4행: 실습 일시 / 실습진행시간 / 3시간(1줄 — 높이만 원본 그대로 34.6pt)
#cell-text(0pt, 100.75pt, 3, lab[실습] + lab(trk: -0.1pt)[ ] + lab(trk: -0.25pt)[일시])
#if 일시 == none [
// 빈 양식: 원본 탭 정지 스캐폴드
#date-token(3, 0pt, val(trk: -0.5pt)[년])
#date-token(3, 29.95pt, val[월])
#date-token(3, 59.95pt, val[일])
#date-token(3, 95pt, val[시] + val(trk: -0.15pt)[ ] + val[부터] + val(trk: -0.15pt)[ ] + val[\~])
#date-token(3, 164.9pt, val[시] + val(trk: -0.1pt)[ ] + val(trk: -0.25pt)[까지])
] else [
#cell-left(100.75pt, 339.9pt, 3, val(일시), li: 35.95pt)
]
#cell-text(339.9pt, 419.05pt, 3, lab(trk: -0.1pt)[실습진행시간])
#cell-text(419.05pt, 505.75pt, 3, val(trk: -0.25pt)[3시간])
// 5행: 실습 장소
#cell-text(0pt, 100.75pt, 4, lab[실습] + lab(trk: -0.1pt)[ ] + lab(trk: -0.25pt)[장소])
#cell-left(100.75pt, 505.75pt, 4,
val[IT/BT] + val[관] + val(trk: -0.45pt)[ ] + val[811호와] + val(trk: -0.3pt)[ ] + val(trk: -0.2pt)[코드트리],
li: 10.5pt)
// 6행: 실습 내용 (라벨은 Word vAlign=center — 세로 중앙) + 기재 내용(왼쪽 위)
#cell-text(0pt, 100.75pt, 5, lab[실습] + lab(trk: -0.1pt)[ ] + lab(trk: -0.25pt)[내용])
#if 내용 != none [
#place(dx: X0 + 100.75pt, dy: Y0 + RY.at(5),
box(width: 405pt, height: 412.2pt,
inset: (top: 5.4pt, bottom: 5.4pt, left: 5.4pt, right: 5.4pt),
align(top + left, {
// 전역 par(spacing: 0pt)를 상속하면 문단/목록 사이 간격이 사라지므로 내용 칸에서만 복구
set par(spacing: 0.8em)
text(font: kr-font, size: 10pt, 내용)
})))
]
// 7행: 담당 교수명 / 박희진
#cell-text(0pt, 100.75pt, 6, lab[담당] + lab(trk: -0.2pt)[ ] + lab(trk: -0.25pt)[교수명])
#cell-left(100.75pt, 505.75pt, 6, val(trk: -0.25pt)[박희진], li: 10.5pt)
// 8행: 담당교수 의견 / 담당 교수 확인 / (인)
#cell-text(0pt, 100.75pt, 7, lab[담당교수] + lab(trk: -0.3pt)[ ] + lab(trk: -0.25pt)[의견])
#if 의견 != "" [#cell-left(100.75pt, 362.45pt, 7, val(의견))]
// 담당 교수 확인: 원본 들여쓰기 때문에 '담당 교/수 확인'으로 접히는 양식 결함을
// '담당 교수' / '확인' 2줄 중앙 정렬로 명시 배치
#cell-text(362.45pt, 433.2pt, 7,
lab[담당] + lab(trk: -1.25pt)[ ] + lab[교수] + linebreak() + lab(trk: -0.3pt)[확인])
#cell-text(433.2pt, 505.75pt, 7, lab(trk: -0.25pt)[(인)])
// 빨간 안내문
#let r(body, trk: 0pt) = text(font: kr-font, size: 11pt, weight: "bold", fill: red, tracking: trk, body)
#place(dx: 42.45pt, dy: 774pt,
r[※] + r(trk: -0.1pt)[ ] + r[1회차에] + r(trk: -0.05pt)[ ] + r[3시간,] + r(trk: 0.1pt)[ ]
+ r[15회차] + r(trk: -0.05pt)[ ] + r[이상의] + r(trk: 0.1pt)[ ] + r[연구실] + r(trk: -0.05pt)[ ]
+ r[실습일지] + r(trk: 0.1pt)[ ] + r[작성] + r(trk: 0.1pt)[ ] + r[필수] + r(trk: 0.1pt)[ ]
+ r[(] + r(trk: -0.05pt)[ ] + r[한학기] + r(trk: -0.05pt)[ ] + r[45시간] + r(trk: -0.05pt)[ ]
+ r[실습] + r(trk: -0.05pt)[ ] + r[필수] + r(trk: -0.05pt)[ ] + r(trk: -0.5pt)[)])
]
}
// 이 파일을 직접 컴파일하면 빈 양식
#실습일지()