import_viewer: round-trip ViewerStoryProgress with per-family offsets
This commit is contained in:
@@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using SVSim.Database;
|
||||
using SVSim.Database.Entities.Story;
|
||||
using SVSim.Database.Enums;
|
||||
using SVSim.Database.Models;
|
||||
using SVSim.Database.Repositories.Viewer;
|
||||
@@ -417,6 +418,52 @@ public class AdminController : SVSimController
|
||||
}
|
||||
}
|
||||
|
||||
// Pass D: StoryProgress with per-family offsets
|
||||
var skippedStoryIds = new HashSet<long>();
|
||||
if (request.StoryProgress is { } storyRows)
|
||||
{
|
||||
var existingStory = await _dbContext.ViewerStoryProgress
|
||||
.Where(p => p.ViewerId == viewer.Id).ToListAsync();
|
||||
_dbContext.ViewerStoryProgress.RemoveRange(existingStory);
|
||||
|
||||
// Compute effective ids and bulk-load referenced catalog rows.
|
||||
var effectiveIds = new List<int>(storyRows.Count);
|
||||
var rowEffective = new List<(ImportStoryProgress row, int effective)>(storyRows.Count);
|
||||
foreach (var r in storyRows)
|
||||
{
|
||||
long offset = r.StoryApiType switch
|
||||
{
|
||||
1 => 0L,
|
||||
2 => 10_000_000L,
|
||||
3 => 20_000_000L,
|
||||
_ => -1L
|
||||
};
|
||||
if (offset < 0) { skippedStoryIds.Add(r.StoryId); continue; }
|
||||
int wireId = r.SubChapterId ?? r.StoryId;
|
||||
int effective = checked((int)(wireId + offset));
|
||||
effectiveIds.Add(effective);
|
||||
rowEffective.Add((r, effective));
|
||||
}
|
||||
var present = (await _dbContext.StoryWorlds
|
||||
.Where(s => effectiveIds.Contains(s.Id))
|
||||
.Select(s => s.Id).ToListAsync()).ToHashSet();
|
||||
|
||||
var nowUtc = DateTime.UtcNow;
|
||||
foreach (var (r, eff) in rowEffective)
|
||||
{
|
||||
if (!present.Contains(eff)) { skippedStoryIds.Add(eff); continue; }
|
||||
_dbContext.ViewerStoryProgress.Add(new ViewerStoryProgress
|
||||
{
|
||||
ViewerId = viewer.Id,
|
||||
StoryId = eff,
|
||||
IsFinish = r.IsFinish,
|
||||
IsSkipped = r.IsSkipped,
|
||||
FinishedAt = r.IsFinish ? nowUtc : null,
|
||||
SkippedAt = r.IsSkipped ? nowUtc : null
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
await _dbContext.SaveChangesAsync();
|
||||
|
||||
if (skippedCardIds.Count > 0)
|
||||
@@ -455,6 +502,13 @@ public class AdminController : SVSimController
|
||||
request.SteamId, viewer.Id, skippedAchievementCounterTypes.Count,
|
||||
string.Join(", ", skippedAchievementCounterTypes.Take(10)));
|
||||
}
|
||||
if (skippedStoryIds.Count > 0)
|
||||
{
|
||||
_logger.LogWarning(
|
||||
"ImportViewer (steam_id={SteamId}, viewer_id={ViewerId}): skipped {Count} unknown story_id(s). Sample: [{Sample}]",
|
||||
request.SteamId, viewer.Id, skippedStoryIds.Count,
|
||||
string.Join(", ", skippedStoryIds.Take(10)));
|
||||
}
|
||||
|
||||
return new ImportViewerResponse
|
||||
{
|
||||
@@ -466,6 +520,7 @@ public class AdminController : SVSimController
|
||||
SkippedMissionCounterCount = skippedMissionCounterIds.Count,
|
||||
SkippedAchievementCount = skippedAchievementTypes.Count,
|
||||
SkippedAchievementCounterCount = skippedAchievementCounterTypes.Count,
|
||||
SkippedStoryCount = skippedStoryIds.Count,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,9 @@ public class ImportViewerRequest
|
||||
|
||||
[JsonPropertyName("achievements")]
|
||||
public List<ImportAchievement>? Achievements { get; set; }
|
||||
|
||||
[JsonPropertyName("story_progress")]
|
||||
public List<ImportStoryProgress>? StoryProgress { get; set; }
|
||||
}
|
||||
|
||||
public class ImportDeck
|
||||
@@ -110,6 +113,15 @@ public class ImportAchievement
|
||||
[JsonPropertyName("total_count")] public int TotalCount { get; set; }
|
||||
}
|
||||
|
||||
public class ImportStoryProgress
|
||||
{
|
||||
[JsonPropertyName("story_api_type")] public int StoryApiType { get; set; }
|
||||
[JsonPropertyName("story_id")] public int StoryId { get; set; }
|
||||
[JsonPropertyName("sub_chapter_id")] public int? SubChapterId { get; set; }
|
||||
[JsonPropertyName("is_finish")] public bool IsFinish { get; set; }
|
||||
[JsonPropertyName("is_skipped")] public bool IsSkipped { get; set; }
|
||||
}
|
||||
|
||||
public class ImportMissionMeta
|
||||
{
|
||||
[JsonPropertyName("has_received_pick_two_mission")]
|
||||
|
||||
Reference in New Issue
Block a user