mirror of
https://github.com/LBPUnion/ProjectLighthouse.git
synced 2025-09-27 11:49:05 +00:00
Attempt to remodel PhotoSubject and Photo relationship
This commit is contained in:
parent
35ea2682b9
commit
6cd3d61fa0
8 changed files with 126 additions and 40 deletions
|
@ -95,20 +95,20 @@ public class PhotosController : ControllerBase
|
||||||
if (validLevel) photo.SlotId = photo.XmlLevelInfo.SlotId;
|
if (validLevel) photo.SlotId = photo.XmlLevelInfo.SlotId;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (photo.Subjects.Count > 4) return this.BadRequest();
|
if (photo.PhotoSubjects.Count > 4) return this.BadRequest();
|
||||||
|
|
||||||
if (photo.Timestamp > TimeHelper.Timestamp) photo.Timestamp = TimeHelper.Timestamp;
|
if (photo.Timestamp > TimeHelper.Timestamp) photo.Timestamp = TimeHelper.Timestamp;
|
||||||
|
|
||||||
// Check for duplicate photo subjects
|
// Check for duplicate photo subjects
|
||||||
List<string> subjectUserIds = new(4);
|
List<string> subjectUserIds = new(4);
|
||||||
foreach (PhotoSubject subject in photo.Subjects)
|
foreach (PhotoSubject subject in photo.PhotoSubjects)
|
||||||
{
|
{
|
||||||
if (subjectUserIds.Contains(subject.Username) && !string.IsNullOrEmpty(subject.Username)) return this.BadRequest();
|
if (subjectUserIds.Contains(subject.Username) && !string.IsNullOrEmpty(subject.Username)) return this.BadRequest();
|
||||||
|
|
||||||
subjectUserIds.Add(subject.Username);
|
subjectUserIds.Add(subject.Username);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (PhotoSubject subject in photo.Subjects.Where(subject => !string.IsNullOrEmpty(subject.Username)))
|
foreach (PhotoSubject subject in photo.PhotoSubjects.Where(subject => !string.IsNullOrEmpty(subject.Username)))
|
||||||
{
|
{
|
||||||
subject.User = await this.database.Users.FirstOrDefaultAsync(u => u.Username == subject.Username);
|
subject.User = await this.database.Users.FirstOrDefaultAsync(u => u.Username == subject.Username);
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ public class PhotosController : ControllerBase
|
||||||
|
|
||||||
await this.database.SaveChangesAsync();
|
await this.database.SaveChangesAsync();
|
||||||
|
|
||||||
photo.PhotoSubjectIds = photo.Subjects.Where(s => s.UserId != 0).Select(subject => subject.PhotoSubjectId.ToString()).ToArray();
|
photo.PhotoSubjectIds = photo.PhotoSubjects.Where(s => s.UserId != 0).Select(subject => subject.PhotoSubjectId.ToString()).ToArray();
|
||||||
|
|
||||||
Logger.Debug($"Adding PhotoSubjectCollection ({photo.PhotoSubjectCollection}) to photo", LogArea.Photos);
|
Logger.Debug($"Adding PhotoSubjectCollection ({photo.PhotoSubjectCollection}) to photo", LogArea.Photos);
|
||||||
|
|
||||||
|
|
|
@ -76,21 +76,21 @@
|
||||||
</i>
|
</i>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@if (Model.Subjects.Count > 0)
|
@if (Model.PhotoSubjects.Count > 0)
|
||||||
{
|
{
|
||||||
<p>
|
<p>
|
||||||
<b>Photo contains @Model.Subjects.Count @(Model.Subjects.Count == 1 ? "person" : "people"):</b>
|
<b>Photo contains @Model.PhotoSubjects.Count @(Model.PhotoSubjects.Count == 1 ? "person" : "people"):</b>
|
||||||
</p>
|
</p>
|
||||||
}
|
}
|
||||||
<div id="hover-subjects-@Model.PhotoId">
|
<div id="hover-subjects-@Model.PhotoId">
|
||||||
@foreach (PhotoSubject subject in Model.Subjects)
|
@foreach (PhotoSubject subject in Model.PhotoSubjects)
|
||||||
{
|
{
|
||||||
@await subject.User.ToLink(Html, ViewData, language, timeZone)
|
@await subject.User.ToLink(Html, ViewData, language, timeZone)
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@{
|
@{
|
||||||
PhotoSubject[] subjects = Model.Subjects.ToArray();
|
PhotoSubject[] subjects = Model.PhotoSubjects.ToArray();
|
||||||
foreach (PhotoSubject subject in subjects) subject.Username = subject.User.Username;
|
foreach (PhotoSubject subject in subjects) subject.Username = subject.User.Username;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ public class CleanupBrokenPhotosMaintenanceJob : IMaintenanceJob
|
||||||
|
|
||||||
// Checks should generally be ordered in least computationally expensive to most.
|
// Checks should generally be ordered in least computationally expensive to most.
|
||||||
|
|
||||||
if (photo.Subjects.Count > 4)
|
if (photo.PhotoSubjects.Count > 4)
|
||||||
{
|
{
|
||||||
tooManyPhotoSubjects = true;
|
tooManyPhotoSubjects = true;
|
||||||
goto removePhoto;
|
goto removePhoto;
|
||||||
|
@ -60,7 +60,7 @@ public class CleanupBrokenPhotosMaintenanceJob : IMaintenanceJob
|
||||||
};
|
};
|
||||||
|
|
||||||
List<int> subjectUserIds = new(4);
|
List<int> subjectUserIds = new(4);
|
||||||
foreach (PhotoSubject subject in photo.Subjects)
|
foreach (PhotoSubject subject in photo.PhotoSubjects)
|
||||||
{
|
{
|
||||||
if (subjectUserIds.Contains(subject.UserId))
|
if (subjectUserIds.Contains(subject.UserId))
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
using LBPUnion.ProjectLighthouse.Database;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace ProjectLighthouse.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(DatabaseContext))]
|
||||||
|
[Migration("20230215195324_ChangeLocationStorage")]
|
||||||
|
public partial class FixPhotoAndSubjectRelation : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "PhotoId",
|
||||||
|
table: "PhotoSubjects",
|
||||||
|
type: "int",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0);
|
||||||
|
|
||||||
|
migrationBuilder.Sql(
|
||||||
|
"UPDATE PhotoSubjects as ps inner join Photos as p on find_in_set(ps.PhotoSubjectId, p.PhotoSubjectCollection) SET ps.PhotoId = p.PhotoId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_PhotoSubjects_PhotoId",
|
||||||
|
table: "PhotoSubjects",
|
||||||
|
column: "PhotoId");
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_PhotoSubjects_Photos_PhotoId",
|
||||||
|
table: "PhotoSubjects",
|
||||||
|
column: "PhotoId",
|
||||||
|
principalTable: "Photos",
|
||||||
|
principalColumn: "PhotoId",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_PhotoSubjects_Photos_PhotoId",
|
||||||
|
table: "PhotoSubjects");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_PhotoSubjects_PhotoId",
|
||||||
|
table: "PhotoSubjects");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "PhotoId",
|
||||||
|
table: "PhotoSubjects");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,5 @@
|
||||||
// <auto-generated />
|
// <auto-generated />
|
||||||
using System;
|
using System;
|
||||||
using LBPUnion.ProjectLighthouse;
|
|
||||||
using LBPUnion.ProjectLighthouse.Database;
|
using LBPUnion.ProjectLighthouse.Database;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
@ -719,11 +718,16 @@ namespace ProjectLighthouse.Migrations
|
||||||
b.Property<string>("Bounds")
|
b.Property<string>("Bounds")
|
||||||
.HasColumnType("longtext");
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("PhotoId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
b.Property<int>("UserId")
|
b.Property<int>("UserId")
|
||||||
.HasColumnType("int");
|
.HasColumnType("int");
|
||||||
|
|
||||||
b.HasKey("PhotoSubjectId");
|
b.HasKey("PhotoSubjectId");
|
||||||
|
|
||||||
|
b.HasIndex("PhotoId");
|
||||||
|
|
||||||
b.HasIndex("UserId");
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
b.ToTable("PhotoSubjects");
|
b.ToTable("PhotoSubjects");
|
||||||
|
@ -1296,12 +1300,20 @@ namespace ProjectLighthouse.Migrations
|
||||||
|
|
||||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Profile.PhotoSubject", b =>
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Profile.PhotoSubject", b =>
|
||||||
{
|
{
|
||||||
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Profile.Photo", "Photo")
|
||||||
|
.WithMany("PhotoSubjects")
|
||||||
|
.HasForeignKey("PhotoId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Profile.User", "User")
|
b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Profile.User", "User")
|
||||||
.WithMany()
|
.WithMany()
|
||||||
.HasForeignKey("UserId")
|
.HasForeignKey("UserId")
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Photo");
|
||||||
|
|
||||||
b.Navigation("User");
|
b.Navigation("User");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1348,6 +1360,11 @@ namespace ProjectLighthouse.Migrations
|
||||||
|
|
||||||
b.Navigation("User");
|
b.Navigation("User");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Profile.Photo", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("PhotoSubjects");
|
||||||
|
});
|
||||||
#pragma warning restore 612, 618
|
#pragma warning restore 612, 618
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#nullable enable
|
#nullable enable
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
@ -9,7 +8,6 @@ using LBPUnion.ProjectLighthouse.Database;
|
||||||
using LBPUnion.ProjectLighthouse.Serialization;
|
using LBPUnion.ProjectLighthouse.Serialization;
|
||||||
using LBPUnion.ProjectLighthouse.Types.Entities.Level;
|
using LBPUnion.ProjectLighthouse.Types.Entities.Level;
|
||||||
using LBPUnion.ProjectLighthouse.Types.Levels;
|
using LBPUnion.ProjectLighthouse.Types.Levels;
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Types.Entities.Profile;
|
namespace LBPUnion.ProjectLighthouse.Types.Entities.Profile;
|
||||||
|
|
||||||
|
@ -65,31 +63,7 @@ public class Photo
|
||||||
[XmlElement("plan")]
|
[XmlElement("plan")]
|
||||||
public string PlanHash { get; set; } = "";
|
public string PlanHash { get; set; } = "";
|
||||||
|
|
||||||
[NotMapped]
|
public virtual ICollection<PhotoSubject> PhotoSubjects { get; set; } = new HashSet<PhotoSubject>();
|
||||||
public List<PhotoSubject> Subjects {
|
|
||||||
get {
|
|
||||||
if (this.SubjectsXmlDontUseLiterallyEver != null) return this.SubjectsXmlDontUseLiterallyEver;
|
|
||||||
if (this._subjects != null) return this._subjects;
|
|
||||||
|
|
||||||
List<PhotoSubject> response = new();
|
|
||||||
using DatabaseContext database = new();
|
|
||||||
|
|
||||||
foreach (string idStr in this.PhotoSubjectIds.Where(idStr => !string.IsNullOrEmpty(idStr)))
|
|
||||||
{
|
|
||||||
if (!int.TryParse(idStr, out int id)) throw new InvalidCastException(idStr + " is not a valid number.");
|
|
||||||
|
|
||||||
PhotoSubject? photoSubject = database.PhotoSubjects
|
|
||||||
.Include(p => p.User)
|
|
||||||
.FirstOrDefault(p => p.PhotoSubjectId == id);
|
|
||||||
if (photoSubject == null) continue;
|
|
||||||
|
|
||||||
response.Add(photoSubject);
|
|
||||||
}
|
|
||||||
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
set => this._subjects = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
[XmlIgnore]
|
[XmlIgnore]
|
||||||
|
@ -134,7 +108,7 @@ public class Photo
|
||||||
string slot = LbpSerializer.TaggedStringElement("slot", LbpSerializer.StringElement("id", slotId), "type", slotType.ToString().ToLower());
|
string slot = LbpSerializer.TaggedStringElement("slot", LbpSerializer.StringElement("id", slotId), "type", slotType.ToString().ToLower());
|
||||||
if (slotId == 0) slot = "";
|
if (slotId == 0) slot = "";
|
||||||
|
|
||||||
string subjectsAggregate = this.Subjects.Aggregate(string.Empty, (s, subject) => s + subject.Serialize());
|
string subjectsAggregate = this.PhotoSubjects.Aggregate(string.Empty, (s, subject) => s + subject.Serialize());
|
||||||
|
|
||||||
string photo = LbpSerializer.StringElement("id", this.PhotoId) +
|
string photo = LbpSerializer.StringElement("id", this.PhotoId) +
|
||||||
LbpSerializer.StringElement("small", this.SmallHash) +
|
LbpSerializer.StringElement("small", this.SmallHash) +
|
||||||
|
|
|
@ -20,10 +20,17 @@ public class PhotoSubject
|
||||||
public int UserId { get; set; }
|
public int UserId { get; set; }
|
||||||
|
|
||||||
[XmlIgnore]
|
[XmlIgnore]
|
||||||
[ForeignKey(nameof(UserId))]
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
|
[ForeignKey(nameof(UserId))]
|
||||||
public User User { get; set; }
|
public User User { get; set; }
|
||||||
|
|
||||||
|
public int PhotoId { get; set; }
|
||||||
|
|
||||||
|
[XmlIgnore]
|
||||||
|
[JsonIgnore]
|
||||||
|
[ForeignKey(nameof(PhotoId))]
|
||||||
|
public Photo Photo { get; set; }
|
||||||
|
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
[XmlElement("npHandle")]
|
[XmlElement("npHandle")]
|
||||||
public string Username { get; set; }
|
public string Username { get; set; }
|
||||||
|
|
|
@ -7,9 +7,11 @@ using System.Text.Json.Serialization;
|
||||||
using System.Xml.Serialization;
|
using System.Xml.Serialization;
|
||||||
using LBPUnion.ProjectLighthouse.Configuration;
|
using LBPUnion.ProjectLighthouse.Configuration;
|
||||||
using LBPUnion.ProjectLighthouse.Database;
|
using LBPUnion.ProjectLighthouse.Database;
|
||||||
|
using LBPUnion.ProjectLighthouse.Helpers;
|
||||||
using LBPUnion.ProjectLighthouse.Serialization;
|
using LBPUnion.ProjectLighthouse.Serialization;
|
||||||
using LBPUnion.ProjectLighthouse.Types.Misc;
|
using LBPUnion.ProjectLighthouse.Types.Misc;
|
||||||
using LBPUnion.ProjectLighthouse.Types.Users;
|
using LBPUnion.ProjectLighthouse.Types.Users;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace LBPUnion.ProjectLighthouse.Types.Entities.Profile;
|
namespace LBPUnion.ProjectLighthouse.Types.Entities.Profile;
|
||||||
|
|
||||||
|
@ -224,6 +226,37 @@ public class User
|
||||||
|
|
||||||
public string Serialize(GameVersion gameVersion = GameVersion.LittleBigPlanet1)
|
public string Serialize(GameVersion gameVersion = GameVersion.LittleBigPlanet1)
|
||||||
{
|
{
|
||||||
|
long start = TimeHelper.TimestampMillis;
|
||||||
|
var stats = this.database.Users.AsNoTracking().DefaultIfEmpty().Select(_ => new
|
||||||
|
{
|
||||||
|
ReviewCount = this.database.Reviews.Count(r => r.ReviewerId == this.UserId),
|
||||||
|
CommentCount = this.database.Comments.Count(c => c.PosterUserId == this.UserId),
|
||||||
|
PhotoCount = this.database.Photos.Count(p => p.CreatorId == this.UserId),
|
||||||
|
PlaylistCount = this.database.Playlists.Count(p => p.CreatorId == this.UserId),
|
||||||
|
HeartedLevelCount = this.database.HeartedLevels.Count(p => p.UserId == this.UserId),
|
||||||
|
HeartedUserCount = this.database.HeartedProfiles.Count(p => p.UserId == this.UserId),
|
||||||
|
HeartedPlaylistCount = this.database.HeartedPlaylists.Count(p => p.UserId == this.UserId),
|
||||||
|
QueuedLevelCount = this.database.QueuedLevels.Count(p => p.UserId == this.UserId),
|
||||||
|
})
|
||||||
|
.FirstOrDefault();
|
||||||
|
Console.WriteLine(@$"Fetching stats in single query took {TimeHelper.TimestampMillis - start}");
|
||||||
|
start = TimeHelper.TimestampMillis;
|
||||||
|
var stats2 = new
|
||||||
|
{
|
||||||
|
ReviewCount = this.Reviews,
|
||||||
|
CommentCount = this.Comments,
|
||||||
|
PhotoCount = this.PhotosByMe,
|
||||||
|
PlaylistCount = this.Lists,
|
||||||
|
HeartedLevelCount = this.HeartedLevels,
|
||||||
|
HeartedUserCount = this.HeartedUsers,
|
||||||
|
HeartedPlaylistCount = this.HeartedPlaylists,
|
||||||
|
QueuedLevelCount = this.QueuedLevels,
|
||||||
|
};
|
||||||
|
Console.WriteLine(@$"Fetching stats in multiple queries took {TimeHelper.TimestampMillis - start}");
|
||||||
|
|
||||||
|
start = TimeHelper.TimestampMillis;
|
||||||
|
int photosWithMe = this.PhotosWithMe();
|
||||||
|
Console.WriteLine(@$"Fetching photos with me took {TimeHelper.TimestampMillis - start}");
|
||||||
string user = LbpSerializer.TaggedStringElement("npHandle", this.Username, "icon", this.IconHash) +
|
string user = LbpSerializer.TaggedStringElement("npHandle", this.Username, "icon", this.IconHash) +
|
||||||
LbpSerializer.StringElement("game", (int)gameVersion) +
|
LbpSerializer.StringElement("game", (int)gameVersion) +
|
||||||
this.serializeSlots(gameVersion) +
|
this.serializeSlots(gameVersion) +
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue