MarketAlly.AIPlugin.Extensions/MarketAlly.AIPlugin.Learning/RefactorIQRepository.cs

223 lines
8.4 KiB
C#
Executable File

using Microsoft.Data.Sqlite;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MarketAlly.AIPlugin.Learning
{
public class RefactorIQRepository
{
private readonly string _connectionString;
public RefactorIQRepository(string databasePath)
{
_connectionString = $"Data Source={databasePath}";
}
public async Task<List<SuccessPattern>> GetSuccessfulPatternsAsync()
{
var patterns = new List<SuccessPattern>();
using var connection = new SqliteConnection(_connectionString);
await connection.OpenAsync();
var query = @"
SELECT
SuggestionType,
AVG(CAST(Success AS REAL)) as SuccessRate,
AVG(ActualImprovement) as AverageImprovement,
COUNT(*) as UsageCount
FROM LearningRecords
WHERE Success = 1
GROUP BY SuggestionType
HAVING COUNT(*) >= 3";
using var command = new SqliteCommand(query, connection);
using var reader = await command.ExecuteReaderAsync();
while (await reader.ReadAsync())
{
patterns.Add(new SuccessPattern
{
PatternName = reader.SafeGetString("SuggestionType"),
SuccessRate = reader.SafeGetDouble("SuccessRate"),
AverageImprovement = reader.SafeGetDouble("AverageImprovement"),
UsageCount = reader.SafeGetInt32("UsageCount")
});
}
return patterns;
}
public async Task<List<FailurePattern>> GetFailurePatternsAsync()
{
var patterns = new List<FailurePattern>();
using var connection = new SqliteConnection(_connectionString);
await connection.OpenAsync();
var query = @"
SELECT
SuggestionType,
AVG(CAST((1 - Success) AS REAL)) as FailureRate,
COUNT(*) as FailureCount
FROM LearningRecords
WHERE Success = 0
GROUP BY SuggestionType
HAVING COUNT(*) >= 2";
using var command = new SqliteCommand(query, connection);
using var reader = await command.ExecuteReaderAsync();
while (await reader.ReadAsync())
{
patterns.Add(new FailurePattern
{
IssueType = reader.SafeGetString("SuggestionType"),
FailureRate = reader.SafeGetDouble("FailureRate"),
FailureCount = reader.SafeGetInt32("FailureCount")
});
}
return patterns;
}
public async Task StoreLearningRecordAsync(LearningRecord record)
{
using var connection = new SqliteConnection(_connectionString);
await connection.OpenAsync();
// Create table if it doesn't exist
await EnsureLearningTablesExistAsync(connection);
var query = @"
INSERT INTO LearningRecords
(SuggestionId, SuggestionType, Confidence, ExpectedImprovement, ActualImprovement,
Success, CompilationStatus, ErrorCountBefore, ErrorCountAfter, Timestamp)
VALUES
(@SuggestionId, @SuggestionType, @Confidence, @ExpectedImprovement, @ActualImprovement,
@Success, @CompilationStatus, @ErrorCountBefore, @ErrorCountAfter, @Timestamp)";
using var command = new SqliteCommand(query, connection);
command.Parameters.AddWithValue("@SuggestionId", record.SuggestionId.ToString());
command.Parameters.AddWithValue("@SuggestionType", record.SuggestionType.ToString());
command.Parameters.AddWithValue("@Confidence", record.Confidence);
command.Parameters.AddWithValue("@ExpectedImprovement", record.ExpectedImprovement);
command.Parameters.AddWithValue("@ActualImprovement", record.ActualImprovement);
command.Parameters.AddWithValue("@Success", record.Success ? 1 : 0);
command.Parameters.AddWithValue("@CompilationStatus", record.CompilationStatus.ToString());
command.Parameters.AddWithValue("@ErrorCountBefore", record.ErrorCountBefore);
command.Parameters.AddWithValue("@ErrorCountAfter", record.ErrorCountAfter);
command.Parameters.AddWithValue("@Timestamp", record.Timestamp.ToString("yyyy-MM-dd HH:mm:ss"));
await command.ExecuteNonQueryAsync();
}
public async Task StoreLearningSessionAsync(LearningResult result)
{
using var connection = new SqliteConnection(_connectionString);
await connection.OpenAsync();
await EnsureLearningTablesExistAsync(connection);
var query = @"
INSERT INTO LearningSessions
(SessionId, StartTime, EndTime, TotalDuration, TotalSuggestions, TotalAppliedChanges,
SuccessfulChanges, SuccessRate, BaselineErrors, FinalErrors)
VALUES
(@SessionId, @StartTime, @EndTime, @TotalDuration, @TotalSuggestions, @TotalAppliedChanges,
@SuccessfulChanges, @SuccessRate, @BaselineErrors, @FinalErrors)";
using var command = new SqliteCommand(query, connection);
command.Parameters.AddWithValue("@SessionId", result.SessionId.ToString());
command.Parameters.AddWithValue("@StartTime", result.StartTime.ToString("yyyy-MM-dd HH:mm:ss"));
command.Parameters.AddWithValue("@EndTime", result.EndTime.ToString("yyyy-MM-dd HH:mm:ss"));
command.Parameters.AddWithValue("@TotalDuration", result.TotalDuration.TotalMinutes);
command.Parameters.AddWithValue("@TotalSuggestions", result.TotalSuggestions);
command.Parameters.AddWithValue("@TotalAppliedChanges", result.TotalAppliedChanges);
command.Parameters.AddWithValue("@SuccessfulChanges", result.SuccessfulChanges);
command.Parameters.AddWithValue("@SuccessRate", result.SuccessRate);
command.Parameters.AddWithValue("@BaselineErrors", result.BaselineCompilation?.ErrorCount ?? 0);
var finalErrors = result.Iterations.LastOrDefault()?.PostChangeCompilation?.ErrorCount ??
result.BaselineCompilation?.ErrorCount ?? 0;
command.Parameters.AddWithValue("@FinalErrors", finalErrors);
await command.ExecuteNonQueryAsync();
}
public async Task BoostPatternConfidenceAsync(SuggestionType type, double boost)
{
using var connection = new SqliteConnection(_connectionString);
await connection.OpenAsync();
await EnsureLearningTablesExistAsync(connection);
var query = @"
INSERT OR REPLACE INTO PatternConfidence (SuggestionType, ConfidenceModifier)
VALUES (@SuggestionType, COALESCE(
(SELECT ConfidenceModifier FROM PatternConfidence WHERE SuggestionType = @SuggestionType), 0
) + @Boost)";
using var command = new SqliteCommand(query, connection);
command.Parameters.AddWithValue("@SuggestionType", type.ToString());
command.Parameters.AddWithValue("@Boost", boost);
await command.ExecuteNonQueryAsync();
}
public async Task ReducePatternConfidenceAsync(SuggestionType type, double reduction)
{
await BoostPatternConfidenceAsync(type, -reduction);
}
private async Task EnsureLearningTablesExistAsync(SqliteConnection connection)
{
var queries = new[]
{
@"CREATE TABLE IF NOT EXISTS LearningRecords (
Id INTEGER PRIMARY KEY AUTOINCREMENT,
SuggestionId TEXT NOT NULL,
SuggestionType TEXT NOT NULL,
Confidence REAL NOT NULL,
ExpectedImprovement REAL NOT NULL,
ActualImprovement REAL NOT NULL,
Success INTEGER NOT NULL,
CompilationStatus TEXT NOT NULL,
ErrorCountBefore INTEGER NOT NULL,
ErrorCountAfter INTEGER NOT NULL,
Timestamp TEXT NOT NULL
)",
@"CREATE TABLE IF NOT EXISTS LearningSessions (
Id INTEGER PRIMARY KEY AUTOINCREMENT,
SessionId TEXT NOT NULL,
StartTime TEXT NOT NULL,
EndTime TEXT NOT NULL,
TotalDuration REAL NOT NULL,
TotalSuggestions INTEGER NOT NULL,
TotalAppliedChanges INTEGER NOT NULL,
SuccessfulChanges INTEGER NOT NULL,
SuccessRate REAL NOT NULL,
BaselineErrors INTEGER NOT NULL,
FinalErrors INTEGER NOT NULL
)",
@"CREATE TABLE IF NOT EXISTS PatternConfidence (
SuggestionType TEXT PRIMARY KEY,
ConfidenceModifier REAL NOT NULL DEFAULT 0
)"
};
foreach (var query in queries)
{
using var command = new SqliteCommand(query, connection);
await command.ExecuteNonQueryAsync();
}
}
}
}