#268 added API for processing probable poem metres

This commit is contained in:
Hamid Reza Mohammadi 2021-12-30 15:32:16 +03:30
parent f289073023
commit 32826ef4f5
5 changed files with 254 additions and 102 deletions

View File

@ -2254,6 +2254,48 @@ namespace RMuseum.Controllers
return Ok(res.Result);
}
/// <summary>
/// save ganjoor poem probable metre
/// </summary>
/// <param name="id"></param>
/// <param name="metre"></param>
/// <returns></returns>
[HttpPut]
[Route("probablemetre/save/{id}")]
[Authorize(Policy = RMuseumSecurableItem.GanjoorEntityShortName + ":" + SecurableItem.ModifyOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
[ProducesResponseType((int)HttpStatusCode.NotFound)]
public async Task<IActionResult> SaveGanjoorPoemProbableMetre(int id, [FromBody] string metre)
{
RServiceResult<bool> res =
await _ganjoorService.SaveGanjoorPoemProbableMetre(id, metre);
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
return Ok();
}
/// <summary>
/// dismiss ganjoor poem probable metre
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[HttpDelete]
[Route("probablemetre/dismiss/{id}")]
[Authorize(Policy = RMuseumSecurableItem.GanjoorEntityShortName + ":" + SecurableItem.ModifyOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
[ProducesResponseType((int)HttpStatusCode.NotFound)]
public async Task<IActionResult> DismissGanjoorPoemProbableMetre(int id)
{
RServiceResult<bool> res =
await _ganjoorService.SaveGanjoorPoemProbableMetre(id, "dismissed");
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
return Ok();
}
/// <summary>
/// readonly mode
/// </summary>

View File

@ -1371,6 +1371,21 @@
</summary>
<returns></returns>
</member>
<member name="M:RMuseum.Controllers.GanjoorController.SaveGanjoorPoemProbableMetre(System.Int32,System.String)">
<summary>
save ganjoor poem probable metre
</summary>
<param name="id"></param>
<param name="metre"></param>
<returns></returns>
</member>
<member name="M:RMuseum.Controllers.GanjoorController.DismissGanjoorPoemProbableMetre(System.Int32)">
<summary>
dismiss ganjoor poem probable metre
</summary>
<param name="id"></param>
<returns></returns>
</member>
<member name="P:RMuseum.Controllers.GanjoorController.ReadOnlyMode">
<summary>
readonly mode
@ -10072,6 +10087,14 @@
</summary>
<returns></returns>
</member>
<member name="M:RMuseum.Services.IGanjoorService.SaveGanjoorPoemProbableMetre(System.Int32,System.String)">
<summary>
save ganjoor poem probable metre
</summary>
<param name="id">problable metre id</param>
<param name="metre"></param>
<returns></returns>
</member>
<member name="T:RMuseum.Services.IGanjoorTranslationService">
<summary>
translation service implementation
@ -11281,6 +11304,9 @@
<summary>
IGanjoorService implementation
</summary>
<summary>
IGanjoorService implementation
</summary>
</member>
<member name="M:RMuseum.Services.Implementation.GanjoorService.SwitchCoupletBookmark(System.Guid,System.Int32,System.Int32)">
<summary>
@ -11363,20 +11389,6 @@
<param name="rhythm"></param>
<returns></returns>
</member>
<member name="M:RMuseum.Services.Implementation.GanjoorService.StartFindingMissingRhythms(System.Boolean,System.Int32)">
<summary>
Start finding missing rhthms
</summary>
<param name="onlyPoemsWithRhymes"></param>
<param name="poemsNum"></param>
<returns></returns>
</member>
<member name="M:RMuseum.Services.Implementation.GanjoorService.GetNextGanjoorPoemProbableMetre">
<summary>
get next ganjoor poem probable metre
</summary>
<returns></returns>
</member>
<member name="M:RMuseum.Services.Implementation.GanjoorService.StartGeneratingSubCatsTOC(System.Guid,System.Int32)">
<summary>
start generating sub cats TOC
@ -11437,6 +11449,28 @@
</summary>
<returns></returns>
</member>
<member name="M:RMuseum.Services.Implementation.GanjoorService.StartFindingMissingRhythms(System.Boolean,System.Int32)">
<summary>
Start finding missing rhthms
</summary>
<param name="onlyPoemsWithRhymes"></param>
<param name="poemsNum"></param>
<returns></returns>
</member>
<member name="M:RMuseum.Services.Implementation.GanjoorService.GetNextGanjoorPoemProbableMetre">
<summary>
get next ganjoor poem probable metre
</summary>
<returns></returns>
</member>
<member name="M:RMuseum.Services.Implementation.GanjoorService.SaveGanjoorPoemProbableMetre(System.Int32,System.String)">
<summary>
save ganjoor poem probable metre
</summary>
<param name="id">problable metre id</param>
<param name="metre"></param>
<returns></returns>
</member>
<member name="M:RMuseum.Services.Implementation.GanjoorService.GetRelatedPoems(System.Int32,System.Int32,System.Int32)">
<summary>
get a poem related poems

View File

@ -695,5 +695,13 @@ namespace RMuseum.Services
/// </summary>
/// <returns></returns>
Task<RServiceResult<GanjoorPoemCompleteViewModel>> GetNextGanjoorPoemProbableMetre();
/// <summary>
/// save ganjoor poem probable metre
/// </summary>
/// <param name="id">problable metre id</param>
/// <param name="metre"></param>
/// <returns></returns>
Task<RServiceResult<bool>> SaveGanjoorPoemProbableMetre(int id, string metre);
}
}

View File

@ -97,94 +97,6 @@ namespace RMuseum.Services.Implementation
return new RServiceResult<bool>(true);
}
/// <summary>
/// Start finding missing rhthms
/// </summary>
/// <param name="onlyPoemsWithRhymes"></param>
/// <param name="poemsNum"></param>
/// <returns></returns>
public RServiceResult<bool> StartFindingMissingRhythms(bool onlyPoemsWithRhymes, int poemsNum = 1000)
{
_backgroundTaskQueue.QueueBackgroundWorkItem
(
async token =>
{
using (RMuseumDbContext context = new RMuseumDbContext(new DbContextOptions<RMuseumDbContext>())) //this is long running job, so _context might be already been freed/collected by GC
{
LongRunningJobProgressServiceEF jobProgressServiceEF = new LongRunningJobProgressServiceEF(context);
var job = (await jobProgressServiceEF.NewJob($"StartFindingMissingRhythms", "Query data")).Result;
try
{
var poemIds = await context.GanjoorPoems.AsNoTracking()
.Where(p =>
p.GanjoorMetreId == null && (onlyPoemsWithRhymes == false || !string.IsNullOrEmpty(p.RhymeLetters))
&&
false == (context.GanjoorVerses.Where(v => v.PoemId == p.Id && (v.VersePosition == VersePosition.Paragraph || v.VersePosition == VersePosition.Single)).Any() )
)
.Take(poemsNum)
.Select(p => p.Id)
.ToArrayAsync();
await jobProgressServiceEF.UpdateJob(job.Id, 0, $"Total: {poemIds.Length}");
var metres = await context.GanjoorMetres.OrderBy(m => m.Rhythm).AsNoTracking().Select(m => m.Rhythm).ToArrayAsync();
using (HttpClient httpClient = new HttpClient())
{
for (int i = 0; i < poemIds.Length; i++)
{
var id = poemIds[i];
if ((await context.GanjoorPoemProbableMetres.Where(p => p.PoemId == id).AnyAsync()) == true)
continue;
var res = await _FindPoemRhythm(id, context, httpClient, metres, true );
if (res.Result == null)
res.Result = "";
GanjoorPoemProbableMetre prometre = new GanjoorPoemProbableMetre()
{
PoemId = id,
Metre = res.Result
};
context.GanjoorPoemProbableMetres.Add(prometre);
await jobProgressServiceEF.UpdateJob(job.Id, i);
}
}
await jobProgressServiceEF.UpdateJob(job.Id, 100, "", true);
}
catch (Exception exp)
{
await jobProgressServiceEF.UpdateJob(job.Id, 100, "", false, exp.ToString());
}
}
});
return new RServiceResult<bool>(true);
}
/// <summary>
/// get next ganjoor poem probable metre
/// </summary>
/// <returns></returns>
public async Task<RServiceResult<GanjoorPoemCompleteViewModel>> GetNextGanjoorPoemProbableMetre()
{
var next = await _context.GanjoorPoemProbableMetres.Where(p => p.Metre != "dismissed").AsNoTracking().FirstOrDefaultAsync();
if (next == null)
return new RServiceResult<GanjoorPoemCompleteViewModel>(null);
var res = await GetPoemById(next.PoemId);
if (!string.IsNullOrEmpty(res.ExceptionString))
return new RServiceResult<GanjoorPoemCompleteViewModel>(null, res.ExceptionString);
if (res.Result == null)
return new RServiceResult<GanjoorPoemCompleteViewModel>(null, "poem does not exist!");
res.Result.GanjoorMetre = new GanjoorMetre()
{
Rhythm = next.Metre
};
return res;
}
private async Task _GeneratingSubCatsTOC(Guid userId, RMuseumDbContext context, LongRunningJobProgressServiceEF jobProgressServiceEF, RLongRunningJobStatus job, int catId)
{
foreach (var cat in await context.GanjoorCategories.AsNoTracking().Where(c => c.ParentId == catId).ToListAsync())

View File

@ -0,0 +1,156 @@
using Microsoft.EntityFrameworkCore;
using RMuseum.DbContext;
using RMuseum.Models.Ganjoor;
using RMuseum.Models.Ganjoor.ViewModels;
using RMuseum.Services.Implementation.ImportedFromDesktopGanjoor;
using RSecurityBackend.Models.Generic;
using RSecurityBackend.Models.Generic.Db;
using RSecurityBackend.Services.Implementation;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
namespace RMuseum.Services.Implementation
{
/// <summary>
/// IGanjoorService implementation
/// </summary>
public partial class GanjoorService : IGanjoorService
{
/// <summary>
/// Start finding missing rhthms
/// </summary>
/// <param name="onlyPoemsWithRhymes"></param>
/// <param name="poemsNum"></param>
/// <returns></returns>
public RServiceResult<bool> StartFindingMissingRhythms(bool onlyPoemsWithRhymes, int poemsNum = 1000)
{
_backgroundTaskQueue.QueueBackgroundWorkItem
(
async token =>
{
using (RMuseumDbContext context = new RMuseumDbContext(new DbContextOptions<RMuseumDbContext>())) //this is long running job, so _context might be already been freed/collected by GC
{
LongRunningJobProgressServiceEF jobProgressServiceEF = new LongRunningJobProgressServiceEF(context);
var job = (await jobProgressServiceEF.NewJob($"StartFindingMissingRhythms", "Query data")).Result;
try
{
var poemIds = await context.GanjoorPoems.AsNoTracking()
.Where(p =>
p.GanjoorMetreId == null && (onlyPoemsWithRhymes == false || !string.IsNullOrEmpty(p.RhymeLetters))
&&
false == (context.GanjoorVerses.Where(v => v.PoemId == p.Id && (v.VersePosition == VersePosition.Paragraph || v.VersePosition == VersePosition.Single)).Any())
)
.Take(poemsNum)
.Select(p => p.Id)
.ToArrayAsync();
await jobProgressServiceEF.UpdateJob(job.Id, 0, $"Total: {poemIds.Length}");
var metres = await context.GanjoorMetres.OrderBy(m => m.Rhythm).AsNoTracking().Select(m => m.Rhythm).ToArrayAsync();
using (HttpClient httpClient = new HttpClient())
{
for (int i = 0; i < poemIds.Length; i++)
{
var id = poemIds[i];
if ((await context.GanjoorPoemProbableMetres.Where(p => p.PoemId == id).AnyAsync()) == true)
continue;
var res = await _FindPoemRhythm(id, context, httpClient, metres, true);
if (res.Result == null)
res.Result = "";
GanjoorPoemProbableMetre prometre = new GanjoorPoemProbableMetre()
{
PoemId = id,
Metre = res.Result
};
context.GanjoorPoemProbableMetres.Add(prometre);
await jobProgressServiceEF.UpdateJob(job.Id, i);
}
}
await jobProgressServiceEF.UpdateJob(job.Id, 100, "", true);
}
catch (Exception exp)
{
await jobProgressServiceEF.UpdateJob(job.Id, 100, "", false, exp.ToString());
}
}
});
return new RServiceResult<bool>(true);
}
/// <summary>
/// get next ganjoor poem probable metre
/// </summary>
/// <returns></returns>
public async Task<RServiceResult<GanjoorPoemCompleteViewModel>> GetNextGanjoorPoemProbableMetre()
{
var next = await _context.GanjoorPoemProbableMetres.Where(p => p.Metre != "dismissed").AsNoTracking().FirstOrDefaultAsync();
if (next == null)
return new RServiceResult<GanjoorPoemCompleteViewModel>(null);
var res = await GetPoemById(next.PoemId);
if (!string.IsNullOrEmpty(res.ExceptionString))
return new RServiceResult<GanjoorPoemCompleteViewModel>(null, res.ExceptionString);
if (res.Result == null)
return new RServiceResult<GanjoorPoemCompleteViewModel>(null, "poem does not exist!");
res.Result.GanjoorMetre = new GanjoorMetre()
{
Rhythm = next.Metre
};
return res;
}
/// <summary>
/// save ganjoor poem probable metre
/// </summary>
/// <param name="id">problable metre id</param>
/// <param name="metre"></param>
/// <returns></returns>
public async Task<RServiceResult<bool>> SaveGanjoorPoemProbableMetre(int id, string metre)
{
try
{
var item = await _context.GanjoorPoemProbableMetres.Where(p => p.Id == id).SingleAsync();
metre = metre.Trim();
if (string.IsNullOrEmpty(metre))
metre = "dismissed";
if (metre == "dismissed")
{
item.Metre = "dismissed";
_context.Update(item);
await _context.SaveChangesAsync();
return new RServiceResult<bool>(true);
}
var rhythm = await _context.GanjoorMetres.AsNoTracking().Where(m => m.Rhythm == metre).SingleOrDefaultAsync();
if(rhythm == null)
{
rhythm = new GanjoorMetre()
{
Rhythm = metre,
VerseCount = 0
};
_context.GanjoorMetres.Add(rhythm);
await _context.SaveChangesAsync();
}
var poem = await _context.GanjoorPoems.Where(p => p.Id == item.PoemId).SingleAsync();
poem.GanjoorMetreId = rhythm.Id;
_context.Update(poem);
_context.Remove(item);
await _context.SaveChangesAsync();
return new RServiceResult<bool>(true);
}
catch(Exception exp)
{
return new RServiceResult<bool>(false, exp.ToString());
}
}
}
}