$ErrorActionPreference='Stop' $root='c:\Users\fdavalos\OneDrive - up.edu.mx\microtracking\MicrotrackingFer' $logRe='^(?:LOG:)?\[([\d\-/ :]+)\] X:(-?\d+),Y:(-?\d+),C:(\d+),V:(\d+),P:(\d+),S:(\d+),er:(\d+)$' $ftRe='^(?:LOG:)?\[([\d\-/ :]+)\] FineTune: dC=(\d+), dynE=(\d+), e=(\d+), near=(\d), Cmax=(\d+)$' function ParseLog([string]$path){ $o=@{} foreach($t in @('X','Y','C','V','P','S','E','ftDc','ftDynE','ftE','ftNear','ftCmax')){$o[$t]=New-Object 'System.Collections.Generic.List[long]'} $o.ts=New-Object 'System.Collections.Generic.List[string]' $o.ftTs=New-Object 'System.Collections.Generic.List[string]' $o.spec=@{} $o.other=New-Object 'System.Collections.Generic.List[string]' $o.posVals=@{} $o.posSamples=New-Object 'System.Collections.Generic.List[string]' $o.cloud=New-Object 'System.Collections.Generic.List[string]' $lines=[IO.File]::ReadAllLines($path) $o.total=$lines.Count $o.lines_ref=$lines[0]; $o.last_ref=$lines[$lines.Count-1] foreach($ln in $lines){ if($ln -match $logRe){ $o.ts.Add($matches[1]) $o.X.Add([long]$matches[2]); $o.Y.Add([long]$matches[3]); $o.C.Add([long]$matches[4]) $o.V.Add([long]$matches[5]); $o.P.Add([long]$matches[6]); $o.S.Add([long]$matches[7]); $o.E.Add([long]$matches[8]) } elseif($ln -match $ftRe){ $o.ftTs.Add($matches[1]) $o.ftDc.Add([long]$matches[2]); $o.ftDynE.Add([long]$matches[3]); $o.ftE.Add([long]$matches[4]); $o.ftNear.Add([long]$matches[5]); $o.ftCmax.Add([long]$matches[6]) } else { $t2=$ln.Trim() if($t2 -eq ''){ $o.spec['empty']=1+[int]$o.spec['empty'] } elseif($ln -match 'COM READY'){ $o.spec['COM READY']=1+[int]$o.spec['COM READY']; $o.cloud.Add(('COMREADY | '+$ln)) } elseif($ln -match 'WS cerrado'){ $o.spec['WS cerrado']=1+[int]$o.spec['WS cerrado']; $o.cloud.Add(('WSCLOSED | '+$ln)) } elseif($ln -match 'Desconectado'){ $o.spec['Desconectado']=1+[int]$o.spec['Desconectado']; $o.cloud.Add(('DISCON | '+$ln)) } elseif($ln -match 'Servidor'){ $o.spec['Servidor']=1+[int]$o.spec['Servidor']; $o.cloud.Add(('SERV | '+$ln)) } elseif($ln -match '^POS:(\d+):(\d+)$'){ $o.spec['POS:']=1+[int]$o.spec['POS:']; $v=$matches[1]+':'+$matches[2]; $o.posVals[$v]=1+[int]$o.posVals[$v]; if($o.posSamples.Count -lt 4){$o.posSamples.Add($ln)} } else { $o.spec['other']=1+[int]$o.spec['other']; if($o.other.Count -lt 6){ $o.other.Add($ln) } } } } return $o } #MORE1 function Analyze($o){ $n=$o.ts.Count if($n -eq 0){ Write-Host ' (sin muestras LOG)'; return } $t=@($o.ts | %{ [datetime]::Parse($_) }) Write-Host (" lineasTotales={0} LOG={1} FT={2}" -f $o.total,$n,$o.ftTs.Count) Write-Host (" ventana: {0} -> {1} (span {2} min)" -f $t[0].ToString('yyyy-MM-dd HH:mm:ss'),$t[$n-1].ToString('HH:mm:ss'),[int]($t[$n-1]-$t[0]).TotalMinutes) Write-Host (" 1a linea: "+$o.lines_ref) Write-Host (" ul linea: "+$o.last_ref) $dts=New-Object 'double[]' ($n-1) for($i=1;$i -lt $n;$i++){$dts[$i-1]=($t[$i]-$t[$i-1]).TotalSeconds} $med=$dts|Sort-Object|Select-Object -Index [int]($dts.Count/2) $g=1..($n-1) | ?{ ($t[$_] - $t[$_-1]).TotalSeconds -gt 15 } Write-Host (" dt(s): min={0} med={1} max={2} gaps>15s: {3}" -f [int]($dts|Measure-Object -Minimum).Minimum,[int]$med,[int]($dts|Measure-Object -Maximum).Maximum,$g.Count) if($g.Count -gt 0){ Write-Host (" gaps: "+(($g|select -First 10)|%{ $t[$_].ToString('HH:mm:ss')+"(+"+[int]($t[$_]-$t[$_-1]).TotalSeconds+"s)" }) -join ' | ') } $back=1..($n-1) | ?{ $o.S[$_] -lt $o.S[$_-1] } $dup=1..($n-1) | ?{ $o.S[$_] -eq $o.S[$_-1] } Write-Host (" S: {0} -> {1} ({2} u/s) S-back={3} S-dup={4}" -f $o.S[0],$o.S[$n-1],([math]::Round(($o.S[$n-1]-$o.S[0])/($t[$n-1]-$t[0]).TotalSeconds,3)),$back.Count,$dup.Count) Write-Host (" spec: "+(($o.spec.GetEnumerator() | ?{$_.Value -gt 0} | %{$_.Key+"="+$_.Value}) -join ', ')) if($o.posVals.Count -gt 0){ $top=$o.posVals.GetEnumerator()|Sort-Object Value -Descending|Select-Object -First 12 Write-Host (" POS: distintos={0} top: {1}" -f $o.posVals.Count,(($top|%{"$($_.Key)x$($_.Value)"}) -join ' ')) foreach($s in $o.posSamples){ Write-Host (" sample: "+$s) } } if($o.other.Count -gt 0){ foreach($s in $o.other){ Write-Host (" other: "+$s.Substring(0,[Math]::Min(90,$s.Length))) } } if($o.cloud.Count -gt 0){ Write-Host (" cloud ({0} eventos) 1ro: "+$o.cloud[0]) Write-Host (" cloud ultimo: "+$o.cloud[$o.cloud.Count-1]) } $runs=New-Object 'System.Collections.Generic.List[string]' $cur=$o.E[0]; $st=0 for($i=1;$i -le $n;$i++){ if($i -lt $n -and $o.E[$i] -eq $cur){ continue } $runs.Add( ("er="+$cur+": "+$t[$st].ToString('HH:mm:ss')+"->"+$t[$i-1].ToString('HH:mm:ss')+" (n="+($i-$st)+")") ) if($i -lt $n){ $cur=$o.E[$i]; $st=$i } } Write-Host (" er(t): "+($runs -join ' ')) $nPos=@{} for($i=0;$i -lt $n;$i++){$k=$o.X[$i].ToString()+':'+$o.Y[$i].ToString(); $nPos[$k]=1+[int]$nPos[$k]} $fm=(1..($n-1) | ?{ $o.X[$_] -ne $o.X[0] -or $o.Y[$_] -ne $o.Y[0] } | select -First 1) $fmS=if($null -ne $fm){ $t[$fm].ToString('HH:mm:ss') } else { 'nunca' } Write-Host (" X: {0}..{1} Y: {2}..{3} pos.distintas={4} 1er.mov={5}" -f ($o.X|Measure-Object -Minimum).Minimum,($o.X|Measure-Object -Maximum).Maximum,($o.Y|Measure-Object -Minimum).Minimum,($o.Y|Measure-Object -Maximum).Maximum,$nPos.Count,$fmS) $topPos=$nPos.GetEnumerator()|Sort-Object Value -Descending|Select-Object -First 5 Write-Host (" pos.mas estacionadas: "+(($topPos|%{"$($_.Key) x$($_.Value)"}) -join ' ')) $idx=@(0,[int]($n/4),[int]($n/2),[int](3*$n/4),($n-1)) Write-Host ' checkpoints (hora | X:Y | C | V | P | er):' foreach($i in $idx){ Write-Host (" "+$t[$i].ToString('HH:mm:ss')+" | "+$o.X[$i]+":"+$o.Y[$i]+" | C="+$o.C[$i]+" V="+$o.V[$i]+" P="+$o.P[$i]+" er="+$o.E[$i]) } Write-Host (" C: min={0} max={1} mean={2} P max={3}" -f ($o.C|Measure-Object -Minimum).Minimum,($o.C|Measure-Object -Maximum).Maximum,[int]($o.C|Measure-Object -Average).Average,($o.P|Measure-Object -Maximum).Maximum) $drop=1..($n-1) | ?{ ($o.C[$_] - $o.C[$_-1]) -lt -10000 } Write-Host (" saltos grandes C (>10k uA): "+$drop.Count) if($drop.Count -gt 0){ $drop | Sort-Object { $o.C[$_] - $o.C[$_-1] } | select -First 6 | %{ Write-Host (" "+$t[$_].ToString('HH:mm:ss')+" C "+$o.C[$_-1]+" -> "+$o.C[$_]+" (d="+($o.C[$_]-$o.C[$_-1])+")") } } $m=$o.ftTs.Count if($m -gt 0){ $near0=(0..($m-1) | ?{ $o.ftNear[$_] -eq 0 }).Count Write-Host (" FT: near=0 en {0}/{1} ({2}%) dC max={3} dynE: {4}..{5} e top: {6}" -f $near0,$m,[math]::Round(100*$near0/$m,1),($o.ftDc|Measure-Object -Maximum).Maximum,($o.ftDynE|Measure-Object -Minimum).Minimum,($o.ftDynE|Measure-Object -Maximum).Maximum,((($o.ftE|Group-Object|Sort-Object {$_.Count} -Descending|select -First 6)|%{"$($_.Name)x$($_.Count)"}) -join ', ')) } } #MORE2 $files=@('full_log_21082025.txt','log(3).txt','gyuggyhoy.txt') $logs=@{} foreach($f in $files){ Write-Host ("########## $f ##########") $o=ParseLog (Join-Path $root $f) $logs[$f]=$o Analyze $o Write-Host '' } Write-Host '########## CROSS-CHECK log(3) vs gyuggyhoy (ambos 14/09) ##########' $a=$logs['log(3).txt']; $b=$logs['gyuggyhoy.txt'] $da=@{}; for($i=0;$i -lt $a.ts.Count;$i++){$da[$a.ts[$i]]=@($a.X[$i],$a.Y[$i],$a.C[$i])} $db=@{}; for($i=0;$i -lt $b.ts.Count;$i++){$db[$b.ts[$i]]=@($b.X[$i],$b.Y[$i],$b.C[$i])} $common=@($da.Keys | ?{ $db.ContainsKey($_) } | Sort-Object) Write-Host (" log(3): "+$a.ts[0]+" -> "+$a.ts[$a.ts.Count-1]) Write-Host (" gyuggyhoy: "+$b.ts[0]+" -> "+$b.ts[$b.ts.Count-1]) if($common.Count -gt 0){ Write-Host (" ventana comun: "+$common.Count+" ts ("+$common[0]+" -> "+$common[$common.Count-1]+")") $xm=0; $cm=0; $samps=@() foreach($ts in $common){ if($da[$ts][0] -ne $db[$ts][0] -or $da[$ts][1] -ne $db[$ts][1]){$xm++} if($da[$ts][2] -ne $db[$ts][2]){$cm++; if($samps.Count -lt 5){ $samps.Add(("$ts log3 X/Y="+$da[$ts][0]+":"+$da[$ts][1]+" C="+$da[$ts][2]+" | guggy X/Y="+$db[$ts][0]+":"+$db[$ts][1]+" C="+$db[$ts][2])) } } } Write-Host (" mismatches en ventana comun: X/Y="+$xm+" C="+$cm) foreach($s in $samps){ Write-Host (" "+$s) } } else { Write-Host ' ventana comun: vacia' } Write-Host (" boot estimado log(3): "+([datetime]::Parse($a.ts[0]).AddSeconds(-[long]$a.S[0])).ToString('HH:mm:ss')+" (S0="+$a.S[0]+" @ "+$a.ts[0]+")") Write-Host (" boot estimado gyuggyhoy: "+([datetime]::Parse($b.ts[0]).AddSeconds(-[long]$b.S[0])).ToString('HH:mm:ss')+" (S0="+$b.S[0]+" @ "+$b.ts[0]+")") Write-Host '########## FIN ##########'