diff --git a/MileStone3_toDoList/ipo_card_add.md b/MileStone3_toDoList/ipo_card_add.md new file mode 100644 index 0000000..d2af384 --- /dev/null +++ b/MileStone3_toDoList/ipo_card_add.md @@ -0,0 +1,7 @@ +### 機能名: TODOリスト-add + +| 項目 | 内容 | +|------|------| +| **Input (きっかけ)** | ユーザーは「add (タスクの名称)」と入力する. +| **Process (裏側の処理)** | サーバーは入力されたタスク名の文字列を受け取り,タスクが未完了の状態で保存する.サーバーは保存しているタスクをすべて読み込む. +| **Output (結果)** | 正常にタスクが保存されれば「タスクが追加されました」と表示する.もし入力したタスク名と一致する,保存されたタスクがすでにあれば,「同名のタスクがあります。タスク名を変更してください。」と表示する. \ No newline at end of file diff --git a/MileStone3_toDoList/ipo_card_done.md b/MileStone3_toDoList/ipo_card_done.md new file mode 100644 index 0000000..a362151 --- /dev/null +++ b/MileStone3_toDoList/ipo_card_done.md @@ -0,0 +1,7 @@ +### 機能名: TODOリスト-done + +| 項目 | 内容 | +|------|------| +| **Input (きっかけ)** | ユーザーは「done (タスクの名称)」と入力する. +| **Process (裏側の処理)** | サーバーは入力されたタスク名の文字列を受け取る.保存されたタスクをすべて読み込み,入力されたタスク名と同じ名前のタスクを探し,それに対して名前の前に*をつけて保存する. +| **Output (結果)** | もし入力したタスク名と一致する名前のタスクがリストにあり,名前の前に*をつけて保存ができた場合,「正常に処理されました。」と表示する.もし一致するタスク名がリストにない場合,「リストの中にそのようなタスクはありません。」と表示する. \ No newline at end of file diff --git a/MileStone3_toDoList/ipo_card_list.md b/MileStone3_toDoList/ipo_card_list.md new file mode 100644 index 0000000..5d5c1a0 --- /dev/null +++ b/MileStone3_toDoList/ipo_card_list.md @@ -0,0 +1,7 @@ +### 機能名: TODOリスト-list + +| 項目 | 内容 | +|------|------| +| **Input (きっかけ)** | ユーザーは「list」と入力する. +| **Process (裏側の処理)** | サーバーは保存しているタスクをすべて読み込む. +| **Output (結果)** | 保存しているタスクをすべて表示する.未完了のタスクはタスク名のみ,完了したタスクはタスク名の前に「*」をつけて,タスク名とともに表示される. \ No newline at end of file diff --git a/MileStone3_toDoList/todo.js b/MileStone3_toDoList/todo.js new file mode 100644 index 0000000..9c9789b --- /dev/null +++ b/MileStone3_toDoList/todo.js @@ -0,0 +1,121 @@ +#!/usr/bin/env node +"use strict"; + +const readline = require("readline"); + +// ====== In-memory storage (DBなし / ファイル保存なし) ====== +/** + * tasks: { name: string, done: boolean }[] + */ +const tasks = []; + +// ====== Helpers ====== +function findTaskByName(name) { + return tasks.find(t => t.name === name); +} + +function addTask(name) { + // Process: 入力されたタスク名を受け取り、未完了で保存。保存タスクをすべて読み込む(= tasksを見る) + if (findTaskByName(name)) { + console.log("同名のタスクがあります。タスク名を変更してください。"); + return; + } + tasks.push({ name, done: false }); + console.log("タスクが追加されました"); +} + +function listTasks() { + // Process: 保存しているタスクをすべて読み込む(= tasks を走査) + if (tasks.length === 0) { + // 空のときに表示 + console.log("(タスクはありません)"); + return; + } + + for (const t of tasks) { + // Output: 未完了はタスク名のみ、完了は先頭に「*」 + if (t.done) { + console.log(`*${t.name}`); + } else { + console.log(t.name); + } + } +} + +function doneTask(name) { + // Process: 保存タスクから同名を探し、*をつけて保存(= done=true にする) + const task = findTaskByName(name); + if (!task) { + console.log("リストの中にそのようなタスクはありません。"); + return; + } + task.done = true; + console.log("正常に処理されました。"); +} +// ヘルプ表示 +function printHelp() { + console.log("使い方:"); + console.log('タスクを追加: add (タスクの名称)'); + console.log("リストを表示: list"); + console.log('タスクを完了: done (タスクの名称)'); + console.log("終了する: exit"); +} + +// ====== CLI loop ====== +const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, + prompt: "> ", +}); + +printHelp(); +rl.prompt(); + +rl.on("line", (line) => { + const input = line.trim(); + + if (input === "") { + rl.prompt(); + return; + } + + if (input === "exit" || input === "quit") { + rl.close(); + return; + } + + if (input === "help") { + printHelp(); + rl.prompt(); + return; + } + + // コマンド + 引数(タスク名はスペースを含む可能性があるので、先頭だけコマンドとして切る) + const [cmd, ...rest] = input.split(" "); + const arg = rest.join(" ").trim(); // タスク名 + + if (cmd === "add") { + if (!arg) { + console.log("タスク名を入力してください。例: add レポートを書く"); + } else { + addTask(arg); + } + } else if (cmd === "list") { + listTasks(); + } else if (cmd === "done") { + if (!arg) { + console.log("タスク名を入力してください。例: done レポートを書く"); + } else { + doneTask(arg); + } + } else { + console.log("不明なコマンドです。help を参照してください。"); + } + + rl.prompt(); +}); + +rl.on("close", () => { + console.log("終了します。"); + process.exit(0); +}); \ No newline at end of file diff --git a/MileStone4_conclusion/greeting_alphabet.js b/MileStone4_conclusion/greeting_alphabet.js new file mode 100644 index 0000000..c56457b --- /dev/null +++ b/MileStone4_conclusion/greeting_alphabet.js @@ -0,0 +1,55 @@ +#!/usr/bin/env node +"use strict"; + +const readline = require("readline"); + +/** + * 時間帯から挨拶を返す + * 日本語版と英語版の両方に対応 + */ +function getGreetingByTime(date = new Date(), isEnglish = false) { + const h = date.getHours(); + + if (h >= 4 && h <= 9) { + return isEnglish ? "Good morning" : "おはようございます"; + } else if (h >= 10 && h <= 17) { + return isEnglish ? "Hello" : "こんにちは"; + } else { + return isEnglish ? "Good afternoon" : "こんばんは"; + } +} + +/** + * 名前がアルファベットのみか判定 + */ +function isAlphabetOnly(name) { + return /^[A-Za-z]+$/.test(name); +} + +const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, +}); + +rl.question("お名前を入力してください: ", (answer) => { + const name = (answer ?? "").trim(); + + // 未入力チェック + if (!name) { + console.log("名前を入力してください。"); + rl.close(); + return; + } + + const englishName = isAlphabetOnly(name); + const greeting = getGreetingByTime(new Date(), englishName); + + // 出力の分岐 + if (englishName) { + console.log(`${greeting}, ${name}!`); + } else { + console.log(`${name}さん、${greeting}`); + } + + rl.close(); +}); \ No newline at end of file diff --git a/MileStone4_conclusion/ipo_card1_name.md b/MileStone4_conclusion/ipo_card1_name.md new file mode 100644 index 0000000..6c52900 --- /dev/null +++ b/MileStone4_conclusion/ipo_card1_name.md @@ -0,0 +1,7 @@ +### 機能名:おしゃべり挨拶ボット-名称によって挨拶変更 + +| 項目 | 内容 | +|------|------| +| **input** | ユーザーは自分の名前を入力する.| +| **Process** | サーバーはユーザーがテキストボックスに打ち込んだ名前を受け取る.| +| **Output** | 画面上に「(ユーザー名)さん、〇〇」と表示する.〇〇に入る挨拶は時間によって変動し,04:00から09:59までは「おはようございます」,10:00から17:59までは「こんにちは」,18:00から03:59までは「こんばんは」が入る.もしユーザーが何も入力しなかった場合は,「名前を入力してください.」と返す.もしユーザー名がアルファベットのみで構成されていたら,「〇〇, (ユーザー名)!」と表示し,〇〇に「こんにちは」の代わりに「Hello」,「こんばんは」の代わりに「Good afternoon」, 「おはようございます」の代わりに「Good morning」を入れる.| \ No newline at end of file diff --git a/MileStone4_conclusion/ipo_card2_tax.md b/MileStone4_conclusion/ipo_card2_tax.md new file mode 100644 index 0000000..dc21c69 --- /dev/null +++ b/MileStone4_conclusion/ipo_card2_tax.md @@ -0,0 +1,6 @@ +### 機能名: 割り勘計算機-消費税を加算 +| 項目 | 内容 | +|------|------| +| **Input** | ユーザーは合計金額と人数を正の整数値で入力する.その後,ユーザーは税率(%)を0以上の数で入力する. | +| **Process** | サーバーはユーザーが入力した文字列を受け取る.その後,合計金額の値を人数の値で割って,1人あたりの金額を計算する.そして,計算した金額に(1 + (入力した税率)/100)をかけて税込みの値を計算する. +| **Output** | 画面上に「1人あたりの金額は〇〇円です。」と表示する.〇〇には,計算した1人あたりの金額の値を入れる.ユーザーが人数を入力する際に何も入力しなかった場合,「人数を入力してください。」と返す.ユーザーが合計金額を入力する際に何も入力しなかった場合,「合計金額を入力してください。」と返す.ユーザーが税率を入力する際に何も入力しなかった場合,「税率を入力してください。」と返す.ユーザーが有効でない値,すなわち,負の値・浮動小数点型の値・0(特に人数を入力する際),文字列を入力した際は,「有効な数字を入力してください。」と返す. | \ No newline at end of file diff --git a/MileStone4_conclusion/ipo_card3_show.md b/MileStone4_conclusion/ipo_card3_show.md new file mode 100644 index 0000000..222d675 --- /dev/null +++ b/MileStone4_conclusion/ipo_card3_show.md @@ -0,0 +1,14 @@ +### 機能名: TODOリスト-list + +| 項目 | 内容 | +|------|------| +| **Input (きっかけ)** | ユーザーは「show todo」「show done」のいずれかを入力する. +| **Process (裏側の処理)** | サーバーは保存しているタスクをすべて読み込む. +| **Output (結果)** | 「list todo」と入力された場合,保存されているタスクの内完了したタスク名のみ表示する.「list done」と入力された場合,保存されているタスクの内未完了のタスク名のみ表示する. + +### 機能名: TODOリスト-show(MileStone3で提出したコードでのlistにあたる) +| 項目 | 内容 | +|------|------| +| **Input (きっかけ)** | ユーザーは「show」と入力する. +| **Process (裏側の処理)** | サーバーは保存しているタスクをすべて読み込む. +| **Output (結果)** | 保存しているタスクをすべて表示する.未完了のタスクはタスク名のみ,完了したタスクはタスク名の前に「*」をつけて,タスク名とともに表示される. \ No newline at end of file diff --git a/MileStone4_conclusion/todo_show.js b/MileStone4_conclusion/todo_show.js new file mode 100644 index 0000000..ce886b7 --- /dev/null +++ b/MileStone4_conclusion/todo_show.js @@ -0,0 +1,148 @@ +"use strict"; + +const readline = require("readline"); + +// ====== In-memory storage (DBなし / ファイル保存なし) ====== +/** + * tasks: { name: string, done: boolean }[] + */ +const tasks = []; + +// ====== Helpers ====== +function findTaskByName(name) { + return tasks.find(t => t.name === name); +} + +function addTask(name) { + if (findTaskByName(name)) { + console.log("同名のタスクがあります。タスク名を変更してください。"); + return; + } + tasks.push({ name, done: false }); + console.log("タスクが追加されました"); +} + +function showTasks() { + if (tasks.length === 0) { + console.log("(タスクはありません)"); + return; + } + + for (const t of tasks) { + if (t.done) { + console.log(`*${t.name}`); + } else { + console.log(t.name); + } + } +} + +function listTasks(type) { + let filtered; + + if (type === "todo") { + filtered = tasks.filter(t => !t.done); + } else if (type === "done") { + filtered = tasks.filter(t => t.done); + } else { + console.log("list は 'todo' または 'done' を指定してください。"); + return; + } + + if (filtered.length === 0) { + console.log("(該当するタスクはありません)"); + return; + } + + for (const t of filtered) { + if (t.done) { + console.log(`*${t.name}`); + } else { + console.log(t.name); + } + } +} + +function doneTask(name) { + const task = findTaskByName(name); + if (!task) { + console.log("リストの中にそのようなタスクはありません。"); + return; + } + task.done = true; + console.log("正常に処理されました。"); +} + +function printHelp() { + console.log("使い方:"); + console.log("タスクを追加: add (タスクの名称)"); + console.log("リストの表示: show"); + console.log("未完了のタスクのみ表示: list todo"); + console.log("完了したタスクのみ表示: list done"); + console.log("タスクの完了: done (タスクの名称)"); + console.log("終了: exit"); +} + +// ====== CLI loop ====== +const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, + prompt: "> ", +}); + +printHelp(); +rl.prompt(); + +rl.on("line", (line) => { + const input = line.trim(); + + if (input === "") { + rl.prompt(); + return; + } + + if (input === "exit" || input === "quit") { + rl.close(); + return; + } + + if (input === "help") { + printHelp(); + rl.prompt(); + return; + } + + const [cmd, ...rest] = input.split(" "); + const arg = rest.join(" ").trim(); + + if (cmd === "add") { + if (!arg) { + console.log("タスク名を入力してください。例: add レポートを書く"); + } else { + addTask(arg); + } + } else if (cmd === "show") { + showTasks(); + } else if (cmd === "list") { + if (!arg) { + console.log("list には 'todo' または 'done' を指定してください。"); + } else { + listTasks(arg); + } + } else if (cmd === "done") { + if (!arg) { + console.log("タスク名を入力してください。例: done レポートを書く"); + } else { + doneTask(arg); + } + } else { + console.log("不明なコマンドです。help を参照してください。"); + } + + rl.prompt(); +}); + +rl.on("close", () => { + console.log("終了します。"); + process.exit(0); +}); \ No newline at end of file diff --git a/MileStone4_conclusion/warikan_tax.js b/MileStone4_conclusion/warikan_tax.js new file mode 100644 index 0000000..0df7df0 --- /dev/null +++ b/MileStone4_conclusion/warikan_tax.js @@ -0,0 +1,77 @@ +#!/usr/bin/env node +"use strict"; + +const readline = require("readline"); + +const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, +}); + +// 正の整数(1,2,3,...)チェック:合計金額・人数用 +function isPositiveIntegerString(s) { + const t = s.trim(); + if (t === "") return false; + const n = Number(t); + return Number.isInteger(n) && n > 0; +} + +// 0以上の数チェック(小数OK):税率用 +function isNonNegativeNumberString(s) { + const t = s.trim(); + if (t === "") return false; + const n = Number(t); + return Number.isFinite(n) && n >= 0; +} + +function invalidNumberMessage() { + console.log("有効な数字を入力してください。"); +} + +// 合計金額 +rl.question("合計金額を入力してください: ", (total) => { + if (total.trim() === "") { + console.log("合計金額を入力してください。"); + rl.close(); + return; + } + if (!isPositiveIntegerString(total)) { + invalidNumberMessage(); + rl.close(); + return; + } + + // 人数 + rl.question("人数を入力してください: ", (people) => { + if (people.trim() === "") { + console.log("人数を入力してください。"); + rl.close(); + return; + } + if (!isPositiveIntegerString(people)) { + invalidNumberMessage(); + rl.close(); + return; + } + + // 税率 + rl.question("税率(%)を入力してください: ", (taxRate) => { + if (taxRate.trim() === "") { + console.log("税率を入力してください。"); + rl.close(); + return; + } + if (!isNonNegativeNumberString(taxRate)) { + invalidNumberMessage(); + rl.close(); + return; + } + + const perPerson = Number(total) / Number(people); + const taxedPerPerson = perPerson * (1 + Number(taxRate) / 100); + + console.log(`1人あたりの金額は${taxedPerPerson}円です。`); + rl.close(); + }); + }); +}); \ No newline at end of file diff --git a/docs/ipo_card_template.md b/docs/ipo_card_template.md index 8409646..cfb95e9 100644 --- a/docs/ipo_card_template.md +++ b/docs/ipo_card_template.md @@ -11,13 +11,13 @@ ## IPOカード -### 機能名: __________ +### 機能名: ____返答処理______ | 項目 | 内容 | |------|------| -| **Input (きっかけ)** | ユーザーが何を入力し、何をするか? | -| **Process (裏側の処理)** | サーバーは何を受け取り、DBに何を保存/削除するか? | -| **Output (結果)** | 処理後、画面はどう変化し、データはどうなっているか? | +| **Input (きっかけ)** | ユーザーは時間に応じた挨拶をインプット +| **Process (裏側の処理)** | サーバーは言葉を受け取り、現在時刻に応じた挨拶文を生成する +| **Output (結果)** | 時間帯に応じた挨拶文を返す ---