← Back to blog

SOTA Log Parser v0.0.4 - Prêt à télécharger !

Traduit automatiquement de l'anglais. Voir l'original

By admin · 7/31/2026

Ce que les journaux savaient déjà

Une visite de sotalogparser, et des mauvaises réponses qui l'ont façonné.

Shroud of the Avatar écrit tout. Chaque coup, chaque prise, chaque chef-d'œuvre raté, chaque mot prononcé près de vous, horodaté, en texte brut, dans un dossier que vous possédez déjà. Un joueur de deux ans est assis sur quelques millions de lignes de cela.

Presque personne ne les lit, car un journal de discussion n'est pas un enregistrement — c'est la matière première pour en créer un. C'est une application qui fait la lecture : une application de bureau multiplateforme qui analyse ce dossier en un index interrogeable et en tire treize rapports.

Les règles ont été dérivées à partir d'un corpus réel de 3,84 millions de lignes et en reconnaissent 99,91 %. Ce corpus est la raison pour laquelle les parties intéressantes de cet article existent. Chaque décision non évidente ci-dessous était d'abord une réponse plausible, et le corpus est ce qui a prouvé qu'elle était fausse.


La forme de la chose

Trois couches, strictement unidirectionnelles.

SotaLogParser.Core

Analyse, découverte, indexation, rapports. Aucune dépendance à l'interface utilisateur.

SotaLogParser.App

Vues et modèles de vue Avalonia.

SotaLogParser.Desktop

Point d'entrée uniquement.

.NET 10, Avalonia 12, MVVM. Une seule base de code produit des builds autonomes en un seul fichier pour six environnements d'exécution — Windows, macOS et Linux, x64 et arm64 chacun. Tout ce qui vaut un test vit dans Core, c'est pourquoi il y en a 522 et qu'aucun ne nécessite une fenêtre.

Le pipeline

LogLineReader divise [horodatage] message et replie les lignes de continuation. ChatLogParser exécute une liste ordonnée de règles, la première correspondance gagne. Ce que rien ne revendique devient un UnrecognizedEvent.

Cette dernière partie est une règle, pas un repli. Ne jamais perdre une ligne. Le compartiment non reconnu est le seul mécanisme par lequel une lacune dans l'ensemble de règles est visible du tout — jeter silencieusement ce qui ne correspond pas cacherait exactement l'information nécessaire pour la corriger. L'application affiche le pourcentage de couverture et vous permet de filtrer un journal jusqu'aux seules lignes non réclamées, c'est ainsi que 99,91 % est devenu 99,91 %.

L'index

Un fichier journal obtient un LogSummary. Tout ce qui traverse l'ensemble du corpus passe par un index SQLite : analyse, attachement du contexte de scène, écriture de lignes de faits, une transaction par fichier, relecture uniquement des fichiers dont la taille ou l'heure de modification a changé. 3,84 M de lignes indexées en environ vingt secondes dans environ 19 Mo.

L'index est un cache jetable et jamais une source de vérité. Les changements de schéma ou d'analyseur incrémentent une version, et le fichier est supprimé et reconstruit plutôt que migré. Rien dedans ne peut être régénéré à partir des journaux, donc rien dedans ne vaut le risque d'un bug de migration.

Deux choses à son sujet qui ont nécessité un corpus pour être apprises.

L'analyseur est sans état par ligne, donc seule une ligne de changement de zone sait où quelque chose s'est passé. Un suiveur verrouille la dernière scène entrée et se réinitialise au début d'une session. Environ un quart des événements réels se produisent avant toute ligne Entering — ils atterrissent dans une scène (inconnue), qui est un vrai compartiment que les rapports doivent montrer, pas une lacune à filtrer.

Le combat a une direction. Un quart des lignes d'attaque dans le corpus sont des monstres frappant le joueur, et leurs capacités ressemblent exactement à celles du joueur. Sans diviser par direction, « vos compétences » liste des compétences que le joueur n'a jamais utilisées.


Treize rapports

Le rail les regroupe. Chacun se charge paresseusement à la première ouverture et se recharge lorsque le filtre de date, de scène ou de personnage change ; tout s'exporte en CSV.

Aperçu et Navigateur de journal

Ce que couvre l'index, et chaque ligne d'un seul journal telle que l'analyseur l'a vue. Le navigateur existe pour la règle de couverture ci-dessus — filtrez sur Non reconnu et vous regardez les angles morts restants de l'analyseur, dans l'ordre.

Combat — Compétences vs monstres

Comment chaque compétence performe contre chaque cible, et où une paire bat ce que le reste des données prédit. 65 compétences croisant 282 cibles est un tableau à deux entrées, et la cellule intéressante est celle qui bat à la fois sa ligne et sa colonne. Trois choix, chacun d'abord faux :

  • Polissage médian, pas les moyennes. Avec les moyennes, une cellule exceptionnelle tire vers le haut sa propre ligne de compétence et sa colonne de cible, donc chaque voisin lit comme résistant. Une vraie découverte, six inventées.

  • Non pondéré. Pondérer la médiane permet à toute cellule détenant plus de la moitié des observations de sa ligne de définir sa propre ligne de base — ce qui est précisément la paire fortement cultivée que vous voulez le plus mesurer.

  • Une porte d'étalement en plus d'une porte d'échantillon. Une compétence utilisée contre seulement deux cibles n'a pas de ligne de base indépendante, donc l'écart entre ses deux cellules lit comme une interaction énorme. Contre le corpus réel, cette seule porte est la différence entre une découverte défendable et huit artefacts.

Combat — Ce qui vous frappe

La question miroir, et le rapport le plus récent : quelles créatures vous attaquent, avec quoi, pour combien, et à quelle fréquence vos défenses l'arrêtent. Ce n'est pas le rapport précédent avec la flèche inversée — réutiliser la machinerie sortante aurait été faux de quatre façons, chacune produisant un nombre plausible plutôt qu'un échec visible.

Plus de la moitié des tirs entrants atterrissent sur l'animal de compagnie.

tentatives

visant le joueur

51 138

visant l'animal de compagnie

64 248

Et ils ne se comportent pas du tout de la même manière : 52 % des coups visant le joueur ne connectent rien, contre 0,5 % des coups visant un animal de compagnie. Regroupés, le profil défensif n'appartient à aucun des deux. Les animaux de compagnie sont exclus — et leur part signalée, car « cela couvre 44 % de ce qui vous a été lancé » est quelque chose qu'un lecteur mérite de savoir.

Le chiffre de mitigation évident omet la majorité de la mitigation. La formule du rapport sortant compte les esquives, les blocages, les parades et les coups obliques, et arrive à 18 % entrants. Mais 52 % des attaques entrantes sont connectées, n'ont rien infligé — exclues par cette formule. Le chiffre honnête est 66,2 %. Pendant ce temps, les blocages et les résistances sont absents des lignes entrantes entièrement — zéro de chacun dans 3,84 M de lignes — donc ces colonnes sont omises plutôt que montrées comme des zéros structurels, car une colonne toujours zéro lit comme « vous n'avez jamais bloqué quoi que ce soit ».

Une esquive ne nomme jamais ce qui a été esquivé. Toutes les 7 120 esquives entrantes et les 17 474 sortantes se trouvent dans le compartiment non nommé quel que soit ce qui les a provoquées. Donc chaque taux par capacité divise par les attaques qui ont nommé une capacité, et le taux d'esquive vit sur le cumul par créature où il est vrai.

Et le classement est par dégâts par coup, car les trois ordres plausibles s'accordent à peine :

tentatives

par coup

par toucher

passe à travers

Crocodile massif, basique

4 310

2,1

58

4 %

Razorback (T18), basique

217

23,4

461,5

5 %

Vigorem Cavas (T14), Shadow Blast

309

247,9

247,9

100 %

Classez par fréquence et le rapport s'ouvre sur un crocodile faisant deux dégâts. Classez par dégâts par toucher et il s'ouvre sur un événement qui se produit une fois sur vingt. Seul le par coup intègre le taux de connexion et répond combien cela va-t-il me coûter.

Combat — Records

Records personnels : plus grand critique par compétence, coup le plus dur reçu, chacun traçable jusqu'à la ligne dont il provient. C'est le seul rapport qui doit défaire un cumul dont le reste de l'application dépend. Les dégâts de l'animal de compagnie sont crédités au propriétaire, ce qui est juste pour les totaux et faux pour un record :

joueur

animal de compagnie

plus grand critique

1 843 (Chaîne d'éclairs)

6 735 (Piqûre de wyverne)

coup le plus dur reçu

1 206

2 628

Plus de coups atterrissent sur l'animal de compagnie que sur le joueur — 64 245 contre 44 329 — donc « le coup le plus dur que vous avez reçu » est l'ecchymose de quelqu'un d'autre à moins que vous ne vérifiiez. Les records sont par personnage et jamais regroupés, les égalités vont au plus ancien, et les dégâts sur la durée sont exclus : le plus grand de ceux-ci dans le corpus est 13 555, ce qui bat chaque attaque, et l'intégrer silencieusement répond à une question différente.

Monde — Activité de scène

Où le temps est allé, et à quoi chaque lieu était bon. Trois choses qu'il doit bien faire :

  • Un taux a besoin d'un dénominateur auquel vous pouvez faire confiance. Trois minutes à Arlia ont collecté une récompense de 10 000 XP — 206 897 à l'heure, deuxième place devant un spot cultivé pendant quatre-vingts heures. Le chiffre par scène est toujours affiché, à côté des minutes dont il provient, mais les classements appliquent un plancher de 30 minutes et disent combien de scènes cela a exclu.

  • Les morts et les victoires sont les mêmes lignes lues depuis des extrémités opposées. 281 lignes de mort sont 246 victoires, 22 morts, 15 spectateurs et 2 auto-morts. Compter les lignes rapporte un cinquième de victoires en plus que ce qui a été fait et cache chaque mort.

  • Le butin de cadavre est du combat ; la récolte est de la cueillette. Tanglemire enregistre 743 attaques, 1 305 récoltes et aucun butin de cadavre du tout. Un compartiment de butin combiné l'étiquette par le total qui gagne, donc un spot de pêche avec des loups ressort comme une zone de combat.

Monde — Butin et Pêche

D'où venaient les chutes et ce que chaque lieu produit réellement ; chaque prise pivotée par où vous avez pêché, par l'eau dont elle provient, et par espèce.

Artisanat — Recettes

Taux exceptionnels par recette, jusqu'où un chef-d'œuvre peut être poussé, et ce que cela a coûté. Les intervalles sont l'intervalle de score de Wilson, pas l'approximation normale — ce qui met la borne supérieure au-dessus de 1 à sept succès sur huit et s'effondre à un point à zéro sur douze. Trois de plus :

  • Une tentative est un artisanat. Les deux lignes de complétion sont des alternatives, jamais les deux. Le corpus révèle l'erreur immédiatement : Dark Red Dye enregistre 73 231 ordinaires et 73 433 exceptionnels, donc traiter l'exceptionnel comme un sous-ensemble des tentatives donne un taux de succès supérieur à 100 %.

  • Un échec de chef-d'œuvre nomme l'objet un niveau en dessous de là où la tentative a été faite. Compter par le nombre imprimé invente une courbe lisse à partir de rien.

  • La significativité et la taille d'effet sont des quantités séparées. L'intervalle décide si une recette diffère vraiment du taux global ; le taux observé décide si elle diffère assez pour être mentionnée. Les confondre a signalé une des trois recettes alimentaires regroupées près de 45 % et a laissé ses deux voisines non marquées.

Plus — Progression

Expérience gagnée et compétences entraînées. Les tranches calmes sont conservées — une série construite uniquement à partir des jours où quelque chose s'est passé dessine un mois comme une série ininterrompue, l'exact opposé de ce que le lecteur a ouvert pour découvrir.

Et les étapes ne sont pas des niveaux. Le jeu n'annonce pas chaque niveau : Tailoring passe par 44, 48, 51, 54, donc 85 annonces couvrent 117 niveaux. Le rapport montre les étapes et la plage observée, et marque les lignes où plus de niveaux sont passés que ce qui a été annoncé. « Niveaux gagnés » n'est tout simplement pas dans le journal, et le rapport le dit plutôt que de deviner.

Le piège connexe, à l'échelle du corpus : les lectures d'expérience sont des totaux cumulés, et il y en a quatre différentes par pool — gagné à vie, le pool du personnage, le pool partagé, et leur somme, écrits ensemble comme un bloc. Les lectures totalisent 1,57 billion contre 187 millions réellement attribués. Les attributions sont sélectionnées positivement par type, jamais comme « tout ce qui n'est pas une lecture », car cette formulation admet silencieusement chaque type de lecture ajouté plus tard.

Plus — Conversations

Le flux de discussion plat retissé en échanges. Il n'y a aucun marqueur de conversation dans le journal du tout, donc une série est divisée là où la parole s'est arrêtée pendant dix minutes. Deux règles gagnent leur place : une série avec personne dedans sauf le joueur n'est pas une conversation (sinon une session passée à faire de la publicité sur Traders remplit le rapport d'« échanges » unilatéraux), et un message sans horodatage garde sa position de fichier (trier les nuls au début ouvre un écart de la largeur de toute la conversation).

« Moi » est résolu par ligne contre le propre personnage du journal — un corpus avec six personnages a six réponses à qui suis-je.

Plus — Économie

Surtout notable pour ce qu'il refuse de calculer. Le journal n'a pas de prix ni de lignes d'achat, donc les unités vendues sont connaissables et les revenus ne le sont pas. Le seul chiffre d'or n'importe où est Vous avez ramassé N or., qui n'a rien à voir avec votre vendeur. Le rapport le dit, car un nombre d'or imprimé à côté d'un tableau de ventes sera lu comme des recettes.

Ce qu'il fait ressortir, c'est la répartition des commandes permanentes — commande exécutée contre consultée — qui est la seule chose dans les données sur laquelle un vendeur peut agir, et qui est ressortie nettement divisée dans le corpus : chaque matière première 100 % commandes, chaque bien raffiné 100 % consulté.

Plus — Échanges

Les échanges joueur à joueur repliés ensemble. Un échange est une série de lignes — ouvert, des objets mis et repris, fermé — et aucune ligne unique ne dit ce qui a changé de mains. Quatre choses :

  • L'or est un total cumulé, pas un changement. La ligne énonce le nouveau chiffre. Un vrai échange dans le corpus fait passer l'or à 99 000 puis revient à 0 avant de se compléter ; additionner les lignes rapporte quatre-vingt-dix-neuf mille or qui n'ont jamais bougé.

  • Les deux côtés sont journalisés asymétriquement. Le jeu enregistre le partenaire ajoutant et retirant des objets, mais seulement le joueur ajoutant — jamais retirant. Donc le côté du joueur est « ce qui a été offert » et peut surestimer ; le côté du partenaire est exact. Le rapport dit lequel est lequel.

  • La plupart des « échanges » sont avec vous-même. 64 des 106 échanges complétés sont entre les propres alts du joueur, et là où les journaux des deux alts sont présents, le même échange est stocké deux fois, une fois de chaque côté. Signalé et filtrable.

  • Le nom du partenaire est parfois mutilé par le jeuZealoty,,1]Zealoty. Cela est dans le journal, pas quelque chose que l'analyseur fait. La réparation ne correspond qu'à cette forme doublée exacte, car les vrais noms contiennent des virgules.


Le site compagnon

L'application peut éventuellement se connecter à un site Web compagnon et publier quatre ensembles de données : records personnels, prises de pêche, cellules compétence-vs-cible, et capacités de monstres.

Les deux derniers sont différents des deux premiers d'une manière qui doit être respectée. Ce sont des totaux cumulés, donc une re-publication remplace plutôt qu'accumule — ce qui signifie que la publication doit toujours être non filtrée par date et scène, car sous la sémantique de remplacement, une tranche filtrée n'envoie pas des chiffres plus faibles, elle supprime les plus complets. Et un personnage au-dessus du plafond de cellules du serveur est sauté entièrement plutôt que tronqué, pour la même raison.

Ce qui monte, ce sont les statistiques suffisantes — compte, Σln(1+dégâts), Σln(1+dégâts)² — plutôt que le résultat ajusté, car le polissage médian ne se regroupe pas entre joueurs et les sommes le font. Elles sont additives, ce qui rend possible le regroupement communautaire exact et le leave-one-out en temps constant. (Le 1 + est porteur : l'inverse est exp(x) − 1, et les relire avec un simple exp est à moins d'un pour cent près à quelques centaines de dégâts et à un tiers près à trois. Plausible partout et faux partout. C'est ainsi que la première implémentation du site a été livrée.)

Une chose que le corpus a aussi apprise ici. Une capacité est en grande partie une propriété de sa créature — 22 des 74 capacités appartiennent à exactement une, et 169 des 272 créatures en ont deux ou moins. Donc il n'y a pas de modèle à deux voies à ajuster ; ce qui le remplace compare une capacité à elle-même uniquement là où trois créatures ou plus l'utilisent, leave-one-out, donc la créature détenant la plupart des observations d'une capacité ne peut pas définir sa propre ligne de base et se déclarer ordinaire. Earth Elemental détient 2 955 des 3 637 coups d'Earthquake et ressort à 0,08× ; un pool auto-inclus aurait lu environ 1,0 et n'aurait rien dit.

Le compte est facultatif et reste facultatif. Restaurer une session lit un fichier et ne fait aucune requête. Le premier paquet quitte la machine lorsque vous cliquez sur Se connecter ou Publier, jamais avant. Aucun rapport ne prend de dépendance à être connecté, et les contrôles de publication sont masqués lorsqu'on est déconnecté plutôt que montrés désactivés.


Confidentialité

Les journaux de discussion contiennent les messages d'autres joueurs, et ce fait contraint le code plutôt que d'être mentionné dans une politique.

L'index stocke le texte brut des messages — c'est cela le rapport des conversations. Il vit dans votre répertoire de données d'application, hors du référentiel, et rien de lui n'est jamais téléversé. Aucune charge utile future ne devrait changer cela sans demander à l'utilisateur en toutes lettres.

Ce que la publication envoie, ce sont les noms de personnages, les noms de compétences et de créatures, les chiffres, les scènes et les heures. Un de ceux-ci mérite de l'attention : le journal ne dit jamais si un attaquant était une créature ou un autre joueur, donc un nom d'attaquant peut être celui d'une vraie personne. C'est pourquoi la publication montre les lignes réelles une fois par ensemble de données avant le premier téléversement plutôt que de seulement les compter. Le téléversement est tourné vers l'extérieur et ne peut pas être annulé d'ici.

Les journaux réels sont ignorés par git ; les fixtures de test sont expurgées à la main.


Où cela en est

Fonctionne de bout en bout. Treize rapports, aucun espace réservé restant dans le rail, 522 tests, six cibles de publication. L'analyseur a 99,91 % du corpus et les 0,09 % restants sont visibles dans l'application plutôt que balayés.

S'il y a un fil conducteur à travers tout cela, c'est que le corpus avait raison et le raisonnement avait tort, encore et encore. Chaque titre ci-dessus qui commence par « trois choses » est une liste de nombres qui semblaient corrects jusqu'à ce que quelqu'un les vérifie contre trois millions de lignes de ce qui s'est réellement passé. C'est toute la méthode : vérifier le motif contre le corpus plutôt que de raisonner sur ce que le jeu écrit probablement.

Downloads