Cache Review Stats; Migrate DeletedBy to enum

This commit is contained in:
LumaLivy 2021-12-10 23:37:55 -05:00
commit e07fd5714e
3 changed files with 69 additions and 39 deletions

View file

@ -76,6 +76,12 @@ namespace LBPUnion.ProjectLighthouse.Controllers
ratedLevel.Rating = Math.Max(Math.Min(1, rating), -1);
Review? review = await this.database.Reviews.FirstOrDefaultAsync(r => r.SlotId == slotId && r.ReviewerId == user.UserId);
if (review != null)
{
review.Thumb = ratedLevel.Rating;
}
await this.database.SaveChangesAsync();
return this.Ok();
@ -95,15 +101,18 @@ namespace LBPUnion.ProjectLighthouse.Controllers
review = new();
review.SlotId = slotId;
review.ReviewerId = user.UserId;
review.DeletedBy = "none";
review.DeletedBy = DeletedBy.None;
review.ThumbsUp = 0;
review.ThumbsDown = 0;
this.database.Reviews.Add(review);
}
review.Thumb = newReview.Thumb;
review.LabelCollection = newReview.LabelCollection;
review.Text = newReview.Text;
review.Deleted = false;
review.Timestamp = TimeHelper.UnixTimeMilliseconds();
// sometimes the game posts a review without also calling dpadrate/user/etc (why??)
// sometimes the game posts/updates a review rating without also calling dpadrate/user/etc (why??)
RatedLevel? ratedLevel = await this.database.RatedLevels.FirstOrDefaultAsync(r => r.SlotId == slotId && r.UserId == user.UserId);
if (ratedLevel == null)
{
@ -116,7 +125,6 @@ namespace LBPUnion.ProjectLighthouse.Controllers
ratedLevel.Rating = newReview.Thumb;
await this.database.SaveChangesAsync();
return this.Ok();
@ -137,21 +145,51 @@ namespace LBPUnion.ProjectLighthouse.Controllers
Random rand = new();
IEnumerable<Review> reviews = this.database.Reviews.Where(r => r.SlotId == slotId && r.Slot.GameVersion <= gameVersion)
Review? yourReview = await this.database.Reviews.FirstOrDefaultAsync(r => r.ReviewerId == user.UserId && r.SlotId == slotId && r.Slot.GameVersion <= gameVersion);
VisitedLevel? visitedLevel = await this.database.VisitedLevels.FirstOrDefaultAsync(v => v.UserId == user.UserId && v.SlotId == slotId && v.Slot.GameVersion <= gameVersion);
Slot? slot = await this.database.Slots.FirstOrDefaultAsync(s => s.SlotId == slotId);
if (slot == null) return this.BadRequest();
Boolean canNowReviewLevel = visitedLevel != null && yourReview == null;
if (canNowReviewLevel)
{
RatedLevel? ratedLevel = await this.database.RatedLevels.FirstOrDefaultAsync(r => r.UserId == user.UserId && r.SlotId == slotId && r.Slot.GameVersion <= gameVersion);
yourReview = new();
yourReview.ReviewerId = user.UserId;
yourReview.Reviewer = user;
yourReview.Thumb = ratedLevel?.Rating == null ? 0 : ratedLevel.Rating;
yourReview.Slot = slot;
yourReview.SlotId = slotId;
yourReview.DeletedBy = DeletedBy.None;
yourReview.Text = "You haven't reviewed this level yet. Edit this blank review to upload it!";
yourReview.LabelCollection = "";
yourReview.Deleted = false;
yourReview.Timestamp = TimeHelper.UnixTimeMilliseconds();
}
IQueryable<Review?> reviews = this.database.Reviews.Where(r => r.SlotId == slotId && r.Slot.GameVersion <= gameVersion)
.Include(r => r.Reviewer)
.Include(r => r.Slot)
.AsEnumerable() // performance? Needed for next line (ThumbsUp is not in DB)
.OrderByDescending(r => r.ThumbsUp)
.ThenByDescending(_ => rand.Next())
.ThenByDescending(_ => EF.Functions.Random())
.Skip(pageStart - 1)
.Take(pageSize);
string inner = Enumerable.Aggregate(reviews, string.Empty, (current, review) =>
IEnumerable<Review?> prependedReviews;
if (canNowReviewLevel) // this can only be true if you have not posted a review but have visited the level
{
RatedLevel? ratedLevel = this.database.RatedLevels.FirstOrDefault(r => r.SlotId == slotId && r.UserId == review.ReviewerId);
RatedReview? ratedReview = this.database.RatedReviews.FirstOrDefault(r => r.ReviewId == review.ReviewId && r.UserId == user.UserId);
// prepend the fake review to the top of the list to be easily edited
prependedReviews = reviews.ToList().Prepend(yourReview);
}
else
{
prependedReviews = reviews.ToList();
}
return current + review.Serialize(ratedLevel, ratedReview);
string inner = Enumerable.Aggregate(prependedReviews, string.Empty, (current, review) =>
{
if (review == null) return current;
return current + review.Serialize();
});
string response = LbpSerializer.TaggedStringElement("reviews", inner, new Dictionary<string, object>

View file

@ -1,9 +1,15 @@
using System.Xml.Serialization;
namespace LBPUnion.ProjectLighthouse.Types
{
public static class DeletedBy
public enum DeletedBy
{
public static string Moderator { get => "moderator"; }
public static string LevelAuthor { get => "level_author"; }
[XmlEnum(Name = "none")]
None,
[XmlEnum(Name = "moderator")]
Moderator,
[XmlEnum(Name = "level_author")]
LevelAuthor
// TODO: deletion types for comments (profile etc)
}
}

View file

@ -37,7 +37,8 @@ namespace LBPUnion.ProjectLighthouse.Types.Reviews
[NotMapped]
[XmlIgnore]
public string[] Labels {
public string[] Labels
{
get => this.LabelCollection.Split(",");
set => this.LabelCollection = string.Join(',', value);
}
@ -46,44 +47,29 @@ namespace LBPUnion.ProjectLighthouse.Types.Reviews
public Boolean Deleted { get; set; }
[XmlElement("deleted_by")]
public string DeletedBy { get; set; } // enum ? Needs testing e.g. Moderated/Author/Level Author? etc.
public DeletedBy DeletedBy { get; set; }
[XmlElement("text")]
public string Text { get; set; }
[NotMapped]
[XmlElement("thumb")]
public int Thumb { get; set; } // (unused) -- temp value for getting thumb from review upload body for updating level rating
public int Thumb { get; set; }
[NotMapped]
[XmlElement("thumbsup")]
public int ThumbsUp {
get {
using Database database = new();
return database.RatedReviews.Count(r => r.ReviewId == this.ReviewId && r.Thumb == 1);
}
}
[NotMapped]
public int ThumbsUp { get; set; }
[XmlElement("thumbsdown")]
public int ThumbsDown {
get {
using Database database = new();
public int ThumbsDown { get; set; }
return database.RatedReviews.Count(r => r.ReviewId == this.ReviewId && r.Thumb == -1);
}
}
public string Serialize(RatedLevel? yourLevelRating = null, RatedReview? yourRatingStats = null) {
public string Serialize(RatedLevel? yourLevelRating = null, RatedReview? yourRatingStats = null)
{
return this.Serialize("review", yourLevelRating, yourRatingStats);
}
public string Serialize(string elementOverride, RatedLevel? yourLevelRating = null, RatedReview? yourRatingStats = null)
{
string reviewData = LbpSerializer.TaggedStringElement("slot_id", this.SlotId, "type", this.Slot.Type) +
LbpSerializer.StringElement("reviewer", this.Reviewer.Username) +
LbpSerializer.StringElement("thumb", yourLevelRating?.Rating) +
LbpSerializer.StringElement("thumb", this.Thumb) +
LbpSerializer.StringElement("timestamp", this.Timestamp) +
LbpSerializer.StringElement("labels", this.LabelCollection) +
LbpSerializer.StringElement("deleted", this.Deleted) +