Work for collection and redo of timeinfo

This commit is contained in:
Steven Hildreth 2018-12-10 22:41:15 -06:00
parent 6242831067
commit e59a3195a8
24 changed files with 469 additions and 52 deletions

View file

@ -7,8 +7,10 @@ using Roadie.Api.Services;
using Roadie.Library.Caching;
using Roadie.Library.Identity;
using Roadie.Library.Models.Pagination;
using System;
using System.Net;
using System.Threading.Tasks;
using models = Roadie.Library.Models;
namespace Roadie.Api.Controllers
{
@ -27,33 +29,22 @@ namespace Roadie.Api.Controllers
this.CollectionService = collectionService;
}
//[EnableQuery]
//public IActionResult Get()
//{
// return Ok(this._RoadieDbContext.Labels.ProjectToType<models.Label>());
//}
//[HttpGet("{id}")]
//[ProducesResponseType(200)]
//[ProducesResponseType(404)]
//public IActionResult Get(Guid id)
//{
// var key = id.ToString();
// var result = this._cacheManager.Get<models.Label>(key, () =>
// {
// var d = this._RoadieDbContext.Labels.FirstOrDefault(x => x.RoadieId == id);
// if (d != null)
// {
// return d.Adapt<models.Label>();
// }
// return null;
// }, key);
// if (result == null)
// {
// return NotFound();
// }
// return Ok(result);
//}
[HttpGet("{id}")]
[ProducesResponseType(200)]
[ProducesResponseType(404)]
public async Task<IActionResult> Get(Guid id, string inc = null)
{
var result = await this.CollectionService.ById(await this.CurrentUserModel(), id, (inc ?? models.Collections.Collection.DefaultIncludes).ToLower().Split(","));
if (result == null || result.IsNotFoundResult)
{
return NotFound();
}
if (!result.IsSuccess)
{
return StatusCode((int)HttpStatusCode.InternalServerError);
}
return Ok(result);
}
[HttpGet]
[ProducesResponseType(200)]

View file

@ -206,7 +206,7 @@ namespace Roadie.Api.Services
join rm in this.DbContext.ReleaseMedias on r.Id equals rm.ReleaseId
where r.ArtistId == artist.Id
select rm.Id).Count(),
TrackTime = validCartistTracks.Any() ? TimeSpan.FromSeconds(Math.Floor((double)trackTime / 1000)).ToString(@"dd\:hh\:mm\:ss") : "--:--",
TrackTime = validCartistTracks.Any() ? new TimeInfo((decimal)trackTime).ToFullFormattedString() : "--:--",
TrackCount = validCartistTracks.Count(),
TrackPlayedCount = artist.PlayedCount
};

View file

@ -24,8 +24,7 @@ namespace Roadie.Api.Services
IHttpContext httpContext,
data.IRoadieDbContext context,
ICacheManager cacheManager,
ILogger<BookmarkService> logger,
ICollectionService collectionService)
ILogger<BookmarkService> logger)
: base(configuration, httpEncoder, context, cacheManager, logger, httpContext)
{
}

View file

@ -1,12 +1,16 @@
using Microsoft.EntityFrameworkCore;
using Mapster;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Roadie.Library;
using Roadie.Library.Caching;
using Roadie.Library.Configuration;
using Roadie.Library.Encoding;
using Roadie.Library.Enums;
using Roadie.Library.Extensions;
using Roadie.Library.Models;
using Roadie.Library.Models.Collections;
using Roadie.Library.Models.Pagination;
using Roadie.Library.Models.Statistics;
using Roadie.Library.Models.Users;
using Roadie.Library.Utility;
using System;
@ -21,16 +25,134 @@ namespace Roadie.Api.Services
{
public class CollectionService : ServiceBase, ICollectionService
{
private IBookmarkService BookmarkService { get; } = null;
public CollectionService(IRoadieSettings configuration,
IHttpEncoder httpEncoder,
IHttpContext httpContext,
data.IRoadieDbContext dbContext,
ICacheManager cacheManager,
ILogger<CollectionService> logger)
ILogger<CollectionService> logger,
IBookmarkService bookmarkService)
: base(configuration, httpEncoder, dbContext, cacheManager, logger, httpContext)
{
this.BookmarkService = bookmarkService;
}
public async Task<OperationResult<Collection>> ById(User roadieUser, Guid id, IEnumerable<string> includes = null)
{
var sw = Stopwatch.StartNew();
sw.Start();
var cacheKey = string.Format("urn:collection_by_id_operation:{0}:{1}", id, includes == null ? "0" : string.Join("|", includes));
var result = await this.CacheManager.GetAsync<OperationResult<Collection>>(cacheKey, async () =>
{
return await this.CollectionByIdAction(id, includes);
}, data.Artist.CacheRegionUrn(id));
sw.Stop();
if (result?.Data != null && roadieUser != null)
{
var userBookmarkResult = await this.BookmarkService.List(roadieUser, new PagedRequest(), false, BookmarkType.Collection);
if (userBookmarkResult.IsSuccess)
{
result.Data.UserBookmarked = userBookmarkResult?.Rows?.FirstOrDefault(x => x.Bookmark.Text == result.Data.Id.ToString()) != null;
}
}
return new OperationResult<Collection>(result.Messages)
{
Data = result?.Data,
IsNotFoundResult = result?.IsNotFoundResult ?? false,
Errors = result?.Errors,
IsSuccess = result?.IsSuccess ?? false,
OperationTime = sw.ElapsedMilliseconds
};
}
private async Task<OperationResult<Collection>> CollectionByIdAction(Guid id, IEnumerable<string> includes = null)
{
var sw = Stopwatch.StartNew();
sw.Start();
var collection = this.GetCollection(id);
if (collection == null)
{
return new OperationResult<Collection>(true, string.Format("Collection Not Found [{0}]", id));
}
var result = collection.Adapt<Collection>();
result.AlternateNames = collection.AlternateNames;
result.Tags = collection.Tags;
result.URLs = collection.URLs;
result.Thumbnail = this.MakeCollectionThumbnailImage(collection.RoadieId);
result.MediumThumbnail = base.MakeThumbnailImage(id, "collection", this.Configuration.MediumImageSize.Width, this.Configuration.MediumImageSize.Height);
result.CollectionFoundCount = (from crc in this.DbContext.CollectionReleases
where crc.CollectionId == collection.Id
select crc.Id).Count();
if (includes != null && includes.Any())
{
if (includes.Contains("list"))
{
result.ListInCSVFormat = collection.ListInCSVFormat;
result.ListInCSV = collection.ListInCSV;
}
else
{
result.ListInCSV = null;
result.ListInCSVFormat = null;
}
if (includes.Contains("releases"))
{
result.Releases = (from crc in this.DbContext.CollectionReleases
join r in this.DbContext.Releases.Include(x => x.Artist) on crc.ReleaseId equals r.Id
where crc.CollectionId == collection.Id
orderby crc.ListNumber
select new CollectionRelease
{
ListNumber = crc.ListNumber,
Release = Library.Models.Releases.ReleaseList.FromDataRelease(r, r.Artist, this.HttpContext.BaseUrl, this.MakeArtistThumbnailImage(r.Artist.RoadieId), this.MakeReleaseThumbnailImage(r.RoadieId))
}).ToArray();
}
if (includes.Contains("stats"))
{
var collectionReleases = (from crc in this.DbContext.CollectionReleases
join r in this.DbContext.Releases.Include(x => x.Artist) on crc.ReleaseId equals r.Id
where crc.CollectionId == collection.Id
select r);
var collectionTracks = (from crc in this.DbContext.CollectionReleases
join r in this.DbContext.Releases.Include(x => x.Artist) on crc.ReleaseId equals r.Id
join rm in this.DbContext.ReleaseMedias on r.Id equals rm.ReleaseId
join t in this.DbContext.Tracks on rm.Id equals t.ReleaseMediaId
where crc.CollectionId == collection.Id
select t);
result.Statistics = new CollectionStatistics
{
FileSize = collectionTracks.Sum(x => (long?)x.FileSize).ToFileSize(),
MissingTrackCount = collectionTracks.Count(x => x.Hash != null),
ReleaseCount = collectionReleases.Count(),
ReleaseMediaCount = collectionReleases.Sum(x => x.MediaCount),
Duration = collectionReleases.Sum(x => (long?)x.Duration),
TrackCount = collectionReleases.Sum(x => x.TrackCount),
TrackPlayedCount = collectionReleases.Sum(x => x.PlayedCount)
};
}
}
sw.Stop();
return new OperationResult<Collection>
{
Data = result,
IsSuccess = result != null,
OperationTime = sw.ElapsedMilliseconds
};
}
public async Task<Library.Models.Pagination.PagedResult<CollectionList>> List(User roadieUser, PagedRequest request, bool? doRandomize = false, Guid? releaseId = null, Guid? artistId = null)
{
var sw = new Stopwatch();

View file

@ -1,13 +1,17 @@
using Roadie.Library.Models.Collections;
using Roadie.Library;
using Roadie.Library.Models.Collections;
using Roadie.Library.Models.Pagination;
using Roadie.Library.Models.Users;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Roadie.Api.Services
{
public interface ICollectionService
{
Task<OperationResult<Collection>> ById(User roadieUser, Guid id, IEnumerable<string> includes = null);
Task<PagedResult<CollectionList>> List(User roadieUser, PagedRequest request, bool? doRandomize = false, Guid? releaseId = null, Guid? artistId = null);
}
}

View file

@ -135,6 +135,7 @@ namespace Roadie.Api.Services
join r in this.DbContext.Releases on cr.ReleaseId equals r.Id
where c.RoadieId == request.FilterToCollectionId.Value
select r.Id).ToArray();
}
int[] favoriteReleaseIds = new int[0];
if (request.FilterFavoriteOnly)
@ -271,6 +272,52 @@ namespace Roadie.Api.Services
release.Genre = genre?.dt ?? new DataToken();
}
if (request.FilterToCollectionId.HasValue)
{
// Get and number the releases found for the Collection
var collectionReleases = (from c in this.DbContext.Collections
join cr in this.DbContext.CollectionReleases on c.Id equals cr.CollectionId
where collectionReleaseIds.Contains(cr.ReleaseId)
orderby cr.ListNumber
select cr);
foreach (var release in rows)
{
var cr = collectionReleases.FirstOrDefault(x => x.ReleaseId == release.DatabaseId);
if (cr != null)
{
release.ListNumber = cr.ListNumber;
}
}
// For the missing releases create a dummy release list item
var resultListNumbers = (from x in rows select x.ListNumber).ToList();
var collection = this.GetCollection(request.FilterToCollectionId.Value);
var missingReleases = (from par in collection.PositionArtistReleases()
where !resultListNumbers.Contains(par.Position)
select par);
var newRows = new List<ReleaseList>(rows);
foreach(var missingRelease in missingReleases)
{
newRows.Add(new ReleaseList
{
Artist = new DataToken
{
Text = missingRelease.Artist
},
Release = new DataToken
{
Text = missingRelease.Release
},
CssClass = "missing",
ArtistThumbnail = new Image($"{this.HttpContext.ImageBaseUrl }/unknown.jpg"),
Thumbnail = new Image($"{this.HttpContext.ImageBaseUrl }/unknown.jpg"),
ListNumber = missingRelease.Position
});
}
// Resort the list for the collection by listNumber
rows = newRows.OrderBy(x => x.ListNumber).Skip(request.SkipValue).Take(request.LimitValue).ToArray();
rowCount = newRows.Count();
}
if (roadieUser != null)
{
var userReleaseRatings = (from ur in this.DbContext.UserReleases
@ -507,7 +554,7 @@ namespace Roadie.Api.Services
TrackCount = release.TrackCount,
TrackPlayedCount = release.PlayedCount,
TrackSize = releaseTracks.Sum(x => (long?)x.size).ToFileSize(),
TrackTime = releaseTracks.Any() ? TimeSpan.FromSeconds(Math.Floor((double)releaseTime / 1000)).ToString(@"hh\:mm\:ss") : "--:--"
TrackTime = releaseTracks.Any() ? new TimeInfo((decimal)releaseTime).ToFullFormattedString() : "--:--"
};
result.MaxMediaNumber = releaseMedias.Max(x => x.MediaNumber);
result.Statistics = releaseStats;

View file

@ -518,6 +518,7 @@ namespace Roadie.Api.Services
};
}
private Image MakeImage(Guid id, string type, int? width, int? height, string caption = null)
{
if (width.HasValue && height.HasValue && (width.Value != this.Configuration.ThumbnailImageSize.Width || height.Value != this.Configuration.ThumbnailImageSize.Height))
@ -526,5 +527,7 @@ namespace Roadie.Api.Services
}
return new Image($"{this.HttpContext.ImageBaseUrl }/{type}/{id}", caption, null);
}
}
}

View file

@ -150,9 +150,9 @@ namespace Roadie.Api.Services
FavoriteCount = userTracks.Count(x => x.IsFavorite ?? false),
PlayedCount = userTracks.Sum(x => x.PlayedCount),
FileSizeFormatted = ((long?)track.FileSize).ToFileSize(),
Time = TimeSpan.FromSeconds(Math.Floor((double)track.Duration / 1000)).ToString(@"hh\:mm\:ss")
Time = new TimeInfo((decimal)track.Duration).ToFullFormattedString()
};
}
}
}
}

View file

@ -71,6 +71,9 @@ namespace Roadie.Api
// c.SwaggerEndpoint("/swagger/swagger.json", "Roadie API");
// c.RoutePrefix = string.Empty;
//});
app.UseStaticFiles();
app.UseSignalR(routes =>
{
routes.MapHub<PlayActivityHub>("/playActivityHub");

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View file

@ -1,4 +1,5 @@
using Roadie.Library.Enums;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

View file

@ -1,5 +1,10 @@
using System;
using CsvHelper;
using Newtonsoft.Json;
using Roadie.Library.Enums;
using Roadie.Library.Utility;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace Roadie.Library.Data
@ -23,5 +28,129 @@ namespace Roadie.Library.Data
return Collection.CacheUrn(this.RoadieId);
}
}
public int? _positionColumn = null;
public int PositionColumn
{
get
{
if (this._positionColumn == null)
{
var looper = -1;
foreach (var pos in this.ListInCSVFormat.Split(','))
{
looper++;
if (pos.ToLower().Equals("position"))
{
this._positionColumn = looper;
}
}
}
return this._positionColumn.Value;
}
}
public int? _artistColumn = null;
public int ArtistColumn
{
get
{
if (this._artistColumn == null)
{
var looper = -1;
foreach (var pos in this.ListInCSVFormat.Split(','))
{
looper++;
if (pos.ToLower().Equals("artist"))
{
this._artistColumn = looper;
}
}
}
return this._artistColumn.Value;
}
}
public int? _releaseColumn = null;
public int ReleaseColumn
{
get
{
if (this._releaseColumn == null)
{
var looper = -1;
foreach (var pos in this.ListInCSVFormat.Split(','))
{
looper++;
if (pos.ToLower().Equals("release"))
{
this._releaseColumn = looper;
}
}
}
return this._releaseColumn.Value;
}
}
private IEnumerable<PositionAristRelease> _positionAristReleases = null;
public IEnumerable<PositionAristRelease> PositionArtistReleases()
{
if (this._positionAristReleases == null)
{
var rows = new List<PositionAristRelease>();
using (var sr = new StringReader(this.ListInCSV))
{
var index = 0;
var csv = new CsvReader(sr, new CsvHelper.Configuration.Configuration { MissingFieldFound = null, HasHeaderRecord = false });
while (csv.Read())
{
index++;
rows.Add(new PositionAristRelease
{
Index = index,
Position = csv.GetField<int>(this.PositionColumn),
Artist = SafeParser.ToString(csv.GetField<string>(this.ArtistColumn)),
Release = SafeParser.ToString(csv.GetField<string>(this.ReleaseColumn)),
});
}
}
this._positionAristReleases = rows;
}
return this._positionAristReleases;
}
}
[Serializable]
public class PositionAristRelease
{
[JsonIgnore]
public Statuses Status { get; set; }
[JsonProperty("Status")]
public string StatusVerbose
{
get
{
return this.Status.ToString();
}
}
/// <summary>
/// This is the index (position in the list regardless of the position number)
/// </summary>
[JsonIgnore]
public int Index { get; set; }
/// <summary>
/// This is the position number for the list (can be a year "1984" can be a number "14")
/// </summary>
public int Position { get; set; }
public string Artist { get; set; }
public string Release { get; set; }
public override string ToString()
{
return string.Format("Position [{0}], Artist [{1}], Release [{2}]", this.Position, this.Artist, this.Release);
}
}
}

View file

@ -0,0 +1,19 @@
using Roadie.Library.Utility;
using System;
using System.Collections.Generic;
using System.Text;
namespace Roadie.Library.Extensions
{
public static class DecimalExt
{
public static int ToSecondsFromMilliseconds(this decimal? value)
{
if (value > 0)
{
return (int)new TimeInfo(value.Value).Seconds;
}
return 0;
}
}
}

View file

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Roadie.Library.Extensions
{
public static class TimeSpanExt
{
public static string ToDuration(this TimeSpan input)
{
if(input == null || input.TotalMilliseconds == 0)
{
return "--/--/--";
}
return input.ToString(@"ddd\.hh\:mm\:ss");
}
}
}

View file

@ -1,12 +1,15 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Roadie.Library.Models.Statistics;
namespace Roadie.Library.Models.Collections
{
[Serializable]
public class Collection : EntityModelBase
{
public const string DefaultIncludes = "stats";
public int CollectionCount { get; set; }
public string CollectionType { get; set; }
@ -17,10 +20,44 @@ namespace Roadie.Library.Models.Collections
[MaxLength(200)]
public string Edition { get; set; }
[MaxLength(100)]
public string Name { get; set; }
public DataToken Maintainer { get; set; }
public IEnumerable<CollectionRelease> Releases { get; set; }
public Image Thumbnail { get; set; }
public Image MediumThumbnail { get; set; }
public string ListInCSVFormat { get; set; }
public string ListInCSV { get; set; }
public int PercentComplete
{
get
{
if (this.CollectionCount == 0 || this.CollectionFoundCount == 0)
{
return 0;
}
return (int)Math.Floor((decimal)this.CollectionFoundCount / (decimal)this.CollectionCount * 100);
}
}
public int? MissingReleaseCount
{
get
{
if(this.CollectionCount == this.CollectionFoundCount)
{
return null;
}
return this.CollectionCount - this.CollectionFoundCount;
}
}
public int? CollectionFoundCount { get; set; }
public CollectionStatistics Statistics { get; set; }
}
}

View file

@ -8,7 +8,7 @@ namespace Roadie.Library.Models.Collections
[Serializable]
public class CollectionRelease
{
public Release Release { get; set; }
public ReleaseList Release { get; set; }
public int ListNumber { get; set; }
}
}

View file

@ -1,4 +1,5 @@
using Roadie.Library.Models.Statistics;
using Roadie.Library.Utility;
using System;
using System.ComponentModel.DataAnnotations;
@ -32,7 +33,7 @@ namespace Roadie.Library.Models
public ReleaseGroupingStatistics Statistics { get; set; }
public int? Duration { get; set; }
public decimal? Duration { get; set; }
public string DurationTime
{
get
@ -41,7 +42,7 @@ namespace Roadie.Library.Models
{
return "--:--";
}
return TimeSpan.FromSeconds(this.Duration.Value / 1000).ToString(@"dd\.hh\:mm\:ss");
return new TimeInfo(this.Duration.Value).ToFullFormattedString();
}
}

View file

@ -1,6 +1,7 @@
using Mapster;
using Roadie.Library.Models.Statistics;
using Roadie.Library.Models.Users;
using Roadie.Library.Utility;
using System;
using System.Collections.Generic;
using System.Text;
@ -28,7 +29,7 @@ namespace Roadie.Library.Models.Playlists
public Image MediumThumbnail { get; set; }
public short? TrackCount { get; set; }
public short? ReleaseCount { get; set; }
public int? Duration { get; set; }
public decimal? Duration { get; set; }
public string DurationTime
{
get
@ -37,7 +38,7 @@ namespace Roadie.Library.Models.Playlists
{
return "--:--";
}
return TimeSpan.FromSeconds(this.Duration.Value / 1000).ToString(@"dd\.hh\:mm\:ss");
return new TimeInfo(this.Duration.Value).ToFullFormattedString();
}
}

View file

@ -1,4 +1,5 @@
using System;
using Roadie.Library.Utility;
using System;
using System.Collections.Generic;
using System.Text;
@ -13,7 +14,7 @@ namespace Roadie.Library.Models.Playlists
public int? PlaylistCount { get; set; }
public Image UserThumbnail { get; set; }
public bool IsPublic { get; set; }
public int? Duration { get; set; }
public decimal? Duration { get; set; }
public string DurationTime
{
get
@ -22,7 +23,7 @@ namespace Roadie.Library.Models.Playlists
{
return "--:--";
}
return TimeSpan.FromSeconds(this.Duration.Value / 1000).ToString(@"hh\:mm\:ss");
return new TimeInfo(this.Duration.Value).ToFullFormattedString();
}
}

View file

@ -3,6 +3,7 @@ using Newtonsoft.Json;
using Roadie.Library.Enums;
using Roadie.Library.Extensions;
using Roadie.Library.Models.Users;
using Roadie.Library.Utility;
using System;
using System.Collections.Generic;
using System.Text;
@ -47,7 +48,7 @@ namespace Roadie.Library.Models.Releases
public Statuses? Status { get; set; }
public DataToken Genre { get; set; }
public DateTime? LastPlayed { get; set; }
public int? Duration { get; set; }
public decimal? Duration { get; set; }
public string DurationTime
{
get
@ -56,12 +57,25 @@ namespace Roadie.Library.Models.Releases
{
return "--:--";
}
return TimeSpan.FromSeconds(this.Duration.Value / 1000).ToString(@"hh\:mm\:ss");
return new TimeInfo(this.Duration.Value).ToFullFormattedString();
}
}
public int? MediaCount { get; set; }
public bool IsValid
{
get
{
return this.Id != Guid.Empty;
}
}
/// <summary>
/// This is populated on a request to get the list of releases for a collection.
/// </summary>
public int? ListNumber { get; set; }
public static ReleaseList FromDataRelease(Data.Release release, Data.Artist artist, string baseUrl, Image artistThumbnail, Image thumbnail)
{
return new ReleaseList

View file

@ -1,4 +1,5 @@
using System;
using Roadie.Library.Utility;
using System;
namespace Roadie.Library.Models.Statistics
{
@ -13,5 +14,19 @@ namespace Roadie.Library.Models.Statistics
public int? TrackCount { get; set; }
public int? TrackPlayedCount { get; set; }
public string TrackTime { get; set; }
public decimal? Duration { get; set; }
public string DurationTime
{
get
{
if (!this.Duration.HasValue)
{
return "--:--";
}
return new TimeInfo(this.Duration.Value).ToFullFormattedString();
}
}
}
}

View file

@ -1,6 +1,7 @@
using Newtonsoft.Json;
using Roadie.Library.Models.Releases;
using Roadie.Library.Models.Users;
using Roadie.Library.Utility;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
@ -24,14 +25,14 @@ namespace Roadie.Library.Models
{
get
{
return this.Duration.HasValue ? TimeSpan.FromSeconds(this.Duration.Value / 1000).ToString(@"hh\:mm\:ss") : "--:--";
return this.Duration.HasValue ? new TimeInfo((decimal)this.Duration.Value).ToFullFormattedString() : "--:--";
}
}
public string DurationTimeShort
{
get
{
return this.Duration.HasValue ? TimeSpan.FromSeconds(this.Duration.Value / 1000).ToString(@"mm\:ss") : "--:--";
return this.Duration.HasValue ? new TimeInfo((decimal)this.Duration.Value).ToShortFormattedString() : "--:--";
}
}
public DateTime? LastPlayed { get; set; }

View file

@ -6,6 +6,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CsvHelper" Version="12.0.1" />
<PackageReference Include="FluentFTP" Version="19.2.2" />
<PackageReference Include="HtmlAgilityPack" Version="1.8.10" />
<PackageReference Include="ID3" Version="0.5.0-beta.1" />

View file

@ -21,7 +21,7 @@ namespace Roadie.Library.Utility
public decimal Hours { get; set; }
public string HoursForamtted
public string HoursFormatted
{
get
{
@ -77,6 +77,7 @@ namespace Roadie.Library.Utility
public TimeInfo(decimal milliseconds)
{
var secondsTotal = milliseconds / 1000;
var minutesTotal = Math.Floor(secondsTotal / 60);
var hoursTotal = Math.Floor(minutesTotal / 60);
@ -96,9 +97,18 @@ namespace Roadie.Library.Utility
return $"{ (string.IsNullOrEmpty(yearsFormatted) ? string.Empty : yearsFormatted + ":") }{ this.ToString() }";
}
public string ToShortFormattedString()
{
return $"{ MinutesFormatted }:{ SecondsFormatted }";
}
public override string ToString()
{
return $"{ DaysFormatted}:{ HoursForamtted}:{ MinutesFormatted }";
if(this.Days > 0)
{
return $"{ DaysFormatted}:{ HoursFormatted}:{ MinutesFormatted}:{ SecondsFormatted }";
}
return $"{ HoursFormatted}:{ MinutesFormatted }:{ SecondsFormatted }";
}
}
}