+
-
20 samples
+
6x5 samples
-
+
-
50 samples
+
6x20 samples
-
+
-
100 samples
+
6x50 samples
diff --git a/src/components/__tests__/achievements.spec.ts b/src/components/__tests__/achievements.spec.ts
index d047fd0..e6af386 100644
--- a/src/components/__tests__/achievements.spec.ts
+++ b/src/components/__tests__/achievements.spec.ts
@@ -1,7 +1,7 @@
import {describe, it, expect} from 'vitest';
import {mount} from '@vue/test-utils';
import {useAchievements} from '@/hooks/achievements';
-import {AchievementLevel, type Achievements} from '@/utils/types';
+import {AchievementLevel, Category, type Achievements, type Favorites} from '@/utils/types';
import {take} from 'remeda';
import {ALL_VEGGIES, BEANS, FRUITS, GRAINS, LEAFIES, ROOTS, VEGETABLES} from '@/utils/constants';
@@ -31,6 +31,15 @@ const defaultAchievements: Achievements = {
thirtyVeggies: AchievementLevel.NoAchievement,
};
+const getFavorites = (amount: number = 0) =>
+ Object.values(Category).reduce(
+ (acc, category) => ({
+ ...acc,
+ [category]: amount ? [['veggie', amount]] : [],
+ }),
+ {} as Favorites,
+ );
+
describe('achievements', () => {
it('sets initial status', async () => {
const {achievements} = await withSetup(useAchievements);
@@ -39,153 +48,153 @@ describe('achievements', () => {
it('advances completionist', async () => {
const {advanceAchievements, achievements} = await withSetup(useAchievements);
- advanceAchievements(0, [...Array(39)], 0, 0, 0, 0);
+ advanceAchievements(0, [...Array(39)], 0, 0, 0, getFavorites());
expect(achievements.value.completionist).toEqual(AchievementLevel.NoAchievement);
- advanceAchievements(0, [...Array(40)], 0, 0, 0, 0);
+ advanceAchievements(0, [...Array(40)], 0, 0, 0, getFavorites());
expect(achievements.value.completionist).toBe(AchievementLevel.Bronze);
- advanceAchievements(0, [...Array(80)], 0, 0, 0, 0);
+ advanceAchievements(0, [...Array(80)], 0, 0, 0, getFavorites());
expect(achievements.value.completionist).toBe(AchievementLevel.Silver);
- advanceAchievements(0, [...Array(150)], 0, 0, 0, 0);
+ advanceAchievements(0, [...Array(150)], 0, 0, 0, getFavorites());
expect(achievements.value.completionist).toBe(AchievementLevel.Gold);
});
it('goes straight to silver', async () => {
const {advanceAchievements, achievements} = await withSetup(useAchievements);
- advanceAchievements(0, [...Array(80)], 0, 0, 0, 0);
+ advanceAchievements(0, [...Array(80)], 0, 0, 0, getFavorites());
expect(achievements.value.completionist).toBe(AchievementLevel.Silver);
});
it('completionist goes straight to gold', async () => {
const {advanceAchievements, achievements} = await withSetup(useAchievements);
- advanceAchievements(0, [...Array(150)], 0, 0, 0, 0);
+ advanceAchievements(0, [...Array(150)], 0, 0, 0, getFavorites());
expect(achievements.value.completionist).toBe(AchievementLevel.Gold);
});
it('advances experimenterFruit', async () => {
const {advanceAchievements, achievements} = await withSetup(useAchievements);
- advanceAchievements(0, take(FRUITS, 14), 0, 0, 0, 0);
+ advanceAchievements(0, take(FRUITS, 14), 0, 0, 0, getFavorites());
expect(achievements.value.experimenterFruit).toEqual(AchievementLevel.NoAchievement);
- advanceAchievements(0, take(FRUITS, 15), 0, 0, 0, 0);
+ advanceAchievements(0, take(FRUITS, 15), 0, 0, 0, getFavorites());
expect(achievements.value.experimenterFruit).toBe(AchievementLevel.Gold);
});
it('experimenter goes straight to gold', async () => {
const {advanceAchievements, achievements} = await withSetup(useAchievements);
- advanceAchievements(0, take(FRUITS, 15), 0, 0, 0, 0);
+ advanceAchievements(0, take(FRUITS, 15), 0, 0, 0, getFavorites());
expect(achievements.value.experimenterFruit).toBe(AchievementLevel.Gold);
});
it('advances experimenterVegetable', async () => {
const {advanceAchievements, achievements} = await withSetup(useAchievements);
- advanceAchievements(0, take(VEGETABLES, 14), 0, 0, 0, 0);
+ advanceAchievements(0, take(VEGETABLES, 14), 0, 0, 0, getFavorites());
expect(achievements.value.experimenterVegetable).toEqual(AchievementLevel.NoAchievement);
- advanceAchievements(0, take(VEGETABLES, 15), 0, 0, 0, 0);
+ advanceAchievements(0, take(VEGETABLES, 15), 0, 0, 0, getFavorites());
expect(achievements.value.experimenterVegetable).toBe(AchievementLevel.Gold);
});
it('advances experimenterLeafy', async () => {
const {advanceAchievements, achievements} = await withSetup(useAchievements);
- advanceAchievements(0, take(LEAFIES, 14), 0, 0, 0, 0);
+ advanceAchievements(0, take(LEAFIES, 14), 0, 0, 0, getFavorites());
expect(achievements.value.experimenterLeafy).toEqual(AchievementLevel.NoAchievement);
- advanceAchievements(0, take(LEAFIES, 15), 0, 0, 0, 0);
+ advanceAchievements(0, take(LEAFIES, 15), 0, 0, 0, getFavorites());
expect(achievements.value.experimenterLeafy).toBe(AchievementLevel.Gold);
});
it('advances experimenterBean', async () => {
const {advanceAchievements, achievements} = await withSetup(useAchievements);
- advanceAchievements(0, take(BEANS, 14), 0, 0, 0, 0);
+ advanceAchievements(0, take(BEANS, 14), 0, 0, 0, getFavorites());
expect(achievements.value.experimenterBean).toEqual(AchievementLevel.NoAchievement);
- advanceAchievements(0, take(BEANS, 15), 0, 0, 0, 0);
+ advanceAchievements(0, take(BEANS, 15), 0, 0, 0, getFavorites());
expect(achievements.value.experimenterBean).toBe(AchievementLevel.Gold);
});
it('advances experimenterRoot', async () => {
const {advanceAchievements, achievements} = await withSetup(useAchievements);
- advanceAchievements(0, take(ROOTS, 14), 0, 0, 0, 0);
+ advanceAchievements(0, take(ROOTS, 14), 0, 0, 0, getFavorites());
expect(achievements.value.experimenterRoot).toEqual(AchievementLevel.NoAchievement);
- advanceAchievements(0, take(ROOTS, 15), 0, 0, 0, 0);
+ advanceAchievements(0, take(ROOTS, 15), 0, 0, 0, getFavorites());
expect(achievements.value.experimenterRoot).toBe(AchievementLevel.Gold);
});
it('advances experimenterGrain', async () => {
const {advanceAchievements, achievements} = await withSetup(useAchievements);
- advanceAchievements(0, take(GRAINS, 14), 0, 0, 0, 0);
+ advanceAchievements(0, take(GRAINS, 14), 0, 0, 0, getFavorites());
expect(achievements.value.experimenterGrain).toEqual(AchievementLevel.NoAchievement);
- advanceAchievements(0, take(GRAINS, 15), 0, 0, 0, 0);
+ advanceAchievements(0, take(GRAINS, 15), 0, 0, 0, getFavorites());
expect(achievements.value.experimenterGrain).toBe(AchievementLevel.Gold);
});
it('advances hot streak', async () => {
const {advanceAchievements, achievements} = await withSetup(useAchievements);
- advanceAchievements(0, [], 4, 0, 0, 0);
+ advanceAchievements(0, [], 4, 0, 0, getFavorites());
expect(achievements.value.hotStreak).toEqual(AchievementLevel.NoAchievement);
- advanceAchievements(0, [], 5, 0, 0, 0);
+ advanceAchievements(0, [], 5, 0, 0, getFavorites());
expect(achievements.value.hotStreak).toEqual(AchievementLevel.Bronze);
- advanceAchievements(0, [], 10, 0, 0, 0);
+ advanceAchievements(0, [], 10, 0, 0, getFavorites());
expect(achievements.value.hotStreak).toEqual(AchievementLevel.Silver);
- advanceAchievements(0, [], 20, 0, 0, 0);
+ advanceAchievements(0, [], 20, 0, 0, getFavorites());
expect(achievements.value.hotStreak).toEqual(AchievementLevel.Gold);
});
it('advances committed', async () => {
const {advanceAchievements, achievements} = await withSetup(useAchievements);
- advanceAchievements(0, [], 0, 11, 0, 0);
+ advanceAchievements(0, [], 0, 11, 0, getFavorites());
expect(achievements.value.committed).toEqual(AchievementLevel.NoAchievement);
- advanceAchievements(0, [], 0, 12, 0, 0);
+ advanceAchievements(0, [], 0, 12, 0, getFavorites());
expect(achievements.value.committed).toEqual(AchievementLevel.Bronze);
- advanceAchievements(0, [], 0, 26, 0, 0);
+ advanceAchievements(0, [], 0, 26, 0, getFavorites());
expect(achievements.value.committed).toEqual(AchievementLevel.Silver);
- advanceAchievements(0, [], 0, 52, 0, 0);
+ advanceAchievements(0, [], 0, 52, 0, getFavorites());
expect(achievements.value.committed).toEqual(AchievementLevel.Gold);
});
it('advances challengeAccepted', async () => {
const {advanceAchievements, achievements} = await withSetup(useAchievements);
- advanceAchievements(0, [], 0, 0, 4, 0);
+ advanceAchievements(0, [], 0, 0, 4, getFavorites());
expect(achievements.value.challengeAccepted).toEqual(AchievementLevel.NoAchievement);
- advanceAchievements(0, [], 0, 0, 5, 0);
+ advanceAchievements(0, [], 0, 0, 5, getFavorites());
expect(achievements.value.challengeAccepted).toEqual(AchievementLevel.Bronze);
- advanceAchievements(0, [], 0, 0, 10, 0);
+ advanceAchievements(0, [], 0, 0, 10, getFavorites());
expect(achievements.value.challengeAccepted).toEqual(AchievementLevel.Silver);
- advanceAchievements(0, [], 0, 0, 20, 0);
+ advanceAchievements(0, [], 0, 0, 20, getFavorites());
expect(achievements.value.challengeAccepted).toEqual(AchievementLevel.Gold);
});
it('advances thirtyVeggies', async () => {
const {advanceAchievements, achievements} = await withSetup(useAchievements);
- advanceAchievements(29, [], 0, 0, 0, 0);
+ advanceAchievements(29, [], 0, 0, 0, getFavorites());
expect(achievements.value.thirtyVeggies).toEqual(AchievementLevel.NoAchievement);
- advanceAchievements(30, [], 0, 0, 0, 0);
+ advanceAchievements(30, [], 0, 0, 0, getFavorites());
expect(achievements.value.thirtyVeggies).toBe(AchievementLevel.Gold);
- advanceAchievements(40, [], 0, 0, 0, 0);
+ advanceAchievements(40, [], 0, 0, 0, getFavorites());
expect(achievements.value.thirtyVeggies).toBe(AchievementLevel.Platinum);
});
it('resets thirtyVeggies', async () => {
const {advanceAchievements, achievements} = await withSetup(useAchievements);
- advanceAchievements(30, [], 0, 0, 0, 0);
+ advanceAchievements(30, [], 0, 0, 0, getFavorites());
expect(achievements.value.thirtyVeggies).toEqual(AchievementLevel.Gold);
- advanceAchievements(0, [], 0, 0, 0, 0);
+ advanceAchievements(0, [], 0, 0, 0, getFavorites());
expect(achievements.value.thirtyVeggies).toBe(AchievementLevel.NoAchievement);
- advanceAchievements(40, [], 0, 0, 0, 0);
+ advanceAchievements(40, [], 0, 0, 0, getFavorites());
expect(achievements.value.thirtyVeggies).toEqual(AchievementLevel.Platinum);
- advanceAchievements(0, [], 0, 0, 0, 0);
+ advanceAchievements(0, [], 0, 0, 0, getFavorites());
expect(achievements.value.thirtyVeggies).toBe(AchievementLevel.NoAchievement);
- advanceAchievements(40, [], 0, 0, 0, 0);
+ advanceAchievements(40, [], 0, 0, 0, getFavorites());
expect(achievements.value.thirtyVeggies).toEqual(AchievementLevel.Platinum);
- advanceAchievements(39, [], 0, 0, 0, 0);
+ advanceAchievements(39, [], 0, 0, 0, getFavorites());
expect(achievements.value.thirtyVeggies).toBe(AchievementLevel.Gold);
});
it('advances favorite', async () => {
const {advanceAchievements, achievements} = await withSetup(useAchievements);
- advanceAchievements(0, [], 0, 0, 0, 19);
+ advanceAchievements(0, [], 0, 0, 0, getFavorites(4));
expect(achievements.value.favorite).toEqual(AchievementLevel.NoAchievement);
- advanceAchievements(0, [], 0, 0, 0, 20);
+ advanceAchievements(0, [], 0, 0, 0, getFavorites(5));
expect(achievements.value.favorite).toEqual(AchievementLevel.Bronze);
- advanceAchievements(0, [], 0, 0, 0, 50);
+ advanceAchievements(0, [], 0, 0, 0, getFavorites(20));
expect(achievements.value.favorite).toEqual(AchievementLevel.Silver);
- advanceAchievements(0, [], 0, 0, 0, 100);
+ advanceAchievements(0, [], 0, 0, 0, getFavorites(50));
expect(achievements.value.favorite).toEqual(AchievementLevel.Gold);
});
@@ -205,7 +214,7 @@ describe('achievements', () => {
thirtyVeggies: AchievementLevel.Platinum,
};
const {advanceAchievements, achievements, resetAchievements} = await withSetup(useAchievements);
- advanceAchievements(40, ALL_VEGGIES, 30, 52, 20, 100);
+ advanceAchievements(40, ALL_VEGGIES, 30, 52, 20, getFavorites(50));
expect(achievements.value).toEqual(expectedAchievements);
resetAchievements();
expect(achievements.value).toEqual(defaultAchievements);
diff --git a/src/components/__tests__/activityStore.spec.ts b/src/components/__tests__/activityStore.spec.ts
index 3040390..ae39261 100644
--- a/src/components/__tests__/activityStore.spec.ts
+++ b/src/components/__tests__/activityStore.spec.ts
@@ -503,30 +503,6 @@ describe('activityStore', () => {
});
});
- it('returns max amount of single veggie logged', () => {
- activityStore.startDate = threeWeeksAgo;
- activityStore.weeks.push(
- {
- startDate: threeWeeksAgo,
- veggies: ['apple', 'edamame', 'portobello'],
- },
- {
- startDate: twoWeeksAgo,
- veggies: ['apple', 'edamame'],
- },
- {
- startDate: lastWeek,
- veggies: ['wheat'],
- },
- {
- startDate: thisWeek,
- veggies: ['apple', 'portobello', 'black trumpet mushroom'],
- },
- );
-
- expect(activityStore.maxAmount).toBe(3);
- });
-
it('resets the store', () => {
activityStore.startDate = thisWeek;
activityStore.weeks.push({
diff --git a/src/hooks/achievements.ts b/src/hooks/achievements.ts
index be7cbc6..b301dd1 100644
--- a/src/hooks/achievements.ts
+++ b/src/hooks/achievements.ts
@@ -3,7 +3,7 @@ import {intersection, isDeepEqual, mapValues} from 'remeda';
import {createActor, setup, type MachineContext} from 'xstate';
import type {GuardArgs} from 'xstate/guards';
import {BEANS, FRUITS, GRAINS, LEAFIES, ROOTS, VEGETABLES} from '@/utils/constants';
-import type {Achievements} from '@/utils/types';
+import type {Achievements, Favorites} from '@/utils/types';
type AdvanceEvent = {
type: 'ADVANCE';
@@ -12,7 +12,7 @@ type AdvanceEvent = {
completedChallenges: number;
hotStreakLength: number;
totalWeeks: number;
- maxAmount: number;
+ favorites: Favorites;
};
type ResetEvent = {
@@ -39,7 +39,7 @@ const guards = {
favorite:
(threshold: number) =>
({event}: GuardArgs
) =>
- event.maxAmount >= threshold,
+ Object.values(event.favorites).every((favorites) => favorites[0]?.[1] >= threshold),
hotStreak:
(threshold: number) =>
({event}: GuardArgs) =>
@@ -297,15 +297,15 @@ export function useAchievements() {
ADVANCE: [
{
target: '3',
- guard: guards.favorite(100),
+ guard: guards.favorite(50),
},
{
target: '2',
- guard: guards.favorite(50),
+ guard: guards.favorite(20),
},
{
target: '1',
- guard: guards.favorite(20),
+ guard: guards.favorite(5),
},
],
},
@@ -315,11 +315,11 @@ export function useAchievements() {
ADVANCE: [
{
target: '3',
- guard: guards.favorite(100),
+ guard: guards.favorite(50),
},
{
target: '2',
- guard: guards.favorite(50),
+ guard: guards.favorite(20),
},
],
},
@@ -328,7 +328,7 @@ export function useAchievements() {
on: {
ADVANCE: {
target: '3',
- guard: guards.favorite(100),
+ guard: guards.favorite(50),
},
},
},
@@ -454,7 +454,7 @@ export function useAchievements() {
hotStreakLength: number,
totalWeeks: number,
completedChallenges: number,
- maxAmount: number,
+ favorites: Favorites,
) =>
actor.send({
type: 'ADVANCE',
@@ -463,7 +463,7 @@ export function useAchievements() {
hotStreakLength,
totalWeeks,
completedChallenges,
- maxAmount,
+ favorites,
}),
resetAchievements: () => actor.send({type: 'RESET'}),
};
diff --git a/src/i18n/en.json b/src/i18n/en.json
index 6738a27..2ed3bdf 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -62,11 +62,11 @@
},
"favorite": {
"title": "Playing Favorites",
- "ariaLabel": "{0} repeat uses of same veggie",
- "badgeText": "{0} samples",
- "1": "You have sampled the same veggie 20 times, earning you the bronze achievement!",
- "2": "You have sampled the same veggie 50 times, earning you the silver achievement!",
- "3": "You have sampled the same veggie 100, earning you the gold achievement!"
+ "ariaLabel": "{0} uses of a veggie in all categories",
+ "badgeText": "6x{0} samples",
+ "1": "You have sampled your favorite veggies at least 5 times in each category, earning you the bronze achievement!",
+ "2": "You have sampled your favorite veggies at least 20 times in each category, earning you the silver achievement!",
+ "3": "You have sampled your favorite veggies at least 100 times in each category, earning you the gold achievement!"
},
"hotStreak": {
"title": "Hot Streak",
diff --git a/src/i18n/fi.json b/src/i18n/fi.json
index 23ba31e..3a77114 100644
--- a/src/i18n/fi.json
+++ b/src/i18n/fi.json
@@ -61,12 +61,12 @@
"3": "Olet kokeillut 15:tä erilaista kasvista ansaiten tämän palkinnon!"
},
"favorite": {
- "title": "Oma suosikki",
- "ariaLabel": "Sama kasvis {0} kertaa",
- "badgeText": "{0} kokeilua",
- "1": "Olet kokeillut samaa kasvista 20 kertaa ja ansainnut pronssisen palkinnon!",
- "2": "Olet kokeillut samaa kasvista 50 kertaa ja ansainnut hopeisen palkinnon!",
- "3": "Olet kokeillut samaa kasvista 100 kertaa ja ansainnut kultaisen palkinnon!"
+ "title": "Omat suosikit",
+ "ariaLabel": "Yksi kasvis {0} kertaa joka ryhmässä",
+ "badgeText": "6x{0} kokeilua",
+ "1": "Olet kokeillut suosikkikasviksiasi vähintään viisi kertaa joka ryhmässä, ansaiten pronssisen palkinnon!",
+ "2": "Olet kokeillut suosikkikasviksiasi vähintään 20 kertaa joka ryhmässä, ansaiten hopeisen palkinnon!",
+ "3": "Olet kokeillut suosikkikasviksiasi vähintään 50 kertaa joka ryhmässä, ansaiten kultaisen palkinnon!"
},
"hotStreak": {
"title": "Putki päällä",
diff --git a/src/stores/activityStore.ts b/src/stores/activityStore.ts
index 7055ef4..b686cce 100644
--- a/src/stores/activityStore.ts
+++ b/src/stores/activityStore.ts
@@ -2,20 +2,7 @@ import {computed, ref, watchEffect} from 'vue';
import {defineStore} from 'pinia';
import {useNow, useStorage} from '@vueuse/core';
import {DateTime} from 'luxon';
-import {
- difference,
- entries,
- filter,
- first,
- groupBy,
- map,
- pipe,
- prop,
- sortBy,
- take,
- unique,
- values,
-} from 'remeda';
+import {difference, entries, filter, groupBy, map, pipe, prop, sortBy, take, unique} from 'remeda';
import {Category, type Favorites, type Challenge, type Week} from '@/utils/types';
import {dateParser, getCategoryForVeggie, getRandomVeggie} from '@/utils/helpers';
@@ -155,17 +142,6 @@ export const useActivityStore = defineStore('activity', () => {
),
);
- const maxAmount = computed(
- () =>
- pipe(
- allVeggies.value,
- groupBy((veggie) => veggie),
- values(),
- sortBy([({length}) => length, 'desc']),
- first,
- )?.length ?? 0,
- );
-
// Actions
const toggleVeggie = (targetVeggie: string) => {
const weekStart = currentDate.value.startOf('week');
@@ -202,7 +178,6 @@ export const useActivityStore = defineStore('activity', () => {
favorites,
getWeekStarts,
hotStreak,
- maxAmount,
over30Veggies,
startDate,
suggestions,
diff --git a/src/stores/appStateStore.ts b/src/stores/appStateStore.ts
index 46935ce..d2e40d3 100644
--- a/src/stores/appStateStore.ts
+++ b/src/stores/appStateStore.ts
@@ -12,7 +12,7 @@ type Message = {
export const useAppStateStore = defineStore('appState', () => {
const {advanceAchievements, achievements, resetAchievements} = useAchievements();
- const {currentVeggies, uniqueVeggies, hotStreak, weeks, completedChallenges, maxAmount} =
+ const {currentVeggies, uniqueVeggies, hotStreak, weeks, completedChallenges, favorites} =
storeToRefs(useActivityStore());
watchEffect(() =>
@@ -22,7 +22,7 @@ export const useAppStateStore = defineStore('appState', () => {
hotStreak.value,
weeks.value.length,
completedChallenges.value,
- maxAmount.value,
+ favorites.value,
),
);