185 lines
5.6 KiB
C#
185 lines
5.6 KiB
C#
using SQLVision.Core.Enums;
|
|
using SQLVision.Core.Models;
|
|
using SQLVision.Visualizers.Interfaces;
|
|
using System.Data;
|
|
|
|
namespace SQLVision.Visualizers.Visualizers;
|
|
|
|
public class ChartVisualizer : IVisualizer
|
|
{
|
|
public FrameworkElement Visualize(DataTable data, OutputDefinition definition)
|
|
{
|
|
if (data.Rows.Count == 0)
|
|
{
|
|
return CreateEmptyChartMessage("Нет данных для построения графика");
|
|
}
|
|
|
|
try
|
|
{
|
|
var chartType = definition.ChartType;
|
|
var cartesianChart = new CartesianChart
|
|
{
|
|
Series = CreateSeries(data, definition),
|
|
XAxes = CreateXAxes(data, definition),
|
|
YAxes = CreateYAxes(definition),
|
|
LegendPosition = LegendPosition.Right,
|
|
TooltipPosition = LiveChartsCore.Measure.TooltipPosition.Hidden
|
|
};
|
|
|
|
return cartesianChart;
|
|
}
|
|
catch (Exception)
|
|
{
|
|
return CreateEmptyChartMessage("Ошибка при построении графика");
|
|
}
|
|
}
|
|
|
|
private ISeries[] CreateSeries(DataTable data, OutputDefinition definition)
|
|
{
|
|
var series = new List<ISeries>();
|
|
|
|
if (!string.IsNullOrEmpty(definition.SeriesColumn))
|
|
{
|
|
// Разделение по сериям
|
|
var seriesGroups = data.AsEnumerable()
|
|
.GroupBy(row => row[definition.SeriesColumn])
|
|
.ToList();
|
|
|
|
foreach (var group in seriesGroups)
|
|
{
|
|
var seriesName = group.Key.ToString();
|
|
var values = group.Select(row =>
|
|
{
|
|
if (string.IsNullOrEmpty(definition.YAxisColumn))
|
|
return Convert.ToDouble(row[1]);
|
|
return Convert.ToDouble(row[definition.YAxisColumn]);
|
|
}).ToArray();
|
|
|
|
series.Add(CreateSeriesByType(definition.ChartType, values, seriesName));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Одна серия
|
|
var values = data.AsEnumerable()
|
|
.Select(row =>
|
|
{
|
|
if (string.IsNullOrEmpty(definition.YAxisColumn))
|
|
return Convert.ToDouble(row[1]);
|
|
return Convert.ToDouble(row[definition.YAxisColumn]);
|
|
}).ToArray();
|
|
|
|
series.Add(CreateSeriesByType(definition.ChartType, values, definition.Description));
|
|
}
|
|
|
|
return series.ToArray();
|
|
}
|
|
|
|
private ISeries CreateSeriesByType(ChartType chartType, double[] values, string name)
|
|
{
|
|
return chartType switch
|
|
{
|
|
ChartType.Line => new LineSeries<double>
|
|
{
|
|
Values = values,
|
|
Name = name,
|
|
Fill = null,
|
|
GeometrySize = 8,
|
|
LineSmoothness = 0
|
|
},
|
|
ChartType.Bar => new ColumnSeries<double>
|
|
{
|
|
Values = values,
|
|
Name = name
|
|
},
|
|
ChartType.Area => new LineSeries<double>
|
|
{
|
|
Values = values,
|
|
Name = name,
|
|
Fill = new SolidColorPaint(SKColors.Blue.WithAlpha(50))
|
|
},
|
|
ChartType.Scatter => new ScatterSeries<ObservablePoint>
|
|
{
|
|
Values = values.Select((v, i) => new ObservablePoint(i, v)),
|
|
Name = name,
|
|
GeometrySize = 10
|
|
},
|
|
_ => new LineSeries<double>
|
|
{
|
|
Values = values,
|
|
Name = name
|
|
}
|
|
};
|
|
}
|
|
|
|
private Axis[] CreateXAxes(DataTable data, OutputDefinition definition)
|
|
{
|
|
var labels = new List<string>();
|
|
|
|
if (!string.IsNullOrEmpty(definition.XAxisColumn))
|
|
{
|
|
labels = data.AsEnumerable()
|
|
.Select(row => row[definition.XAxisColumn].ToString())
|
|
.ToList();
|
|
}
|
|
else if (data.Columns.Count > 0)
|
|
{
|
|
// Берем первый столбец для оси X
|
|
labels = data.AsEnumerable()
|
|
.Select(row => row[0].ToString())
|
|
.ToList();
|
|
}
|
|
else
|
|
{
|
|
labels = Enumerable.Range(0, data.Rows.Count)
|
|
.Select(i => i.ToString())
|
|
.ToList();
|
|
}
|
|
|
|
return new[]
|
|
{
|
|
new Axis
|
|
{
|
|
Labels = labels.ToArray(),
|
|
LabelsRotation = labels.Count > 10 ? 45 : 0,
|
|
TextSize = 12
|
|
}
|
|
};
|
|
}
|
|
|
|
private Axis[] CreateYAxes(OutputDefinition definition)
|
|
{
|
|
return new[]
|
|
{
|
|
new Axis
|
|
{
|
|
Name = string.IsNullOrEmpty(definition.YAxisColumn) ? "Значения" : definition.YAxisColumn,
|
|
TextSize = 12
|
|
}
|
|
};
|
|
}
|
|
|
|
private FrameworkElement CreateEmptyChartMessage(string message)
|
|
{
|
|
var textBlock = new TextBlock
|
|
{
|
|
Text = message,
|
|
HorizontalAlignment = HorizontalAlignment.Center,
|
|
VerticalAlignment = VerticalAlignment.Center,
|
|
FontSize = 16,
|
|
Foreground = new Microsoft.UI.Xaml.Media.SolidColorBrush(Microsoft.UI.Colors.Gray)
|
|
};
|
|
|
|
var border = new Border
|
|
{
|
|
Child = textBlock,
|
|
Background = new Microsoft.UI.Xaml.Media.SolidColorBrush(Microsoft.UI.Colors.Transparent),
|
|
Padding = new Thickness(20)
|
|
};
|
|
|
|
return border;
|
|
}
|
|
|
|
public bool CanVisualize(OutputType type) => type == OutputType.Chart;
|
|
}
|