From 9d367882fb7e5fc375b7d14e6409a735e68fca8a Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Sat, 21 Jan 2023 15:30:29 +0900
Subject: [PATCH] add some achievements

---
 locales/ja-JP.yml                                 |  6 ++++++
 packages/backend/src/core/AchievementService.ts   |  2 ++
 packages/frontend/src/components/MkPageWindow.vue | 15 ++++++++++++++-
 packages/frontend/src/os.ts                       |  4 +++-
 packages/frontend/src/pages/scratchpad.vue        |  4 ++++
 packages/frontend/src/scripts/achievements.ts     | 12 ++++++++++++
 6 files changed, 41 insertions(+), 2 deletions(-)

diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index e46e6ab9de..aac5d5e833 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -1119,6 +1119,12 @@ _achievements:
     _htl20npm:
       title: "流れるTL"
       description: "ホームタイムラインの流速が20npmを越す"
+    _outputHelloWorldOnScratchpad:
+      title: "Hello, world!"
+      description: "スクラッチパッドで hello world を出力した"
+    _open3windows:
+      title: "マルチウィンドウ"
+      description: "ウィンドウを3つ以上開いた状態にした"
     _driveFolderCircularReference:
       title: "循環参照"
       description: "ドライブのフォルダを再帰的な入れ子にしようとした"
diff --git a/packages/backend/src/core/AchievementService.ts b/packages/backend/src/core/AchievementService.ts
index 4ed75308eb..149974452c 100644
--- a/packages/backend/src/core/AchievementService.ts
+++ b/packages/backend/src/core/AchievementService.ts
@@ -65,6 +65,8 @@ const ACHIEVEMENT_TYPES = [
 	'postedAt0min0sec',
 	'selfQuote',
 	'htl20npm',
+	'outputHelloWorldOnScratchpad',
+	'open3windows',
 	'driveFolderCircularReference',
 	'reactWithoutRead',
 	'clickedClickHere',
diff --git a/packages/frontend/src/components/MkPageWindow.vue b/packages/frontend/src/components/MkPageWindow.vue
index 25b9da2d0b..d12aafd06d 100644
--- a/packages/frontend/src/components/MkPageWindow.vue
+++ b/packages/frontend/src/components/MkPageWindow.vue
@@ -24,7 +24,7 @@
 </template>
 
 <script lang="ts" setup>
-import { ComputedRef, inject, provide } from 'vue';
+import { ComputedRef, inject, onMounted, onUnmounted, provide } from 'vue';
 import RouterView from '@/components/global/RouterView.vue';
 import MkWindow from '@/components/MkWindow.vue';
 import { popout as _popout } from '@/scripts/popout';
@@ -35,6 +35,8 @@ import { mainRouter, routes } from '@/router';
 import { Router } from '@/nirax';
 import { i18n } from '@/i18n';
 import { PageMetadata, provideMetadataReceiver, setPageMetadata } from '@/scripts/page-metadata';
+import { openingWindowsCount } from '@/os';
+import { claimAchievement } from '@/scripts/achievements';
 
 const props = defineProps<{
 	initialPath: string;
@@ -128,6 +130,17 @@ function popout() {
 	windowEl.close();
 }
 
+onMounted(() => {
+	openingWindowsCount.value++;
+	if (openingWindowsCount.value >= 3) {
+		claimAchievement('open3windows');
+	}
+});
+
+onUnmounted(() => {
+	openingWindowsCount.value--;
+});
+
 defineExpose({
 	close,
 });
diff --git a/packages/frontend/src/os.ts b/packages/frontend/src/os.ts
index 111bd0cd8d..01f8244060 100644
--- a/packages/frontend/src/os.ts
+++ b/packages/frontend/src/os.ts
@@ -9,7 +9,7 @@ import * as Misskey from 'misskey-js';
 import { i18n } from './i18n';
 import MkPostFormDialog from '@/components/MkPostFormDialog.vue';
 import MkWaitingDialog from '@/components/MkWaitingDialog.vue';
-import MkPageWindow from '@/components/MkPageWindow.vue'
+import MkPageWindow from '@/components/MkPageWindow.vue';
 import MkToast from '@/components/MkToast.vue';
 import MkDialog from '@/components/MkDialog.vue';
 import MkEmojiPickerDialog from '@/components/MkEmojiPickerDialog.vue';
@@ -18,6 +18,8 @@ import MkPopupMenu from '@/components/MkPopupMenu.vue';
 import MkContextMenu from '@/components/MkContextMenu.vue';
 import { MenuItem } from '@/types/menu';
 
+export const openingWindowsCount = ref(0);
+
 export const apiWithDialog = ((
 	endpoint: string,
 	data: Record<string, any> = {},
diff --git a/packages/frontend/src/pages/scratchpad.vue b/packages/frontend/src/pages/scratchpad.vue
index bd68df724e..0d52850b5d 100644
--- a/packages/frontend/src/pages/scratchpad.vue
+++ b/packages/frontend/src/pages/scratchpad.vue
@@ -47,6 +47,7 @@ import { definePageMetadata } from '@/scripts/page-metadata';
 import { AsUiComponent, AsUiRoot, patch, registerAsUiLib, render } from '@/scripts/aiscript/ui';
 import MkAsUi from '@/components/MkAsUi.vue';
 import { miLocalStorage } from '@/local-storage';
+import { claimAchievement } from '@/scripts/achievements';
 
 const parser = new Parser();
 let aiscript: Interpreter;
@@ -90,6 +91,9 @@ async function run() {
 			});
 		},
 		out: (value) => {
+			if (value.type === 'str' && value.value.toLowerCase().replace(',', '').includes('hello world')) {
+				claimAchievement('outputHelloWorldOnScratchpad');
+			}
 			logs.value.push({
 				id: Math.random(),
 				text: value.type === 'str' ? value.value : utils.valToString(value),
diff --git a/packages/frontend/src/scripts/achievements.ts b/packages/frontend/src/scripts/achievements.ts
index c8245ad3db..70ea0ffbd4 100644
--- a/packages/frontend/src/scripts/achievements.ts
+++ b/packages/frontend/src/scripts/achievements.ts
@@ -61,6 +61,8 @@ export const ACHIEVEMENT_TYPES = [
 	'postedAt0min0sec',
 	'selfQuote',
 	'htl20npm',
+	'outputHelloWorldOnScratchpad',
+	'open3windows',
 	'driveFolderCircularReference',
 	'reactWithoutRead',
 	'clickedClickHere',
@@ -346,6 +348,16 @@ export const ACHIEVEMENT_BADGES = {
 		bg: 'linear-gradient(0deg, rgb(220 223 225), rgb(172 192 207))',
 		frame: 'bronze',
 	},
+	'outputHelloWorldOnScratchpad': {
+		img: '/fluent-emoji/1f530.png',
+		bg: 'linear-gradient(0deg, rgb(58 231 198), rgb(37 194 255))',
+		frame: 'bronze',
+	},
+	'open3windows': {
+		img: '/fluent-emoji/1f5a5.png',
+		bg: 'linear-gradient(0deg, rgb(144 224 255), rgb(255 168 252))',
+		frame: 'bronze',
+	},
 	'driveFolderCircularReference': {
 		img: '/fluent-emoji/1f4c2.png',
 		bg: 'linear-gradient(0deg, rgb(144 224 255), rgb(255 168 252))',