Vereinsmeisterschaften  22aa7800eae54b428d40e835886cefe1fdefdfdf
This is a software that can be used to manage the internal competition of the swimming club Illertissen called "Vereinsmeisterschaften".
Loading...
Searching...
No Matches
AnalyticsWidgetRacesAges.xaml.cs
1using System.Windows.Input;
2using CommunityToolkit.Mvvm.Input;
3using LiveChartsCore;
4using LiveChartsCore.Defaults;
5using LiveChartsCore.Kernel;
6using LiveChartsCore.Kernel.Events;
7using LiveChartsCore.SkiaSharpView;
8using LiveChartsCore.SkiaSharpView.Painting;
10
12{
16 public partial class AnalyticsWidgetRacesAges : AnalyticsWidgetBase
17 {
18 #region Class WidgetModelRaceAgePoint
19
23 public class WidgetModelRaceAgePoint : WeightedPoint
24 {
25 private int _raceID;
29 public int RaceID
30 {
31 get => _raceID;
32 set { _raceID = value; OnPropertyChanged(); }
33 }
34
35 private ushort _birthYear;
39 public ushort BirthYear
40 {
41 get => _birthYear;
42 set { _birthYear = value; OnPropertyChanged(); }
43 }
44
45 private bool _isDisplayedFaded = false;
49 public bool IsDisplayedFaded
50 {
51 get => _isDisplayedFaded;
52 set { _isDisplayedFaded = value; OnPropertyChanged(); }
53 }
54
62 public WidgetModelRaceAgePoint(ushort birthYear, int numberOccurences, int raceID, int numberRaces) : base(birthYear, numberRaces - raceID, numberOccurences)
63 {
64 RaceID = raceID;
65 }
66 }
67
68 #endregion
69
70 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
71
73
74 public AnalyticsWidgetRacesAges(AnalyticsModuleRacesAges analyticsModule) : base(analyticsModule)
75 {
76 InitializeComponent();
77 PART_scrollViewerChart.SizeChanged += (sender, e) => OnPropertyChanged(nameof(ChartHeight));
78 Refresh();
79 }
80
81 public override string Icon => "\uED55";
82
83 public override void Refresh()
84 {
85 AgeSpanPoints = AgesPerRaceReversed.SelectMany(model =>
86 model.BirthYears.GroupBy(year => year)
87 .Select(group =>
89 group.Key, // year
90 group.Count(),
91 model.RaceID,
93 .ToList();
94
95 _yAxis = new Axis
96 {
97 IsVisible = true,
99 NamePaint = ColorPaintMahAppsText,
100 NameTextSize = ANALYTICS_WIDGET_AXIS_TEXTSIZE_DEFAULT,
101 TextSize = ANALYTICS_WIDGET_AXIS_TEXTSIZE_DEFAULT,
102 MinStep = 1,
103 Labels = RaceIds.Select(id => $"#{id}").ToArray(),
104 LabelsDensity = 0,
105 LabelsPaint = ColorPaintMahAppsText,
106 SeparatorsPaint = IsPointHovered ? ColorPaintMahAppsBackground : COLORPAINT_SEPARATORS,
107 CrosshairPaint = ColorPaintMahAppsText,
108 CrosshairSnapEnabled = true
109 };
110
111 OnPropertyChanged(nameof(AgesPerRaceSeries));
112 OnPropertyChanged(nameof(XAxes));
113 OnPropertyChanged(nameof(YAxes));
114 base.Refresh();
115 }
116
120 public List<AnalyticsModuleRacesAges.ModelRaceAges> AgesPerRaceReversed => _analyticsModule?.AgeListsPerRace?.AsEnumerable().Reverse().ToList() ?? new List<AnalyticsModuleRacesAges.ModelRaceAges>();
121
125 public int NumberRaces => AgesPerRaceReversed.Count;
126
130 public List<int> RaceIds => AgesPerRaceReversed.Select(r => r.RaceID).ToList();
131
136 public List<WidgetModelRaceAgePoint> AgeSpanPoints { get; set; } = new List<WidgetModelRaceAgePoint>();
137
141 public ISeries[] AgesPerRaceSeries
142 {
143 get
144 {
145 if (_analyticsModule == null || AnalyticsAvailable == false) return null;
146
147 List<ISeries> seriesList = new List<ISeries>();
148 ISeries series = new ScatterSeries<WidgetModelRaceAgePoint>
149 {
150 Values = AgeSpanPoints,
151 YToolTipLabelFormatter = point => $"{Properties.Resources.RaceString} #{point.Model.RaceID}" +
152 Environment.NewLine +
153 $"{point.Model.X}" + (point.Model.Weight > 1 ? $" ({point.Model.Weight}x)" : ""),
154 Stroke = new SolidColorPaint(ColorPaintMahAppsAccent.Color, 4),
155 Fill = new SolidColorPaint(ColorPaintMahAppsAccent.Color.WithAlpha(100)),
156 MinGeometrySize = 15,
157 GeometrySize = 22
158 }
159 .OnPointMeasured(point =>
160 {
161 if (point.Visual is null) return;
162
163 // modify alpha channel for transparency
164 SolidColorPaint normalPaintFill = new SolidColorPaint(ColorPaintMahAppsAccent.Color.WithAlpha(100));
165 SolidColorPaint fadedPaintFill = new SolidColorPaint(ColorPaintMahAppsAccent.Color.WithAlpha(20));
166 SolidColorPaint normalPaintStroke = new SolidColorPaint(ColorPaintMahAppsAccent.Color, 4);
167 SolidColorPaint fadedPaintStroke = new SolidColorPaint(ColorPaintMahAppsAccent.Color.WithAlpha(30), 4);
168
169 point.Visual.Fill = point.Model.IsDisplayedFaded ? fadedPaintFill : normalPaintFill;
170 point.Visual.Stroke = point.Model.IsDisplayedFaded ? fadedPaintStroke : normalPaintStroke;
171 });
172 seriesList.Add(series);
173 return seriesList.ToArray();
174 }
175 }
176
180 public double ChartMaxRowWidth => 30;
181
186 public double ChartHeight => Math.Max(PART_scrollViewerChart.ActualHeight, NumberRaces * ChartMaxRowWidth);
187
191 public Axis[] XAxes =>
192 [
193 new Axis
194 {
195 IsVisible = true,
197 NamePaint = ColorPaintMahAppsText,
198 NameTextSize = ANALYTICS_WIDGET_AXIS_TEXTSIZE_DEFAULT,
199 LabelsPaint = ColorPaintMahAppsText,
200 TextSize = ANALYTICS_WIDGET_AXIS_TEXTSIZE_DEFAULT,
201 MinStep = 1
202 }
203 ];
204
205 // Private field used here for y axis because it contains properties that change dynamically during mouse hovering
206 private Axis _yAxis;
210 public Axis[] YAxes => [_yAxis];
211
212 private bool _isPointHovered;
216 public bool IsPointHovered
217 {
218 get => _isPointHovered;
219 set
220 {
221 _isPointHovered = value;
222 OnPropertyChanged();
223
224 _yAxis?.SeparatorsPaint = IsPointHovered ? ColorPaintMahAppsBackground : COLORPAINT_SEPARATORS;
225 OnPropertyChanged(nameof(YAxes));
226 }
227 }
228
232 public ICommand ChartHoveredPointsChangedCommand => new RelayCommand<HoverCommandArgs>(args =>
233 {
234 bool hasPoint = args?.NewPoints != null && args.NewPoints.Any();
235 IsPointHovered = hasPoint;
236
237 if (!hasPoint)
238 {
239 ClearPointFading();
240 }
241 else
242 {
243 ChartPoint point = args?.NewPoints?.FirstOrDefault();
244 WidgetModelRaceAgePoint model = (WidgetModelRaceAgePoint)point.Context.DataSource;
245
246 UpdatePointFading(model.RaceID);
247
248 args.Chart.CoreChart.Update(new ChartUpdateParams { IsAutomaticUpdate = false, Throttling = false });
249 }
250 });
251
252 private void UpdatePointFading(int hoveredRaceID)
253 => AgeSpanPoints.ForEach(p => p.IsDisplayedFaded = (p.RaceID != hoveredRaceID));
254 private void ClearPointFading()
255 => AgeSpanPoints.ForEach(p => p.IsDisplayedFaded = false);
256 }
257}
Analytics module to calculate the ages for each race.
Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
static string BirthYearString
Sucht eine lokalisierte Zeichenfolge, die Birth Year ähnelt.
static string RaceString
Sucht eine lokalisierte Zeichenfolge, die Race ähnelt.
SolidColorPaint ColorPaintMahAppsBackground
SolidColorPaint that represents the MahApps.Brushes.ThemeBackground brush.
SolidColorPaint ColorPaintMahAppsAccent
SolidColorPaint that represents the MahApps.Brushes.Accent brush.
bool AnalyticsAvailable
Indicating if the analytics module has data.
IAnalyticsModule AnalyticsModule
Analytics module used by this user control.
SolidColorPaint ColorPaintMahAppsText
SolidColorPaint that represents the MahApps.Brushes.Text brush.
AnalyticsWidgetBase(IAnalyticsModule analyticsModule)
Constructor of the AnalyticsWidgetBase
WidgetModelRaceAgePoint(ushort birthYear, int numberOccurences, int raceID, int numberRaces)
Constructor for one WidgetModelRaceAgePoint
double ChartHeight
Calculate the chart height manually to support scrolling of the ScatterSeries by the surrounding scro...
List< WidgetModelRaceAgePoint > AgeSpanPoints
List with points that are displayed in the scatter chart.
override void Refresh()
Refresh the data displayed in the user control.
ICommand ChartHoveredPointsChangedCommand
Called, when a new point in the chart is hovered or when no point is hovered anymore.
List< AnalyticsModuleRacesAges.ModelRaceAges > AgesPerRaceReversed
Get the AnalyticsModuleRacesAges.AgeListsPerRace in reversed order.