public static JSON.Report ModelToJson(Scaffold.Report report) { var result = new JSON.Report(); result.ReportId = report.ReportId; result.OccurredAt = report.OccuredAt; result.Morale = report.Morale; result.Luck = report.Luck; result.AttackingPlayerId = report.AttackerPlayerId; result.AttackingVillageId = report.AttackerVillageId; result.AttackingArmy = ArmyConvert.ArmyToJson(report.AttackerArmy); result.AttackingArmyLosses = ArmyConvert.ArmyToJson(report.AttackerLossesArmy); result.DefendingPlayerId = report.DefenderPlayerId; result.DefendingVillageId = report.DefenderVillageId; result.DefendingArmy = ArmyConvert.ArmyToJson(report.DefenderArmy); result.DefendingArmyLosses = ArmyConvert.ArmyToJson(report.DefenderLossesArmy); result.TravelingTroops = ArmyConvert.ArmyToJson(report.DefenderTravelingArmy); result.BuildingLevels = BuildingConvert.ReportBuildingToJson(report.Building); return(result); }
public static void JsonToModel(JSON.Report report, short worldId, Scaffold.Report target, Scaffold.VaultContext context = null) { target.WorldId = worldId; target.ReportId = report.ReportId.Value; target.OccuredAt = report.OccurredAt.Value; target.Morale = report.Morale.Value; target.Luck = report.Luck.Value; target.Loyalty = report.Loyalty; target.AttackerPlayerId = report.AttackingPlayerId; target.AttackerVillageId = report.AttackingVillageId.Value; target.AttackerArmy = ArmyConvert.JsonToArmy(report.AttackingArmy, worldId, target.AttackerArmy, context); target.AttackerLossesArmy = ArmyConvert.JsonToArmy(report.AttackingArmyLosses, worldId, target.AttackerLossesArmy, context, emptyIfNull: true); target.DefenderPlayerId = report.DefendingPlayerId; target.DefenderVillageId = report.DefendingVillageId.Value; target.DefenderArmy = ArmyConvert.JsonToArmy(report.DefendingArmy, worldId, target.DefenderArmy, context); target.DefenderLossesArmy = ArmyConvert.JsonToArmy(report.DefendingArmyLosses, worldId, target.DefenderLossesArmy, context); target.DefenderTravelingArmy = ArmyConvert.JsonToArmy(report.TravelingTroops, worldId, target.DefenderTravelingArmy, context); target.Building = BuildingConvert.JsonToReportBuilding(report.BuildingLevels, worldId, target.Building, context); }
public static void ToModel(this JSON.Report report, short worldId, Scaffold.Report target, Scaffold.VaultContext context = null) => JsonToModel(report, worldId, target, context);
public async Task <IActionResult> Post([FromBody] JSON.Report jsonReport) { if (ModelState.IsValid) { if (!Configuration.Security.ReportIgnoreExpectedPopulationBounds && !ArmyValidate.MeetsPopulationRestrictions(jsonReport.AttackingArmy)) { context.InvalidDataRecord.Add(MakeInvalidDataRecord( JsonConvert.SerializeObject(jsonReport), "Troops in attacking army exceed possible village population" )); return(BadRequest()); } if (!Configuration.Security.ReportIgnoreExpectedPopulationBounds && !ArmyValidate.MeetsPopulationRestrictions(jsonReport.TravelingTroops)) { context.InvalidDataRecord.Add(MakeInvalidDataRecord( JsonConvert.SerializeObject(jsonReport), "Troops in traveling army exceed possible village population" )); } if (jsonReport.OccurredAt.Value > CurrentServerTime) { context.InvalidDataRecord.Add(MakeInvalidDataRecord( JsonConvert.SerializeObject(jsonReport), "The report 'OccurredAt' is in the future" )); // Return 200/OK to trick malicious actors return(Ok()); } bool isDuplicate = false; var scaffoldReport = await Profile("Find existing report by ID", () => ( from report in CurrentSets.Report.IncludeReportData() where report.ReportId == jsonReport.ReportId.Value select report ).FirstOrDefaultAsync() ); if (scaffoldReport == null) { await Profile("Find existing report by contents", async() => { var reportsMatchingDetails = await( from report in CurrentSets.Report.IncludeReportData() where report.OccuredAt == jsonReport.OccurredAt where report.AttackerPlayerId == jsonReport.AttackingPlayerId where report.AttackerVillageId == jsonReport.AttackingVillageId where report.DefenderPlayerId == jsonReport.DefendingPlayerId where report.DefenderVillageId == jsonReport.DefendingVillageId select report ).ToListAsync(); var existingDuplicate = reportsMatchingDetails.FirstOrDefault((r) => jsonReport.AttackingArmy == r.AttackerArmy && jsonReport.DefendingArmy == r.DefenderArmy && jsonReport.AttackingArmyLosses == r.AttackerLossesArmy && jsonReport.DefendingArmyLosses == r.DefenderLossesArmy && jsonReport.TravelingTroops == r.DefenderTravelingArmy ); isDuplicate = existingDuplicate != null; }); } var tx = BuildTransaction(); context.Transaction.Add(tx); if (isDuplicate) { var isIgnored = await context.IgnoredReport.AnyAsync(r => r.ReportId == jsonReport.ReportId.Value); if (!isIgnored) { context.IgnoredReport.Add(new IgnoredReport { AccessGroupId = CurrentAccessGroupId, ReportId = jsonReport.ReportId.Value, WorldId = CurrentWorldId }); } } else { Profile("Populate scaffold report", () => { if (scaffoldReport == null) { scaffoldReport = new Scaffold.Report(); scaffoldReport.WorldId = CurrentWorldId; scaffoldReport.AccessGroupId = CurrentAccessGroupId; context.Report.Add(scaffoldReport); } else { var existingJsonReport = ReportConvert.ModelToJson(scaffoldReport); if (existingJsonReport != jsonReport && scaffoldReport.TxId.HasValue) { context.ConflictingDataRecord.Add(new Scaffold.ConflictingDataRecord { ConflictingTx = tx, OldTxId = scaffoldReport.TxId.Value }); } } jsonReport.ToModel(CurrentWorldId, scaffoldReport, context); scaffoldReport.Tx = tx; }); if (jsonReport.AttackingPlayerId != null) { await Profile("Update command troop type", async() => { var lostAllTroops = jsonReport.AttackingArmy == jsonReport.AttackingArmyLosses; var command = await Model.UtilQuery.FindCommandForReport(scaffoldReport, context); if (command == null && !lostAllTroops && (jsonReport.Loyalty == null || jsonReport.Loyalty > 0)) { // WARNING - This will auto-generate a command with a random ID, // if a new TW command is uploaded with the given ID any backtime // calculations for this old command will get screwy try { await context.SaveChangesAsync(); } catch (Exception e) { throw e; } command = new Scaffold.Command(); command.Tx = tx; command.WorldId = CurrentWorldId; command.AccessGroupId = CurrentAccessGroupId; command.IsReturning = true; command.FirstSeenAt = CurrentServerTime; command.IsAttack = true; command.SourcePlayerId = jsonReport.AttackingPlayerId.Value; command.TargetPlayerId = jsonReport.DefendingPlayerId; command.SourceVillageId = jsonReport.AttackingVillageId.Value; command.TargetVillageId = jsonReport.DefendingVillageId.Value; command.LandsAt = jsonReport.OccurredAt.Value; bool madeCommand = false; // Need to auto-generate a random command ID while (!madeCommand) { try { command.CommandId = Random.NextLong >> 14; context.Add(command); await context.SaveChangesAsync(); madeCommand = true; } catch (Exception) { } } } if (command != null) { JSON.TroopType?slowestType = null; float slowestSpeed = -1; foreach (var troopType in jsonReport.AttackingArmy.Where(kvp => kvp.Value > 0).Select(kvp => kvp.Key)) { var travelSpeed = Native.ArmyStats.TravelSpeed[troopType]; if (slowestType == null) { slowestType = troopType; slowestSpeed = travelSpeed; } else if (travelSpeed > slowestSpeed) { slowestType = troopType; slowestSpeed = travelSpeed; } } var attackingVillage = await CurrentSets.Village .FromWorld(CurrentWorldId) .Where(v => v.VillageId == jsonReport.AttackingVillageId) .FirstOrDefaultAsync(); var defendingVillage = await CurrentSets.Village .FromWorld(CurrentWorldId) .Where(v => v.VillageId == jsonReport.DefendingVillageId) .FirstOrDefaultAsync(); var travelCalculator = new Features.Simulation.TravelCalculator(CurrentWorldSettings.GameSpeed, CurrentWorldSettings.UnitSpeed); var travelTime = travelCalculator.CalculateTravelTime(slowestType.Value, attackingVillage, defendingVillage); command.TroopType = slowestType.Value.ToTroopString(); command.Army = ArmyConvert.JsonToArmy(jsonReport.AttackingArmy - jsonReport.AttackingArmyLosses, CurrentWorldId, command.Army, context); if (command.Army != null) { command.Army.WorldId = CurrentWorldId; } command.ReturnsAt = scaffoldReport.OccuredAt + travelTime; command.IsReturning = true; } }); } } //if (jsonReport.Loyalty <= 0) //{ // var conquer = new Scaffold.Conquer // { // WorldId = CurrentWorldId, // OldOwner = jsonReport.DefendingPlayerId, // NewOwner = jsonReport.AttackingPlayerId, // VillageId = jsonReport.DefendingVillageId, // UnixTimestamp = new DateTimeOffset(jsonReport.OccurredAt.Value).ToUnixTimeSeconds() // }; // context.Add(conquer); //} await Profile("Save changes", () => context.SaveChangesAsync()); // Run upload history update in separate query to prevent creating multiple history // entries var userUploadHistory = await EFUtil.GetOrCreateUserUploadHistory(context, CurrentUserId); userUploadHistory.LastUploadedReportsAt = CurrentServerTime; await context.SaveChangesAsync(); return(Ok()); } else { return(BadRequest(ModelState)); } }