private async Task <ActionResult> UpdateFractionStatistics() { if (!await CheckIp()) { return(Json(new NoPermissionFailure())); } try { var strategy = _db.Database.CreateExecutionStrategy(); await strategy.ExecuteAsync(async() => { using var transaction = await _db.Database.BeginTransactionAsync(); await UpdateFractionStatistics_Internal(); await _db.SaveChangesAsync(); lock (_dbLock) { transaction.Commit(); } }); LoggingUtil.Log("Fraction statistics have been updated."); return(Json(new { success = true })); } catch (Exception e) { LoggingUtil.Error("Failed to compute fraction statistics"); LoggingUtil.Error(e.StackTrace); return(Json(new { success = false })); } }
public async Task <string> LogToFile <T>(string folder, IDictionary <string, T> toLog) { var now = DateTime.UtcNow; var dir = Path.Combine(_logFolder, folder); if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } var fileName = $"{now:yyyy_MM_dd__HH_mm_ss_ff}.log"; var filePath = Path.Combine(dir, fileName); if (File.Exists(filePath)) { LoggingUtil.Error($"Log {filePath} already exists!"); return(null); } var fileContent = new StringBuilder(); foreach (var(key, value) in toLog) { fileContent.Append($"{key}:{value}\n\n"); } await File.WriteAllTextAsync(filePath, fileContent.ToString()); return(filePath); }
private async Task <ActionResult> UpdateAbilityData(string data) { if (string.IsNullOrWhiteSpace(data)) { return(Json(new MissingArgumentFailure())); } if (!data.TryToJson(out JsonDocument parsedAbilityData)) { return(Json(new InvalidRequestFailure())); } var abilityData = parsedAbilityData.RootElement; try { var strategy = _db.Database.CreateExecutionStrategy(); await strategy.ExecuteAsync(async() => { using var transaction = await _db.Database.BeginTransactionAsync(); var properties = abilityData.EnumerateObject().Where(p => !string.IsNullOrWhiteSpace(p.Name)); var abilities = await _db.GetOrCreateAsync(properties.Select(p => p.Name), a => a.Name, CreateAbility); foreach (var(values, ability) in properties.Select(p => p.Value).Zip(abilities)) { ability.UpdateValues(values); } await _db.SaveChangesAsync(); lock (_dbLock) { transaction.Commit(); } }); return(Json(new { Success = true })); } catch (Exception e) { LoggingUtil.Error("Updating ability data failed"); LoggingUtil.Error(e.ToString()); await _fileLogger.LogToFile("update_ability_data", new Dictionary <string, object> { { "exception", e.ToString() }, { "errorSource", e.Source }, { "targetSite", e.TargetSite } }); return(Json(new { Success = false })); } }
private async Task <ActionResult> UpdateRankings() { if (!await CheckIp()) { return(Json(new NoPermissionFailure())); } try { await UpdateRanking(RankingTypes.Rating, false); } catch (Exception e) { LoggingUtil.Error("Failed to update ranking"); LoggingUtil.Error(e.StackTrace); return(Json(new { success = false })); } return(Json(new { success = true })); }
private async Task <ActionResult> UpdateUnitData(string dataString, string type = "unit") { if (string.IsNullOrWhiteSpace(dataString)) { return(Json(new MissingArgumentFailure())); } if (!dataString.TryToJson(out JsonDocument parsedUnitData)) { return(Json(new InvalidRequestFailure())); } var unitData = parsedUnitData.RootElement; try { var strategy = _db.Database.CreateExecutionStrategy(); await strategy.ExecuteAsync(async() => { using var transaction = await _db.Database.BeginTransactionAsync(); var properties = unitData.EnumerateObject().Where(p => !string.IsNullOrWhiteSpace(p.Name)); var unitNames = properties.Select(p => p.Name); var units = await _db.GetOrCreateAsync(unitNames, u => u.Name, name => CreateUnitOrBuilder(name, type)); foreach (var(data, unit) in properties.Select(p => p.Value).Zip(units)) { unit.UpdateValues(data); } await _db.SaveChangesAsync(); // Remove all old links between abilities and units var sqlUnitNames = string.Join(", ", unitNames.Select(u => $"'{u}'")); var usedAbilities = new List <string>(); await _db.Database.ExecuteSqlRawAsync($"DELETE FROM UnitAbilities WHERE UnitName IN ({sqlUnitNames})"); foreach (var unitObject in unitData.EnumerateObject()) { for (int i = 1; i <= 24; i++) { string abilityName = unitObject.Value.GetValueOrDefault($"Ability{i}"); if (!string.IsNullOrWhiteSpace(abilityName)) { var newAbility = new UnitAbility { UnitName = unitObject.Name, AbilityName = abilityName, Slot = i }; _db.UnitAbilities.Add(newAbility); usedAbilities.Add(abilityName); } } } if (usedAbilities.Count > 0) { await _db.GetOrCreateAsync(usedAbilities, a => a.Name, CreateAbility); } await _db.SaveChangesAsync(); lock (_dbLock) { transaction.Commit(); } }); return(Json(new { Success = true })); } catch (Exception e) { LoggingUtil.Error($"Updating {type} data failed"); await _fileLogger.LogToFile($"update_{type}_data", new Dictionary <string, object> { { "exception", e.ToString() }, { "errorSource", e.Source }, { "targetSite", e.TargetSite } }); return(Json(new { Success = false })); } }
private async Task UpdateRanking(RankingTypes type, bool asc) { string key = type + "|" + asc; _cache.Set(key, true, DateTime.UtcNow.AddDays(1)); var oldTimeout = _db.Database.GetCommandTimeout(); _db.Database.SetCommandTimeout(TimeSpan.FromHours(1)); try { var strategy = _db.Database.CreateExecutionStrategy(); await strategy.ExecuteAsync(async() => { using var transcation = await _db.Database.BeginTransactionAsync(); await _db.Database.ExecuteSqlRawAsync($"DELETE FROM Rankings WHERE Type = {(int)type} AND Ascending = {(asc ? 1 : 0)}"); LoggingUtil.Log($"Cleared Ranking for {type} {asc}"); string sql; string sqlJoins = "JOIN Matches AS m \n" + "ON m.MatchId = pm.MatchId \n"; string sqlWheres = "WHERE m.IsTraining = FALSE \n"; string sqlSelects, sqlOrderBy; switch (type) { case RankingTypes.EarnedTangos: sqlSelects = ", SUM(EarnedTangos) AS Gold \n"; sqlOrderBy = "ORDER BY Gold " + (asc ? "ASC" : "DESC") + " \n"; break; case RankingTypes.EarnedGold: sqlSelects = ", SUM(EarnedGold) AS Gold \n"; sqlOrderBy = "ORDER BY Gold " + (asc ? "ASC" : "DESC") + " \n"; break; case RankingTypes.Rating: default: sqlSelects = ", SUM(RatingChange) AS Rating \n"; sqlOrderBy = "ORDER BY Rating " + (asc ? "ASC" : "DESC") + " \n"; sqlJoins = ""; sqlWheres = ""; break; } sql = "INSERT INTO Rankings \n" + "(Type, Ascending, PlayerId, Position) \n" + $"SELECT @t := {(int)type}, @a := {(asc ? "TRUE" : "FALSE")}, PlayerId, @rownum := @rownum + 1 AS position\n" + "FROM (SELECT PlayerId \n" + sqlSelects + "FROM PlayerMatchData AS pm \n" + sqlJoins + sqlWheres + "GROUP BY pm.PlayerId \n" + sqlOrderBy + ") AS pr, \n" + "(SELECT @rownum := 0) AS r \n"; await _db.Database.ExecuteSqlRawAsync(sql); lock (_dbLock) { transcation.Commit(); } }); LoggingUtil.Log("Ranking has been updated."); } catch (Exception e) { LoggingUtil.Error(e.ToString()); LoggingUtil.Error("Failed to update ranking"); } finally { _db.Database.SetCommandTimeout(oldTimeout); } }