Docs/Migration : architecture initiale (pipeline donnees -> GI -> evenements/personnages), audit logiciel 5.5, plan de tests, cahier des charges par lots bornes, journal des modifications, registre des erreurs. Tools : CheckIntegrity (T-STAT-02..04), LogStats (compteurs normalises, A/B 4.27/5.5). Empreinte de reference de l'arbre 4.27. Tests : aller-retour Snapshot/Restore verifie par MD5 ; T-STAT-02, 03, 04 au vert ; T-STAT-01 : 1 package UE4 (GI.uasset), traite en L1. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
76 lines
4 KiB
PowerShell
76 lines
4 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
Compteurs normalises d'un journal LifePlay, ou comparaison A/B de deux journaux.
|
|
|
|
.DESCRIPTION
|
|
Reconnait les messages anglais (4.27) et francais (editeur 5.5 localise).
|
|
Normalise par le nombre de personnages generes (lignes "index SPAWN"),
|
|
selon le protocole du rapport du 2026-09-28 (paragraphe 8).
|
|
|
|
.EXAMPLE
|
|
.\Tools\LogStats.ps1 Saved\Logs\LifePlay.log
|
|
.\Tools\LogStats.ps1 -Compare D:\Game\LifePlay_Build_427_Dev\WindowsNoEditor\LifePlay\Saved\Logs\LifePlay.log, Saved\Logs\LifePlay.log
|
|
#>
|
|
param(
|
|
[Parameter(Position = 0)][string]$Log,
|
|
[string[]]$Compare,
|
|
[int]$Top = 15
|
|
)
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
$reNone = 'Accessed None trying to read property (\w+)|Acc[eè]s [aà] None, tentative de lecture de la propri[eé]t[eé] (\w+)'
|
|
|
|
function Get-LogStats([string]$Path) {
|
|
$lines = [IO.File]::ReadAllLines((Resolve-Path $Path))
|
|
$spawnLines = $lines -match 'index SPAWN'
|
|
$spawnActors = $spawnLines | ForEach-Object { if ($_ -match '\] (Person_C_\d+) index SPAWN') { $Matches[1] } } | Sort-Object -Unique
|
|
$noneProps = foreach ($l in $lines) { if ($l -match $reNone) { if ($Matches[1]) { $Matches[1] } else { $Matches[2] } } }
|
|
$noneMesh = @($noneProps | Where-Object { $_ -match 'mesh' }).Count
|
|
$files = @{}
|
|
foreach ($l in ($lines -match "GetAllFilesFromFolder \| '([^']+)' ext='([^']+)' -> (\d+)")) {
|
|
if ($l -match "GetAllFilesFromFolder \| '([^']+)' ext='([^']+)' -> (\d+)") { $files["$($Matches[1]) $($Matches[2])"] = [int]$Matches[3] }
|
|
}
|
|
$n = [math]::Max(1, $spawnLines.Count)
|
|
[pscustomobject]@{
|
|
Fichier = $Path
|
|
Lignes = $lines.Count
|
|
Personnages = $spawnLines.Count
|
|
ActeursDistincts = @($spawnActors).Count
|
|
AccessedNone = @($noneProps).Count
|
|
AccessedNoneMaillage = $noneMesh
|
|
NoneMaillageParPerso = [math]::Round($noneMesh / $n, 2)
|
|
NoSkeletalMesh = @($lines -match 'No SkeletalMesh').Count
|
|
IndexHorsBornes = @($lines -match 'Attempted to access index|Tentative d.acc[eè]s [aà] l.index|from array .* of length').Count
|
|
LoadTxtOK = @($lines -match 'LoadTxt OK').Count
|
|
LoadTxtEchec = @($lines -match 'LoadTxt (ECHEC|FAIL)').Count
|
|
LogClassError = @($lines -match 'LogClass: Error').Count
|
|
FailedToLoad = @($lines -match "Failed to load '/Game/").Count
|
|
Fatal = @($lines -match 'Fatal error|LogWindows: Error: ===').Count
|
|
Erreurs = @($lines -match ': Error: ').Count
|
|
Avertissements = @($lines -match ': Warning: ').Count
|
|
LogLifePlay = @($lines -match 'LogLifePlay').Count
|
|
TraceModding = @($lines -match 'LogLPModdingTrace').Count
|
|
_Proprietes = $noneProps | Group-Object | Sort-Object Count -Descending | Select-Object -First $Top Count, Name
|
|
_Fichiers = $files
|
|
}
|
|
}
|
|
|
|
function Show([object]$s) {
|
|
$s | Select-Object * -ExcludeProperty _* | Format-List
|
|
"Acces a None par propriete ($Top premieres) :"
|
|
$s._Proprietes | Format-Table -AutoSize
|
|
}
|
|
|
|
if ($Compare) {
|
|
if ($Compare.Count -ne 2) { throw '-Compare attend exactement deux journaux : reference, cible' }
|
|
$a = Get-LogStats $Compare[0]; $b = Get-LogStats $Compare[1]
|
|
$props = ($a | Select-Object * -ExcludeProperty _*, Fichier).PSObject.Properties.Name
|
|
"A = $($Compare[0])`nB = $($Compare[1])`n"
|
|
$props | ForEach-Object { [pscustomobject]@{ Mesure = $_; A = $a.$_; B = $b.$_ } } | Format-Table -AutoSize
|
|
"Fichiers enumeres (GetAllFilesFromFolder) qui different :"
|
|
$keys = @($a._Fichiers.Keys) + @($b._Fichiers.Keys) | Sort-Object -Unique
|
|
$diff = $keys | Where-Object { $a._Fichiers[$_] -ne $b._Fichiers[$_] } | ForEach-Object { [pscustomobject]@{ Dossier = $_; A = $a._Fichiers[$_]; B = $b._Fichiers[$_] } }
|
|
if ($diff) { $diff | Format-Table -AutoSize } else { " aucun ($($keys.Count) enumerations identiques)" }
|
|
} elseif ($Log) {
|
|
Show (Get-LogStats $Log)
|
|
} else { throw 'Indiquer un journal, ou -Compare reference,cible' }
|