From 2541f3f8cca228d334124697275f548d76269577 Mon Sep 17 00:00:00 2001 From: tayttt Date: Wed, 25 Sep 2024 03:13:24 +0800 Subject: [PATCH] 2024-09-25 V1.0.0.0 --- Txgy.DataStat/App.xaml | 2 +- Txgy.DataStat/App.xaml.cs | 25 +- Txgy.DataStat/IServices/IDataService.cs | 17 + Txgy.DataStat/Models/City.cs | 28 ++ Txgy.DataStat/Models/CustomLegend.cs | 111 +++++ Txgy.DataStat/Models/EventTimeStatsResult.cs | 14 + Txgy.DataStat/Models/FracCurveDataSchme.cs | 22 + Txgy.DataStat/Models/FracDataReader.cs | 97 +++++ Txgy.DataStat/Models/PosData.cs | 16 + Txgy.DataStat/Services/DataService.cs | 47 +++ Txgy.DataStat/Services/PosDataService.cs | 59 +++ Txgy.DataStat/Txgy.DataStat.csproj | 2 +- .../ViewModels/LoadDataFromFileViewModel.cs | 73 ++++ .../ViewModels/MainWindowViewModel.cs | 384 +++++++++++++++++- .../ViewModels/TestItemsSourceViewModel.cs | 16 + .../ViewModels/UserControlAViewModel.cs | 25 ++ .../ViewModels/UserControlBViewModel.cs | 23 ++ Txgy.DataStat/Views/CustomDialog.xaml | 42 ++ Txgy.DataStat/Views/CustomDialog.xaml.cs | 28 ++ Txgy.DataStat/Views/LoadDataFromFileView.xaml | 50 +++ .../Views/LoadDataFromFileView.xaml.cs | 31 ++ Txgy.DataStat/Views/MainWindow.xaml | 291 ++++++++++++- Txgy.DataStat/Views/TestItemsSource.xaml | 23 ++ Txgy.DataStat/Views/TestItemsSource.xaml.cs | 38 ++ Txgy.DataStat/Views/UserControlA.xaml | 16 + Txgy.DataStat/Views/UserControlA.xaml.cs | 31 ++ Txgy.DataStat/Views/UserControlB.xaml | 14 + Txgy.DataStat/Views/UserControlB.xaml.cs | 31 ++ 28 files changed, 1547 insertions(+), 9 deletions(-) create mode 100644 Txgy.DataStat/IServices/IDataService.cs create mode 100644 Txgy.DataStat/Models/City.cs create mode 100644 Txgy.DataStat/Models/CustomLegend.cs create mode 100644 Txgy.DataStat/Models/EventTimeStatsResult.cs create mode 100644 Txgy.DataStat/Models/FracCurveDataSchme.cs create mode 100644 Txgy.DataStat/Models/FracDataReader.cs create mode 100644 Txgy.DataStat/Models/PosData.cs create mode 100644 Txgy.DataStat/Services/DataService.cs create mode 100644 Txgy.DataStat/Services/PosDataService.cs create mode 100644 Txgy.DataStat/ViewModels/LoadDataFromFileViewModel.cs create mode 100644 Txgy.DataStat/ViewModels/TestItemsSourceViewModel.cs create mode 100644 Txgy.DataStat/ViewModels/UserControlAViewModel.cs create mode 100644 Txgy.DataStat/ViewModels/UserControlBViewModel.cs create mode 100644 Txgy.DataStat/Views/CustomDialog.xaml create mode 100644 Txgy.DataStat/Views/CustomDialog.xaml.cs create mode 100644 Txgy.DataStat/Views/LoadDataFromFileView.xaml create mode 100644 Txgy.DataStat/Views/LoadDataFromFileView.xaml.cs create mode 100644 Txgy.DataStat/Views/TestItemsSource.xaml create mode 100644 Txgy.DataStat/Views/TestItemsSource.xaml.cs create mode 100644 Txgy.DataStat/Views/UserControlA.xaml create mode 100644 Txgy.DataStat/Views/UserControlA.xaml.cs create mode 100644 Txgy.DataStat/Views/UserControlB.xaml create mode 100644 Txgy.DataStat/Views/UserControlB.xaml.cs diff --git a/Txgy.DataStat/App.xaml b/Txgy.DataStat/App.xaml index cbf26f0..8dcd58e 100644 --- a/Txgy.DataStat/App.xaml +++ b/Txgy.DataStat/App.xaml @@ -1,7 +1,7 @@  diff --git a/Txgy.DataStat/App.xaml.cs b/Txgy.DataStat/App.xaml.cs index d4d02fd..286a7aa 100644 --- a/Txgy.DataStat/App.xaml.cs +++ b/Txgy.DataStat/App.xaml.cs @@ -1,6 +1,11 @@ -using System.Configuration; +using Microsoft.Extensions.DependencyInjection; +using System.Configuration; using System.Data; using System.Windows; +using Txgy.DataStat.IServices; +using Txgy.DataStat.Services; +using Txgy.DataStat.ViewModels; +using Txgy.DataStat.Views; namespace Txgy.DataStat { @@ -9,6 +14,24 @@ namespace Txgy.DataStat /// public partial class App : Application { + public new static App Current => (App)Application.Current; + + public IServiceProvider Services { get; } + + public App() + { + var services = new ServiceCollection(); + + // Register services + services.AddSingleton(); + + // Register view models + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + + Services = services.BuildServiceProvider(); + } } } diff --git a/Txgy.DataStat/IServices/IDataService.cs b/Txgy.DataStat/IServices/IDataService.cs new file mode 100644 index 0000000..7aaf541 --- /dev/null +++ b/Txgy.DataStat/IServices/IDataService.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Txgy.DataStat.Models; + +namespace Txgy.DataStat.IServices +{ + public interface IDataService + { + ObservableCollection Cities { get; } + void LoadCitiesFromFile(string filePath); + void SaveCitiesToFile(string filePath); + } +} diff --git a/Txgy.DataStat/Models/City.cs b/Txgy.DataStat/Models/City.cs new file mode 100644 index 0000000..3edbebf --- /dev/null +++ b/Txgy.DataStat/Models/City.cs @@ -0,0 +1,28 @@ +using CommunityToolkit.Mvvm.ComponentModel; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Txgy.DataStat.Models +{ + public class City : ObservableObject + { + private string _name; + private string _area; + + public string Name + { + get => _name; + set => SetProperty(ref _name, value); + } + + public string Area + { + get => _area; + set => SetProperty(ref _area, value); + } + } + +} diff --git a/Txgy.DataStat/Models/CustomLegend.cs b/Txgy.DataStat/Models/CustomLegend.cs new file mode 100644 index 0000000..d8dab76 --- /dev/null +++ b/Txgy.DataStat/Models/CustomLegend.cs @@ -0,0 +1,111 @@ +using LiveChartsCore.Drawing; +using LiveChartsCore.Kernel.Events; +using LiveChartsCore.Kernel.Sketches; +using LiveChartsCore.Measure; +using LiveChartsCore.SkiaSharpView.Drawing.Geometries; +using LiveChartsCore.SkiaSharpView.Drawing; +using LiveChartsCore.SkiaSharpView.Painting; +using LiveChartsCore.SkiaSharpView.VisualElements; +using LiveChartsCore.VisualElements; +using LiveChartsCore; +using SkiaSharp; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using LiveChartsCore.SkiaSharpView; +using System.Windows; + +namespace Txgy.DataStat.Models +{ + public class CustomLegend : IChartLegend + { + private static readonly int s_zIndex = 10050; + private readonly StackPanel _stackPanel = new(); + private readonly SolidColorPaint _fontPaint = new(new SKColor(30, 20, 30)) + { + SKTypeface = SKTypeface.FromFamilyName("Arial", SKFontStyle.Bold), + ZIndex = s_zIndex + 1 + }; + + public void Draw(Chart chart) + { + var legendPosition = chart.GetLegendPosition(); + + _stackPanel.X = legendPosition.X; + _stackPanel.Y = legendPosition.Y; + + chart.AddVisual(_stackPanel); + if (chart.LegendPosition == LegendPosition.Hidden) chart.RemoveVisual(_stackPanel); + } + + public LvcSize Measure(Chart chart) + { + _stackPanel.Orientation = ContainerOrientation.Horizontal; + _stackPanel.HorizontalAlignment = Align.End; + _stackPanel.MaxWidth = double.MaxValue; + _stackPanel.MaxHeight = chart.ControlSize.Height; + + // clear the previous elements. + foreach (var visual in _stackPanel.Children.ToArray()) + { + _ = _stackPanel.Children.Remove(visual); + chart.RemoveVisual(visual); + } + + var theme = LiveCharts.DefaultSettings.GetTheme(); + + foreach (var series in chart.Series.Where(x => x.IsVisibleAtLegend)) + { + var color = new SolidColorPaint(theme.GetSeriesColor(series).AsSKColor()) { ZIndex=s_zIndex+1}; + var panel = new StackPanel + { + + Padding = new Padding(12, 6), + VerticalAlignment = Align.Middle, + HorizontalAlignment = Align.End, + Children = + { + new SVGVisual + { + Path = SKPath.ParseSvgPathData(SVGPoints.Square), + Width = 25, + Height = 25, + ClippingMode = ClipMode.None, // required on legends // mark + Fill=color + //Fill = new SolidColorPaint(theme.GetSeriesColor(series).AsSKColor()) + //{ + // ZIndex = s_zIndex + 1 + //} + }, + new LabelVisual + { + Text = series.Name ?? string.Empty, + Paint = _fontPaint, + TextSize = 15, + ClippingMode = ClipMode.None, // required on legends // mark + Padding = new Padding(8, 0, 0, 0), + VerticalAlignment = Align.Start, + HorizontalAlignment = Align.Start + } + } + }; + + panel.PointerDown += GetPointerDownHandler(series); + _stackPanel.Children.Add(panel); + } + + return _stackPanel.Measure(chart); + } + + private static VisualElementHandler GetPointerDownHandler( + IChartSeries series) + { + return (visual, args) => + { + series.IsVisible = !series.IsVisible; + }; + } + } +} diff --git a/Txgy.DataStat/Models/EventTimeStatsResult.cs b/Txgy.DataStat/Models/EventTimeStatsResult.cs new file mode 100644 index 0000000..38e5765 --- /dev/null +++ b/Txgy.DataStat/Models/EventTimeStatsResult.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Txgy.DataStat.Models +{ + public class EventTimeStatsResult + { + public double time { get; set; } + public double total { get; set; } + } +} diff --git a/Txgy.DataStat/Models/FracCurveDataSchme.cs b/Txgy.DataStat/Models/FracCurveDataSchme.cs new file mode 100644 index 0000000..9d68808 --- /dev/null +++ b/Txgy.DataStat/Models/FracCurveDataSchme.cs @@ -0,0 +1,22 @@ +using CommunityToolkit.Mvvm.ComponentModel; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Txgy.DataStat.Models +{ + public class FracCurveDataSchme : ObservableObject + { + public int FirstDataRow { get; set; } = 3; + public int TimeCol { get; set; } = 1; + public int SurPreCol { get; set; } = 2; + public int CasingPreCol { get; set; } = 3; + public int SlurryRateCol { get; set; } = 7; + public string Separator { get; set; } = "tab"; + public string DPoint { get; set; } = "dot"; + + + } +} diff --git a/Txgy.DataStat/Models/FracDataReader.cs b/Txgy.DataStat/Models/FracDataReader.cs new file mode 100644 index 0000000..d3b7c84 --- /dev/null +++ b/Txgy.DataStat/Models/FracDataReader.cs @@ -0,0 +1,97 @@ +using CommunityToolkit.Mvvm.ComponentModel; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Txgy.DataStat.Models +{ + public partial class FracDataReader : ObservableObject + { + [ObservableProperty] + bool absoluteTime = false; + + [ObservableProperty] + string filePath = ""; + public int FirstDataRow { get; set; } = 3; + public int TimeCol { get; set; } = 1; + public int SurPreCol { get; set; } = 2; + public int CasingPreCol { get; set; } = 3; + public int SlurryRateCol { get; set; } = 7; + public string Separator { get; set; } = "tab"; + public string DPoint { get; set; } = "dot"; + + public double skipValue = 1; + + public List ReadData(double timeSpan) + { + var dataRows = new List(); + //try + { + if (FilePath != "") + { + string allTexts = File.ReadAllText(FilePath); + string[] rows = allTexts.Split('\n', StringSplitOptions.RemoveEmptyEntries); + if (rows.Length > 0) + { + var sep = GetDelimiter(Separator); + DateTime startTime = new DateTime(); + if(AbsoluteTime) + startTime = DateTime.Parse(rows[FirstDataRow - 1].Split(sep)[TimeCol - 1]); + + for (int i = FirstDataRow - 1; i < rows.Length; i++) + { + + var cols = rows[i].Trim().Split(sep, StringSplitOptions.RemoveEmptyEntries); + //double skip = double.Parse(cols[TimeCol - 1].Trim()) / skipValue; + //double skip = Math.Floor(double.Parse(cols[TimeCol - 1].Trim())); + //Debug.WriteLine(skip); + if (cols.Length > 0) + { + //double skip = double.Parse(cols[TimeCol - 1].Trim()); + //if (Math.Abs(skip % skipValue)<1e-10) + { + var fracRow = new FracDataRow + { + time = AbsoluteTime? (DateTime.Parse(cols[TimeCol - 1])-startTime).TotalSeconds/ timeSpan : double.Parse(cols[TimeCol - 1].Trim()), + surPre = double.Parse(cols[SurPreCol - 1].Trim()), + casingPre = double.Parse(cols[CasingPreCol - 1].Trim()), + slurryRate = double.Parse(cols[SlurryRateCol - 1].Trim()), + }; + dataRows.Add(fracRow); + } + } + } + } + } + } + //catch (Exception ex) + //{ + // Console.WriteLine($"Error reading file: {ex.Message}"); + //} + return dataRows; + } + char GetDelimiter(string delimiterName) + { + return delimiterName.ToLower() switch + { + "tab" => '\t', + "comma" => ',', + "semicolon" => ';', + "dot" => '.', + _ => throw new ArgumentException("Unsupported delimiter") + }; + } + + } + public class FracDataRow + { + public double time { get; set; } + public double surPre { get; set; } + public double casingPre { get; set; } + public double slurryRate { get; set; } + } +} diff --git a/Txgy.DataStat/Models/PosData.cs b/Txgy.DataStat/Models/PosData.cs new file mode 100644 index 0000000..4c17efe --- /dev/null +++ b/Txgy.DataStat/Models/PosData.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Txgy.DataStat.Models +{ + public class PosData + { + public double X { get; set; } + public double Y { get; set; } + public double Z { get; set; } + public double Time { get; set; } + } +} diff --git a/Txgy.DataStat/Services/DataService.cs b/Txgy.DataStat/Services/DataService.cs new file mode 100644 index 0000000..77815ef --- /dev/null +++ b/Txgy.DataStat/Services/DataService.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Txgy.DataStat.IServices; +using Txgy.DataStat.Models; + +namespace Txgy.DataStat.Services +{ + public class DataService : IDataService + { + public ObservableCollection Cities { get; } + + public DataService() + { + Cities = new ObservableCollection + { + new City { Name = "City1", Area = "Area1" }, + new City { Name = "City2", Area = "Area2" }, + new City { Name = "City3", Area = "Area3" }, + }; + } + + public void LoadCitiesFromFile(string filePath) + { + // 假设文件是CSV格式,包含Name和Area两列 + var lines = System.IO.File.ReadAllLines(filePath); + Cities.Clear(); + foreach (var line in lines) + { + var parts = line.Split(','); + if (parts.Length == 2) + { + Cities.Add(new City { Name = parts[0], Area = parts[1] }); + } + } + } + + public void SaveCitiesToFile(string filePath) + { + var lines = Cities.Select(city => $"{city.Name},{city.Area}"); + System.IO.File.WriteAllLines(filePath, lines); + } + } +} diff --git a/Txgy.DataStat/Services/PosDataService.cs b/Txgy.DataStat/Services/PosDataService.cs new file mode 100644 index 0000000..e00ae84 --- /dev/null +++ b/Txgy.DataStat/Services/PosDataService.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Txgy.DataStat.Models; + +namespace Txgy.DataStat.Services +{ + public static class PosDataService + { + public static List ReadPosDataFromFile(string filePath) + { + List datas = new List(); + string str = File.ReadAllText(filePath); + string[] rows = str.Trim().Split('\n'); + for (int i = 1; i < rows.Length; i++) + { + var cols = rows[i].Trim().Split("\t", StringSplitOptions.RemoveEmptyEntries); + var pos = new PosData + { + X = double.Parse(cols[0]), + Y = double.Parse(cols[1]), + Z = double.Parse(cols[2]), + Time = double.Parse(cols[3]), + }; + datas.Add(pos); + } + return datas; + } + + public static List StatsTimeFreq(List datas, int StatsStep) + { + List results = new List(); + int statsCount = (int)((float)(datas[datas.Count - 1].Time) / StatsStep) + 1; + int[] slArr = new int[statsCount]; + float[] sjArr = new float[statsCount]; + + int curIndex = 0; + for (int i = 0; i < slArr.Length; i++) + { + int curSj = (i + 1) * (int)StatsStep; + sjArr[i] = (float)curSj / StatsStep; + while (datas[curIndex].Time < curSj) + { + slArr[i]++; + curIndex++; + if (curIndex >= datas.Count) + { + break; + } + } + results.Add(new EventTimeStatsResult { time = sjArr[i], total = slArr[i] }); + } + return results; + } + } +} diff --git a/Txgy.DataStat/Txgy.DataStat.csproj b/Txgy.DataStat/Txgy.DataStat.csproj index cfcb12a..e8fbeda 100644 --- a/Txgy.DataStat/Txgy.DataStat.csproj +++ b/Txgy.DataStat/Txgy.DataStat.csproj @@ -13,13 +13,13 @@ + - diff --git a/Txgy.DataStat/ViewModels/LoadDataFromFileViewModel.cs b/Txgy.DataStat/ViewModels/LoadDataFromFileViewModel.cs new file mode 100644 index 0000000..65aa850 --- /dev/null +++ b/Txgy.DataStat/ViewModels/LoadDataFromFileViewModel.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +using HandyControl.Controls; +using Txgy.DataStat.IServices; +using Txgy.DataStat.Models; +using Txgy.DataStat.Services; +using Txgy.DataStat.Views; + +namespace Txgy.DataStat.ViewModels +{ + public partial class LoadDataFromFileViewModel : ObservableObject + { + private readonly IDataService _dataService; + public ObservableCollection Cities => _dataService.Cities; + + public ObservableCollection C2 => new ObservableCollection { new City { Name="河北",Area="100"} }; + + [ObservableProperty] + string selectedFilePath = ""; + + [ObservableProperty] + string saveFilePath = ""; + + [RelayCommand] + void ChooseFile() + { + var openFileDialog = new Microsoft.Win32.OpenFileDialog(); + if (openFileDialog.ShowDialog() == true) + { + SelectedFilePath = openFileDialog.FileName; + } + } + + [RelayCommand] + void LoadCities() + { + if (!string.IsNullOrEmpty(SelectedFilePath)) + _dataService.LoadCitiesFromFile(SelectedFilePath); + } + + [RelayCommand] + void ChooseSaveFile() + { + var saveFileDialog = new Microsoft.Win32.SaveFileDialog(); + saveFileDialog.Filter = "City files (*.txt)|*.txt"; + if (saveFileDialog.ShowDialog() == true) + { + SaveFilePath = saveFileDialog.FileName; + } + } + + [RelayCommand] + void SaveCities() + { + if (!string.IsNullOrEmpty(SaveFilePath)) + { + _dataService.SaveCitiesToFile(SaveFilePath); + Dialog.Show(new CustomDialog()); + } + } + + public LoadDataFromFileViewModel(IDataService dataService) + { + _dataService = dataService; + } + } +} diff --git a/Txgy.DataStat/ViewModels/MainWindowViewModel.cs b/Txgy.DataStat/ViewModels/MainWindowViewModel.cs index 73fbf30..affd9c1 100644 --- a/Txgy.DataStat/ViewModels/MainWindowViewModel.cs +++ b/Txgy.DataStat/ViewModels/MainWindowViewModel.cs @@ -1,9 +1,26 @@ -using CommunityToolkit.Mvvm.ComponentModel; -using System; +using System; using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Diagnostics; +using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; +using System.Windows.Media.TextFormatting; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +using LiveChartsCore; +using LiveChartsCore.Drawing; +using LiveChartsCore.Kernel.Sketches; +using LiveChartsCore.SkiaSharpView; +using LiveChartsCore.SkiaSharpView.Painting; +using LiveChartsCore.SkiaSharpView.VisualElements; +using Microsoft.Win32; +using SkiaSharp; +using Txgy.DataStat.Models; +using Txgy.DataStat.Services; +using static System.Net.Mime.MediaTypeNames; namespace Txgy.DataStat.ViewModels { @@ -11,5 +28,368 @@ namespace Txgy.DataStat.ViewModels { [ObservableProperty] string message = "Hello tay"; + + [ObservableProperty] + FracDataReader fracReader = new FracDataReader(); + + [ObservableProperty] + double startTime = 0; + + [ObservableProperty] + double endTime = 55; + + [ObservableProperty] + string posFilePath = ""; + + [ObservableProperty] + string wellName = "276"; + + //[ObservableProperty] + //double yAxis1Max = 500; + private double yAxisSurPreMax = 500; + + public double YAxisSurPreMax + { + get { return yAxisSurPreMax; } + set + { + SetProperty(ref yAxisSurPreMax, value); + if (YAxes[1] != null) + YAxes[1].MaxLimit = yAxisSurPreMax; + } + } + private double yAxisEventsMax = 10; + + public double YAxisEventsMax + { + get { return yAxisEventsMax; } + set + { + SetProperty(ref yAxisEventsMax, value); + if (YAxes[0] != null) + YAxes[0].MaxLimit = yAxisEventsMax; + } + } + + private string timeUnitSelected = "分"; + + public string TimeUnitSelected + { + get { return timeUnitSelected; } + set + { + SetProperty(ref timeUnitSelected, value); + TimeUnit = timeUnitSelected == "分" ? 60 : 1; + } + } + int TimeUnit = 60; + public List TimeUnits { get; } = new List { "分", "秒" }; + List ListFracData = new List(); + List eventFreqs = new List(); + private static readonly SKColor s_blue = new(25, 118, 210); + private static readonly SKColor s_red = new(229, 57, 53); + private static readonly SKColor s_yellow = new(198, 167, 0); + private static readonly SKColor s_SlurryRate = new(25, 118, 210); + private static readonly SKColor s_SurPre = new(229, 57, 53); + private static readonly SKColor s_CasingPre = new(198, 167, 0); + private static readonly SKColor s_Events = new(68, 84, 106); + + //public ObservableCollection Series { get; set; } + [ObservableProperty] + LabelVisual title = new LabelVisual + { + Text = "276", + TextSize = 25, + Padding = new LiveChartsCore.Drawing.Padding(15), + Paint = new SolidColorPaint(SKColors.DarkSlateGray), + }; + + [ObservableProperty] + private ISeries[] mySeries; + + public ISeries[] Series { get; set; } = + { + new ColumnSeries + { + Name = "Event Frequency", + Values = new[] { 0 }, + Stroke = null, + MaxBarWidth = 10, + // but you can customize the gradient + Fill = new LinearGradientPaint( + // the gradient will use the following colors array + new[] { s_Events, s_Events }, + // we must go from the point: + // (x0, y0) where x0 could be read as "the middle of the x axis" (0.5) and y0 as "the start of the y axis" (0) + new SKPoint(0.5f, 0), + // to the point: + // (x1, y1) where x1 could be read as "the middle of the x axis" (0.5) and y0 as "the end of the y axis" (1) + new SKPoint(0.5f, 1) + ), + ScalesYAt = 0, + }, + new LineSeries + { + LineSmoothness = 1, + Name = "Surface Pressure", + Values = new double[] { 300, 400, 500, 400, 300 }, + Stroke = new SolidColorPaint(s_SurPre, 2), + GeometrySize = 0, + GeometryStroke = null, + Fill = null, + ScalesYAt = 1, + }, + new LineSeries + { + Name = "Casing Pressure", + Values = new double[] { 50, 75, 100, 75, 50 }, + Stroke = new SolidColorPaint(s_CasingPre, 2), + GeometrySize = 0, + GeometryStroke = null, + Fill = null, + ScalesYAt = 2, + }, + new LineSeries + { + Name = "Slurry Rate", + Values = new double[] { 5, 6, 3, 2, 1 }, + Stroke = new SolidColorPaint(s_SlurryRate, 2), + GeometrySize = 0, + GeometryStroke = null, + Fill = null, + ScalesYAt = 3, + }, + }; + public ICartesianAxis[] YAxes { get; set; } = + { + new Axis // the "hundreds" series will be scaled on this axis + { + Name = "Events", + NameTextSize = 14, + NamePaint = new SolidColorPaint + { + Color = s_Events, + FontFamily = "微软雅黑", + SKFontStyle = new SKFontStyle( + SKFontStyleWeight.ExtraBold, + SKFontStyleWidth.Normal, + SKFontStyleSlant.Upright + ), + }, + NamePadding = new LiveChartsCore.Drawing.Padding(0, 20), + Padding = new LiveChartsCore.Drawing.Padding(20, 0, 0, 0), + TextSize = 12, + LabelsPaint = new SolidColorPaint(s_Events), + TicksPaint = new SolidColorPaint(s_Events), + SubticksPaint = new SolidColorPaint(s_Events), + DrawTicksPath = true, + ShowSeparatorLines = false, + Position = LiveChartsCore.Measure.AxisPosition.End, + MinStep = 1, + MinLimit = 0, + MaxLimit = 10, + }, + new Axis // the "units" and "tens" series will be scaled on this axis + { + Name = "Surface Pressure", + NameTextSize = 14, + NamePaint = new SolidColorPaint + { + Color = s_SurPre, + FontFamily = "微软雅黑", + SKFontStyle = new SKFontStyle( + SKFontStyleWeight.ExtraBold, + SKFontStyleWidth.Normal, + SKFontStyleSlant.Upright + ), + }, + NamePadding = new LiveChartsCore.Drawing.Padding(0, 20), + Padding = new LiveChartsCore.Drawing.Padding(0, 0, 20, 0), + TextSize = 12, + LabelsPaint = new SolidColorPaint(s_SurPre), + TicksPaint = new SolidColorPaint(s_SurPre), + SubticksPaint = new SolidColorPaint(s_SurPre), + DrawTicksPath = true, + MinLimit = 0, + MaxLimit = 600, + }, + new Axis // the "hundreds" series will be scaled on this axis + { + Name = "Casing Pressure", + NameTextSize = 14, + NamePaint = new SolidColorPaint + { + Color = s_CasingPre, + FontFamily = "微软雅黑", + SKFontStyle = new SKFontStyle( + SKFontStyleWeight.ExtraBold, + SKFontStyleWidth.Normal, + SKFontStyleSlant.Upright + ), + }, + NamePadding = new LiveChartsCore.Drawing.Padding(0, 20), + Padding = new LiveChartsCore.Drawing.Padding(20, 0, 0, 0), + TextSize = 12, + LabelsPaint = new SolidColorPaint(s_CasingPre), + TicksPaint = new SolidColorPaint(s_CasingPre), + SubticksPaint = new SolidColorPaint(s_CasingPre), + DrawTicksPath = true, + ShowSeparatorLines = false, + Position = LiveChartsCore.Measure.AxisPosition.End, + MinLimit=0, + MaxLimit = 300, + IsVisible = false, + }, + new Axis // the "thousands" series will be scaled on this axis + { + Name = "Slurry Rate", + NameTextSize = 14, + NamePadding = new LiveChartsCore.Drawing.Padding(0, 20), + Padding = new LiveChartsCore.Drawing.Padding(20, 0, 0, 0), + NamePaint = new SolidColorPaint + { + Color = s_SlurryRate, + FontFamily = "微软雅黑", + SKFontStyle = new SKFontStyle( + SKFontStyleWeight.ExtraBold, + SKFontStyleWidth.Normal, + SKFontStyleSlant.Upright + ), + }, + TextSize = 12, + LabelsPaint = new SolidColorPaint(s_SlurryRate), + TicksPaint = new SolidColorPaint(s_SlurryRate), + SubticksPaint = new SolidColorPaint(s_SlurryRate), + DrawTicksPath = true, + ShowSeparatorLines = false, + Position = LiveChartsCore.Measure.AxisPosition.End, + MinLimit=0, + MaxLimit = 10, + IsVisible = false, + }, + }; + public Axis[] XAxis { get; set; } = new Axis[] { new Axis { MinLimit = 0,MinStep=60,Name="Time(min)" } }; + public SolidColorPaint LegendTextPaint { get; set; } = + new SolidColorPaint + { + Color = new SKColor(50, 50, 50), + SKTypeface = SKTypeface.FromFamilyName("Courier New"), + }; + + public SolidColorPaint LedgendBackgroundPaint { get; set; } = + new SolidColorPaint(new SKColor(240, 240, 240)); + + [RelayCommand] + void InputFracData() + { + UpdateWellName(); + ListFracData = FracReader.ReadData((double)TimeUnit); + + var serie = Series[1]; + serie.Values = ListFracData + .Where(data => data.time > StartTime && data.time < EndTime * TimeUnit) + .Select(data => data.surPre) + .ToArray(); + var serie1 = Series[2]; + serie1.Values = ListFracData + .Where(data => data.time > StartTime && data.time < EndTime * TimeUnit) + .Select(data => data.casingPre) + .ToArray(); + var serie2 = Series[3]; + serie2.Values = ListFracData + .Where(data => data.time > StartTime && data.time < EndTime * TimeUnit) + .Select(data => data.slurryRate) + .ToArray(); + SetXAxis(); + } + + void SetXAxis() + { + var axis = XAxis[0]; + var lbls = ListFracData + .Select(data => Math.Round(data.time, 0).ToString()) + .ToArray(); + + axis.Labels = lbls; + axis.MinStep = 800; + //axis.MaxLimit = 55 * 60; + //axis.MinLimit = StartTime; + axis.MaxLimit = EndTime * TimeUnit; + } + + [RelayCommand] + void SelectFracFile() + { + OpenFileDialog ofd = new OpenFileDialog(); + ofd.Filter = "压裂曲线数据|*.txt"; + if (ofd.ShowDialog() == true) + { + FracReader.FilePath = ofd.FileName; + Message=Path.GetFileNameWithoutExtension(ofd.FileName); + } + } + + [RelayCommand] + void SelectPosFile() + { + OpenFileDialog ofd = new OpenFileDialog(); + ofd.Filter = "微地震数据|*.pos"; + if (ofd.ShowDialog() == true) + { + PosFilePath = ofd.FileName; + } + } + + [RelayCommand] + void CountEventFrequency() + { + var posDatas = PosDataService.ReadPosDataFromFile(PosFilePath); + eventFreqs = PosDataService.StatsTimeFreq(posDatas, 60); + UpdateWellName(); + UpdateFreqSerier(); + } + + void UpdateFreqSerier() + { + var serieEvents = Series[0]; + List freqDatas = new List(); + + for (int i = 1; i < ListFracData.Count; i++) + { + var time = ListFracData[i].time; + if (Math.Abs(time % 1) < 1e-10 && time > 0) + { + var value = eventFreqs + .Where(t => t.time == time) + .Select(t => t.total) + .ToList(); + if (value != null && value.Count > 0) + freqDatas.Add((int)(value[0])); + } + else + { + freqDatas.Add(0); + } + } + serieEvents.Values = freqDatas.ToArray(); + } + + void UpdateWellName() + { + Title.Text = "KKM-" + WellName + " Fracturing Trends vs Microseismic Frequency"; + } + + //public void Create + public MainWindowViewModel() + { + //FracDataFormat.FirstDataRow = 100; + //Title2 = new LabelVisual + //{ + // Text = "KKM-" + WellName + " Fracturing Trends vs.Microseismic Frequency", + // TextSize = 25, + // Padding = new LiveChartsCore.Drawing.Padding(15), + // Paint = new SolidColorPaint(SKColors.DarkSlateGray), + //}; + } } } diff --git a/Txgy.DataStat/ViewModels/TestItemsSourceViewModel.cs b/Txgy.DataStat/ViewModels/TestItemsSourceViewModel.cs new file mode 100644 index 0000000..ac5e006 --- /dev/null +++ b/Txgy.DataStat/ViewModels/TestItemsSourceViewModel.cs @@ -0,0 +1,16 @@ +using CommunityToolkit.Mvvm.ComponentModel; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Txgy.DataStat.Models; + +namespace Txgy.DataStat.ViewModels +{ + public partial class TestItemsSourceViewModel:ObservableObject + { + + } +} diff --git a/Txgy.DataStat/ViewModels/UserControlAViewModel.cs b/Txgy.DataStat/ViewModels/UserControlAViewModel.cs new file mode 100644 index 0000000..60ad2d6 --- /dev/null +++ b/Txgy.DataStat/ViewModels/UserControlAViewModel.cs @@ -0,0 +1,25 @@ +using CommunityToolkit.Mvvm.ComponentModel; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Txgy.DataStat.IServices; +using Txgy.DataStat.Models; + +namespace Txgy.DataStat.ViewModels +{ + public class UserControlAViewModel : ObservableObject + { + + public ObservableCollection Cities => _dataService.Cities; + + private readonly IDataService _dataService; + public UserControlAViewModel(IDataService dataService) + { + _dataService = dataService; + // DataList = _dataService.DataList; + } + } +} diff --git a/Txgy.DataStat/ViewModels/UserControlBViewModel.cs b/Txgy.DataStat/ViewModels/UserControlBViewModel.cs new file mode 100644 index 0000000..e0d9701 --- /dev/null +++ b/Txgy.DataStat/ViewModels/UserControlBViewModel.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Txgy.DataStat.IServices; +using Txgy.DataStat.Models; + +namespace Txgy.DataStat.ViewModels +{ + public class UserControlBViewModel + { + public ObservableCollection Cities => _dataService.Cities; + + private readonly IDataService _dataService; + public UserControlBViewModel(IDataService dataService) + { + _dataService = dataService; + // DataList = _dataService.DataList; + } + } +} diff --git a/Txgy.DataStat/Views/CustomDialog.xaml b/Txgy.DataStat/Views/CustomDialog.xaml new file mode 100644 index 0000000..d4fc08f --- /dev/null +++ b/Txgy.DataStat/Views/CustomDialog.xaml @@ -0,0 +1,42 @@ + + + + + +