// See the License for the specific language governing permissions and\r
// limitations under the License.\r
\r
+using System;\r
using System.Collections.Generic;\r
using System.Linq;\r
using static System.Math;\r
private int _fleet;\r
private Record[] _friend;\r
private Record[] _guard;\r
- private int[] _enemyHp;\r
- private int[] _enemyGuardHp;\r
- private int[] _enemyStartHp;\r
- private int[] _enemyGuardStartHp;\r
+ private Record[] _enemy;\r
+ private Record[] _enemyGuard;\r
private readonly List<int> _escapingShips = new List<int>();\r
- private int _flagshipRecoveryType;\r
private bool _lastCell;\r
\r
public BattleState BattleState { get; set; }\r
- public string Formation { get; private set; }\r
+ public int[] Formation { get; private set; }\r
+ public int[] FighterPower { get; private set; }\r
public EnemyFighterPower EnemyFighterPower { get; private set; }\r
public int AirControlLevel { get; private set; }\r
public BattleResultRank ResultRank { get; private set; }\r
- public List<char> WrongResultRank { get; set; } = new List<char>(2);\r
- public ShipStatus[] EnemyResultStatus { get; private set; }\r
- public ShipStatus[] EnemyGuardResultStatus { get; private set; }\r
- public bool EnemyIsCombined => EnemyGuardResultStatus.Length > 0;\r
+ public RankPair DisplayedResultRank { get; } = new RankPair();\r
+ public BattleResult Result { get; set; }\r
+ public bool EnemyIsCombined => _enemyGuard.Length > 0;\r
public List<AirBattleResult> AirBattleResults { get; } = new List<AirBattleResult>();\r
\r
+ public class RankPair\r
+ {\r
+ public char Assumed { get; set; }\r
+ public char Actual { get; set; }\r
+ public bool IsError => Assumed != Actual;\r
+ }\r
+\r
+ public class BattleResult\r
+ {\r
+ public class Combined\r
+ {\r
+ public ShipStatus[] Main { get; set; }\r
+ public ShipStatus[] Guard { get; set; }\r
+ }\r
+\r
+ public Combined Friend { get; set; }\r
+ public Combined Enemy { get; set; }\r
+ }\r
+\r
public BattleInfo(ShipInfo shipInfo, ItemInfo itemInfo)\r
{\r
_shipInfo = shipInfo;\r
_itemInfo = itemInfo;\r
}\r
\r
- public void InspectBattle(dynamic json, string url)\r
+ public void InspectBattle(string url, string request, dynamic json)\r
{\r
- Formation = FormationName(json);\r
+ if (json.api_formation())\r
+ Formation = ((dynamic[])json.api_formation).Select(f => f is string ? (int)int.Parse(f) : (int)f)\r
+ .ToArray();\r
AirControlLevel = CheckAirControlLevel(json);\r
ShowResult(false); // 昼戦の結果を夜戦のときに表示する\r
- SetupResult(json);\r
+ SetupResult(request, json, url.Contains("practice"));\r
+ FighterPower = CalcFighterPower();\r
EnemyFighterPower = CalcEnemyFighterPower(json);\r
BattleState = IsNightBattle(json) ? BattleState.Night : BattleState.Day;\r
CalcDamage(json);\r
- ClearEnemyOverKill();\r
ResultRank = url.EndsWith("ld_airbattle") ? CalcLdAirBattleRank() : CalcResultRank();\r
- }\r
-\r
- private void ClearEnemyOverKill()\r
- {\r
- _enemyHp = _enemyHp.Select(hp => hp < 0 ? 0 : hp).ToArray();\r
- _enemyGuardHp = _enemyGuardHp.Select(hp => hp < 0 ? 0 : hp).ToArray();\r
- }\r
-\r
- public void InspectMapNext(string request)\r
- {\r
- var type = HttpUtility.ParseQueryString(request)["api_recovery_type"];\r
- if (type == null)\r
- return;\r
- _flagshipRecoveryType = int.Parse(type);\r
+ SetResult();\r
}\r
\r
private bool IsNightBattle(dynamic json) => json.api_hougeki();\r
return (int)json.api_deck_id - 1;\r
}\r
\r
- private string FormationName(dynamic json)\r
- {\r
- if (!json.api_formation()) // 演習の夜戦\r
- return "";\r
- switch ((int)json.api_formation[2])\r
- {\r
- case 1:\r
- return "同航戦";\r
- case 2:\r
- return "反航戦";\r
- case 3:\r
- return "T字有利";\r
- case 4:\r
- return "T字不利";\r
- }\r
- return "";\r
- }\r
-\r
- private void SetupResult(dynamic json)\r
+ private void SetupResult(string request, dynamic json, bool practice)\r
{\r
if (_friend != null)\r
return;\r
+ _shipInfo.SaveBattleStartStatus();\r
_fleet = DeckId(json);\r
var fstats = _shipInfo.GetShipStatuses(_fleet);\r
- FlagshipRecovery(fstats[0]);\r
- _friend = Record.Setup(fstats);\r
- _enemyHp = (int[])json.api_e_nowhps;\r
- _enemyStartHp = (int[])_enemyHp.Clone();\r
- EnemyResultStatus = ((int[])json.api_ship_ke)\r
- .Select(id => new ShipStatus {Id = id, Spec = _shipInfo.GetSpec(id)}).ToArray();\r
- EnemyGuardResultStatus = new ShipStatus[0];\r
- if (json.api_ship_ke_combined())\r
- {\r
- EnemyGuardResultStatus = ((int[])json.api_ship_ke_combined)\r
- .Select(id => new ShipStatus {Id = id, Spec = _shipInfo.GetSpec(id)}).ToArray();\r
- }\r
- _guard = new Record[0];\r
- _enemyGuardHp = new int[0];\r
- _enemyGuardStartHp = new int[0];\r
- if (json.api_f_nowhps_combined())\r
- _guard = Record.Setup(_shipInfo.GetShipStatuses(1));\r
- if (json.api_e_nowhps_combined()) // 敵が連合艦隊\r
+ FlagshipRecovery(request, fstats[0]);\r
+ _friend = Record.Setup(fstats, practice);\r
+ _guard = json.api_f_nowhps_combined()\r
+ ? Record.Setup(_shipInfo.GetShipStatuses(1), practice)\r
+ : new Record[0];\r
+ _enemy = Record.Setup((int[])json.api_e_nowhps,\r
+ ((int[])json.api_ship_ke).Select(_shipInfo.GetSpec).ToArray(),\r
+ ((int[][])json.api_eSlot).Select(slot => slot.Select(_itemInfo.GetSpecByItemId).ToArray()).ToArray(),\r
+ practice);\r
+ _enemyGuard = json.api_ship_ke_combined()\r
+ ? Record.Setup((int[])json.api_e_nowhps_combined,\r
+ ((int[])json.api_ship_ke_combined).Select(_shipInfo.GetSpec).ToArray(),\r
+ ((int[][])json.api_eSlot).Select(slot => slot.Select(_itemInfo.GetSpecByItemId).ToArray())\r
+ .ToArray(), practice)\r
+ : new Record[0];\r
+ }\r
+\r
+ private void SetResult()\r
+ {\r
+ Result = new BattleResult\r
{\r
- _enemyGuardHp = (int[])json.api_e_nowhps_combined;\r
- _enemyGuardStartHp = (int[])_enemyGuardHp.Clone();\r
- }\r
+ Friend = new BattleResult.Combined\r
+ {\r
+ Main = _friend.Select(r => r.SnapShot).ToArray(),\r
+ Guard = _guard.Select(r => r.SnapShot).ToArray()\r
+ },\r
+ Enemy = new BattleResult.Combined\r
+ {\r
+ Main = _enemy.Select(r => r.SnapShot).ToArray(),\r
+ Guard = _enemyGuard.Select(r => r.SnapShot).ToArray()\r
+ }\r
+ };\r
}\r
\r
- private void FlagshipRecovery(ShipStatus flagship)\r
+ private void FlagshipRecovery(string request, ShipStatus flagship)\r
{\r
- switch (_flagshipRecoveryType)\r
+ var type = int.Parse(HttpUtility.ParseQueryString(request)["api_recovery_type"] ?? "0");\r
+ switch (type)\r
{\r
case 0:\r
return;\r
ConsumeSlotItem(flagship, 43); // 女神\r
break;\r
}\r
- if (_flagshipRecoveryType != 0)\r
+ if (type != 0)\r
_shipInfo.SetBadlyDamagedShips();\r
- _flagshipRecoveryType = 0;\r
}\r
\r
private static void ConsumeSlotItem(ShipStatus ship, int id)\r
return (int)stage1.api_disp_seiku;\r
}\r
\r
+ private int[] CalcFighterPower()\r
+ {\r
+ if (_guard.Length > 0 && _enemyGuard.Length > 0)\r
+ return _shipInfo.GetFighterPower(0).Zip(_shipInfo.GetFighterPower(1), (a, b) => a + b).ToArray();\r
+ return _shipInfo.GetFighterPower(_fleet);\r
+ }\r
+\r
private EnemyFighterPower CalcEnemyFighterPower(dynamic json)\r
{\r
var result = new EnemyFighterPower();\r
ByTurn,\r
Support,\r
Aircraft,\r
- AirBase\r
+ AirBase,\r
+ Friend\r
}\r
\r
private class Phase\r
new Phase("support_info", CombatType.Support),\r
new Phase("opening_taisen", CombatType.ByTurn),\r
new Phase("opening_atack", CombatType.AtOnce),\r
+ new Phase("friendly_battle", CombatType.Friend),\r
new Phase("hougeki", CombatType.ByTurn),\r
new Phase("hougeki1", CombatType.ByTurn),\r
new Phase("hougeki2", CombatType.ByTurn),\r
case CombatType.AirBase:\r
CalcAirBaseAttackDamage(json[api]);\r
break;\r
+ case CombatType.Friend:\r
+ CalcFriendAttackDamage(json[api]);\r
+ break;\r
}\r
}\r
\r
{\r
if (json.api_support_hourai != null)\r
{\r
- CalcDamageAtOnce(json.api_support_hourai.api_damage, _enemyHp, _enemyGuardHp);\r
+ CalcRawDamageAtOnce(json.api_support_hourai.api_damage, _enemy, _enemyGuard);\r
}\r
else if (json.api_support_airatack != null)\r
{\r
- CalcDamageAtOnce(json.api_support_airatack.api_stage3.api_edam, _enemyHp, _enemyGuardHp);\r
+ CalcRawDamageAtOnce(json.api_support_airatack.api_stage3.api_edam, _enemy, _enemyGuard);\r
}\r
}\r
\r
}\r
}\r
\r
+ private void CalcFriendAttackDamage(dynamic json)\r
+ {\r
+ CalcDamageByTurn(json.api_hougeki, true);\r
+ }\r
+\r
private void AddAirBattleResult(dynamic json, string phaseName)\r
{\r
var stage1 = json.api_stage1;\r
if (stage1 == null || (stage1.api_f_count == 0 && stage1.api_e_count == 0))\r
return;\r
- AirBattleResults.Add(new AirBattleResult\r
+ var result = new AirBattleResult\r
{\r
PhaseName = phaseName,\r
AirControlLevel = json.api_stage1.api_disp_seiku() ? (int)json.api_stage1.api_disp_seiku : 0,\r
EnemyCount = (int)json.api_stage2.api_e_count,\r
EnemyLost = (int)json.api_stage2.api_e_lostcount\r
}\r
- });\r
+ };\r
+ if (json.api_stage2 != null && json.api_stage2.api_air_fire())\r
+ {\r
+ var airfire = json.api_stage2.api_air_fire;\r
+ var idx = (int)airfire.api_idx;\r
+ result.AirFire = new AirBattleResult.AirFireResult\r
+ {\r
+ ShipName = idx < _friend.Length ? _friend[idx].Name : _guard[idx - 6].Name,\r
+ Kind = (int)airfire.api_kind,\r
+ Items = ((int[])airfire.api_use_items).Select(id => _itemInfo.GetSpecByItemId(id).Name).ToArray()\r
+ };\r
+ }\r
+ AirBattleResults.Add(result);\r
}\r
\r
private void CalcKoukuDamage(dynamic json)\r
{\r
if (json.api_stage3() && json.api_stage3 != null)\r
- CalcDamageAtOnce(json.api_stage3, _friend, _enemyHp);\r
+ CalcDamageAtOnce(json.api_stage3, _friend, _enemy);\r
if (json.api_stage3_combined() && json.api_stage3_combined != null)\r
- CalcDamageAtOnce(json.api_stage3_combined, _guard, _enemyGuardHp);\r
+ CalcDamageAtOnce(json.api_stage3_combined, _guard, _enemyGuard);\r
}\r
\r
private void CalcDamageAtOnce(dynamic json)\r
{\r
- CalcDamageAtOnce(json, _friend, _guard, _enemyHp, _enemyGuardHp);\r
+ CalcDamageAtOnce(json, _friend, _guard, _enemy, _enemyGuard);\r
}\r
\r
- private void CalcDamageAtOnce(dynamic json, Record[] friend, int[] enemy)\r
+ private void CalcDamageAtOnce(dynamic json, Record[] friend, Record[] enemy)\r
{\r
CalcDamageAtOnce(json, friend, null, enemy, null);\r
}\r
\r
- private void CalcDamageAtOnce(dynamic json, Record[] friend, Record[] guard, int[] enemy, int[] enemyGuard)\r
+ private void CalcDamageAtOnce(dynamic json,\r
+ Record[] friend, Record[] guard, Record[] enemy, Record[] enemyGuard)\r
{\r
if (json.api_fdam() && json.api_fdam != null)\r
- CalcDamageAtOnce(json.api_fdam, friend, guard);\r
+ CalcRawDamageAtOnce(json.api_fdam, friend, guard);\r
if (json.api_edam() && json.api_edam != null)\r
- CalcDamageAtOnce(json.api_edam, enemy, enemyGuard);\r
+ CalcRawDamageAtOnce(json.api_edam, enemy, enemyGuard);\r
}\r
\r
- private void CalcDamageAtOnce(dynamic rawDamage, Record[] friend, Record[] guard = null)\r
+ private void CalcRawDamageAtOnce(dynamic rawDamage, Record[] friend, Record[] guard = null)\r
{\r
var damage = (int[])rawDamage;\r
for (var i = 0; i < friend.Length; i++)\r
guard[i].ApplyDamage(damage[i + 6]);\r
}\r
\r
- private void CalcDamageAtOnce(dynamic rawDamage, int[] enemy, int[] enemyGuard = null)\r
- {\r
- var damage = (int[])rawDamage;\r
- for (var i = 0; i < enemy.Length; i++)\r
- enemy[i] -= damage[i];\r
- if (enemyGuard == null)\r
- return;\r
- for (var i = 0; i < enemyGuard.Length; i++)\r
- enemyGuard[i] -= damage[i + 6];\r
- }\r
-\r
- private void CalcDamageByTurn(dynamic json)\r
+ private void CalcDamageByTurn(dynamic json, bool ignoreFriendDamage = false)\r
{\r
if (!(json.api_df_list() && json.api_df_list != null &&\r
json.api_damage() && json.api_damage != null &&\r
json.api_at_eflag() && json.api_at_eflag != null))\r
return;\r
\r
- var targets = ((dynamic[])json.api_df_list).Select(x => (int[])x);\r
- var damages = ((dynamic[])json.api_damage).Select(x => (int[])x);\r
+ var targets = (int[][])json.api_df_list;\r
+ var damages = (int[][])json.api_damage;\r
var eflags = (int[])json.api_at_eflag;\r
- foreach (var turn in\r
- targets.Zip(damages, (t, d) => new {t, d}).Zip(eflags, (td, e) => new {e, td.t, td.d}))\r
+ var records = new[] {new Record[12], new Record[12]};\r
+ Array.Copy(_friend, records[1], _friend.Length);\r
+ Array.Copy(_guard, 0, records[1], 6, _guard.Length);\r
+ Array.Copy(_enemy, records[0], _enemy.Length);\r
+ Array.Copy(_enemyGuard, 0, records[0], 6, _enemyGuard.Length);\r
+ for (var i = 0; i < eflags.Length; i++)\r
{\r
- foreach (var hit in turn.t.Zip(turn.d, (t, d) => new {t, d}))\r
- {\r
- if (hit.t == -1)\r
- continue;\r
- if (turn.e == 1)\r
- {\r
- if (hit.t < _friend.Length)\r
- {\r
- _friend[hit.t].ApplyDamage(hit.d);\r
- }\r
- else\r
- {\r
- _guard[hit.t - 6].ApplyDamage(hit.d);\r
- }\r
- }\r
- else\r
- {\r
- if (hit.t < _enemyHp.Length)\r
- {\r
- _enemyHp[hit.t] -= hit.d;\r
- }\r
- else\r
- {\r
- _enemyGuardHp[hit.t - 6] -= hit.d;\r
- }\r
- }\r
- }\r
+ // 一度に複数の目標を狙う攻撃はないものと仮定する\r
+ var hit = new {t = targets[i][0], d = damages[i].Sum(d => d >= 0 ? d : 0)};\r
+ if (hit.t == -1)\r
+ continue;\r
+ if (ignoreFriendDamage && eflags[i] == 1)\r
+ continue;\r
+ records[eflags[i]][hit.t].ApplyDamage(hit.d);\r
}\r
}\r
\r
{\r
BattleState = BattleState.Result;\r
ShowResult(!_lastCell);\r
+ _shipInfo.SaveBattleResult();\r
VerifyResultRank(json);\r
CleanupResult();\r
SetEscapeShips(json);\r
{\r
if (_friend == null)\r
return;\r
- WrongResultRank.Clear();\r
if (!json.api_win_rank())\r
return;\r
var assumed = "PSABCDE"[(int)ResultRank];\r
if (assumed == 'P')\r
assumed = 'S';\r
var actual = ((string)json.api_win_rank)[0];\r
- if (assumed == actual)\r
- return;\r
- WrongResultRank.AddRange(new[] {assumed, actual});\r
+ DisplayedResultRank.Assumed = assumed;\r
+ DisplayedResultRank.Actual = actual;\r
}\r
\r
public void InspectPracticeResult(dynamic json)\r
{\r
BattleState = BattleState.Result;\r
ShowResult(false);\r
+ VerifyResultRank(json);\r
CleanupResult();\r
}\r
\r
_shipInfo.SetBadlyDamagedShips();\r
else\r
_shipInfo.ClearBadlyDamagedShips();\r
- SetEnemyResultStatus();\r
- }\r
-\r
- private void SetEnemyResultStatus()\r
- {\r
- for (var i = 0; i < _enemyHp.Length; i++)\r
- {\r
- EnemyResultStatus[i].MaxHp = _enemyStartHp[i];\r
- EnemyResultStatus[i].NowHp = _enemyHp[i];\r
- }\r
- for (var i = 0; i < _enemyGuardHp.Length; i++)\r
- {\r
- EnemyGuardResultStatus[i].MaxHp = _enemyGuardStartHp[i];\r
- EnemyGuardResultStatus[i].NowHp = _enemyGuardHp[i];\r
- }\r
}\r
\r
public void SetEscapeShips(dynamic json)\r
private class Record\r
{\r
private ShipStatus _status;\r
+ private bool _practice;\r
+ public ShipStatus SnapShot => (ShipStatus)_status.Clone();\r
public int NowHp => _status.NowHp;\r
public bool Escaped => _status.Escaped;\r
public ShipStatus.Damage DamageLevel => _status.DamageLevel;\r
- public int StartHp;\r
+ public string Name => _status.Name;\r
+ public int StartHp { get; private set; }\r
\r
- public static Record[] Setup(ShipStatus[] ships) =>\r
- (from s in ships select new Record {_status = (ShipStatus)s.Clone(), StartHp = s.NowHp}).ToArray();\r
+ public static Record[] Setup(ShipStatus[] ships, bool practice) =>\r
+ (from s in ships\r
+ select new Record {_status = (ShipStatus)s.Clone(), _practice = practice, StartHp = s.NowHp}).ToArray();\r
+\r
+ public static Record[] Setup(int[] nowhps, ShipSpec[] ships, ItemSpec[][] slots, bool practice)\r
+ {\r
+ return Enumerable.Range(0, nowhps.Length).Select(i =>\r
+ new Record\r
+ {\r
+ StartHp = nowhps[i],\r
+ _status = new ShipStatus\r
+ {\r
+ Id = ships[i].Id,\r
+ NowHp = nowhps[i],\r
+ MaxHp = nowhps[i],\r
+ Spec = ships[i],\r
+ Slot = slots[i].Select(spec => new ItemStatus {Id = spec.Id, Spec = spec}).ToArray(),\r
+ SlotEx = new ItemStatus(0)\r
+ },\r
+ _practice = practice\r
+ }).ToArray();\r
+ }\r
\r
public void ApplyDamage(int damage)\r
{\r
return;\r
}\r
_status.NowHp = 0;\r
+ if (_practice)\r
+ return;\r
foreach (var item in new[] {_status.SlotEx}.Concat(_status.Slot))\r
{\r
if (item.Spec.Id == 42)\r
\r
private BattleResultRank CalcLdAirBattleRank()\r
{\r
- var combined = _friend.Concat(_guard).ToArray();\r
- var friendNowShips = combined.Count(r => r.NowHp > 0);\r
+ var combined = _friend.Concat(_guard).Where(r => !r.Escaped).ToArray();\r
var friendGauge = combined.Sum(r => r.StartHp - r.NowHp);\r
- var friendSunk = combined.Count(r => r.NowHp == 0);\r
var friendGaugeRate = Floor((double)friendGauge / combined.Sum(r => r.StartHp) * 100);\r
\r
- if (friendSunk == 0)\r
- {\r
- if (friendGauge == 0)\r
- return BattleResultRank.P;\r
- if (friendGaugeRate < 10)\r
- return BattleResultRank.A;\r
- if (friendGaugeRate < 20)\r
- return BattleResultRank.B;\r
- if (friendGaugeRate < 50)\r
- return BattleResultRank.C;\r
- return BattleResultRank.D;\r
- }\r
- if (friendSunk < friendNowShips)\r
+ if (friendGauge <= 0)\r
+ return BattleResultRank.P;\r
+ if (friendGaugeRate < 10)\r
+ return BattleResultRank.A;\r
+ if (friendGaugeRate < 20)\r
+ return BattleResultRank.B;\r
+ if (friendGaugeRate < 50)\r
+ return BattleResultRank.C;\r
+ if (friendGaugeRate < 80)\r
return BattleResultRank.D;\r
return BattleResultRank.E;\r
}\r
private BattleResultRank CalcResultRank()\r
{\r
var friend = _friend.Concat(_guard).ToArray();\r
- var enemyHp = _enemyHp.Concat(_enemyGuardHp).ToArray();\r
- var enemyStartHp = _enemyStartHp.Concat(_enemyGuardStartHp).ToArray();\r
+ var enemy = _enemy.Concat(_enemyGuard).ToArray();\r
\r
var friendCount = friend.Length;\r
var friendStartHpTotal = 0;\r
}\r
var friendGaugeRate = (int)((double)(friendStartHpTotal - friendNowHpTotal) / friendStartHpTotal * 100);\r
\r
- var enemyCount = enemyHp.Length;\r
- var enemyStartHpTotal = enemyStartHp.Sum();\r
- var enemyNowHpTotal = enemyHp.Sum();\r
- var enemySunk = enemyHp.Count(hp => hp == 0);\r
+ var enemyCount = enemy.Length;\r
+ var enemyStartHpTotal = enemy.Sum(r => r.StartHp);\r
+ var enemyNowHpTotal = enemy.Sum(r => r.NowHp);\r
+ var enemySunk = enemy.Count(r => r.NowHp == 0);\r
var enemyGaugeRate = (int)((double)(enemyStartHpTotal - enemyNowHpTotal) / enemyStartHpTotal * 100);\r
\r
if (friendSunk == 0 && enemySunk == enemyCount)\r
}\r
if (friendSunk == 0 && enemySunk >= (int)(enemyCount * 0.7) && enemyCount > 1)\r
return BattleResultRank.A;\r
- if (friendSunk < enemySunk && enemyHp[0] == 0)\r
+ if (friendSunk < enemySunk && enemy[0].NowHp == 0)\r
return BattleResultRank.B;\r
if (friendCount == 1 && friend[0].DamageLevel == ShipStatus.Damage.Badly)\r
return BattleResultRank.D;\r
return BattleResultRank.E;\r
return BattleResultRank.D;\r
}\r
+\r
+ /// <summary>\r
+ /// テスト専用\r
+ /// </summary>\r
+ public void InjectResultStatus(ShipStatus[] main, ShipStatus[] guard, ShipStatus[] enemy, ShipStatus[] enemyGuard)\r
+ {\r
+ Result = new BattleResult\r
+ {\r
+ Friend = new BattleResult.Combined { Main = main, Guard = guard},\r
+ Enemy = new BattleResult.Combined {Main = enemy, Guard = enemyGuard}\r
+ };\r
+ }\r
}\r
}
\ No newline at end of file