7 Commits

Author SHA1 Message Date
Claude (owner)
cce5469dc2 music_quiz: answer 정규화 도입 (대소문자/공백 무시)
- mq:answer/normalize: storage 의 norm.in 을 한 글자씩 떼어내
  소문자화 + 공백 제거 후 norm.acc 에 누적. char 단위 반복은
  'data modify ... set string from ... <start> <end>' (1.20+) 로,
  결합은 매크로 ($(acc)$(c)) 로 수행하는 pure-datapack 구현.

- process: 큐의 text 를 정규화한 결과를 judge.input 으로 사용
- judge: answer.title 정규화 후 judge.answer 로 사용
- iter_aliases: alias 각 항목 정규화 후 비교

원본 songs.mcfunction 의 title/alias 표기는 그대로 유지 (display
및 정규화 입력으로 모두 사용됨). 입력이 'Lose My Mind' / 'lose my mind'
/ 'LOSEMYMIND' / 'losemymind' 어떤 형태든 동일한 정규형으로 떨어져 매치.
2026-05-15 00:23:42 +09:00
Claude (owner)
8c30f4de5e temp: 애니메이션 painting 텍스처 검증용 sample 파일 추가
리소스팩 1번 방식 (.png 세로 스트립 + .png.mcmeta) 이
painting_variant 에서 동작하는지 검증하기 위한 샘플.

사용 위치: musicquiz 리소스팩의
  assets/musicquiz/textures/painting/gif.png
  assets/musicquiz/textures/painting/gif.png.mcmeta

데이터팩 v1.0.6 의 mq:gif painting_variant 와 짝.
2026-05-14 23:58:07 +09:00
Claude (owner)
ae434c3a07 music_quiz: answer/macro/match — NBT path compound matcher 공백 제거
execute if data <source> <path> 의 path 토큰은 공백을 허용하지 않음.
'judge {input:...}' → 'judge{input:...}' 로 붙여써야 compound predicate 가
정상 적용됨.
2026-05-14 23:50:28 +09:00
Claude (owner)
663891c966 music_quiz: 애니메이션 텍스처 테스트용 painting_variant gif 추가
리소스팩 musicquiz:gif 텍스처가 .png.mcmeta 애니메이션을 따르는지
검증하기 위한 1×1 painting_variant. 텍스처 자체는 리소스팩에 별도 배치.
2026-05-14 23:39:20 +09:00
Claude (owner)
c2dcf0c44f music_quiz: painting_variant 를 mq 네임스페이스로 통합
- data/musicquiz/painting_variant/* → data/mq/painting_variant/* 로 이동
  변종 ID = mq:cover_NN, 텍스처 asset_id = musicquiz:cover_NN (리소스팩)
- title/author 필드 제거 (기본값 사용)
- init/config.mcfunction 의 image.namespace 기본값을 "mq" 로 변경
2026-05-14 23:23:29 +09:00
Claude (owner)
f71bd95de5 music_quiz: pack.mcmeta 에 min_format / max_format 명시 (26.1.2 = format 75)
25w31a 이후 pack metadata 에서 min_format / max_format 가 권장 필드로
추가됨. 없으면 게임 시작 시 PackRepository.reload 단계에서
"missing mandatory fields min_format and max_format" WARN 로그가
fallback 으로 처리되며, 향후 버전에서 hard fail 로 바뀔 가능성이
있어 명시. 단일 버전(26.1.2) 만 지원하므로 75/75 로 고정.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-14 23:04:43 +09:00
Claude (owner)
b19f37969a music_quiz: add painting_variant definitions (cover_01 ~ cover_50)
리소스팩의 assets/musicquiz/textures/painting/cover_NN.png 를 게임에서
painting entity 로 띄우려면 데이터팩 쪽에 painting_variant 정의가
있어야 한다. 곡 수(50)에 맞춰 data/musicquiz/painting_variant/cover_NN.json
50개를 추가. asset_id 의 musicquiz:cover_NN 이 자동으로
assets/musicquiz/textures/painting/cover_NN.png 를 가져다 쓴다.
width/height = 1×1 (정사각 한 블록).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-14 22:57:49 +09:00
62 changed files with 343 additions and 9 deletions

View File

@@ -2,7 +2,9 @@
execute store result score alen func.temp run data get storage mq:tmp aliases execute store result score alen func.temp run data get storage mq:tmp aliases
execute if score alen func.temp matches 0 run return 0 execute if score alen func.temp matches 0 run return 0
data modify storage mq:tmp judge.answer set from storage mq:tmp aliases[0] data modify storage mq:tmp norm.in set from storage mq:tmp aliases[0]
function mq:answer/normalize
data modify storage mq:tmp judge.answer set from storage mq:tmp norm.acc
function mq:answer/macro/match with storage mq:tmp judge function mq:answer/macro/match with storage mq:tmp judge
data remove storage mq:tmp aliases[0] data remove storage mq:tmp aliases[0]

View File

@@ -2,8 +2,10 @@
# 매치되면 @s answer = 1 → check_answer 가 정답처리 흐름으로 진입 # 매치되면 @s answer = 1 → check_answer 가 정답처리 흐름으로 진입
# 매치 안되면 @s answer = 2 → check_answer 가 reset 처리 (1회 비교 후 초기화) # 매치 안되면 @s answer = 2 → check_answer 가 reset 처리 (1회 비교 후 초기화)
# 1) 제목과 비교 # 1) 제목과 비교 (정규화 후)
data modify storage mq:tmp judge.answer set from storage mq:main answer.title data modify storage mq:tmp norm.in set from storage mq:main answer.title
function mq:answer/normalize
data modify storage mq:tmp judge.answer set from storage mq:tmp norm.acc
function mq:answer/macro/match with storage mq:tmp judge function mq:answer/macro/match with storage mq:tmp judge
# 2) 제목 매치 실패 시 alias 들과 순차 비교 (조기 종료) # 2) 제목 매치 실패 시 alias 들과 순차 비교 (조기 종료)

View File

@@ -0,0 +1,13 @@
# 입력 문자열 정규화 — 소문자 변환 + 공백 제거 (대소문자/공백 무시 비교용)
#
# 입력 : storage mq:tmp norm.in (원본 문자열)
# 출력 : storage mq:tmp norm.acc (정규화 결과)
#
# 호출 예:
# data modify storage mq:tmp norm.in set from storage mq:main answer.title
# function mq:answer/normalize
# # 이후 storage mq:tmp norm.acc 에 결과
#
# 동작: norm.in 을 한 글자씩 떼어내며 normalize/step 으로 재귀
data modify storage mq:tmp norm.acc set value ""
function mq:answer/normalize/step

View File

@@ -0,0 +1,3 @@
# acc 끝에 c 를 매크로로 concat
# 매크로 인자: storage mq:tmp norm → $(acc), $(c)
$data modify storage mq:tmp norm.acc set value "$(acc)$(c)"

View File

@@ -0,0 +1,47 @@
# normalize 의 1-문자 처리 + 재귀 스텝
# 사전조건: storage mq:tmp norm.in 비어있지 않을 수 있음 / norm.acc 누적값
execute store result score n.len func.temp run data get storage mq:tmp norm.in
execute if score n.len func.temp matches 0 run return 0
# 머리글자 추출 → norm.c
data modify storage mq:tmp norm.c set string from storage mq:tmp norm.in 0 1
# 공백 제거 (스킵)
execute if data storage mq:tmp norm{c:" "} run data modify storage mq:tmp norm.c set value ""
# 대문자 A-Z → 소문자 a-z
execute if data storage mq:tmp norm{c:"A"} run data modify storage mq:tmp norm.c set value "a"
execute if data storage mq:tmp norm{c:"B"} run data modify storage mq:tmp norm.c set value "b"
execute if data storage mq:tmp norm{c:"C"} run data modify storage mq:tmp norm.c set value "c"
execute if data storage mq:tmp norm{c:"D"} run data modify storage mq:tmp norm.c set value "d"
execute if data storage mq:tmp norm{c:"E"} run data modify storage mq:tmp norm.c set value "e"
execute if data storage mq:tmp norm{c:"F"} run data modify storage mq:tmp norm.c set value "f"
execute if data storage mq:tmp norm{c:"G"} run data modify storage mq:tmp norm.c set value "g"
execute if data storage mq:tmp norm{c:"H"} run data modify storage mq:tmp norm.c set value "h"
execute if data storage mq:tmp norm{c:"I"} run data modify storage mq:tmp norm.c set value "i"
execute if data storage mq:tmp norm{c:"J"} run data modify storage mq:tmp norm.c set value "j"
execute if data storage mq:tmp norm{c:"K"} run data modify storage mq:tmp norm.c set value "k"
execute if data storage mq:tmp norm{c:"L"} run data modify storage mq:tmp norm.c set value "l"
execute if data storage mq:tmp norm{c:"M"} run data modify storage mq:tmp norm.c set value "m"
execute if data storage mq:tmp norm{c:"N"} run data modify storage mq:tmp norm.c set value "n"
execute if data storage mq:tmp norm{c:"O"} run data modify storage mq:tmp norm.c set value "o"
execute if data storage mq:tmp norm{c:"P"} run data modify storage mq:tmp norm.c set value "p"
execute if data storage mq:tmp norm{c:"Q"} run data modify storage mq:tmp norm.c set value "q"
execute if data storage mq:tmp norm{c:"R"} run data modify storage mq:tmp norm.c set value "r"
execute if data storage mq:tmp norm{c:"S"} run data modify storage mq:tmp norm.c set value "s"
execute if data storage mq:tmp norm{c:"T"} run data modify storage mq:tmp norm.c set value "t"
execute if data storage mq:tmp norm{c:"U"} run data modify storage mq:tmp norm.c set value "u"
execute if data storage mq:tmp norm{c:"V"} run data modify storage mq:tmp norm.c set value "v"
execute if data storage mq:tmp norm{c:"W"} run data modify storage mq:tmp norm.c set value "w"
execute if data storage mq:tmp norm{c:"X"} run data modify storage mq:tmp norm.c set value "x"
execute if data storage mq:tmp norm{c:"Y"} run data modify storage mq:tmp norm.c set value "y"
execute if data storage mq:tmp norm{c:"Z"} run data modify storage mq:tmp norm.c set value "z"
# acc = acc + c (매크로 결합)
function mq:answer/normalize/append with storage mq:tmp norm
# 나머지로 진행
data modify storage mq:tmp norm.in set string from storage mq:tmp norm.in 1
function mq:answer/normalize/step

View File

@@ -5,7 +5,11 @@ execute if score qlen func.temp matches 0 run return 0
# 첫번째 항목 = 가장 먼저 제출된 것 # 첫번째 항목 = 가장 먼저 제출된 것
data modify storage mq:tmp judge set value {input:"", answer:""} data modify storage mq:tmp judge set value {input:"", answer:""}
data modify storage mq:tmp judge.input set from storage mq:input queue[0].text
# 입력 정규화 (소문자 + 공백제거) — 정답과 비교는 둘 다 정규화된 형태로
data modify storage mq:tmp norm.in set from storage mq:input queue[0].text
function mq:answer/normalize
data modify storage mq:tmp judge.input set from storage mq:tmp norm.acc
# 매크로로 해당 seq 를 가진 플레이어 찾아서 judge 실행 # 매크로로 해당 seq 를 가진 플레이어 찾아서 judge 실행
data modify storage mq:tmp _find set value {seq:0} data modify storage mq:tmp _find set value {seq:0}

View File

@@ -11,11 +11,11 @@ data modify storage mq:main spawn set value {x: 144, y: 61, z: -219, r: 180, f:
# pitch — 1.0 = 원본 속도 # pitch — 1.0 = 원본 속도
data modify storage mq:main audio set value {namespace: "musicquiz", source: "weather", volume: 1.0, pitch: 1.0} data modify storage mq:main audio set value {namespace: "musicquiz", source: "weather", volume: 1.0, pitch: 1.0}
# 정답 페인팅 — minecraft_launcher 리소스팩 musicquiz:cover_NN painting_variant # 정답 페인팅 — 데이터팩의 mq:cover_NN painting_variant (텍스처는 리소스팩 musicquiz:cover_NN)
# namespace — painting_variant 네임스페이스 (기본 "musicquiz") # namespace — painting_variant 네임스페이스 (기본 "mq")
# x,y,z — 페인팅 entity 좌표 (벽면 앞쪽 블록 위치) # x,y,z — 페인팅 entity 좌표 (벽면 앞쪽 블록 위치)
# facing — 페인팅이 바라보는 방향: south=0 / west=1 / north=2 / east=3 # facing — 페인팅이 바라보는 방향: south=0 / west=1 / north=2 / east=3
data modify storage mq:main image set value {namespace: "musicquiz", x: 144, y: 84, z: -261, facing: 0b} data modify storage mq:main image set value {namespace: "mq", x: 144, y: 84, z: -261, facing: 0b}
# 정답 입력용 marker entity 소환 좌표 # 정답 입력용 marker entity 소환 좌표
data modify storage mq:main marker set value {x: 144, y: 59, z: -219} data modify storage mq:main marker set value {x: 144, y: 59, z: -219}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_01",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_02",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_03",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_04",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_05",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_06",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_07",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_08",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_09",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_10",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_11",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_12",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_13",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_14",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_15",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_16",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_17",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_18",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_19",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_20",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_21",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_22",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_23",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_24",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_25",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_26",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_27",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_28",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_29",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_30",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_31",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_32",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_33",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_34",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_35",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_36",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_37",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_38",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_39",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_40",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_41",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_42",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_43",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_44",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_45",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_46",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_47",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_48",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_49",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:cover_50",
"width": 1,
"height": 1
}

View File

@@ -0,0 +1,5 @@
{
"asset_id": "musicquiz:gif",
"width": 1,
"height": 1
}

View File

@@ -1,6 +1,8 @@
{ {
"pack": { "pack": {
"pack_format": 75, "pack_format": 75,
"min_format": 75,
"max_format": 75,
"description": "음악퀴즈용 데이터팩입니다." "description": "음악퀴즈용 데이터팩입니다."
} }
} }

BIN
temp/gif.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

6
temp/gif.png.mcmeta Normal file
View File

@@ -0,0 +1,6 @@
{
"animation": {
"frametime": 1,
"interpolate": false
}
}