교통·날씨 데이터 계약 v1

실제 공개기관에서 내려받은 관측값이 아니라 이 실습을 위해 직접 작성한 합성 표본입니다.
지역 A/B는 가상 코드, 기간은 예제의 날짜이며 추출일은 표본 패키지 작성일입니다.
source_url은 이 표본을 제공하는 부트캠프 ZIP 경로입니다.
reference_url은 실제 데이터로 교체할 때 탐색할 공개 포털로, 표본의 직접 출처나 사용 허가 증빙이 아닙니다.
실제 자료 교체 시 데이터 상세 URL·제공자·해당 자료 사용 조건·추출일·관측 기간·단위·시간 경계를 재확인합니다.
네트워크나 API 키가 필요하지 않습니다. 개인 이동 경로는 포함하지 않습니다.

Python 3를 설치한 뒤 ZIP을 풀고 README가 있는 폴더에서 실행합니다.
  python3 -m unittest discover -s tests -v
  python3 contract.py
시작본에서는 산출물 누락에 따른 실패가 정상입니다. 검증기와 tests는 수정하지 않습니다.
source.json과 dictionary.json의 TODO, question.json의 빈 질문, audit.csv를 완성합니다.
SHA-256은 raw 파일의 바이트에서 계산하며 줄바꿈을 바꿔도 값이 달라집니다. 원본을 덮어쓰지 않습니다.
실패 메시지 SOURCE는 메타데이터, PERIOD는 날짜 순서, PRIVACY는 금지 열,
TYPE/UNIT은 사전 타입/단위, AUDIT는 CSV 행 수와 규칙, HASH는 원본 변경을 확인하라는 뜻입니다.
AssertionError의 expected/actual과 ValueError의 마지막 줄을 읽고 해당 산출물부터 고칩니다.

스프레드시트 순서
1. raw/traffic.csv와 raw/weather.csv를 쉼표 구분 UTF-8로 가져옵니다. region/date는 텍스트로 둡니다.
2. 원본과 별도의 작업 시트에서 헤더 제외 행 수를 셉니다(traffic 7, weather 6).
3. 마지막 숫자 열의 빈 셀을 제외한 사본을 만듭니다(traffic 6, weather 5). 0은 남깁니다.
4. 사본에서 모든 열을 기준으로 완전히 같은 행의 추가분만 제외합니다(traffic 5, weather 5).
5. audit.csv에 dataset,stage,rows,rule 순서로 6개 기록을 입력하고 CSV UTF-8로 내보냅니다.
   raw / nonmissing / unique 순서를 지킵니다. 규칙 이름은 레슨과 contract.py를 확인합니다.
6. 필터를 해제하고 원본은 그대로 보존합니다. 분석 결합은 다음 모듈에서 진행합니다.

다음 모듈 인계
raw/traffic.csv, raw/weather.csv, source.json, dictionary.json, question.json, audit.csv를 함께 유지합니다.
traffic은 동일 행 중복 1건과 vehicle_count 빈칸 1건, weather는 rain_mm 빈칸 1건을 의도적으로 포함합니다.
0은 유효한 관측값입니다. 지역·날짜의 후보 키 중복은 여기서 보고만 하며 원본을 변경하지 않습니다.
사전과 source를 읽고 후속 정제에서 별도 정제본을 만듭니다.
