diff --git a/apps/frontend/components/achievements/Category.svelte b/apps/frontend/components/achievements/Category.svelte
index 9940a6cca..0534e14b6 100644
--- a/apps/frontend/components/achievements/Category.svelte
+++ b/apps/frontend/components/achievements/Category.svelte
@@ -176,7 +176,7 @@
>
- {#if category && userState.achievements.categories[category.id].totalPoints}
+ {#if category && userState.achievements.categories[category.id]?.totalPoints}
0 && maxCharacter >= criteriaTree.amount;
+ if (criteriaTree?.operator === CriteriaTreeOperator.Any) {
+ let anyCount = 0;
+ for (const childCriteriaTreeId of criteriaTree.children) {
+ const childCriteriaTree =
+ wowthingData.achievements.criteriaTreeById.get(childCriteriaTreeId);
+ const childMaxCharacter =
+ criteriaCharacters?.[childCriteriaTree?.criteriaId || -1]?.[0]?.[1] || 0;
+ anyCount += childMaxCharacter;
+ }
+ have = anyCount >= criteriaTree.amount;
+ } else {
+ const maxCharacter =
+ criteriaCharacters?.[criteriaTree?.criteriaId || -1]?.[0]?.[1] || 0;
+ have = maxCharacter > 0 && maxCharacter >= criteriaTree.amount;
+ }
} else {
let maybeCriteria: number[][];
maybeCriteria = criteriaCharacters[criteria?.id] || [[0, 0]];
diff --git a/apps/frontend/components/achievements/get-account-data.ts b/apps/frontend/components/achievements/get-account-data.ts
index 5fcfa70b5..c4a5e1328 100644
--- a/apps/frontend/components/achievements/get-account-data.ts
+++ b/apps/frontend/components/achievements/get-account-data.ts
@@ -12,7 +12,7 @@ import type { UserQuestData } from '@/types/data';
import { CriteriaTreeOperator } from '@/enums/wow';
import { userState } from '@/user-home/state/user';
-const debugId = 42315;
+const debugId = 13638;
export function getAccountData(
achievementData: AchievementData,
diff --git a/apps/frontend/components/achievements/get-achievement-data.ts b/apps/frontend/components/achievements/get-achievement-data.ts
index 68a801ccb..6b7546749 100644
--- a/apps/frontend/components/achievements/get-achievement-data.ts
+++ b/apps/frontend/components/achievements/get-achievement-data.ts
@@ -14,7 +14,7 @@ import type {
import type { UserQuestData } from '@/types/data';
import type { AchievementStatus } from './types';
-const debugId = 42315;
+const debugId = 13638;
export function getAchievementStatus(
userAchievementData: UserAchievementData,
diff --git a/apps/frontend/data/achievements.ts b/apps/frontend/data/achievements.ts
index e6007792c..692378dc6 100644
--- a/apps/frontend/data/achievements.ts
+++ b/apps/frontend/data/achievements.ts
@@ -83,6 +83,7 @@ type ExtraAchievementCategory = {
targetSlug: string;
achievementIds?: (number | number[])[];
+ onlyAchievementIds?: boolean;
overrideName?: string;
overrideSlug?: string;
}[];
@@ -356,7 +357,45 @@ export const extraCategories: ExtraAchievementCategory[] = [
],
},
null,
- { targetSlug: 'expansion-features/skyriding', nameType: 2 },
+ {
+ targetSlug: 'expansion-features/skyriding',
+ nameType: 2,
+ onlyAchievementIds: true,
+ achievementIds: [
+ // Meta
+ 19478,
+ // Glyph Hunter
+ 16575, 16576, 16577, 16578, 17411,
+ // Waking Shores
+ 15915, 15916, 15917, 15927, 15928, 15929, 17195, 17196, 17197,
+ // Ohn'ahran Plains
+ 15918, 15919, 15920, 15930, 15931, 15932, 17198, 17199, 17200,
+ // Azure Span
+ 15921, 15922, 15923, 15933, 15934, 15935, 17201, 17202, 17203,
+ // Thaldraszus
+ 15924, 15925, 15926, 15936, 15937, 15938, 17204, 17205, 17206,
+ // Completionist
+ 15939, 15940, 15941, 17330, 17331, 17332,
+ // Forbidden Reach
+ 17279, 17280, 17281, 17284, 17286, 17287, 17288, 17289, 17290,
+ // Forbidden Reach Completionist
+ 17294, 17296, 17298,
+ // Zaralek Cavern
+ 17483, 17484, 17485, 17486, 17487, 17488, 17489, 17490, 17491,
+ // Zaralek Cavern Completionist
+ 17492, 17493, 17494,
+ // Zaralek Cavern Glyph Hunter
+ 18150,
+ // Challenge
+ 18790, 18791, 18792,
+ // Emerald Dream
+ 19109, 19110, 19111, 19112, 19113, 19114, 19115, 19116, 19117,
+ // Emerald Dream Completionist
+ 19127, 19128, 19129,
+ // Emerald Dream Glyph Hunter
+ 19306,
+ ],
+ },
{
targetSlug: 'collections/dragon-isle-drake-cosmetics',
nameType: 3,
@@ -401,6 +440,30 @@ export const extraCategories: ExtraAchievementCategory[] = [
41597, // Glory of the Omega Raider
],
},
+ null,
+ {
+ targetSlug: 'expansion-features/skyriding',
+ nameType: 2,
+ onlyAchievementIds: true,
+ achievementIds: [
+ // Glyph Hunter
+ 40702, 40166, 40703, 40704, 40705, 42727,
+ // Isle of Dorn
+ 40316, 40317, 40318, 40139, 40320, 40321, 40322, 40323, 40324,
+ // Ringing Deeps
+ 40325, 40326, 40327, 40328, 40329, 40330, 40331, 40332, 40333,
+ // Hallowfall
+ 40334, 40335, 40336, 40337, 40338, 40339, 40340, 40341, 40342,
+ // Azj-Kahet
+ 40343, 40344, 40345, 40346, 40347, 40348, 40349, 40350, 40351,
+ // Khaz Algar Completionist
+ 40352, 40353, 40354,
+ // Undermine Skyrocketing
+ 40936, 40937, 40938,
+ // Undermine Breaknecking
+ 41081, 41083, 41084,
+ ],
+ },
],
},
{
diff --git a/apps/frontend/data/currencies.ts b/apps/frontend/data/currencies.ts
index f009ab80b..9abb3fd94 100644
--- a/apps/frontend/data/currencies.ts
+++ b/apps/frontend/data/currencies.ts
@@ -193,6 +193,7 @@ export const currencyExtra: Record = {
126411: [
3310, // Coffer Key Shards
3028, // Restored Coffer Key
+ 3356, // Untainted Mana-Crystals
null,
3378, // Dawnlight Manaflux
3383, // Adventurer Dawncrest
diff --git a/apps/frontend/data/tasks/11-midnight/delves.ts b/apps/frontend/data/tasks/11-midnight/delves.ts
index bfab7a2ee..e89ae25b3 100644
--- a/apps/frontend/data/tasks/11-midnight/delves.ts
+++ b/apps/frontend/data/tasks/11-midnight/delves.ts
@@ -20,6 +20,42 @@ export const midDelves: Task = {
questReset: DbResetType.Weekly,
questIds: [93784],
},
+ {
+ key: 'repAmani',
+ name: 'Rep: {faction:2696}',
+ minimumLevel: 90,
+ accountWide: true,
+ alwaysStarted: true,
+ questReset: DbResetType.Weekly,
+ questIds: [93819],
+ },
+ {
+ key: 'repHarati',
+ name: 'Rep: {faction:2704}',
+ minimumLevel: 90,
+ accountWide: true,
+ alwaysStarted: true,
+ questReset: DbResetType.Weekly,
+ questIds: [93822],
+ },
+ {
+ key: 'repSilvermoon',
+ name: 'Rep: {faction:2710}',
+ minimumLevel: 90,
+ accountWide: true,
+ alwaysStarted: true,
+ questReset: DbResetType.Weekly,
+ questIds: [93821],
+ },
+ {
+ key: 'repSingularity',
+ name: 'Rep: {faction:2699}',
+ minimumLevel: 90,
+ accountWide: true,
+ alwaysStarted: true,
+ questReset: DbResetType.Weekly,
+ questIds: [93820],
+ },
null,
{
key: 'bounty',
@@ -31,19 +67,14 @@ export const midDelves: Task = {
questReset: DbResetType.Weekly,
questResetForced: true,
questIds: [86371],
- // This seems wrong, I got no tracking quest for using the map or looting the box
- // subChores: [
- // {
- // key: 'get',
- // name: 'Get Bounty',
- // questIds: [86371],
- // },
- // {
- // key: 'use',
- // name: 'Use Bounty',
- // questIds: [92887],
- // },
- // ],
+ },
+ {
+ key: 'nullaeus',
+ name: 'Nullaeus Invasion',
+ minimumLevel: 90,
+ alwaysStarted: true,
+ questIds: [92887],
+ questReset: DbResetType.Weekly,
},
{
key: 'gilded',
@@ -65,13 +96,5 @@ export const midDelves: Task = {
},
],
},
- // {
- // key: 'nullaeus',
- // name: "Nullaeus Invasion",
- // minimumLevel: 90,
- // alwaysStarted: true,
- // questIds: [], // ??
- // questReset: DbResetType.Weekly,
- // },
],
};
diff --git a/apps/frontend/shared/stores/data/achievements/process.ts b/apps/frontend/shared/stores/data/achievements/process.ts
index 77053cb1f..b0384b05d 100644
--- a/apps/frontend/shared/stores/data/achievements/process.ts
+++ b/apps/frontend/shared/stores/data/achievements/process.ts
@@ -110,11 +110,15 @@ export function processAchievementsData(rawData: RawAchievements): DataAchieveme
childSlug = childSlugOverride;
}
+ const childAchievementIds = child.achievementIds || [];
+
category.children.push({
- id: childCat2.id,
+ id: child.onlyAchievementIds ? categoryId++ : childCat2.id,
name: childName,
slug: childSlug,
- achievementIds: (child.achievementIds || []).concat(childCat2.achievementIds),
+ achievementIds: child.onlyAchievementIds
+ ? childAchievementIds
+ : childAchievementIds.concat(childCat2.achievementIds),
children: [],
});
} else {
@@ -712,7 +716,7 @@ export function processAchievementsData(rawData: RawAchievements): DataAchieveme
name: '[TWW] Worldsoul-Searching',
slug: 'worldsoul-searching',
achievementIds: [
- 19458, // Worldsoul-Searching
+ 61451, // Worldsoul-Searching
40244, // Nerub-ar Palace
41222, // Liberation of Undermine
@@ -754,10 +758,10 @@ export function processAchievementsData(rawData: RawAchievements): DataAchieveme
41133, // You Xal Not Pass > Isle Remember You
40231, // The War Within Pathfinder
- 20118, // The War Within Pathfinder > The Isle of Dorn
- 19560, // The War Within Pathfinder > The Ringing Deeps
- 20598, // The War Within Pathfinder > Hallowfall
- 19559, // The War Within Pathfinder > Azj-Kahet
+ // 20118, // The War Within Pathfinder > The Isle of Dorn
+ // 19560, // The War Within Pathfinder > The Ringing Deeps
+ // 20598, // The War Within Pathfinder > Hallowfall
+ // 19559, // The War Within Pathfinder > Azj-Kahet
40790, // The War Within Pathfinder > Khaz Algar Explorer
// Glory of the Delver
@@ -807,12 +811,19 @@ export function processAchievementsData(rawData: RawAchievements): DataAchieveme
for (const category of ret.categories.filter((cat) => cat?.id >= 100000)) {
for (const maybeArray of category.achievementIds) {
- if (Array.isArray(maybeArray)) {
- for (const achievementId of maybeArray) {
- ret.achievementToCategory[achievementId] ||= category.id;
+ const achievementIds = Array.isArray(maybeArray) ? maybeArray : [maybeArray];
+ for (const achievementId of achievementIds) {
+ (ret.achievementToCategoryIds[achievementId] ||= []).push(category.id);
+ }
+ }
+
+ const validChildren = (category.children || []).filter((cat) => cat?.id > 100_000);
+ for (const child of validChildren) {
+ for (const maybeArray of child.achievementIds) {
+ const achievementIds = Array.isArray(maybeArray) ? maybeArray : [maybeArray];
+ for (const achievementId of achievementIds) {
+ (ret.achievementToCategoryIds[achievementId] ||= []).push(child.id);
}
- } else {
- ret.achievementToCategory[maybeArray] ||= category.id;
}
}
}
diff --git a/apps/frontend/shared/stores/data/achievements/types.ts b/apps/frontend/shared/stores/data/achievements/types.ts
index 3d008714d..547fa9573 100644
--- a/apps/frontend/shared/stores/data/achievements/types.ts
+++ b/apps/frontend/shared/stores/data/achievements/types.ts
@@ -23,5 +23,5 @@ export class DataAchievements {
public criteriaTreeById = new Map();
public isHidden: Record = {};
- public achievementToCategory: Record = {};
+ public achievementToCategoryIds: Record = {};
}
diff --git a/apps/frontend/stores/lazy/achievements.ts b/apps/frontend/stores/lazy/achievements.ts
index 6f5735199..76f2eae48 100644
--- a/apps/frontend/stores/lazy/achievements.ts
+++ b/apps/frontend/stores/lazy/achievements.ts
@@ -321,7 +321,7 @@ class AchievementProcessor {
}
}
-const debugId = 42315;
+const debugId = 13638;
export function getAccountData(
achievementData: AchievementData,
diff --git a/apps/frontend/stores/user-achievements.ts b/apps/frontend/stores/user-achievements.ts
index e5afdeed9..4e655f07b 100644
--- a/apps/frontend/stores/user-achievements.ts
+++ b/apps/frontend/stores/user-achievements.ts
@@ -88,8 +88,10 @@ export class UserAchievementDataStore extends WritableFancyStore 8x > 7x)' },
{ id: 'seen', name: 'Last seen' },
];
diff --git a/apps/frontend/user-home/components/transmog-sets/TableCategory.svelte b/apps/frontend/user-home/components/transmog-sets/TableCategory.svelte
index e369f8de4..9b4b35f11 100644
--- a/apps/frontend/user-home/components/transmog-sets/TableCategory.svelte
+++ b/apps/frontend/user-home/components/transmog-sets/TableCategory.svelte
@@ -162,7 +162,7 @@
word-spacing: -0.2ch;
}
.percent-cell {
- --width: 2.8rem;
+ --width: 3.4rem;
border-right: 1px solid var(--border-color);
text-align: right;
diff --git a/apps/frontend/user-home/state/activeViewTasks.svelte.ts b/apps/frontend/user-home/state/activeViewTasks.svelte.ts
index 6ae8ec873..c34197256 100644
--- a/apps/frontend/user-home/state/activeViewTasks.svelte.ts
+++ b/apps/frontend/user-home/state/activeViewTasks.svelte.ts
@@ -24,7 +24,9 @@ class ActiveViewTasks {
// Any task with required holidays needs at least one active
if (
task.requiredHolidays?.length > 0 &&
- !task.requiredHolidays.some((holidayId) => !!activeHolidays.value[holidayId])
+ !task.requiredHolidays.some(
+ (holidayId) => activeHolidays.value[holidayId]?.soon === false
+ )
) {
continue;
}
diff --git a/apps/frontend/user-home/state/lazy/achievements.svelte.ts b/apps/frontend/user-home/state/lazy/achievements.svelte.ts
index 7d3867ee8..90b20d8a2 100644
--- a/apps/frontend/user-home/state/lazy/achievements.svelte.ts
+++ b/apps/frontend/user-home/state/lazy/achievements.svelte.ts
@@ -99,7 +99,6 @@ class AchievementProcessor {
}
console.timeEnd('AchievementProcessor.process');
- // console.log(this.data);
return this.data;
}
@@ -318,7 +317,7 @@ class AchievementProcessor {
}
}
-const debugId = 42315;
+const debugId = 13638;
export function getAccountData(
achievementData: AchievementData,
diff --git a/apps/frontend/user-home/state/user/achievements.svelte.ts b/apps/frontend/user-home/state/user/achievements.svelte.ts
index df3f999b1..cfb865267 100644
--- a/apps/frontend/user-home/state/user/achievements.svelte.ts
+++ b/apps/frontend/user-home/state/user/achievements.svelte.ts
@@ -90,8 +90,10 @@ export class DataUserAchievements {
}
const categoryIds = [achievement.categoryId];
- if (wowthingData.achievements.achievementToCategory[achievement.id]) {
- categoryIds.push(wowthingData.achievements.achievementToCategory[achievement.id]);
+ if (wowthingData.achievements.achievementToCategoryIds[achievement.id]) {
+ categoryIds.push(
+ ...wowthingData.achievements.achievementToCategoryIds[achievement.id]
+ );
}
for (const categoryId of categoryIds) {
@@ -153,6 +155,9 @@ export class DataUserAchievements {
console.timeEnd('DataUserAchievements._derivedStats');
+ // console.log(cheevs);
+ // console.log(wowthingData.achievements.achievementToCategoryIds);
+
return {
categories: cheevs,
recent: all.slice(0, 100).map(([, id]) => id),
diff --git a/apps/frontend/utils/characters/use-character-filter.ts b/apps/frontend/utils/characters/use-character-filter.ts
index 1bcdcc139..4b4316012 100644
--- a/apps/frontend/utils/characters/use-character-filter.ts
+++ b/apps/frontend/utils/characters/use-character-filter.ts
@@ -276,6 +276,7 @@ const professionSlugMap: Record = {
herb: 'herbalism',
insc: 'inscription',
jc: 'jewelcrafting',
+ jewel: 'jewelcrafting',
mine: 'mining',
scribe: 'inscription',
skin: 'skinning',
diff --git a/apps/frontend/utils/get-character-sort-func.ts b/apps/frontend/utils/get-character-sort-func.ts
index a61823aac..f5a03b0ac 100644
--- a/apps/frontend/utils/get-character-sort-func.ts
+++ b/apps/frontend/utils/get-character-sort-func.ts
@@ -97,6 +97,9 @@ export const getCharacterSortFunc = (prefixFunc?: SortValueFunction, viewSortBy?
(levelData.level > 10 ? 9 - levelData.partial : 0).toString(),
].join('.')
);
+ } else if (thing === 'levelBand') {
+ const levelData = getCharacterLevel(char);
+ out.push(leftPad(Math.floor(levelData.level % 10), 2, '0'));
} else if (thing === 'mplusrating') {
const rating =
char.mythicPlusSeasonScores?.[Constants.mythicPlusSeason] ||
diff --git a/apps/tool/Data/IgnoredSkillLineAbilities.cs b/apps/tool/Data/IgnoredSkillLineAbilities.cs
index ed274a082..d99218176 100644
--- a/apps/tool/Data/IgnoredSkillLineAbilities.cs
+++ b/apps/tool/Data/IgnoredSkillLineAbilities.cs
@@ -214,6 +214,7 @@ public static partial class Hardcoded
1261938, // Mid ??
// Inscription
+ 127475, // MoP Incarnadine Ink
130407, // MoP Mystery of the Mists
176513, // WoD Draenor Merchant Order
178550, // WoD Borrow Draenic Mortar
@@ -222,7 +223,10 @@ public static partial class Hardcoded
1230063, // Mid ??
// Jewelcrafting
- 25614, // Silver Rose Pendant
+ 25614, // TBC Silver Rose Pendant
+ 26918, // TBC Arcanite Sword Pendant
+ 26920, // TBC Blood Crown
+ 32810, // TBC Primal Stone Statue
407161, // Immaculate Coalescing Dracothyst (temporary legendary craft)
// Leatherworking
diff --git a/apps/tool/Tools/StaticTool.cs b/apps/tool/Tools/StaticTool.cs
index 0357a7288..c9df9d167 100644
--- a/apps/tool/Tools/StaticTool.cs
+++ b/apps/tool/Tools/StaticTool.cs
@@ -297,8 +297,9 @@ public async Task Run()
_reagents = await LoadProfessionReagents();
var professions = await LoadProfessions(traits);
+ // 33388 is a riding skill
cacheData.ItemToRequiredAbility = _itemMap.Values
- .Where(item => item.RequiredAbility > 0)
+ .Where(item => item.RequiredAbility > 0 && item.RequiredAbility != 33388)
.ToDictionary(
item => item.Id,
item => item.RequiredAbility
@@ -309,7 +310,8 @@ public async Task Run()
{
if (cacheData.ItemToRequiredAbility.ContainsKey(kvp.Key))
{
- ToolContext.Logger.Warning("ItemToRequiredAbility already exists: {key} {value}", kvp.Key, kvp.Value);
+ ToolContext.Logger.Warning("ItemToRequiredAbility already exists: {key} = {current} !! {value}",
+ kvp.Key, cacheData.ItemToRequiredAbility[kvp.Key], kvp.Value);
}
else
{
@@ -602,10 +604,10 @@ private async Task> LoadArtifacts(Language language)
// skipping weird test artifacts
foreach (var artifact in artifacts.Where(artifact => artifact.ID is not (74 or 80 or 81 or 82)))
{
- ToolContext.Logger.Information("artifact {id} {name}", artifact.ID, artifact.Name);
+ // ToolContext.Logger.Information("artifact {id} {name}", artifact.ID, artifact.Name);
if (!artifactAppearanceSetsByArtifact.TryGetValue(artifact.ID, out var appearanceSets))
{
- ToolContext.Logger.Warning("- no appearance sets!");
+ // ToolContext.Logger.Warning("- no appearance sets!");
continue;
}
@@ -613,10 +615,10 @@ private async Task> LoadArtifacts(Language language)
foreach (var appearanceSet in appearanceSets.OrderBy(appearanceSet => appearanceSet.DisplayIndex))
{
- ToolContext.Logger.Information("- set {id} {name}", appearanceSet.ID, appearanceSet.Name);
+ // ToolContext.Logger.Information("- set {id} {name}", appearanceSet.ID, appearanceSet.Name);
if (!artifactAppearancesBySet.TryGetValue(appearanceSet.ID, out var appearances))
{
- ToolContext.Logger.Warning("- - no appearances!");
+ // ToolContext.Logger.Warning("- - no appearances!");
continue;
}
@@ -625,7 +627,7 @@ private async Task> LoadArtifacts(Language language)
var seenModifiers = new HashSet();
foreach (var appearance in appearances.OrderBy(appearance => appearance.DisplayIndex))
{
- ToolContext.Logger.Information("- - appearance {id} {name} => modifier {mod}", appearance.ID, appearance.Name, appearance.ItemAppearanceModifierID);
+ // ToolContext.Logger.Information("- - appearance {id} {name} => modifier {mod}", appearance.ID, appearance.Name, appearance.ItemAppearanceModifierID);
if (!seenModifiers.Add(appearance.ItemAppearanceModifierID))
{
@@ -699,7 +701,7 @@ private async Task> LoadDecor()
{
if (!decorIdToSubcategoryId.TryGetValue(houseDecor.ID, out var outSubcategoryIds))
{
- ToolContext.Logger.Warning("Decor {d} has no sub-category ids!", houseDecor.ID);
+ // ToolContext.Logger.Warning("Decor {d} has no sub-category ids!", houseDecor.ID);
continue;
}
@@ -876,7 +878,7 @@ private async Task>> LoadProfessions(
{
if (!categoriesByProfession.TryGetValue(professionId, out var professionCategories))
{
- ToolContext.Logger.Warning("No profession categories for profession {id}", professionId);
+ // ToolContext.Logger.Warning("No profession categories for profession {id}", professionId);
continue;
}
@@ -1560,12 +1562,12 @@ private static async Task>> LoadTraits()
foreach ((int skillLineId, var dumpTrees) in skillLineIdToTraitTrees.OrderBy(kvp => kvp.Key))
{
- ToolContext.Logger.Information("SkillLine {id}", skillLineId);
+ // ToolContext.Logger.Information("SkillLine {id}", skillLineId);
var outTrees = ret[skillLineId] = new();
foreach (var dumpTree in dumpTrees)
{
- ToolContext.Logger.Information(" Tree {tree}", dumpTree.ID);
+ // ToolContext.Logger.Information(" Tree {tree}", dumpTree.ID);
if (dumpTree.FirstTraitNodeID == 0)
{
@@ -1584,7 +1586,7 @@ private static async Task>> LoadTraits()
while (nodeIdQueue.Count > 0)
{
int nodeId = nodeIdQueue.Dequeue();
- ToolContext.Logger.Information(" Node: {id}", nodeId);
+ // ToolContext.Logger.Information(" Node: {id}", nodeId);
var traitNode = traitNodeById[nodeId];
@@ -1631,7 +1633,7 @@ private static async Task>> LoadTraits()
}
else
{
- ToolContext.Logger.Warning(" No TraitCond->TraitNode for {cond}", cond.ID);
+ // ToolContext.Logger.Warning(" No TraitCond->TraitNode for {cond}", cond.ID);
}
}
}