Feat Widgets 0209
This commit is contained in:
		| @@ -235,67 +235,36 @@ public class ResultadosController : ControllerBase | ||||
|         return Ok(resultadosGanadores); | ||||
|     } | ||||
|  | ||||
|     [HttpGet("municipio/{ambitoId}")] // Cambiamos el nombre del parámetro de ruta | ||||
|     public async Task<IActionResult> GetResultadosPorMunicipio(int ambitoId) // Cambiamos el tipo de string a int | ||||
|     [HttpGet("municipio/{ambitoId}")] | ||||
|     public async Task<IActionResult> GetResultadosPorMunicipio(int ambitoId, [FromQuery] int categoriaId) | ||||
|     { | ||||
|         _logger.LogInformation("Buscando resultados para AmbitoGeograficoId: {AmbitoId}", ambitoId); | ||||
|         // Validamos que el ámbito exista | ||||
|         var ambito = await _dbContext.AmbitosGeograficos.AsNoTracking() | ||||
|             .FirstOrDefaultAsync(a => a.Id == ambitoId && a.NivelId == 30); | ||||
|         if (ambito == null) return NotFound($"No se encontró el municipio con ID {ambitoId}"); | ||||
|  | ||||
|         // PASO 1: Buscar el Ámbito Geográfico directamente por su CLAVE PRIMARIA (AmbitoGeograficoId). | ||||
|         var ambito = await _dbContext.AmbitosGeograficos | ||||
|             .AsNoTracking() | ||||
|             .FirstOrDefaultAsync(a => a.Id == ambitoId && a.NivelId == 30); // Usamos a.Id == ambitoId | ||||
|  | ||||
|         if (ambito == null) | ||||
|         { | ||||
|             _logger.LogWarning("No se encontró el ámbito para el ID interno: {AmbitoId} o no es Nivel 30.", ambitoId); | ||||
|             return NotFound(new { message = $"No se encontró el municipio con ID interno {ambitoId}" }); | ||||
|         } | ||||
|         _logger.LogInformation("Ámbito encontrado: Id={AmbitoId}, Nombre={AmbitoNombre}", ambito.Id, ambito.Nombre); | ||||
|  | ||||
|         // PASO 2: Usar la CLAVE PRIMARIA (ambito.Id) para buscar el estado del recuento. | ||||
|         var estadoRecuento = await _dbContext.EstadosRecuentos | ||||
|             .AsNoTracking() | ||||
|             .FirstOrDefaultAsync(e => e.AmbitoGeograficoId == ambito.Id); | ||||
|  | ||||
|         if (estadoRecuento == null) | ||||
|         { | ||||
|             _logger.LogWarning("No se encontró EstadoRecuento para AmbitoGeograficoId: {AmbitoId}", ambito.Id); | ||||
|             return NotFound(new { message = $"No se han encontrado resultados de recuento para el municipio {ambito.Nombre}" }); | ||||
|         } | ||||
|  | ||||
|         // PASO 3: Usar la CLAVE PRIMARIA (ambito.Id) para buscar los votos. | ||||
|         // Obtenemos los votos para ESE municipio y ESA categoría | ||||
|         var resultadosVotos = await _dbContext.ResultadosVotos | ||||
|             .AsNoTracking() | ||||
|             .Include(rv => rv.AgrupacionPolitica) // Incluimos el nombre del partido | ||||
|             .Where(rv => rv.AmbitoGeograficoId == ambito.Id) | ||||
|             .OrderByDescending(rv => rv.CantidadVotos) | ||||
|             .Include(rv => rv.AgrupacionPolitica) | ||||
|             .Where(rv => rv.AmbitoGeograficoId == ambitoId && rv.CategoriaId == categoriaId) | ||||
|             .ToListAsync(); | ||||
|  | ||||
|         // PASO 4: Calcular el total de votos positivos para el porcentaje. | ||||
|         long totalVotosPositivos = resultadosVotos.Sum(r => r.CantidadVotos); | ||||
|         // Calculamos el total de votos solo para esta selección | ||||
|         var totalVotosPositivos = (decimal)resultadosVotos.Sum(r => r.CantidadVotos); | ||||
|  | ||||
|         // PASO 5: Mapear todo al DTO de respuesta que el frontend espera. | ||||
|         var respuestaDto = new MunicipioResultadosDto | ||||
|         { | ||||
|             MunicipioNombre = ambito.Nombre, | ||||
|             UltimaActualizacion = estadoRecuento.FechaTotalizacion, | ||||
|             PorcentajeEscrutado = estadoRecuento.MesasTotalizadasPorcentaje, | ||||
|             PorcentajeParticipacion = estadoRecuento.ParticipacionPorcentaje, | ||||
|             Resultados = resultadosVotos.Select(rv => new AgrupacionResultadoDto | ||||
|         // Mapeamos a la respuesta final que espera el frontend | ||||
|         var respuesta = resultadosVotos | ||||
|             .OrderByDescending(r => r.CantidadVotos) | ||||
|             .Select(rv => new | ||||
|             { | ||||
|                 Nombre = rv.AgrupacionPolitica.Nombre, | ||||
|                 Votos = rv.CantidadVotos, | ||||
|                 Porcentaje = totalVotosPositivos > 0 ? (rv.CantidadVotos * 100.0m / totalVotosPositivos) : 0 | ||||
|             }).ToList(), | ||||
|             VotosAdicionales = new VotosAdicionalesDto | ||||
|             { | ||||
|                 EnBlanco = estadoRecuento.VotosEnBlanco, | ||||
|                 Nulos = estadoRecuento.VotosNulos, | ||||
|                 Recurridos = estadoRecuento.VotosRecurridos | ||||
|             } | ||||
|         }; | ||||
|                 id = rv.AgrupacionPolitica.Id, | ||||
|                 nombre = rv.AgrupacionPolitica.NombreCorto ?? rv.AgrupacionPolitica.Nombre, | ||||
|                 votos = rv.CantidadVotos, | ||||
|                 porcentaje = totalVotosPositivos > 0 ? (rv.CantidadVotos / totalVotosPositivos) * 100 : 0 | ||||
|             }).ToList(); | ||||
|  | ||||
|         return Ok(respuestaDto); | ||||
|         return Ok(respuesta); | ||||
|     } | ||||
|  | ||||
|     [HttpGet("composicion-congreso")] | ||||
| @@ -535,55 +504,180 @@ public class ResultadosController : ControllerBase | ||||
|     } | ||||
|  | ||||
|     [HttpGet("concejales/{seccionId}")] | ||||
|     public async Task<IActionResult> GetResultadosConcejalesPorSeccion(string seccionId) | ||||
| public async Task<IActionResult> GetResultadosConcejalesPorSeccion(string seccionId) | ||||
| { | ||||
|     var municipiosDeLaSeccion = await _dbContext.AmbitosGeograficos | ||||
|         .AsNoTracking() | ||||
|         .Where(a => a.NivelId == 30 && a.SeccionProvincialId == seccionId) | ||||
|         .Select(a => a.Id) | ||||
|         .ToListAsync(); | ||||
|  | ||||
|     if (!municipiosDeLaSeccion.Any()) | ||||
|     { | ||||
|         return Ok(new List<object>()); | ||||
|     } | ||||
|  | ||||
|     var resultadosMunicipales = await _dbContext.ResultadosVotos | ||||
|         .AsNoTracking() | ||||
|         .Include(r => r.AgrupacionPolitica) | ||||
|         .Where(r => r.CategoriaId == 7 && municipiosDeLaSeccion.Contains(r.AmbitoGeograficoId)) | ||||
|         .ToListAsync(); | ||||
|  | ||||
|     var logosConcejales = await _dbContext.LogosAgrupacionesCategorias | ||||
|         .AsNoTracking() | ||||
|         .Where(l => l.CategoriaId == 7) | ||||
|         .ToDictionaryAsync(l => l.AgrupacionPoliticaId); | ||||
|  | ||||
|     var totalVotosSeccion = (decimal)resultadosMunicipales.Sum(r => r.CantidadVotos); | ||||
|  | ||||
|     var resultadosFinales = resultadosMunicipales | ||||
|         // 1. Agrupamos por el ID del partido para evitar duplicados. | ||||
|         .GroupBy(r => r.AgrupacionPoliticaId)  | ||||
|         .Select(g => new | ||||
|         { | ||||
|             // 2. Obtenemos la entidad completa del primer elemento del grupo. | ||||
|             Agrupacion = g.First().AgrupacionPolitica, | ||||
|             Votos = g.Sum(r => r.CantidadVotos) | ||||
|         }) | ||||
|         .OrderByDescending(r => r.Votos) | ||||
|         .Select(r => new | ||||
|         { | ||||
|             Id = r.Agrupacion.Id, // Aseguramos que el Id esté en el objeto final | ||||
|             r.Agrupacion.Nombre, | ||||
|             r.Agrupacion.NombreCorto, | ||||
|             r.Agrupacion.Color, | ||||
|             LogoUrl = logosConcejales.GetValueOrDefault(r.Agrupacion.Id)?.LogoUrl, | ||||
|             Votos = r.Votos, | ||||
|             // --- CORRECCIÓN CLAVE --- | ||||
|             // 3. Usamos el nombre de propiedad correcto que el frontend espera: 'votosPorcentaje' | ||||
|             VotosPorcentaje = totalVotosSeccion > 0 ? ((decimal)r.Votos * 100 / totalVotosSeccion) : 0 | ||||
|         }) | ||||
|         .ToList(); | ||||
|  | ||||
|     return Ok(resultadosFinales); | ||||
| } | ||||
|  | ||||
|     [HttpGet("mapa-por-seccion")] | ||||
|     public async Task<IActionResult> GetResultadosMapaPorSeccion([FromQuery] int categoriaId) | ||||
|     { | ||||
|         // 1. Obtenemos todos los resultados a nivel de MUNICIPIO para la categoría dada. | ||||
|         var resultadosMunicipales = await _dbContext.ResultadosVotos | ||||
|             .AsNoTracking() | ||||
|             .Include(r => r.AmbitoGeografico) | ||||
|             .Include(r => r.AgrupacionPolitica) | ||||
|             .Where(r => r.CategoriaId == categoriaId && r.AmbitoGeografico.NivelId == 30) | ||||
|             .ToListAsync(); | ||||
|  | ||||
|         // 2. Agrupamos en memoria por Sección Electoral y sumamos los votos. | ||||
|         var ganadoresPorSeccion = resultadosMunicipales | ||||
|             .GroupBy(r => r.AmbitoGeografico.SeccionProvincialId) | ||||
|             .Select(g => | ||||
|             { | ||||
|                 // Para cada sección, encontramos al partido con más votos. | ||||
|                 var ganador = g | ||||
|                     .GroupBy(r => r.AgrupacionPolitica) | ||||
|                     .Select(pg => new { Agrupacion = pg.Key, TotalVotos = pg.Sum(r => r.CantidadVotos) }) | ||||
|                     .OrderByDescending(x => x.TotalVotos) | ||||
|                     .FirstOrDefault(); | ||||
|  | ||||
|                 // Buscamos el nombre de la sección | ||||
|                 var seccionInfo = _dbContext.AmbitosGeograficos | ||||
|                     .FirstOrDefault(a => a.SeccionProvincialId == g.Key && a.NivelId == 20); | ||||
|  | ||||
|                 return new | ||||
|                 { | ||||
|                     SeccionId = g.Key, | ||||
|                     SeccionNombre = seccionInfo?.Nombre, | ||||
|                     AgrupacionGanadoraId = ganador?.Agrupacion.Id, | ||||
|                     ColorGanador = ganador?.Agrupacion.Color | ||||
|                 }; | ||||
|             }) | ||||
|             .Where(r => r.SeccionId != null) // Filtramos cualquier posible nulo | ||||
|             .ToList(); | ||||
|  | ||||
|         return Ok(ganadoresPorSeccion); | ||||
|     } | ||||
|  | ||||
|     [HttpGet("seccion/{seccionId}")] | ||||
|     public async Task<IActionResult> GetResultadosDetallePorSeccion(string seccionId, [FromQuery] int categoriaId) | ||||
|     { | ||||
|         // 1. Encontrar todos los municipios (Nivel 30) que pertenecen a la sección dada (Nivel 20) | ||||
|         var municipiosDeLaSeccion = await _dbContext.AmbitosGeograficos | ||||
|             .AsNoTracking() | ||||
|             .Where(a => a.NivelId == 30 && a.SeccionProvincialId == seccionId) | ||||
|             .Select(a => a.Id) // Solo necesitamos sus IDs | ||||
|             .Select(a => a.Id) | ||||
|             .ToListAsync(); | ||||
|  | ||||
|         if (!municipiosDeLaSeccion.Any()) | ||||
|         { | ||||
|             return Ok(new List<object>()); | ||||
|         } | ||||
|         if (!municipiosDeLaSeccion.Any()) return Ok(new List<object>()); | ||||
|  | ||||
|         // 2. Obtener todos los resultados de la categoría Concejales (ID 7) para esos municipios | ||||
|         var resultadosMunicipales = await _dbContext.ResultadosVotos | ||||
|             .AsNoTracking() | ||||
|             .Include(r => r.AgrupacionPolitica) | ||||
|             .Where(r => r.CategoriaId == 7 && municipiosDeLaSeccion.Contains(r.AmbitoGeograficoId)) | ||||
|             .Where(r => r.CategoriaId == categoriaId && municipiosDeLaSeccion.Contains(r.AmbitoGeograficoId)) | ||||
|             .ToListAsync(); | ||||
|  | ||||
|         var logosConcejales = await _dbContext.LogosAgrupacionesCategorias | ||||
|             .AsNoTracking() | ||||
|             .Where(l => l.CategoriaId == 7) | ||||
|             .ToDictionaryAsync(l => l.AgrupacionPoliticaId); | ||||
|  | ||||
|         // 3. Agrupar y sumar en memoria para obtener el total por partido para la sección | ||||
|         var totalVotosSeccion = resultadosMunicipales.Sum(r => r.CantidadVotos); | ||||
|  | ||||
|         var totalVotosSeccion = (decimal)resultadosMunicipales.Sum(r => r.CantidadVotos); | ||||
|         var resultadosFinales = resultadosMunicipales | ||||
|             .GroupBy(r => r.AgrupacionPolitica) | ||||
|             // 1. Agrupamos por el ID del partido, que es un valor único y estable | ||||
|             .GroupBy(r => r.AgrupacionPoliticaId) | ||||
|             .Select(g => new | ||||
|             { | ||||
|                 Agrupacion = g.Key, | ||||
|                 // 2. Obtenemos el objeto Agrupacion del primer elemento del grupo | ||||
|                 Agrupacion = g.First().AgrupacionPolitica, | ||||
|                 Votos = g.Sum(r => r.CantidadVotos) | ||||
|             }) | ||||
|             .OrderByDescending(r => r.Votos) | ||||
|             .Select(r => new | ||||
|             { | ||||
|                 r.Agrupacion.Id, | ||||
|                 r.Agrupacion.Nombre, | ||||
|                 r.Agrupacion.NombreCorto, | ||||
|                 r.Agrupacion.Color, | ||||
|                 LogoUrl = logosConcejales.GetValueOrDefault(r.Agrupacion.Id)?.LogoUrl, | ||||
|                 r.Votos, | ||||
|                 votosPorcentaje = totalVotosSeccion > 0 ? ((decimal)r.Votos * 100 / totalVotosSeccion) : 0 | ||||
|                 id = r.Agrupacion.Id, | ||||
|                 nombre = r.Agrupacion.NombreCorto ?? r.Agrupacion.Nombre, | ||||
|                 votos = r.Votos, | ||||
|                 porcentaje = totalVotosSeccion > 0 ? ((decimal)r.Votos * 100 / totalVotosSeccion) : 0 | ||||
|             }) | ||||
|             .ToList(); | ||||
|  | ||||
|         return Ok(resultadosFinales); | ||||
|     } | ||||
|  | ||||
|     [HttpGet("mapa-por-municipio")] | ||||
|     public async Task<IActionResult> GetResultadosMapaPorMunicipio([FromQuery] int categoriaId) | ||||
|     { | ||||
|         // Obtenemos los votos primero | ||||
|         var votosPorMunicipio = await _dbContext.ResultadosVotos | ||||
|             .AsNoTracking() | ||||
|             .Where(r => r.CategoriaId == categoriaId && r.AmbitoGeografico.NivelId == 30) | ||||
|             .ToListAsync(); | ||||
|  | ||||
|         // Luego, los agrupamos en memoria | ||||
|         var ganadores = votosPorMunicipio | ||||
|             .GroupBy(r => r.AmbitoGeograficoId) | ||||
|             .Select(g => g.OrderByDescending(r => r.CantidadVotos).First()) | ||||
|             .ToList(); | ||||
|  | ||||
|         // Ahora, obtenemos los detalles necesarios en una sola consulta adicional | ||||
|         var idsAgrupacionesGanadoras = ganadores.Select(g => g.AgrupacionPoliticaId).ToList(); | ||||
|         var idsAmbitosGanadores = ganadores.Select(g => g.AmbitoGeograficoId).ToList(); | ||||
|  | ||||
|         var agrupacionesInfo = await _dbContext.AgrupacionesPoliticas | ||||
|             .AsNoTracking() | ||||
|             .Where(a => idsAgrupacionesGanadoras.Contains(a.Id)) | ||||
|             .ToDictionaryAsync(a => a.Id); | ||||
|  | ||||
|         var ambitosInfo = await _dbContext.AmbitosGeograficos | ||||
|             .AsNoTracking() | ||||
|             .Where(a => idsAmbitosGanadores.Contains(a.Id)) | ||||
|             .ToDictionaryAsync(a => a.Id); | ||||
|  | ||||
|         // Finalmente, unimos todo en memoria | ||||
|         var resultadoFinal = ganadores.Select(g => new | ||||
|         { | ||||
|             AmbitoId = g.AmbitoGeograficoId, | ||||
|             DepartamentoNombre = ambitosInfo.GetValueOrDefault(g.AmbitoGeograficoId)?.Nombre, | ||||
|             AgrupacionGanadoraId = g.AgrupacionPoliticaId, | ||||
|             ColorGanador = agrupacionesInfo.GetValueOrDefault(g.AgrupacionPoliticaId)?.Color | ||||
|         }) | ||||
|         .Where(r => r.DepartamentoNombre != null) // Filtramos por si acaso | ||||
|         .ToList(); | ||||
|  | ||||
|         return Ok(resultadoFinal); | ||||
|     } | ||||
| } | ||||
| @@ -14,7 +14,7 @@ using System.Reflection; | ||||
| [assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Api")] | ||||
| [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] | ||||
| [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] | ||||
| [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+608ae655bedf6c59be5fec1e14fc308871d2fd62")] | ||||
| [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+12860f24067a7de29ec937e18f314f2f24059f47")] | ||||
| [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Api")] | ||||
| [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Api")] | ||||
| [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] | ||||
|   | ||||
| @@ -1 +1 @@ | ||||
| {"GlobalPropertiesHash":"b5T/+ta4fUd8qpIzUTm3KyEwAYYUsU5ASo+CSFM3ByE=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["BNGxWTPjjFD1Fj56FltRDUvsBzgMlQvuqV\u002BraH2IhwQ=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","ywKm3DCyXg4YCbZAIx3JUlT8N4Irff3GswYUVDST\u002BjQ=","6WTvWQ72AaZBYOVSmaxaci9tc1dW5p7IK9Kscjj2cb0=","vAy46VJ9Gp8QqG/Px4J1mj8jL6ws4/A01UKRmMYfYek=","cdgbHR/E4DJsddPc\u002BTpzoUMOVNaFJZm33Pw7AxU9Ees=","4r4JGR4hS5m4rsLfuCSZxzrknTBxKFkLQDXc\u002B2KbqTU=","yVoZ4UnBcSOapsJIi046hnn7ylD3jAcEBUxQ\u002Brkvj/4=","/GfbpJthEWmsuz0uFx1QLHM7gyM1wLLeQgAIl4SzUD4=","i5\u002B5LcfxQD8meRAkQbVf4wMvjxSE4\u002BjCd2/FdPtMpms=","AvSkxVPIg0GjnB1RJ4hDNyo9p9GONrzDs8uVuixH\u002BOE=","IgT9pOgRnK37qfILj2QcjFoBZ180HMt\u002BScgje2iYOo4=","ezUlOMzNZmyKDIe1wwXqvX\u002BvhwfB992xNVts7r2zcTc=","y2BV4WpkQuLfqQhfOQBtmuzh940c3s4LAopGKfztfTE=","lHTUEsMkDu8nqXtfTwl7FRfgocyyc7RI5O/edTHN1\u002B0=","A7nz7qgOtQ1CwZZLvNnr0b5QZB3fTi3y4i6y7rBIcxQ=","znnuRi2tsk7AACuYo4WSgj7NcLriG4PKVaF4L35SvDk=","khGrM2Rl22MsVh9N6\u002B7todRrMuJ6o3ljuHxZF/aubqE=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","6xYke/2SzNspypSwIgizeNUH7b\u002Bfoz3wYfKk6z1tMsw="],"CachedAssets":{},"CachedCopyCandidates":{}} | ||||
| {"GlobalPropertiesHash":"b5T/+ta4fUd8qpIzUTm3KyEwAYYUsU5ASo+CSFM3ByE=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["BNGxWTPjjFD1Fj56FltRDUvsBzgMlQvuqV\u002BraH2IhwQ=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","ywKm3DCyXg4YCbZAIx3JUlT8N4Irff3GswYUVDST\u002BjQ=","6WTvWQ72AaZBYOVSmaxaci9tc1dW5p7IK9Kscjj2cb0=","vAy46VJ9Gp8QqG/Px4J1mj8jL6ws4/A01UKRmMYfYek=","cdgbHR/E4DJsddPc\u002BTpzoUMOVNaFJZm33Pw7AxU9Ees=","4r4JGR4hS5m4rsLfuCSZxzrknTBxKFkLQDXc\u002B2KbqTU=","yVoZ4UnBcSOapsJIi046hnn7ylD3jAcEBUxQ\u002Brkvj/4=","/GfbpJthEWmsuz0uFx1QLHM7gyM1wLLeQgAIl4SzUD4=","i5\u002B5LcfxQD8meRAkQbVf4wMvjxSE4\u002BjCd2/FdPtMpms=","AvSkxVPIg0GjnB1RJ4hDNyo9p9GONrzDs8uVuixH\u002BOE=","IgT9pOgRnK37qfILj2QcjFoBZ180HMt\u002BScgje2iYOo4=","ezUlOMzNZmyKDIe1wwXqvX\u002BvhwfB992xNVts7r2zcTc=","y2BV4WpkQuLfqQhfOQBtmuzh940c3s4LAopGKfztfTE=","lHTUEsMkDu8nqXtfTwl7FRfgocyyc7RI5O/edTHN1\u002B0=","A7nz7qgOtQ1CwZZLvNnr0b5QZB3fTi3y4i6y7rBIcxQ=","znnuRi2tsk7AACuYo4WSgj7NcLriG4PKVaF4L35SvDk=","eeoSVF\u002BzWQgGKOM9hSCzmc0CNSUCyP/f6aJxLHiJ4A8=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","nt6JdXgYN0sYJ/7di0B2aSGDokBPJnFqtwyBcMkycYI="],"CachedAssets":{},"CachedCopyCandidates":{}} | ||||
| @@ -1 +1 @@ | ||||
| {"GlobalPropertiesHash":"tJTBjV/i0Ihkc6XuOu69wxL8PBac9c9Kak6srMso4pU=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["BNGxWTPjjFD1Fj56FltRDUvsBzgMlQvuqV\u002BraH2IhwQ=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","ywKm3DCyXg4YCbZAIx3JUlT8N4Irff3GswYUVDST\u002BjQ=","6WTvWQ72AaZBYOVSmaxaci9tc1dW5p7IK9Kscjj2cb0=","vAy46VJ9Gp8QqG/Px4J1mj8jL6ws4/A01UKRmMYfYek=","cdgbHR/E4DJsddPc\u002BTpzoUMOVNaFJZm33Pw7AxU9Ees=","4r4JGR4hS5m4rsLfuCSZxzrknTBxKFkLQDXc\u002B2KbqTU=","yVoZ4UnBcSOapsJIi046hnn7ylD3jAcEBUxQ\u002Brkvj/4=","/GfbpJthEWmsuz0uFx1QLHM7gyM1wLLeQgAIl4SzUD4=","i5\u002B5LcfxQD8meRAkQbVf4wMvjxSE4\u002BjCd2/FdPtMpms=","AvSkxVPIg0GjnB1RJ4hDNyo9p9GONrzDs8uVuixH\u002BOE=","IgT9pOgRnK37qfILj2QcjFoBZ180HMt\u002BScgje2iYOo4=","ezUlOMzNZmyKDIe1wwXqvX\u002BvhwfB992xNVts7r2zcTc=","y2BV4WpkQuLfqQhfOQBtmuzh940c3s4LAopGKfztfTE=","lHTUEsMkDu8nqXtfTwl7FRfgocyyc7RI5O/edTHN1\u002B0=","A7nz7qgOtQ1CwZZLvNnr0b5QZB3fTi3y4i6y7rBIcxQ=","znnuRi2tsk7AACuYo4WSgj7NcLriG4PKVaF4L35SvDk=","khGrM2Rl22MsVh9N6\u002B7todRrMuJ6o3ljuHxZF/aubqE=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","6xYke/2SzNspypSwIgizeNUH7b\u002Bfoz3wYfKk6z1tMsw="],"CachedAssets":{},"CachedCopyCandidates":{}} | ||||
| {"GlobalPropertiesHash":"tJTBjV/i0Ihkc6XuOu69wxL8PBac9c9Kak6srMso4pU=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["BNGxWTPjjFD1Fj56FltRDUvsBzgMlQvuqV\u002BraH2IhwQ=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","ywKm3DCyXg4YCbZAIx3JUlT8N4Irff3GswYUVDST\u002BjQ=","6WTvWQ72AaZBYOVSmaxaci9tc1dW5p7IK9Kscjj2cb0=","vAy46VJ9Gp8QqG/Px4J1mj8jL6ws4/A01UKRmMYfYek=","cdgbHR/E4DJsddPc\u002BTpzoUMOVNaFJZm33Pw7AxU9Ees=","4r4JGR4hS5m4rsLfuCSZxzrknTBxKFkLQDXc\u002B2KbqTU=","yVoZ4UnBcSOapsJIi046hnn7ylD3jAcEBUxQ\u002Brkvj/4=","/GfbpJthEWmsuz0uFx1QLHM7gyM1wLLeQgAIl4SzUD4=","i5\u002B5LcfxQD8meRAkQbVf4wMvjxSE4\u002BjCd2/FdPtMpms=","AvSkxVPIg0GjnB1RJ4hDNyo9p9GONrzDs8uVuixH\u002BOE=","IgT9pOgRnK37qfILj2QcjFoBZ180HMt\u002BScgje2iYOo4=","ezUlOMzNZmyKDIe1wwXqvX\u002BvhwfB992xNVts7r2zcTc=","y2BV4WpkQuLfqQhfOQBtmuzh940c3s4LAopGKfztfTE=","lHTUEsMkDu8nqXtfTwl7FRfgocyyc7RI5O/edTHN1\u002B0=","A7nz7qgOtQ1CwZZLvNnr0b5QZB3fTi3y4i6y7rBIcxQ=","znnuRi2tsk7AACuYo4WSgj7NcLriG4PKVaF4L35SvDk=","eeoSVF\u002BzWQgGKOM9hSCzmc0CNSUCyP/f6aJxLHiJ4A8=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","nt6JdXgYN0sYJ/7di0B2aSGDokBPJnFqtwyBcMkycYI="],"CachedAssets":{},"CachedCopyCandidates":{}} | ||||
		Reference in New Issue
	
	Block a user