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.
363 lines
14 KiB
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));
|
|
}
|
|
}
|