본문으로 건너뛰기

매트릭스 표 — 컬럼 이름이 행 id인 것

문서 목록으로

두 축의 곱을 격자로 적은 시트를 읽는 설계입니다.

어느 레이아웃의 기능인가 — 지금은 이름 기반 레이아웃 하나입니다. 이 문서는 「격자를 이미 있는 형태로 읽는 법」을 정하고 레이아웃을 한정하지 않는데, 구현은 워크북의 정의된 이름으로 테이블 경계를 잡는 레이아웃에만 있습니다. 주 레이아웃에서 격자를 적으면 이 설계가 아니라 「컬럼 이름이 식별자가 아니다」로 거부됩니다 — 그 거부가 이 설계의 출발점이고, 아래 「매트릭스로 판독하는 조건」이 그것을 뒤집는 규칙입니다. 뒤집는 자리가 레이아웃마다 따로이기 때문에 한쪽에만 있습니다.

주 레이아웃에서 지금 쓸 수 있는 형태는 복합 키입니다 — key="attacker,defender" 로 적으면 두 축의 곱이 행이 되고 조회가 다인자가 됩니다(주 레이아웃 §3.5). 격자보다 넓게 적히는 대신 표기가 이미 있고, 이 설계가 사는 이유(105,558칸을 219행으로)는 규모가 그만할 때 생깁니다.


시트가 하는 말

id 24000000 24000001 24000002 ... (482개)
key:11000000~11999999 number number number
:required 1 1 1
11000000 0 -25 -125
11000001 ...

첫 컬럼은 한 축이고, 나머지 컬럼 이름 전부가 다른 축의 id입니다. 값은 그 둘의 교차점 하나입니다. 219 × 482 = 105,558개.

문제는 하나뿐입니다 — 24000000은 식별자가 아닙니다. 생성되는 코드는 프로퍼티 이름이 필요하고, 숫자로 시작하는 이름을 가질 수 있는 언어가 13개 중에 없습니다.

테이블 여부

낯설게 보이는 것이 당연하고, 답은 그렇다입니다.

매트릭스는 키 두 개의 함수입니다. 우리 테이블은 키 하나에서 레코드로 가는 것이고요. 그 둘을 잇는 방법은 이미 있습니다 — 한 축을 행으로, 다른 축을 배열의 자리로.

행 = 마을, 배열의 자리 = 교역품, 칸 = 값

그러면 남는 문제가 이름 하나뿐입니다. 24000000은 식별자가 아니라 프로퍼티 이름이 될 수 없는데, 배열의 원소는 이름이 필요 없습니다. 대신 「그 자리가 어느 id였나」를 잃으므로, 그것만 옆 테이블로 돌려주면 됩니다.

그래서 이 문서가 정하는 것은 새 형태가 아니라 격자를 이미 있는 형태로 읽는 법입니다.

출력 방식

테이블 둘. 값은 배열 하나로, 컬럼 id는 그 옆의 테이블로.

나오는 것형태
SystemMatrix{ id, value: number[482] } × 219행
SystemMatrixColumn{ id, at: int } × 482행

이름이 이름인 컬럼은 그대로 남습니다 — CombatFaction{ id, name, value: number[7] }입니다.

var at = Data.SystemMatrixColumn.FindById(goodsId).At;
var cost = Data.SystemMatrix.FindById(townId).Value[at];

코어는 한 줄도 바뀌지 않습니다. 배열 컬럼도 기본 인덱스도 이미 있는 것이고, 매트릭스는 우리가 이미 표현할 수 있는 테이블의 다른 표기였을 뿐입니다. 형식도, 생성기 13개도, 와이어도 그대로입니다 — 바뀌는 것은 그 격자를 읽는 레이아웃 파일 하나입니다.

한 줄은 나중에 필요해졌습니다. 격자에 행 벌이 있으면 컬럼 집합이 벌마다 다르고, 접기는 컬럼 이름으로 맞춥니다 — 그런데 격자의 컬럼 이름은 이 문서가 위치로 다시 붙인 것입니다. 그래서 코어에 「이 컬럼을 벌끼리 맞출 때 쓰는 이름」 하나가 생겼고, 격자는 거기에 컬럼 id를 넣습니다. 코어는 여전히 격자를 모릅니다.

벌이 있는 격자

지역마다 축의 크기가 다를 수 있습니다 — 실측에서 원본이 마을 735개, 벌이 724개이고 벌의 id가 원본의 부분집합이지만 접두사가 아닙니다. 규칙과 실측은 행 벌의 4.2에 있고, 이 문서가 지키는 것은 둘입니다.

무엇
컬럼마다 맞추는 이름에 컬럼 id를 넣습니다접기가 위치가 아니라 id로 맞추도록
벌인 시트는 컬럼 테이블을 만들지 않습니다접힌 뒤 자리는 원본의 것이므로, 벌의 컬럼 테이블은 틀린 자리를 적은 표가 됩니다

값 배열은 그 결과로 원소가 없을 수 있는 배열이 됩니다. 벌에 없는 마을이 그 벌의 행에서 「값 없음」이고, 그것이 「0이라고 적혀 있음」과 구별되어야 하기 때문입니다.

상수셋을 쓰지 않는 이유

컬럼 id를 상수로 내는 쪽을 먼저 봤습니다. 되지 않습니다 — 상수는 스칼라뿐이고, 배열 상수를 내려면 렌더러 13개를 고쳐야 합니다. 코어를 건드리지 않는다는 이 설계의 전제가 거기서 깨집니다.

그리고 되더라도 테이블 쪽이 낫습니다. 상수 배열에서 id를 찾는 것은 482개를 훑는 일이고, 테이블은 생성된 인덱스로 한 번에 찾습니다. 원래 하려던 일 — 「id로 자리를 찾는다」 — 을 테이블이 이미 하고 있었습니다.

long-form 3컬럼을 쓰지 않는 이유

{townId, goodsId, value} 한 행이 셀 하나면 105,558행이 됩니다. 코어 무변경인 것은 같지만,

  • 행이 500배가 되고,
  • 조회가 복합 키라 생성되는 인덱스로는 못 찾습니다 — 로드 후 사전을 손으로 만들어야 합니다.

데이터가 성기다면 이야기가 달랐을 텐데, 측정해 보니 105,558칸 중 비어 있는 것은 482칸(한 행) 뿐입니다. 성기지 않은 격자에 long-form을 쓰면 좌표를 값보다 많이 저장하게 됩니다.

매트릭스로 판독하는 조건

이름이 정수인 컬럼이 하나라도 있을 때입니다. 그 컬럼들만 배열이 되고, 이름이 이름인 컬럼은 지금까지대로 보통 필드로 남습니다.

「나머지 전부가 정수여야 한다」로 두면 실제 시트가 걸립니다 — CombatFactionid 다음에 name이 오고 그 뒤부터 id 컬럼입니다. 격자에 설명 컬럼이 하나 붙어 있는 것이지 격자가 아닌 것이 아닙니다.

규칙
이름이 정수인 컬럼 → 배열의 원소시트 순서 그대로가 자리입니다
이름이 식별자인 컬럼 → 그대로name은 축이 아니라 그 행의 설명입니다
정수 컬럼의 타입은 전부 같아야한 배열의 원소들이므로. 다르면 그 컬럼과 함께 거부합니다

정수 이름 컬럼이 하나도 없으면 아무것도 달라지지 않습니다. 그리고 있는 표는 지금까지 「24000000은 식별자가 아닙니다」로 거부되던 것이므로, 동작하던 시트가 알아채지 못할 다른 형태가 되는 경우가 없습니다.

자르기는 걸지 않습니다. 이 레이아웃은 값이 있는 마지막 원소에서 배열을 자르는데 (설계), 매트릭스에서 그러면 로우마다 배열 길이가 달라지고 value[at]이 성립하지 않습니다. 자리가 곧 뜻인 배열은 자를 수 있는 배열이 아닙니다.

컬럼 테이블의 이름

<테이블 이름>Column입니다. 두 번째 축에 시트가 붙여준 이름이 없기 때문입니다 — 있는 것은 id 하나뿐이고 그것은 첫 축의 것입니다.

at자리이지 id가 아닙니다. 배열이 0부터 세므로 시트에 적힌 순서 그대로이고, 컬럼이 중간에 추가되면 그 뒤가 전부 밀립니다 — 그래서 배포할 때 두 테이블은 같이 나가야 합니다. 한쪽만 새것이면 알아채지 못할 다른 칸을 읽습니다.