public async Task <IActionResult> OnPostAsync() { var guildID = await CheckUserPrivilege(); if (!guildID.HasValue) { return(RedirectToPage("/Guild/Index")); } if (!ModelState.IsValid) { return(Page()); } var zhou = new Zhou { GuildID = guildID.Value, Name = Input.Name, Description = Input.Description, BossID = Input.BossID, }; var characters = Input.CharacterListString?.Split(',') ?? Array.Empty <string>() .Distinct().ToArray(); if (characters.Length != 5) { //Many of the algorithms assume every Zhou has 5 characters. return(RedirectToPage("./Index")); } (float range, int id)[] characterData = new (float, int)[5];
public async Task <IActionResult> OnPostAsync() { var guildID = await CheckUserPrivilege(); if (!guildID.HasValue) { return(RedirectToPage("/Guild/Index")); } var imGuild = await _context.GetGuildAsync(guildID.Value); if (string.IsNullOrEmpty(Input)) { StatusMessage2 = "错误:输入为空。"; return(Page()); } var parser = _parserFactory.GetParser(_context.DbContext, guildID.Value); await parser.ReadDatabase(); var list = new List <Zhou>(); var newConfigList = new List <CharacterConfig>(); int lineNum = 0; var errorMsg = new StringBuilder(); errorMsg.AppendLine("错误:读取轴表失败。"); var errorCount = 0; const int MaxErrorMsg = 5; var allLines = DuplicateCheckBehavior == ZhouParserDuplicateCheckBehavior.Return ? new List <string>() : null; using var reader = new StringReader(Input); string line; while ((line = reader.ReadLine()) is not null) { allLines?.Add(line); lineNum += 1; try { var z = parser.Parse(line, HasName, CreateConfigs, newConfigList); if (z is not null) { list.Add(z); } } catch (Exception e) { if (++errorCount <= MaxErrorMsg) { errorMsg.AppendLine($" 第{lineNum}行:{e.Message}。"); } list.Add(null); } } if (errorCount != 0) { if (errorCount > MaxErrorMsg) { errorMsg.AppendLine($" 以及{errorCount - MaxErrorMsg}个其他错误。"); } errorMsg.AppendLine("轴表没有被修改。"); StatusMessage2 = errorMsg.ToString(); return(Page()); } errorMsg.Clear(); errorMsg.AppendLine("检测到重复的轴:"); var unsavedMergeCheck = new List <Zhou>(); var unsavedDupCheck = new List <ZhouVariant>(); var returnInputContent = new StringBuilder(); var updatedZV = new HashSet <ZhouVariant>(); //Each zv can only be updated once. Use this to check. var dupUpdateCount = 0; var allUserConfigs = await _context.DbContext.UserCharacterConfigs .Include(ucc => ucc.CharacterConfig) .Where(ucc => ucc.CharacterConfig.GuildID == guildID) .ToListAsync(); var pendingIMAdd = new List <(Zhou, ZhouVariant)>(); foreach (var cc in newConfigList) { await Guilds.ConfigsModel.CheckAndAddRankConfigAsync(_context.DbContext, cc, allUserConfigs); } for (int i = 0; i < list.Count; ++i) { var z = list[i]; if (z is null) { continue; //i is to keep the line number. If parsing fails it will be null. } var v = ((List <ZhouVariant>)z.Variants)[0]; Zhou existingSameZhou = null; if (Merge || DuplicateCheckBehavior != ZhouParserDuplicateCheckBehavior.Ignore) { existingSameZhou = await _context.DbContext.Zhous .FirstOrDefaultAsync(zz => zz.GuildID == guildID.Value && zz.BossID == z.BossID && zz.C1ID == z.C1ID && zz.C2ID == z.C2ID && zz.C3ID == z.C3ID && zz.C4ID == z.C4ID && zz.C5ID == z.C5ID); //Assuming same order (by range). if (existingSameZhou is null) { existingSameZhou = unsavedMergeCheck.FirstOrDefault(zz => zz.BossID == z.BossID && zz.C1ID == z.C1ID && zz.C2ID == z.C2ID && zz.C3ID == z.C3ID && zz.C4ID == z.C4ID && zz.C5ID == z.C5ID); } } //Dup check. if (DuplicateCheckBehavior != ZhouParserDuplicateCheckBehavior.Ignore && existingSameZhou is not null) { if (!HasName || existingSameZhou.Name == z.Name) { //Name check passed. //Check configs. if (existingSameZhou.ZhouID != 0) { await _context.DbContext.Entry(existingSameZhou).Collection(zz => zz.Variants).LoadAsync(); } bool dupCheckResult = true; foreach (var existingV in existingSameZhou.Variants) { if (existingV.ZhouVariantID != 0) { await _context.DbContext.Entry(existingV).Collection(vv => vv.CharacterConfigs).LoadAsync(); } if (existingV.CharacterConfigs.Count != v.CharacterConfigs.Count) { continue; } bool checkFailed = false; foreach (var existingConfig in existingV.CharacterConfigs) { if (existingConfig.CharacterConfigID == 0) { //This is a new zv. Compare cc instance. if (!v.CharacterConfigs.Any(vcc => vcc.CharacterConfig == existingConfig.CharacterConfig)) { checkFailed = true; break; } } else { //This is a db zv. Compare cc id. if (!v.CharacterConfigs.Any(vcc => vcc.CharacterConfigID == existingConfig.CharacterConfigID)) { checkFailed = true; break; } } } if (!checkFailed) { switch (DuplicateCheckBehavior) { case ZhouParserDuplicateCheckBehavior.Error: dupCheckResult = false; errorCount += 1; errorMsg.AppendLine($" 第{i + 1}行:检测到重复的轴。"); break; case ZhouParserDuplicateCheckBehavior.Modify: if (existingV.ZhouVariantID == 0 || updatedZV.Contains(existingV)) { errorCount += 1; errorMsg.AppendLine($" 第{i + 1}行:输入中包含重复的轴,无法更新。"); } else { existingV.CharacterConfigs.Clear(); foreach (var ncc in v.CharacterConfigs) { existingV.CharacterConfigs.Add(ncc); } existingV.Content = v.Content; existingV.Damage = v.Damage; existingV.IsDraft = AsDraft; existingV.Name = v.Name; //This should be null. updatedZV.Add(existingV); } dupCheckResult = false; break; case ZhouParserDuplicateCheckBehavior.Return: returnInputContent.AppendLine(allLines[i]); dupCheckResult = false; break; } break; } } if (!dupCheckResult) { //Process next. continue; } } } //Merge check. Zhou mergedInto = null; if (Merge) { mergedInto = existingSameZhou; if (HasName && mergedInto is not null && mergedInto.Name != z.Name) { //Only merge when name is the same. mergedInto = null; } } //Add the new item. v.IsDraft = AsDraft; if (mergedInto is not null) { v.ZhouID = mergedInto.ZhouID; v.Zhou = mergedInto; _context.DbContext.ZhouVariants.Add(v); pendingIMAdd.Add((mergedInto, v)); } else { _context.DbContext.Zhous.Add(z); pendingIMAdd.Add((z, v)); unsavedMergeCheck.Add(z); } } if (errorCount != 0) { //Error or modify. //Modify can also generate error (cannot modify a new zv). errorMsg.AppendLine("轴表没有被修改。"); StatusMessage2 = errorMsg.ToString(); return(Page()); } await _context.DbContext.SaveChangesAsync(); //Update IM context only after saving of DB context succeeded. foreach (var(z, v) in pendingIMAdd) { imGuild.AddZhouVariant(allUserConfigs, v, z, v.CharacterConfigs); } foreach (var v in updatedZV) { imGuild.UpdateZhouVariant(v); } if (DuplicateCheckBehavior == ZhouParserDuplicateCheckBehavior.Return) { StatusMessage2 = "轴表已被修改。重复的项目如下,这些项目未被添加。"; Input = returnInputContent.ToString(); return(Page()); } StatusMessage = "导入成功。"; if (dupUpdateCount > 0) { StatusMessage += $"{dupUpdateCount}个已存在的重复轴被更新。"; } return(RedirectToPage()); }