public static async Task SendWarAndSaveAsync(MainRepository repo, CountryWar war) { MapLog mapLog = null; await repo.CountryDiplomacies.SetWarAsync(war); if ((war.Status == CountryWarStatus.InReady && war.RequestedStopCountryId == 0) || war.Status == CountryWarStatus.Stoped) { // 戦争を周りに通知 var country1 = await repo.Country.GetAliveByIdAsync(war.RequestedCountryId).GetOrErrorAsync(ErrorCode.CountryNotFoundError); var country2 = await repo.Country.GetAliveByIdAsync(war.InsistedCountryId).GetOrErrorAsync(ErrorCode.CountryNotFoundError); mapLog = new MapLog { ApiGameDateTime = (await repo.System.GetAsync()).GameDateTime, Date = DateTime.Now, IsImportant = true, }; if (war.Status == CountryWarStatus.InReady) { if (war.RequestedStopCountryId == 0) { mapLog.EventType = EventType.WarInReady; if (war.Mode == CountryWarMode.Religion) { mapLog.Message = "<country>" + country1.Name + "</country> は、<date>" + war.StartGameDate.ToString() + "</date> より <country>" + country2.Name + "</country> と宗教戦争を開始します"; } else { mapLog.Message = "<country>" + country1.Name + "</country> は、<date>" + war.StartGameDate.ToString() + "</date> より <country>" + country2.Name + "</country> へ侵攻します"; } await PushNotificationService.SendCountryAsync(repo, "宣戦布告", $"{war.StartGameDate.ToString()} より {country2.Name} と戦争します", country1.Id); await PushNotificationService.SendCountryAsync(repo, "宣戦布告", $"{war.StartGameDate.ToString()} より {country1.Name} と戦争します", country2.Id); } } else if (war.Status == CountryWarStatus.Stoped) { mapLog.EventType = EventType.WarStopped; mapLog.Message = "<country>" + country1.Name + "</country> と <country>" + country2.Name + "</country> の戦争は停戦しました"; await PushNotificationService.SendCountryAsync(repo, "停戦", $"{country2.Name} との戦争は停戦しました", country1.Id); await PushNotificationService.SendCountryAsync(repo, "停戦", $"{country1.Name} との戦争は停戦しました", country2.Id); } await repo.MapLog.AddAsync(mapLog); } await repo.SaveChangesAsync(); await StatusStreaming.Default.SendAllAsync(ApiData.From(war)); if (mapLog != null) { await StatusStreaming.Default.SendAllAsync(ApiData.From(mapLog)); await AnonymousStreaming.Default.SendAllAsync(ApiData.From(mapLog)); } }
public async Task <IEnumerable <uint> > GetPenaltyCountries( [FromBody] CountryWar assumptionWar = null) { using (var repo = MainRepository.WithRead()) { var chara = await repo.Character.GetByIdAsync(this.AuthData.CharacterId).GetOrErrorAsync(ErrorCode.LoginCharacterNotFoundError); var countries = await CountryService.GetPenaltyCountriesAsync(repo, assumptionWar); return(countries); } }
/// <summary> /// 戦争を設定する /// </summary> /// <param name="war">新しい戦争</param> public async Task SetWarAsync(CountryWar war) { try { var old = await this.GetCountryWarAsync(war.RequestedCountryId, war.InsistedCountryId); old.Some(o => { this.container.Context.CountryWars.Remove(o); }); if (war.Status != CountryWarStatus.None) { await this.container.Context.CountryWars.AddAsync(war); } } catch (Exception ex) { this.container.Error(ex); } }
public async Task SetCountryWarAsync( [FromRoute] uint targetId, [FromBody] CountryWar param) { CountryWar war; Optional <CountryAlliance> alliance; MapLog mapLog = null; if (param.Status != CountryWarStatus.InReady && param.Status != CountryWarStatus.StopRequesting && param.Status != CountryWarStatus.Stoped) { ErrorCode.InvalidParameterError.Throw(); } using (var repo = MainRepository.WithReadAndWrite()) { var system = await repo.System.GetAsync(); if (system.IsSoftStoped) { ErrorCode.SystemSoftStopedError.Throw(); } var self = await repo.Character.GetByIdAsync(this.AuthData.CharacterId).GetOrErrorAsync(ErrorCode.LoginCharacterNotFoundError); var myPosts = await repo.Country.GetCharacterPostsAsync(self.Id); if (!myPosts.Any(p => p.Type.CanDiplomacy())) { ErrorCode.NotPermissionError.Throw(); } if (system.IsBattleRoyaleMode) { // 全国戦争中に戦争操作はできない ErrorCode.InvalidOperationError.Throw(); } if (system.RuleSet != GameRuleSet.Religion && param.Mode == CountryWarMode.Religion) { // 宗教戦争は宗教ルールでないと布告できない ErrorCode.RuleSetError.Throw(); } var towns = await repo.Town.GetAllAsync(); var myCountry = await repo.Country.GetAliveByIdAsync(self.CountryId).GetOrErrorAsync(ErrorCode.CountryNotFoundError); var target = await repo.Country.GetAliveByIdAsync(targetId).GetOrErrorAsync(ErrorCode.CountryNotFoundError); var wars = await repo.CountryDiplomacies.GetAllWarsAsync(); var old = await repo.CountryDiplomacies.GetCountryWarAsync(self.CountryId, targetId); alliance = await repo.CountryDiplomacies.GetCountryAllianceAsync(self.CountryId, targetId); old.Some((o) => { if (o.Status == param.Status) { ErrorCode.MeaninglessOperationError.Throw(); } if ((o.Status == CountryWarStatus.Available || o.Status == CountryWarStatus.InReady) && param.Status == CountryWarStatus.InReady) { // 重複して宣戦布告はできない ErrorCode.MeaninglessOperationError.Throw(); } else if (o.Status == CountryWarStatus.StopRequesting && param.Status == CountryWarStatus.Stoped && o.RequestedStopCountryId == self.CountryId) { // 自分の停戦要求を自分で承認できない ErrorCode.NotPermissionError.Throw(); } else if (o.Status == CountryWarStatus.Stoped && param.Status == CountryWarStatus.StopRequesting) { // 一度決まった停戦を撤回できない ErrorCode.NotPermissionError.Throw(); } if (o.Status == CountryWarStatus.Stoped && param.Status == CountryWarStatus.InReady) { // 停戦後の再布告 if (param.StartGameDate.ToInt() < system.IntGameDateTime + 12 * 12 + 1 || param.StartGameDate.Year < Config.StartYear + Config.UpdateStartYear + Config.CountryBattleStopDuring / 12) { // 開戦が早すぎる ErrorCode.InvalidParameterError.Throw(); } else if (param.StartGameDate.ToInt() > system.IntGameDateTime + 12 * 24) { // 開戦が遅すぎる ErrorCode.InvalidParameterError.Throw(); } } else if (o.Status == CountryWarStatus.StopRequesting && param.Status == CountryWarStatus.InReady) { // 停戦撤回または拒否 if (o.StartGameDate.ToInt() <= system.GameDateTime.ToInt()) { // 開戦後の場合は開戦扱い param.Status = CountryWarStatus.Available; } } param.RequestedStopCountryId = o.RequestedStopCountryId; if (param.Status == CountryWarStatus.StopRequesting) { param.RequestedStopCountryId = self.CountryId; } param.RequestedCountryId = o.RequestedCountryId; param.InsistedCountryId = o.InsistedCountryId; param.StartGameDate = o.StartGameDate; param.Mode = o.Mode; }); old.None(() => { if (param.Mode == CountryWarMode.Religion) { if (myCountry.Religion == ReligionType.Any || myCountry.Religion == ReligionType.None) { // 国教を持たない国は宗教戦争を布告できない ErrorCode.InvalidOperationError.Throw(); } if (target.Religion == myCountry.Religion) { // 同じ宗教の国には宗教戦争を布告できない ErrorCode.ReligionError.Throw(); } } if (wars.Where(w => w.Status == CountryWarStatus.Available || w.Status == CountryWarStatus.InReady || w.Status == CountryWarStatus.StopRequesting) .Where(w => w.IsJoin(myCountry.Id) || w.IsJoin(target.Id)) .Any(w => w.Mode != param.Mode)) { // 就業戦争と通常戦争を両方することはできない ErrorCode.InvalidWarModeError.Throw(); } if (!towns.GetAroundCountries(towns.Where(t => t.CountryId == param.InsistedCountryId)).Contains(param.RequestedCountryId)) { // 飛び地布告 ErrorCode.InvalidOperationError.Throw(); } if (param.Status == CountryWarStatus.StopRequesting || param.Status == CountryWarStatus.Stoped) { // 存在しない戦争を停戦にはできない ErrorCode.NotPermissionError.Throw(); } else if (param.StartGameDate.ToInt() < system.IntGameDateTime + 12 * 12 + 1 || param.StartGameDate.Year < Config.StartYear + Config.UpdateStartYear + Config.CountryBattleStopDuring / 12) { // 開戦が早すぎる ErrorCode.InvalidParameterError.Throw(); } else if (param.StartGameDate.ToInt() > system.IntGameDateTime + 12 * 24) { // 開戦が遅すぎる ErrorCode.InvalidParameterError.Throw(); } }); alliance.Some((a) => { if (a.Status == CountryAllianceStatus.Available || a.Status == CountryAllianceStatus.ChangeRequesting || a.Status == CountryAllianceStatus.InBreaking) { // 同盟が有効中 ErrorCode.NotPermissionError.Throw(); } if (a.Status == CountryAllianceStatus.Requesting) { // 自動で同盟申請を却下する a.Status = CountryAllianceStatus.Broken; } }); war = new CountryWar { RequestedCountryId = param.RequestedCountryId, InsistedCountryId = param.InsistedCountryId, StartGameDate = param.StartGameDate, Status = param.Status, RequestedStopCountryId = param.RequestedStopCountryId, Mode = param.Mode, }; await CountryService.SendWarAndSaveAsync(repo, war); } if (alliance.HasData) { var a = alliance.Data; await StatusStreaming.Default.SendCountryAsync(ApiData.From(a), a.RequestedCountryId); await StatusStreaming.Default.SendCountryAsync(ApiData.From(a), a.InsistedCountryId); } }
public static async Task <IReadOnlyList <uint> > GetPenaltyCountriesAsync(MainRepository repo, CountryWar assumptionWar = null) { return(Enumerable.Empty <uint>().ToArray()); /* * var reinforcements = (await repo.Reinforcement.GetAllAsync()).Where(r => r.Status == ReinforcementStatus.Active); * var characters = (await repo.Character.GetAllAliveAsync()).Where(c => c.DeleteTurn < 200 && (c.AiType == CharacterAiType.Human || c.AiType == CharacterAiType.Administrator)); * var countries = (await repo.Country.GetAllAsync()).Where(c => !c.HasOverthrown); * var wars = (await repo.CountryDiplomacies.GetAllWarsAsync()) * .Where(w => !countries.Any(c => c.Id == w.RequestedCountryId && c.AiType == CountryAiType.Farmers)) * .Where(w => w.Status != CountryWarStatus.Stoped && w.Status != CountryWarStatus.None); * if (assumptionWar != null) * { * wars = wars * .Where(w => !(w.IsJoin(assumptionWar.InsistedCountryId) && w.IsJoin(assumptionWar.RequestedCountryId))) * .Append(assumptionWar) * .Where(w => w.Status != CountryWarStatus.Stoped && w.Status != CountryWarStatus.None); * } * * var penaltyWarCountries = new List<uint>(); * * // 複数国による同時宣戦を行っている国を抽出 * var cooperateWarCountries = wars * .GroupBy(w => w.InsistedCountryId) * .Where(g => g.Count() >= 2) * .SelectMany(g => g.Select(w => w.RequestedCountryId)) * .Distinct(); * * // 過剰援軍にペナルティ * var reinforcementsOfCountry = characters * .GroupBy(c => c.CountryId) * .GroupJoin(reinforcements, c => c.Key, r => r.RequestedCountryId, (c, rs) => new { CountryId = c.Key, Reinforcements = rs, Characters = c, }); * foreach (var data in reinforcementsOfCountry) * { * IEnumerable<uint> GetEnemies(IEnumerable<uint> countryIds) * { * return wars * .Where(w => countryIds.Any(c => w.IsJoin(c))) * .SelectMany(w => new uint[] { w.InsistedCountryId, w.RequestedCountryId, }) * .Except(countryIds) * .Distinct(); * } * * // 敵(自分が相手する国) * var countries1 = GetEnemies(new uint[] { data.CountryId, }); * * // 敵の敵(味方) * var countries2 = GetEnemies(countries1); * * // 敵の敵の敵(味方の敵) * var countries3 = GetEnemies(countries2); * * var warTargetCountries = countries3 * .Join(reinforcementsOfCountry, a => a, b => b.CountryId, (aa, bb) => bb); * var mySideCountries = countries2 * .Join(reinforcementsOfCountry, a => a, b => b.CountryId, (aa, bb) => bb); * * if (warTargetCountries.Any() && mySideCountries.Any()) * { * var warTargetsCharacterCount = warTargetCountries.Sum(c => c.Characters.Count()); * var warTargetsReinforcementCount = warTargetCountries.Sum(c => c.Reinforcements.Count()); * var mySideCharacterCount = mySideCountries.Sum(c => c.Characters.Count()); * var mySideReinforcementCount = mySideCountries.Sum(c => c.Reinforcements.Count()); * * var isPenalty = false; * * // 単純な過剰援軍 * if (mySideReinforcementCount > 0 && mySideCharacterCount > warTargetsCharacterCount + 3) * { * isPenalty = true; * } * // 複数国同時布告による事実上の過剰援軍 * else if (cooperateWarCountries.Contains(data.CountryId) && * mySideCharacterCount > warTargetsCharacterCount + 5) * { * isPenalty = true; * } * * if (isPenalty) * { * penaltyWarCountries.Add(data.CountryId); * } * } * } * * return penaltyWarCountries; */ }