using System; using System.Windows; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using Dione.Data; using Dione.Models; using Microsoft.Win32; namespace Dione.ViewModels { public class SettingsViewModel : ObservableObject { // ── API ────────────────────────────────────────────────────────────────── private string _selectedEndpointPreset = "Custom"; public string SelectedEndpointPreset { get => _selectedEndpointPreset; set { if (SetProperty(ref _selectedEndpointPreset, value) && value != "Custom") ApplyPreset(value); } } public string[] EndpointPresets { get; } = { "Custom", "OpenAI", "Anthropic", "Google AI", "Azure OpenAI", "LM Studio (Local)", "Ollama (Local)" }; private string _apiEndpoint = "http://127.0.0.1:1234/v1/chat/completions"; public string ApiEndpoint { get => _apiEndpoint; set => SetProperty(ref _apiEndpoint, value); } private string _modelName = ""; public string ModelName { get => _modelName; set => SetProperty(ref _modelName, value); } private string _apiKey = ""; public string ApiKey { get => _apiKey; set => SetProperty(ref _apiKey, value); } private double _temperature = 0.7; public double Temperature { get => _temperature; set => SetProperty(ref _temperature, value); } private int _maxTokens = 2048; public int MaxTokens { get => _maxTokens; set => SetProperty(ref _maxTokens, value); } // ── Prompt ─────────────────────────────────────────────────────────────── private string _systemPrompt = ""; public string SystemPrompt { get => _systemPrompt; set => SetProperty(ref _systemPrompt, value); } private string _userPrompt = ""; public string UserPrompt { get => _userPrompt; set => SetProperty(ref _userPrompt, value); } // ── Output ─────────────────────────────────────────────────────────────── private string _outputDirectory = ""; public string OutputDirectory { get => _outputDirectory; set => SetProperty(ref _outputDirectory, value); } private string _outputFilePrefix = "batch"; public string OutputFilePrefix { get => _outputFilePrefix; set => SetProperty(ref _outputFilePrefix, value); } private int _maxFileSizeMb = 250; public int MaxFileSizeMb { get => _maxFileSizeMb; set => SetProperty(ref _maxFileSizeMb, value); } // ── Timeout ────────────────────────────────────────────────────────────── private int _apiTimeoutSeconds = 120; public int ApiTimeoutSeconds { get => _apiTimeoutSeconds; set => SetProperty(ref _apiTimeoutSeconds, value); } private double _timeoutPerTokenRatio = 0.5; public double TimeoutPerTokenRatio { get => _timeoutPerTokenRatio; set => SetProperty(ref _timeoutPerTokenRatio, value); } // ── Verifica qualita ───────────────────────────────────────────────────── private bool _enableQualityVerification = false; public bool EnableQualityVerification { get => _enableQualityVerification; set => SetProperty(ref _enableQualityVerification, value); } private bool _useSameModelForVerification = true; public bool UseSameModelForVerification { get => _useSameModelForVerification; set => SetProperty(ref _useSameModelForVerification, value); } private string _verificationApiEndpoint = ""; public string VerificationApiEndpoint { get => _verificationApiEndpoint; set => SetProperty(ref _verificationApiEndpoint, value); } private string _verificationModelName = ""; public string VerificationModelName { get => _verificationModelName; set => SetProperty(ref _verificationModelName, value); } private string _verificationApiKey = ""; public string VerificationApiKey { get => _verificationApiKey; set => SetProperty(ref _verificationApiKey, value); } private double _revenuePerHighQualityRecord = 0.005; public double RevenuePerHighQualityRecord { get => _revenuePerHighQualityRecord; set => SetProperty(ref _revenuePerHighQualityRecord, value); } // ── Costi ──────────────────────────────────────────────────────────────── private double _electricityCostPerKwh = 0.25; public double ElectricityCostPerKwh { get => _electricityCostPerKwh; set => SetProperty(ref _electricityCostPerKwh, value); } private double _systemPowerWatt = 350; public double SystemPowerWatt { get => _systemPowerWatt; set => SetProperty(ref _systemPowerWatt, value); } private string _apiCostType = "Free"; public string ApiCostType { get => _apiCostType; set => SetProperty(ref _apiCostType, value); } public string[] ApiCostTypes { get; } = { "Free", "PerCall", "PerBlock" }; private double _apiCostPerCall = 0; public double ApiCostPerCall { get => _apiCostPerCall; set => SetProperty(ref _apiCostPerCall, value); } private double _apiCostPerBlock = 0; public double ApiCostPerBlock { get => _apiCostPerBlock; set => SetProperty(ref _apiCostPerBlock, value); } private int _apiBlockSize = 1000; public int ApiBlockSize { get => _apiBlockSize; set => SetProperty(ref _apiBlockSize, value); } // ── Status ─────────────────────────────────────────────────────────────── private string _statusMessage = ""; public string StatusMessage { get => _statusMessage; set => SetProperty(ref _statusMessage, value); } // ── Commands ───────────────────────────────────────────────────────────── public RelayCommand SaveCommand { get; } public RelayCommand BrowseOutputDirectoryCommand { get; } public RelayCommand ResetTelemetryCommand { get; } public RelayCommand ResetDatabaseCommand { get; } public RelayCommand InsertDefaultBettingPromptCommand { get; } // ── Constructor ────────────────────────────────────────────────────────── public SettingsViewModel() { SaveCommand = new RelayCommand(Save); BrowseOutputDirectoryCommand = new RelayCommand(BrowseOutputDirectory); ResetTelemetryCommand = new RelayCommand(ResetTelemetry); ResetDatabaseCommand = new RelayCommand(ResetDatabase); InsertDefaultBettingPromptCommand = new RelayCommand(InsertDefaultBettingPrompt); Load(); } // ── Private methods ────────────────────────────────────────────────────── public void Load() { try { var s = SynthDataDbContext.LoadSettings(); ApiEndpoint = s.ApiEndpoint; ModelName = s.ModelName; ApiKey = s.ApiKey; Temperature = s.Temperature; MaxTokens = s.MaxTokens; SystemPrompt = s.SystemPrompt; UserPrompt = s.UserPrompt; OutputDirectory = s.OutputDirectory; OutputFilePrefix = s.OutputFilePrefix; MaxFileSizeMb = s.MaxFileSizeMb; ApiTimeoutSeconds = s.ApiTimeoutSeconds; TimeoutPerTokenRatio = s.TimeoutPerTokenRatio; EnableQualityVerification = s.EnableQualityVerification; UseSameModelForVerification = s.UseSameModelForVerification; VerificationApiEndpoint = s.VerificationApiEndpoint; VerificationModelName = s.VerificationModelName; VerificationApiKey = s.VerificationApiKey; RevenuePerHighQualityRecord = s.RevenuePerHighQualityRecord; ElectricityCostPerKwh = s.ElectricityCostPerKwh; SystemPowerWatt = s.SystemPowerWatt; ApiCostType = s.ApiCostType; ApiCostPerCall = s.ApiCostPerCall; ApiCostPerBlock = s.ApiCostPerBlock; ApiBlockSize = s.ApiBlockSize; StatusMessage = "Impostazioni caricate."; } catch (Exception ex) { StatusMessage = "Errore caricamento: " + ex.Message; } } private void Save() { if (string.IsNullOrWhiteSpace(OutputDirectory)) { StatusMessage = "Seleziona una cartella di output."; return; } try { SynthDataDbContext.SaveSettings(new AppSettings { ApiEndpoint = ApiEndpoint, ModelName = ModelName, ApiKey = ApiKey, Temperature = Temperature, MaxTokens = MaxTokens, SystemPrompt = SystemPrompt, UserPrompt = UserPrompt, OutputDirectory = OutputDirectory, OutputFilePrefix = OutputFilePrefix, MaxFileSizeMb = MaxFileSizeMb, ApiTimeoutSeconds = ApiTimeoutSeconds, TimeoutPerTokenRatio = TimeoutPerTokenRatio, EnableQualityVerification = EnableQualityVerification, UseSameModelForVerification = UseSameModelForVerification, VerificationApiEndpoint = VerificationApiEndpoint, VerificationModelName = VerificationModelName, VerificationApiKey = VerificationApiKey, RevenuePerHighQualityRecord = RevenuePerHighQualityRecord, ElectricityCostPerKwh = ElectricityCostPerKwh, SystemPowerWatt = SystemPowerWatt, ApiCostType = ApiCostType, ApiCostPerCall = ApiCostPerCall, ApiCostPerBlock = ApiCostPerBlock, ApiBlockSize = ApiBlockSize, }); StatusMessage = "Impostazioni salvate."; } catch (Exception ex) { StatusMessage = "Errore salvataggio: " + ex.Message; } } private void BrowseOutputDirectory() { var dlg = new System.Windows.Forms.FolderBrowserDialog { Description = "Seleziona la cartella di output", SelectedPath = OutputDirectory }; if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK) OutputDirectory = dlg.SelectedPath; } private void ResetTelemetry() { if (MessageBox.Show("Eliminare TUTTA la telemetria?", "Conferma", MessageBoxButton.YesNo, MessageBoxImage.Warning) != MessageBoxResult.Yes) return; try { SynthDataDbContext.DeleteAllTelemetry(); StatusMessage = "Telemetria eliminata."; } catch (Exception ex) { StatusMessage = "Errore: " + ex.Message; } } private void ResetDatabase() { if (MessageBox.Show("Resettare COMPLETAMENTE il database? Tutte le impostazioni e la telemetria verranno cancellate.", "Conferma Reset", MessageBoxButton.YesNo, MessageBoxImage.Stop) != MessageBoxResult.Yes) return; try { SynthDataDbContext.ResetDatabase(); Load(); StatusMessage = "Database resettato."; } catch (Exception ex) { StatusMessage = "Errore: " + ex.Message; } } private void InsertDefaultBettingPrompt() { SystemPrompt = "Sei il nodo validatore di una blockchain per una piattaforma di scommesse decentralizzata. " + "Il tuo compito e generare transazioni fittizie ma realistiche in formato JSON puro. " + "Non includere testo introduttivo o conclusivo, restituisci solo un array di oggetti JSON.\n\n" + "Regole per la generazione dei dati:\n" + "- Ogni transazione deve avere un tx_hash esadecimale casuale di 64 caratteri e un timestamp ISO 8601.\n" + "- bet_type puo essere solo 'singola' o 'multipla'.\n" + "- Genera un bankroll_at_time casuale tra 100 e 5000.\n" + "- Logica dello Stake: Se 'singola', stake_amount deve essere intero e multiplo di 5. " + "Se 'multipla', genera confidence_level tra 0.0 e 1.0. Se confidenza tra 0.9 e 1.0, " + "stake_amount fino al 10% del bankroll. Altrimenti sotto l'1%.\n" + "- Includi smart_contract_log che spiega come lo smart contract ha processato i fondi."; UserPrompt = "Genera un blocco di 5 nuove transazioni sequenziali rispettando rigorosamente le regole di business."; StatusMessage = "Prompt blockchain betting inseriti. Ricorda di salvare."; } private void ApplyPreset(string preset) { switch (preset) { case "OpenAI": ApiEndpoint = "https://api.openai.com/v1/chat/completions"; ModelName = "gpt-4o"; StatusMessage = "Preset OpenAI applicato. Inserisci la API Key."; break; case "Anthropic": ApiEndpoint = "https://api.anthropic.com/v1/messages"; ModelName = "claude-3-5-sonnet-20241022"; StatusMessage = "Preset Anthropic applicato. Inserisci la API Key."; break; case "Google AI": ApiEndpoint = "https://generativelanguage.googleapis.com/v1beta/openai/chat/completions"; ModelName = "gemini-2.0-flash-exp"; StatusMessage = "Preset Google AI applicato. Inserisci la API Key."; break; case "Azure OpenAI": ApiEndpoint = "https://.openai.azure.com/openai/deployments//chat/completions?api-version=2024-02-15-preview"; ModelName = "gpt-4"; StatusMessage = "Sostituisci e ."; break; case "LM Studio (Local)": ApiEndpoint = "http://127.0.0.1:1234/v1/chat/completions"; ModelName = ""; ApiKey = ""; StatusMessage = "Preset LM Studio applicato."; break; case "Ollama (Local)": ApiEndpoint = "http://127.0.0.1:11434/v1/chat/completions"; ModelName = "llama3.3"; ApiKey = ""; StatusMessage = "Preset Ollama applicato."; break; } } } }