terminal-quest 1.1.2 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/App.js +2 -2
- package/dist/components/HintBar.js +3 -2
- package/dist/data/commands-meta.js +112 -106
- package/dist/data/stories/00-beginner-pc.js +127 -112
- package/dist/data/stories/01-first-server.js +11 -5
- package/dist/data/stories/02-messy-project.js +14 -7
- package/dist/data/stories/03-log-detective.js +22 -6
- package/dist/data/stories/04-deploy-day.js +64 -10
- package/dist/data/stories/05-git-incident.js +80 -19
- package/dist/data/stories/06-pipe-master.js +74 -14
- package/dist/data/stories/07-dangerous-commands.js +79 -12
- package/dist/data/stories/k1-treasure-hunt.js +160 -145
- package/dist/data/types.d.ts +1 -1
- package/dist/engine/CommandFeedback.js +10 -3
- package/dist/engine/CommandHandler.js +5 -0
- package/dist/engine/commands/cat.js +12 -1
- package/dist/engine/commands/cut.js +3 -0
- package/dist/engine/commands/grep.js +6 -0
- package/dist/engine/commands/head.js +3 -0
- package/dist/engine/commands/help.js +7 -3
- package/dist/engine/commands/sort.js +3 -0
- package/dist/engine/commands/tail.js +3 -0
- package/dist/engine/commands/uniq.js +3 -0
- package/dist/screens/StorySelectScreen.d.ts +2 -1
- package/dist/screens/StorySelectScreen.js +55 -7
- package/dist/screens/TerminalScreen.js +67 -17
- package/dist/state/useGameState.d.ts +1 -0
- package/dist/state/useGameState.js +13 -2
- package/package.json +1 -1
|
@@ -8,19 +8,19 @@ const mission1FS = {
|
|
|
8
8
|
watashi: {
|
|
9
9
|
type: 'directory',
|
|
10
10
|
children: {
|
|
11
|
-
'
|
|
11
|
+
'photos': {
|
|
12
12
|
type: 'directory',
|
|
13
13
|
children: {},
|
|
14
14
|
},
|
|
15
|
-
'
|
|
15
|
+
'music': {
|
|
16
16
|
type: 'directory',
|
|
17
17
|
children: {},
|
|
18
18
|
},
|
|
19
|
-
'
|
|
19
|
+
'memo': {
|
|
20
20
|
type: 'directory',
|
|
21
21
|
children: {},
|
|
22
22
|
},
|
|
23
|
-
'
|
|
23
|
+
'welcome.txt': {
|
|
24
24
|
type: 'file',
|
|
25
25
|
content: 'はじめまして!これはあなたの新しいパソコンです。\nまずは、今いる場所を確認してみましょう。\n',
|
|
26
26
|
},
|
|
@@ -40,26 +40,26 @@ const mission2FS = {
|
|
|
40
40
|
watashi: {
|
|
41
41
|
type: 'directory',
|
|
42
42
|
children: {
|
|
43
|
-
'
|
|
43
|
+
'photos': {
|
|
44
44
|
type: 'directory',
|
|
45
45
|
children: {
|
|
46
|
-
'
|
|
46
|
+
'travel-photo.txt': {
|
|
47
47
|
type: 'file',
|
|
48
48
|
content: '海辺で撮った写真です。とてもきれいでした。\n',
|
|
49
49
|
},
|
|
50
50
|
},
|
|
51
51
|
},
|
|
52
|
-
'
|
|
52
|
+
'music': {
|
|
53
53
|
type: 'directory',
|
|
54
54
|
children: {
|
|
55
|
-
'
|
|
55
|
+
'favorites.txt': {
|
|
56
56
|
type: 'file',
|
|
57
57
|
content: '1. 夏の思い出\n2. 星空のメロディー\n3. 雨の日の歌\n',
|
|
58
58
|
},
|
|
59
|
-
'
|
|
59
|
+
'playlist': {
|
|
60
60
|
type: 'directory',
|
|
61
61
|
children: {
|
|
62
|
-
'
|
|
62
|
+
'driving.txt': {
|
|
63
63
|
type: 'file',
|
|
64
64
|
content: 'アップテンポな曲を集めました!\n',
|
|
65
65
|
},
|
|
@@ -67,10 +67,10 @@ const mission2FS = {
|
|
|
67
67
|
},
|
|
68
68
|
},
|
|
69
69
|
},
|
|
70
|
-
'
|
|
70
|
+
'recipes': {
|
|
71
71
|
type: 'directory',
|
|
72
72
|
children: {
|
|
73
|
-
'
|
|
73
|
+
'curry.txt': {
|
|
74
74
|
type: 'file',
|
|
75
75
|
content: '材料: じゃがいも、にんじん、たまねぎ、お肉\n作り方: 野菜を切って煮込む\n',
|
|
76
76
|
},
|
|
@@ -92,14 +92,14 @@ const mission3FS = {
|
|
|
92
92
|
watashi: {
|
|
93
93
|
type: 'directory',
|
|
94
94
|
children: {
|
|
95
|
-
'
|
|
95
|
+
'photos': {
|
|
96
96
|
type: 'directory',
|
|
97
97
|
children: {
|
|
98
|
-
'
|
|
98
|
+
'sea.txt': {
|
|
99
99
|
type: 'file',
|
|
100
100
|
content: '青い海と白い砂浜の写真です。\n',
|
|
101
101
|
},
|
|
102
|
-
'
|
|
102
|
+
'mountain.txt': {
|
|
103
103
|
type: 'file',
|
|
104
104
|
content: '紅葉がきれいな山の写真です。\n',
|
|
105
105
|
},
|
|
@@ -121,29 +121,29 @@ const mission4FS = {
|
|
|
121
121
|
watashi: {
|
|
122
122
|
type: 'directory',
|
|
123
123
|
children: {
|
|
124
|
-
'
|
|
124
|
+
'photos': {
|
|
125
125
|
type: 'directory',
|
|
126
126
|
children: {
|
|
127
|
-
'
|
|
127
|
+
'travel': {
|
|
128
128
|
type: 'directory',
|
|
129
129
|
children: {},
|
|
130
130
|
},
|
|
131
|
-
'
|
|
131
|
+
'pets': {
|
|
132
132
|
type: 'directory',
|
|
133
133
|
children: {},
|
|
134
134
|
},
|
|
135
135
|
},
|
|
136
136
|
},
|
|
137
|
-
'
|
|
137
|
+
'memo': {
|
|
138
138
|
type: 'directory',
|
|
139
139
|
children: {
|
|
140
|
-
'
|
|
140
|
+
'shopping.txt': {
|
|
141
141
|
type: 'file',
|
|
142
142
|
content: '牛乳、パン、たまご\n',
|
|
143
143
|
},
|
|
144
144
|
},
|
|
145
145
|
},
|
|
146
|
-
'
|
|
146
|
+
'important.txt': {
|
|
147
147
|
type: 'file',
|
|
148
148
|
content: '明日の会議は10時から。\n',
|
|
149
149
|
},
|
|
@@ -163,49 +163,49 @@ const mission5FS = {
|
|
|
163
163
|
watashi: {
|
|
164
164
|
type: 'directory',
|
|
165
165
|
children: {
|
|
166
|
-
'
|
|
166
|
+
'memo': {
|
|
167
167
|
type: 'directory',
|
|
168
168
|
children: {
|
|
169
|
-
'
|
|
169
|
+
'shopping.txt': {
|
|
170
170
|
type: 'file',
|
|
171
171
|
content: '牛乳、パン、たまご\n',
|
|
172
172
|
},
|
|
173
|
-
'
|
|
173
|
+
'todo.txt': {
|
|
174
174
|
type: 'file',
|
|
175
175
|
content: '1. 掃除\n2. 買い物\n3. 料理\n',
|
|
176
176
|
},
|
|
177
|
-
'
|
|
177
|
+
'old-memo.tmp': {
|
|
178
178
|
type: 'file',
|
|
179
179
|
content: '一時ファイルです。\n',
|
|
180
180
|
},
|
|
181
181
|
},
|
|
182
182
|
},
|
|
183
|
-
'
|
|
183
|
+
'photos': {
|
|
184
184
|
type: 'directory',
|
|
185
185
|
children: {
|
|
186
|
-
'
|
|
186
|
+
'travel': {
|
|
187
187
|
type: 'directory',
|
|
188
188
|
children: {
|
|
189
|
-
'
|
|
189
|
+
'memories.txt': {
|
|
190
190
|
type: 'file',
|
|
191
191
|
content: '楽しい旅行の思い出です。\n',
|
|
192
192
|
},
|
|
193
193
|
},
|
|
194
194
|
},
|
|
195
|
-
'
|
|
195
|
+
'junk.tmp': {
|
|
196
196
|
type: 'file',
|
|
197
197
|
content: '不要な一時ファイルです。\n',
|
|
198
198
|
},
|
|
199
199
|
},
|
|
200
200
|
},
|
|
201
|
-
'
|
|
201
|
+
'recipes': {
|
|
202
202
|
type: 'directory',
|
|
203
203
|
children: {
|
|
204
|
-
'
|
|
204
|
+
'curry.txt': {
|
|
205
205
|
type: 'file',
|
|
206
206
|
content: '材料: じゃがいも、にんじん、たまねぎ、お肉\n作り方: 野菜を切って煮込む\n',
|
|
207
207
|
},
|
|
208
|
-
'
|
|
208
|
+
'temp.tmp': {
|
|
209
209
|
type: 'file',
|
|
210
210
|
content: '不要な一時ファイルです。\n',
|
|
211
211
|
},
|
|
@@ -227,7 +227,7 @@ const mission6FS = {
|
|
|
227
227
|
watashi: {
|
|
228
228
|
type: 'directory',
|
|
229
229
|
children: {
|
|
230
|
-
'
|
|
230
|
+
'diary': {
|
|
231
231
|
type: 'directory',
|
|
232
232
|
children: {
|
|
233
233
|
'2024-01-15.txt': {
|
|
@@ -282,7 +282,7 @@ const mission7FS = {
|
|
|
282
282
|
watashi: {
|
|
283
283
|
type: 'directory',
|
|
284
284
|
children: {
|
|
285
|
-
'
|
|
285
|
+
'report.txt': {
|
|
286
286
|
type: 'file',
|
|
287
287
|
content: reportContent,
|
|
288
288
|
},
|
|
@@ -313,7 +313,7 @@ const mission8FS = {
|
|
|
313
313
|
watashi: {
|
|
314
314
|
type: 'directory',
|
|
315
315
|
children: {
|
|
316
|
-
'
|
|
316
|
+
'contacts.csv': {
|
|
317
317
|
type: 'file',
|
|
318
318
|
content: contactsCSV,
|
|
319
319
|
},
|
|
@@ -333,24 +333,24 @@ const mission9FS = {
|
|
|
333
333
|
watashi: {
|
|
334
334
|
type: 'directory',
|
|
335
335
|
children: {
|
|
336
|
-
'
|
|
336
|
+
'shared': {
|
|
337
337
|
type: 'directory',
|
|
338
338
|
children: {
|
|
339
|
-
'
|
|
339
|
+
'report.txt': {
|
|
340
340
|
type: 'file',
|
|
341
341
|
content: 'チームの月次レポートです。\n',
|
|
342
342
|
},
|
|
343
|
-
'
|
|
343
|
+
'count.sh': {
|
|
344
344
|
type: 'file',
|
|
345
345
|
content: '#!/bin/bash\necho "集計完了!"\n',
|
|
346
346
|
permissions: '-rw-r--r--',
|
|
347
347
|
},
|
|
348
348
|
},
|
|
349
349
|
},
|
|
350
|
-
'
|
|
350
|
+
'memo': {
|
|
351
351
|
type: 'directory',
|
|
352
352
|
children: {
|
|
353
|
-
'
|
|
353
|
+
'todo.txt': {
|
|
354
354
|
type: 'file',
|
|
355
355
|
content: '1. レポート提出\n2. 会議準備\n',
|
|
356
356
|
},
|
|
@@ -388,7 +388,7 @@ const gitStatusOutput10 = [
|
|
|
388
388
|
' (use "git add <file>..." to update what will be committed)',
|
|
389
389
|
' (use "git restore <file>..." to discard changes in working directory)',
|
|
390
390
|
'',
|
|
391
|
-
'\tmodified:
|
|
391
|
+
'\tmodified: monthly.txt',
|
|
392
392
|
'',
|
|
393
393
|
'no changes added to commit (use "git add" to track)',
|
|
394
394
|
].join('\n');
|
|
@@ -401,7 +401,7 @@ const mission10FS = {
|
|
|
401
401
|
watashi: {
|
|
402
402
|
type: 'directory',
|
|
403
403
|
children: {
|
|
404
|
-
'
|
|
404
|
+
'reports': {
|
|
405
405
|
type: 'directory',
|
|
406
406
|
children: {
|
|
407
407
|
'.git': {
|
|
@@ -413,19 +413,19 @@ const mission10FS = {
|
|
|
413
413
|
},
|
|
414
414
|
branches: {
|
|
415
415
|
type: 'file',
|
|
416
|
-
content: '
|
|
416
|
+
content: 'main',
|
|
417
417
|
},
|
|
418
418
|
log: {
|
|
419
419
|
type: 'file',
|
|
420
420
|
content: gitLogContent10,
|
|
421
421
|
},
|
|
422
|
-
|
|
422
|
+
status: {
|
|
423
423
|
type: 'file',
|
|
424
424
|
content: gitStatusOutput10,
|
|
425
425
|
},
|
|
426
426
|
},
|
|
427
427
|
},
|
|
428
|
-
'
|
|
428
|
+
'monthly.txt': {
|
|
429
429
|
type: 'file',
|
|
430
430
|
content: '1月の活動報告\n- プロジェクトA: 順調に進行中\n- プロジェクトB: 来月開始予定\n',
|
|
431
431
|
},
|
|
@@ -495,34 +495,37 @@ export const story00 = {
|
|
|
495
495
|
correctIndex: 1,
|
|
496
496
|
explanation: 'cd (Change Directory) は、別のフォルダに移動するコマンドです。',
|
|
497
497
|
},
|
|
498
|
-
narrative: '
|
|
498
|
+
narrative: 'パソコンの中には photos(写真)、music(音楽)、recipes(レシピ)などのフォルダがあるみたい。フォルダの中に移動して、どんなファイルがあるか見てみよう!',
|
|
499
499
|
initialCwd: '/home/watashi',
|
|
500
500
|
initialFS: mission2FS,
|
|
501
501
|
newCommands: ['cd', 'cat'],
|
|
502
502
|
objectives: [
|
|
503
503
|
{
|
|
504
504
|
id: 'obj-00-02-01',
|
|
505
|
-
description: '
|
|
506
|
-
checks: [{ type: 'cwd_equals', path: '/home/watashi
|
|
505
|
+
description: 'music(音楽)フォルダに移動しよう',
|
|
506
|
+
checks: [{ type: 'cwd_equals', path: '/home/watashi/music' }],
|
|
507
507
|
hints: [
|
|
508
508
|
{ level: 1, text: 'フォルダを移動するコマンドがあります。' },
|
|
509
|
-
{ level: 2, text: '「Change Directory」の略で、
|
|
510
|
-
{ level: 3, text: '「cd
|
|
509
|
+
{ level: 2, text: '「Change Directory」の略で、cd のあとに移動したいフォルダの名前を書きます。例えば cd music のように。' },
|
|
510
|
+
{ level: 3, text: '「cd music」と入力してEnterキーを押してみましょう。music は音楽フォルダのことです。' },
|
|
511
511
|
],
|
|
512
512
|
},
|
|
513
513
|
{
|
|
514
514
|
id: 'obj-00-02-02',
|
|
515
|
-
description: '
|
|
516
|
-
checks: [
|
|
515
|
+
description: 'favorites.txt の中身を読もう',
|
|
516
|
+
checks: [
|
|
517
|
+
{ type: 'command_executed', command: 'cat' },
|
|
518
|
+
{ type: 'output_contains', pattern: '星空' },
|
|
519
|
+
],
|
|
517
520
|
hints: [
|
|
518
521
|
{ level: 1, text: 'ファイルの中身を画面に表示するコマンドがあります。' },
|
|
519
522
|
{ level: 2, text: '猫の鳴き声に似た3文字のコマンドです。' },
|
|
520
|
-
{ level: 3, text: '「cat
|
|
523
|
+
{ level: 3, text: '「cat favorites.txt」と入力してみましょう。favorites はお気に入りのことです。' },
|
|
521
524
|
],
|
|
522
525
|
},
|
|
523
526
|
{
|
|
524
527
|
id: 'obj-00-02-03',
|
|
525
|
-
description: '
|
|
528
|
+
description: 'ホームフォルダに戻ろう(.. は「1つ上のフォルダ」の意味)',
|
|
526
529
|
checks: [{ type: 'cwd_equals', path: '/home/watashi' }],
|
|
527
530
|
hints: [
|
|
528
531
|
{ level: 1, text: 'cd コマンドで上のフォルダに戻れます。' },
|
|
@@ -544,39 +547,42 @@ export const story00 = {
|
|
|
544
547
|
correctIndex: 1,
|
|
545
548
|
explanation: 'mkdir (Make Directory) は、新しいフォルダ(ディレクトリ)を作成するコマンドです。',
|
|
546
549
|
},
|
|
547
|
-
narrative: '
|
|
548
|
-
initialCwd: '/home/watashi
|
|
550
|
+
narrative: 'photos(写真)フォルダの中がごちゃごちゃしてきた。「travel」(旅行)や「pets」(ペット)のフォルダを作って、写真を整理しよう!',
|
|
551
|
+
initialCwd: '/home/watashi/photos',
|
|
549
552
|
initialFS: mission3FS,
|
|
550
553
|
newCommands: ['mkdir', 'touch'],
|
|
551
554
|
objectives: [
|
|
552
555
|
{
|
|
553
556
|
id: 'obj-00-03-01',
|
|
554
|
-
description: '
|
|
555
|
-
checks: [{ type: 'file_exists', path: '/home/watashi
|
|
557
|
+
description: '「travel」(旅行)フォルダを作ろう',
|
|
558
|
+
checks: [{ type: 'file_exists', path: '/home/watashi/photos/travel' }],
|
|
556
559
|
hints: [
|
|
557
560
|
{ level: 1, text: '新しいフォルダを作るコマンドがあります。' },
|
|
558
561
|
{ level: 2, text: '「Make Directory」の略で、5文字のコマンドです。' },
|
|
559
|
-
{ level: 3, text: '「mkdir
|
|
562
|
+
{ level: 3, text: '「mkdir travel」と入力してEnterキーを押してみましょう。travel は旅行フォルダです。' },
|
|
560
563
|
],
|
|
561
564
|
},
|
|
562
565
|
{
|
|
563
566
|
id: 'obj-00-03-02',
|
|
564
|
-
description: '
|
|
565
|
-
checks: [{ type: 'file_exists', path: '/home/watashi
|
|
567
|
+
description: '「pets」(ペット)フォルダを作ろう',
|
|
568
|
+
checks: [{ type: 'file_exists', path: '/home/watashi/photos/pets' }],
|
|
566
569
|
hints: [
|
|
567
570
|
{ level: 1, text: 'さっきと同じコマンドで、別の名前のフォルダを作りましょう。' },
|
|
568
571
|
{ level: 2, text: 'mkdir の後にフォルダ名を指定します。' },
|
|
569
|
-
{ level: 3, text: '「mkdir
|
|
572
|
+
{ level: 3, text: '「mkdir pets」と入力してみましょう。pets はペットフォルダです。' },
|
|
570
573
|
],
|
|
571
574
|
},
|
|
572
575
|
{
|
|
573
576
|
id: 'obj-00-03-03',
|
|
574
|
-
description: '
|
|
575
|
-
checks: [{ type: 'file_exists', path: '/home/watashi
|
|
577
|
+
description: 'travel フォルダの中に「memories.txt」ファイルを作ろう',
|
|
578
|
+
checks: [{ type: 'file_exists', path: '/home/watashi/photos/travel/memories.txt' }],
|
|
576
579
|
hints: [
|
|
577
580
|
{ level: 1, text: '空のファイルを作るコマンドがあります。' },
|
|
578
|
-
{ level: 2, text: 'touch コマンドでファイルを作れます。フォルダ名/ファイル名
|
|
579
|
-
{ level: 3, text: '「touch
|
|
581
|
+
{ level: 2, text: 'touch コマンドでファイルを作れます。フォルダ名/ファイル名 のように書くと、フォルダの中にファイルを作れます。/ は「の中の」という意味です。' },
|
|
582
|
+
{ level: 3, text: '「touch travel/memories.txt」と入力してみましょう。memories は思い出のことです。' },
|
|
583
|
+
],
|
|
584
|
+
feedbacks: [
|
|
585
|
+
{ pattern: '^touch memories', message: 'travel フォルダの中に作りたいので、「travel/memories.txt」のようにフォルダ名/ファイル名 で指定しましょう。' },
|
|
580
586
|
],
|
|
581
587
|
},
|
|
582
588
|
],
|
|
@@ -593,29 +599,32 @@ export const story00 = {
|
|
|
593
599
|
correctIndex: 1,
|
|
594
600
|
explanation: 'cp (Copy) は、ファイルやフォルダをコピーするコマンドです。mv は移動、rm は削除です。',
|
|
595
601
|
},
|
|
596
|
-
narrative: '
|
|
602
|
+
narrative: 'あれ?「important.txt」(大事なメモ)がホームフォルダに置きっぱなしだ。これは「memo」フォルダに入れるべきだよね。ファイルをコピーしたり移動したりして、きちんと整理しよう。',
|
|
597
603
|
initialCwd: '/home/watashi',
|
|
598
604
|
initialFS: mission4FS,
|
|
599
605
|
newCommands: ['cp', 'mv'],
|
|
600
606
|
objectives: [
|
|
601
607
|
{
|
|
602
608
|
id: 'obj-00-04-01',
|
|
603
|
-
description: '
|
|
604
|
-
checks: [{ type: 'file_exists', path: '/home/watashi
|
|
609
|
+
description: 'important.txt を memo フォルダにコピーしよう',
|
|
610
|
+
checks: [{ type: 'file_exists', path: '/home/watashi/memo/important.txt' }],
|
|
605
611
|
hints: [
|
|
606
612
|
{ level: 1, text: 'ファイルをコピーするコマンドがあります。' },
|
|
607
|
-
{ level: 2, text: '「Copy」の略で、2
|
|
608
|
-
{ level: 3, text: '「cp
|
|
613
|
+
{ level: 2, text: '「Copy」の略で、2文字のコマンドです。cp のあとに「コピーしたいファイル名」「コピー先」の順に書きます。' },
|
|
614
|
+
{ level: 3, text: '「cp important.txt memo/important.txt」と入力してみましょう。important は大事なメモのことです。' },
|
|
615
|
+
],
|
|
616
|
+
feedbacks: [
|
|
617
|
+
{ pattern: 'cp memo/', message: '順番が逆かもしれません。cp のあとはまず「コピーしたいファイル」、次に「コピー先」を書きます。' },
|
|
609
618
|
],
|
|
610
619
|
},
|
|
611
620
|
{
|
|
612
621
|
id: 'obj-00-04-02',
|
|
613
|
-
description: '
|
|
614
|
-
checks: [{ type: 'file_not_exists', path: '/home/watashi
|
|
622
|
+
description: 'ホームフォルダの important.txt を片付けよう(移動または削除)',
|
|
623
|
+
checks: [{ type: 'file_not_exists', path: '/home/watashi/important.txt' }],
|
|
615
624
|
hints: [
|
|
616
625
|
{ level: 1, text: 'ファイルを移動するコマンドや、削除するコマンドがあります。' },
|
|
617
626
|
{ level: 2, text: 'mv コマンドで移動、rm コマンドで削除できます。もうコピー済みなので削除でもOKです。' },
|
|
618
|
-
{ level: 3, text: '「rm
|
|
627
|
+
{ level: 3, text: '「rm important.txt」と入力してみましょう。' },
|
|
619
628
|
],
|
|
620
629
|
},
|
|
621
630
|
],
|
|
@@ -640,41 +649,44 @@ export const story00 = {
|
|
|
640
649
|
{
|
|
641
650
|
id: 'obj-00-05-01',
|
|
642
651
|
description: '.tmp ファイルを探そう',
|
|
643
|
-
checks: [
|
|
652
|
+
checks: [
|
|
653
|
+
{ type: 'command_executed', command: 'find' },
|
|
654
|
+
{ type: 'output_contains', pattern: '.tmp' },
|
|
655
|
+
],
|
|
644
656
|
hints: [
|
|
645
657
|
{ level: 1, text: 'ファイルを名前で検索するコマンドがあります。' },
|
|
646
|
-
{ level: 2, text: 'find
|
|
647
|
-
{ level: 3, text: '「find . -name "*.tmp"
|
|
658
|
+
{ level: 2, text: 'find コマンドで、特定の名前のファイルを探せます。find のあとに「.」(今いるフォルダ)と -name「名前のパターン」を書きます。' },
|
|
659
|
+
{ level: 3, text: '「find . -name "*.tmp"」と入力してみましょう。. は「今いるフォルダ」、* は「何でもOK」という意味です。' },
|
|
648
660
|
],
|
|
649
661
|
},
|
|
650
662
|
{
|
|
651
663
|
id: 'obj-00-05-02',
|
|
652
|
-
description: '
|
|
653
|
-
checks: [{ type: 'file_not_exists', path: '/home/watashi
|
|
664
|
+
description: 'memo/old-memo.tmp を削除しよう',
|
|
665
|
+
checks: [{ type: 'file_not_exists', path: '/home/watashi/memo/old-memo.tmp' }],
|
|
654
666
|
hints: [
|
|
655
667
|
{ level: 1, text: 'ファイルを削除するコマンドがあります。' },
|
|
656
668
|
{ level: 2, text: '「Remove」の略で、2文字のコマンドです。' },
|
|
657
|
-
{ level: 3, text: '「rm
|
|
669
|
+
{ level: 3, text: '「rm memo/old-memo.tmp」と入力してみましょう。' },
|
|
658
670
|
],
|
|
659
671
|
},
|
|
660
672
|
{
|
|
661
673
|
id: 'obj-00-05-03',
|
|
662
|
-
description: '
|
|
663
|
-
checks: [{ type: 'file_not_exists', path: '/home/watashi
|
|
674
|
+
description: 'photos/junk.tmp を削除しよう',
|
|
675
|
+
checks: [{ type: 'file_not_exists', path: '/home/watashi/photos/junk.tmp' }],
|
|
664
676
|
hints: [
|
|
665
677
|
{ level: 1, text: 'さっきと同じコマンドで別のファイルを削除しましょう。' },
|
|
666
678
|
{ level: 2, text: 'rm コマンドにファイルのパスを指定します。' },
|
|
667
|
-
{ level: 3, text: '「rm
|
|
679
|
+
{ level: 3, text: '「rm photos/junk.tmp」と入力してみましょう。' },
|
|
668
680
|
],
|
|
669
681
|
},
|
|
670
682
|
{
|
|
671
683
|
id: 'obj-00-05-04',
|
|
672
|
-
description: '
|
|
673
|
-
checks: [{ type: 'file_not_exists', path: '/home/watashi
|
|
684
|
+
description: 'recipes/temp.tmp を削除しよう',
|
|
685
|
+
checks: [{ type: 'file_not_exists', path: '/home/watashi/recipes/temp.tmp' }],
|
|
674
686
|
hints: [
|
|
675
687
|
{ level: 1, text: '最後の一時ファイルも削除しましょう。' },
|
|
676
688
|
{ level: 2, text: 'rm コマンドにファイルのパスを指定します。' },
|
|
677
|
-
{ level: 3, text: '「rm
|
|
689
|
+
{ level: 3, text: '「rm recipes/temp.tmp」と入力してみましょう。' },
|
|
678
690
|
],
|
|
679
691
|
},
|
|
680
692
|
],
|
|
@@ -691,17 +703,17 @@ export const story00 = {
|
|
|
691
703
|
correctIndex: 2,
|
|
692
704
|
explanation: 'grep は、ファイルの中身から指定した文字列を含む行を検索するコマンドです。find はファイル名で検索します。',
|
|
693
705
|
},
|
|
694
|
-
narrative: '
|
|
695
|
-
initialCwd: '/home/watashi
|
|
706
|
+
narrative: 'diary(日記)フォルダに過去の日記がある。今日の日記を書いて、それから過去の日記から気になる言葉を探してみよう!',
|
|
707
|
+
initialCwd: '/home/watashi/diary',
|
|
696
708
|
initialFS: mission6FS,
|
|
697
709
|
newCommands: ['echo', 'grep'],
|
|
698
710
|
objectives: [
|
|
699
711
|
{
|
|
700
712
|
id: 'obj-00-06-01',
|
|
701
713
|
description: '新しい日記ファイル 2024-01-17.txt を作ろう',
|
|
702
|
-
checks: [{ type: 'file_exists', path: '/home/watashi
|
|
714
|
+
checks: [{ type: 'file_exists', path: '/home/watashi/diary/2024-01-17.txt' }],
|
|
703
715
|
hints: [
|
|
704
|
-
{ level: 1, text: 'echo
|
|
716
|
+
{ level: 1, text: 'echo コマンドと > 記号を使うと、文字をファイルに書き込めます。> は「ファイルに書き込む」という意味です。' },
|
|
705
717
|
{ level: 2, text: 'echo "内容" > ファイル名 の形式で、ファイルを作って内容を書き込めます。' },
|
|
706
718
|
{ level: 3, text: '「echo "今日はいい天気だった。" > 2024-01-17.txt」と入力してみましょう。' },
|
|
707
719
|
],
|
|
@@ -709,7 +721,10 @@ export const story00 = {
|
|
|
709
721
|
{
|
|
710
722
|
id: 'obj-00-06-02',
|
|
711
723
|
description: '過去の日記から「桜」という言葉を探そう',
|
|
712
|
-
checks: [
|
|
724
|
+
checks: [
|
|
725
|
+
{ type: 'command_executed', command: 'grep' },
|
|
726
|
+
{ type: 'output_contains', pattern: '桜' },
|
|
727
|
+
],
|
|
713
728
|
hints: [
|
|
714
729
|
{ level: 1, text: 'ファイルの中から特定の言葉を検索するコマンドがあります。' },
|
|
715
730
|
{ level: 2, text: 'grep コマンドで、指定した言葉を含む行を探せます。' },
|
|
@@ -730,7 +745,7 @@ export const story00 = {
|
|
|
730
745
|
correctIndex: 1,
|
|
731
746
|
explanation: 'tail はファイルの末尾(最後の部分)を表示するコマンドです。head は最初の部分を表示します。',
|
|
732
747
|
},
|
|
733
|
-
narrative: '
|
|
748
|
+
narrative: '旅行のレポート(report.txt)が長くて全部読むのは大変。最初の部分と最後の部分だけ確認して、全体の行数も数えてみよう。',
|
|
734
749
|
initialCwd: '/home/watashi',
|
|
735
750
|
initialFS: mission7FS,
|
|
736
751
|
newCommands: ['head', 'tail', 'wc'],
|
|
@@ -742,7 +757,7 @@ export const story00 = {
|
|
|
742
757
|
hints: [
|
|
743
758
|
{ level: 1, text: 'ファイルの最初の数行だけを表示するコマンドがあります。' },
|
|
744
759
|
{ level: 2, text: '「頭」を意味する英語のコマンドです。' },
|
|
745
|
-
{ level: 3, text: '「head
|
|
760
|
+
{ level: 3, text: '「head report.txt」と入力してみましょう。' },
|
|
746
761
|
],
|
|
747
762
|
},
|
|
748
763
|
{
|
|
@@ -752,7 +767,7 @@ export const story00 = {
|
|
|
752
767
|
hints: [
|
|
753
768
|
{ level: 1, text: 'ファイルの最後の数行だけを表示するコマンドがあります。' },
|
|
754
769
|
{ level: 2, text: '「しっぽ」を意味する英語のコマンドです。head の反対です。' },
|
|
755
|
-
{ level: 3, text: '「tail
|
|
770
|
+
{ level: 3, text: '「tail report.txt」と入力してみましょう。' },
|
|
756
771
|
],
|
|
757
772
|
},
|
|
758
773
|
{
|
|
@@ -764,7 +779,7 @@ export const story00 = {
|
|
|
764
779
|
hints: [
|
|
765
780
|
{ level: 1, text: 'ファイルの行数や文字数を数えるコマンドがあります。' },
|
|
766
781
|
{ level: 2, text: '「Word Count」の略のコマンドで、-l オプションをつけると行数だけ表示できます。' },
|
|
767
|
-
{ level: 3, text: '「wc -l
|
|
782
|
+
{ level: 3, text: '「wc -l report.txt」と入力してみましょう。-l は「行数だけを数える」という意味です。' },
|
|
768
783
|
],
|
|
769
784
|
},
|
|
770
785
|
],
|
|
@@ -781,7 +796,7 @@ export const story00 = {
|
|
|
781
796
|
correctIndex: 2,
|
|
782
797
|
explanation: 'uniq は、隣接する重複行を取り除くコマンドです。sort で並べ替えてから使うのがポイントです。',
|
|
783
798
|
},
|
|
784
|
-
narrative: '
|
|
799
|
+
narrative: '連絡先のファイル(contacts.csv)がぐちゃぐちゃで、同じ人が何回も登録されている。きれいに並べ替えて、重複を取り除こう!',
|
|
785
800
|
initialCwd: '/home/watashi',
|
|
786
801
|
initialFS: mission8FS,
|
|
787
802
|
newCommands: ['sort', 'uniq', 'cut'],
|
|
@@ -793,17 +808,17 @@ export const story00 = {
|
|
|
793
808
|
hints: [
|
|
794
809
|
{ level: 1, text: 'ファイルの中身を並べ替えるコマンドがあります。' },
|
|
795
810
|
{ level: 2, text: '「並べ替え」を意味する英語のコマンドです。' },
|
|
796
|
-
{ level: 3, text: '「sort
|
|
811
|
+
{ level: 3, text: '「sort contacts.csv」と入力してみましょう。' },
|
|
797
812
|
],
|
|
798
813
|
},
|
|
799
814
|
{
|
|
800
815
|
id: 'obj-00-08-02',
|
|
801
|
-
description: '重複を取り除こう(
|
|
816
|
+
description: '重複を取り除こう(uniq コマンド)',
|
|
802
817
|
checks: [{ type: 'command_executed', command: 'uniq' }],
|
|
803
818
|
hints: [
|
|
804
|
-
{ level: 1, text: '
|
|
805
|
-
{ level: 2, text: '
|
|
806
|
-
{ level: 3, text: '「
|
|
819
|
+
{ level: 1, text: '重複した行を取り除くコマンドがあります。' },
|
|
820
|
+
{ level: 2, text: 'uniq コマンドで重複行を取り除けます。ただし uniq は「隣り合った行」しかまとめないので、先に sort で並べてから使うのがコツです。' },
|
|
821
|
+
{ level: 3, text: '「uniq contacts.csv」と入力してみましょう。' },
|
|
807
822
|
],
|
|
808
823
|
},
|
|
809
824
|
{
|
|
@@ -815,8 +830,8 @@ export const story00 = {
|
|
|
815
830
|
],
|
|
816
831
|
hints: [
|
|
817
832
|
{ level: 1, text: 'CSVの特定の列だけを切り出すコマンドがあります。' },
|
|
818
|
-
{ level: 2, text: 'cut
|
|
819
|
-
{ level: 3, text: '「cut -d, -f1
|
|
833
|
+
{ level: 2, text: 'cut コマンドで列を取り出せます。-d, は「カンマで区切る」、-f1 は「1列目を取り出す」という意味です。' },
|
|
834
|
+
{ level: 3, text: '「cut -d, -f1 contacts.csv」と入力してみましょう。' },
|
|
820
835
|
],
|
|
821
836
|
},
|
|
822
837
|
],
|
|
@@ -833,7 +848,7 @@ export const story00 = {
|
|
|
833
848
|
correctIndex: 1,
|
|
834
849
|
explanation: 'chmod (Change Mode) はファイルの権限を変更するコマンドです。+x で実行権限を追加します。',
|
|
835
850
|
},
|
|
836
|
-
narrative: '
|
|
851
|
+
narrative: 'shared(共有)フォルダにある集計スクリプト(count.sh)を実行したいけど、実行する権限がない。権限を設定して使えるようにしよう!',
|
|
837
852
|
initialCwd: '/home/watashi',
|
|
838
853
|
initialFS: mission9FS,
|
|
839
854
|
newCommands: ['chmod'],
|
|
@@ -844,8 +859,8 @@ export const story00 = {
|
|
|
844
859
|
checks: [{ type: 'command_executed', command: 'chmod' }],
|
|
845
860
|
hints: [
|
|
846
861
|
{ level: 1, text: 'ファイルの権限(パーミッション)を変更するコマンドがあります。' },
|
|
847
|
-
{ level: 2, text: '「Change Mode」の略のコマンドで、+x
|
|
848
|
-
{ level: 3, text: '「chmod +x
|
|
862
|
+
{ level: 2, text: '「Change Mode」の略のコマンドで、+x をつけるとファイルを「実行してもいいよ」という許可を追加できます。プログラムを動かすときに必要です。' },
|
|
863
|
+
{ level: 3, text: '「chmod +x shared/count.sh」と入力してみましょう。shared は共有フォルダ、count.sh は集計スクリプトです。' },
|
|
849
864
|
],
|
|
850
865
|
},
|
|
851
866
|
{
|
|
@@ -853,9 +868,9 @@ export const story00 = {
|
|
|
853
868
|
description: 'やることリストを sort で並べ替えて表示しよう',
|
|
854
869
|
checks: [{ type: 'command_executed', command: 'sort' }],
|
|
855
870
|
hints: [
|
|
856
|
-
{ level: 1, text: '
|
|
857
|
-
{ level: 2, text: '
|
|
858
|
-
{ level: 3, text: '「
|
|
871
|
+
{ level: 1, text: 'ファイルの中身を並べ替えて表示するコマンドがあります。' },
|
|
872
|
+
{ level: 2, text: 'sort コマンドにファイル名を渡すと、中身を並べ替えて表示します。' },
|
|
873
|
+
{ level: 3, text: '「sort memo/todo.txt」と入力してみましょう。' },
|
|
859
874
|
],
|
|
860
875
|
},
|
|
861
876
|
],
|
|
@@ -872,8 +887,8 @@ export const story00 = {
|
|
|
872
887
|
correctIndex: 1,
|
|
873
888
|
explanation: 'git status は、どのファイルが変更されたか、ステージされているかなどの現在の状態を表示します。',
|
|
874
889
|
},
|
|
875
|
-
narrative: '
|
|
876
|
-
initialCwd: '/home/watashi
|
|
890
|
+
narrative: 'reports(レポート)フォルダでは git を使って変更履歴を管理している。どんな変更が行われたか確認してみよう!',
|
|
891
|
+
initialCwd: '/home/watashi/reports',
|
|
877
892
|
initialFS: mission10FS,
|
|
878
893
|
newCommands: ['git'],
|
|
879
894
|
objectives: [
|
|
@@ -895,7 +910,7 @@ export const story00 = {
|
|
|
895
910
|
description: '変更の履歴を見てみよう(git log)',
|
|
896
911
|
checks: [
|
|
897
912
|
{ type: 'command_executed', command: 'git' },
|
|
898
|
-
{ type: 'output_contains', pattern: '
|
|
913
|
+
{ type: 'output_contains', pattern: 'Author:' },
|
|
899
914
|
],
|
|
900
915
|
hints: [
|
|
901
916
|
{ level: 1, text: '過去の変更履歴を表示するGitコマンドがあります。' },
|