Files
Tornado3_2026Election/SYSTEM_SPEC.md
2026-04-17 00:39:25 +09:00

12 KiB

선거방송 송출 프로그램 요구사항 정의 (v0.1)


1. 시스템 개요

1.1 목적

  • Tornado3를 통해 선거 방송 자막 송출
  • 포맷(디자인)에 데이터 매핑 후 송출

2. 데이터 처리

2.1 데이터 수신

  • Polling 기반
  • 수동 수신 가능

2.2 수동 수신 정책

  • 수동 수신 시 polling 주기 초기화
  • 3초 이내 재요청 금지

2.3 갱신 vs 송출

  • 갱신 중 송출 요청 시 → 갱신 완료 후 송출

2.4 데이터 기준

  • 득표율: 소수점 1자리 반올림
  • 득표수: 3자리 콤마

2.5 데이터 유효성

  • 필수 필드 누락 시 송출 금지
  • 사진 필수 포맷에서 이미지 없으면 송출 금지

3. 포맷

3.1 정의

  • 디자인 템플릿
  • 데이터 매핑 구조

3.2 구조

  • 포맷 → 컷 → (준비 → 송출)

3.3 루프

  • 하위 범주 반복 (예: 시도별 17개)

3.4 데이터 반영

  • 현재 컷 반영 금지
  • 다음 컷부터 반영

3.5 송출 시간

  • 포맷별 설정 가능
  • 변경 시 다음 컷부터 적용

4. 스케줄

4.1 구조

  • 큐 기반

4.2 상태

  • 현재 송출: 빨간색
  • 다음 송출: 주황색

4.3 제어

  • 다음 포맷 변경 가능
  • 현재 포맷 강제 중지 후 전환 가능
  • 순서 변경 가능

4.4 삭제 정책

  • 대기 포맷 삭제 가능
  • 송출 중 포맷 삭제 불가

4.5 루프

  • 전체 루프 가능
  • 첫 포맷부터 재시작

4.6 빈 스케줄

  • 설정에 따라:
    • 즉시 Out
    • 마지막 화면 유지

4.7 종료

  • 수동 종료 시:
    • 스케줄 종료
    • 해당 Layer Out

5. 방송 영역

  • 노멀
  • 좌상단
  • 하단
  • VideoWall

특징:

  • 독립 스케줄
  • 동시 송출 가능

6. 방송사 설정

대상

  • KNN, TBC, KBC, G1, TJB, JTV

특징

  • 동일 구조
  • 지역 필터만 다름

지역 필터

  • 기본값 제공
  • 사용자 수정 가능

7. 유력/확실/당선

기준

  • 후보 단위

수동 입력

  • 콤보박스 선택
  • 자동 판정보다 우선

자동 판정

  • 수동 지정 없는 경우만 적용
  • 당선 조건:
    • (1위 - 2위) > 남은 개표수

초기화

  • 전체 초기화 가능

저장

  • 방송사 + 선거종류 + 선거구 + 후보 기준

8. Tornado3 연동

방식

  • TCP + DLL

기능

  • 이미지 변경
  • 텍스트 변경
  • 준비
  • 송출

응답 처리

  • ACK 대기 없음
  • 5초 내 응답 없으면 실패

상태

  • IDLE
  • READY (송출 가능 상태)
  • SENDING
  • ON_AIR
  • ERROR

연결

  • 끊김 시 재연결
  • 재연결 후 사용자 확인 후 재개

9. 상태 흐름

IDLE → READY → SENDING → ON_AIR → NEXT

ERROR


10. 복원

대상

  • 스케줄
  • 방송사
  • 상태값

방식

  • 통합 대화상자
  • 체크박스 선택

11. UI 구조

네비게이션

  • 통합 스케줄
  • 노멀
  • 좌상단
  • 하단
  • VideoWall
  • 데이터
  • 설정
  • 로그

표시

  • 빨강: 현재 송출
  • 주황: 다음 송출

12. 이미지

경로 규칙: {선택경로}/{선거종류}/{지역코드}/{후보코드}.png


13. 예외 처리

  • API 실패 → 사용자 알림
  • Tornado 실패 → ERROR 상태

14. 핵심 개념

  • 포맷 기반
  • 컷 단위 송출
  • 스케줄 큐 구조
  • 상태 머신 기반 제어

15. 인코딩 검증 규칙

  • 한글 문자열이 포함된 파일을 수정한 뒤에는 반드시 인코딩 깨짐 여부를 다시 확인한다.
  • UI 문구, 로그 문구, 기본값 문자열은 저장 직후 한글이 정상 표시되는지 우선 점검한다.
  • ?, U+FFFD(치환 문자), 비정상 한자 형태의 모지바케가 보이면 즉시 수정 대상으로 간주한다.
  • 텍스트 파일은 UTF-8 기준으로 관리한다.

16. Karisma / Tornado3 연동 기준

  • CG 연동 라이브러리는 Interop.KAsyncEngineLib.dll을 사용한다.
  • Interop.KAsyncEngineLib.dllAMD64 기준이므로 앱 실행 대상도 x64를 기준으로 운영한다.
  • 기본 접속 대상은 127.0.0.1:30001이다.
  • TORNADO_KARISMA_HOST가 있으면 기본 호스트 대신 사용한다.
  • TORNADO_KARISMA_PORT가 있으면 기본 포트 대신 사용한다.
  • 앱은 시작 시 공유 Karisma 어댑터 1개를 만들고 127.0.0.1:30001 연결을 즉시 시도한다.
  • 노멀, 좌상단, 하단, 비디오월 채널은 같은 TCP 연결을 공유하고, 채널별 output/layer 바인딩만 다르게 사용한다.
  • 앱 시작 시 T3_Cut 경로가 유효하지 않으면 실CG 대신 Mock Adapter로 폴백한다.
  • 현재 구현 기준으로는 시작 시 Mock으로 결정된 경우, 설정 변경만으로 실CG 어댑터로 승격되지 않으므로 앱 재시작이 필요할 수 있다.
  • 채널 기본 바인딩은 노멀=0:0, 좌상단=0:1, 하단=0:2, 비디오월=1:0이다.
  • 환경변수 TORNADO_KARISMA_BIND_NORMAL, TORNADO_KARISMA_BIND_TOPLEFT, TORNADO_KARISMA_BIND_BOTTOM, TORNADO_KARISMA_BIND_VIDEOWALL로 채널 바인딩을 덮어쓸 수 있다.

17. T3_Cut 운영 규칙

  • 사용자 설정 명칭은 이미지 루트 경로가 아니라 T3_Cut 경로로 표기한다.
  • 송출에 사용하는 컷 파일 확장자는 .tscn이다.
  • 컷 파일은 T3_Cut 루트 아래의 고정된 포맷 구조를 기준으로 사용한다.
  • 기본 T3_Cut 탐색 순서는 TORNADO_T3CUT_PATH 환경변수, 문서\Tornado3 Data\T3_Cut\T3_Cut, 문서\Tornado3 Data\T3_Cut, 다운로드\T3_Cut 순서다.
  • 사용자가 상위 폴더를 선택했더라도 그 아래의 T3_Cut 하위 폴더에서 .tscn 파일이 확인되면 해당 하위 폴더를 실제 송출 루트로 정규화한다.
  • 포맷 목록은 폴더 스캔으로 동적 생성하지 않고 하드코딩된 목록으로 관리한다.
  • 같은 컷 이름에 _loop.tscn 파일이 있으면 반복 송출 컷으로 사용한다.
  • 최초 송출 시에는 기본 컷 파일을 사용한다.
  • 이미 송출 중인 상태에서 같은 컷을 다시 사용할 때는 _loop.tscn이 있으면 우선 사용한다.
  • _loop.tscn이 없으면 기본 .tscn 파일로 폴백한다.
  • 예시: 1-2위_광역단체장.tscn은 최초 송출용, 1-2위_광역단체장_loop.tscn은 반복 송출용으로 간주한다.

18. CG 연동 상태 UI 표기 기준

  • 메인 화면 상단에는 CG 연동 상태를 표시한다.
  • 사용자는 UI에서 현재 어댑터가 실CG인지 Mock인지 즉시 식별할 수 있어야 한다.
  • 상단 상태 영역에는 실CG 연동 여부, 연결 대상, 채널 정상 상태 요약을 함께 표시한다.
  • 채널 패널별로도 해당 채널이 어떤 백엔드를 사용하는지 표시한다.
  • 실제 Karisma 사용 시 연결 대상 예시는 127.0.0.1:30001 형식으로 표시한다.

19. CG Return Value / Callback 로그 정책

  • CG 시스템으로부터 오는 Return Value 관련 결과는 로그 탭에서 확인할 수 있어야 한다.
  • 즉시 반환되는 값과 비동기 콜백 결과를 모두 로그로 남긴다.
  • Connect() 호출 직후의 반환값은 즉시 로그로 기록한다.
  • LoadScene()LoadSceneForce() 호출 결과도 즉시 로그로 기록한다.
  • KAEventHandler 기반 콜백 결과를 LogService를 통해 공용 로그에 남긴다.
  • 로그에는 콜백 이름, 결과 enum 이름, 숫자 코드, 추가 정보(scene, object, output, layer 등)를 함께 남긴다.
  • OnConnect(int ErrorCode)0을 성공으로 간주하고, 0이 아닌 값은 실패로 기록한다.
  • eKResult.RESULT_SUCCESS는 정보 로그로 남기고, 그 외 결과는 경고 로그로 남긴다.
  • 현재 로깅 대상에는 OnConnect, OnClose, OnLogMessage, OnMessageNo, OnLoadScene, OnLoadSceneForce, OnBeginTransaction, OnEndTransaction, OnHeartBeat, OnSetValue, OnSetCounterNumberKey, OnScenePrepare, OnScenePrepareEx, OnPlay, OnPlayOut, OnPause, OnResume, OnStop, OnStopAll, OnCutIn, OnCutOut, OnTrigger, OnTriggerObject, OnQueryIsOnAir, OnQueryLayerCount, OnScenePlayingStarted, OnScenePlayed, OnSceneAnimationPlayed, OnScenePaused를 포함한다.
  • CG 콜백 로그와 앱 내부 로그는 같은 로그 시스템에 합쳐서 표시한다.

2026-04-09 운영 규칙 업데이트

스케줄 조작 규칙

  • 다음은 목록 순서를 바꾸지 않고 다음 예약만 이동한다.
  • 다음으로 지정된 항목은 대기 목록에서 노란색으로 표시한다.
  • 다음 컷 즉시 송출은 현재 송출 중인 컷을 끝내고, 노란색으로 예약된 다음 컷을 즉시 송출한다.
  • 아래는 대기 목록의 순서 변경 전용이다.
  • 제거는 대기 항목만 삭제하며, 송출 중이거나 준비 중인 항목은 제거하지 않는다.

대기 목록 상태 표시 규칙

  • 빨강: 현재 송출 중인 항목
  • 노랑: 다음 송출 예정 항목
  • 회색: 그 외 항목
  • 완료 상태 항목은 카드 전체를 흐리게 표시한다.

단계별 컷 사용 규칙

  • 투표율 계열 컷은 사전 단계에서 사용한다.
  • 득표수, 순위, 판세 등 나머지 대부분의 컷은 개표 단계에서 사용한다.
  • 사전_역대당선자* 계열은 사전개표 양쪽 단계에서 모두 사용할 수 있다.
  • 단계에 맞지 않는 컷은 목록에서 숨기고, 송출 직전 검증에서도 차단한다.

MediaWall 분류 규칙

  • 포멧 정리.xlsx사전, 개표, 판세 시트에서 MediaWall로 표기된 컷은 비디오월 모드 전용으로 분류한다.
  • 현재 비디오월 전용 컷은 다음과 같다.
  • 민방_타이틀
  • 사전_역대투표율_loop
  • 투표율_시도별
  • 1-2위_광역단체장_5760
  • 1-3위_기초단체장_5760
  • 모든후보_광역단체장_5760
  • 이시각1위_광역단체장
  • 판세_기초단체장_5760
  • 광역의원표

T3_Cut 및 루프 컷 규칙

  • T3_Cut 경로 아래의 .tscn 파일을 송출 컷으로 사용한다.
  • 같은 이름의 _loop.tscn 파일이 있으면, 이미 송출 중인 상태에서 재호출할 때 loop 컷을 우선 사용한다.

CG 연결 상태 표시 규칙

  • CG 상태는 Karisma 어댑터 존재 여부가 아니라 공유 TCP 30001 연결 성공 여부를 기준으로 표시한다.
  • Connected / Disconnected 표시는 OnConnectOnClose 콜백 기준으로 갱신한다.
  • 공유 연결 상태는 해당 연결을 사용하는 모든 채널 패널에 동일하게 반영한다.
  • TCP 연결이 끊기면 5초 간격으로 자동 재접속을 시도한다.

2026-04-14 TCP / SetValue 디버깅 업데이트

  • 앱 실행 직후 30001과의 TCP 연결을 바로 시도하고, 이후 각 채널은 그 단일 연결을 공유한다.
  • Karisma SDK 콜백 수신을 위해 전용 STA 스레드에서 메시지 펌프를 유지한다.
  • SetValue 검증을 위해 후보 이름 키를 기존 Candidate1Name, Candidate2Name 외에 후보명01, 후보명02로도 함께 전달한다.
  • 현재 테스트 빌드 기준 후보명01=김후보, 후보명02=이후보를 함께 송신해 실제 장면 변수 반영 여부를 확인한다.
  • .tscn별 실제 변수 목록은 사전 스캔 리포트(TSCN_VARIABLE_DISCOVERY_E_DRIVE.md)를 기준으로 읽고, 현재 장면에 존재하는 변수에만 SetValue/SetCounterNumberKey를 보낸다.
  • ElectionDataSnapshot에서 후보명NN, 정당명NN, 득표수NN, 득표율NN, 순위NN, 표차NN, 득표차NN, 선거구명NN, 시도명NN, 개표율NN, 투표율01, 전국투표율01을 장면 변수로 자동 매핑한다.
  • ani가 포함된 컷은 득표율NN 텍스트 값과 별도로 IKACounter.SetCounterNumberKey(1, voteRate)를 함께 전송한다.
  • 유확당NN유력.vrv, 확정.vrv 또는 확실.vrv, 당선.vrv로 해석하고, 후보사진NN, 정당바NN, 정당판NN, 정당심볼NN, 그룹NNT3_Cut 아래 로컬 에셋 폴더에서 해석한다.
  • 대표 검증 컷 1-2위_ani_광역단체장에 대해서는 실경로 기준 라이브 검증에서 Success Count: 21, Failure Count: 0을 확인했다(LIVE_VALIDATE_1-2위_ani_광역단체장.md).

인코딩 확인 원칙

  • 터미널 출력이 깨져 보이는 것과 파일 자체 인코딩 손상을 구분해서 판단한다.
  • 한글 문자열 상태 판단은 편집기 화면 또는 UTF-8 파일 직접 읽기 기준으로 확인한다.