diff --git a/src/completionist.ts b/src/completionist.ts index 461769f..cf727cd 100644 --- a/src/completionist.ts +++ b/src/completionist.ts @@ -24,7 +24,7 @@ export function getFunDailies(dailies: gw2.Daily): void { getAchievements(achievements) .then(axiosData) - .then(cleanUpFractalDailies) + .then(cleanUpDailyNames) .then(populateDailies) .then(arrangeFractalDailies) .catch(error); @@ -73,7 +73,7 @@ function axiosData(response: AxiosResponse): T { return response.data; } -export function cleanUpFractalDailies( +export function cleanUpDailyNames( data: ReadonlyArray, ): ReadonlyArray { const dailies = [... data]; @@ -82,12 +82,42 @@ export function cleanUpFractalDailies( const a = dailies[index]; if (fractal.isRecommended(a)) { dailies[index] = fractal.fixRecommendedName(a); + } else if (isDailyActivityParticipation(a)) { + const today = new Date(); + dailies[index] = fixDailyActivityName(a, today); } } return dailies; } +export function isDailyActivityParticipation( + a: Readonly, +): boolean { + return a.id === 1939; +} + +export function fixDailyActivityName( + a: Readonly, + date: Date, +): gw2.Achievement { + return { + bits: a.bits, + description: a.description, + flags: a.flags, + icon: a.icon, + id: a.id, + locked_text: a.locked_text, + name: `${a.name} (${gw2.activityFor(date)})`, + point_cap: a.point_cap, + prerequisites: a.prerequisites, + requirement: a.requirement, + rewards: a.rewards, + tiers: a.tiers, + type: a.type, + }; +} + export function icon(a: { readonly icon?: string }): string { return a.icon || "https://render.guildwars2.com/file/483E3939D1A7010BDEA2970FB27703CAAD5FBB0F/42684.png"; } diff --git a/src/gw2.ts b/src/gw2.ts index e57453e..a1095a5 100644 --- a/src/gw2.ts +++ b/src/gw2.ts @@ -72,3 +72,24 @@ export interface Achievement { export function id(v: { readonly id: number }): number { return v.id; } + +export const enum Activity { + CrabToss = "Crab Toss", + KegBrawl = "Keg Brawl", + SanctumSprint = "Sanctum Sprint", + SouthsunSurvival = "Southsun Survival", +} + +const activityCycle = [ + Activity.KegBrawl, + Activity.CrabToss, + Activity.SanctumSprint, + Activity.SouthsunSurvival, + Activity.CrabToss, + Activity.SanctumSprint, + Activity.SouthsunSurvival, +]; + +export function activityFor(date: Date): Activity { + return activityCycle[date.getUTCDay()]; +} diff --git a/test/completionist.ts b/test/completionist.ts index 664c955..62445e0 100644 --- a/test/completionist.ts +++ b/test/completionist.ts @@ -2,6 +2,7 @@ import test from "ava"; import { JSDOM } from "jsdom"; import * as lib from "../src/completionist"; import * as helper from "./helpers/helper"; +import mkmacro from "./helpers/mkmacro"; const jsdom = new JSDOM(``, {}); function el(): HTMLElement { @@ -86,26 +87,26 @@ test("icon() returns icon property value for truthy icon property", (t) => { t.regex(lib.icon({ icon: "foo" }), /foo/); }); -test("cleanUpFractalDailies() returns empty list on empty list input", (t) => { - const clean = lib.cleanUpFractalDailies([]); +test("cleanUpDailyNames() returns empty list on empty list input", (t) => { + const clean = lib.cleanUpDailyNames([]); t.deepEqual(clean, []); }); -test("cleanUpFractalDailies() leaves names of regular achievements alone", (t) => { +test("cleanUpDailyNames() leaves names of regular achievements alone", (t) => { const someRegularDaily = helper.achievementWithName("42"); t.is(someRegularDaily.name, "42", "Precondition"); - const clean = lib.cleanUpFractalDailies([someRegularDaily]); + const clean = lib.cleanUpDailyNames([someRegularDaily]); t.is(clean[0].name, someRegularDaily.name, "Regular achievement should be unchanged"); }); -test("cleanUpFractalDailies() fixes Recommended Fractal names", (t) => { +test("cleanUpDailyNames() fixes Recommended Fractal names", (t) => { const someRegularDaily = helper.achievementWithName("27"); const someRecommendedFractal = helper.someRecommendedFractal("27"); t.notRegex(someRecommendedFractal.name, /Snowblind/, "Precondition"); - const clean = lib.cleanUpFractalDailies([ + const clean = lib.cleanUpDailyNames([ someRecommendedFractal, someRegularDaily, ]); @@ -114,6 +115,16 @@ test("cleanUpFractalDailies() fixes Recommended Fractal names", (t) => { t.not(clean[1].name, clean[0].name, "Regular achievement should be left alone"); }); +test("cleanUpDailyNames() fixes Daily Activity names", (t) => { + const activityPattern = /Keg|Crab|Sprint|Survival/; + const someDailyActivity = helper.achievementWithId(1939); + t.notRegex(someDailyActivity.name, activityPattern, "Precondition"); + + const clean = lib.cleanUpDailyNames([someDailyActivity]); + + t.regex(clean[0].name, activityPattern, "Daily Activity name should be cleaned up"); +}); + test("fullyLevelled() returns true for max level 80", (t) => { const pos = { id: 47, @@ -141,3 +152,35 @@ test("fullyLevelled() returns false for max level other than 80", (t) => { const res = lib.fullyLevelled(neg); t.false(res); }); + +test("Achievement 1939 is Daily Activity Participation", (t) => { + t.true(lib.isDailyActivityParticipation(helper.achievementWithId(1939))); +}); + +test("Other achievements are not Daily Activity Participation", (t) => { + t.false(lib.isDailyActivityParticipation(helper.achievementWithId(1938))); + t.false(lib.isDailyActivityParticipation(helper.achievementWithId(1940))); +}); + +const dailyActivity = mkmacro((t, input: string, expected: RegExp) => { + const dayOfWeek = new Date(input); + + const activity = lib.fixDailyActivityName( + helper.achievementWithId(1939), + dayOfWeek); + + t.regex(activity.name, expected); +}); + +test("Daily Activity, Sunday, is Keg Brawl", dailyActivity, "2018-01-07", /Keg/); +test("Daily Activity, Monday, is Crab Toss", dailyActivity, "2018-01-08", /Crab/); +test("Daily Activity, Tuesday, is Sanctum Sprint", dailyActivity, "2018-01-09", /Sanctum/); +test("Daily Activity, Tuesday, is not Keg Brawl", (t) => { + const someTuesday = new Date("2018-01-09"); + + const activity = lib.fixDailyActivityName( + helper.achievementWithId(1939), + someTuesday); + + t.notRegex(activity.name, /Keg/); +}); diff --git a/test/gw2.ts b/test/gw2.ts index 11a1d8e..62dc612 100644 --- a/test/gw2.ts +++ b/test/gw2.ts @@ -1,5 +1,5 @@ import test from "ava"; -import { id } from "../src/gw2"; +import { Activity, activityFor, id } from "../src/gw2"; import mkmacro from "./helpers/mkmacro"; const macro = mkmacro((t, input, expected) => { @@ -10,3 +10,18 @@ test("gw2.id of", macro, -1, -1); test("gw2.id of", macro, 0, 0); test("gw2.id of", macro, 1, 1); test("gw2.id of", macro, 2, 2); + +const dailyActivity = mkmacro((t, dayOfWeek: string, expected: Activity) => { + const activity = activityFor(new Date(dayOfWeek)); + + t.is(activity, expected); +}); + +test("gw2.activityFor Sunday is Keg Brawl", dailyActivity, "2018-01-07", Activity.KegBrawl); +test("gw2.activityFor Monday is Crab Toss", dailyActivity, "2018-01-08", Activity.CrabToss); +test("gw2.activityFor Tuesday is Sanctum Sprint", dailyActivity, "2018-01-09", Activity.SanctumSprint); +test("gw2.activityFor Wednesday is Southsun Survival", dailyActivity, "2018-01-10", Activity.SouthsunSurvival); +test("gw2.activityFor Thursday is Crab Toss", dailyActivity, "2018-01-11", Activity.CrabToss); +test("gw2.activityFor Friday is Sanctum Sprint", dailyActivity, "2018-01-12", Activity.SanctumSprint); +test("gw2.activityFor Saturday is Southsun Survival", dailyActivity, "2018-01-13", Activity.SouthsunSurvival); +test("gw2.activityFor loops around", dailyActivity, "2018-01-14", Activity.KegBrawl); diff --git a/test/helpers/helper.ts b/test/helpers/helper.ts index 9aab08f..5f6bbf2 100644 --- a/test/helpers/helper.ts +++ b/test/helpers/helper.ts @@ -30,6 +30,20 @@ export function rewardId(item: ItemId): gw2.Reward { }; } +export function achievementWithId(theId: number): gw2.Achievement { + return { + description: "foo", + flags: [], + id: theId, + locked_text: "", + name: "foobar", + requirement: "", + rewards: [], + tiers: [], + type: gw2.AchievementType.Default, + }; +} + export function achievementWithName(n: string): gw2.Achievement { return { description: "foo",