forked from ddrilling/AsbCloudServer
WellOperationRepository RemoveDuplicates TrimOverlapping and tested on local base
This commit is contained in:
parent
44bb602350
commit
f7caa7eb38
@ -132,5 +132,23 @@ namespace AsbCloudApp.Repositories
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task<IEnumerable<ValidationResult>> ValidateWithDbAsync(IEnumerable<WellOperationDto> wellOperations, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Удаление полных дубликатов операций по всем скважинам
|
||||
/// </summary>
|
||||
/// <param name="onProgressCallback"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<int> RemoveDuplicates(Action<string, double?> onProgressCallback, CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// Усечение пересекающейся последующей операции по дате и глубине забоя
|
||||
/// </summary>
|
||||
/// <param name="geDate">Фильтр по дате. Если хоть одна операция попадет в в фильтр, то будет обработана вся скважина, а не только эта операция</param>
|
||||
/// <param name="leDate">Фильтр по дате. Если хоть одна операция попадет в в фильтр, то будет обработана вся скважина, а не только эта операция</param>
|
||||
/// <param name="onProgressCallback"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<int> TrimOverlapping(DateTimeOffset? geDate, DateTimeOffset leDate, Action<string, double?> onProgressCallback, CancellationToken token);
|
||||
}
|
||||
}
|
@ -5,6 +5,8 @@ using AsbCloudApp.Services;
|
||||
using AsbCloudDb;
|
||||
using AsbCloudDb.Model;
|
||||
using DocumentFormat.OpenXml.Spreadsheet;
|
||||
using DocumentFormat.OpenXml.Vml;
|
||||
using DocumentFormat.OpenXml.Wordprocessing;
|
||||
using Irony.Parsing;
|
||||
using Mapster;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
@ -12,6 +14,7 @@ using Microsoft.Extensions.Caching.Memory;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@ -533,59 +536,160 @@ public class WellOperationRepository : IWellOperationRepository
|
||||
return dtos;
|
||||
}
|
||||
|
||||
public async Task RemoveDuplicates(CancellationToken token)
|
||||
public async Task<int> RemoveDuplicates(Action<string, double?> onProgressCallback, CancellationToken token)
|
||||
{
|
||||
var dbset = db.Set<WellOperation>();
|
||||
var groups = await dbset
|
||||
IQueryable<WellOperation> dbset = db.Set<WellOperation>();
|
||||
var query = dbset
|
||||
.GroupBy(o => new { o.IdWell, o.IdType })
|
||||
.Select(g => new { g.Key.IdWell, g.Key.IdType });
|
||||
|
||||
var groups = await query
|
||||
.ToArrayAsync(token);
|
||||
|
||||
var count = groups.Count();
|
||||
var i = 0;
|
||||
var totalRemoved = 0;
|
||||
var total = 0;
|
||||
foreach (var group in groups)
|
||||
await RemoveDuplicatesInGroup(group.Key.IdWell, group.Key.IdType, token);
|
||||
{
|
||||
var result = await RemoveDuplicatesInGroup(group.IdWell, group.IdType, token);
|
||||
totalRemoved += result.removed;
|
||||
total += result.total;
|
||||
var percent = i++ / count;
|
||||
var message = $"RemoveDuplicates [{i} of {count}] wellId: {group.IdWell}, opType: {group.IdType}, affected: {result.removed} of {result.total}";
|
||||
onProgressCallback?.Invoke(message, percent);
|
||||
Trace.TraceInformation(message);
|
||||
}
|
||||
var messageDone = $"RemoveDuplicates done [{i} of {count}] totalAffected: {totalRemoved} of {total}";
|
||||
Trace.TraceInformation(messageDone);
|
||||
onProgressCallback?.Invoke(messageDone, 1);
|
||||
return totalRemoved;
|
||||
}
|
||||
|
||||
private async Task RemoveDuplicatesInGroup(int idWell, int idType, CancellationToken token)
|
||||
private async Task<(int removed, int total)> RemoveDuplicatesInGroup(int idWell, int idType, CancellationToken token)
|
||||
{
|
||||
var dbset = db.Set<WellOperation>();
|
||||
var operationsEnumerator = dbset
|
||||
var entities = await dbset
|
||||
.Where(o => o.IdWell == idWell && o.IdType == idType)
|
||||
.OrderBy(o => o.DateStart)
|
||||
.GetEnumerator();
|
||||
.ToListAsync(token);
|
||||
|
||||
if (!operationsEnumerator.MoveNext())
|
||||
return;
|
||||
using var entitiesEnumerator = entities.GetEnumerator();
|
||||
|
||||
var preOperation = operationsEnumerator.Current;
|
||||
while (operationsEnumerator.MoveNext())
|
||||
if (!entitiesEnumerator.MoveNext())
|
||||
return (0, 0);
|
||||
|
||||
var preEntity = entitiesEnumerator.Current;
|
||||
while (entitiesEnumerator.MoveNext())
|
||||
{
|
||||
var operation = operationsEnumerator.Current;
|
||||
if (preOperation.IsSame(operation))
|
||||
dbset.Remove(operation);
|
||||
var entity = entitiesEnumerator.Current;
|
||||
if (preEntity.IsSame(entity))
|
||||
dbset.Remove(entity);
|
||||
else
|
||||
preOperation = operation;
|
||||
preEntity = entity;
|
||||
}
|
||||
await db.SaveChangesAsync(token);
|
||||
var removed = await db.SaveChangesAsync(token);
|
||||
return (removed, entities.Count);
|
||||
}
|
||||
|
||||
public async Task TrimOverlapping(DateTimeOffset leDate, CancellationToken token)
|
||||
public async Task<int> TrimOverlapping(DateTimeOffset? geDate, DateTimeOffset leDate, Action<string, double?> onProgressCallback, CancellationToken token)
|
||||
{
|
||||
var leDateUtc = leDate.ToUniversalTime();
|
||||
var dbset = db.Set<WellOperation>();
|
||||
var groups = await dbset
|
||||
IQueryable<WellOperation> query = db.Set<WellOperation>();
|
||||
if (geDate.HasValue)
|
||||
{
|
||||
var geDateUtc = geDate.Value.ToUniversalTime();
|
||||
query = query.Where(e => e.DateStart >= geDateUtc);
|
||||
}
|
||||
|
||||
var groups = await query
|
||||
.GroupBy(o => new { o.IdWell, o.IdType })
|
||||
.Select(g => new{
|
||||
MaxDate = g.Max(o => o.DateStart),
|
||||
g.Key.IdWell,
|
||||
g.Key.IdType,
|
||||
})
|
||||
.Where(g => g.MaxDate <= leDateUtc)
|
||||
.ToArrayAsync(token);
|
||||
|
||||
var count = groups.Count();
|
||||
var i = 0;
|
||||
(int takeover, int trimmed,int total) totalResult = (0, 0, 0);
|
||||
foreach (var group in groups)
|
||||
await TrimOverlapping(group.IdWell, group.IdType, token);
|
||||
{
|
||||
var result = await TrimOverlapping(group.IdWell, group.IdType, token);
|
||||
totalResult.takeover += result.takeover;
|
||||
totalResult.trimmed += result.trimmed;
|
||||
totalResult.total += result.total;
|
||||
var percent = i++ / count;
|
||||
var message = $"TrimOverlapping [{i} of {count}] wellId: {group.IdWell}, opType: {group.IdType}, takeover:{result.takeover}, trimmed:{result.trimmed}, of {result.total}";
|
||||
onProgressCallback?.Invoke(message, percent);
|
||||
Trace.TraceInformation(message);
|
||||
}
|
||||
var messageDone = $"TrimOverlapping done [{i} of {count}] total takeover:{totalResult.takeover}, total trimmed:{totalResult.trimmed} of {totalResult.total}";
|
||||
Trace.TraceInformation(messageDone);
|
||||
onProgressCallback?.Invoke(messageDone, 1);
|
||||
return totalResult.takeover + totalResult.trimmed;
|
||||
}
|
||||
|
||||
private Task TrimOverlapping(int idWell, int idType, CancellationToken token)
|
||||
private async Task<(int takeover, int trimmed, int total)> TrimOverlapping(int idWell, int idType, CancellationToken token)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
var dbset = db.Set<WellOperation>();
|
||||
var query = dbset
|
||||
.Where(o => o.IdWell == idWell)
|
||||
.Where(o => o.IdType == idType)
|
||||
.OrderBy(o => o.DateStart)
|
||||
.ThenBy(o => o.DepthStart);
|
||||
|
||||
var entities = await query
|
||||
.ToListAsync(token);
|
||||
|
||||
using var entitiesEnumerator = entities.GetEnumerator();
|
||||
|
||||
if (!entitiesEnumerator.MoveNext())
|
||||
return (0, 0, 0);
|
||||
|
||||
int takeover = 0;
|
||||
int trimmed = 0;
|
||||
var preEntity = entitiesEnumerator.Current;
|
||||
while (entitiesEnumerator.MoveNext())
|
||||
{
|
||||
var entity = entitiesEnumerator.Current;
|
||||
var preDepth = preEntity.DepthEnd;
|
||||
|
||||
if (preEntity.DepthEnd >= entity.DepthEnd)
|
||||
{
|
||||
dbset.Remove(entity);
|
||||
takeover++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (preEntity.DepthEnd > entity.DepthStart)
|
||||
{
|
||||
entity.DepthStart = preEntity.DepthEnd;
|
||||
trimmed++;
|
||||
}
|
||||
|
||||
var preDate = preEntity.DateStart.AddHours(preEntity.DurationHours);
|
||||
|
||||
if (preDate >= entity.DateStart.AddHours(entity.DurationHours))
|
||||
{
|
||||
dbset.Remove(entity);
|
||||
takeover++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (preDate > entity.DateStart)
|
||||
{
|
||||
var entityDateEnd = entity.DateStart.AddHours(entity.DurationHours);
|
||||
entity.DateStart = preDate;
|
||||
entity.DurationHours = (entityDateEnd - entity.DateStart).TotalHours;
|
||||
trimmed++;
|
||||
}
|
||||
|
||||
preEntity = entity;
|
||||
}
|
||||
var affected = await db.SaveChangesAsync(token);
|
||||
return (takeover, trimmed, entities.Count);
|
||||
}
|
||||
}
|
||||
|
@ -505,6 +505,38 @@ namespace AsbCloudWebApi.Controllers
|
||||
return File(stream, "application/octet-stream", fileName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Удаляет полые дубликаты операций
|
||||
/// </summary>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/api/well/wellOperations/RemoveDuplicates")]
|
||||
[Permission]
|
||||
[Obsolete]
|
||||
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
|
||||
public async Task<IActionResult> RemoveDuplicates(CancellationToken token)
|
||||
{
|
||||
var result = await operationRepository.RemoveDuplicates((_, _) => { }, token);
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Удаляет полностью пересекающиеся операции или "подрезает" более поздние их по глубине и дате.
|
||||
/// </summary>
|
||||
/// <param name="geDate"></param>
|
||||
/// <param name="leDate"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/api/well/wellOperations/TrimOverlapping")]
|
||||
[Permission]
|
||||
[Obsolete]
|
||||
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
|
||||
public async Task<IActionResult> TrimOverlapping(DateTimeOffset? geDate, DateTimeOffset leDate, CancellationToken token)
|
||||
{
|
||||
var result = await operationRepository.TrimOverlapping(geDate, leDate, (_, _) => { }, token);
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Возвращает шаблон файла импорта
|
||||
/// </summary>
|
||||
|
Loading…
Reference in New Issue
Block a user