Я работаю над приложением Blazor для измерения веса. Данные поступают со стороннего устройства в режиме реального времени. У меня на информационной панели есть компонент результатов взвешивания, который я пытаюсь отобразить в сетке в соответствии с некоторыми правилами. Сетка данных периодически загружает данные из базы данных.
Aggregate Measurements рассчитает данные взвешивания клиента (Огулбей, Йешилкёй) на основе номерного знака (06GG111, 34HH222) текущего дня. время в порядке убывания. Могут быть изменения тренда, как вы можете видеть на двухдневных выборочных данных. Измерение начинается с 3000 для Oğulbey,06GG111 и увеличивается до 4224 27 ноября 2024 г. (Это первая последовательность) Затем в тот же день она снова снижается до 3000 для Oğulbey,06GG111 и достигает 4068. (Это вторая последовательность) Это определение смены тренда. (То же самое, что и снижение)
Вот выборка данных за 2 дня
**3000 2024-11-26 16:45:49 Oğulbey 06GG111
3345 2024-11-26 16:45:56 Yeşilköy 34HH222
3426 2024-11-26 16:46:56 Oğulbey 06GG111
3771 2024-11-26 16:47:26 Yeşilköy 34HH222**
3000 2024-11-27 16:59:27 Oğulbey 06GG111
3345 2024-11-27 16:59:48 Yeşilköy 34HH222
3661 2024-11-27 17:00:27 Oğulbey 06GG111
4006 2024-11-27 17:00:40 Yeşilköy 34HH222
4224 2024-11-27 17:01:27 Oğulbey 06GG111
3000 2024-11-27 17:04:11 Oğulbey 06GG111
3345 2024-11-27 17:04:30 Yeşilköy 34HH222
3530 2024-11-27 17:05:11 Oğulbey 06GG111
3875 2024-11-27 17:05:24 Yeşilköy 34HH222
4068 2024-11-27 17:06:11 Oğulbey 06GG111
expected output:
Second sequence because of trend change
3000 4068 2024-11-27 17:06:11 Oğulbey 06GG111
3345 3875 2024-11-27 17:05:24 Yeşilköy 34HH222
first sequence
3000 4224 2024-11-27 17:01:27 Oğulbey 06GG111
3345 4006 2024-11-27 17:00:40 Yeşilköy 34HH222
previous day
3345 3771 2024-11-26 16:47:26 Yeşilköy 34HH222
3000 3426 2024-11-26 16:46:56 Oğulbey 06GG111
Вот компонент, но он не дает ожидаемого результата.
@page "/weighing-results"
@using OfficeOpenXml
@using OfficeOpenXml.Style
@using Radzen
@using Radzen.Blazor
@using WeighingDeviceDashboard.Service
@inject IMeasurementService MeasurementService
@inject IJSRuntime JS
.highlight {
animation: blink 1s alternate 5; /* Adjust duration, iterations, and timing as needed */
/* animation-fill-mode: forwards; */
animation-timing-function: cubic-bezier(0, 0, 0.2, 1);
}
@@keyframes blink {
0% {
background-color: #ff0000; /* Yellow (highlight color) */
font-weight: bold;
}
50% {
background-color: #ffffff; /* White (default background color) */
}
100% {
background-color: #ff0000; /* Yellow (highlight color) */
font-weight: bold;
}
}
@result.PlateNumber
@result.FirstWeighingValue.ToString("F0")
@result.LastWeighingValue.ToString("F0")
@(result.WeightDifference!= null?
(result.WeightDifference > 0? $"+{result.WeightDifference.Value.ToString("F0")}" :
(result.WeightDifference < 0? $"{result.WeightDifference.Value.ToString("F0")}" : $"0"))
: "-")
@code {
RadzenDataGrid grid = new();
List weighingResults = new List();
private readonly SemaphoreSlim _measurementLock = new SemaphoreSlim(1, 1);
bool isLoading = false;
private CancellationTokenSource _cancellationTokenSource;
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
_cancellationTokenSource = new CancellationTokenSource();
await LoadDataPeriodically(_cancellationTokenSource.Token);
}
private async Task LoadDataPeriodically(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
await ShowLoading();
weighingResults = await GetWeighingResultsAsync();
await grid.Reload();
StateHasChanged(); // Ensure UI updates
try
{
await Task.Delay(60000, cancellationToken); // 1,2 minutes delay
}
catch (TaskCanceledException)
{
// Task was canceled, exit the loop
break;
}
}
}
private async Task ShowLoading()
{
isLoading = true;
await Task.Yield();
isLoading = false;
}
private async Task GetWeighingResultsAsync()
{
await _measurementLock.WaitAsync();
try
{
var measurements = await MeasurementService.GetMeasurementsAsync();
return AggregateMeasurements(measurements);
}
finally
{
_measurementLock.Release();
}
}
private List AggregateMeasurements(IEnumerable measurements)
{
var results = new List();
var current_date = DateTime.Now.Date;
var measurementGroups = measurements
.GroupBy(m => (m.ClientId, m.PlateNumber, m.Timestamp.Date))
.Select(g => new
{
Group = g.OrderBy(m => m.Timestamp).ToList(),
ClientId = g.Key.ClientId,
PlateNumber = g.Key.PlateNumber,
Date = g.Key.Date
});
foreach (var groupInfo in measurementGroups)
{
int sequence = 1;
Trend? currentTrend = null;
Measurement? previousMeasurement = null;
WeighingResult? currentResult = null;
foreach (var measurement in groupInfo.Group)
{
var currentValue = (float)measurement.Value;
// Determine trend
Trend? newTrend = null;
if (previousMeasurement != null)
{
var previousValue = (float)previousMeasurement.Value;
newTrend = GetTrend(previousValue, currentValue);
}
// Check for trend change
if (previousMeasurement != null && newTrend != currentTrend)
{
// Create a new result when trend changes
sequence++;
currentResult = new WeighingResult
{
ClientId = measurement.ClientId,
PlateNumber = measurement.PlateNumber,
FirstWeighingValue = currentValue,
LastWeighingValue = currentValue,
LastWeighingDateTime = measurement.Timestamp,
ReceiptNo = measurement.ReceiptNo,
WeighingSequence = sequence,
IsNew = true // Mark as new for highlighting
};
results.Add(currentResult);
}
else if (currentResult == null)
{
// Create the first result
currentResult = new WeighingResult
{
ClientId = measurement.ClientId,
PlateNumber = measurement.PlateNumber,
FirstWeighingValue = currentValue,
LastWeighingValue = currentValue,
LastWeighingDateTime = measurement.Timestamp,
ReceiptNo = measurement.ReceiptNo,
WeighingSequence = sequence,
IsNew = true // Mark as new for highlighting
};
results.Add(currentResult);
}
else
{
// Update existing result
if (currentValue < currentResult.FirstWeighingValue)
{
currentResult.FirstWeighingValue = currentValue;
}
if (currentValue > currentResult.LastWeighingValue)
{
currentResult.LastWeighingValue = currentValue;
currentResult.LastWeighingDateTime = measurement.Timestamp;
currentResult.ReceiptNo = measurement.ReceiptNo;
}
}
// Update trend tracking
currentTrend = newTrend;
previousMeasurement = measurement;
}
}
// Sort results by date and sequence
return results
.OrderByDescending(r => r.LastWeighingDateTime)
.ThenBy(r => r.WeighingSequence)
.ToList();
}
private Trend? GetTrend(float previousValue, float currentValue)
{
if (currentValue > previousValue) return Trend.Increasing;
if (currentValue < previousValue) return Trend.Decreasing;
return null;
}
private enum Trend
{
Increasing,
Decreasing
}
private async Task ExportExcel()
{
var filter = grid.View;
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
var stream = new MemoryStream();
using (var package = new ExcelPackage(stream))
{
var workSheet = package.Workbook.Worksheets.Add("Weighing Results");
var recordIndex = 2;
workSheet.Row(1).Style.Font.Bold = true;
var headerCells = workSheet.Cells["A1:G1"];
headerCells.Style.Font.Bold = true;
headerCells.Style.Font.Size = 13;
headerCells.Style.Border.BorderAround(ExcelBorderStyle.Thin);
headerCells.Style.Border.Top.Style = ExcelBorderStyle.Thin;
headerCells.Style.Border.Left.Style = ExcelBorderStyle.Thin;
headerCells.Style.Border.Right.Style = ExcelBorderStyle.Thin;
headerCells.Style.Border.Bottom.Style = ExcelBorderStyle.Thin;
headerCells.Style.Font.Color.SetColor(System.Drawing.Color.Black);
headerCells.Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid;
headerCells.Style.Fill.BackgroundColor.SetColor(System.Drawing.Color.LightGray);
workSheet.Cells[1, 1].Value = "Warehouse";
workSheet.Cells[1, 2].Value = "Plate Number";
workSheet.Cells[1, 3].Value = "First Weighing Value";
workSheet.Cells[1, 4].Value = "Last Weighing Value";
workSheet.Cells[1, 5].Value = "Weight Difference";
workSheet.Cells[1, 6].Value = "Last Weighing Date Time";
workSheet.Cells[1, 7].Value = "Receipt Number";
foreach (var result in filter)
{
workSheet.Cells[recordIndex, 1].Value = result.ClientId;
workSheet.Cells[recordIndex, 2].Value = result.PlateNumber;
workSheet.Cells[recordIndex, 3].Value = result.FirstWeighingValue.ToString("F0");
workSheet.Cells[recordIndex, 4].Value = result.LastWeighingValue.ToString("F0");
workSheet.Cells[recordIndex, 5].Value = result.WeightDifference?.ToString("F0");
workSheet.Cells[recordIndex, 6].Value = result.LastWeighingDateTime.ToString("g");
workSheet.Cells[recordIndex, 7].Value = result.ReceiptNo;
recordIndex++;
}
workSheet.Cells[workSheet.Dimension.Address].AutoFitColumns();
await package.SaveAsync();
}
stream.Position = 0;
var excelName = $"Weighing Results-{DateTime.Now.ToString("ddMMyyyyHHmm")}.xlsx";
using var streamRef = new DotNetStreamReference(stream: stream);
await JS.InvokeVoidAsync("downloadFileFromStream", excelName, streamRef);
}
public void Dispose()
{
_cancellationTokenSource?.Cancel();
_cancellationTokenSource?.Dispose();
}
}
Подробнее здесь: https://stackoverflow.com/questions/792 ... y-properly
Как исправить метод совокупных измерений, чтобы он отображался правильно? ⇐ C#
Место общения программистов C#
1732723610
Anonymous
Я работаю над приложением Blazor для измерения веса. Данные поступают со стороннего устройства в режиме реального времени. У меня на информационной панели есть компонент результатов взвешивания, который я пытаюсь отобразить в сетке в соответствии с некоторыми правилами. Сетка данных периодически загружает данные из базы данных.
Aggregate Measurements рассчитает данные взвешивания клиента (Огулбей, Йешилкёй) на основе номерного знака (06GG111, 34HH222) текущего дня. время в порядке убывания. Могут быть изменения тренда, как вы можете видеть на двухдневных выборочных данных. Измерение начинается с 3000 для Oğulbey,06GG111 и увеличивается до 4224 27 ноября 2024 г. (Это первая последовательность) Затем в тот же день она снова снижается до 3000 для Oğulbey,06GG111 и достигает 4068. (Это вторая последовательность) Это определение смены тренда. (То же самое, что и снижение)
Вот выборка данных за 2 дня
**3000 2024-11-26 16:45:49 Oğulbey 06GG111
3345 2024-11-26 16:45:56 Yeşilköy 34HH222
3426 2024-11-26 16:46:56 Oğulbey 06GG111
3771 2024-11-26 16:47:26 Yeşilköy 34HH222**
3000 2024-11-27 16:59:27 Oğulbey 06GG111
3345 2024-11-27 16:59:48 Yeşilköy 34HH222
3661 2024-11-27 17:00:27 Oğulbey 06GG111
4006 2024-11-27 17:00:40 Yeşilköy 34HH222
4224 2024-11-27 17:01:27 Oğulbey 06GG111
3000 2024-11-27 17:04:11 Oğulbey 06GG111
3345 2024-11-27 17:04:30 Yeşilköy 34HH222
3530 2024-11-27 17:05:11 Oğulbey 06GG111
3875 2024-11-27 17:05:24 Yeşilköy 34HH222
4068 2024-11-27 17:06:11 Oğulbey 06GG111
expected output:
Second sequence because of trend change
3000 4068 2024-11-27 17:06:11 Oğulbey 06GG111
3345 3875 2024-11-27 17:05:24 Yeşilköy 34HH222
first sequence
3000 4224 2024-11-27 17:01:27 Oğulbey 06GG111
3345 4006 2024-11-27 17:00:40 Yeşilköy 34HH222
previous day
3345 3771 2024-11-26 16:47:26 Yeşilköy 34HH222
3000 3426 2024-11-26 16:46:56 Oğulbey 06GG111
Вот компонент, но он не дает ожидаемого результата.
@page "/weighing-results"
@using OfficeOpenXml
@using OfficeOpenXml.Style
@using Radzen
@using Radzen.Blazor
@using WeighingDeviceDashboard.Service
@inject IMeasurementService MeasurementService
@inject IJSRuntime JS
.highlight {
animation: blink 1s alternate 5; /* Adjust duration, iterations, and timing as needed */
/* animation-fill-mode: forwards; */
animation-timing-function: cubic-bezier(0, 0, 0.2, 1);
}
@@keyframes blink {
0% {
background-color: #ff0000; /* Yellow (highlight color) */
font-weight: bold;
}
50% {
background-color: #ffffff; /* White (default background color) */
}
100% {
background-color: #ff0000; /* Yellow (highlight color) */
font-weight: bold;
}
}
@result.PlateNumber
@result.FirstWeighingValue.ToString("F0")
@result.LastWeighingValue.ToString("F0")
@(result.WeightDifference!= null?
(result.WeightDifference > 0? $"+{result.WeightDifference.Value.ToString("F0")}" :
(result.WeightDifference < 0? $"{result.WeightDifference.Value.ToString("F0")}" : $"0"))
: "-")
@code {
RadzenDataGrid grid = new();
List weighingResults = new List();
private readonly SemaphoreSlim _measurementLock = new SemaphoreSlim(1, 1);
bool isLoading = false;
private CancellationTokenSource _cancellationTokenSource;
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
_cancellationTokenSource = new CancellationTokenSource();
await LoadDataPeriodically(_cancellationTokenSource.Token);
}
private async Task LoadDataPeriodically(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
await ShowLoading();
weighingResults = await GetWeighingResultsAsync();
await grid.Reload();
StateHasChanged(); // Ensure UI updates
try
{
await Task.Delay(60000, cancellationToken); // 1,2 minutes delay
}
catch (TaskCanceledException)
{
// Task was canceled, exit the loop
break;
}
}
}
private async Task ShowLoading()
{
isLoading = true;
await Task.Yield();
isLoading = false;
}
private async Task GetWeighingResultsAsync()
{
await _measurementLock.WaitAsync();
try
{
var measurements = await MeasurementService.GetMeasurementsAsync();
return AggregateMeasurements(measurements);
}
finally
{
_measurementLock.Release();
}
}
private List AggregateMeasurements(IEnumerable measurements)
{
var results = new List();
var current_date = DateTime.Now.Date;
var measurementGroups = measurements
.GroupBy(m => (m.ClientId, m.PlateNumber, m.Timestamp.Date))
.Select(g => new
{
Group = g.OrderBy(m => m.Timestamp).ToList(),
ClientId = g.Key.ClientId,
PlateNumber = g.Key.PlateNumber,
Date = g.Key.Date
});
foreach (var groupInfo in measurementGroups)
{
int sequence = 1;
Trend? currentTrend = null;
Measurement? previousMeasurement = null;
WeighingResult? currentResult = null;
foreach (var measurement in groupInfo.Group)
{
var currentValue = (float)measurement.Value;
// Determine trend
Trend? newTrend = null;
if (previousMeasurement != null)
{
var previousValue = (float)previousMeasurement.Value;
newTrend = GetTrend(previousValue, currentValue);
}
// Check for trend change
if (previousMeasurement != null && newTrend != currentTrend)
{
// Create a new result when trend changes
sequence++;
currentResult = new WeighingResult
{
ClientId = measurement.ClientId,
PlateNumber = measurement.PlateNumber,
FirstWeighingValue = currentValue,
LastWeighingValue = currentValue,
LastWeighingDateTime = measurement.Timestamp,
ReceiptNo = measurement.ReceiptNo,
WeighingSequence = sequence,
IsNew = true // Mark as new for highlighting
};
results.Add(currentResult);
}
else if (currentResult == null)
{
// Create the first result
currentResult = new WeighingResult
{
ClientId = measurement.ClientId,
PlateNumber = measurement.PlateNumber,
FirstWeighingValue = currentValue,
LastWeighingValue = currentValue,
LastWeighingDateTime = measurement.Timestamp,
ReceiptNo = measurement.ReceiptNo,
WeighingSequence = sequence,
IsNew = true // Mark as new for highlighting
};
results.Add(currentResult);
}
else
{
// Update existing result
if (currentValue < currentResult.FirstWeighingValue)
{
currentResult.FirstWeighingValue = currentValue;
}
if (currentValue > currentResult.LastWeighingValue)
{
currentResult.LastWeighingValue = currentValue;
currentResult.LastWeighingDateTime = measurement.Timestamp;
currentResult.ReceiptNo = measurement.ReceiptNo;
}
}
// Update trend tracking
currentTrend = newTrend;
previousMeasurement = measurement;
}
}
// Sort results by date and sequence
return results
.OrderByDescending(r => r.LastWeighingDateTime)
.ThenBy(r => r.WeighingSequence)
.ToList();
}
private Trend? GetTrend(float previousValue, float currentValue)
{
if (currentValue > previousValue) return Trend.Increasing;
if (currentValue < previousValue) return Trend.Decreasing;
return null;
}
private enum Trend
{
Increasing,
Decreasing
}
private async Task ExportExcel()
{
var filter = grid.View;
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
var stream = new MemoryStream();
using (var package = new ExcelPackage(stream))
{
var workSheet = package.Workbook.Worksheets.Add("Weighing Results");
var recordIndex = 2;
workSheet.Row(1).Style.Font.Bold = true;
var headerCells = workSheet.Cells["A1:G1"];
headerCells.Style.Font.Bold = true;
headerCells.Style.Font.Size = 13;
headerCells.Style.Border.BorderAround(ExcelBorderStyle.Thin);
headerCells.Style.Border.Top.Style = ExcelBorderStyle.Thin;
headerCells.Style.Border.Left.Style = ExcelBorderStyle.Thin;
headerCells.Style.Border.Right.Style = ExcelBorderStyle.Thin;
headerCells.Style.Border.Bottom.Style = ExcelBorderStyle.Thin;
headerCells.Style.Font.Color.SetColor(System.Drawing.Color.Black);
headerCells.Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid;
headerCells.Style.Fill.BackgroundColor.SetColor(System.Drawing.Color.LightGray);
workSheet.Cells[1, 1].Value = "Warehouse";
workSheet.Cells[1, 2].Value = "Plate Number";
workSheet.Cells[1, 3].Value = "First Weighing Value";
workSheet.Cells[1, 4].Value = "Last Weighing Value";
workSheet.Cells[1, 5].Value = "Weight Difference";
workSheet.Cells[1, 6].Value = "Last Weighing Date Time";
workSheet.Cells[1, 7].Value = "Receipt Number";
foreach (var result in filter)
{
workSheet.Cells[recordIndex, 1].Value = result.ClientId;
workSheet.Cells[recordIndex, 2].Value = result.PlateNumber;
workSheet.Cells[recordIndex, 3].Value = result.FirstWeighingValue.ToString("F0");
workSheet.Cells[recordIndex, 4].Value = result.LastWeighingValue.ToString("F0");
workSheet.Cells[recordIndex, 5].Value = result.WeightDifference?.ToString("F0");
workSheet.Cells[recordIndex, 6].Value = result.LastWeighingDateTime.ToString("g");
workSheet.Cells[recordIndex, 7].Value = result.ReceiptNo;
recordIndex++;
}
workSheet.Cells[workSheet.Dimension.Address].AutoFitColumns();
await package.SaveAsync();
}
stream.Position = 0;
var excelName = $"Weighing Results-{DateTime.Now.ToString("ddMMyyyyHHmm")}.xlsx";
using var streamRef = new DotNetStreamReference(stream: stream);
await JS.InvokeVoidAsync("downloadFileFromStream", excelName, streamRef);
}
public void Dispose()
{
_cancellationTokenSource?.Cancel();
_cancellationTokenSource?.Dispose();
}
}
Подробнее здесь: [url]https://stackoverflow.com/questions/79231030/how-to-fix-aggregate-measurements-method-in-order-to-display-properly[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия