From cd862f5701a219a7aca9bc419668601fcb769c52 Mon Sep 17 00:00:00 2001 From: LumaLivy <7350336+LumaLivy@users.noreply.github.com> Date: Fri, 10 Dec 2021 23:36:36 -0500 Subject: [PATCH 1/6] Database migrations --- ...0211211043517_CacheReviewStats.Designer.cs | 828 ++++++++++++++++++ .../20211211043517_CacheReviewStats.cs | 66 ++ .../Migrations/DatabaseModelSnapshot.cs | 14 +- 3 files changed, 905 insertions(+), 3 deletions(-) create mode 100644 ProjectLighthouse/Migrations/20211211043517_CacheReviewStats.Designer.cs create mode 100644 ProjectLighthouse/Migrations/20211211043517_CacheReviewStats.cs diff --git a/ProjectLighthouse/Migrations/20211211043517_CacheReviewStats.Designer.cs b/ProjectLighthouse/Migrations/20211211043517_CacheReviewStats.Designer.cs new file mode 100644 index 00000000..ca4261c1 --- /dev/null +++ b/ProjectLighthouse/Migrations/20211211043517_CacheReviewStats.Designer.cs @@ -0,0 +1,828 @@ +// +using LBPUnion.ProjectLighthouse; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace ProjectLighthouse.Migrations +{ + [DbContext(typeof(Database))] + [Migration("20211211043517_CacheReviewStats")] + partial class CacheReviewStats + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.AuthenticationAttempt", b => + { + b.Property("AuthenticationAttemptId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("GameTokenId") + .HasColumnType("int"); + + b.Property("IPAddress") + .HasColumnType("longtext"); + + b.Property("Platform") + .HasColumnType("int"); + + b.Property("Timestamp") + .HasColumnType("bigint"); + + b.HasKey("AuthenticationAttemptId"); + + b.HasIndex("GameTokenId"); + + b.ToTable("AuthenticationAttempts"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b => + { + b.Property("TokenId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("GameVersion") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int"); + + b.Property("UserLocation") + .HasColumnType("longtext"); + + b.Property("UserToken") + .HasColumnType("longtext"); + + b.HasKey("TokenId"); + + b.ToTable("GameTokens"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.HeartedProfile", b => + { + b.Property("HeartedProfileId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("HeartedUserId") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("HeartedProfileId"); + + b.HasIndex("HeartedUserId"); + + b.HasIndex("UserId"); + + b.ToTable("HeartedProfiles"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.HeartedLevel", b => + { + b.Property("HeartedLevelId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("SlotId") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("HeartedLevelId"); + + b.HasIndex("SlotId"); + + b.HasIndex("UserId"); + + b.ToTable("HeartedLevels"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.QueuedLevel", b => + { + b.Property("QueuedLevelId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("SlotId") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("QueuedLevelId"); + + b.HasIndex("SlotId"); + + b.HasIndex("UserId"); + + b.ToTable("QueuedLevels"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.RatedLevel", b => + { + b.Property("RatedLevelId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Rating") + .HasColumnType("int"); + + b.Property("RatingLBP1") + .HasColumnType("double"); + + b.Property("SlotId") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("RatedLevelId"); + + b.HasIndex("SlotId"); + + b.HasIndex("UserId"); + + b.ToTable("RatedLevels"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.Slot", b => + { + b.Property("SlotId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AuthorLabels") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("BackgroundHash") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CreatorId") + .HasColumnType("int"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FirstUploaded") + .HasColumnType("bigint"); + + b.Property("GameVersion") + .HasColumnType("int"); + + b.Property("IconHash") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("InitiallyLocked") + .HasColumnType("tinyint(1)"); + + b.Property("LastUpdated") + .HasColumnType("bigint"); + + b.Property("Lbp1Only") + .HasColumnType("tinyint(1)"); + + b.Property("LevelType") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("LocationId") + .HasColumnType("int"); + + b.Property("MaximumPlayers") + .HasColumnType("int"); + + b.Property("MinimumPlayers") + .HasColumnType("int"); + + b.Property("MoveRequired") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("PlaysLBP1") + .HasColumnType("int"); + + b.Property("PlaysLBP1Complete") + .HasColumnType("int"); + + b.Property("PlaysLBP1Unique") + .HasColumnType("int"); + + b.Property("PlaysLBP2") + .HasColumnType("int"); + + b.Property("PlaysLBP2Complete") + .HasColumnType("int"); + + b.Property("PlaysLBP2Unique") + .HasColumnType("int"); + + b.Property("PlaysLBP3") + .HasColumnType("int"); + + b.Property("PlaysLBP3Complete") + .HasColumnType("int"); + + b.Property("PlaysLBP3Unique") + .HasColumnType("int"); + + b.Property("PlaysLBPVita") + .HasColumnType("int"); + + b.Property("PlaysLBPVitaComplete") + .HasColumnType("int"); + + b.Property("PlaysLBPVitaUnique") + .HasColumnType("int"); + + b.Property("ResourceCollection") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RootLevel") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Shareable") + .HasColumnType("int"); + + b.Property("SubLevel") + .HasColumnType("tinyint(1)"); + + b.Property("TeamPick") + .HasColumnType("tinyint(1)"); + + b.HasKey("SlotId"); + + b.HasIndex("CreatorId"); + + b.HasIndex("LocationId"); + + b.ToTable("Slots"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.VisitedLevel", b => + { + b.Property("VisitedLevelId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("PlaysLBP1") + .HasColumnType("int"); + + b.Property("PlaysLBP2") + .HasColumnType("int"); + + b.Property("PlaysLBP3") + .HasColumnType("int"); + + b.Property("PlaysLBPVita") + .HasColumnType("int"); + + b.Property("SlotId") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("VisitedLevelId"); + + b.HasIndex("SlotId"); + + b.HasIndex("UserId"); + + b.ToTable("VisitedLevels"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Photo", b => + { + b.Property("PhotoId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatorId") + .HasColumnType("int"); + + b.Property("LargeHash") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("MediumHash") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("PhotoSubjectCollection") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("PlanHash") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("SmallHash") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Timestamp") + .HasColumnType("bigint"); + + b.HasKey("PhotoId"); + + b.HasIndex("CreatorId"); + + b.ToTable("Photos"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.PhotoSubject", b => + { + b.Property("PhotoSubjectId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Bounds") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("PhotoSubjectId"); + + b.HasIndex("UserId"); + + b.ToTable("PhotoSubjects"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Comment", b => + { + b.Property("CommentId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Message") + .HasColumnType("longtext"); + + b.Property("PosterUserId") + .HasColumnType("int"); + + b.Property("TargetUserId") + .HasColumnType("int"); + + b.Property("ThumbsDown") + .HasColumnType("int"); + + b.Property("ThumbsUp") + .HasColumnType("int"); + + b.Property("Timestamp") + .HasColumnType("bigint"); + + b.HasKey("CommentId"); + + b.HasIndex("PosterUserId"); + + b.HasIndex("TargetUserId"); + + b.ToTable("Comments"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.LastMatch", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("GameVersion") + .HasColumnType("int"); + + b.Property("Timestamp") + .HasColumnType("bigint"); + + b.HasKey("UserId"); + + b.ToTable("LastMatches"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Location", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("X") + .HasColumnType("int"); + + b.Property("Y") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("Locations"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Reviews.RatedReview", b => + { + b.Property("RatedReviewId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ReviewId") + .HasColumnType("int"); + + b.Property("Thumb") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("RatedReviewId"); + + b.HasIndex("ReviewId"); + + b.HasIndex("UserId"); + + b.ToTable("RatedReviews"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Reviews.Review", b => + { + b.Property("ReviewId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Deleted") + .HasColumnType("tinyint(1)"); + + b.Property("DeletedBy") + .HasColumnType("int"); + + b.Property("LabelCollection") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ReviewerId") + .HasColumnType("int"); + + b.Property("SlotId") + .HasColumnType("int"); + + b.Property("Text") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Thumb") + .HasColumnType("int"); + + b.Property("ThumbsDown") + .HasColumnType("int"); + + b.Property("ThumbsUp") + .HasColumnType("int"); + + b.Property("Timestamp") + .HasColumnType("bigint"); + + b.HasKey("ReviewId"); + + b.HasIndex("ReviewerId"); + + b.HasIndex("SlotId"); + + b.ToTable("Reviews"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Score", b => + { + b.Property("ScoreId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("PlayerIdCollection") + .HasColumnType("longtext"); + + b.Property("Points") + .HasColumnType("int"); + + b.Property("SlotId") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("ScoreId"); + + b.HasIndex("SlotId"); + + b.ToTable("Scores"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.User", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Biography") + .HasColumnType("longtext"); + + b.Property("Game") + .HasColumnType("int"); + + b.Property("IconHash") + .HasColumnType("longtext"); + + b.Property("IsAdmin") + .HasColumnType("tinyint(1)"); + + b.Property("LocationId") + .HasColumnType("int"); + + b.Property("Password") + .HasColumnType("longtext"); + + b.Property("PasswordResetRequired") + .HasColumnType("tinyint(1)"); + + b.Property("Pins") + .HasColumnType("longtext"); + + b.Property("PlanetHash") + .HasColumnType("longtext"); + + b.Property("Username") + .HasColumnType("longtext"); + + b.HasKey("UserId"); + + b.HasIndex("LocationId"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.WebToken", b => + { + b.Property("TokenId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int"); + + b.Property("UserToken") + .HasColumnType("longtext"); + + b.HasKey("TokenId"); + + b.ToTable("WebTokens"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.AuthenticationAttempt", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.GameToken", "GameToken") + .WithMany() + .HasForeignKey("GameTokenId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GameToken"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.HeartedProfile", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "HeartedUser") + .WithMany() + .HasForeignKey("HeartedUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("HeartedUser"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.HeartedLevel", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot") + .WithMany() + .HasForeignKey("SlotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Slot"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.QueuedLevel", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot") + .WithMany() + .HasForeignKey("SlotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Slot"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.RatedLevel", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot") + .WithMany() + .HasForeignKey("SlotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Slot"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.Slot", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Creator") + .WithMany() + .HasForeignKey("CreatorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LBPUnion.ProjectLighthouse.Types.Profiles.Location", "Location") + .WithMany() + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("Location"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Levels.VisitedLevel", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot") + .WithMany() + .HasForeignKey("SlotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Slot"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Photo", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Creator") + .WithMany() + .HasForeignKey("CreatorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Creator"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.PhotoSubject", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Comment", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Poster") + .WithMany() + .HasForeignKey("PosterUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Target") + .WithMany() + .HasForeignKey("TargetUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Poster"); + + b.Navigation("Target"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Reviews.RatedReview", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.Reviews.Review", "Review") + .WithMany() + .HasForeignKey("ReviewId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Review"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Reviews.Review", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Reviewer") + .WithMany() + .HasForeignKey("ReviewerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot") + .WithMany() + .HasForeignKey("SlotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Reviewer"); + + b.Navigation("Slot"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Score", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot") + .WithMany() + .HasForeignKey("SlotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Slot"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.User", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.Profiles.Location", "Location") + .WithMany() + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Location"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/ProjectLighthouse/Migrations/20211211043517_CacheReviewStats.cs b/ProjectLighthouse/Migrations/20211211043517_CacheReviewStats.cs new file mode 100644 index 00000000..43ff8248 --- /dev/null +++ b/ProjectLighthouse/Migrations/20211211043517_CacheReviewStats.cs @@ -0,0 +1,66 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace ProjectLighthouse.Migrations +{ + public partial class CacheReviewStats : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "DeletedBy", + table: "Reviews", + type: "int", + nullable: false, + oldClrType: typeof(string), + oldType: "longtext") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AddColumn( + name: "Thumb", + table: "Reviews", + type: "int", + nullable: false, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "ThumbsDown", + table: "Reviews", + type: "int", + nullable: false, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "ThumbsUp", + table: "Reviews", + type: "int", + nullable: false, + defaultValue: 0); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Thumb", + table: "Reviews"); + + migrationBuilder.DropColumn( + name: "ThumbsDown", + table: "Reviews"); + + migrationBuilder.DropColumn( + name: "ThumbsUp", + table: "Reviews"); + + migrationBuilder.AlterColumn( + name: "DeletedBy", + table: "Reviews", + type: "longtext", + nullable: false, + oldClrType: typeof(int), + oldType: "int") + .Annotation("MySql:CharSet", "utf8mb4"); + } + } +} diff --git a/ProjectLighthouse/Migrations/DatabaseModelSnapshot.cs b/ProjectLighthouse/Migrations/DatabaseModelSnapshot.cs index 0e83b95a..d4f8cfe9 100644 --- a/ProjectLighthouse/Migrations/DatabaseModelSnapshot.cs +++ b/ProjectLighthouse/Migrations/DatabaseModelSnapshot.cs @@ -472,9 +472,8 @@ namespace ProjectLighthouse.Migrations b.Property("Deleted") .HasColumnType("tinyint(1)"); - b.Property("DeletedBy") - .IsRequired() - .HasColumnType("longtext"); + b.Property("DeletedBy") + .HasColumnType("int"); b.Property("LabelCollection") .IsRequired() @@ -490,6 +489,15 @@ namespace ProjectLighthouse.Migrations .IsRequired() .HasColumnType("longtext"); + b.Property("Thumb") + .HasColumnType("int"); + + b.Property("ThumbsDown") + .HasColumnType("int"); + + b.Property("ThumbsUp") + .HasColumnType("int"); + b.Property("Timestamp") .HasColumnType("bigint"); From e07fd5714e5607d2e56942956d96d34afdd00783 Mon Sep 17 00:00:00 2001 From: LumaLivy <7350336+LumaLivy@users.noreply.github.com> Date: Fri, 10 Dec 2021 23:37:55 -0500 Subject: [PATCH 2/6] Cache Review Stats; Migrate DeletedBy to enum --- .../Controllers/ReviewController.cs | 60 +++++++++++++++---- ProjectLighthouse/Types/DeletedBy.cs | 12 +++- ProjectLighthouse/Types/Reviews/Review.cs | 36 ++++------- 3 files changed, 69 insertions(+), 39 deletions(-) diff --git a/ProjectLighthouse/Controllers/ReviewController.cs b/ProjectLighthouse/Controllers/ReviewController.cs index 35948771..c6145e3e 100644 --- a/ProjectLighthouse/Controllers/ReviewController.cs +++ b/ProjectLighthouse/Controllers/ReviewController.cs @@ -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 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 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 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 diff --git a/ProjectLighthouse/Types/DeletedBy.cs b/ProjectLighthouse/Types/DeletedBy.cs index 02d61ec0..666e4437 100644 --- a/ProjectLighthouse/Types/DeletedBy.cs +++ b/ProjectLighthouse/Types/DeletedBy.cs @@ -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) } } \ No newline at end of file diff --git a/ProjectLighthouse/Types/Reviews/Review.cs b/ProjectLighthouse/Types/Reviews/Review.cs index a2ee79d0..3a25bd06 100644 --- a/ProjectLighthouse/Types/Reviews/Review.cs +++ b/ProjectLighthouse/Types/Reviews/Review.cs @@ -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 - - [NotMapped] + public int Thumb { get; set; } + [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) + @@ -97,5 +83,5 @@ namespace LBPUnion.ProjectLighthouse.Types.Reviews } } - + } \ No newline at end of file From 9ad1f6eeb155a2158f01a37334e2be3a086bdc20 Mon Sep 17 00:00:00 2001 From: LumaLivy <7350336+LumaLivy@users.noreply.github.com> Date: Sat, 11 Dec 2021 00:01:51 -0500 Subject: [PATCH 3/6] Finalize adding review support/cleaning some warnings --- .gitignore | 8 ++ ProjectLighthouse/Database.cs | 7 +- .../Maintenance/Commands/CreateUserCommand.cs | 5 +- .../Commands/WipeTokensForUserCommand.cs | 1 + .../20211211043517_CacheReviewStats.cs | 66 ----------- ...0211211045823_AddLevelReviews.Designer.cs} | 17 ++- .../20211211045823_AddLevelReviews.cs | 107 ++++++++++++++++++ .../Migrations/DatabaseModelSnapshot.cs | 38 +++++++ .../ExternalAuth/AuthenticationPage.cshtml.cs | 2 +- .../Types/Settings/ServerStatics.cs | 8 +- 10 files changed, 180 insertions(+), 79 deletions(-) delete mode 100644 ProjectLighthouse/Migrations/20211211043517_CacheReviewStats.cs rename ProjectLighthouse/Migrations/{20211211043517_CacheReviewStats.Designer.cs => 20211211045823_AddLevelReviews.Designer.cs} (98%) create mode 100644 ProjectLighthouse/Migrations/20211211045823_AddLevelReviews.cs diff --git a/.gitignore b/.gitignore index bb08bcee..d0391f6a 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,11 @@ riderModule.iml lighthouse.config.json gitBranch.txt gitVersion.txt +ProjectLighthouse/.vscode/tasks.json +ProjectLighthouse/.vscode/launch.json +logs/Startup.log +logs/LoggerInfo.log +logs/all.log +.vscode/tasks.json +.vscode/launch.json +.editorconfig diff --git a/ProjectLighthouse/Database.cs b/ProjectLighthouse/Database.cs index 3a5366cc..6e84e6ef 100644 --- a/ProjectLighthouse/Database.cs +++ b/ProjectLighthouse/Database.cs @@ -6,6 +6,7 @@ using LBPUnion.ProjectLighthouse.Helpers; using LBPUnion.ProjectLighthouse.Logging; using LBPUnion.ProjectLighthouse.Types; using LBPUnion.ProjectLighthouse.Types.Levels; +using LBPUnion.ProjectLighthouse.Types.Reviews; using LBPUnion.ProjectLighthouse.Types.Profiles; using LBPUnion.ProjectLighthouse.Types.Settings; using Microsoft.AspNetCore.Http; @@ -31,6 +32,8 @@ namespace LBPUnion.ProjectLighthouse public DbSet VisitedLevels { get; set; } public DbSet RatedLevels { get; set; } public DbSet AuthenticationAttempts { get; set; } + public DbSet Reviews { get; set; } + public DbSet RatedReviews { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder options) => options.UseMySql(ServerSettings.Instance.DbConnectionString, MySqlServerVersion.LatestSupportedServerVersion); @@ -60,7 +63,7 @@ namespace LBPUnion.ProjectLighthouse return user; } - #nullable enable +#nullable enable public async Task AuthenticateUser(LoginData loginData, string userLocation, string titleId = "") { // TODO: don't use psn name to authenticate @@ -252,6 +255,6 @@ namespace LBPUnion.ProjectLighthouse public async Task PhotoFromSubject(PhotoSubject subject) => await this.Photos.FirstOrDefaultAsync(p => p.PhotoSubjectIds.Contains(subject.PhotoSubjectId.ToString())); - #nullable disable +#nullable disable } } \ No newline at end of file diff --git a/ProjectLighthouse/Maintenance/Commands/CreateUserCommand.cs b/ProjectLighthouse/Maintenance/Commands/CreateUserCommand.cs index b3db6c4a..ca0379fb 100644 --- a/ProjectLighthouse/Maintenance/Commands/CreateUserCommand.cs +++ b/ProjectLighthouse/Maintenance/Commands/CreateUserCommand.cs @@ -1,5 +1,4 @@ -using System; -using System.Diagnostics; +#nullable enable using System.Threading.Tasks; using JetBrains.Annotations; using Kettu; @@ -21,7 +20,7 @@ namespace LBPUnion.ProjectLighthouse.Maintenance.Commands string password = args[1]; password = HashHelper.Sha256Hash(password); - + User? user = await this._database.Users.FirstOrDefaultAsync(u => u.Username == onlineId); if (user == null) { diff --git a/ProjectLighthouse/Maintenance/Commands/WipeTokensForUserCommand.cs b/ProjectLighthouse/Maintenance/Commands/WipeTokensForUserCommand.cs index 4e42461a..3da9514c 100644 --- a/ProjectLighthouse/Maintenance/Commands/WipeTokensForUserCommand.cs +++ b/ProjectLighthouse/Maintenance/Commands/WipeTokensForUserCommand.cs @@ -1,3 +1,4 @@ +#nullable enable using System; using System.Linq; using System.Threading.Tasks; diff --git a/ProjectLighthouse/Migrations/20211211043517_CacheReviewStats.cs b/ProjectLighthouse/Migrations/20211211043517_CacheReviewStats.cs deleted file mode 100644 index 43ff8248..00000000 --- a/ProjectLighthouse/Migrations/20211211043517_CacheReviewStats.cs +++ /dev/null @@ -1,66 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace ProjectLighthouse.Migrations -{ - public partial class CacheReviewStats : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "DeletedBy", - table: "Reviews", - type: "int", - nullable: false, - oldClrType: typeof(string), - oldType: "longtext") - .OldAnnotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.AddColumn( - name: "Thumb", - table: "Reviews", - type: "int", - nullable: false, - defaultValue: 0); - - migrationBuilder.AddColumn( - name: "ThumbsDown", - table: "Reviews", - type: "int", - nullable: false, - defaultValue: 0); - - migrationBuilder.AddColumn( - name: "ThumbsUp", - table: "Reviews", - type: "int", - nullable: false, - defaultValue: 0); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "Thumb", - table: "Reviews"); - - migrationBuilder.DropColumn( - name: "ThumbsDown", - table: "Reviews"); - - migrationBuilder.DropColumn( - name: "ThumbsUp", - table: "Reviews"); - - migrationBuilder.AlterColumn( - name: "DeletedBy", - table: "Reviews", - type: "longtext", - nullable: false, - oldClrType: typeof(int), - oldType: "int") - .Annotation("MySql:CharSet", "utf8mb4"); - } - } -} diff --git a/ProjectLighthouse/Migrations/20211211043517_CacheReviewStats.Designer.cs b/ProjectLighthouse/Migrations/20211211045823_AddLevelReviews.Designer.cs similarity index 98% rename from ProjectLighthouse/Migrations/20211211043517_CacheReviewStats.Designer.cs rename to ProjectLighthouse/Migrations/20211211045823_AddLevelReviews.Designer.cs index ca4261c1..98610a6c 100644 --- a/ProjectLighthouse/Migrations/20211211043517_CacheReviewStats.Designer.cs +++ b/ProjectLighthouse/Migrations/20211211045823_AddLevelReviews.Designer.cs @@ -10,8 +10,8 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion; namespace ProjectLighthouse.Migrations { [DbContext(typeof(Database))] - [Migration("20211211043517_CacheReviewStats")] - partial class CacheReviewStats + [Migration("20211211045823_AddLevelReviews")] + partial class AddLevelReviews { protected override void BuildTargetModel(ModelBuilder modelBuilder) { @@ -407,7 +407,7 @@ namespace ProjectLighthouse.Migrations b.ToTable("Comments"); }); - modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.LastMatch", b => + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.LastContact", b => { b.Property("UserId") .ValueGeneratedOnAdd() @@ -421,7 +421,7 @@ namespace ProjectLighthouse.Migrations b.HasKey("UserId"); - b.ToTable("LastMatches"); + b.ToTable("LastContacts"); }); modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Profiles.Location", b => @@ -546,6 +546,9 @@ namespace ProjectLighthouse.Migrations b.Property("Biography") .HasColumnType("longtext"); + b.Property("BooHash") + .HasColumnType("longtext"); + b.Property("Game") .HasColumnType("int"); @@ -558,6 +561,9 @@ namespace ProjectLighthouse.Migrations b.Property("LocationId") .HasColumnType("int"); + b.Property("MehHash") + .HasColumnType("longtext"); + b.Property("Password") .HasColumnType("longtext"); @@ -573,6 +579,9 @@ namespace ProjectLighthouse.Migrations b.Property("Username") .HasColumnType("longtext"); + b.Property("YayHash") + .HasColumnType("longtext"); + b.HasKey("UserId"); b.HasIndex("LocationId"); diff --git a/ProjectLighthouse/Migrations/20211211045823_AddLevelReviews.cs b/ProjectLighthouse/Migrations/20211211045823_AddLevelReviews.cs new file mode 100644 index 00000000..ccdf6c2c --- /dev/null +++ b/ProjectLighthouse/Migrations/20211211045823_AddLevelReviews.cs @@ -0,0 +1,107 @@ +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace ProjectLighthouse.Migrations +{ + public partial class AddLevelReviews : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Reviews", + columns: table => new + { + ReviewId = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + ReviewerId = table.Column(type: "int", nullable: false), + SlotId = table.Column(type: "int", nullable: false), + Timestamp = table.Column(type: "bigint", nullable: false), + LabelCollection = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Deleted = table.Column(type: "tinyint(1)", nullable: false), + DeletedBy = table.Column(type: "int", nullable: false), + Text = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Thumb = table.Column(type: "int", nullable: false), + ThumbsUp = table.Column(type: "int", nullable: false), + ThumbsDown = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Reviews", x => x.ReviewId); + table.ForeignKey( + name: "FK_Reviews_Slots_SlotId", + column: x => x.SlotId, + principalTable: "Slots", + principalColumn: "SlotId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_Reviews_Users_ReviewerId", + column: x => x.ReviewerId, + principalTable: "Users", + principalColumn: "UserId", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "RatedReviews", + columns: table => new + { + RatedReviewId = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + UserId = table.Column(type: "int", nullable: false), + ReviewId = table.Column(type: "int", nullable: false), + Thumb = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_RatedReviews", x => x.RatedReviewId); + table.ForeignKey( + name: "FK_RatedReviews_Reviews_ReviewId", + column: x => x.ReviewId, + principalTable: "Reviews", + principalColumn: "ReviewId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_RatedReviews_Users_UserId", + column: x => x.UserId, + principalTable: "Users", + principalColumn: "UserId", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateIndex( + name: "IX_RatedReviews_ReviewId", + table: "RatedReviews", + column: "ReviewId"); + + migrationBuilder.CreateIndex( + name: "IX_RatedReviews_UserId", + table: "RatedReviews", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_Reviews_ReviewerId", + table: "Reviews", + column: "ReviewerId"); + + migrationBuilder.CreateIndex( + name: "IX_Reviews_SlotId", + table: "Reviews", + column: "SlotId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "RatedReviews"); + + migrationBuilder.DropTable( + name: "Reviews"); + } + } +} diff --git a/ProjectLighthouse/Migrations/DatabaseModelSnapshot.cs b/ProjectLighthouse/Migrations/DatabaseModelSnapshot.cs index 70f91a28..4afc7b51 100644 --- a/ProjectLighthouse/Migrations/DatabaseModelSnapshot.cs +++ b/ProjectLighthouse/Migrations/DatabaseModelSnapshot.cs @@ -770,6 +770,44 @@ namespace ProjectLighthouse.Migrations b.Navigation("Target"); }); + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Reviews.RatedReview", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.Reviews.Review", "Review") + .WithMany() + .HasForeignKey("ReviewId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Review"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Reviews.Review", b => + { + b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "Reviewer") + .WithMany() + .HasForeignKey("ReviewerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot") + .WithMany() + .HasForeignKey("SlotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Reviewer"); + + b.Navigation("Slot"); + }); + modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Score", b => { b.HasOne("LBPUnion.ProjectLighthouse.Types.Levels.Slot", "Slot") diff --git a/ProjectLighthouse/Pages/ExternalAuth/AuthenticationPage.cshtml.cs b/ProjectLighthouse/Pages/ExternalAuth/AuthenticationPage.cshtml.cs index f64d3102..c4bd98e3 100644 --- a/ProjectLighthouse/Pages/ExternalAuth/AuthenticationPage.cshtml.cs +++ b/ProjectLighthouse/Pages/ExternalAuth/AuthenticationPage.cshtml.cs @@ -12,7 +12,7 @@ namespace LBPUnion.ProjectLighthouse.Pages.ExternalAuth public class AuthenticationPage : BaseLayout { public AuthenticationPage(Database database) : base(database) - {} + { } public List AuthenticationAttempts; diff --git a/ProjectLighthouse/Types/Settings/ServerStatics.cs b/ProjectLighthouse/Types/Settings/ServerStatics.cs index 1bb8227c..d5f94c12 100644 --- a/ProjectLighthouse/Types/Settings/ServerStatics.cs +++ b/ProjectLighthouse/Types/Settings/ServerStatics.cs @@ -10,13 +10,15 @@ namespace LBPUnion.ProjectLighthouse.Types.Settings { public const string ServerName = "ProjectLighthouse"; - public static bool DbConnected { - get { + public static bool DbConnected + { + get + { try { return new Database().Database.CanConnect(); } - catch(Exception e) + catch (Exception e) { Logger.Log(e.ToString(), LoggerLevelDatabase.Instance); return false; From d596eeefc2b7ba73a4b02a7daebf661675e597f7 Mon Sep 17 00:00:00 2001 From: LumaLivy <7350336+LumaLivy@users.noreply.github.com> Date: Sat, 11 Dec 2021 01:03:46 -0500 Subject: [PATCH 4/6] Reviews now appear ingame --- .../Controllers/ReviewController.cs | 11 +-- ProjectLighthouse/Types/DeletedBy.cs | 1 + ProjectLighthouse/Types/Levels/Slot.cs | 48 ++++++++++--- ProjectLighthouse/Types/Reviews/Review.cs | 17 ++++- ProjectLighthouse/Types/User.cs | 71 +++++++++++++------ 5 files changed, 108 insertions(+), 40 deletions(-) diff --git a/ProjectLighthouse/Controllers/ReviewController.cs b/ProjectLighthouse/Controllers/ReviewController.cs index 65e007de..55e75962 100644 --- a/ProjectLighthouse/Controllers/ReviewController.cs +++ b/ProjectLighthouse/Controllers/ReviewController.cs @@ -146,10 +146,13 @@ namespace LBPUnion.ProjectLighthouse.Controllers Random rand = new(); 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; + + Boolean canNowReviewLevel = slot.CreatorId != user.UserId && 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); @@ -160,10 +163,10 @@ namespace LBPUnion.ProjectLighthouse.Controllers yourReview.Thumb = ratedLevel?.Rating == null ? 0 : ratedLevel.Rating; yourReview.Slot = slot; yourReview.SlotId = slotId; + yourReview.Deleted = false; 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(); } @@ -226,9 +229,9 @@ namespace LBPUnion.ProjectLighthouse.Controllers string inner = Enumerable.Aggregate(reviews, string.Empty, (current, review) => { - RatedLevel? ratedLevel = this.database.RatedLevels.FirstOrDefault(r => r.SlotId == review.SlotId && r.UserId == user.UserId); + //RatedLevel? ratedLevel = this.database.RatedLevels.FirstOrDefault(r => r.SlotId == review.SlotId && r.UserId == user.UserId); //RatedReview? ratedReview = this.database.RatedReviews.FirstOrDefault(r => r.ReviewId == review.ReviewId && r.UserId == user.UserId); - return current + review.Serialize(ratedLevel/*, ratedReview*/); + return current + review.Serialize(/*, ratedReview*/); }); string response = LbpSerializer.TaggedStringElement("reviews", inner, new Dictionary diff --git a/ProjectLighthouse/Types/DeletedBy.cs b/ProjectLighthouse/Types/DeletedBy.cs index 666e4437..c8beade1 100644 --- a/ProjectLighthouse/Types/DeletedBy.cs +++ b/ProjectLighthouse/Types/DeletedBy.cs @@ -2,6 +2,7 @@ using System.Xml.Serialization; namespace LBPUnion.ProjectLighthouse.Types { + [XmlRoot("deleted_by")] public enum DeletedBy { [XmlEnum(Name = "none")] diff --git a/ProjectLighthouse/Types/Levels/Slot.cs b/ProjectLighthouse/Types/Levels/Slot.cs index ff0c580e..de339f29 100644 --- a/ProjectLighthouse/Types/Levels/Slot.cs +++ b/ProjectLighthouse/Types/Levels/Slot.cs @@ -6,6 +6,7 @@ using System.Xml.Serialization; using LBPUnion.ProjectLighthouse.Helpers; using LBPUnion.ProjectLighthouse.Serialization; using LBPUnion.ProjectLighthouse.Types.Profiles; +using LBPUnion.ProjectLighthouse.Types.Reviews; namespace LBPUnion.ProjectLighthouse.Types.Levels { @@ -40,7 +41,8 @@ namespace LBPUnion.ProjectLighthouse.Types.Levels [NotMapped] [XmlElement("resource")] - public string[] Resources { + public string[] Resources + { get => this.ResourceCollection.Split(","); set => this.ResourceCollection = string.Join(',', value); } @@ -102,8 +104,10 @@ namespace LBPUnion.ProjectLighthouse.Types.Levels [XmlIgnore] [NotMapped] - public int Hearts { - get { + public int Hearts + { + get + { using Database database = new(); return database.HeartedLevels.Count(s => s.SlotId == this.SlotId); @@ -160,8 +164,10 @@ namespace LBPUnion.ProjectLighthouse.Types.Levels [NotMapped] [XmlElement("thumbsup")] - public int Thumbsup { - get { + public int Thumbsup + { + get + { using Database database = new(); return database.RatedLevels.Count(r => r.SlotId == this.SlotId && r.Rating == 1); @@ -170,8 +176,10 @@ namespace LBPUnion.ProjectLighthouse.Types.Levels [NotMapped] [XmlElement("thumbsdown")] - public int Thumbsdown { - get { + public int Thumbsdown + { + get + { using Database database = new(); return database.RatedLevels.Count(r => r.SlotId == this.SlotId && r.Rating == -1); @@ -180,8 +188,10 @@ namespace LBPUnion.ProjectLighthouse.Types.Levels [NotMapped] [XmlElement("averageRating")] - public double RatingLBP1 { - get { + public double RatingLBP1 + { + get + { using Database database = new(); IQueryable ratedLevels = database.RatedLevels.Where(r => r.SlotId == this.SlotId && r.RatingLBP1 > 0); @@ -191,6 +201,18 @@ namespace LBPUnion.ProjectLighthouse.Types.Levels } } + [NotMapped] + [XmlElement("reviewCount")] + public int ReviewCount + { + get + { + using Database database = new(); + + return database.Reviews.Count(r => r.SlotId == this.SlotId); + } + } + [XmlElement("leveltype")] public string LevelType { get; set; } = ""; @@ -200,7 +222,7 @@ namespace LBPUnion.ProjectLighthouse.Types.Levels LbpSerializer.StringElement("sizeOfResources", this.Resources.Sum(FileHelper.ResourceSize)); } - public string Serialize(RatedLevel? yourRatingStats = null, VisitedLevel? yourVisitedStats = null) + public string Serialize(RatedLevel? yourRatingStats = null, VisitedLevel? yourVisitedStats = null, Review? yourReview = null) { string slotData = LbpSerializer.StringElement("name", this.Name) + @@ -249,7 +271,11 @@ namespace LBPUnion.ProjectLighthouse.Types.Levels LbpSerializer.StringElement("yourLBP2PlayCount", yourVisitedStats?.PlaysLBP2) + LbpSerializer.StringElement("yourLBP3PlayCount", yourVisitedStats?.PlaysLBP3) + LbpSerializer.StringElement - ("yourLBPVitaPlayCount", yourVisitedStats?.PlaysLBPVita); // i doubt this is the right name but we'll go with it + ("yourLBPVitaPlayCount", yourVisitedStats?.PlaysLBPVita) + // i doubt this is the right name but we'll go with it + yourReview?.Serialize("yourReview") + + LbpSerializer.StringElement("reviewsEnabled", true) + + LbpSerializer.StringElement("commentsEnabled", false) + + LbpSerializer.StringElement("reviewCount", this.ReviewCount); return LbpSerializer.TaggedStringElement("slot", slotData, "type", "user"); } diff --git a/ProjectLighthouse/Types/Reviews/Review.cs b/ProjectLighthouse/Types/Reviews/Review.cs index 3a25bd06..80ca0e80 100644 --- a/ProjectLighthouse/Types/Reviews/Review.cs +++ b/ProjectLighthouse/Types/Reviews/Review.cs @@ -1,10 +1,11 @@ #nullable enable using System; +using System.IO; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; -using System.Linq; using LBPUnion.ProjectLighthouse.Types.Levels; using LBPUnion.ProjectLighthouse.Serialization; +using System.Xml; using System.Xml.Serialization; namespace LBPUnion.ProjectLighthouse.Types.Reviews @@ -67,13 +68,25 @@ namespace LBPUnion.ProjectLighthouse.Types.Reviews public string Serialize(string elementOverride, RatedLevel? yourLevelRating = null, RatedReview? yourRatingStats = null) { + + XmlWriterSettings settings = new XmlWriterSettings(); + settings.OmitXmlDeclaration = true; + + XmlSerializer serializer = new(typeof(DeletedBy)); + StringWriter stringWriter = new StringWriter(); + using (XmlWriter xmlWriter = XmlWriter.Create(stringWriter, settings)) + { + serializer.Serialize(xmlWriter, this.DeletedBy); + } + string deletedBy = stringWriter.ToString(); + string reviewData = LbpSerializer.TaggedStringElement("slot_id", this.SlotId, "type", this.Slot.Type) + LbpSerializer.StringElement("reviewer", this.Reviewer.Username) + LbpSerializer.StringElement("thumb", this.Thumb) + LbpSerializer.StringElement("timestamp", this.Timestamp) + LbpSerializer.StringElement("labels", this.LabelCollection) + LbpSerializer.StringElement("deleted", this.Deleted) + - LbpSerializer.StringElement("deleted_by", this.DeletedBy) + + deletedBy + LbpSerializer.StringElement("text", this.Text) + LbpSerializer.StringElement("thumbsup", this.ThumbsUp) + LbpSerializer.StringElement("thumbsdown", this.ThumbsDown) + diff --git a/ProjectLighthouse/Types/User.cs b/ProjectLighthouse/Types/User.cs index 6f24a385..f88f0f1b 100644 --- a/ProjectLighthouse/Types/User.cs +++ b/ProjectLighthouse/Types/User.cs @@ -26,27 +26,40 @@ namespace LBPUnion.ProjectLighthouse.Types public string Biography { get; set; } [NotMapped] - public int Reviews => 0; + public int Reviews + { + get + { + using Database database = new(); + return database.Reviews.Count(r => r.ReviewerId == this.UserId); + } + } [NotMapped] - public int Comments { - get { + public int Comments + { + get + { using Database database = new(); return database.Comments.Count(c => c.TargetUserId == this.UserId); } } [NotMapped] - public int PhotosByMe { - get { + public int PhotosByMe + { + get + { using Database database = new(); return database.Photos.Count(p => p.CreatorId == this.UserId); } } [NotMapped] - public int PhotosWithMe { - get { + public int PhotosWithMe + { + get + { using Database database = new(); return Enumerable.Sum(database.Photos, photo => photo.Subjects.Count(subject => subject.User.UserId == this.UserId)); } @@ -61,24 +74,30 @@ namespace LBPUnion.ProjectLighthouse.Types public Location Location { get; set; } [NotMapped] - public int HeartedLevels { - get { + public int HeartedLevels + { + get + { using Database database = new(); return database.HeartedLevels.Count(p => p.UserId == this.UserId); } } [NotMapped] - public int HeartedUsers { - get { + public int HeartedUsers + { + get + { using Database database = new(); return database.HeartedProfiles.Count(p => p.UserId == this.UserId); } } [NotMapped] - public int QueuedLevels { - get { + public int QueuedLevels + { + get + { using Database database = new(); return database.QueuedLevels.Count(p => p.UserId == this.UserId); } @@ -88,8 +107,10 @@ namespace LBPUnion.ProjectLighthouse.Types public string PlanetHash { get; set; } = ""; - public int Hearts { - get { + public int Hearts + { + get + { using Database database = new(); return database.HeartedProfiles.Count(s => s.HeartedUserId == this.UserId); @@ -104,10 +125,12 @@ namespace LBPUnion.ProjectLighthouse.Types public string BooHash { get; set; } = ""; public string MehHash { get; set; } = ""; - #nullable enable +#nullable enable [NotMapped] - public string Status { - get { + public string Status + { + get + { using Database database = new(); LastContact? lastMatch = database.LastContacts.Where (l => l.UserId == this.UserId) @@ -118,7 +141,7 @@ namespace LBPUnion.ProjectLighthouse.Types return "Currently online on " + lastMatch.GameVersion.ToPrettyString(); } } - #nullable disable +#nullable disable public string Serialize(GameVersion gameVersion = GameVersion.LittleBigPlanet1) { @@ -156,8 +179,10 @@ namespace LBPUnion.ProjectLighthouse.Types /// The number of used slots on the earth /// [NotMapped] - public int UsedSlots { - get { + public int UsedSlots + { + get + { using Database database = new(); return database.Slots.Count(s => s.CreatorId == this.UserId); } @@ -218,7 +243,7 @@ namespace LBPUnion.ProjectLighthouse.Types #endregion Slots - #nullable enable +#nullable enable public override bool Equals(object? obj) { if (obj is User user) return user.UserId == UserId; @@ -238,6 +263,6 @@ namespace LBPUnion.ProjectLighthouse.Types [SuppressMessage("ReSharper", "NonReadonlyMemberInGetHashCode")] public override int GetHashCode() => this.UserId; - #nullable disable +#nullable disable } } \ No newline at end of file From 16a41d4fb50e1506604664e22fe6c83ccd03eddd Mon Sep 17 00:00:00 2001 From: LumaLivy <7350336+LumaLivy@users.noreply.github.com> Date: Sat, 11 Dec 2021 01:07:06 -0500 Subject: [PATCH 5/6] Update wording on review template --- ProjectLighthouse/Controllers/ReviewController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ProjectLighthouse/Controllers/ReviewController.cs b/ProjectLighthouse/Controllers/ReviewController.cs index 55e75962..ca6549ba 100644 --- a/ProjectLighthouse/Controllers/ReviewController.cs +++ b/ProjectLighthouse/Controllers/ReviewController.cs @@ -165,7 +165,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers yourReview.SlotId = slotId; yourReview.Deleted = false; yourReview.DeletedBy = DeletedBy.None; - yourReview.Text = "You haven't reviewed this level yet. Edit this blank review to upload it!"; + yourReview.Text = "You haven't reviewed this level yet. Edit this blank review to upload one!"; yourReview.LabelCollection = ""; yourReview.Timestamp = TimeHelper.UnixTimeMilliseconds(); } From aa71592a1ecc29bbcf78e348f66bbc6dbca9f305 Mon Sep 17 00:00:00 2001 From: LumaLivy <7350336+LumaLivy@users.noreply.github.com> Date: Sat, 11 Dec 2021 01:38:23 -0500 Subject: [PATCH 6/6] Restore behaviour of cached review stats --- ProjectLighthouse/Controllers/ReviewController.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ProjectLighthouse/Controllers/ReviewController.cs b/ProjectLighthouse/Controllers/ReviewController.cs index ca6549ba..71befbb0 100644 --- a/ProjectLighthouse/Controllers/ReviewController.cs +++ b/ProjectLighthouse/Controllers/ReviewController.cs @@ -269,8 +269,18 @@ namespace LBPUnion.ProjectLighthouse.Controllers this.database.RatedReviews.Add(ratedReview); } + int oldThumb = ratedReview.Thumb; ratedReview.Thumb = Math.Max(Math.Min(1, rating), -1); + if (oldThumb != ratedReview.Thumb) + { + if (oldThumb == -1) review.ThumbsDown--; + else if (oldThumb == 1) review.ThumbsUp--; + + if (ratedReview.Thumb == -1) review.ThumbsDown++; + else if (ratedReview.Thumb == 1) review.ThumbsUp++; + } + await this.database.SaveChangesAsync(); return this.Ok();