Aggiorna gestione JSON e aggiungi controlli UI moderni

Sostituito System.Text.Json con Newtonsoft.Json (JToken) nei database manager per maggiore compatibilità e robustezza.
Aggiunti nuovi controlli personalizzati (ModernButton, ModernDataGridView, ModernDateTimePicker, ModernLabel, ModernPanel, ModernProgressBar, ModernTabControl, ModernTextBox) per un'interfaccia moderna a tema scuro.
Aggiornate e aggiunte dipendenze NuGet (CsvHelper, Microsoft.ML, Newtonsoft.Json, RestSharp, ecc.).
Rimossa una using non utilizzata in API.cs.
This commit is contained in:
2026-02-25 20:00:09 +01:00
23 changed files with 883 additions and 167 deletions

View File

@@ -1,20 +1,16 @@
using System; using System;
using System.Collections.Generic;
using System.Data.SqlClient; using System.Data.SqlClient;
using System.Linq; using Newtonsoft.Json.Linq;
using System.Text;
using System.Text.Json.Nodes;
using System.Threading.Tasks;
namespace HorseRacingPredictor.Football.Database namespace HorseRacingPredictor.Football.Database
{ {
internal class BetType : HorseRacingPredictor.Football.Manager.Database internal class BetType : HorseRacingPredictor.Football.Manager.Database
{ {
public void Upsert(SqlConnection connection, JsonNode betType) public void Upsert(SqlConnection connection, JToken betType)
{ {
try try
{ {
var id = betType["id"]?.GetValue<int>(); var id = betType["id"]?.Value<int>();
if (id == null) return; // Salta il record se l'id è null if (id == null) return; // Salta il record se l'id è null
var query = @" var query = @"
@@ -29,7 +25,7 @@ namespace HorseRacingPredictor.Football.Database
using (var command = new SqlCommand(query, connection)) using (var command = new SqlCommand(query, connection))
{ {
command.Parameters.AddWithValue("@bet_type_id", id); command.Parameters.AddWithValue("@bet_type_id", id);
command.Parameters.AddWithValue("@name", betType["name"]?.GetValue<string>() ?? ""); command.Parameters.AddWithValue("@name", betType["name"]?.Value<string>() ?? "");
command.ExecuteNonQuery(); command.ExecuteNonQuery();
} }
} }

View File

@@ -1,20 +1,16 @@
using System; using System;
using System.Collections.Generic;
using System.Data.SqlClient; using System.Data.SqlClient;
using System.Linq; using Newtonsoft.Json.Linq;
using System.Text;
using System.Text.Json.Nodes;
using System.Threading.Tasks;
namespace HorseRacingPredictor.Football.Database namespace HorseRacingPredictor.Football.Database
{ {
internal class Bookmaker : HorseRacingPredictor.Football.Manager.Database internal class Bookmaker : HorseRacingPredictor.Football.Manager.Database
{ {
public void Upsert(SqlConnection connection, JsonNode bookmaker) public void Upsert(SqlConnection connection, JToken bookmaker)
{ {
try try
{ {
var id = bookmaker["id"]?.GetValue<int>(); var id = bookmaker["id"]?.Value<int>();
if (id == null) return; // Salta il record se l'id è null if (id == null) return; // Salta il record se l'id è null
var query = @" var query = @"
@@ -29,7 +25,7 @@ namespace HorseRacingPredictor.Football.Database
using (var command = new SqlCommand(query, connection)) using (var command = new SqlCommand(query, connection))
{ {
command.Parameters.AddWithValue("@bookmaker_id", id); command.Parameters.AddWithValue("@bookmaker_id", id);
command.Parameters.AddWithValue("@name", bookmaker["name"]?.GetValue<string>() ?? ""); command.Parameters.AddWithValue("@name", bookmaker["name"]?.Value<string>() ?? "");
command.ExecuteNonQuery(); command.ExecuteNonQuery();
} }
} }

View File

@@ -1,16 +1,12 @@
using System; using System;
using System.Collections.Generic;
using System.Data.SqlClient; using System.Data.SqlClient;
using System.Linq; using Newtonsoft.Json.Linq;
using System.Text;
using System.Text.Json.Nodes;
using System.Threading.Tasks;
namespace HorseRacingPredictor.Football.Database namespace HorseRacingPredictor.Football.Database
{ {
internal class Comparison : HorseRacingPredictor.Football.Manager.Database internal class Comparison : HorseRacingPredictor.Football.Manager.Database
{ {
public void Upsert(SqlConnection connection, int predictionId, JsonNode comparison) public void Upsert(SqlConnection connection, int predictionId, JToken comparison)
{ {
try try
{ {
@@ -56,20 +52,20 @@ namespace HorseRacingPredictor.Football.Database
command.Parameters.AddWithValue("@prediction_id", predictionId); command.Parameters.AddWithValue("@prediction_id", predictionId);
// Aggiungi tutti i parametri del confronto // Aggiungi tutti i parametri del confronto
command.Parameters.AddWithValue("@form_home", comparison["form"]?["home"]?.GetValue<string>() ?? (object)DBNull.Value); command.Parameters.AddWithValue("@form_home", comparison["form"]?["home"]?.Value<string>() ?? (object)DBNull.Value);
command.Parameters.AddWithValue("@form_away", comparison["form"]?["away"]?.GetValue<string>() ?? (object)DBNull.Value); command.Parameters.AddWithValue("@form_away", comparison["form"]?["away"]?.Value<string>() ?? (object)DBNull.Value);
command.Parameters.AddWithValue("@att_home", comparison["att"]?["home"]?.GetValue<string>() ?? (object)DBNull.Value); command.Parameters.AddWithValue("@att_home", comparison["att"]?["home"]?.Value<string>() ?? (object)DBNull.Value);
command.Parameters.AddWithValue("@att_away", comparison["att"]?["away"]?.GetValue<string>() ?? (object)DBNull.Value); command.Parameters.AddWithValue("@att_away", comparison["att"]?["away"]?.Value<string>() ?? (object)DBNull.Value);
command.Parameters.AddWithValue("@def_home", comparison["def"]?["home"]?.GetValue<string>() ?? (object)DBNull.Value); command.Parameters.AddWithValue("@def_home", comparison["def"]?["home"]?.Value<string>() ?? (object)DBNull.Value);
command.Parameters.AddWithValue("@def_away", comparison["def"]?["away"]?.GetValue<string>() ?? (object)DBNull.Value); command.Parameters.AddWithValue("@def_away", comparison["def"]?["away"]?.Value<string>() ?? (object)DBNull.Value);
command.Parameters.AddWithValue("@poisson_home", comparison["poisson_distribution"]?["home"]?.GetValue<string>() ?? (object)DBNull.Value); command.Parameters.AddWithValue("@poisson_home", comparison["poisson_distribution"]?["home"]?.Value<string>() ?? (object)DBNull.Value);
command.Parameters.AddWithValue("@poisson_away", comparison["poisson_distribution"]?["away"]?.GetValue<string>() ?? (object)DBNull.Value); command.Parameters.AddWithValue("@poisson_away", comparison["poisson_distribution"]?["away"]?.Value<string>() ?? (object)DBNull.Value);
command.Parameters.AddWithValue("@h2h_home", comparison["h2h"]?["home"]?.GetValue<string>() ?? (object)DBNull.Value); command.Parameters.AddWithValue("@h2h_home", comparison["h2h"]?["home"]?.Value<string>() ?? (object)DBNull.Value);
command.Parameters.AddWithValue("@h2h_away", comparison["h2h"]?["away"]?.GetValue<string>() ?? (object)DBNull.Value); command.Parameters.AddWithValue("@h2h_away", comparison["h2h"]?["away"]?.Value<string>() ?? (object)DBNull.Value);
command.Parameters.AddWithValue("@goals_home", comparison["goals"]?["home"]?.GetValue<string>() ?? (object)DBNull.Value); command.Parameters.AddWithValue("@goals_home", comparison["goals"]?["home"]?.Value<string>() ?? (object)DBNull.Value);
command.Parameters.AddWithValue("@goals_away", comparison["goals"]?["away"]?.GetValue<string>() ?? (object)DBNull.Value); command.Parameters.AddWithValue("@goals_away", comparison["goals"]?["away"]?.Value<string>() ?? (object)DBNull.Value);
command.Parameters.AddWithValue("@total_home", comparison["total"]?["home"]?.GetValue<string>() ?? (object)DBNull.Value); command.Parameters.AddWithValue("@total_home", comparison["total"]?["home"]?.Value<string>() ?? (object)DBNull.Value);
command.Parameters.AddWithValue("@total_away", comparison["total"]?["away"]?.GetValue<string>() ?? (object)DBNull.Value); command.Parameters.AddWithValue("@total_away", comparison["total"]?["away"]?.Value<string>() ?? (object)DBNull.Value);
command.ExecuteNonQuery(); command.ExecuteNonQuery();
} }

View File

@@ -1,17 +1,17 @@
using System; using System;
using System.Data; using System.Data;
using System.Data.SqlClient; using System.Data.SqlClient;
using System.Text.Json.Nodes; using Newtonsoft.Json.Linq;
namespace HorseRacingPredictor.Football.Database namespace HorseRacingPredictor.Football.Database
{ {
internal class Fixture : HorseRacingPredictor.Football.Manager.Database internal class Fixture : HorseRacingPredictor.Football.Manager.Database
{ {
public void Upsert(SqlConnection connection, SqlTransaction transaction, JsonNode fixture) public void Upsert(SqlConnection connection, SqlTransaction transaction, JToken fixture)
{ {
try try
{ {
var id = fixture["id"]?.GetValue<int>(); var id = fixture["id"]?.Value<int>();
if (id == null) return; // Salta il record se l'id è null if (id == null) return; // Salta il record se l'id è null
var query = @" var query = @"
@@ -63,20 +63,20 @@ namespace HorseRacingPredictor.Football.Database
// Parametri principali // Parametri principali
command.Parameters.AddWithValue("@fixture_id", id); command.Parameters.AddWithValue("@fixture_id", id);
command.Parameters.AddWithValue("@timezone", fixture["timezone"]?.GetValue<string>() ?? ""); command.Parameters.AddWithValue("@timezone", fixture["timezone"]?.Value<string>() ?? "");
command.Parameters.AddWithValue("@date", fixture["date"]?.GetValue<DateTime>() ?? DateTime.MinValue); command.Parameters.AddWithValue("@date", fixture["date"]?.Value<DateTime>() ?? DateTime.MinValue);
command.Parameters.AddWithValue("@timestamp", fixture["timestamp"]?.GetValue<long>() ?? 0L); command.Parameters.AddWithValue("@timestamp", fixture["timestamp"]?.Value<long>() ?? 0L);
command.Parameters.AddWithValue("@referee", fixture["referee"]?.GetValue<string>() ?? (object)DBNull.Value); command.Parameters.AddWithValue("@referee", fixture["referee"]?.Value<string>() ?? (object)DBNull.Value);
// Parametri venue // Parametri venue
int? venueId = venue?["id"]?.GetValue<int?>(); int? venueId = venue?["id"]?.Value<int?>();
command.Parameters.AddWithValue("@venue_id", venueId.HasValue ? (object)venueId.Value : DBNull.Value); command.Parameters.AddWithValue("@venue_id", venueId.HasValue ? (object)venueId.Value : DBNull.Value);
// Parametri status // Parametri status
command.Parameters.AddWithValue("@status_long", status?["long"]?.GetValue<string>() ?? ""); command.Parameters.AddWithValue("@status_long", status?["long"]?.Value<string>() ?? "");
command.Parameters.AddWithValue("@status_short", status?["short"]?.GetValue<string>() ?? ""); command.Parameters.AddWithValue("@status_short", status?["short"]?.Value<string>() ?? "");
int? elapsed = status?["elapsed"]?.GetValue<int?>(); int? elapsed = status?["elapsed"]?.Value<int?>();
int? extra = null; // Assumo che l'API restituisca questo valore, altrimenti va gestito come gli altri int? extra = null; // Assumo che l'API restituisca questo valore, altrimenti va gestito come gli altri
command.Parameters.AddWithValue("@status_elapsed", elapsed.HasValue ? (object)elapsed.Value : DBNull.Value); command.Parameters.AddWithValue("@status_elapsed", elapsed.HasValue ? (object)elapsed.Value : DBNull.Value);
@@ -101,11 +101,11 @@ namespace HorseRacingPredictor.Football.Database
/// <summary> /// <summary>
/// Metodo di supporto per inserire/aggiornare le informazioni sulla venue /// Metodo di supporto per inserire/aggiornare le informazioni sulla venue
/// </summary> /// </summary>
private void UpsertVenue(SqlConnection connection, SqlTransaction transaction, JsonNode venue) private void UpsertVenue(SqlConnection connection, SqlTransaction transaction, JToken venue)
{ {
try try
{ {
var id = venue["id"]?.GetValue<int>(); var id = venue["id"]?.Value<int>();
if (id == null) return; if (id == null) return;
var query = @" var query = @"
@@ -121,8 +121,8 @@ namespace HorseRacingPredictor.Football.Database
using (var command = new SqlCommand(query, connection, transaction)) using (var command = new SqlCommand(query, connection, transaction))
{ {
command.Parameters.AddWithValue("@venue_id", id); command.Parameters.AddWithValue("@venue_id", id);
command.Parameters.AddWithValue("@name", venue["name"]?.GetValue<string>() ?? ""); command.Parameters.AddWithValue("@name", venue["name"]?.Value<string>() ?? "");
command.Parameters.AddWithValue("@city", venue["city"]?.GetValue<string>() ?? ""); command.Parameters.AddWithValue("@city", venue["city"]?.Value<string>() ?? "");
command.ExecuteNonQuery(); command.ExecuteNonQuery();
} }
} }

View File

@@ -3,20 +3,20 @@ using System.Collections.Generic;
using System.Data.SqlClient; using System.Data.SqlClient;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Text.Json.Nodes; using Newtonsoft.Json.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace HorseRacingPredictor.Football.Database namespace HorseRacingPredictor.Football.Database
{ {
internal class FixtureLeague : HorseRacingPredictor.Football.Manager.Database internal class FixtureLeague : HorseRacingPredictor.Football.Manager.Database
{ {
public void Upsert(SqlConnection connection, SqlTransaction transaction, int fixtureId, int leagueId, JsonNode leagueData) public void Upsert(SqlConnection connection, SqlTransaction transaction, int fixtureId, int leagueId, JToken leagueData)
{ {
try try
{ {
// Estrai i valori prima della query per utilizzarli nel log // Estrai i valori prima della query per utilizzarli nel log
string round = leagueData["round"]?.GetValue<string>() ?? ""; string round = leagueData["round"]?.Value<string>() ?? "";
bool? standings = leagueData["standings"]?.GetValue<bool?>(); bool? standings = leagueData["standings"]?.Value<bool?>();
string standingsValue = standings.HasValue ? standings.Value.ToString() : "NULL"; string standingsValue = standings.HasValue ? standings.Value.ToString() : "NULL";
// Log dell'operazione prima di tentare l'upsert // Log dell'operazione prima di tentare l'upsert

View File

@@ -1,12 +1,12 @@
using System; using System;
using System.Data.SqlClient; using System.Data.SqlClient;
using System.Text.Json.Nodes; using Newtonsoft.Json.Linq;
namespace HorseRacingPredictor.Football.Database namespace HorseRacingPredictor.Football.Database
{ {
internal class Goals : HorseRacingPredictor.Football.Manager.Database internal class Goals : HorseRacingPredictor.Football.Manager.Database
{ {
public void Upsert(SqlConnection connection, JsonNode goals, int fixtureId) public void Upsert(SqlConnection connection, JToken goals, int fixtureId)
{ {
try try
{ {
@@ -27,8 +27,8 @@ namespace HorseRacingPredictor.Football.Database
END"; END";
using (var command = new SqlCommand(query, connection)) using (var command = new SqlCommand(query, connection))
{ {
command.Parameters.AddWithValue("@home", goals["home"]?.GetValue<int?>() ?? 0); command.Parameters.AddWithValue("@home", goals["home"]?.Value<int?>() ?? 0);
command.Parameters.AddWithValue("@away", goals["away"]?.GetValue<int?>() ?? 0); command.Parameters.AddWithValue("@away", goals["away"]?.Value<int?>() ?? 0);
command.Parameters.AddWithValue("@fixture_id", fixtureId); command.Parameters.AddWithValue("@fixture_id", fixtureId);
command.ExecuteNonQuery(); command.ExecuteNonQuery();
} }

View File

@@ -1,16 +1,16 @@
using System; using System;
using System.Data.SqlClient; using System.Data.SqlClient;
using System.Text.Json.Nodes; using Newtonsoft.Json.Linq;
namespace HorseRacingPredictor.Football.Database namespace HorseRacingPredictor.Football.Database
{ {
internal class League : HorseRacingPredictor.Football.Manager.Database internal class League : HorseRacingPredictor.Football.Manager.Database
{ {
public void Upsert(SqlConnection connection, JsonNode league) public void Upsert(SqlConnection connection, JToken league)
{ {
try try
{ {
var id = league["id"]?.GetValue<int>(); var id = league["id"]?.Value<int>();
if (id == null) return; // Salta il record se l'id è null if (id == null) return; // Salta il record se l'id è null
var query = @" var query = @"
@@ -25,11 +25,11 @@ namespace HorseRacingPredictor.Football.Database
using (var command = new SqlCommand(query, connection)) using (var command = new SqlCommand(query, connection))
{ {
command.Parameters.AddWithValue("@league_id", id); command.Parameters.AddWithValue("@league_id", id);
command.Parameters.AddWithValue("@name", league["name"]?.GetValue<string>() ?? ""); command.Parameters.AddWithValue("@name", league["name"]?.Value<string>() ?? "");
command.Parameters.AddWithValue("@country", league["country"]?.GetValue<string>() ?? ""); command.Parameters.AddWithValue("@country", league["country"]?.Value<string>() ?? "");
command.Parameters.AddWithValue("@logo", league["logo"]?.GetValue<string>() ?? ""); command.Parameters.AddWithValue("@logo", league["logo"]?.Value<string>() ?? "");
command.Parameters.AddWithValue("@flag", league["flag"]?.GetValue<string>() ?? ""); command.Parameters.AddWithValue("@flag", league["flag"]?.Value<string>() ?? "");
command.Parameters.AddWithValue("@season", league["season"]?.GetValue<int>() ?? 0); command.Parameters.AddWithValue("@season", league["season"]?.Value<int>() ?? 0);
command.ExecuteNonQuery(); command.ExecuteNonQuery();
} }
} }
@@ -39,11 +39,11 @@ namespace HorseRacingPredictor.Football.Database
} }
} }
public void Upsert(SqlConnection connection, SqlTransaction transaction, JsonNode league) public void Upsert(SqlConnection connection, SqlTransaction transaction, JToken league)
{ {
try try
{ {
var id = league["id"]?.GetValue<int>(); var id = league["id"]?.Value<int>();
if (id == null) return; // Salta il record se l'id è null if (id == null) return; // Salta il record se l'id è null
var query = @" var query = @"
@@ -58,11 +58,11 @@ namespace HorseRacingPredictor.Football.Database
using (var command = new SqlCommand(query, connection, transaction)) using (var command = new SqlCommand(query, connection, transaction))
{ {
command.Parameters.AddWithValue("@league_id", id); command.Parameters.AddWithValue("@league_id", id);
command.Parameters.AddWithValue("@name", league["name"]?.GetValue<string>() ?? ""); command.Parameters.AddWithValue("@name", league["name"]?.Value<string>() ?? "");
command.Parameters.AddWithValue("@country", league["country"]?.GetValue<string>() ?? ""); command.Parameters.AddWithValue("@country", league["country"]?.Value<string>() ?? "");
command.Parameters.AddWithValue("@logo", league["logo"]?.GetValue<string>() ?? ""); command.Parameters.AddWithValue("@logo", league["logo"]?.Value<string>() ?? "");
command.Parameters.AddWithValue("@flag", league["flag"]?.GetValue<string>() ?? ""); command.Parameters.AddWithValue("@flag", league["flag"]?.Value<string>() ?? "");
command.Parameters.AddWithValue("@season", league["season"]?.GetValue<int>() ?? 0); command.Parameters.AddWithValue("@season", league["season"]?.Value<int>() ?? 0);
command.ExecuteNonQuery(); command.ExecuteNonQuery();
} }
} }

View File

@@ -1,12 +1,12 @@
using System; using System;
using System.Data.SqlClient; using System.Data.SqlClient;
using System.Text.Json.Nodes; using Newtonsoft.Json.Linq;
namespace HorseRacingPredictor.Football.Database namespace HorseRacingPredictor.Football.Database
{ {
internal class LeagueStats : HorseRacingPredictor.Football.Manager.Database internal class LeagueStats : HorseRacingPredictor.Football.Manager.Database
{ {
public int Insert(SqlConnection connection, int? teamId, int? predictionId, bool isHome, JsonNode stats) public int Insert(SqlConnection connection, int? teamId, int? predictionId, bool isHome, JToken stats)
{ {
try try
{ {
@@ -35,27 +35,27 @@ namespace HorseRacingPredictor.Football.Database
command.Parameters.AddWithValue("@team_id", teamId.HasValue ? (object)teamId.Value : DBNull.Value); command.Parameters.AddWithValue("@team_id", teamId.HasValue ? (object)teamId.Value : DBNull.Value);
command.Parameters.AddWithValue("@prediction_id", predictionId.HasValue ? (object)predictionId.Value : DBNull.Value); command.Parameters.AddWithValue("@prediction_id", predictionId.HasValue ? (object)predictionId.Value : DBNull.Value);
command.Parameters.AddWithValue("@is_home", isHome); command.Parameters.AddWithValue("@is_home", isHome);
command.Parameters.AddWithValue("@form", stats["form"]?.GetValue<string>() ?? (object)DBNull.Value); command.Parameters.AddWithValue("@form", stats["form"]?.Value<string>() ?? (object)DBNull.Value);
var fixtures = stats["fixtures"]; var fixtures = stats["fixtures"];
command.Parameters.AddWithValue("@fixtures_played_home", fixtures?["played"]?["home"]?.GetValue<int?>() ?? (object)DBNull.Value); command.Parameters.AddWithValue("@fixtures_played_home", fixtures?["played"]?["home"]?.Value<int?>() ?? (object)DBNull.Value);
command.Parameters.AddWithValue("@fixtures_played_away", fixtures?["played"]?["away"]?.GetValue<int?>() ?? (object)DBNull.Value); command.Parameters.AddWithValue("@fixtures_played_away", fixtures?["played"]?["away"]?.Value<int?>() ?? (object)DBNull.Value);
command.Parameters.AddWithValue("@fixtures_played_total", fixtures?["played"]?["total"]?.GetValue<int?>() ?? (object)DBNull.Value); command.Parameters.AddWithValue("@fixtures_played_total", fixtures?["played"]?["total"]?.Value<int?>() ?? (object)DBNull.Value);
var wins = stats["fixtures"]?["wins"]; var wins = stats["fixtures"]?["wins"];
command.Parameters.AddWithValue("@wins_home", wins?["home"]?.GetValue<int?>() ?? (object)DBNull.Value); command.Parameters.AddWithValue("@wins_home", wins?["home"]?.Value<int?>() ?? (object)DBNull.Value);
command.Parameters.AddWithValue("@wins_away", wins?["away"]?.GetValue<int?>() ?? (object)DBNull.Value); command.Parameters.AddWithValue("@wins_away", wins?["away"]?.Value<int?>() ?? (object)DBNull.Value);
command.Parameters.AddWithValue("@wins_total", wins?["total"]?.GetValue<int?>() ?? (object)DBNull.Value); command.Parameters.AddWithValue("@wins_total", wins?["total"]?.Value<int?>() ?? (object)DBNull.Value);
var draws = stats["fixtures"]?["draws"]; var draws = stats["fixtures"]?["draws"];
command.Parameters.AddWithValue("@draws_home", draws?["home"]?.GetValue<int?>() ?? (object)DBNull.Value); command.Parameters.AddWithValue("@draws_home", draws?["home"]?.Value<int?>() ?? (object)DBNull.Value);
command.Parameters.AddWithValue("@draws_away", draws?["away"]?.GetValue<int?>() ?? (object)DBNull.Value); command.Parameters.AddWithValue("@draws_away", draws?["away"]?.Value<int?>() ?? (object)DBNull.Value);
command.Parameters.AddWithValue("@draws_total", draws?["total"]?.GetValue<int?>() ?? (object)DBNull.Value); command.Parameters.AddWithValue("@draws_total", draws?["total"]?.Value<int?>() ?? (object)DBNull.Value);
var loses = stats["fixtures"]?["loses"]; var loses = stats["fixtures"]?["loses"];
command.Parameters.AddWithValue("@loses_home", loses?["home"]?.GetValue<int?>() ?? (object)DBNull.Value); command.Parameters.AddWithValue("@loses_home", loses?["home"]?.Value<int?>() ?? (object)DBNull.Value);
command.Parameters.AddWithValue("@loses_away", loses?["away"]?.GetValue<int?>() ?? (object)DBNull.Value); command.Parameters.AddWithValue("@loses_away", loses?["away"]?.Value<int?>() ?? (object)DBNull.Value);
command.Parameters.AddWithValue("@loses_total", loses?["total"]?.GetValue<int?>() ?? (object)DBNull.Value); command.Parameters.AddWithValue("@loses_total", loses?["total"]?.Value<int?>() ?? (object)DBNull.Value);
command.ExecuteNonQuery(); command.ExecuteNonQuery();
} }

View File

@@ -1,26 +1,27 @@
using System; using System;
using System.Data.SqlClient; using System.Data.SqlClient;
using System.Text.Json.Nodes; using System.Linq;
using Newtonsoft.Json.Linq;
namespace HorseRacingPredictor.Football.Database namespace HorseRacingPredictor.Football.Database
{ {
internal class Odds : HorseRacingPredictor.Football.Manager.Database internal class Odds : HorseRacingPredictor.Football.Manager.Database
{ {
public void Upsert(SqlConnection connection, JsonNode bookmakers, int fixtureId) public void Upsert(SqlConnection connection, JToken bookmakers, int fixtureId)
{ {
try try
{ {
// Aggiungiamo log per tracciare la struttura dei dati // Aggiungiamo log per tracciare la struttura dei dati
LogError($"Inizio elaborazione quote per fixture {fixtureId} con {bookmakers?.AsArray().Count ?? 0} bookmakers", null); LogError($"Inizio elaborazione quote per fixture {fixtureId} con {bookmakers?.Children().Count() ?? 0} bookmakers", null);
// Per ogni bookmaker // Per ogni bookmaker
foreach (var bookmaker in bookmakers.AsArray()) foreach (var bookmaker in bookmakers.Children())
{ {
int bookmakerId = bookmaker["id"].GetValue<int>(); int bookmakerId = bookmaker["id"].Value<int>();
var bets = bookmaker["bets"]; var bets = bookmaker["bets"];
// Cerchiamo le quote di tipo Match Winner (1X2) // Cerchiamo le quote di tipo Match Winner (1X2)
foreach (var bet in bets.AsArray()) foreach (var bet in bets.Children())
{ {
// Gestiamo in modo più sicuro il recupero di valori dal JSON // Gestiamo in modo più sicuro il recupero di valori dal JSON
string betName = GetStringValueSafe(bet, "name"); string betName = GetStringValueSafe(bet, "name");
@@ -35,7 +36,7 @@ namespace HorseRacingPredictor.Football.Database
if (betTypeId == 0) continue; if (betTypeId == 0) continue;
// Estrai e salva le quote // Estrai e salva le quote
foreach (var value in bet["values"].AsArray()) foreach (var value in bet["values"].Children())
{ {
// Gestiamo in modo più sicuro il recupero di valori dal JSON // Gestiamo in modo più sicuro il recupero di valori dal JSON
string valueType = GetStringValueSafe(value, "value"); string valueType = GetStringValueSafe(value, "value");
@@ -128,9 +129,9 @@ namespace HorseRacingPredictor.Football.Database
} }
/// <summary> /// <summary>
/// Ottiene un valore stringa da un JsonNode in modo sicuro /// Ottiene un valore stringa da un JToken in modo sicuro
/// </summary> /// </summary>
private string GetStringValueSafe(JsonNode node, string propertyName) private string GetStringValueSafe(JToken node, string propertyName)
{ {
try try
{ {
@@ -140,10 +141,10 @@ namespace HorseRacingPredictor.Football.Database
var value = node[propertyName]; var value = node[propertyName];
// Gestiamo diversi tipi di nodi // Gestiamo diversi tipi di nodi
if (value.GetValueKind() == System.Text.Json.JsonValueKind.String) if (value.Type == JTokenType.String)
return value.GetValue<string>(); return value.Value<string>();
else if (value.GetValueKind() == System.Text.Json.JsonValueKind.Number) else if (value.Type == JTokenType.Float || value.Type == JTokenType.Integer)
return value.GetValue<decimal>().ToString(); return value.Value<decimal>().ToString();
else else
return value.ToString(); return value.ToString();
} }
@@ -155,9 +156,9 @@ namespace HorseRacingPredictor.Football.Database
} }
/// <summary> /// <summary>
/// Ottiene un valore decimale da un JsonNode in modo sicuro /// Ottiene un valore decimale da un JToken in modo sicuro
/// </summary> /// </summary>
private decimal GetDecimalValueSafe(JsonNode node, string propertyName) private decimal GetDecimalValueSafe(JToken node, string propertyName)
{ {
try try
{ {
@@ -167,15 +168,15 @@ namespace HorseRacingPredictor.Football.Database
var value = node[propertyName]; var value = node[propertyName];
// Gestiamo diversi tipi di nodi // Gestiamo diversi tipi di nodi
if (value.GetValueKind() == System.Text.Json.JsonValueKind.Number) if (value.Type == JTokenType.Float || value.Type == JTokenType.Integer)
{ {
// Assicuriamoci che il valore sia esattamente quello originale // Assicuriamoci che il valore sia esattamente quello originale
return value.GetValue<decimal>(); return value.Value<decimal>();
} }
else if (value.GetValueKind() == System.Text.Json.JsonValueKind.String) else if (value.Type == JTokenType.String)
{ {
// Utilizziamo InvariantCulture per garantire una corretta interpretazione dei decimali // Utilizziamo InvariantCulture per garantire una corretta interpretazione dei decimali
if (decimal.TryParse(value.GetValue<string>(), if (decimal.TryParse(value.Value<string>(),
System.Globalization.NumberStyles.Any, System.Globalization.NumberStyles.Any,
System.Globalization.CultureInfo.InvariantCulture, System.Globalization.CultureInfo.InvariantCulture,
out decimal result)) out decimal result))
@@ -185,7 +186,7 @@ namespace HorseRacingPredictor.Football.Database
} }
// Aggiungiamo un log più dettagliato per aiutare il debug // Aggiungiamo un log più dettagliato per aiutare il debug
LogError($"Impossibile convertire '{value}' (tipo: {value.GetValueKind()}) in decimal per proprietà '{propertyName}'", null); LogError($"Impossibile convertire '{value}' (tipo: {value.Type}) in decimal per proprietà '{propertyName}'", null);
return 0; return 0;
} }
catch (Exception ex) catch (Exception ex)

View File

@@ -1,30 +1,30 @@
using System; using System;
using System.Data.SqlClient; using System.Data.SqlClient;
using System.Text.Json.Nodes; using Newtonsoft.Json.Linq;
namespace HorseRacingPredictor.Football.Database namespace HorseRacingPredictor.Football.Database
{ {
internal class Prediction : HorseRacingPredictor.Football.Manager.Database internal class Prediction : HorseRacingPredictor.Football.Manager.Database
{ {
public void Upsert(SqlConnection connection, JsonNode predictions, int fixtureId) public void Upsert(SqlConnection connection, JToken predictions, int fixtureId)
{ {
try try
{ {
// Estrazione dei dati dalla risposta JSON // Estrazione dei dati dalla risposta JSON
string advice = predictions["advice"]?.GetValue<string>(); string advice = predictions["advice"]?.Value<string>();
if (string.IsNullOrEmpty(advice)) return; // Nessuna previsione se non c'è consiglio if (string.IsNullOrEmpty(advice)) return; // Nessuna previsione se non c'è consiglio
// Estrazione degli altri valori, con gestione null // Estrazione degli altri valori, con gestione null
int? winnerId = predictions["winner"]?["id"]?.GetValue<int?>(); int? winnerId = predictions["winner"]?["id"]?.Value<int?>();
string winnerName = predictions["winner"]?["name"]?.GetValue<string>(); string winnerName = predictions["winner"]?["name"]?.Value<string>();
string winnerComment = predictions["winner"]?["comment"]?.GetValue<string>(); string winnerComment = predictions["winner"]?["comment"]?.Value<string>();
bool? winOrDraw = predictions["win_or_draw"]?.GetValue<bool?>(); bool? winOrDraw = predictions["win_or_draw"]?.Value<bool?>();
string underOver = predictions["under_over"]?.GetValue<string>(); string underOver = predictions["under_over"]?.Value<string>();
string goalsHome = predictions["goals"]?["home"]?.GetValue<string>(); string goalsHome = predictions["goals"]?["home"]?.Value<string>();
string goalsAway = predictions["goals"]?["away"]?.GetValue<string>(); string goalsAway = predictions["goals"]?["away"]?.Value<string>();
string percentHome = predictions["percent"]?["home"]?.GetValue<string>(); string percentHome = predictions["percent"]?["home"]?.Value<string>();
string percentDraw = predictions["percent"]?["draw"]?.GetValue<string>(); string percentDraw = predictions["percent"]?["draw"]?.Value<string>();
string percentAway = predictions["percent"]?["away"]?.GetValue<string>(); string percentAway = predictions["percent"]?["away"]?.Value<string>();
// Query per l'upsert con tutti i campi disponibili // Query per l'upsert con tutti i campi disponibili
var query = @" var query = @"

View File

@@ -1,12 +1,12 @@
using System; using System;
using System.Data.SqlClient; using System.Data.SqlClient;
using System.Text.Json.Nodes; using Newtonsoft.Json.Linq;
namespace HorseRacingPredictor.Football.Database namespace HorseRacingPredictor.Football.Database
{ {
internal class Score : HorseRacingPredictor.Football.Manager.Database internal class Score : HorseRacingPredictor.Football.Manager.Database
{ {
public void Upsert(SqlConnection connection, JsonNode score, int fixtureId) public void Upsert(SqlConnection connection, JToken score, int fixtureId)
{ {
try try
{ {
@@ -26,14 +26,14 @@ namespace HorseRacingPredictor.Football.Database
END"; END";
using (var command = new SqlCommand(query, connection)) using (var command = new SqlCommand(query, connection))
{ {
command.Parameters.AddWithValue("@home_halftime", score["halftime"]["home"]?.GetValue<int?>() ?? 0); command.Parameters.AddWithValue("@home_halftime", score["halftime"]?["home"]?.Value<int?>() ?? 0);
command.Parameters.AddWithValue("@away_halftime", score["halftime"]["away"]?.GetValue<int?>() ?? 0); command.Parameters.AddWithValue("@away_halftime", score["halftime"]?["away"]?.Value<int?>() ?? 0);
command.Parameters.AddWithValue("@home_fulltime", score["fulltime"]["home"]?.GetValue<int?>() ?? 0); command.Parameters.AddWithValue("@home_fulltime", score["fulltime"]?["home"]?.Value<int?>() ?? 0);
command.Parameters.AddWithValue("@away_fulltime", score["fulltime"]["away"]?.GetValue<int?>() ?? 0); command.Parameters.AddWithValue("@away_fulltime", score["fulltime"]?["away"]?.Value<int?>() ?? 0);
command.Parameters.AddWithValue("@home_extratime", score["extratime"]["home"]?.GetValue<int?>() ?? 0); command.Parameters.AddWithValue("@home_extratime", score["extratime"]?["home"]?.Value<int?>() ?? 0);
command.Parameters.AddWithValue("@away_extratime", score["extratime"]["away"]?.GetValue<int?>() ?? 0); command.Parameters.AddWithValue("@away_extratime", score["extratime"]?["away"]?.Value<int?>() ?? 0);
command.Parameters.AddWithValue("@home_penalty", score["penalty"]["home"]?.GetValue<int?>() ?? 0); command.Parameters.AddWithValue("@home_penalty", score["penalty"]?["home"]?.Value<int?>() ?? 0);
command.Parameters.AddWithValue("@away_penalty", score["penalty"]["away"]?.GetValue<int?>() ?? 0); command.Parameters.AddWithValue("@away_penalty", score["penalty"]?["away"]?.Value<int?>() ?? 0);
command.Parameters.AddWithValue("@fixture_id", fixtureId); command.Parameters.AddWithValue("@fixture_id", fixtureId);
command.ExecuteNonQuery(); command.ExecuteNonQuery();
} }

View File

@@ -1,17 +1,17 @@
using System; using System;
using System.Data.SqlClient; using System.Data.SqlClient;
using System.Text.Json.Nodes; using Newtonsoft.Json.Linq;
namespace HorseRacingPredictor.Football.Database namespace HorseRacingPredictor.Football.Database
{ {
internal class Team : HorseRacingPredictor.Football.Manager.Database internal class Team : HorseRacingPredictor.Football.Manager.Database
{ {
public void UpsertTeams(SqlConnection connection, SqlTransaction transaction, JsonNode teams, int fixtureId) public void UpsertTeams(SqlConnection connection, SqlTransaction transaction, JToken teams, int fixtureId)
{ {
try try
{ {
var homeTeamId = teams["home"]["id"]?.GetValue<int>(); var homeTeamId = teams["home"]["id"]?.Value<int>();
var awayTeamId = teams["away"]["id"]?.GetValue<int>(); var awayTeamId = teams["away"]["id"]?.Value<int>();
if (homeTeamId == null || awayTeamId == null) return; // Salta il record se uno degli id è null if (homeTeamId == null || awayTeamId == null) return; // Salta il record se uno degli id è null
var queryTeam = @" var queryTeam = @"
@@ -31,14 +31,14 @@ namespace HorseRacingPredictor.Football.Database
// Upsert home team // Upsert home team
command.Parameters.AddWithValue("@team_id", homeTeamId); command.Parameters.AddWithValue("@team_id", homeTeamId);
command.Parameters.AddWithValue("@name", homeTeam["name"]?.GetValue<string>() ?? ""); command.Parameters.AddWithValue("@name", homeTeam["name"]?.Value<string>() ?? "");
command.Parameters.AddWithValue("@logo", homeTeam["logo"]?.GetValue<string>() ?? ""); command.Parameters.AddWithValue("@logo", homeTeam["logo"]?.Value<string>() ?? "");
command.ExecuteNonQuery(); command.ExecuteNonQuery();
// Upsert away team // Upsert away team
command.Parameters["@team_id"].Value = awayTeamId; command.Parameters["@team_id"].Value = awayTeamId;
command.Parameters["@name"].Value = awayTeam["name"]?.GetValue<string>() ?? ""; command.Parameters["@name"].Value = awayTeam["name"]?.Value<string>() ?? "";
command.Parameters["@logo"].Value = awayTeam["logo"]?.GetValue<string>() ?? ""; command.Parameters["@logo"].Value = awayTeam["logo"]?.Value<string>() ?? "";
command.ExecuteNonQuery(); command.ExecuteNonQuery();
} }

View File

@@ -1,16 +1,12 @@
using System; using System;
using System.Collections.Generic;
using System.Data.SqlClient; using System.Data.SqlClient;
using System.Linq; using Newtonsoft.Json.Linq;
using System.Text;
using System.Text.Json.Nodes;
using System.Threading.Tasks;
namespace HorseRacingPredictor.Football.Database namespace HorseRacingPredictor.Football.Database
{ {
internal class TeamStats : HorseRacingPredictor.Football.Manager.Database internal class TeamStats : HorseRacingPredictor.Football.Manager.Database
{ {
public int Insert(SqlConnection connection, int? teamId, int? predictionId, bool isHome, JsonNode stats) public int Insert(SqlConnection connection, int? teamId, int? predictionId, bool isHome, JToken stats)
{ {
try try
{ {
@@ -35,18 +31,18 @@ namespace HorseRacingPredictor.Football.Database
command.Parameters.AddWithValue("@team_id", teamId.HasValue ? (object)teamId.Value : DBNull.Value); command.Parameters.AddWithValue("@team_id", teamId.HasValue ? (object)teamId.Value : DBNull.Value);
command.Parameters.AddWithValue("@prediction_id", predictionId.HasValue ? (object)predictionId.Value : DBNull.Value); command.Parameters.AddWithValue("@prediction_id", predictionId.HasValue ? (object)predictionId.Value : DBNull.Value);
command.Parameters.AddWithValue("@is_home", isHome); command.Parameters.AddWithValue("@is_home", isHome);
command.Parameters.AddWithValue("@played", stats["played"]?.GetValue<int?>() ?? (object)DBNull.Value); command.Parameters.AddWithValue("@played", stats["played"]?.Value<int?>() ?? (object)DBNull.Value);
command.Parameters.AddWithValue("@form", stats["form"]?.GetValue<string>() ?? (object)DBNull.Value); command.Parameters.AddWithValue("@form", stats["form"]?.Value<string>() ?? (object)DBNull.Value);
command.Parameters.AddWithValue("@att", stats["att"]?.GetValue<string>() ?? (object)DBNull.Value); command.Parameters.AddWithValue("@att", stats["att"]?.Value<string>() ?? (object)DBNull.Value);
command.Parameters.AddWithValue("@def", stats["def"]?.GetValue<string>() ?? (object)DBNull.Value); command.Parameters.AddWithValue("@def", stats["def"]?.Value<string>() ?? (object)DBNull.Value);
var goalsFor = stats["goals"]?["for"]; var goalsFor = stats["goals"]?["for"];
command.Parameters.AddWithValue("@goals_for_total", goalsFor?["total"]?.GetValue<int?>() ?? (object)DBNull.Value); command.Parameters.AddWithValue("@goals_for_total", goalsFor?["total"]?.Value<int?>() ?? (object)DBNull.Value);
command.Parameters.AddWithValue("@goals_for_average", goalsFor?["average"]?.GetValue<string>() ?? (object)DBNull.Value); command.Parameters.AddWithValue("@goals_for_average", goalsFor?["average"]?.Value<string>() ?? (object)DBNull.Value);
var goalsAgainst = stats["goals"]?["against"]; var goalsAgainst = stats["goals"]?["against"];
command.Parameters.AddWithValue("@goals_against_total", goalsAgainst?["total"]?.GetValue<int?>() ?? (object)DBNull.Value); command.Parameters.AddWithValue("@goals_against_total", goalsAgainst?["total"]?.Value<int?>() ?? (object)DBNull.Value);
command.Parameters.AddWithValue("@goals_against_average", goalsAgainst?["average"]?.GetValue<string>() ?? (object)DBNull.Value); command.Parameters.AddWithValue("@goals_against_average", goalsAgainst?["average"]?.Value<string>() ?? (object)DBNull.Value);
command.ExecuteNonQuery(); command.ExecuteNonQuery();
} }

View File

@@ -2,7 +2,6 @@ using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using RestSharp; using RestSharp;
using HorseRacingPredictor.Football.Database; using HorseRacingPredictor.Football.Database;
using HorseRacingPredictor.Football.API;
using League = HorseRacingPredictor.Football.API.League; using League = HorseRacingPredictor.Football.API.League;
using Fixture = HorseRacingPredictor.Football.API.Fixture; using Fixture = HorseRacingPredictor.Football.API.Fixture;

View File

@@ -0,0 +1,107 @@
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace BettingPredictor.UI.Controls
{
/// <summary>
/// Pulsante moderno con tema scuro e effetti hover
/// </summary>
public class ModernButton : Button
{
private bool isHovering = false;
private Color normalColor = ModernTheme.Colors.AccentPrimary;
private Color hoverColor = ModernTheme.Colors.AccentSecondary;
private int borderRadius = ModernTheme.BorderRadius.Medium;
public ModernButton()
{
// Configurazione base
FlatStyle = FlatStyle.Flat;
FlatAppearance.BorderSize = 0;
BackColor = normalColor;
ForeColor = ModernTheme.Colors.TextPrimary;
Font = ModernTheme.Fonts.ButtonFont;
Cursor = Cursors.Hand;
Size = new Size(100, 35);
// Abilita il double buffering per evitare flickering
SetStyle(ControlStyles.UserPaint |
ControlStyles.AllPaintingInWmPaint |
ControlStyles.OptimizedDoubleBuffer, true);
}
public Color NormalColor
{
get => normalColor;
set
{
normalColor = value;
if (!isHovering) BackColor = value;
}
}
public Color HoverColor
{
get => hoverColor;
set => hoverColor = value;
}
public int BorderRadius
{
get => borderRadius;
set
{
borderRadius = value;
Invalidate();
}
}
protected override void OnMouseEnter(EventArgs e)
{
base.OnMouseEnter(e);
isHovering = true;
BackColor = hoverColor;
}
protected override void OnMouseLeave(EventArgs e)
{
base.OnMouseLeave(e);
isHovering = false;
BackColor = normalColor;
}
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
// Disegna il background con bordi arrotondati
using (GraphicsPath path = GetRoundedRectangle(ClientRectangle, borderRadius))
{
using (SolidBrush brush = new SolidBrush(BackColor))
{
e.Graphics.FillPath(brush, path);
}
}
// Disegna il testo centrato
TextRenderer.DrawText(e.Graphics, Text, Font, ClientRectangle,
ForeColor, TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter);
}
private GraphicsPath GetRoundedRectangle(Rectangle rect, int radius)
{
GraphicsPath path = new GraphicsPath();
int diameter = radius * 2;
path.AddArc(rect.X, rect.Y, diameter, diameter, 180, 90);
path.AddArc(rect.Right - diameter, rect.Y, diameter, diameter, 270, 90);
path.AddArc(rect.Right - diameter, rect.Bottom - diameter, diameter, diameter, 0, 90);
path.AddArc(rect.X, rect.Bottom - diameter, diameter, diameter, 90, 90);
path.CloseFigure();
return path;
}
}
}

View File

@@ -0,0 +1,104 @@
using System;
using System.Drawing;
using System.Windows.Forms;
namespace BettingPredictor.UI.Controls
{
/// <summary>
/// DataGridView moderna con tema scuro
/// </summary>
public class ModernDataGridView : DataGridView
{
public ModernDataGridView()
{
// Configurazione base
BackgroundColor = ModernTheme.Colors.PrimaryBackground;
GridColor = ModernTheme.Colors.BorderPrimary;
BorderStyle = BorderStyle.None;
// Colori delle celle
DefaultCellStyle.BackColor = ModernTheme.Colors.GridRowEven;
DefaultCellStyle.ForeColor = ModernTheme.Colors.TextPrimary;
DefaultCellStyle.SelectionBackColor = ModernTheme.Colors.GridSelected;
DefaultCellStyle.SelectionForeColor = ModernTheme.Colors.TextPrimary;
DefaultCellStyle.Font = ModernTheme.Fonts.RegularFont;
// Alternating row color
AlternatingRowsDefaultCellStyle.BackColor = ModernTheme.Colors.GridRowOdd;
AlternatingRowsDefaultCellStyle.ForeColor = ModernTheme.Colors.TextPrimary;
// Header
ColumnHeadersDefaultCellStyle.BackColor = ModernTheme.Colors.GridHeader;
ColumnHeadersDefaultCellStyle.ForeColor = ModernTheme.Colors.TextPrimary;
ColumnHeadersDefaultCellStyle.Font = ModernTheme.Fonts.SubtitleFont;
ColumnHeadersDefaultCellStyle.SelectionBackColor = ModernTheme.Colors.GridHeader;
ColumnHeadersDefaultCellStyle.SelectionForeColor = ModernTheme.Colors.TextPrimary;
ColumnHeadersBorderStyle = DataGridViewHeaderBorderStyle.Single;
ColumnHeadersHeight = 35;
// Row
RowHeadersDefaultCellStyle.BackColor = ModernTheme.Colors.GridHeader;
RowHeadersDefaultCellStyle.ForeColor = ModernTheme.Colors.TextPrimary;
RowHeadersDefaultCellStyle.SelectionBackColor = ModernTheme.Colors.GridHeader;
RowHeadersDefaultCellStyle.SelectionForeColor = ModernTheme.Colors.TextPrimary;
RowHeadersVisible = false;
// Altre impostazioni
EnableHeadersVisualStyles = false;
AllowUserToAddRows = false;
AllowUserToDeleteRows = false;
ReadOnly = true;
SelectionMode = DataGridViewSelectionMode.FullRowSelect;
MultiSelect = false;
AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
RowTemplate.Height = 30;
// Abilita il double buffering per evitare flickering
DoubleBuffered = true;
// Eventi per l'hover effect
CellMouseEnter += OnCellMouseEnterHandler;
CellMouseLeave += OnCellMouseLeaveHandler;
}
private void OnCellMouseEnterHandler(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex >= 0)
{
Rows[e.RowIndex].DefaultCellStyle.BackColor = ModernTheme.Colors.GridHover;
}
}
private void OnCellMouseLeaveHandler(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex >= 0)
{
// Ripristina il colore originale in base all'indice della riga
if (e.RowIndex % 2 == 0)
Rows[e.RowIndex].DefaultCellStyle.BackColor = ModernTheme.Colors.GridRowEven;
else
Rows[e.RowIndex].DefaultCellStyle.BackColor = ModernTheme.Colors.GridRowOdd;
}
}
public void HighlightWinnerRows()
{
if (Columns.Contains("Risultato Reale"))
{
foreach (DataGridViewRow row in Rows)
{
if (row.Cells["Risultato Reale"].Value != null &&
row.Cells["Risultato Reale"].Value.ToString() == "1")
{
row.DefaultCellStyle.BackColor = ModernTheme.Colors.StatusWin;
}
else if (row.Cells["Risultato Reale"].Value != null &&
int.TryParse(row.Cells["Risultato Reale"].Value.ToString(), out int pos) && pos <= 3)
{
row.DefaultCellStyle.BackColor = ModernTheme.Colors.StatusPlace;
}
}
}
}
}
}

View File

@@ -0,0 +1,48 @@
using System;
using System.Drawing;
using System.Windows.Forms;
namespace BettingPredictor.UI.Controls
{
/// <summary>
/// DateTimePicker moderna con tema scuro
/// Nota: Il controllo DateTimePicker di WinForms non supporta completamente il custom painting,
/// quindi alcuni elementi potrebbero mantenere lo stile di sistema
/// </summary>
public class ModernDateTimePicker : DateTimePicker
{
public ModernDateTimePicker()
{
// Configurazione base
Font = ModernTheme.Fonts.RegularFont;
Format = DateTimePickerFormat.Custom;
CustomFormat = "dd/MM/yyyy";
// Imposta i colori per il calendario
CalendarMonthBackground = ModernTheme.Colors.TertiaryBackground;
CalendarForeColor = ModernTheme.Colors.TextPrimary;
CalendarTitleBackColor = ModernTheme.Colors.SecondaryBackground;
CalendarTitleForeColor = ModernTheme.Colors.TextPrimary;
CalendarTrailingForeColor = ModernTheme.Colors.TextDisabled;
// Dimensioni
Height = 30;
}
/// <summary>
/// Imposta il formato lungo (con ora)
/// </summary>
public void SetLongFormat()
{
CustomFormat = "dd/MM/yyyy HH:mm";
}
/// <summary>
/// Imposta il formato corto (solo data)
/// </summary>
public void SetShortFormat()
{
CustomFormat = "dd/MM/yyyy";
}
}
}

View File

@@ -0,0 +1,78 @@
using System.Drawing;
using System.Windows.Forms;
namespace BettingPredictor.UI.Controls
{
/// <summary>
/// Label moderna con tema scuro e testo ben visibile
/// </summary>
public class ModernLabel : Label
{
public ModernLabel()
{
// Configurazione base per visibilità su sfondo scuro
ForeColor = ModernTheme.Colors.TextSecondary;
Font = ModernTheme.Fonts.RegularFont;
BackColor = Color.Transparent;
AutoSize = true;
// Abilita anti-aliasing per testo più leggibile
SetStyle(ControlStyles.OptimizedDoubleBuffer |
ControlStyles.AllPaintingInWmPaint, true);
}
/// <summary>
/// Imposta lo stile del label come titolo
/// </summary>
public void SetAsTitleLabel()
{
Font = ModernTheme.Fonts.TitleFont;
ForeColor = ModernTheme.Colors.TextPrimary;
}
/// <summary>
/// Imposta lo stile del label come sottotitolo
/// </summary>
public void SetAsSubtitleLabel()
{
Font = ModernTheme.Fonts.SubtitleFont;
ForeColor = ModernTheme.Colors.TextPrimary;
}
/// <summary>
/// Imposta lo stile del label come testo di stato
/// </summary>
public void SetAsStatusLabel()
{
Font = ModernTheme.Fonts.RegularFont;
ForeColor = ModernTheme.Colors.TextSecondary;
}
/// <summary>
/// Imposta lo stile del label come testo di successo
/// </summary>
public void SetAsSuccessLabel()
{
Font = ModernTheme.Fonts.RegularFont;
ForeColor = ModernTheme.Colors.AccentSuccess;
}
/// <summary>
/// Imposta lo stile del label come testo di errore
/// </summary>
public void SetAsErrorLabel()
{
Font = ModernTheme.Fonts.RegularFont;
ForeColor = ModernTheme.Colors.AccentError;
}
/// <summary>
/// Imposta lo stile del label come testo di warning
/// </summary>
public void SetAsWarningLabel()
{
Font = ModernTheme.Fonts.RegularFont;
ForeColor = ModernTheme.Colors.AccentWarning;
}
}
}

View File

@@ -0,0 +1,99 @@
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace BettingPredictor.UI.Controls
{
/// <summary>
/// Panel moderno con tema scuro e bordi arrotondati
/// </summary>
public class ModernPanel : Panel
{
private int borderRadius = ModernTheme.BorderRadius.Medium;
private Color borderColor = ModernTheme.Colors.BorderPrimary;
private int borderWidth = 1;
public ModernPanel()
{
BackColor = ModernTheme.Colors.SecondaryBackground;
// Abilita il double buffering
SetStyle(ControlStyles.UserPaint |
ControlStyles.AllPaintingInWmPaint |
ControlStyles.OptimizedDoubleBuffer |
ControlStyles.ResizeRedraw, true);
}
public int BorderRadius
{
get => borderRadius;
set
{
borderRadius = value;
Invalidate();
}
}
public Color BorderColor
{
get => borderColor;
set
{
borderColor = value;
Invalidate();
}
}
public int BorderWidth
{
get => borderWidth;
set
{
borderWidth = value;
Invalidate();
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
// Disegna il background con bordi arrotondati
using (GraphicsPath path = GetRoundedRectangle(ClientRectangle, borderRadius))
{
// Background
using (SolidBrush brush = new SolidBrush(BackColor))
{
e.Graphics.FillPath(brush, path);
}
// Bordo
if (borderWidth > 0)
{
using (Pen pen = new Pen(borderColor, borderWidth))
{
e.Graphics.DrawPath(pen, path);
}
}
}
}
private GraphicsPath GetRoundedRectangle(Rectangle rect, int radius)
{
GraphicsPath path = new GraphicsPath();
int diameter = radius * 2;
rect.Inflate(-borderWidth / 2, -borderWidth / 2);
path.AddArc(rect.X, rect.Y, diameter, diameter, 180, 90);
path.AddArc(rect.Right - diameter, rect.Y, diameter, diameter, 270, 90);
path.AddArc(rect.Right - diameter, rect.Bottom - diameter, diameter, diameter, 0, 90);
path.AddArc(rect.X, rect.Bottom - diameter, diameter, diameter, 90, 90);
path.CloseFigure();
return path;
}
}
}

View File

@@ -0,0 +1,54 @@
using System.Drawing;
using System.Windows.Forms;
namespace BettingPredictor.UI.Controls
{
/// <summary>
/// ProgressBar moderna con tema scuro e animazioni fluide
/// </summary>
public class ModernProgressBar : ProgressBar
{
public ModernProgressBar()
{
// Configurazione base
SetStyle(ControlStyles.UserPaint |
ControlStyles.AllPaintingInWmPaint |
ControlStyles.OptimizedDoubleBuffer, true);
Height = 6;
BackColor = ModernTheme.Colors.TertiaryBackground;
ForeColor = ModernTheme.Colors.AccentPrimary;
}
protected override void OnPaint(PaintEventArgs e)
{
Rectangle rect = ClientRectangle;
Graphics g = e.Graphics;
// Disegna il background
using (SolidBrush brush = new SolidBrush(ModernTheme.Colors.TertiaryBackground))
{
g.FillRectangle(brush, rect);
}
// Calcola la larghezza del progresso
int progressWidth = (int)(rect.Width * ((double)Value / Maximum));
// Disegna la barra di progresso
if (progressWidth > 0)
{
Rectangle progressRect = new Rectangle(rect.X, rect.Y, progressWidth, rect.Height);
using (SolidBrush brush = new SolidBrush(ForeColor))
{
g.FillRectangle(brush, progressRect);
}
}
}
public void SetProgressColor(Color color)
{
ForeColor = color;
Invalidate();
}
}
}

View File

@@ -0,0 +1,98 @@
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace BettingPredictor.UI.Controls
{
/// <summary>
/// TabControl moderna con tema scuro
/// </summary>
public class ModernTabControl : TabControl
{
public ModernTabControl()
{
SetStyle(ControlStyles.UserPaint |
ControlStyles.AllPaintingInWmPaint |
ControlStyles.OptimizedDoubleBuffer |
ControlStyles.ResizeRedraw, true);
DrawMode = TabDrawMode.OwnerDrawFixed;
SizeMode = TabSizeMode.Fixed;
ItemSize = new Size(120, 40);
Padding = new Point(20, 0);
}
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.Clear(ModernTheme.Colors.PrimaryBackground);
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
// Disegna il background del tab panel
Rectangle tabPanelRect = new Rectangle(0, ItemSize.Height, Width, Height - ItemSize.Height);
using (SolidBrush brush = new SolidBrush(ModernTheme.Colors.SecondaryBackground))
{
e.Graphics.FillRectangle(brush, tabPanelRect);
}
}
protected override void OnDrawItem(DrawItemEventArgs e)
{
Graphics g = e.Graphics;
g.SmoothingMode = SmoothingMode.AntiAlias;
// Get tab rectangle
Rectangle tabRect = GetTabRect(e.Index);
bool isSelected = (e.Index == SelectedIndex);
// Disegna il background della tab
Color backColor = isSelected ? ModernTheme.Colors.SecondaryBackground : ModernTheme.Colors.PrimaryBackground;
using (SolidBrush brush = new SolidBrush(backColor))
{
g.FillRectangle(brush, tabRect);
}
// Disegna la linea di selezione in alto
if (isSelected)
{
Rectangle accentRect = new Rectangle(tabRect.X, tabRect.Y, tabRect.Width, 3);
using (SolidBrush brush = new SolidBrush(ModernTheme.Colors.AccentPrimary))
{
g.FillRectangle(brush, accentRect);
}
}
// Disegna il testo della tab
string tabText = TabPages[e.Index].Text;
Color textColor = isSelected ? ModernTheme.Colors.TextPrimary : ModernTheme.Colors.TextSecondary;
Font tabFont = isSelected ? ModernTheme.Fonts.SubtitleFont : ModernTheme.Fonts.RegularFont;
StringFormat sf = new StringFormat
{
Alignment = StringAlignment.Center,
LineAlignment = StringAlignment.Center
};
using (SolidBrush brush = new SolidBrush(textColor))
{
g.DrawString(tabText, tabFont, brush, tabRect, sf);
}
// Disegna il bordo tra le tabs
if (e.Index < TabCount - 1)
{
using (Pen pen = new Pen(ModernTheme.Colors.BorderPrimary, 1))
{
g.DrawLine(pen, tabRect.Right, tabRect.Top + 10, tabRect.Right, tabRect.Bottom - 10);
}
}
}
protected override void OnSelectedIndexChanged(EventArgs e)
{
base.OnSelectedIndexChanged(e);
Invalidate();
}
}
}

View File

@@ -0,0 +1,139 @@
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace BettingPredictor.UI.Controls
{
/// <summary>
/// TextBox moderno con tema scuro e bordi arrotondati
/// </summary>
public class ModernTextBox : TextBox
{
private Color borderColor = ModernTheme.Colors.BorderPrimary;
private Color focusBorderColor = ModernTheme.Colors.BorderAccent;
private bool isFocused = false;
private int borderRadius = ModernTheme.BorderRadius.Medium;
public ModernTextBox()
{
// Configurazione base
BorderStyle = BorderStyle.None;
BackColor = ModernTheme.Colors.TertiaryBackground;
ForeColor = ModernTheme.Colors.TextPrimary;
Font = ModernTheme.Fonts.RegularFont;
Padding = new Padding(8, 8, 8, 8);
// Abilita il double buffering
SetStyle(ControlStyles.UserPaint |
ControlStyles.AllPaintingInWmPaint |
ControlStyles.OptimizedDoubleBuffer, true);
}
public Color BorderColor
{
get => borderColor;
set
{
borderColor = value;
Invalidate();
}
}
public Color FocusBorderColor
{
get => focusBorderColor;
set
{
focusBorderColor = value;
Invalidate();
}
}
public int BorderRadius
{
get => borderRadius;
set
{
borderRadius = value;
Invalidate();
}
}
protected override void OnEnter(EventArgs e)
{
base.OnEnter(e);
isFocused = true;
Invalidate();
}
protected override void OnLeave(EventArgs e)
{
base.OnLeave(e);
isFocused = false;
Invalidate();
}
protected override void OnReadOnlyChanged(EventArgs e)
{
base.OnReadOnlyChanged(e);
// Cambia il colore del testo per i campi read-only
if (ReadOnly)
{
ForeColor = ModernTheme.Colors.TextSecondary;
BackColor = ModernTheme.Colors.SecondaryBackground;
}
else
{
ForeColor = ModernTheme.Colors.TextPrimary;
BackColor = ModernTheme.Colors.TertiaryBackground;
}
Invalidate();
}
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
// Disegna il background
using (GraphicsPath path = GetRoundedRectangle(ClientRectangle, borderRadius))
{
using (SolidBrush brush = new SolidBrush(BackColor))
{
e.Graphics.FillPath(brush, path);
}
// Disegna il bordo
Color currentBorderColor = isFocused ? focusBorderColor : borderColor;
using (Pen pen = new Pen(currentBorderColor, 1.5f))
{
e.Graphics.DrawPath(pen, path);
}
}
// Disegna il testo
if (!string.IsNullOrEmpty(Text))
{
TextRenderer.DrawText(e.Graphics, Text, Font,
new Rectangle(8, 0, Width - 16, Height),
ForeColor, TextFormatFlags.Left | TextFormatFlags.VerticalCenter);
}
}
private GraphicsPath GetRoundedRectangle(Rectangle rect, int radius)
{
GraphicsPath path = new GraphicsPath();
int diameter = radius * 2;
rect.Inflate(-1, -1);
path.AddArc(rect.X, rect.Y, diameter, diameter, 180, 90);
path.AddArc(rect.Right - diameter, rect.Y, diameter, diameter, 270, 90);
path.AddArc(rect.Right - diameter, rect.Bottom - diameter, diameter, diameter, 0, 90);
path.AddArc(rect.X, rect.Bottom - diameter, diameter, diameter, 90, 90);
path.CloseFigure();
return path;
}
}
}

View File

@@ -1,23 +1,28 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="CsvHelper" version="33.0.1" targetFramework="net481" /> <package id="CsvHelper" version="33.1.0" targetFramework="net481" />
<package id="Microsoft.Bcl.AsyncInterfaces" version="10.0.0-preview.4.25258.110" targetFramework="net481" /> <package id="Microsoft.Bcl.AsyncInterfaces" version="10.0.0-rc.1.25451.107" targetFramework="net481" />
<package id="Microsoft.Bcl.HashCode" version="6.0.0" targetFramework="net481" /> <package id="Microsoft.Bcl.HashCode" version="6.0.0" targetFramework="net481" />
<package id="Microsoft.Bcl.Numerics" version="10.0.0-preview.4.25258.110" targetFramework="net481" /> <package id="Microsoft.Bcl.Numerics" version="10.0.0-rc.1.25451.107" targetFramework="net481" />
<package id="Microsoft.CSharp" version="4.7.0" targetFramework="net481" /> <package id="Microsoft.CSharp" version="4.7.0" targetFramework="net481" />
<package id="Microsoft.ML" version="5.0.0-preview.1.25127.4" targetFramework="net481" /> <package id="Microsoft.ML" version="5.0.0-preview.25503.2" targetFramework="net481" />
<package id="Microsoft.ML.CpuMath" version="5.0.0-preview.1.25127.4" targetFramework="net481" /> <package id="Microsoft.ML.CpuMath" version="5.0.0-preview.25503.2" targetFramework="net481" />
<package id="Microsoft.ML.DataView" version="5.0.0-preview.1.25127.4" targetFramework="net481" /> <package id="Microsoft.ML.DataView" version="5.0.0-preview.25503.2" targetFramework="net481" />
<package id="Microsoft.ML.FastTree" version="5.0.0-preview.1.25127.4" targetFramework="net481" /> <package id="Microsoft.ML.FastTree" version="5.0.0-preview.25503.2" targetFramework="net481" />
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net481" /> <package id="Newtonsoft.Json" version="13.0.4" targetFramework="net481" />
<package id="RestSharp" version="112.1.1-alpha.0.4" targetFramework="net481" />
<package id="System.Buffers" version="4.6.1" targetFramework="net481" /> <package id="System.Buffers" version="4.6.1" targetFramework="net481" />
<package id="System.CodeDom" version="10.0.0-preview.4.25258.110" targetFramework="net481" /> <package id="System.CodeDom" version="10.0.0-rc.1.25451.107" targetFramework="net481" />
<package id="System.Collections.Immutable" version="10.0.0-preview.4.25258.110" targetFramework="net481" /> <package id="System.Collections.Immutable" version="10.0.0-rc.1.25451.107" targetFramework="net481" />
<package id="System.IO.Pipelines" version="10.0.0-rc.1.25451.107" targetFramework="net481" />
<package id="System.Memory" version="4.6.3" targetFramework="net481" /> <package id="System.Memory" version="4.6.3" targetFramework="net481" />
<package id="System.Numerics.Tensors" version="10.0.0-preview.4.25258.110" targetFramework="net481" /> <package id="System.Numerics.Tensors" version="10.0.0-rc.1.25451.107" targetFramework="net481" />
<package id="System.Numerics.Vectors" version="4.6.1" targetFramework="net481" /> <package id="System.Numerics.Vectors" version="4.6.1" targetFramework="net481" />
<package id="System.Reflection.Emit.Lightweight" version="4.7.0" targetFramework="net481" /> <package id="System.Reflection.Emit.Lightweight" version="4.7.0" targetFramework="net481" />
<package id="System.Runtime.CompilerServices.Unsafe" version="6.1.2" targetFramework="net481" /> <package id="System.Runtime.CompilerServices.Unsafe" version="6.1.2" targetFramework="net481" />
<package id="System.Threading.Channels" version="10.0.0-preview.4.25258.110" targetFramework="net481" /> <package id="System.Text.Encodings.Web" version="10.0.0-rc.1.25451.107" targetFramework="net481" />
<package id="System.Text.Json" version="10.0.0-rc.1.25451.107" targetFramework="net481" />
<package id="System.Threading.Channels" version="10.0.0-rc.1.25451.107" targetFramework="net481" />
<package id="System.Threading.Tasks.Extensions" version="4.6.3" targetFramework="net481" /> <package id="System.Threading.Tasks.Extensions" version="4.6.3" targetFramework="net481" />
<package id="System.ValueTuple" version="4.6.1" targetFramework="net481" />
</packages> </packages>