You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
SmartAquaViewer/SmartAquaViewer/ViewModel/EnergyViewModel.cs

363 lines
14 KiB

using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Input;
using SmartAquaViewer.Controls;
using SmartAquaViewer.DataAnalysis;
using SmartAquaViewer.Model;
namespace SmartAquaViewer.ViewModel
{
public class EnergyViewModel : INotifyPropertyChanged
{
public GraphControlViewModel GraphControlVM { get; } = new GraphControlViewModel();
public ObservableCollection<GraphType> GraphTypes { get; }
public ReadOnlyObservableCollection<WaterQualityVO> WaterQualityList { get; set; }
private double _totalEnergy;
public double TotalEnergy
{
get => _totalEnergy;
set
{
if (_totalEnergy != value)
{
_totalEnergy = value;
OnPropertyChanged();
}
}
}
private double _totalSandFilterEnergy;
public double TotalSandFilterEnergy
{
get => _totalSandFilterEnergy;
set
{
if (_totalSandFilterEnergy != value)
{
_totalSandFilterEnergy = value;
OnPropertyChanged();
}
}
}
private double _totalCirculationPumpEnergy;
public double TotalCirculationPumpEnergy
{
get => _totalCirculationPumpEnergy;
set
{
if (_totalCirculationPumpEnergy != value)
{
_totalCirculationPumpEnergy = value;
OnPropertyChanged();
}
}
}
private double _totalHeatPumpEnergy;
public double TotalHeatPumpEnergy
{
get => _totalHeatPumpEnergy;
set
{
if (_totalHeatPumpEnergy != value)
{
_totalHeatPumpEnergy = value;
OnPropertyChanged();
}
}
}
private double _totalAirBlowerEnergy;
public double TotalAirBlowerEnergy
{
get => _totalAirBlowerEnergy;
set
{
if (_totalAirBlowerEnergy != value)
{
_totalAirBlowerEnergy = value;
OnPropertyChanged();
}
}
}
private double _totalOzoneGeneratorEnergy;
public double TotalOzoneGeneratorEnergy
{
get => _totalOzoneGeneratorEnergy;
set
{
if (_totalOzoneGeneratorEnergy != value)
{
_totalOzoneGeneratorEnergy = value;
OnPropertyChanged();
}
}
}
private double _totalUVSterilizerEnergy;
public double TotalUVSterilizerEnergy
{
get => _totalUVSterilizerEnergy;
set
{
if (_totalUVSterilizerEnergy != value)
{
_totalUVSterilizerEnergy = value;
OnPropertyChanged();
}
}
}
private double _totalOzoneDissolverEnergy;
public double TotalOzoneDissolverEnergy
{
get => _totalOzoneDissolverEnergy;
set
{
if (_totalOzoneDissolverEnergy != value)
{
_totalOzoneDissolverEnergy = value;
OnPropertyChanged();
}
}
}
private double _totalExcessOzoneDestroyerEnergy;
public double TotalExcessOzoneDestroyerEnergy
{
get => _totalExcessOzoneDestroyerEnergy;
set
{
if (_totalExcessOzoneDestroyerEnergy != value)
{
_totalExcessOzoneDestroyerEnergy = value;
OnPropertyChanged();
}
}
}
private int _selectedGraphIndex = -1;
public int SelectedGraphIndex
{
get => _selectedGraphIndex;
set
{
if (_selectedGraphIndex != value)
{
_selectedGraphIndex = value;
OnPropertyChanged();
// 인덱스가 바뀌면 enum도 맞춰준다
if (value >= 0 && value < GraphTypes.Count)
SelectedGraphType = GraphTypes[value];
}
}
}
private GraphType _selectedGraphType;
public GraphType SelectedGraphType
{
get => _selectedGraphType;
set
{
if (_selectedGraphType != value)
{
_selectedGraphType = value;
OnPropertyChanged();
OnPropertyChanged(nameof(ShowXSelector));
RebuildFieldCandidates();
var idx = GraphTypes.IndexOf(value);
if (idx != -1 && idx != _selectedGraphIndex)
{
_selectedGraphIndex = idx;
OnPropertyChanged(nameof(SelectedGraphIndex));
}
}
}
}
private StepFieldKind _selectedKind = StepFieldKind.Energy; // 기본값은 센서
public StepFieldKind SelectedKind
{
get => _selectedKind;
set
{
if (_selectedKind != value)
{
_selectedKind = value;
OnPropertyChanged();
}
}
}
public bool ShowXSelector => SelectedGraphType == GraphType.SCATTER;
// [필드 후보 목록] 탭/시스템에 따라 달라짐
public ObservableCollection<FieldItem> AvailableFields { get; } = new();
// [X축 후보/선택]
public ObservableCollection<FieldItem> XFieldCandidates { get; } = new();
private FieldItem? _selectedXField;
public FieldItem? SelectedXField
{
get => _selectedXField;
set { if (_selectedXField != value) { _selectedXField = value; OnPropertyChanged(); } }
}
// [Y축 후보/선택] — Line/Step: 다중, Scatter/Box: 단일
public ObservableCollection<FieldItem> YFieldCandidates { get; } = new();
// 다중 선택(Y)용
public ObservableCollection<FieldItem> SelectedYFields { get; } = new();
// 단일 선택(Y)용
private FieldItem? _selectedYField;
public FieldItem? SelectedYField
{
get => _selectedYField;
set { if (_selectedYField != value) { _selectedYField = value; OnPropertyChanged(); } }
}
private bool _useAverage;
public bool UseAverage { get => _useAverage; set { _useAverage = value; OnPropertyChanged(); } }
private bool _showMarkers;
public bool ShowMarkers { get => _showMarkers; set { _showMarkers = value; OnPropertyChanged(); } }
private bool _showLegends;
public bool ShowLegends { get => _showLegends; set { _showLegends = value; OnPropertyChanged(); } }
private bool _isDonut;
public bool IsDonut { get => _isDonut; set { _isDonut = value; OnPropertyChanged(); } }
public ICommand DrawGraphCommand { get; }
public EnergyViewModel()
{
GraphTypes = new ObservableCollection<GraphType>
{
GraphType.LINE,
GraphType.STACKAREA,
GraphType.PIE
};
WaterQualityList = Datas.Instance.WaterQualityView;
TotalSandFilterEnergy = WaterQualityList.Sum(vo => vo.Filtering.SandFilterEnergy);
TotalCirculationPumpEnergy = WaterQualityList.Sum(vo => vo.Filtering.CirculationPumpEnergy);
TotalHeatPumpEnergy = WaterQualityList.Sum(vo => vo.Filtering.HeatPumpEnergy);
TotalAirBlowerEnergy = WaterQualityList.Sum(vo => vo.Filtering.AirBlowerEnergy);
TotalOzoneGeneratorEnergy = WaterQualityList.Sum(vo => vo.Sterilizing.OzoneGeneratorEnergy);
TotalUVSterilizerEnergy = WaterQualityList.Sum(vo => vo.Sterilizing.UVSterilizerEnergy);
TotalOzoneDissolverEnergy = WaterQualityList.Sum(vo => vo.Sterilizing.OzoneDissolverEnergy);
TotalExcessOzoneDestroyerEnergy = WaterQualityList.Sum(vo => vo.Sterilizing.ExcessOzoneDestroyerEnergy);
TotalEnergy = WaterQualityList.Sum(vo => vo.TotalEnergy);
SelectedKind = StepFieldKind.Energy; // 기본적으로 에너지 관련 필드만 표시
DrawGraphCommand = new RelayCommand(DrawGraph);
RebuildAvailableFields();
RebuildFieldCandidates();
}
private void DrawGraph(object obj)
{
switch (SelectedGraphType)
{
case GraphType.LINE:
GraphControlVM.SetMultiLineGraph(WaterQualityList.ToList(), SelectedYFields, DataType.Energy, ShowMarkers, ShowLegends);
break;
case GraphType.STACKAREA:
GraphControlVM.SetStackAreaPlot(WaterQualityList.ToList(), SelectedYFields, DataType.Energy, ShowMarkers, ShowLegends);
break;
case GraphType.PIE:
GraphControlVM.SetPieChart(WaterQualityList.ToList(), SelectedYFields, DataType.Energy, UseAverage, IsDonut);
break;
default:
break;
}
}
private void RebuildAvailableFields()
{
AvailableFields.Clear();
// 공통 시간
AvailableFields.Add(new FieldItem { Name = "RecordedTime", Display = "시간", DataType = typeof(DateTime) });
AvailableFields.Add(new FieldItem { Name = "TotalEnergy", Display = "총 전력", DataType = typeof(double), Kind = StepFieldKind.Energy });
AvailableFields.Add(new FieldItem { Name = "Filtering.SandFilterEnergy", Display = "모래여과기", DataType = typeof(double), Kind = StepFieldKind.Energy });
AvailableFields.Add(new FieldItem { Name = "Filtering.CirculationPumpEnergy", Display = "순환펌프", DataType = typeof(double), Kind = StepFieldKind.Energy });
AvailableFields.Add(new FieldItem { Name = "Filtering.HeatPumpEnergy", Display = "히트펌프", DataType = typeof(double), Kind = StepFieldKind.Energy });
AvailableFields.Add(new FieldItem { Name = "Filtering.AirBlowerEnergy", Display = "에어브로와", DataType = typeof(double), Kind = StepFieldKind.Energy });
AvailableFields.Add(new FieldItem { Name = "Sterilizing.OzoneGeneratorEnergy", Display = "오존발생기", DataType = typeof(double), Kind = StepFieldKind.Energy });
AvailableFields.Add(new FieldItem { Name = "Sterilizing.UVSterilizerEnergy", Display = "자외선 살균기", DataType = typeof(double), Kind = StepFieldKind.Energy });
AvailableFields.Add(new FieldItem { Name = "Sterilizing.OzoneDissolverEnergy", Display = "오존용해장치", DataType = typeof(double), Kind = StepFieldKind.Energy });
AvailableFields.Add(new FieldItem { Name = "Sterilizing.ExcessOzoneDestroyerEnergy", Display = "배오존장치", DataType = typeof(double), Kind = StepFieldKind.Energy });
}
private void RebuildFieldCandidates()
{
// 후보 초기화
XFieldCandidates.Clear();
YFieldCandidates.Clear();
// X축: 시간 우선
foreach (var f in AvailableFields)
{
XFieldCandidates.Add(f);
if (SelectedGraphType == GraphType.LINE || SelectedGraphType == GraphType.STACKAREA) break;
}
SelectedXField = AvailableFields.FirstOrDefault(f => f.DataType == typeof(DateTime))
?? AvailableFields.FirstOrDefault();
IEnumerable<FieldItem> src = AvailableFields.Where(f => f.Kind == SelectedKind);
if (SelectedGraphType is GraphType.LINE or GraphType.STACKAREA or GraphType.PIE)
{
// 수치형만 (LINE/STACKAREA/PIE 연속값 위주)
src = src.Where(f => f.DataType == typeof(double));
}
// Y축 후보: 수치형
foreach (var f in src)
{
if (SelectedGraphType is GraphType.STACKAREA or GraphType.PIE && f.Name.Equals("TotalEnergy")) continue;
YFieldCandidates.Add(f);
}
// 기본 선택 세팅 (타입별)
SelectedYFields.Clear();
SelectedYField = null;
switch (SelectedGraphType)
{
case GraphType.LINE:
//var def = YFieldCandidates.FirstOrDefault();
//if (def != null) SelectedYFields.Add(def);
break;
case GraphType.STACKAREA:
SelectedYField = YFieldCandidates.FirstOrDefault();
break;
case GraphType.PIE:
//SelectedYField = YFieldCandidates.FirstOrDefault();
break;
}
OnPropertyChanged(nameof(SelectedYFields));
}
public event PropertyChangedEventHandler? PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string? name = null)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}