Files

5.2 KiB

import json import calendar from datetime import datetime

def generate_universal_calendar(): print("=" * 50) print(" 옵시디언 캔버스 대형 달력 자동 생성 프로그램 ") print("=" * 50)

# 1. 사용자로부터 연도 및 월 입력 받기
try:
    year = int(input("▶ 생성할 연도를 입력하세요 (예: 2026): "))
    month = int(input("▶ 생성할 월을 입력하세요 (1~12): "))
    if not (1 <= month <= 12):
        print("❌ 월은 1부터 12 사이의 숫자여야 합니다.")
        return
except ValueError:
    print("❌ 올바른 숫자를 입력해주세요.")
    return

# 2. 달력의 레이아웃 및 크기 기본 사양 정의
card_width = 320
day_height = 140
box_height = 100
gap_x = 20
gap_y = 20

# 일자 카드 1개 + 하단 10개 박스가 차지하는 1주일 행(Row)의 총 높이
row_total_height = day_height + gap_y + (box_height * 10) + (gap_y * 10) # 1380px

# 3. 해당 월의 요일 정보 및 일수 자동 계산
# weekday_start: 0(월요일) ~ 6(일요일)
# num_days: 해당 월의 총 일수 (28~31)
weekday_start, num_days = calendar.monthrange(year, month)

# 일요일 시작 달력 규격을 위해 인덱스 조정 (기본 파이썬은 월요일 시작)
# 파이썬(월=0, 화=1 ... 토=5, 일=6) -> 변경(일=0, 월=1, 화=2 ... 토=6)
start_offset = (weekday_start + 1) % 7

nodes = []

# 4. 최상단 대형 메인 헤더 타이틀 생성
nodes.append({
    "id": "calendar-main-title",
    "type": "text",
    "text": f"# 📅 {year}년 {month}월 (Calendar)",
    "x": 0,
    "y": -120,
    "width": (card_width * 7) + (gap_x * 6), # 7열 전체 폭에 정렬 (2360px)
    "height": 100,
    "color": "3" # 노란색 강조
})

# 5. 고정 요일 머리글 배치 (일요일 ~ 토요일 순서)
weekdays = [
    {"name": "☀️ 일요일", "color": "1"}, # 일요일 주황/적색 강조
    {"name": "월요일", "color": None},
    {"name": "화요일", "color": None},
    {"name": "수요일", "color": None},
    {"name": "목요일", "color": None},
    {"name": "금요일", "color": None},
    {"name": "🐳 토요일", "color": "2"}  # 토요일 청색 강조
]

for idx, day_info in enumerate(weekdays):
    w_node = {
        "id": f"w-header-{idx}",
        "type": "text",
        "text": f"### {day_info['name']}",
        "x": idx * (card_width + gap_x),
        "y": 0,
        "width": card_width,
        "height": 60
    }
    if day_info["color"]:
        w_node["color"] = day_info["color"]
    nodes.append(w_node)
    
# 6. 일자 배치 및 일자별 하단 10개 텍스트 상자 자동 배치 루프
for day in range(1, num_days + 1):
    # 시작 요일(offset)을 반영하여 현재 일자가 위치할 7열 바둑판 좌표 계산
    grid_pos = (start_offset + day - 1) % 7
    week_row = (start_offset + day - 1) // 7
    
    # 현재 일자의 시작 X, Y 물리 좌표 산출
    current_x = grid_pos * (card_width + gap_x)
    current_y = 80 + (week_row * row_total_height)
    
    # 주말 컬러 색상 코드 할당
    day_color = None
    if grid_pos == 0:    # 일요일
        day_color = "1"
    elif grid_pos == 6:  # 토요일
        day_color = "2"
        
    # 메인 일자 노드 삽입
    day_node = {
        "id": f"day-node-{day}",
        "type": "text",
        "text": f"## {day}",
        "x": current_x,
        "y": current_y,
        "width": card_width,
        "height": day_height
    }
    if day_color:
        day_node["color"] = day_color
    nodes.append(day_node)
    
    # 일자 노드 바로 아래에 10단 텍스트 레이어 수직 배치
    box_start_y = current_y + day_height + gap_y
    for b_idx in range(1, 11):
        box_node = {
            "id": f"day-{day}-slot-{b_idx}",
            "type": "text",
            "text": "",
            "x": current_x,
            "y": box_start_y + ((b_idx - 1) * (box_height + gap_y)),
            "width": card_width,
            "height": box_height
        }
        nodes.append(box_node)
        
# 7. 옵시디언 캔버스 데이터 최종 통합 규칙 선언
canvas_json_structure = {
    "nodes": nodes,
    "edges": []
}

# 8. 파일로 내보내기 수행
output_filename = f"{year}년_{month}월_대형달력.canvas"
with open(output_filename, "w", encoding="utf-8") as file:
    json.dump(canvas_json_structure, file, ensure_ascii=False, indent=2)
    
print("-" * 50)
print(f"🎉 작성이 완료되었습니다! 총 {len(nodes)}개의 개체가 구성되었습니다.")
print(f"💾 생성된 파일명: {output_filename}")
print("💡 팁: 해당 파일을 옵시디언 보관소(Vault)에 넣어 즉시 열어보세요.")
print("=" * 50)

if name == "main": generate_universal_calendar()