Skip to content

Commit 1c6c324

Browse files
committed
feat(sushi-bot): Implement weekly wakeup ranking achievements
1 parent 9a89662 commit 1c6c324

3 files changed

Lines changed: 138 additions & 0 deletions

File tree

achievements/achievements.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,33 @@ const achievements: Achievement[] = [
572572
condition: '週間起床ランキングで満点を獲得する',
573573
category: 'sushi-bot',
574574
},
575+
{
576+
id: 'asa-week-repdigit-1',
577+
difficulty: 'hard',
578+
title: '起床フィーバータイム',
579+
condition: '週間起床ランキングでゾロ目である3桁の得点を獲得する',
580+
category: 'sushi-bot',
581+
counter: 'asa-week-repdigit',
582+
value: 1,
583+
},
584+
{
585+
id: 'asa-week-power-of-two-1',
586+
difficulty: 'hard',
587+
title: '起床ロボット',
588+
condition: '週間起床ランキングで2の冪乗数の得点を獲得する',
589+
category: 'sushi-bot',
590+
counter: 'asa-week-power-of-two',
591+
value: 1,
592+
},
593+
{
594+
id: 'asa-week-334-1',
595+
difficulty: 'hard',
596+
title: 'なんでや',
597+
condition: '週間起床ランキングで334点を獲得する',
598+
category: 'sushi-bot',
599+
counter: 'asa-week-334',
600+
value: 1,
601+
},
575602
{
576603
id: 'first-exercise',
577604
difficulty: 'easy',

sushi-bot/index.test.ts

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,20 @@
11
import moment from 'moment';
2+
import schedule, {Job, JobCallback} from 'node-schedule';
3+
import {unlock, increment} from '../achievements';
4+
import State from '../lib/state';
5+
import {MockedStateInterface} from '../lib/__mocks__/state';
26
import sushi from './index.js';
37
import Slack from '../lib/slackMock';
48

59
vi.mock('../achievements');
610
vi.mock('moment');
711
vi.mock('../lib/state');
12+
vi.mock('node-schedule', () => ({
13+
default: {
14+
scheduleJob: vi.fn(),
15+
},
16+
scheduleJob: vi.fn(),
17+
}));
818
vi.mock('fs-extra', () => ({
919
mkdirp: vi.fn(),
1020
readFile: vi.fn(() => Promise.resolve(Buffer.from(''))),
@@ -13,11 +23,18 @@ vi.mock('fs-extra', () => ({
1323
}));
1424

1525
let slack: InstanceType<typeof Slack> = null;
26+
let scheduleCallback: JobCallback | null = null;
1627

1728
describe('sushi-bot', async () => {
1829
const originalMoment = (await vi.importActual<{default: typeof import('moment')}>('moment')).default;
1930

2031
beforeEach(async () => {
32+
vi.clearAllMocks();
33+
scheduleCallback = null;
34+
vi.mocked(schedule.scheduleJob).mockImplementation((rule, fn) => {
35+
scheduleCallback = fn;
36+
return {} as Job;
37+
});
2138
slack = new Slack();
2239
await sushi(slack);
2340

@@ -464,4 +481,89 @@ describe('sushi-bot', async () => {
464481
ts: slack.fakeTimestamp,
465482
});
466483
}));
484+
485+
describe('weekly wakeup ranking achievements', () => {
486+
beforeEach(() => {
487+
vi.mocked(slack.webClient.users.list).mockResolvedValue({
488+
ok: true,
489+
members: [
490+
{
491+
id: slack.fakeUser,
492+
name: 'fakeUser',
493+
profile: {
494+
display_name: 'Fake User',
495+
image_24: 'https://example.com/image.png',
496+
},
497+
},
498+
],
499+
});
500+
});
501+
502+
it('unlocks "起床フィーバータイム" (asa-week-repdigit) when score is a 3-digit repdigit (e.g. 333)', async () => {
503+
const mockedState = State as MockedStateInterface<any>;
504+
const state = mockedState.mocks.get('sushi-bot-counter-asa');
505+
state.data = {[slack.fakeUser]: 333};
506+
507+
expect(scheduleCallback).not.toBeNull();
508+
// 2023-01-01 is a Sunday!
509+
await scheduleCallback!(new Date('2023-01-01T19:00:00+09:00'));
510+
511+
expect(increment).toHaveBeenCalledWith(slack.fakeUser, 'asa-week-repdigit');
512+
});
513+
514+
it('does not unlock "起床フィーバータイム" when score is not a 3-digit repdigit (e.g. 334)', async () => {
515+
const mockedState = State as MockedStateInterface<any>;
516+
const state = mockedState.mocks.get('sushi-bot-counter-asa');
517+
state.data = {[slack.fakeUser]: 334};
518+
519+
expect(scheduleCallback).not.toBeNull();
520+
await scheduleCallback!(new Date('2023-01-01T19:00:00+09:00'));
521+
522+
expect(increment).not.toHaveBeenCalledWith(slack.fakeUser, 'asa-week-repdigit');
523+
});
524+
525+
it('unlocks "起床ロボット" (asa-week-power-of-two) when score is a power of 2 (e.g. 256)', async () => {
526+
const mockedState = State as MockedStateInterface<any>;
527+
const state = mockedState.mocks.get('sushi-bot-counter-asa');
528+
state.data = {[slack.fakeUser]: 256};
529+
530+
expect(scheduleCallback).not.toBeNull();
531+
await scheduleCallback!(new Date('2023-01-01T19:00:00+09:00'));
532+
533+
expect(increment).toHaveBeenCalledWith(slack.fakeUser, 'asa-week-power-of-two');
534+
});
535+
536+
it('does not unlock "起床ロボット" when score is not a power of 2 (e.g. 255)', async () => {
537+
const mockedState = State as MockedStateInterface<any>;
538+
const state = mockedState.mocks.get('sushi-bot-counter-asa');
539+
state.data = {[slack.fakeUser]: 255};
540+
541+
expect(scheduleCallback).not.toBeNull();
542+
await scheduleCallback!(new Date('2023-01-01T19:00:00+09:00'));
543+
544+
expect(increment).not.toHaveBeenCalledWith(slack.fakeUser, 'asa-week-power-of-two');
545+
});
546+
547+
it('unlocks "なんでや" (asa-week-334) when score is exactly 334', async () => {
548+
const mockedState = State as MockedStateInterface<any>;
549+
const state = mockedState.mocks.get('sushi-bot-counter-asa');
550+
state.data = {[slack.fakeUser]: 334};
551+
552+
expect(scheduleCallback).not.toBeNull();
553+
await scheduleCallback!(new Date('2023-01-01T19:00:00+09:00'));
554+
555+
expect(increment).toHaveBeenCalledWith(slack.fakeUser, 'asa-week-334');
556+
});
557+
558+
it('does not unlock "なんでや" when score is not exactly 334 (e.g. 333)', async () => {
559+
const mockedState = State as MockedStateInterface<any>;
560+
const state = mockedState.mocks.get('sushi-bot-counter-asa');
561+
state.data = {[slack.fakeUser]: 333};
562+
563+
expect(scheduleCallback).not.toBeNull();
564+
await scheduleCallback!(new Date('2023-01-01T19:00:00+09:00'));
565+
566+
expect(increment).not.toHaveBeenCalledWith(slack.fakeUser, 'asa-week-334');
567+
});
568+
});
467569
});

sushi-bot/index.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,15 @@ export default async function ({eventClient, webClient: slack}: SlackInterface)
444444
if (count >= 7 * 108) {
445445
unlock(user, 'asa-week-perfect');
446446
}
447+
if (count >= 100 && count <= 999 && count % 111 === 0) {
448+
increment(user, 'asa-week-repdigit');
449+
}
450+
if (count > 0 && (count & (count - 1)) === 0) {
451+
increment(user, 'asa-week-power-of-two');
452+
}
453+
if (count === 334) {
454+
increment(user, 'asa-week-334');
455+
}
447456

448457
return {
449458
author_name: `${index + 1}位: ${name} (${count}点)`,

0 commit comments

Comments
 (0)