private void _endVoting(IDbConnection connection, IHubContext <MainGameHub> hubContext = null, bool notifyClients = true) { if (VotingInProgress) { throw new Exception(Error.TimeVotingIsNotOver); } if (_voteSate == VoteStates.EndedFinished) { throw new Exception(Error.VotingRunnerVoteIsFinishedBefore); } if (_voteSate == VoteStates.EndInProgress) { throw new Exception(Error.VotingRunnerEndInProgress); } try { _voteSate = VoteStates.EndInProgress; _activeCandidates = null; List <IUserOfficerOut> officers = _endVotingDb(connection); if (officers == null || !officers.Any()) { _voteSate = VoteStates.EndedFinished; return; } _rebuildWeekOfficers(officers); if (notifyClients) { _notifyClientsOnVotingEnded(connection, hubContext); } _voteSate = VoteStates.EndedFinished; } catch (Exception e) { if (e.Message == VoteStates.EndedFinished.ToString()) { if (notifyClients) { _notifyClientsOnVotingEnded(connection, hubContext); } _voteSate = VoteStates.EndedFinished; } else { _voteSate = VoteStates.EndedErrorInFinished; throw; } } }
private void _startVoting(IDbConnection connection, IHubContext <MainGameHub> hubContext = null, bool notifyClients = true) { if (!VotingInProgress) { throw new Exception(Error.IsNotVotePeriod); } if (_voteSate == VoteStates.StartedRunned) { throw new Exception(Error.VotingRunnerVoteIsFinishedBefore); } if (_voteSate == VoteStates.StartInProgress) { throw new Exception(Error.VotingRunnerStartInProgress); } List <CandidatOut> finalzers = null; try { _voteSate = VoteStates.StartInProgress; finalzers = _startVotingDb(connection); _activeCandidates = new ActiveCandidates(finalzers); //_notyfyOnVoteEndedComplete if (notifyClients) { _notifyClientsOnVoteStarted(hubContext); } _voteSate = VoteStates.StartedRunned; } catch (Exception e) { if (e.Message == VoteStates.StartedRunned.ToString()) { finalzers = _officerCandidatRepository.GetRegistredOfficerCandidatesByTopPvp(connection, MAX_CANDIDATES_COUNT); _activeCandidates = new ActiveCandidates(finalzers); if (notifyClients) { _notifyClientsOnVoteStarted(hubContext); } _voteSate = VoteStates.StartedRunned; } else { _voteSate = VoteStates.StartedErrorInRun; throw; } } }
public void OnAppStop() { _voteSate = VoteStates.Undefined; if (_weekOfficersStorage != null) { _weekOfficersStorage.Clear(); _weekOfficersStorage = null; } // ReSharper disable once RedundantCheckBeforeAssignment if (_activeCandidates == null) { return; } _activeCandidates.Dispose(); _activeCandidates = null; }
private List <IUserOfficerOut> _endVotingDb(IDbConnection connection) { var existOfficer = _getFirstOfficer(connection); var startRegister = StartRegistrationTime; var endTime = EndVoteTime; if (existOfficer?.dateEnd == endTime) { throw new NotImplementedException(VoteStates.EndedFinished.ToString()); } var winners = _get_c_vote_get_top_finalized_officers(connection, 4).Select(i => new WinnerCandidat(i)) .ToList(); if (winners.Count < 4) { var existIds = winners.Select(i => i.UserId).ToList(); var selectCount = 4 - existIds.Count; var topCandidates = _officerCandidatRepository.GetRegistredOfficerCandidatesByTopPvp(connection, 0); if (!topCandidates.Any()) { _voteSate = VoteStates.EndedFinished; return(null); } if (topCandidates.Count < 4) { throw new NotImplementedException("topCandidates.Count < 4"); } var selectedCandidates = topCandidates.Where(i => !existIds.Contains(i.UserId)) .OrderByDescending(i => i.Voices) .ThenBy(i => i.Id) .Take(selectCount) .Select(i => new WinnerCandidat(i)) .ToList(); var newUserIds = selectedCandidates.Select(i => i.UserId).ToList(); var sqlUserIds = newUserIds.Aggregate("", (current, i) => current + (i + ",")); sqlUserIds = sqlUserIds.Substring(0, sqlUserIds.Length - 1); var userTableName = _provider.GetTableName(nameof(user)); var allianceUserTableName = _provider.GetTableName(nameof(alliance_user)); var allianceTableName = _provider.GetTableName(nameof(alliance)); //Voices = i.count ?? 0; //UserAvatar = i.userAvatar; //UserId = i.userId; //UserName = i.userName; //UserPvpPoint = (int)i.userPvpPoint; //AllianceId = (int)i.allianceId; //AllianceLabel = i.allianceLabel; //AllianceName = i.allianceName; var sqlAdvancdData = @"SELECT " + @"u.avatarUrls as userAvatar, " + @"u.Id as userId, " + @"u.nickname as userName, " + @"u.pvpPoint as userPvpPoint, " + @"a.Id as allianceId, " + @"a.images as allianceLabel, " + @"a.name as allianceName " + $@"FROM {userTableName} AS u " + $@"LEFT JOIN {allianceUserTableName} AS au ON au.userId=u.Id " + $@"LEFT JOIN {allianceTableName} AS a ON a.Id=au.allianceId WHERE u.Id IN({sqlUserIds})"; var advancdData = _provider.Text <dynamic>(connection, sqlAdvancdData).Select(i => new WinnerCandidat(i)) .ToList(); foreach (var adv in advancdData) { var item = selectedCandidates.Single(i => i.UserId == adv.UserId); item.AllianceId = adv.AllianceId; item.AllianceName = adv.AllianceName; item.AllianceLabel = adv.AllianceLabel; item.UserAvatar = adv.UserAvatar; } winners.AddRange(selectedCandidates); } var execDbo = "EXEC [dbo]."; var finalizeSql = "BEGIN TRAN end_voting BEGIN TRY " + $"{execDbo}[c_vote_save_to_history]; " + $"{execDbo}[c_vote_delete_all]; " + $"{execDbo}[help_reset_index] '{nameof(c_vote)}',0; " + $"{execDbo}[c_officer_save_to_history]; " + $"{execDbo}[c_officer_delete_all]; " + $"{execDbo}[help_reset_index] '{nameof(c_officer)}',0; " + $"{execDbo}[c_vote_delete_all]; " + $"{execDbo}[c_officer_candidat_save_to_history] 1; " + $"{execDbo}[c_officer_candidat_delete_all]; " + $"{execDbo}[help_reset_index] '{nameof(c_officer_candidat)}',0; " + "COMMIT TRAN end_voting " + "SELECT 1; " + "END TRY " + "BEGIN CATCH " + "ROLLBACK TRANSACTION end_voting; " + "THROW; " + "END CATCH "; var result = _provider.Text <int>(connection, finalizeSql).FirstOrDefault(); if (result != 1) { _voteSate = VoteStates.EndedErrorInFinished; throw new NotImplementedException(Error.VotingRunnerEndedErrorInFinished); } if (_weekOfficersStorage != null) { _weekOfficersStorage.Clear(); _weekOfficersStorage = null; } return(_buildOfficers(connection, startRegister, winners)); }
private void _checkAndRunVoteState(IDbConnection connection, int countError = 0, bool notifyClients = true, Exception exception = null) { void Unlock() { _checkAndRunVoteStateLocked = false; } lock (_checkAndRunVoteStateLocker) { if (countError > MAX_LIMIT_TRY) { Unlock(); throw new Exception(Error.VotingRunnerTryErrorMoreMaxLimit, exception); } if (_checkAndRunVoteStateLocked) { Task.Delay(DELAY_BETWEEN_ERRORS).MakeSync(); countError++; _checkAndRunVoteState(connection, countError, notifyClients); } else { try { _checkAndRunVoteStateLocked = true; var voteInProgress = VotingInProgress; var startRegistrationTime = StartRegistrationTime; if (_voteSate == VoteStates.Undefined) { #region модуль не инициализированн app initialized need restore data if (countError != 0) { throw new NotImplementedException("_voteSate == VoteStates.Undefined"); } if (voteInProgress) { _undefinedStateInVotePeriod(connection, notifyClients, startRegistrationTime, countError); } else { _undefinedStateInRegistratedPeriod(connection, notifyClients, countError); } #endregion } else { #region Текущее время соответствует периоду голосования if (voteInProgress) { #region Все ок // ReSharper disable once ConvertIfStatementToSwitchStatement if (_voteSate == VoteStates.StartedRunned) { return; } #endregion #region внешняя ошибка в периоде голосования необходимо дополнительное вмешательство для фиксации if (_voteSate == VoteStates.StartedErrorInRun) { throw new Exception(Error.VotingRunnerStartedErrorInRun); } #endregion #region это данные предыдущего состояния, переключаем на голосование if (_voteSate == VoteStates.EndedFinished) { _startVoting(connection, null, notifyClients); } #endregion #region данные назначаются необходимо подождать результатов для определения else if (_voteSate == VoteStates.StartInProgress) { Unlock(); _checkAndRunVoteState(connection, countError, exception: exception); // _startVoting(connection, null, notifyClients); } #endregion #region неопределенное стосояние в периоде голосвания, не относится к обрабатываемым сценариям else { _voteSate = VoteStates.Undefined; throw new NotImplementedException( "неопределенное стосояние в периоде голосвания, не относится к обрабатываемым сценариям "); } #endregion } #endregion #region Текущее время соответствует периоду регистрации else { #region все ok // ReSharper disable once ConvertIfStatementToSwitchStatement // ReSharper disable once RedundantJumpStatement if (_voteSate == VoteStates.EndedFinished) { return; } #endregion #region период голосования не завершен, завершаем период if (_voteSate == VoteStates.StartedRunned) { _endVoting(connection, notifyClients: notifyClients); } #endregion #region внешняя ошибка в периоде регистрации необходимо дополнительное вмешательство для фиксации else if (_voteSate == VoteStates.EndedErrorInFinished) { throw new Exception(Error.VotingRunnerEndedErrorInFinished); } #endregion #region модуль не инициализированн app initialized need restore data #endregion #region данные назначаются необходимо подождать результатов для определения else if (_voteSate == VoteStates.EndInProgress) { try { Unlock(); _checkAndRunVoteState(connection, countError, notifyClients); } catch (Exception e) { if (_voteSate == VoteStates.StartInProgress) { Unlock(); _checkAndRunVoteState(connection, countError, notifyClients, e); } else { throw; } } } #endregion #region неопределенное стосояние в периоде регистрации, не относится к обрабатываемым сценариям else { _voteSate = VoteStates.Undefined; throw new NotImplementedException("неопределенное стосояние в периоде регистрации, не относится к обрабатываемым сценариям"); } #endregion } #endregion } } catch (Exception e) { Console.WriteLine(e); throw; } finally { Unlock(); } } } }
private void _undefinedStateInRegistratedPeriod(IDbConnection connection, bool notifyClients, int countError) { _voteSate = VoteStates.EndInProgress; try { var firstOfficer = _getFirstOfficer(connection); // данных нет, база пуста это 1 й запуск, создаем любых офицеров в обход голосования if (firstOfficer == null) { var userTableName = _provider.GetTableName(nameof(user)); var allianceUserTableName = _provider.GetTableName(nameof(alliance_user)); var allianceTableName = _provider.GetTableName(nameof(alliance)); var sqlAdvancdData = @"SELECT TOP 4 " + @"u.Id as userId, " + @"u.avatarUrls as userAvatar, " + @"u.nickname as userName, " + @"u.pvpPoint as userPvpPoint, " + @"a.Id as allianceId, " + @"a.name as allianceName, " + @"a.images as allianceLabel " + $@"FROM {userTableName} AS u " + $@"JOIN {allianceUserTableName} AS au ON au.userId=u.Id " + $@"JOIN {allianceTableName} AS a ON a.Id=au.allianceId " + @"WHERE u.isNpc=0 AND u.Id>1000 "; var dataWinners = _provider.Text <dynamic>(connection, sqlAdvancdData); var winners = dataWinners.Select(i => new WinnerCandidat(i)).OrderByDescending(i => i.UserPvpPoint) .ToList(); if (winners.Count < 4) { throw new NotImplementedException("winners.Count < 4"); } var candidates = winners.Select(i => new CandidatOut { UserId = i.UserId }).ToList(); foreach (var candidat in candidates) { _createAndSaveNewCandidate(connection, candidat, true); } var officers = _buildOfficers(connection, StartRegistrationTime, winners); _rebuildWeekOfficers(officers); _voteSate = VoteStates.EndedFinished; } //этот офицер из прошлой недели, новых назначений небыло, нужно завершить процедуру голосвания else if (firstOfficer.dateEnd <= StartRegistrationTime) { //сбрасываем состояния чтобы небыло исключения _voteSate = VoteStates.Undefined; _endVoting(connection, null, notifyClients); } //эот обычный период не требующий дествий,взвращаем управление проверке данных с указанным состоянием else { //заполняем кеш офицерами если его нет в инсте GetOfficers(connection, true); //снимаем блокировку для входа _checkAndRunVoteStateLocked = false; // состояние определено _voteSate = VoteStates.EndedFinished; // определить дальнейшие действия _checkAndRunVoteState(connection, countError); //todo не верно, этот сценарий перезапишет и сресетит данные, а необходимо выгрузить данные в этом состоянии // _endVoting(null, c, notifyClients); } } catch (Exception e) { _voteSate = VoteStates.EndedErrorInFinished; Console.WriteLine(e); throw; } }
private void _undefinedStateInVotePeriod(IDbConnection connection, bool notifyClients, int startRegistrationTime, int countError) { var candidatTbName = _provider.GetTableName(nameof(c_officer_candidat)); ; var maxCandidatSql = $"SELECT TOP 1 * FROM {candidatTbName} ORDER BY Id DESC"; var maxCandidat = _provider.Text <c_officer_candidat>(connection, maxCandidatSql).FirstOrDefault(); if (countError > MAX_LIMIT_TRY) { throw new NotImplementedException(Error.VotingRunnerTryErrorMoreMaxLimit); } try { //todo это первый запуск приложения. зарегестрированных даннх нет или никто не зарегестрировался if (maxCandidat == null) { // создать офицеров и кандидатов _undefinedStateInRegistratedPeriod(connection, false, countError); // сбросить состояние на текущее _voteSate = VoteStates.StartInProgress; // нжно перезапросить данные после обновления и войти в другую ветку условия _undefinedStateInVotePeriod(connection, notifyClients, startRegistrationTime, countError); } // данные верны, это текущий период необходимо восстановить данные текущего переиода и поднять кеши else if (maxCandidat.dateCreate >= startRegistrationTime) { // этот кандидат прошол отбор в голосование. голосование идет, заполняем кеш if (maxCandidat.isFinalizer) { _fillActiveCandidatesFromDb(connection); _voteSate = VoteStates.StartedRunned; // _endVoting(null,c); } // кандидат не проходил в голосование, проверить начиналась ли процедура голосования else { //проверка начиналось ли голосование находится внутри, выбросит исключение _startVoting(connection, null, notifyClients); } } //это кандидаты прошлой недели, нужно проверить текущих офицеров, является ли кандидат офицером, и очистить прошлый период //maxCandidat.dateCreate < startRegistrationTime else { // этот кандидат проходил отбор он может быть а может и не быть офицером //логика переносит кандидатов прошлой недели в кандидат хистори if (maxCandidat.isFinalizer) { // стереть данные в кеше если есть для верного результата if (_weekOfficersStorage != null && !_weekOfficersStorage.IsEmpty) { _weekOfficersStorage.Clear(); _weekOfficersStorage = null; } var officers = GetOfficers(connection, true); if (officers == null || !officers.Any()) { _voteSate = VoteStates.StartedErrorInRun; throw new NotImplementedException("officers == null || !officers.Any()"); } // незнаю что это значит, что то сделать _voteSate = VoteStates.StartedErrorInRun; throw new NotImplementedException(); //_voteSate = VoteStates.StartedRunned; } /*прошлые выборы были не завершенны корректно. * офицеры не назначены, процедура голосвания не начата данных для восстановления недостаточно, * необходимо дополнительное вмешательство*/ throw new NotImplementedException( "прошлые выборы были завершенны не корректно. офицеры не назначены, процедура голосвания не начата"); } } catch (Exception e) { _voteSate = VoteStates.StartedErrorInRun; Console.WriteLine(e); throw; } }