<?php
// =================================================================
// CONFIGURACIÓN DEL BENCHMARK
// =================================================================
define ( 'NUM_BUSQUEDAS' , 500000 ) ; // Iteraciones para probar la velocidad de acceso
echo "<h1>Benchmark Final y Completo para Archmage</h1>" ;
echo "<p>Simulando la estructura de datos real, incluyendo la lista completa de habilidades.</p>" ;
// --- Función para generar los datos de prueba ---
function generarDatos( ) {
$datos = [ ] ;
// --- Listas de datos para generar variedad ---
$razas = [ 'elemental' , 'humano' , 'demonio' , 'no-muerto' , 'bestia' , 'angel' ] ;
$tipos_ataque_normal = [ 'magic' , 'melee' , 'poison' , 'cold' ] ;
$tipos_ataque_extra = [ 'ranged lighting' , 'fire breath' , 'holy strike' , 'psychic blast' ] ;
// ✨ LISTA COMPLETA DE HABILIDADES EXTRAÍDA DEL HTML
$lista_habilidades_posibles = [
'FLYING' , 'ADDITIONAL STRIKE' , 'SWIFT' , 'LARGE SHIELD' , 'PIKE' , 'REGENERATION' ,
'ENDURANCE' , 'SIEGE' , 'BEAUTY' , 'STEAL LIFE' , 'MARKSMANSHIP' , 'SCALES' , 'FEAR' ,
'HEALING' , 'CHARM' , 'BURSTING FLAME' , 'CLUMSINESS' , 'ACCURACY' , 'RECRUIT SPEED' ,
'WEAKNESS TO' , 'INITIATIVE' , 'ATTACK' , 'COUNTERATTACK' , 'HITPOINT' , 'ATTACKTYPE' ,
'PREVENT DAMAGE' , 'DESTROY' , 'RESURRECT' , 'SPELL IMMUNITY' , 'SLEEP' , 'ATTDEF AGAINST' ,
'ATTACK RESISTANCE' , 'SPELL RESISTANCE' , 'DAMAGE SELF'
] ;
$tipos_resistencia_ataque = [
'Missile' , 'Magic' , 'Cold' , 'Fire' , 'Melee' , 'Paralyze' ,
'Poison' , 'Ranged' , 'Psychic' , 'Breath' , 'Lightning' , 'Holy'
] ;
for ( $i = 1 ; $i <= NUM_ELEMENTOS; $i ++ ) {
$id = 1000 + $i ;
// --- Asignación de habilidades (de 1 a 3 por unidad) ---
$habilidades_asignadas = [ ] ;
$num_habilidades_a_asignar = rand ( 1 , 3 ) ; $keys_habilidades_aleatorias = array_rand ( $lista_habilidades_posibles , $num_habilidades_a_asignar ) ; if ( is_array ( $keys_habilidades_aleatorias ) ) { foreach ( $keys_habilidades_aleatorias as $key ) {
$habilidades_asignadas [ ] = $lista_habilidades_posibles [ $key ] ;
}
} else {
$habilidades_asignadas [ ] = $lista_habilidades_posibles [ $keys_habilidades_aleatorias ] ;
}
// --- Creación de resistencias a ataques ---
$resistencias_ataque = [ ] ;
foreach ( $tipos_resistencia_ataque as $tipo ) {
$resistencias_ataque [ $tipo ] = rand ( 0 , 100 ) ; }
$datos [ $id ] = [
'id' => $id ,
'nombre' => "Unidad de prueba #$i " ,
'poder' => rand ( 20000 , 50000 ) , 'hp' => rand ( 50000 , 80000 ) , 'imagen_url' => "https://w...content-available-to-author-only...d.cl/i/units/" . rand ( 1 , 200 ) . ".jpg" ,
'poder_ataque' => rand ( 80000 , 120000 ) , 'tipo_ataque' => $tipos_ataque_normal [ array_rand ( $tipos_ataque_normal ) ] , 'poder_ataque_extra' => rand ( 250000 , 350000 ) , 'tipo_ataque_extra' => $tipos_ataque_extra [ array_rand ( $tipos_ataque_extra ) ] ,
'iniciativa' => rand ( 1 , 5 ) , 'iniciativa_extra' => rand ( 1 , 5 ) , 'contra_ataque' => rand ( 6000 , 8000 ) ,
'mant_oro' => rand ( 0 , 50 ) , 'mant_gente' => rand ( 0 , 10 ) , 'mant_mana' => rand ( 80 , 150 ) ,
'resistencia_ataques' => $resistencias_ataque ,
'res_hechizo1' => rand ( 0 , 100 ) , 'res_hechizo2' => rand ( 0 , 100 ) , 'res_hechizo3' => rand ( 0 , 100 ) , 'res_hechizo4' => rand ( 0 , 100 ) , 'res_hechizo5' => rand ( 0 , 100 ) ,
// ✨ CAMPO DE HABILIDADES ACTUALIZADO
'habilidades' => $habilidades_asignadas , // Ahora es un array con 1 a 3 habilidades
'desc_es' => "Descripción en español para la unidad $i ." ,
'desc_en' => "English description for unit $i ."
] ;
}
return $datos ;
}
// --- Funciones auxiliares ---
function format_mem
( $bytes ) { return number_format ( $bytes / 1024 , 2 ) . ' KB' ; } function format_time
( $start , $end ) { return number_format ( ( $end - $start ) * 1000 , 2 ) . ' ms' ; }
$datos_originales = generarDatos( ) ;
// =================================================================
// PARTE 1: PRUEBAS EN MEMORIA (ARRAYS vs OBJETOS)
// =================================================================
echo "<hr><h2>Pruebas de Rendimiento en Memoria</h2>" ;
// Test 1.1: Array de Arrays
$array_de_arrays = $datos_originales ;
echo "<h3>1. Array de Arrays (Asociativos)</h3>" ;
echo "<strong>Creación:</strong> " . format_time( $start_time , $end_time ) . "<br>" ;
echo "<strong>Uso de Memoria:</strong> " . format_mem( $end_mem - $start_mem ) . "<br>" ;
for ( $i = 0 ; $i < NUM_BUSQUEDAS
; $i ++ ) { $elemento = $array_de_arrays [ 1000 + rand ( 1 , NUM_ELEMENTOS
) ] ; } echo "<strong>Acceso aleatorio (" . number_format ( NUM_BUSQUEDAS
) . " veces):</strong> " . format_time
( $start_time , $end_time ) . "<br>" ;
// Test 1.2: Array de Objetos
$array_de_objetos = [ ] ;
foreach ( $datos_originales as $id => $dato ) { $array_de_objetos [ $id ] = ( object) $dato ; }
echo "<h3>2. Array de Objetos (stdClass)</h3>" ;
echo "<strong>Creación:</strong> " . format_time( $start_time , $end_time ) . "<br>" ;
echo "<strong>Uso de Memoria:</strong> " . format_mem( $end_mem - $start_mem ) . "<br>" ;
for ( $i = 0 ; $i < NUM_BUSQUEDAS
; $i ++ ) { $elemento = $array_de_objetos [ 1000 + rand ( 1 , NUM_ELEMENTOS
) ] ; } echo "<strong>Acceso aleatorio (" . number_format ( NUM_BUSQUEDAS
) . " veces):</strong> " . format_time
( $start_time , $end_time ) . "<br>" ;
// =================================================================
// PARTE 2: PRUEBAS DE GUARDADO Y LECTURA (JSON vs SERIALIZE)
// =================================================================
echo "<hr><h2>Pruebas de Guardado y Lectura en Disco</h2>" ;
// Test 2.1: JSON
echo "<h3>1. JSON (json_encode / json_decode)</h3>" ;
echo "<strong>Tiempo de guardado:</strong> " . format_time( $start_time , $end_time ) . "<br>" ;
echo "<strong>Tamaño del archivo:</strong> " . format_mem
( filesize ( 'datos.json' ) ) . "<br>" ; echo "<strong>Tiempo de lectura:</strong> " . format_time( $start_time , $end_time ) . "<br>" ;
// Test 2.2: PHP Serialize
$serialized_data = serialize ( $array_de_arrays ) ; echo "<h3>2. PHP Serialize (serialize / unserialize)</h3>" ;
echo "<strong>Tiempo de guardado:</strong> " . format_time( $start_time , $end_time ) . "<br>" ;
echo "<strong>Tamaño del archivo:</strong> " . format_mem
( filesize ( 'datos.serialize' ) ) . "<br>" ; echo "<strong>Tiempo de lectura:</strong> " . format_time( $start_time , $end_time ) . "<br>" ;
?>
PD9waHAKCi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Ci8vIENPTkZJR1VSQUNJw5NOIERFTCBCRU5DSE1BUksKLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KZGVmaW5lKCdOVU1fRUxFTUVOVE9TJywgMTk5KTsKZGVmaW5lKCdOVU1fQlVTUVVFREFTJywgNTAwMDAwKTsgLy8gSXRlcmFjaW9uZXMgcGFyYSBwcm9iYXIgbGEgdmVsb2NpZGFkIGRlIGFjY2VzbwoKZWNobyAiPGgxPkJlbmNobWFyayBGaW5hbCB5IENvbXBsZXRvIHBhcmEgQXJjaG1hZ2U8L2gxPiI7CmVjaG8gIjxwPlNpbXVsYW5kbyBsYSBlc3RydWN0dXJhIGRlIGRhdG9zIHJlYWwsIGluY2x1eWVuZG8gbGEgbGlzdGEgY29tcGxldGEgZGUgaGFiaWxpZGFkZXMuPC9wPiI7CgovLyAtLS0gRnVuY2nDs24gcGFyYSBnZW5lcmFyIGxvcyBkYXRvcyBkZSBwcnVlYmEgLS0tCmZ1bmN0aW9uIGdlbmVyYXJEYXRvcygpIHsKICAgICRkYXRvcyA9IFtdOwogICAgCiAgICAvLyAtLS0gTGlzdGFzIGRlIGRhdG9zIHBhcmEgZ2VuZXJhciB2YXJpZWRhZCAtLS0KICAgICRyYXphcyA9IFsnZWxlbWVudGFsJywgJ2h1bWFubycsICdkZW1vbmlvJywgJ25vLW11ZXJ0bycsICdiZXN0aWEnLCAnYW5nZWwnXTsKICAgICR0aXBvc19hdGFxdWVfbm9ybWFsID0gWydtYWdpYycsICdtZWxlZScsICdwb2lzb24nLCAnY29sZCddOwogICAgJHRpcG9zX2F0YXF1ZV9leHRyYSA9IFsncmFuZ2VkIGxpZ2h0aW5nJywgJ2ZpcmUgYnJlYXRoJywgJ2hvbHkgc3RyaWtlJywgJ3BzeWNoaWMgYmxhc3QnXTsKICAgIAogICAgLy8g4pyoIExJU1RBIENPTVBMRVRBIERFIEhBQklMSURBREVTIEVYVFJBw41EQSBERUwgSFRNTAogICAgJGxpc3RhX2hhYmlsaWRhZGVzX3Bvc2libGVzID0gWwogICAgICAgICdGTFlJTkcnLCAnQURESVRJT05BTCBTVFJJS0UnLCAnU1dJRlQnLCAnTEFSR0UgU0hJRUxEJywgJ1BJS0UnLCAnUkVHRU5FUkFUSU9OJywgCiAgICAgICAgJ0VORFVSQU5DRScsICdTSUVHRScsICdCRUFVVFknLCAnU1RFQUwgTElGRScsICdNQVJLU01BTlNISVAnLCAnU0NBTEVTJywgJ0ZFQVInLCAKICAgICAgICAnSEVBTElORycsICdDSEFSTScsICdCVVJTVElORyBGTEFNRScsICdDTFVNU0lORVNTJywgJ0FDQ1VSQUNZJywgJ1JFQ1JVSVQgU1BFRUQnLCAKICAgICAgICAnV0VBS05FU1MgVE8nLCAnSU5JVElBVElWRScsICdBVFRBQ0snLCAnQ09VTlRFUkFUVEFDSycsICdISVRQT0lOVCcsICdBVFRBQ0tUWVBFJywgCiAgICAgICAgJ1BSRVZFTlQgREFNQUdFJywgJ0RFU1RST1knLCAnUkVTVVJSRUNUJywgJ1NQRUxMIElNTVVOSVRZJywgJ1NMRUVQJywgJ0FUVERFRiBBR0FJTlNUJywgCiAgICAgICAgJ0FUVEFDSyBSRVNJU1RBTkNFJywgJ1NQRUxMIFJFU0lTVEFOQ0UnLCAnREFNQUdFIFNFTEYnCiAgICBdOwogICAgCiAgICAkdGlwb3NfcmVzaXN0ZW5jaWFfYXRhcXVlID0gWwogICAgICAgICdNaXNzaWxlJywgJ01hZ2ljJywgJ0NvbGQnLCAnRmlyZScsICdNZWxlZScsICdQYXJhbHl6ZScsIAogICAgICAgICdQb2lzb24nLCAnUmFuZ2VkJywgJ1BzeWNoaWMnLCAnQnJlYXRoJywgJ0xpZ2h0bmluZycsICdIb2x5JwogICAgXTsKCgogICAgZm9yICgkaSA9IDE7ICRpIDw9IE5VTV9FTEVNRU5UT1M7ICRpKyspIHsKICAgICAgICAkaWQgPSAxMDAwICsgJGk7CiAgICAgICAgCiAgICAgICAgLy8gLS0tIEFzaWduYWNpw7NuIGRlIGhhYmlsaWRhZGVzIChkZSAxIGEgMyBwb3IgdW5pZGFkKSAtLS0KICAgICAgICAkaGFiaWxpZGFkZXNfYXNpZ25hZGFzID0gW107CiAgICAgICAgJG51bV9oYWJpbGlkYWRlc19hX2FzaWduYXIgPSByYW5kKDEsIDMpOwogICAgICAgICRrZXlzX2hhYmlsaWRhZGVzX2FsZWF0b3JpYXMgPSBhcnJheV9yYW5kKCRsaXN0YV9oYWJpbGlkYWRlc19wb3NpYmxlcywgJG51bV9oYWJpbGlkYWRlc19hX2FzaWduYXIpOwogICAgICAgIGlmIChpc19hcnJheSgka2V5c19oYWJpbGlkYWRlc19hbGVhdG9yaWFzKSkgewogICAgICAgICAgICBmb3JlYWNoICgka2V5c19oYWJpbGlkYWRlc19hbGVhdG9yaWFzIGFzICRrZXkpIHsKICAgICAgICAgICAgICAgICRoYWJpbGlkYWRlc19hc2lnbmFkYXNbXSA9ICRsaXN0YV9oYWJpbGlkYWRlc19wb3NpYmxlc1ska2V5XTsKICAgICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAkaGFiaWxpZGFkZXNfYXNpZ25hZGFzW10gPSAkbGlzdGFfaGFiaWxpZGFkZXNfcG9zaWJsZXNbJGtleXNfaGFiaWxpZGFkZXNfYWxlYXRvcmlhc107CiAgICAgICAgfQoKICAgICAgICAvLyAtLS0gQ3JlYWNpw7NuIGRlIHJlc2lzdGVuY2lhcyBhIGF0YXF1ZXMgLS0tCiAgICAgICAgJHJlc2lzdGVuY2lhc19hdGFxdWUgPSBbXTsKICAgICAgICBmb3JlYWNoICgkdGlwb3NfcmVzaXN0ZW5jaWFfYXRhcXVlIGFzICR0aXBvKSB7CiAgICAgICAgICAgICRyZXNpc3RlbmNpYXNfYXRhcXVlWyR0aXBvXSA9IHJhbmQoMCwgMTAwKTsKICAgICAgICB9CgogICAgICAgICRkYXRvc1skaWRdID0gWwogICAgICAgICAgICAnaWQnID0+ICRpZCwKICAgICAgICAgICAgJ25vbWJyZScgPT4gIlVuaWRhZCBkZSBwcnVlYmEgIyRpIiwKICAgICAgICAgICAgJ3JhemEnID0+ICRyYXphc1thcnJheV9yYW5kKCRyYXphcyldLAogICAgICAgICAgICAncG9kZXInID0+IHJhbmQoMjAwMDAsIDUwMDAwKSwKICAgICAgICAgICAgJ2hwJyA9PiByYW5kKDUwMDAwLCA4MDAwMCksCiAgICAgICAgICAgICdpbWFnZW5fdXJsJyA9PiAiaHR0cHM6Ly93Li4uY29udGVudC1hdmFpbGFibGUtdG8tYXV0aG9yLW9ubHkuLi5kLmNsL2kvdW5pdHMvIiAuIHJhbmQoMSwgMjAwKSAuICIuanBnIiwKICAgICAgICAgICAgCiAgICAgICAgICAgICdwb2Rlcl9hdGFxdWUnID0+IHJhbmQoODAwMDAsIDEyMDAwMCksCiAgICAgICAgICAgICd0aXBvX2F0YXF1ZScgPT4gJHRpcG9zX2F0YXF1ZV9ub3JtYWxbYXJyYXlfcmFuZCgkdGlwb3NfYXRhcXVlX25vcm1hbCldLAogICAgICAgICAgICAncG9kZXJfYXRhcXVlX2V4dHJhJyA9PiByYW5kKDI1MDAwMCwgMzUwMDAwKSwKICAgICAgICAgICAgJ3RpcG9fYXRhcXVlX2V4dHJhJyA9PiAkdGlwb3NfYXRhcXVlX2V4dHJhW2FycmF5X3JhbmQoJHRpcG9zX2F0YXF1ZV9leHRyYSldLAogICAgICAgICAgICAKICAgICAgICAgICAgJ2luaWNpYXRpdmEnID0+IHJhbmQoMSwgNSksCiAgICAgICAgICAgICdpbmljaWF0aXZhX2V4dHJhJyA9PiByYW5kKDEsIDUpLAogICAgICAgICAgICAnY29udHJhX2F0YXF1ZScgPT4gcmFuZCg2MDAwLCA4MDAwKSwKICAgICAgICAgICAgCiAgICAgICAgICAgICdtYW50X29ybycgPT4gcmFuZCgwLCA1MCksCiAgICAgICAgICAgICdtYW50X2dlbnRlJyA9PiByYW5kKDAsIDEwKSwKICAgICAgICAgICAgJ21hbnRfbWFuYScgPT4gcmFuZCg4MCwgMTUwKSwKICAgICAgICAgICAgCiAgICAgICAgICAgICdyZXNpc3RlbmNpYV9hdGFxdWVzJyA9PiAkcmVzaXN0ZW5jaWFzX2F0YXF1ZSwKCiAgICAgICAgICAgICdyZXNfaGVjaGl6bzEnID0+IHJhbmQoMCwgMTAwKSwKICAgICAgICAgICAgJ3Jlc19oZWNoaXpvMicgPT4gcmFuZCgwLCAxMDApLAogICAgICAgICAgICAncmVzX2hlY2hpem8zJyA9PiByYW5kKDAsIDEwMCksCiAgICAgICAgICAgICdyZXNfaGVjaGl6bzQnID0+IHJhbmQoMCwgMTAwKSwKICAgICAgICAgICAgJ3Jlc19oZWNoaXpvNScgPT4gcmFuZCgwLCAxMDApLAogICAgICAgICAgICAKICAgICAgICAgICAgLy8g4pyoIENBTVBPIERFIEhBQklMSURBREVTIEFDVFVBTElaQURPCiAgICAgICAgICAgICdoYWJpbGlkYWRlcycgPT4gJGhhYmlsaWRhZGVzX2FzaWduYWRhcywgLy8gQWhvcmEgZXMgdW4gYXJyYXkgY29uIDEgYSAzIGhhYmlsaWRhZGVzCiAgICAgICAgICAgIAogICAgICAgICAgICAnZGVzY19lcycgPT4gIkRlc2NyaXBjacOzbiBlbiBlc3Bhw7FvbCBwYXJhIGxhIHVuaWRhZCAkaS4iLAogICAgICAgICAgICAnZGVzY19lbicgPT4gIkVuZ2xpc2ggZGVzY3JpcHRpb24gZm9yIHVuaXQgJGkuIgogICAgICAgIF07CiAgICB9CiAgICByZXR1cm4gJGRhdG9zOwp9CgovLyAtLS0gRnVuY2lvbmVzIGF1eGlsaWFyZXMgLS0tCmZ1bmN0aW9uIGZvcm1hdF9tZW0oJGJ5dGVzKSB7IHJldHVybiBudW1iZXJfZm9ybWF0KCRieXRlcyAvIDEwMjQsIDIpIC4gJyBLQic7IH0KZnVuY3Rpb24gZm9ybWF0X3RpbWUoJHN0YXJ0LCAkZW5kKSB7IHJldHVybiBudW1iZXJfZm9ybWF0KCgkZW5kIC0gJHN0YXJ0KSAqIDEwMDAsIDIpIC4gJyBtcyc7IH0KCiRkYXRvc19vcmlnaW5hbGVzID0gZ2VuZXJhckRhdG9zKCk7CgovLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQovLyBQQVJURSAxOiBQUlVFQkFTIEVOIE1FTU9SSUEgKEFSUkFZUyB2cyBPQkpFVE9TKQovLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQplY2hvICI8aHI+PGgyPlBydWViYXMgZGUgUmVuZGltaWVudG8gZW4gTWVtb3JpYTwvaDI+IjsKCi8vIFRlc3QgMS4xOiBBcnJheSBkZSBBcnJheXMKJHN0YXJ0X21lbSA9IG1lbW9yeV9nZXRfdXNhZ2UoKTsKJHN0YXJ0X3RpbWUgPSBtaWNyb3RpbWUodHJ1ZSk7CiRhcnJheV9kZV9hcnJheXMgPSAkZGF0b3Nfb3JpZ2luYWxlczsKJGVuZF90aW1lID0gbWljcm90aW1lKHRydWUpOwokZW5kX21lbSA9IG1lbW9yeV9nZXRfdXNhZ2UoKTsKZWNobyAiPGgzPjEuIEFycmF5IGRlIEFycmF5cyAoQXNvY2lhdGl2b3MpPC9oMz4iOwplY2hvICI8c3Ryb25nPkNyZWFjacOzbjo8L3N0cm9uZz4gIiAuIGZvcm1hdF90aW1lKCRzdGFydF90aW1lLCAkZW5kX3RpbWUpIC4gIjxicj4iOwplY2hvICI8c3Ryb25nPlVzbyBkZSBNZW1vcmlhOjwvc3Ryb25nPiAiIC4gZm9ybWF0X21lbSgkZW5kX21lbSAtICRzdGFydF9tZW0pIC4gIjxicj4iOwokc3RhcnRfdGltZSA9IG1pY3JvdGltZSh0cnVlKTsKZm9yICgkaT0wOyAkaSA8IE5VTV9CVVNRVUVEQVM7ICRpKyspIHsgJGVsZW1lbnRvID0gJGFycmF5X2RlX2FycmF5c1sxMDAwICsgcmFuZCgxLCBOVU1fRUxFTUVOVE9TKV07IH0KJGVuZF90aW1lID0gbWljcm90aW1lKHRydWUpOwplY2hvICI8c3Ryb25nPkFjY2VzbyBhbGVhdG9yaW8gKCIgLiBudW1iZXJfZm9ybWF0KE5VTV9CVVNRVUVEQVMpIC4gIiB2ZWNlcyk6PC9zdHJvbmc+ICIgLiBmb3JtYXRfdGltZSgkc3RhcnRfdGltZSwgJGVuZF90aW1lKSAuICI8YnI+IjsKCi8vIFRlc3QgMS4yOiBBcnJheSBkZSBPYmpldG9zCiRzdGFydF9tZW0gPSBtZW1vcnlfZ2V0X3VzYWdlKCk7CiRzdGFydF90aW1lID0gbWljcm90aW1lKHRydWUpOwokYXJyYXlfZGVfb2JqZXRvcyA9IFtdOwpmb3JlYWNoICgkZGF0b3Nfb3JpZ2luYWxlcyBhcyAkaWQgPT4gJGRhdG8pIHsgJGFycmF5X2RlX29iamV0b3NbJGlkXSA9IChvYmplY3QpJGRhdG87IH0KJGVuZF90aW1lID0gbWljcm90aW1lKHRydWUpOwokZW5kX21lbSA9IG1lbW9yeV9nZXRfdXNhZ2UoKTsKZWNobyAiPGgzPjIuIEFycmF5IGRlIE9iamV0b3MgKHN0ZENsYXNzKTwvaDM+IjsKZWNobyAiPHN0cm9uZz5DcmVhY2nDs246PC9zdHJvbmc+ICIgLiBmb3JtYXRfdGltZSgkc3RhcnRfdGltZSwgJGVuZF90aW1lKSAuICI8YnI+IjsKZWNobyAiPHN0cm9uZz5Vc28gZGUgTWVtb3JpYTo8L3N0cm9uZz4gIiAuIGZvcm1hdF9tZW0oJGVuZF9tZW0gLSAkc3RhcnRfbWVtKSAuICI8YnI+IjsKJHN0YXJ0X3RpbWUgPSBtaWNyb3RpbWUodHJ1ZSk7CmZvciAoJGk9MDsgJGkgPCBOVU1fQlVTUVVFREFTOyAkaSsrKSB7ICRlbGVtZW50byA9ICRhcnJheV9kZV9vYmpldG9zWzEwMDAgKyByYW5kKDEsIE5VTV9FTEVNRU5UT1MpXTsgfQokZW5kX3RpbWUgPSBtaWNyb3RpbWUodHJ1ZSk7CmVjaG8gIjxzdHJvbmc+QWNjZXNvIGFsZWF0b3JpbyAoIiAuIG51bWJlcl9mb3JtYXQoTlVNX0JVU1FVRURBUykgLiAiIHZlY2VzKTo8L3N0cm9uZz4gIiAuIGZvcm1hdF90aW1lKCRzdGFydF90aW1lLCAkZW5kX3RpbWUpIC4gIjxicj4iOwoKLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KLy8gUEFSVEUgMjogUFJVRUJBUyBERSBHVUFSREFETyBZIExFQ1RVUkEgKEpTT04gdnMgU0VSSUFMSVpFKQovLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQplY2hvICI8aHI+PGgyPlBydWViYXMgZGUgR3VhcmRhZG8geSBMZWN0dXJhIGVuIERpc2NvPC9oMj4iOwoKLy8gVGVzdCAyLjE6IEpTT04KJHN0YXJ0X3RpbWUgPSBtaWNyb3RpbWUodHJ1ZSk7CiRqc29uX2RhdGEgPSBqc29uX2VuY29kZSgkYXJyYXlfZGVfYXJyYXlzKTsKZmlsZV9wdXRfY29udGVudHMoJ2RhdG9zLmpzb24nLCAkanNvbl9kYXRhKTsKJGVuZF90aW1lID0gbWljcm90aW1lKHRydWUpOwplY2hvICI8aDM+MS4gSlNPTiAoanNvbl9lbmNvZGUgLyBqc29uX2RlY29kZSk8L2gzPiI7CmVjaG8gIjxzdHJvbmc+VGllbXBvIGRlIGd1YXJkYWRvOjwvc3Ryb25nPiAiIC4gZm9ybWF0X3RpbWUoJHN0YXJ0X3RpbWUsICRlbmRfdGltZSkgLiAiPGJyPiI7CmVjaG8gIjxzdHJvbmc+VGFtYcOxbyBkZWwgYXJjaGl2bzo8L3N0cm9uZz4gIiAuIGZvcm1hdF9tZW0oZmlsZXNpemUoJ2RhdG9zLmpzb24nKSkgLiAiPGJyPiI7CiRzdGFydF90aW1lID0gbWljcm90aW1lKHRydWUpOwokanNvbl9sZWlkbyA9IGZpbGVfZ2V0X2NvbnRlbnRzKCdkYXRvcy5qc29uJyk7CiRkYXRvc19kZXNkZV9qc29uID0ganNvbl9kZWNvZGUoJGpzb25fbGVpZG8sIHRydWUpOwokZW5kX3RpbWUgPSBtaWNyb3RpbWUodHJ1ZSk7CmVjaG8gIjxzdHJvbmc+VGllbXBvIGRlIGxlY3R1cmE6PC9zdHJvbmc+ICIgLiBmb3JtYXRfdGltZSgkc3RhcnRfdGltZSwgJGVuZF90aW1lKSAuICI8YnI+IjsKdW5saW5rKCdkYXRvcy5qc29uJyk7CgovLyBUZXN0IDIuMjogUEhQIFNlcmlhbGl6ZQokc3RhcnRfdGltZSA9IG1pY3JvdGltZSh0cnVlKTsKJHNlcmlhbGl6ZWRfZGF0YSA9IHNlcmlhbGl6ZSgkYXJyYXlfZGVfYXJyYXlzKTsKZmlsZV9wdXRfY29udGVudHMoJ2RhdG9zLnNlcmlhbGl6ZScsICRzZXJpYWxpemVkX2RhdGEpOwokZW5kX3RpbWUgPSBtaWNyb3RpbWUodHJ1ZSk7CmVjaG8gIjxoMz4yLiBQSFAgU2VyaWFsaXplIChzZXJpYWxpemUgLyB1bnNlcmlhbGl6ZSk8L2gzPiI7CmVjaG8gIjxzdHJvbmc+VGllbXBvIGRlIGd1YXJkYWRvOjwvc3Ryb25nPiAiIC4gZm9ybWF0X3RpbWUoJHN0YXJ0X3RpbWUsICRlbmRfdGltZSkgLiAiPGJyPiI7CmVjaG8gIjxzdHJvbmc+VGFtYcOxbyBkZWwgYXJjaGl2bzo8L3N0cm9uZz4gIiAuIGZvcm1hdF9tZW0oZmlsZXNpemUoJ2RhdG9zLnNlcmlhbGl6ZScpKSAuICI8YnI+IjsKJHN0YXJ0X3RpbWUgPSBtaWNyb3RpbWUodHJ1ZSk7CiRzZXJpYWxfbGVpZG8gPSBmaWxlX2dldF9jb250ZW50cygnZGF0b3Muc2VyaWFsaXplJyk7CiRkYXRvc19kZXNkZV9zZXJpYWwgPSB1bnNlcmlhbGl6ZSgkc2VyaWFsX2xlaWRvKTsKJGVuZF90aW1lID0gbWljcm90aW1lKHRydWUpOwplY2hvICI8c3Ryb25nPlRpZW1wbyBkZSBsZWN0dXJhOjwvc3Ryb25nPiAiIC4gZm9ybWF0X3RpbWUoJHN0YXJ0X3RpbWUsICRlbmRfdGltZSkgLiAiPGJyPiI7CnVubGluaygnZGF0b3Muc2VyaWFsaXplJyk7Cgo/Pg==