slow.monster

STUDIO HAZE · jeniapp

Topaz source

Open by house policy. Topaz is our own language.

Topaz 5.20.2 · 63 files

apps/slow-monster/core/lineagedex.tpz

Topaz · 4897 B · Original file

1// 계통도감의 나무 배치를 계산합니다. 열은 세대이고 뿌리가 왼쪽, 자손이 오른쪽으로 가지를 칩니다.
2// 입력은 발견 순서의 계통 노드 목록이고 출력은 노드마다 열, 행, 픽셀 좌표, 부모의 배치 번호와 나무 전체 크기입니다.
3// 난수 없이 목록 순서만 쓰므로 같은 목록은 늘 같은 배치입니다.
4// 노드 수와 세대를 상수로 가둬 조작된 목록도 멈추지 않거나 넘치지 않고, 가시 영역 160x144 를 넘는 나무는 페이지가 스크롤합니다.
5// Lineage dex layout: a bounded, deterministic depth-first tree layout of discovered lineage nodes.
7import core.evolution
8import core.util { 범위가두기 }
10// 형제를 훑는 배치는 노드 수의 제곱에 가까워 조작된 큰 목록을 256 에서 자릅니다. 그 너머 노드는 그리지 않습니다.
11export let 노드상한 = 256
12export let 세대상한 = 99
13export let 열간격 = 34
14export let 행간격 = 22
15export let 여백x = 14
16export let 여백y = 24
18// 인덱스는 노드 목록의 발견 순서이고 커서가 가리키는 값입니다. 부모인덱스는 배치 목록 안의 부모 자리이며 뿌리와 고아는 -1 입니다.
19export type 배치노드 = {
20 인덱스: int,
21 고유번호: int,
22 부모인덱스: int,
23 열: int,
24 행: int,
25 x: int,
26 y: int,
27 형태이름: string,
28 게놈요약: string,
29 세대: int,
30 시드지문: string,
33export type 계통레이아웃 = {
34 노드들: Array<배치노드>,
35 너비: int,
36 높이: int,
37 행수: int,
40// 부모고유번호 0 은 뿌리이고, 목록에 없는 부모를 가리키는 노드는 고아라 뿌리처럼 다룹니다.
41function 부모인덱스찾기(노드들: Array<evolution.계통노드>, 부모고유번호: int) -> int {
42 if 부모고유번호 == 0 { return -1 }
43 for i in 0..<노드들.length {
44 if 노드들[i].고유번호 == 부모고유번호 { return i }
45 }
46 -1
49function 자식인가(자식: evolution.계통노드, 부모: evolution.계통노드) -> bool {
50 자식.부모고유번호 != 0 && 자식.부모고유번호 == 부모.고유번호
53function 뿌리인가(노드들: Array<evolution.계통노드>, 노드: evolution.계통노드) -> bool {
54 부모인덱스찾기(노드들, 노드.부모고유번호) < 0
57function 자식인덱스들(노드들: Array<evolution.계통노드>, 부모인덱스: int) -> Array<int> {
58 let 부모 = 노드들[부모인덱스]
59 [for i in 0..<노드들.length if i != 부모인덱스 && 자식인가(노드들[i], 부모) => i]
62function 배치인덱스찾기(배치들: Array<배치노드>, 노드인덱스: int) -> int {
63 for i in 0..<배치들.length {
64 if 배치들[i].인덱스 == 노드인덱스 { return i }
65 }
66 -1
69// 뿌리부터 발견 순서대로 깊이 우선 전위 순회하며 방문 순서대로 행을 줍니다. 자식이 부모 바로 아래에 모입니다.
70// 스택에는 역순으로 넣어 꺼내는 순서가 발견 순서가 되게 합니다. 방문 표시가 순환과 중복을 막고 방문 수는 노드상한에서 멈춥니다.
71export function 레이아웃계산(노드들: Array<evolution.계통노드>) -> 계통레이아웃 {
72 let mut 방문 = [for i in 0..<노드들.length => false]
73 let mut 배치들: Array<배치노드> = []
74 let mut 최대열 = 0
75 let mut 스택 = [for i in (노드들.length - 1)..0 by -1 if 뿌리인가(노드들, 노드들[i]) => i]
76 while 스택.length > 0 && 배치들.length < 노드상한 {
77 let 인덱스 = 스택[스택.length - 1]
78 스택 = 스택.slice(0, 스택.length - 1)
79 if !방문[인덱스] {
80 방문[인덱스] = true
81 let 노드 = 노드들[인덱스]
82 let 열 = 범위가두기(노드.세대, 0, 세대상한)
83 let 행 = 배치들.length
84 최대열 = 최대열.atLeast(열)
85 let 부모인덱스 = 부모인덱스찾기(노드들, 노드.부모고유번호)
86 배치들.push({
87 인덱스: 인덱스,
88 고유번호: 노드.고유번호,
89 부모인덱스: if 부모인덱스 < 0 { -1 } else { 배치인덱스찾기(배치들, 부모인덱스) },
90 열: 열,
91 행: 행,
92 x: 여백x + 열 * 열간격,
93 y: 여백y + 행 * 행간격,
94 형태이름: 노드.형태이름,
95 게놈요약: 노드.게놈요약,
96 세대: 노드.세대,
97 시드지문: 노드.시드지문,
98 })
99 let 자식들 = 자식인덱스들(노드들, 인덱스)
100 for i in (자식들.length - 1)..0 by -1 { 스택.push(자식들[i]) }
101 }
102 }
103 // 노드 카드 30x18 이 들어갈 여유를 더하고 가시 영역보다 작아지지 않게 합니다.
104 {
105 노드들: 배치들,
106 너비: (여백x + 최대열 * 열간격 + 32).atLeast(160),
107 높이: (여백y + 배치들.length * 행간격 + 18).atLeast(144),
108 행수: 배치들.length,
109 }

SHA256 ed0ec9eaa05715f0847ef9b96e75c0d39c4167b54f0674dc42adca67b1613429