- Aggiornamento alla versione 5.0.0-preview.25503.2 di Microsoft.ML. - Aggiornamento alla versione 33.1.0 di CsvHelper. - Aggiornamento alla versione 13.0.4 di Newtonsoft.Json. - Aggiornamento alla versione 112.1.1-alpha.0.4 di RestSharp. - Sostituzione di System.Text.Json con Newtonsoft.Json. - Modifiche nei metodi per utilizzare JToken e JObject. - Aggiornamento dei file .csproj e packages.config. - Miglioramenti nella gestione delle eccezioni e nei log. - Rimozione di riferimenti inutilizzati e miglioramenti generali.
200 lines
8.8 KiB
C#
200 lines
8.8 KiB
C#
using System;
|
|
using System.Data.SqlClient;
|
|
using System.Linq;
|
|
using Newtonsoft.Json.Linq;
|
|
|
|
namespace HorseRacingPredictor.Football.Database
|
|
{
|
|
internal class Odds : HorseRacingPredictor.Football.Manager.Database
|
|
{
|
|
public void Upsert(SqlConnection connection, JToken bookmakers, int fixtureId)
|
|
{
|
|
try
|
|
{
|
|
// Aggiungiamo log per tracciare la struttura dei dati
|
|
LogError($"Inizio elaborazione quote per fixture {fixtureId} con {bookmakers?.Children().Count() ?? 0} bookmakers", null);
|
|
|
|
// Per ogni bookmaker
|
|
foreach (var bookmaker in bookmakers.Children())
|
|
{
|
|
int bookmakerId = bookmaker["id"].Value<int>();
|
|
var bets = bookmaker["bets"];
|
|
|
|
// Cerchiamo le quote di tipo Match Winner (1X2)
|
|
foreach (var bet in bets.Children())
|
|
{
|
|
// Gestiamo in modo più sicuro il recupero di valori dal JSON
|
|
string betName = GetStringValueSafe(bet, "name");
|
|
|
|
// Log per debug
|
|
LogError($"Elaborazione bet: '{betName}' per bookmaker {bookmakerId}", null);
|
|
|
|
// Determina il tipo di scommessa (assumiamo che esista una tabella BetType)
|
|
int betTypeId = GetBetTypeId(connection, betName);
|
|
|
|
// Se non riusciamo a determinare il tipo di scommessa, continuiamo con la prossima
|
|
if (betTypeId == 0) continue;
|
|
|
|
// Estrai e salva le quote
|
|
foreach (var value in bet["values"].Children())
|
|
{
|
|
// Gestiamo in modo più sicuro il recupero di valori dal JSON
|
|
string valueType = GetStringValueSafe(value, "value");
|
|
decimal oddValue = GetDecimalValueSafe(value, "odd");
|
|
|
|
// Log per debug
|
|
LogError($"Elaborazione quota: tipo={valueType}, valore={oddValue}", null);
|
|
|
|
if (oddValue > 0) // Verifichiamo che il valore sia valido
|
|
{
|
|
var query = @"
|
|
IF EXISTS (SELECT 1 FROM Odd WHERE fixture_id = @fixture_id AND bookmaker_id = @bookmaker_id
|
|
AND bet_type_id = @bet_type_id AND value = @value)
|
|
BEGIN
|
|
UPDATE Odd
|
|
SET odd = @odd, update_time = @update_time
|
|
WHERE fixture_id = @fixture_id AND bookmaker_id = @bookmaker_id
|
|
AND bet_type_id = @bet_type_id AND value = @value
|
|
END
|
|
ELSE
|
|
BEGIN
|
|
INSERT INTO Odd (fixture_id, bookmaker_id, bet_type_id, value, odd, update_time)
|
|
VALUES (@fixture_id, @bookmaker_id, @bet_type_id, @value, @odd, @update_time)
|
|
END";
|
|
|
|
using (var command = new SqlCommand(query, connection))
|
|
{
|
|
command.Parameters.AddWithValue("@fixture_id", fixtureId);
|
|
command.Parameters.AddWithValue("@bookmaker_id", bookmakerId);
|
|
command.Parameters.AddWithValue("@bet_type_id", betTypeId);
|
|
command.Parameters.AddWithValue("@value", valueType);
|
|
command.Parameters.AddWithValue("@odd", oddValue);
|
|
command.Parameters.AddWithValue("@update_time", DateTime.Now);
|
|
command.ExecuteNonQuery();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogError("l'upsert delle quote", ex);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Ottiene l'ID del tipo di scommessa in base al nome
|
|
/// </summary>
|
|
private int GetBetTypeId(SqlConnection connection, string betTypeName)
|
|
{
|
|
try
|
|
{
|
|
// Prima verifica se il tipo di scommessa esiste
|
|
var queryCheck = "SELECT bet_type_id FROM BetType WHERE name = @name";
|
|
using (var command = new SqlCommand(queryCheck, connection))
|
|
{
|
|
command.Parameters.AddWithValue("@name", betTypeName);
|
|
var result = command.ExecuteScalar();
|
|
|
|
if (result != null && result != DBNull.Value)
|
|
{
|
|
return Convert.ToInt32(result);
|
|
}
|
|
else
|
|
{
|
|
// Se non esiste, inseriscilo (con un ID progressivo)
|
|
var queryInsert = @"
|
|
DECLARE @next_id INT;
|
|
SELECT @next_id = ISNULL(MAX(bet_type_id), 0) + 1 FROM BetType;
|
|
|
|
INSERT INTO BetType (bet_type_id, name)
|
|
VALUES (@next_id, @name);
|
|
|
|
SELECT @next_id;";
|
|
|
|
using (var insertCommand = new SqlCommand(queryInsert, connection))
|
|
{
|
|
insertCommand.Parameters.AddWithValue("@name", betTypeName);
|
|
return Convert.ToInt32(insertCommand.ExecuteScalar());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogError($"determinazione bet_type_id per '{betTypeName}'", ex);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Ottiene un valore stringa da un JToken in modo sicuro
|
|
/// </summary>
|
|
private string GetStringValueSafe(JToken node, string propertyName)
|
|
{
|
|
try
|
|
{
|
|
if (node == null || node[propertyName] == null)
|
|
return string.Empty;
|
|
|
|
var value = node[propertyName];
|
|
|
|
// Gestiamo diversi tipi di nodi
|
|
if (value.Type == JTokenType.String)
|
|
return value.Value<string>();
|
|
else if (value.Type == JTokenType.Float || value.Type == JTokenType.Integer)
|
|
return value.Value<decimal>().ToString();
|
|
else
|
|
return value.ToString();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogError($"estrazione valore stringa per proprietà '{propertyName}'", ex);
|
|
return string.Empty;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Ottiene un valore decimale da un JToken in modo sicuro
|
|
/// </summary>
|
|
private decimal GetDecimalValueSafe(JToken node, string propertyName)
|
|
{
|
|
try
|
|
{
|
|
if (node == null || node[propertyName] == null)
|
|
return 0;
|
|
|
|
var value = node[propertyName];
|
|
|
|
// Gestiamo diversi tipi di nodi
|
|
if (value.Type == JTokenType.Float || value.Type == JTokenType.Integer)
|
|
{
|
|
// Assicuriamoci che il valore sia esattamente quello originale
|
|
return value.Value<decimal>();
|
|
}
|
|
else if (value.Type == JTokenType.String)
|
|
{
|
|
// Utilizziamo InvariantCulture per garantire una corretta interpretazione dei decimali
|
|
if (decimal.TryParse(value.Value<string>(),
|
|
System.Globalization.NumberStyles.Any,
|
|
System.Globalization.CultureInfo.InvariantCulture,
|
|
out decimal result))
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
|
|
// Aggiungiamo un log più dettagliato per aiutare il debug
|
|
LogError($"Impossibile convertire '{value}' (tipo: {value.Type}) in decimal per proprietà '{propertyName}'", null);
|
|
return 0;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogError($"estrazione valore decimal per proprietà '{propertyName}'", ex);
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
}
|