SOTA 로그 파서 v0.0.4 - 다운로드 준비 완료!
영어에서 기계 번역된 글입니다. 원문 보기
로그가 이미 알고 있던 것들
sotalogparser에 대한 둘러보기, 그리고 그것을 형성한 잘못된 답변들.
Shroud of the Avatar는 모든 것을 기록합니다. 모든 휘두름, 모든 낚시, 모든 실패한 명작 제작, 당신 근처에서 누군가 말한 모든 단어가 타임스탬프와 함께 일반 텍스트로, 이미 소유한 폴더에 저장됩니다. 2년 동안 플레이한 유저는 수백만 줄의 로그를 쌓아두고 있습니다.
거의 아무도 그것을 읽지 않습니다. 채팅 로그는 기록이 아니라 기록을 위한 원자재이기 때문입니다. 이것은 그 읽기를 수행하는 앱입니다: 크로스 플랫폼 데스크톱 애플리케이션으로, 그 폴더를 파싱하여 쿼리 가능한 인덱스로 만들고 13가지 방식으로 보고합니다.
규칙은 실제 코퍼스 384만 줄에 대해 도출되었으며 그중 99.91%를 인식합니다. 그 코퍼스가 이 글의 흥미로운 부분이 존재하는 이유입니다. 아래의 모든 비자명한 결정은 처음에는 그럴듯한 답변이었고, 코퍼스가 그것이 틀렸음을 증명했습니다.

구조의 형태
세 개의 레이어, 엄격하게 단방향입니다.
| 파싱, 발견, 인덱싱, 보고. UI 의존성 없음. |
| Avalonia 뷰 및 뷰 모델. |
| 진입점 전용. |
.NET 10, Avalonia 12, MVVM. 하나의 코드베이스가 6가지 런타임(Windows, macOS, Linux 각각 x64 및 arm64)용 자체 포함 단일 파일 빌드를 생성합니다. 테스트할 가치가 있는 모든 것은 Core에 있으며, 그래서 522개의 테스트가 있고 그중 어떤 것도 창을 필요로 하지 않습니다.
파이프라인
LogLineReader는 [타임스탬프] 메시지를 분할하고 연속 줄을 접습니다. ChatLogParser는 정렬된 규칙 목록을 실행하며, 첫 번째 일치가 승리합니다. 아무것도 주장하지 않는 것은 UnrecognizedEvent가 됩니다.
마지막 부분은 폴백이 아니라 규칙입니다. 줄을 절대 버리지 마세요. 인식되지 않은 버킷은 규칙 집합의 공백이 전혀 보이지 않게 하는 유일한 메커니즘입니다 — 일치하지 않는 것을 조용히 버리면 그것을 고치는 데 필요한 정확한 정보가 숨겨질 것입니다. 앱은 적용 범위 백분율을 표시하고 로그를 인식되지 않은 줄만으로 필터링할 수 있게 하며, 이것이 99.91%가 99.91%가 된 방법입니다.
인덱스
하나의 로그 파일은 LogSummary를 얻습니다. 전체 코퍼스의 모든 것은 SQLite 인덱스를 통해 처리됩니다: 파싱, 장면 컨텍스트 첨부, 사실 행 쓰기, 파일당 하나의 트랜잭션, 크기나 수정 시간이 변경된 파일만 다시 읽습니다. 384만 줄이 약 20초 안에 약 19MB로 인덱싱됩니다.
인덱스는 일회용 캐시이며 결코 진실의 원천이 아닙니다. 스키마나 파서 변경은 버전을 올리고, 파일은 마이그레이션 대신 삭제되고 재구축됩니다. 그 안의 어떤 것도 로그에서 재생성할 수 없으므로, 그 안의 어떤 것도 마이그레이션 버그의 위험을 감수할 가치가 없습니다.
코퍼스가 있어야 배운 두 가지가 있습니다.
파서는 줄 단위로 상태가 없으므로, 구역 변경 줄만이 무언가가 어디서 일어났는지 압니다. 추적기는 마지막으로 진입한 장면을 래치하고 세션 시작 시 재설정합니다. 실제 이벤트의 약 4분의 1은 Entering 줄 이전에 발생합니다 — 그것들은 (unknown) 장면에 들어가며, 이는 보고서가 보여주어야 하는 실제 버킷이지 걸러내야 할 공백이 아닙니다.
전투에는 방향이 있습니다. 코퍼스의 공격 줄 중 4분의 1은 몹이 플레이어를 때리는 것이며, 그들의 능력은 플레이어의 것과 똑같이 보입니다. 방향으로 분할하지 않으면 "당신의 스킬"은 플레이어가 한 번도 사용하지 않은 스킬을 나열합니다.
13가지 보고서
레일이 그것들을 그룹화합니다. 각각은 처음 열릴 때 지연 로드되고 날짜, 장면 또는 캐릭터 필터가 변경될 때 다시 로드됩니다; 모든 것은 CSV로 내보낼 수 있습니다.
개요 및 로그 브라우저
인덱스가 다루는 것, 그리고 파서가 본 단일 로그의 모든 줄. 브라우저는 위의 적용 범위 규칙을 위해 존재합니다 — Unrecognized로 필터링하면 파서의 남은 사각지대를 순서대로 보고 있는 것입니다.
전투 — 스킬 대 몹
각 스킬이 각 대상에 대해 어떻게 수행되는지, 그리고 어떤 조합이 나머지 데이터가 예측하는 것보다 더 나은지. 65개의 스킬이 282개의 대상을 교차하는 것은 양방향 테이블이며, 흥미로운 셀은 자신의 행과 열 모두를 이기는 셀입니다. 세 가지 선택, 각각은 처음에는 틀렸습니다:
평균이 아닌 중앙값 폴리시(median polish). 평균을 사용하면 하나의 예외적인 셀이 자신의 스킬 행 과 대상 열을 끌어올려 모든 이웃이 저항하는 것으로 읽힙니다. 하나의 실제 발견, 여섯 개의 발명된 것.
가중치 없음. 중앙값에 가중치를 두면 행 관측치의 절반 이상을 보유한 셀이 자신의 기준선을 정의할 수 있습니다 — 이는 정확히 가장 많이 측정하고 싶은 과도하게 파밍된 조합입니다.
표본 게이트뿐만 아니라 분산 게이트. 두 대상에만 사용된 스킬은 독립적인 기준선이 없으므로 두 셀 사이의 차이가 엄청난 상호작용으로 읽힙니다. 실제 코퍼스에 대해 이 단일 게이트는 하나의 방어 가능한 발견과 여덟 개의 인공물 사이의 차이입니다.
전투 — 당신을 때리는 것

거울 질문, 그리고 가장 새로운 보고서: 어떤 생물이 무엇으로, 얼마나 많이, 얼마나 자주 당신을 공격하고, 당신의 방어가 그것을 얼마나 자주 막는지. 그것은 분명히 화살표가 반대인 이전 보고서가 아닙니다 — 나가는 기계를 재사용하는 것은 네 가지 방식으로 틀렸을 것이며, 그 각각은 눈에 보이는 실패가 아닌 그럴듯한 숫자를 생성합니다.
들어오는 공격의 절반 이상이 펫에게 맞습니다.
시도 | |
|---|---|
플레이어를 겨냥한 | 51,138 |
펫을 겨냥한 | 64,248 |
그리고 그것들은 전혀 다르게 행동합니다: 플레이어를 겨냥한 타격의 52%는 아무것도 연결하지 못하는 반면, 펫을 겨냥한 타격의 0.5%만 그렇습니다. 합치면 방어 프로필은 어느 쪽에도 속하지 않습니다. 펫은 제외되며 — 그들의 몫은 보고됩니다. "이것은 당신에게 던져진 것의 44%를 다룹니다"라는 것은 독자가 알아야 할 사실이기 때문입니다.
명백한 방어 수치는 방어의 대부분을 생략합니다. 나가는 보고서의 공식은 회피, 차단, 패리, 빗맞음을 세어 18%의 들어오는 공격으로 계산합니다. 그러나 들어오는 공격의 52%는 연결되었지만 아무것도 하지 않았습니다 — 그 공식에서 제외됩니다. 정직한 수치는 66.2%입니다. 한편 차단과 저항은 들어오는 줄에 전혀 없습니다 — 384만 줄에서 각각 0개 — 그래서 그 열은 구조적 0으로 표시되는 대신 생략됩니다. 항상 0인 열은 "당신은 한 번도 차단한 적이 없습니다"로 읽히기 때문입니다.
회피는 무엇을 회피했는지 결코 이름을 밝히지 않습니다. 들어오는 회피 7,120개와 나가는 회피 17,474개 모두 그것을 유발한 것이 무엇이든 이름 없는 버킷에 있습니다. 그래서 모든 능력별 비율은 능력을 이름을 밝힌 공격으로 나누고, 회피율은 그것이 사실인 생물별 롤업에 있습니다.
그리고 순위는 스윙당 피해로 매겨집니다. 그럴듯한 세 가지 순서가 거의 일치하지 않기 때문입니다:
시도 | 스윙당 | 히트당 | 통과율 | |
|---|---|---|---|---|
거대 악어, 기본 | 4,310 | 2.1 | 58 | 4% |
래저백 (T18), 기본 | 217 | 23.4 | 461.5 | 5% |
비고렘 카바스 (T14), 섀도우 블래스트 | 309 | 247.9 | 247.9 | 100% |
빈도로 순위를 매기면 보고서는 2의 피해를 주는 악어로 시작합니다. 히트당 피해로 순위를 매기면 20번에 한 번 발생하는 이벤트로 시작합니다. 오직 스윙당만이 연결률을 포함하고 이것이 나에게 얼마나 들 것인가에 답합니다.
전투 — 기록

개인 최고 기록: 스킬별 가장 큰 크리티컬, 받은 가장 강한 타격, 각각 그것이 나온 줄로 추적 가능. 이것은 앱의 나머지가 의존하는 롤업을 되돌려야 하는 유일한 보고서입니다. 펫 피해는 소유자에게 귀속되며, 이는 합계에는 맞지만 기록에는 틀립니다:
플레이어 | 펫 | |
|---|---|---|
가장 큰 크리티컬 | 1,843 (체인 라이트닝) | 6,735 (와이번 스팅) |
받은 가장 강한 타격 | 1,206 | 2,628 |
플레이어보다 펫에게 더 많은 타격이 맞습니다 — 44,329 대 64,245 — 그래서 "당신이 받은 가장 강한 타격"은 확인하지 않으면 다른 사람의 상처입니다. 최고 기록은 캐릭터별로 있으며 결코 합산되지 않고, 동률은 가장 이른 것으로, 지속 피해는 제외됩니다: 코퍼스에서 그중 가장 큰 것은 13,555로 모든 공격을 이기며, 그것을 조용히 포함하면 다른 질문에 답하게 됩니다.
세계 — 장면 활동
시간이 어디에 쓰였는지, 그리고 각 장소가 무엇에 좋았는지. 올바르게 처리해야 할 세 가지:
비율은 신뢰할 수 있는 분모가 필요합니다. Arlia에서 3분은 10,000 XP 보상을 하나 모았습니다 — 시간당 206,897로, 80시간 동안 파밍된 장소보다 앞선 2위입니다. 장면별 수치는 여전히 그것이 나온 분 옆에 표시되지만, 순위는 30분 최소 시간을 적용하고 얼마나 많은 장면이 제외되었는지 말합니다.
킬과 죽음은 반대쪽 끝에서 읽은 같은 줄입니다. 281개의 죽음 줄은 246개의 킬, 22개의 죽음, 15개의 방관자, 2개의 자살입니다. 행을 세는 것은 실제로 만들어진 킬보다 5분의 1 더 많은 킬을 보고하고 모든 죽음을 숨깁니다.
시체 전리품은 전투이고, 수확은 채집입니다. Tanglemire는 743개의 공격, 1,305개의 수확, 그리고 전리품이 전혀 없음을 기록합니다. 하나의 결합된 전리품 버킷은 어느 쪽 합계가 이기든 그것으로 레이블을 붙이므로, 늑대가 있는 낚시터는 전투 구역으로 나옵니다.
세계 — 전리품 및 낚시
드롭이 어디서 왔는지, 각 장소가 실제로 무엇을 산출하는지; 모든 낚시는 낚은 곳, 물, 종별로 피벗됩니다.
제작 — 레시피
레시피별 예외율, 명작이 얼마나 밀어질 수 있는지, 그리고 그것이 얼마나 들었는지. 구간은 정규 근사가 아닌 Wilson 점수 구간입니다 — 이는 8번 중 7번 성공에서 상한을 1 위로 두고 12번 중 0번에서 점으로 붕괴합니다. 세 가지 더:
시도는 한 번의 제작입니다. 두 완료 줄은 대안이며 결코 둘 다가 아닙니다. 코퍼스는 즉시 실수를 드러냅니다: 다크 레드 다이는 73,231개의 일반과 73,433개의 예외를 기록하므로, 예외를 시도의 부분 집합으로 취급하면 100% 이상의 성공률이 나옵니다.
명작 실패는 시도가 이루어진 곳보다 한 단계 아래의 아이템을 이름으로 말합니다. 인쇄된 숫자로 집계하면 아무것도 없는 곳에서 부드러운 곡선을 발명합니다.
유의성과 효과 크기는 별개의 양입니다. 구간은 레시피가 전체 비율과 정말로 다른지 결정합니다; 관찰된 비율은 언급할 만큼 충분히 다른지 결정합니다. 그것들을 혼합하면 45% 근처에 모인 세 가지 음식 레시피 중 하나를 표시하고 두 이웃은 표시하지 않았습니다.
더 보기 — 진행
획득한 경험치와 훈련된 스킬. 조용한 구간은 유지됩니다 — 무언가 일어난 날로만 만들어진 시리즈는 한 달을 끊기지 않은 연속으로 그리며, 독자가 그것을 열어 알아내려는 것의 정확히 반대입니다.
그리고 단계는 레벨이 아닙니다. 게임은 모든 레벨을 알리지 않습니다: 재봉은 44, 48, 51, 54로 진행되므로 85개의 알림이 117개의 레벨을 다룹니다. 보고서는 단계와 관찰된 범위를 보여주고, 알림보다 더 많은 레벨이 지나간 행을 표시합니다. "획득한 레벨"은 단순히 로그에 없으며, 보고서는 추측하는 대신 그렇게 말합니다.
관련된 함정, 코퍼스 전체에 걸쳐: 경험치 판독값은 누적 합계이며, 풀당 네 가지 다른 것이 있습니다 — 평생 획득, 캐릭터 풀, 공유 풀, 그리고 그 합계가 블록으로 함께 기록됩니다. 판독값은 실제로 수여된 1억 8,700만 대비 1조 5,700억으로 합산됩니다. 수여는 종류별로 긍정적으로 선택되며, "판독값이 아닌 것"으로는 절대 선택되지 않습니다. 그 표현은 나중에 추가된 모든 판독값 종류를 조용히 인정하기 때문입니다.
더 보기 — 대화
평평한 채팅 스트림이 교환으로 다시 실로 꿰어집니다. 로그에는 대화 표시가 전혀 없으므로, 말이 10분 동안 멈춘 곳마다 실행이 분할됩니다. 두 가지 규칙이 자리를 얻습니다: 플레이어만 있는 실행은 대화가 아닙니다 (그렇지 않으면 Traders에서 광고하는 데 보낸 세션이 일방적인 "교환"으로 보고서를 채웁니다), 그리고 타임스탬프가 없는 메시지는 파일 위치를 유지합니다 (null을 앞으로 정렬하면 대화 전체 너비의 공백이 열립니다).
"나"는 로그 자체의 캐릭터에 대해 행별로 해석됩니다 — 6명의 캐릭터가 있는 코퍼스는 내가 누구인가에 대한 6개의 답변을 가집니다.
더 보기 — 경제
대부분 계산을 거부하는 것으로 유명합니다. 로그에는 가격도 구매 줄도 없습니다, 그래서 판매된 단위는 알 수 있고 수익은 알 수 없습니다. 유일한 금화 수치는 You picked up N gold.이며, 이는 당신의 상인과 아무 관련이 없습니다. 보고서는 그렇게 말합니다. 판매 테이블 옆에 인쇄된 금화 숫자는 수익으로 읽힐 것이기 때문입니다.
그것이 표면화하는 것은 상시 주문 분할입니다 — 주문 이행 대 구매 — 이는 데이터에서 판매자가 행동할 수 있는 유일한 것이며, 코퍼스에서 깔끔하게 나뉘어 나왔습니다: 모든 원자재는 100% 주문, 모든 정제품은 100% 구매.
더 보기 — 거래

플레이어 간 거래가 다시 접혀집니다. 거래는 줄의 실행입니다 — 열림, 물건 올림 및 되찾음, 닫힘 — 그리고 어떤 단일 줄도 무엇이 오갔는지 말하지 않습니다. 네 가지:
금화는 변화가 아니라 누적 합계입니다. 줄은 새 수치를 말합니다. 코퍼스의 실제 거래는 완료 전에 금화를 99,000으로 올렸다가 0으로 되돌립니다; 줄을 합산하면 움직이지 않은 9만 9천 금화를 보고합니다.
양쪽은 비대칭적으로 기록됩니다. 게임은 파트너가 아이템을 추가 하고 제거하는 것을 기록하지만, 플레이어는 추가만 — 철회는 결코 기록하지 않습니다. 그래서 플레이어 쪽은 "제안된 것"이며 과장할 수 있습니다; 파트너 쪽은 정확합니다. 보고서는 어느 쪽이 어느 것인지 말합니다.
대부분의 "거래"는 자신과의 거래입니다. 완료된 106건의 거래 중 64건은 플레이어 자신의 부캐 간이며, 양쪽 부캐의 로그가 모두 있으면 같은 거래가 각 측에서 한 번씩 두 번 저장됩니다. 표시되고 필터링 가능합니다.
파트너 이름은 때때로 게임에 의해 손상됩니다 —
Zealoty,,1]Zealoty. 이것은 파서가 하는 것이 아니라 로그에 있는 것입니다. 복구는 정확히 그 이중 형태만 일치시킵니다. 실제 이름에는 쉼표가 포함되기 때문입니다.
동반 사이트
앱은 선택적으로 동반 웹사이트에 로그인하고 네 가지 데이터 세트를 게시할 수 있습니다: 개인 최고 기록, 낚시 어획, 스킬 대 대상 셀, 몬스터 능력.
마지막 두 가지는 존중해야 할 방식에서 처음 두 가지와 다릅니다. 그것들은 누적 합계이므로, 재게시는 누적이 아니라 대체합니다 — 이는 게시가 항상 날짜와 장면으로 필터링되지 않아야 함을 의미합니다. 대체 의미론에서 필터링된 조각은 더 약한 수치를 보내는 것이 아니라 더 완전한 수치를 삭제하기 때문입니다. 그리고 서버의 셀 상한을 초과하는 캐릭터는 같은 이유로 잘리는 대신 전체가 건너뜁니다.
올라가는 것은 충분 통계량입니다 — 개수, Σln(1+피해), Σln(1+피해)² — 적합된 결과가 아니라, 중앙값 폴리시는 플레이어 간에 합산되지 않고 합계는 합산되기 때문입니다. 그것들은 가산적이며, 이것이 정확한 커뮤니티 풀링과 상수 시간 leave-one-out을 가능하게 하는 것입니다. (1 +는 하중을 견디는 것입니다: 역은 exp(x) − 1이며, 일반 exp로 다시 읽으면 수백 피해에서 1% 미만, 3에서 3분의 1이 어긋납니다. 모든 곳에서 그럴듯하고 모든 곳에서 틀립니다. 그것이 사이트의 첫 구현이 출시된 방법입니다.)
코퍼스가 여기서도 가르친 한 가지. 능력은 대체로 그 생물의 속성입니다 — 74개의 능력 중 22개는 정확히 하나에 속하며, 272개의 생물 중 169개는 두 개 이하를 가집니다. 그래서 맞출 양방향 모델이 없습니다; 그것을 대체하는 것은 능력의 관측치 대부분을 보유한 생물이 자신의 기준선을 정의하고 자신을 평범하다고 보고할 수 없도록, 세 개 이상의 생물이 사용하는 곳에서만 능력을 자신과 비교합니다. 흙 정령은 지진의 3,637 스윙 중 2,955개를 보유하고 0.08×로 나옵니다; 자기 포함 풀은 약 1.0으로 읽히고 아무 말도 하지 않았을 것입니다.
계정은 선택 사항이며 선택 사항으로 유지됩니다. 세션 복원은 파일을 읽고 요청을 하지 않습니다. 첫 패킷은 Sign in 또는 Publish를 클릭할 때 기계를 떠나며, 그 전에는 절대 아닙니다. 어떤 보고서도 로그인 상태에 의존하지 않으며, 게시 컨트롤은 로그아웃 상태에서 비활성화로 표시되는 대신 숨겨집니다.
개인정보 보호
채팅 로그에는 다른 플레이어의 메시지가 포함되어 있으며, 이 사실은 정책에서 언급되는 대신 코드를 제약합니다.
인덱스는 원시 메시지 텍스트를 저장합니다 — 그것이 바로 대화 보고서입니다. 그것은 저장소 외부의 앱 데이터 디렉토리에 있으며, 그것의 어떤 것도 결코 업로드되지 않습니다. 미래의 어떤 페이로드도 사용자에게 명시적으로 묻지 않고 그것을 바꾸어서는 안 됩니다.
게시가 보내는 것은 캐릭터 이름, 스킬 및 생물 이름, 수치, 장면 및 시간입니다. 그중 하나는 주의가 필요합니다: 로그는 공격자가 생물인지 다른 플레이어인지 결코 말하지 않습니다, 그래서 공격자 이름은 실제 사람의 것일 수 있습니다. 이것이 게시가 첫 업로드 전에 데이터 세트당 실제 행을 세는 대신 한 번 보여주는 이유입니다. 업로드는 외부를 향하며 여기서 되돌릴 수 없습니다.
실제 로그는 git-ignored입니다; 테스트 픽스처는 수동으로 편집됩니다.
그것이 있는 곳
끝에서 끝까지 작동합니다. 13개의 보고서, 레일에 남은 자리 표시자 없음, 522개의 테스트, 6개의 릴리스 대상. 파서는 코퍼스의 99.91%를 가지며 나머지 0.09%는 쓸어버리는 대신 앱에서 볼 수 있습니다.
그 모든 것을 관통하는 실마리가 있다면, 그것은 코퍼스가 옳았고 추론이 틀렸다는 것이 반복적이라는 것입니다. 위의 "세 가지"로 시작하는 모든 제목은 실제로 일어난 300만 줄에 대해 누군가 확인할 때까지 올바르게 보였던 숫자 목록입니다. 그것이 전체 방법입니다: 게임이 아마 기록할 것에 대해 추론하는 대신 코퍼스에 대해 패턴을 확인하세요.
Downloads
- ⬇ SotaLogParser-0.0.4-linux-arm64-0.0.4.zip41 MB · 5 downloadssha256 4730c85a2f0e24fd99c482c910bc85555ae7fe0f3020fd05d6d99c9bda8451db
- ⬇ SotaLogParser-0.0.4-linux-x64-0.0.4.zip43 MB · 6 downloadssha256 f2b238d29931a4870c9b3833383f77f2738598cf7cf1134d7d8ca4a3464025a4
- ⬇ SotaLogParser-0.0.4-osx-arm64-0.0.4.zip44 MB · 6 downloadssha256 19b63abac37cdc3978b9e1912075ca5d0c68b2c06f9e049e6ef0d7e49849e26b
- ⬇ SotaLogParser-0.0.4-win-arm64-0.0.4.zip68 MB · 6 downloadssha256 290855d72cf515bdcc9be5595b84a17e33e7eded4c930c3cef93fcd18de7f499
- ⬇ SotaLogParser-0.0.4-osx-x64-0.0.4.zip46 MB · 5 downloadssha256 8403aa7488fa4c58a833b98e5e11106730c3db1f691596dbe998847bc8182cbd
- ⬇ SotaLogParser-0.0.4-win-x64-0.0.4.zip70 MB · 8 downloadssha256 9e8ba3948b49a650859eb28859cc8aec104ae98db27fce708470e37454537266
