SOTA Log Parser v0.0.4 - Pronto per il download!
Tradotto automaticamente dall'inglese. Vedi l'originale
Cosa sapevano già i log
Un tour di sotalogparser, e delle risposte sbagliate che lo hanno plasmato.
Shroud of the Avatar scrive tutto. Ogni colpo, ogni cattura, ogni capolavoro fallito, ogni parola detta da chiunque vicino a te, con timestamp, in testo semplice, in una cartella che già possiedi. Un giocatore con due anni di esperienza si ritrova con qualche milione di righe.
Quasi nessuno le legge, perché un log di chat non è un registro — è la materia prima per uno. Questa è un'app che fa la lettura: un'applicazione desktop multipiattaforma che analizza quella cartella in un indice interrogabile e ne riferisce in tredici modi.
Le regole sono state derivate da un corpus reale di 3,84 milioni di righe e ne riconoscono il 99,91%. Quel corpus è il motivo per cui le parti interessanti di questo post esistono. Ogni decisione non ovvia qui sotto è stata prima una risposta plausibile, e il corpus è ciò che ha dimostrato che era sbagliata.

La forma della cosa
Tre livelli, strettamente unidirezionali.
| Parsing, scoperta, indicizzazione, reportistica. Nessuna dipendenza dall'interfaccia utente. |
| Viste e view model Avalonia. |
| Solo punto di ingresso. |
.NET 10, Avalonia 12, MVVM. Un'unica base di codice produce build autonome a file singolo per sei runtime — Windows, macOS e Linux, x64 e arm64 ciascuno. Tutto ciò che merita un test vive in Core, ed è per questo che ce ne sono 522 e nessuno richiede una finestra.
La pipeline
LogLineReader divide [timestamp] messaggio e piega le righe di continuazione. ChatLogParser esegue un elenco ordinato di regole, vince la prima corrispondenza. Qualunque cosa non venga rivendicata diventa un UnrecognizedEvent.
Quell'ultima parte è una regola, non un ripiego. Non perdere mai una riga. Il secchio dei non riconosciuti è l'unico meccanismo attraverso cui una lacuna nel set di regole è visibile — scartare silenziosamente ciò che non corrisponde nasconderebbe esattamente l'informazione necessaria per risolverla. L'app mostra la percentuale di copertura e ti permette di filtrare un log fino alle sole righe non rivendicate, ed è così che il 99,91% è diventato il 99,91%.
L'indice
Un file di log ottiene un LogSummary. Tutto attraverso l'intero corpus passa per un indice SQLite: analisi, contesto di scena allegato, righe di fatto scritte, una transazione per file, rilettura solo dei file la cui dimensione o ora di modifica è cambiata. 3,84 milioni di righe indicizzate in circa venti secondi in circa 19 MB.
L'indice è una cache usa e getta e mai una fonte di verità. Modifiche allo schema o al parser aumentano una versione, e il file viene eliminato e ricostruito piuttosto che migrato. Niente in esso non può essere rigenerato dai log, quindi niente in esso vale il rischio di un bug di migrazione.
Due cose a riguardo che hanno richiesto un corpus per essere apprese.
Il parser è senza stato per riga, quindi solo una riga di cambio zona sa dove è successo qualcosa. Un tracker aggancia l'ultima scena entrata e si resetta all'inizio di una sessione. Circa un quarto degli eventi reali avviene prima di qualsiasi riga Entering — finiscono in una scena (unknown), che è un secchio reale che i report devono mostrare, non una lacuna da filtrare via.
Il combattimento ha una direzione. Un quarto delle righe di attacco nel corpus sono mob che colpiscono il giocatore, e le loro abilità sembrano esattamente quelle del giocatore. Senza dividere per direzione, "le tue abilità" elenca abilità che il giocatore non ha mai usato.
Tredici report
La barra li raggruppa. Ognuno si carica pigramente alla prima apertura e si ricarica quando cambia il filtro di data, scena o personaggio; tutto esporta in CSV.
Panoramica e Log browser
Cosa copre l'indice, e ogni riga di un singolo log come l'ha vista il parser. Il browser esiste per la regola di copertura di cui sopra — filtra su Non riconosciuti e stai guardando i punti ciechi rimanenti del parser, in ordine.
Combattimento — Abilità vs mob
Come si comporta ogni abilità contro ogni bersaglio, e dove un abbinamento supera ciò che il resto dei dati prevede. 65 abilità che incrociano 282 bersagli è una tabella a due vie, e la cella interessante è quella che batte sia la sua riga che la sua colonna. Tre scelte, ognuna delle quali era sbagliata all'inizio:
Polish mediano, non medie. Con le medie, una cella eccezionale trascina su la propria riga di abilità e la propria colonna di bersaglio, quindi ogni vicino viene letto come resistente. Un risultato reale, sei inventati.
Non ponderato. Ponderare il mediano permette a qualsiasi cella che detiene più della metà delle osservazioni della sua riga di definire la propria linea di base — che è precisamente l'abbinamento più coltivato che vuoi misurare.
Una soglia di dispersione oltre a una soglia di campione. Un'abilità usata contro solo due bersagli non ha una linea di base indipendente, quindi il divario tra le sue due celle viene letto come un'enorme interazione. Contro il corpus reale questa singola soglia è la differenza tra un risultato difendibile e otto artefatti.
Combattimento — Cosa ti colpisce

La domanda speculare, e il report più recente: quali creature ti attaccano, con cosa, per quanto, e quanto spesso le tue difese lo fermano. È enfaticamente non il report precedente con la freccia invertita — riutilizzare il meccanismo in uscita sarebbe stato sbagliato in quattro modi, ognuno dei quali produce un numero plausibile piuttosto che un fallimento visibile.
Più della metà del fuoco in arrivo colpisce il pet.
tentativi | |
|---|---|
mirati al giocatore | 51.138 |
mirati al pet | 64.248 |
E si comportano in modo completamente diverso: il 52% dei colpi mirati al giocatore connette senza fare nulla, contro lo 0,5% dei colpi mirati a un pet. Uniti, il profilo difensivo non appartiene a nessuno dei due. I pet sono esclusi — e la loro quota riportata, perché "questo copre il 44% di ciò che è stato lanciato contro di te" è qualcosa che un lettore merita.
La cifra ovvia di mitigazione omette la maggior parte della mitigazione. La formula del report in uscita conta schivate, blocchi, parate e colpi di striscio, e arriva al 18% in entrata. Ma il 52% degli attacchi in arrivo sono connessi, senza fare nulla — esclusi da quella formula. La cifra onesta è 66,2%. Nel frattempo, blocchi e resistenze sono assenti dalle righe in arrivo del tutto — zero di ciascuno in 3,84 milioni di righe — quindi quelle colonne sono omesse piuttosto che mostrate come zeri strutturali, perché una colonna che è sempre zero viene letta come "non hai mai bloccato nulla".
Una schivata non nomina mai cosa è stato schivato. Tutte le 7.120 schivate in arrivo e tutte le 17.474 in uscita finiscono nel secchio senza nome qualunque cosa le abbia provocate. Quindi ogni tasso per abilità divide per gli attacchi che hanno nominato un'abilità, e il tasso di schivata vive nel roll-up per creatura dove è vero.
E la classifica è per danno per colpo, perché i tre ordinamenti plausibili concordano a malapena:
tentativi | per colpo | per colpo andato a segno | passa attraverso | |
|---|---|---|---|---|
Coccodrillo Massiccio, base | 4.310 | 2,1 | 58 | 4% |
Razorback (T18), base | 217 | 23,4 | 461,5 | 5% |
Vigorem Cavas (T14), Shadow Blast | 309 | 247,9 | 247,9 | 100% |
Classifica per frequenza e il report si apre su un coccodrillo che fa due danni. Classifica per danno per colpo andato a segno e si apre su un evento che accade una volta su venti. Solo il per-colpo piega il tasso di connessione e risponde quanto mi costerà questo.
Combattimento — Record

Primati personali: critico più grande per abilità, colpo più duro subito, ognuno rintracciabile alla riga da cui proviene. Questo è l'unico report che deve annullare un roll-up da cui dipende il resto dell'app. Il danno del pet è accreditato al proprietario, il che è giusto per i totali e sbagliato per un record:
giocatore | pet | |
|---|---|---|
critico più grande | 1.843 (Chain Lightning) | 6.735 (Wyvern Sting) |
colpo più duro subito | 1.206 | 2.628 |
Più colpi atterrano sul pet che sul giocatore — 64.245 contro 44.329 — quindi "il colpo più duro che hai subito" è un livido di qualcun altro a meno che non controlli. I primati sono per personaggio e mai uniti, i pareggi vanno al più antico, e il danno nel tempo è escluso: il più grande di quelli nel corpus è 13.555, che batte ogni attacco, e includerlo silenziosamente risponde a una domanda diversa.
Mondo — Attività di scena
Dove è andato il tempo, e a cosa serviva ogni luogo. Tre cose che deve fare bene:
Un tasso ha bisogno di un denominatore di cui ti puoi fidare. Tre minuti ad Arlia hanno raccolto un premio da 10.000 XP — 206.897 all'ora, secondo posto davanti a un punto coltivato per ottanta ore. La cifra per scena è comunque mostrata, accanto ai minuti da cui proviene, ma le classifiche applicano un minimo di 30 minuti e dicono quante scene sono state escluse.
Uccisioni e morti sono le stesse righe lette da estremità opposte. 281 righe di morte sono 246 uccisioni, 22 morti, 15 astanti e 2 auto-uccisioni. Contare le righe riporta un quinto di uccisioni in più di quante ne siano state fatte e nasconde ogni morte.
Il bottino dei cadaveri è combattimento; la raccolta è raccolta. Tanglemire registra 743 attacchi, 1.305 raccolte e nessun bottino da cadavere. Un unico secchio di bottino combinato lo etichetta in base a quale totale vince, quindi un punto di pesca con lupi dentro esce come zona di combattimento.
Mondo — Bottino e Pesca
Da dove provenivano i drop e cosa produce effettivamente ogni luogo; ogni cattura ruotata per dove hai pescato, per l'acqua da cui proveniva e per specie.
Artigianato — Ricette
Tassi eccezionali per ricetta, quanto può essere spinto un capolavoro e quanto è costato. Gli intervalli sono l'intervallo di punteggio di Wilson, non l'approssimazione normale — che mette il limite superiore sopra 1 a sette successi su otto e collassa a un punto a zero su dodici. Altri tre:
Un tentativo è una creazione. Le due righe di completamento sono alternative, mai entrambe. Il corpus rivela l'errore immediatamente: Dark Red Dye registra 73.231 ordinarie e 73.433 eccezionali, quindi trattare le eccezionali come un sottoinsieme dei tentativi produce un tasso di successo sopra il 100%.
Un fallimento di capolavoro nomina l'oggetto un gradino sotto dove è stato fatto il tentativo. Totalizzare per il numero stampato inventa una curva liscia dal nulla.
Significatività e dimensione dell'effetto sono quantità separate. L'intervallo decide se una ricetta differisce davvero dal tasso complessivo; il tasso osservato decide se differisce abbastanza da essere menzionato. Confonderli ha segnalato una delle tre ricette alimentari raggruppate vicino al 45% e ha lasciato i suoi due vicini non marcati.
Altro — Progressione
Esperienza guadagnata e abilità addestrate. Le fette tranquille sono mantenute — una serie costruita solo dai giorni in cui è successo qualcosa disegna un mese come una corsa ininterrotta, l'esatto opposto di ciò che il lettore l'ha aperta per scoprire.
E i passi non sono livelli. Il gioco non annuncia ogni livello: Tailoring va 44, 48, 51, 54, quindi 85 annunci coprono 117 livelli. Il report mostra i passi e l'intervallo osservato, e segna le righe dove sono passati più livelli di quanti ne siano stati annunciati. "Livelli guadagnati" semplicemente non è nel log, e il report lo dice piuttosto che indovinare.
La trappola correlata, a livello di corpus: le letture di esperienza sono totali correnti, e ce ne sono quattro diverse per pool — guadagnata a vita, il pool del personaggio, il pool condiviso e la loro somma, scritti insieme come un blocco. Le letture sommano a 1,57 trilioni contro 187 milioni effettivamente assegnati. Gli assegnamenti sono selezionati positivamente per tipo, mai come "qualsiasi cosa che non sia una lettura", perché quella frase ammette silenziosamente ogni tipo di lettura aggiunto in seguito.
Altro — Conversazioni
Il flusso di chat piatto riannodato in scambi. Non c'è alcun marcatore di conversazione nel log, quindi una corsa viene divisa ovunque la conversazione si sia fermata per dieci minuti. Due regole si guadagnano il loro posto: una corsa con nessuno dentro tranne il giocatore non è una conversazione (altrimenti una sessione passata a fare pubblicità su Traders riempie il report di "scambi" unilaterali), e un messaggio senza timestamp mantiene la sua posizione nel file (ordinare i nulli all'inizio apre un vuoto largo quanto l'intera conversazione).
"Io" è risolto per riga contro il personaggio del log stesso — un corpus con sei personaggi ha sei risposte a chi sono io.
Altro — Economia
Per lo più notevole per ciò che rifiuta di calcolare. Il log non ha prezzi né righe di acquisto, quindi le unità vendute sono conoscibili e le entrate no. L'unica cifra in oro ovunque è You picked up N gold., che non ha nulla a che fare con il tuo venditore. Il report lo dice, perché un numero in oro stampato accanto a una tabella di vendite verrà letto come incasso.
Ciò che invece mette in superficie è la divisione degli ordini permanenti — ordine evaso contro sfogliato — che è l'unica cosa nei dati su cui un venditore può agire, e che è uscita nettamente divisa nel corpus: ogni materia prima 100% ordini, ogni bene raffinato 100% sfogliato.
Altro — Scambi

Scambi tra giocatori ripiegati insieme. Uno scambio è una corsa di righe — aperto, cose messe su e riprese, chiuso — e nessuna singola riga dice cosa è cambiato di mano. Quattro cose:
L'oro è un totale corrente, non un cambiamento. La riga afferma la nuova cifra. Un vero scambio nel corpus porta l'oro a 99.000 e di nuovo a 0 prima di completarsi; sommare le righe riporta novantanovemila oro che non si è mai mosso.
I due lati sono registrati in modo asimmetrico. Il gioco registra il partner che aggiunge e rimuove oggetti, ma solo il giocatore che aggiunge — mai che ritira. Quindi il lato del giocatore è "cosa è stato offerto" e può sovrastimare; il lato del partner è esatto. Il report dice quale è quale.
La maggior parte degli "scambi" sono con te stesso. 64 dei 106 scambi completati sono tra gli alt del giocatore stesso, e dove i log di entrambi gli alt sono presenti lo stesso scambio è memorizzato due volte, una per lato. Segnalato e filtrabile.
Il nome del partner è a volte storpiato dal gioco —
Zealoty,,1]Zealoty. Questo è nel log, non qualcosa che fa il parser. La riparazione corrisponde solo a quella forma raddoppiata esatta, perché i nomi reali contengono virgole.
Il sito companion
L'app può opzionalmente accedere a un sito web companion e pubblicare quattro set di dati: primati personali, catture di pesca, celle abilità-vs-bersaglio e abilità dei mostri.
Gli ultimi due sono diversi dai primi due in un modo che va rispettato. Sono totali cumulativi, quindi una ripubblicazione sostituisce piuttosto che accumulare — il che significa che la pubblicazione deve sempre essere non filtrata per data e scena, perché sotto la semantica di sostituzione una fetta filtrata non invia cifre più deboli, elimina quelle più complete. E un personaggio sopra il limite di celle del server è saltato interamente piuttosto che troncato, per lo stesso motivo.
Ciò che sale sono le statistiche sufficienti — conteggio, Σln(1+danno), Σln(1+danno)² — piuttosto che il risultato adattato, perché il polish mediano non si unisce tra giocatori e le somme sì. Sono additive, il che è ciò che rende possibile il pooling comunitario esatto e il leave-one-out a tempo costante. (Il 1 + è portante: l'inverso è exp(x) − 1, e rileggerli con exp semplice è sotto l'uno percento a qualche centinaio di danni e un terzo sotto a tre. Plausibile ovunque e sbagliato ovunque. È così che è stata spedita la prima implementazione del sito.)
Una cosa che anche qui il corpus ha insegnato. Un'abilità è in gran parte una proprietà della sua creatura — 22 delle 74 abilità appartengono a esattamente una, e 169 delle 272 creature ne hanno due o meno. Quindi non c'è un modello a due vie da adattare; ciò che lo sostituisce confronta un'abilità con se stessa solo dove tre o più creature la usano, leave-one-out, così la creatura che detiene la maggior parte delle osservazioni di un'abilità non può definire la propria linea di base e riportarsi come ordinaria. Earth Elemental detiene 2.955 dei 3.637 colpi di Earthquake e esce a 0,08×; un pool auto-inclusivo avrebbe letto circa 1,0 e non avrebbe detto nulla.
L'account è opzionale e resta opzionale. Ripristinare una sessione legge un file e non fa alcuna richiesta. Il primo pacchetto lascia la macchina quando clicchi su Accedi o Pubblica, mai prima. Nessun report dipende dall'essere connessi, e i controlli di pubblicazione sono nascosti quando sei disconnesso piuttosto che mostrati disabilitati.
Privacy
I log di chat contengono messaggi di altri giocatori, e questo fatto vincola il codice piuttosto che essere menzionato in una policy.
L'indice memorizza il testo grezzo dei messaggi — quello è il report delle conversazioni. Vive nella tua directory dei dati dell'app, fuori dal repository, e nulla da esso viene mai caricato. Nessun payload futuro dovrebbe cambiarlo senza chiedere all'utente in parole povere.
Ciò che la pubblicazione invia sono nomi di personaggi, nomi di abilità e creature, cifre, scene e tempi. Uno di questi merita attenzione: il log non dice mai se un attaccante era una creatura o un altro giocatore, quindi un nome di attaccante può essere una persona reale. Ecco perché la pubblicazione mostra le righe effettive una volta per set di dati prima del primo caricamento piuttosto che solo contarli. Il caricamento è rivolto verso l'esterno e non può essere annullato da qui.
I log reali sono git-ignored; i fixture di test sono redatti a mano.
Dove si trova
Funzionante da cima a fondo. Tredici report, nessun segnaposto rimasto nella barra, 522 test, sei target di rilascio. Il parser ha il 99,91% del corpus e il restante 0,09% è visibile nell'app piuttosto che spazzato via.
Se c'è un filo che attraversa tutto, è che il corpus aveva ragione e il ragionamento aveva torto, ancora e ancora. Ogni titolo sopra che inizia con "tre cose" è un elenco di numeri che sembravano corretti finché qualcuno non li ha controllati contro tre milioni di righe di ciò che è realmente accaduto. Questo è l'intero metodo: controlla il modello contro il corpus piuttosto che ragionare su ciò che il gioco probabilmente scrive.
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 · 10 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 · 8 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 · 9 downloadssha256 9e8ba3948b49a650859eb28859cc8aec104ae98db27fce708470e37454537266
