diff --git a/README.md b/README.md
index 51abd25..e85aea5 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,199 @@
-# javascript-subway-final
\ No newline at end of file
+# ๐ ์งํ์ฒ ๋
ธ์ ๋ ๊ฒฝ๋ก ์กฐํ ๋ฏธ์
+
+- ๋ฑ๋ก๋ ์งํ์ฒ ๋
ธ์ ๋์์ ๊ฒฝ๋ก๋ฅผ ์กฐํํ๋ ๊ธฐ๋ฅ์ ๊ตฌํํ๋ค.
+
+> ์งํ์ฒ ๋
ธ์ ๋ ๊ฒฝ๋ก ์กฐํ ๋ฏธ์
์ ์ฐ์ํ ํ
ํฌ์ฝ์ค ํ๋ฆฌ์ฝ์ค ์ฝ๋ฉํ
์คํธ์
๋๋ค.
+> ์งํ์ฒ ๋
ธ์ ๋ ๋ฏธ์
์์๋ ์ ์ ๊ฐ ์ด๋ฏธ ๋ฑ๋ก๋ ์งํ์ฒ ์ญ๋ค์ ํตํด ๊ฒฝ๋ก๋ฅผ ์กฐํํ ์ ์์ต๋๋ค.
+
+## โ๏ธ ์ฃผ์ด์ง ์๊ตฌ์ฌํญ
+
+- [์๊ตฌ์ฌํญ](#์๊ตฌ์ฌํญ)
+- [๊ธฐ๋ฅ์๊ตฌ์ฌํญ](#๊ธฐ๋ฅ-์๊ตฌ์ฌํญ)
+- [ํ๋ก๊ทธ๋๋ฐ ์๊ตฌ์ฌํญ](#ํ๋ก๊ทธ๋๋ฐ-์๊ตฌ์ฌํญ)
+- [๋ฏธ์
์ ์ฅ์ ๋ฐ ์งํ ์๊ตฌ์ฌํญ](#๋ฏธ์
-์ ์ฅ์-๋ฐ-์งํ-์๊ตฌ์ฌํญ)
+
+## โ๏ธ ์ฃผ์ด์ง ์ฐธ๊ณ ์ฌํญ
+
+- [ํ๋ก๊ทธ๋จ ์คํ ๊ฒฐ๊ณผ](#ํ๋ก๊ทธ๋จ-์คํ-๊ฒฐ๊ณผ)
+- [์ต๋จ ๊ฒฝ๋ก](#์ต๋จ-๊ฒฝ๋ก-๋ผ์ด๋ธ๋ฌ๋ฆฌ)
+- [ํํธ](#ํํธ)
+
+## โ๏ธ ๊ตฌํํ ๊ธฐ๋ฅ ๋ชฉ๋ก
+
+### ์ ์ฒด
+
+- ํ์ํ ๋ฐ์ดํฐ(์ญ, ๋
ธ์ , ๊ตฌ๊ฐ ๋ฐ์ดํฐ)๋ฅผ ์ด๊ธฐ ์ค์ ํ๋ ๊ธฐ๋ฅ
+ - [์ด๊ธฐ ์ค์ ](#์ด๊ธฐ-์ค์ )์ ์ฐธ๊ณ
+- ์ ์ ๋ก๋ถํฐ ์งํ์ฒ ์ถ๋ฐ์ญ์ ์
๋ ฅ๋ฐ๋ ๊ธฐ๋ฅ
+- ์ ์ ๋ก๋ถํฐ ์งํ์ฒ ๋์ฐฉ์ญ์ ์
๋ ฅ๋ฐ๋ ๊ธฐ๋ฅ
+
+ - ๐ฆ ์์ธ์ํฉ
+ - ์ ์ ๊ฐ ์กด์ฌํ์ง ์๋ ์ญ์ ์ถ๋ฐ/๋์ฐฉ์ญ์ผ๋ก ์
๋ ฅํ์ ๋
+ - ์ ์ ๊ฐ ์ถ๋ฐ/๋์ฐฉ์ญ์ 1๊ธ์ ์ดํ๋ก ์
๋ ฅํ์ ๋
+ - ์ ์ ๊ฐ ์ถ๋ฐ/๋์ฐฉ์ญ์ ๊ฐ๊ฒ ์
๋ ฅํ์ ใธ๋
+ - ์ ์ ๊ฐ ์ฐ๊ฒฐ๋์ง ์์ ์ถ๋ฐ/๋์ฐฉ์ญ์ ์
๋ ฅํ์ ๋
+ - ์ ์ ๊ฐ ์๋ค๋ก ๊ณต๋ฐฑ์ ํฌํจํด ์ถ๋ฐ/๋์ฐฉ์ญ์ ์
๋ ฅํ์ ๋
+
+- ์ ์ ๊ฐ ์ ํํ ์ต๋จ๊ฑฐ๋ฆฌ/์ต์์๊ฐ ์ต์
์ ๋ฐ๋ ๊ธฐ๋ฅ
+- ๊ฒฐ๊ณผ๋ฅผ ํ๋ก ๋ณด์ฌ์ฃผ๋ ๊ธฐ๋ฅ
+
+### ์งํ์ฒ ์ต๋จ๊ฑฐ๋ฆฌ ๊ด๋ จ ๊ธฐ๋ฅ
+
+### ์งํ์ฒ ์ต์์๊ฐ ๊ด๋ จ ๊ธฐ๋ฅ
+
+## ๊ธฐ๋ฅ ์๊ตฌ์ฌํญ
+
+> ํ๋ฆฌ์ฝ์ค 3์ฃผ์ฐจ ๋ฏธ์
์์ ์ฌ์ฉํ ์ฝ๋๋ฅผ ์ฐธ๊ณ ํด๋ ๋ฌด๊ดํ๋ค.
+
+### ์ด๊ธฐ ์ค์
+
+- ํ๋ก๊ทธ๋จ ์์ ์ ์ญ, ๋
ธ์ , ๊ตฌ๊ฐ ๋ฐ์ดํฐ๋ฅผ ์ด๊ธฐ ์ค์ ํด์ผ ํ๋ค.
+- ๊ฑฐ๋ฆฌ์ ์์ ์๊ฐ์ ์์ ์ ์์ด๋ฉฐ ๋จ์๋ km์ ๋ถ์ ์๋ฏธํ๋ค.
+- ์๋์ ์ฌ์ ๋ฑ๋ก ์ ๋ณด๋ก ๋ฐ๋์ ์ด๊ธฐ ์ค์ ์ ํ๋ค.
+
+```
+1. ์งํ์ฒ ์ญ์ผ๋ก ๊ต๋, ๊ฐ๋จ, ์ญ์ผ, ๋จ๋ถํฐ๋ฏธ๋, ์์ฌ, ์์ฌ์๋ฏผ์์ฒ, ๋งค๋ด ์ญ ์ ๋ณด๊ฐ ๋ฑ๋ก๋์ด ์๋ค.
+2. ์งํ์ฒ ๋
ธ์ ์ผ๋ก 2ํธ์ , 3ํธ์ , ์ ๋ถ๋น์ ์ด ๋ฑ๋ก๋์ด ์๋ค.
+3. ๋
ธ์ ์ ์ญ์ด ์๋์ ๊ฐ์ด ๋ฑ๋ก๋์ด ์๋ค.(์ผ์ชฝ ๋์ด ์ํ ์ข
์ )
+ - 2ํธ์ : ๊ต๋ - ( 2km / 3๋ถ ) - ๊ฐ๋จ - ( 2km / 3๋ถ ) - ์ญ์ผ
+ - 3ํธ์ : ๊ต๋ - ( 3km / 2๋ถ ) - ๋จ๋ถํฐ๋ฏธ๋ - ( 6km / 5๋ถ ) - ์์ฌ - ( 1km / 1๋ถ ) - ๋งค๋ด
+ - ์ ๋ถ๋น์ : ๊ฐ๋จ - ( 2km / 8๋ถ ) - ์์ฌ - ( 10km / 3๋ถ ) - ์์ฌ์๋ฏผ์์ฒ
+```
+
+### ๊ฒฝ๋ก ์กฐํ ๊ธฐ๋ฅ
+
+
+
+- ์ถ๋ฐ์ญ๊ณผ ๋์ฐฉ์ญ์ ์
๋ ฅ๋ฐ์ ๊ฒฝ๋ก๋ฅผ ์กฐํํ๋ค.
+- ๊ฒฝ๋ก ์กฐํ ์ ์ด ๊ฑฐ๋ฆฌ, ์ด ์์ ์๊ฐ์ ํจ๊ป ์ถ๋ ฅํ๋ค.
+- ๊ฒฝ๋ก ์กฐํ ์ `์ต๋จ ๊ฑฐ๋ฆฌ` ๋๋ `์ต์ ์๊ฐ` ์ต์
์ ์ ํํ ์ ์๋ค.
+
+### ์์ธ ์ฒ๋ฆฌ
+
+- ์ถ๋ฐ์ญ๊ณผ ๋์ฐฉ์ญ์ 2๊ธ์ ์ด์์ด์ด์ผ ํ๋ค.
+- ์กด์ฌํ์ง ์๋ ์ญ์ ์ถ๋ฐ์ญ ๋๋ ๋์ฐฉ์ญ์ผ๋ก ์
๋ ฅํ ์ ์๋ค.
+- ๊ฒฝ๋ก ์กฐํ ์ ์ถ๋ฐ์ญ๊ณผ ๋์ฐฉ์ญ์ด ๊ฐ์ ์ ์๋ค.
+- ๊ฒฝ๋ก ์กฐํ ์ ์ถ๋ฐ์ญ๊ณผ ๋์ฐฉ์ญ์ด ์ฐ๊ฒฐ๋์ง ์์ผ๋ฉด ๊ฒฝ๋ก๋ฅผ ์กฐํํ ์ ์๋ค.
+- ๊ทธ ์ธ ์ ์์ ์ผ๋ก ํ๋ก๊ทธ๋จ์ด ์ํ๋์ง ์์ ๊ฒฝ์ฐ `alert`์ผ๋ก ์๋ฌ๋ฅผ ์ถ๋ ฅํ๋ค.
+
+
+
+## ํ๋ก๊ทธ๋๋ฐ ์คํ ๊ฒฐ๊ณผ
+
+### ๊ฒฝ๋ก ์กฐํ
+
+
+
+## ํ๋ก๊ทธ๋๋ฐ ์๊ตฌ์ฌํญ
+
+### ๊ธธ์ฐพ๊ธฐ ๊ด๋ จ ๊ธฐ๋ฅ
+
+- ์ถ๋ฐ์ญ์ ์
๋ ฅํ๋ input ํ๊ทธ๋ `departure-station-name-input` id ์์ฑ๊ฐ์ ๊ฐ์ง๋ค.
+- ๋์ฐฉ์ญ์ ์
๋ ฅํ๋ input ํ๊ทธ๋ `arrival-station-name-input` id ์์ฑ๊ฐ์ ๊ฐ์ง๋ค.
+- ์ต๋จ๊ฑฐ๋ฆฌ, ์ต์์๊ฐ์ ์ ํํ๋ radio๋ `search-type` name ์์ฑ๊ฐ์ ๊ฐ์ง๋ค.
+ - **radio option์ default ๊ฐ์ ์ต๋จ๊ฑฐ๋ฆฌ์ด๋ค.**
+- ๊ธธ์ฐพ๊ธฐ ๋ฒํผ์ `search-button` id ์์ฑ๊ฐ์ ๊ฐ์ง๋ค.
+- ๐ ๊ฒฐ๊ณผ๋ `table`์ ์ด์ฉํ์ฌ ๋ณด์ฌ์ค๋ค.
+
+## ํํธ
+
+## ๋ฐ์ดํฐ ์ด๊ธฐํ
+
+์๋ฐ์คํฌ๋ฆฝํธ์์ ๋ฐ์ดํฐ๋ฅผ ์ด๊ธฐํํ๋ ๋ฐฉ๋ฒ ์ค์ ํ๋๋ ์๋์ ๊ฐ์ด data๋ฅผ `export`ํ๊ณ , `import`ํ๋ ๊ฒ์ด๋ค.
+
+```javascript
+export const users = [
+ {
+ name: "Alt",
+ },
+ {
+ name: "Jamie",
+ },
+ {
+ name: "Sony",
+ },
+];
+
+export const courses = [
+ {
+ name: "frontend",
+ },
+ {
+ name: "backend",
+ },
+ {
+ name: "iOS",
+ },
+ {
+ name: "Android",
+ },
+];
+```
+
+์์ ๊ฐ์ด ๋ฐ์ดํฐ๋ฅผ `export`ํ๋ฉด ์๋์ ๊ฐ์ด ๋ฐ์ดํฐ๋ฅผ `import` ํ์ฌ ์ฌ์ฉํ ์ ์๋ค.
+
+```javascript
+import { users, courses } from "./data.js";
+
+function App() {
+ this.users = users;
+ this.courses = courses;
+}
+```
+
+## ์ต๋จ ๊ฒฝ๋ก ๋ผ์ด๋ธ๋ฌ๋ฆฌ
+
+- `utils/Dijkstra.js` ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํ์ฉํ๋ฉด ๊ฐํธํ๊ฒ ์ต๋จ๊ฑฐ๋ฆฌ๋ฅผ ์กฐํํ ์ ์๋ค.
+- ์ ์ (Vertex)๊ณผ ๊ฐ์ (Edge), ๊ทธ๋ฆฌ๊ณ ๊ฐ์ค์น ๊ฐ๋
์ ์ด์ฉ
+ - ์ ์ : ์งํ์ฒ ์ญ
+ - ๊ฐ์ : ์งํ์ฒ ์ญ ์ฐ๊ฒฐ์ ๋ณด
+ - ๊ฐ์ค์น: ๊ฑฐ๋ฆฌ or ์์ ์๊ฐ
+- ์ต๋จ ๊ฑฐ๋ฆฌ ๊ธฐ์ค ์กฐํ ์ ๊ฐ์ค์น๋ฅผ ๊ฑฐ๋ฆฌ๋ก ์ค์
+- ์ต์ ์๊ฐ ๊ธฐ์ค ์กฐํ ์ ๊ฐ์ค์น๋ฅผ ์๊ฐ์ผ๋ก ์ค์
+
+```javascript
+import Dijkstra from "./utils/Dijkstra.js";
+const dijkstra = new Dijkstra();
+
+//dijkstra.addEdge("์ถ๋ฐ์ญ", "๋์ฐฉ์ญ", ๊ฑฐ๋ฆฌ ๋๋ ์๊ฐ);
+dijkstra.addEdge("V1", "V2", 2);
+dijkstra.addEdge("V2", "V3", 2);
+dijkstra.addEdge("V1", "V3", 100);
+
+const result = dijkstra.findShortestPath("V1", "V3");
+// result = ["V1", "V2", "V3"]
+```
+
+#### ํ
์คํธ์ค๋ช
+
+
+
+- ์ญ ์ฌ์ด์ ๊ฑฐ๋ฆฌ๋ฅผ ๊ณ ๋ คํ์ง ์๋ ๊ฒฝ์ฐ V1->V3 ๊ฒฝ๋ก๊ฐ ์ต๋จ ๊ฒฝ๋ก
+- ์ญ ์ฌ์ด์ ๊ฑฐ๋ฆฌ๋ฅผ ๊ณ ๋ คํ ๊ฒฝ์ฐ V1->V3 ๊ฒฝ๋ก์ ๊ฑฐ๋ฆฌ๋ 100km, V1->V2->V3 ๊ฒฝ๋ก์ ๊ฑฐ๋ฆฌ๋ 4km์ด๋ฏ๋ก ์ต๋จ ๊ฒฝ๋ก๋ V1->V2->V3
+
+
+
+### ์๊ตฌ์ฌํญ
+
+- ์ฌ์ฉ์๊ฐ ์๋ชป๋ ์
๋ ฅ ๊ฐ์ ์์ฑํ ๊ฒฝ์ฐ `alert`์ ์ด์ฉํด ๋ฉ์์ง๋ฅผ ๋ณด์ฌ์ฃผ๊ณ , ์ฌ์
๋ ฅํ ์ ์๊ฒ ํ๋ค.
+- ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(jQuery, Lodash ๋ฑ)๋ฅผ ์ฌ์ฉํ์ง ์๊ณ , ์์ Vanilla JS๋ก๋ง ๊ตฌํํ๋ค.
+- **์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋ ์ปจ๋ฒค์
์ ์งํค๋ฉด์ ํ๋ก๊ทธ๋๋ฐ** ํ๋ค
+ - [https://google.github.io/styleguide/jsguide.html](https://google.github.io/styleguide/jsguide.html)
+ - [https://ui.toast.com/fe-guide/ko_CODING-CONVENSION/](https://ui.toast.com/fe-guide/ko_CODING-CONVENTION)
+- **indent(์ธ๋ดํธ, ๋ค์ฌ์ฐ๊ธฐ) depth๋ฅผ 3์ด ๋์ง ์๋๋ก ๊ตฌํํ๋ค. 2๊น์ง๋ง ํ์ฉ**ํ๋ค.
+ - ์๋ฅผ ๋ค์ด while๋ฌธ ์์ if๋ฌธ์ด ์์ผ๋ฉด ๋ค์ฌ์ฐ๊ธฐ๋ 2์ด๋ค.
+ - ํํธ: indent(์ธ๋ดํธ, ๋ค์ฌ์ฐ๊ธฐ) depth๋ฅผ ์ค์ด๋ ์ข์ ๋ฐฉ๋ฒ์ ํจ์(๋๋ ๋ฉ์๋)๋ฅผ ๋ถ๋ฆฌํ๋ฉด ๋๋ค.
+- **ํจ์(๋๋ ๋ฉ์๋)์ ๊ธธ์ด๊ฐ 15๋ผ์ธ์ ๋์ด๊ฐ์ง ์๋๋ก ๊ตฌํํ๋ค.**
+ - ํจ์(๋๋ ๋ฉ์๋)๊ฐ ํ ๊ฐ์ง ์ผ๋ง ์ ํ๋๋ก ๊ตฌํํ๋ค.
+- ๋ณ์ ์ ์ธ์ [var](https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Statements/var) ๋ฅผ ์ฌ์ฉํ์ง ์๋๋ค. [const](https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Statements/const) ์ [let](https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Statements/let) ์ ์ฌ์ฉํ๋ค.
+- [import](https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Statements/import) ๋ฌธ์ ์ด์ฉํด ์คํฌ๋ฆฝํธ๋ฅผ ๋ชจ๋ํํ๊ณ ๋ถ๋ฌ์ฌ ์ ์๊ฒ ๋ง๋ ๋ค.
+- [template literal](https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Template_literals)์ ์ด์ฉํด ๋ฐ์ดํฐ์ html string์ ๊ฐ๋
์ฑ ์ข๊ฒ ํํํ๋ค.
+
+
+
+## ๋ฏธ์
์ ์ฅ์ ๋ฐ ์งํ ์๊ตฌ์ฌํญ
+
+- ๋ฏธ์
์ [https://github.com/woowacourse/javascript-subway-path-precourse](https://github.com/woowacourse/javascript-subway-path-precourse) ์ ์ฅ์๋ฅผ fork/cloneํด ์์ํ๋ค.
+- **๊ธฐ๋ฅ์ ๊ตฌํํ๊ธฐ ์ ์ javascript-subway-path-precourse/docs/README.md ํ์ผ์ ๊ตฌํํ ๊ธฐ๋ฅ ๋ชฉ๋ก**์ ์ ๋ฆฌํด ์ถ๊ฐํ๋ค.
+- **git์ commit ๋จ์๋ ์ ๋จ๊ณ์์ README.md ํ์ผ์ ์ ๋ฆฌํ ๊ธฐ๋ฅ ๋ชฉ๋ก ๋จ์๋ก ์ถ๊ฐ**ํ๋ค.
+- [ํ๋ฆฌ์ฝ์ค ๊ณผ์ ์ ์ถ](https://github.com/woowacourse/woowacourse-docs/tree/master/precourse) ๋ฌธ์ ์ ์ฐจ๋ฅผ ๋ฐ๋ผ ๋ฏธ์
์ ์ ์ถํ๋ค.
diff --git a/images/dijkstra_example.png b/images/dijkstra_example.png
new file mode 100644
index 0000000..7c75197
Binary files /dev/null and b/images/dijkstra_example.png differ
diff --git a/images/path_result.gif b/images/path_result.gif
new file mode 100644
index 0000000..ee394bd
Binary files /dev/null and b/images/path_result.gif differ
diff --git a/images/path_result.jpg b/images/path_result.jpg
new file mode 100644
index 0000000..40a4bed
Binary files /dev/null and b/images/path_result.jpg differ
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..43a0efa
--- /dev/null
+++ b/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+ ์งํ์ฒ ๊ธธ์ฐพ๊ธฐ
+
+
+
+
๐ ์งํ์ฒ ๊ธธ์ฐพ๊ธฐ
+
+
+
+
diff --git a/src/components/find-path-input-container.js b/src/components/find-path-input-container.js
new file mode 100644
index 0000000..7bf4404
--- /dev/null
+++ b/src/components/find-path-input-container.js
@@ -0,0 +1,46 @@
+import { makeStringToHTML } from "../utils/display/display-utils.js";
+
+import { dijkstraTime, dijkstraDistance } from "../utils/make-edges.js";
+import {
+ validateInput,
+ checkIfStartAndEndSame,
+} from "../utils/input/validator/input-validator.js";
+import { minPath, newResult } from "./find-path-result-container.js";
+
+const app = document.getElementById("app");
+
+export default function findPath() {
+ const subwayPathHTML = `
+
+ ์ถ๋ฐ์ญ
+ ๋์ฐฉ์ญ
+ ์ต๋จ๊ฑฐ๋ฆฌ
+ ์ต์์๊ฐ
+
+
+ `;
+ app.append(makeStringToHTML(subwayPathHTML).firstElementChild);
+
+ const searchButton = document.getElementById("search-button");
+ searchButton.addEventListener("click", () => {
+ const selected = document.querySelector('input[name="search-type"]:checked')
+ .value;
+ const startStation = document.getElementById("departure-station-name-input")
+ .value;
+ const endStation = document.getElementById("arrival-station-name-input")
+ .value;
+ newResult();
+
+ if (!startStation && !endStation) {
+ return checkIfStartAndEndSame(startStation, endStation);
+ }
+
+ if (validateInput(startStation) && validateInput(endStation)) {
+ if (selected === "distance") {
+ minPath(dijkstraDistance, startStation, endStation);
+ } else if (selected === "time") {
+ minPath(dijkstraTime, startStation, endStation);
+ }
+ }
+ });
+}
diff --git a/src/components/find-path-result-container.js b/src/components/find-path-result-container.js
new file mode 100644
index 0000000..a7fb475
--- /dev/null
+++ b/src/components/find-path-result-container.js
@@ -0,0 +1,119 @@
+import {
+ makeStringToHTML,
+ clearElement,
+} from "../utils/display/display-utils.js";
+import { lines } from "../data.js";
+
+export function newResult() {
+ resultWrapper();
+
+ const result = document.getElementById("result");
+ clearElement(result);
+ resultPath(result);
+ resultPathTable(result);
+}
+
+function resultWrapper() {
+ const resultWrapperHTML = ``;
+ app.append(makeStringToHTML(resultWrapperHTML).firstElementChild);
+}
+
+function resultPath(parent) {
+ const subwayPathTitleHTML = `๐ ๊ฒฐ๊ณผ
`;
+ parent.append(makeStringToHTML(subwayPathTitleHTML).firstElementChild);
+}
+
+export function minPath(distanceOrTimeDijkstra, startStation, endStation) {
+ const tbody = document.getElementsByTagName("tbody")[0];
+ const shortestDistance = distanceOrTimeDijkstra.findShortestPath(
+ startStation,
+ endStation
+ );
+
+ tbody.append(
+ distanceAndTimeRow(
+ totalDistance(shortestDistance)[0],
+ totalDistance(shortestDistance)[1]
+ ),
+
+ resultPathStations(shortestDistance)
+ );
+
+ return shortestDistance;
+}
+
+function resultPathStations(result) {
+ const td = document.createElement("td");
+ let resultStations = "";
+
+ for (let i = 0; i < result.length; i++) {
+ resultStations += result[i];
+ if (result[i + 1]) {
+ resultStations += "โก";
+ }
+ }
+
+ td.textContent = resultStations;
+ td.colSpan = 2;
+
+ return td;
+}
+
+function textInTd(innerText) {
+ const td = document.createElement("td");
+ td.textContent = innerText;
+
+ return td;
+}
+
+function distanceAndTimeRow(...args) {
+ const tr = document.createElement("tr");
+
+ for (const text of [...args]) {
+ const tdWithText = textInTd(text);
+ tr.append(tdWithText);
+ }
+
+ return tr;
+}
+
+function resultPathTable(parent) {
+ const subwayPathTableHTML = `
+
+
+
+ | ์ด ๊ฑฐ๋ฆฌ |
+ ์ด ์์ ์๊ฐ |
+
+
+
+
+
+ `;
+ parent.append(makeStringToHTML(subwayPathTableHTML).firstElementChild);
+}
+
+function totalDistance(result) {
+ const totalDistanceAndTimeArray = [];
+ let totalDistances = 0;
+ let totalTimes = 0;
+
+ for (const line of lines) {
+ for (const station of line.stations) {
+ for (let i = 0; i < result.length - 1; i++) {
+ if (
+ (result[i] === station.name &&
+ result[i + 1] === station.nextStation) ||
+ (result[i] === station.nextStation && result[i + 1] === station.name)
+ ) {
+ totalDistances += station.distance;
+ totalTimes += station.time;
+ }
+ }
+ }
+ }
+
+ totalDistanceAndTimeArray.push(totalDistances + "km", totalTimes + "๋ถ");
+
+ return totalDistanceAndTimeArray;
+}
diff --git a/src/data.js b/src/data.js
new file mode 100644
index 0000000..5dd1a50
--- /dev/null
+++ b/src/data.js
@@ -0,0 +1,77 @@
+export const lines = [
+ {
+ lineName: "2ํธ์ ",
+ stations: [
+ {
+ name: "๊ต๋",
+ nextStation: "๊ฐ๋จ",
+ distance: 2,
+ time: 3,
+ },
+ {
+ name: "๊ฐ๋จ",
+ nextStation: "์ญ์ผ",
+ distance: 2,
+ time: 3,
+ },
+ {
+ name: "์ญ์ผ",
+ nextStation: null,
+ distance: null,
+ time: null,
+ },
+ ],
+ },
+ {
+ lineName: "3ํธ์ ",
+ stations: [
+ {
+ name: "๊ต๋",
+ nextStation: "๋จ๋ถํฐ๋ฏธ๋",
+ distance: 3,
+ time: 2,
+ },
+ {
+ name: "๋จ๋ถํฐ๋ฏธ๋",
+ nextStation: "์์ฌ",
+ distance: 6,
+ time: 5,
+ },
+ {
+ name: "์์ฌ",
+ nextStation: "๋งค๋ด",
+ distance: 1,
+ time: 1,
+ },
+ {
+ name: "๋งค๋ด",
+ nextStation: null,
+ distance: null,
+ time: null,
+ },
+ ],
+ },
+ {
+ lineName: "์ ๋ถ๋น์ ",
+ stations: [
+ {
+ name: "๊ฐ๋จ",
+ nextStation: "์์ฌ",
+ distance: 2,
+ time: 8,
+ },
+ {
+ name: "์์ฌ",
+ nextStation: "์์ฌ์๋ฏผ์์ฒ",
+ distance: 10,
+ time: 3,
+ },
+ {
+ name: "์์ฌ์๋ฏผ์์ฒ",
+ nextStation: null,
+ distance: null,
+ time: null,
+ },
+ ],
+ },
+];
diff --git a/src/index.js b/src/index.js
new file mode 100644
index 0000000..3f8e23d
--- /dev/null
+++ b/src/index.js
@@ -0,0 +1,9 @@
+import findPath from "./components/find-path-input-container.js";
+
+function subwayPath() {
+ findPath();
+}
+
+new subwayPath();
+
+// ์ฒซ ํ๋ฉด ๊ทธ๋ฆฌ๊ธฐ
diff --git a/src/utils/Dijkstra.js b/src/utils/Dijkstra.js
new file mode 100644
index 0000000..7c6cfd5
--- /dev/null
+++ b/src/utils/Dijkstra.js
@@ -0,0 +1,220 @@
+export default function Dijkstra() {
+ const Node = {
+ init: function (val, priority) {
+ this.val = val;
+ this.priority = priority;
+ },
+ };
+
+ const PriorityQueue = {
+ init: function () {
+ this.values = [];
+ },
+ enqueue: function (val, priority) {
+ const newNode = Object.create(Node);
+ newNode.init(val, priority);
+
+ this.values.push(newNode);
+
+ let idxOfNewNode = this.values.length - 1;
+
+ while (idxOfNewNode > 0) {
+ const idxOfParentNode = Math.floor((idxOfNewNode - 1) / 2);
+
+ const parentNode = this.values[idxOfParentNode];
+
+ if (priority < parentNode.priority) {
+ this.values[idxOfParentNode] = newNode;
+ this.values[idxOfNewNode] = parentNode;
+ idxOfNewNode = idxOfParentNode;
+ continue;
+ }
+ break;
+ }
+ return this.values;
+ },
+ dequeue: function () {
+ if (this.values.length == 0) {
+ return;
+ }
+ const dequeued = this.values.shift();
+ const lastItem = this.values.pop();
+ if (!lastItem) {
+ return dequeued;
+ }
+ this.values.unshift(lastItem);
+
+ let idxOfTarget = 0;
+
+ while (true) {
+ let idxOfLeftChild = idxOfTarget * 2 + 1;
+ let idxOfRightChild = idxOfTarget * 2 + 2;
+ let leftChild = this.values[idxOfLeftChild];
+ let rightChild = this.values[idxOfRightChild];
+
+ function swap(direction) {
+ const idxOfChild =
+ direction == "left" ? idxOfLeftChild : idxOfRightChild;
+ const child = direction == "left" ? leftChild : rightChild;
+ this.values[idxOfChild] = this.values[idxOfTarget];
+ this.values[idxOfTarget] = child;
+ idxOfTarget = idxOfChild;
+ }
+
+ if (!leftChild) {
+ return dequeued;
+ }
+
+ if (!rightChild) {
+ if (leftChild.priority < lastItem.priority) {
+ swap.call(this, "left");
+ continue;
+ }
+ return dequeued;
+ }
+
+ if (leftChild.priority == rightChild.priority) {
+ swap.call(this, "left");
+ continue;
+ }
+
+ if (
+ leftChild.priority < rightChild.priority &&
+ leftChild.priority < lastItem.priority
+ ) {
+ swap.call(this, "left");
+ continue;
+ }
+
+ if (
+ rightChild.priority < leftChild.priority &&
+ rightChild.priority < lastItem.priority
+ ) {
+ swap.call(this, "right");
+ continue;
+ }
+ }
+ },
+ };
+
+ const WeightedGraph = {
+ init: function () {
+ this.adjacencyList = {};
+ this.length = 0;
+ },
+ addVertex: function (vertex) {
+ if (!this.adjacencyList.hasOwnProperty(vertex)) {
+ this.adjacencyList[vertex] = {};
+ this.length++;
+ }
+ },
+ addEdge: function (vertex1, vertex2, weight) {
+ this.addVertex(vertex1);
+ this.addVertex(vertex2);
+ this.adjacencyList[vertex1][vertex2] = weight;
+ this.adjacencyList[vertex2][vertex1] = weight;
+ return this.adjacencyList;
+ },
+ removeEdge: function (vertex1, vertex2) {
+ if (!this.adjacencyList.hasOwnProperty(vertex1)) {
+ return `There's no ${vertex1}`;
+ }
+ if (!this.adjacencyList.hasOwnProperty(vertex2)) {
+ return `There's no ${vertex2}`;
+ }
+
+ function removeHelper(v1, v2) {
+ if (!this.adjacencyList.hasOwnProperty(v1)) {
+ return `There's no edge between ${v1} and ${v2}`;
+ }
+ delete this.adjacencyList[v1][v2];
+ if (Object.keys(this.adjacencyList[v1]).length == 0) {
+ delete this.adjacencyList[v1];
+ }
+ }
+
+ removeHelper.call(this, vertex1, vertex2);
+ removeHelper.call(this, vertex2, vertex1);
+
+ return this.adjacencyList;
+ },
+ removeVertex: function (vertex) {
+ if (!this.adjacencyList.hasOwnProperty(vertex)) {
+ return `There's no ${vertex}`;
+ }
+ const edges = this.adjacencyList[vertex];
+ for (const key in edges) {
+ this.removeEdge(key, vertex);
+ }
+ return this.adjacencyList;
+ },
+ findShortestRoute: function (start, end) {
+ if (!start || !end) {
+ throw Error("์ถ๋ฐ์ง์ ๋์ฐฉ์ง๋ฅผ ๋ชจ๋ ์
๋ ฅํด์ผ ํฉ๋๋ค.");
+ }
+ const distance = {};
+ const previous = {};
+ const pq = Object.create(PriorityQueue);
+ pq.init();
+ pq.enqueue(start, 0);
+ const visited = {};
+
+ const hashOfVertex = this.adjacencyList;
+ for (const vertexName in hashOfVertex) {
+ const priority = vertexName == start ? 0 : Infinity;
+ distance[vertexName] = priority;
+ previous[vertexName] = null;
+ }
+
+ while (true) {
+ let current = pq.dequeue();
+ if (!current?.val) {
+ return;
+ }
+ current = current.val;
+ if (current == end) {
+ break;
+ }
+ const neighbors = hashOfVertex[current];
+
+ for (const vertexName in neighbors) {
+ if (visited.hasOwnProperty(vertexName)) {
+ continue;
+ }
+ const distFromStart = distance[current] + neighbors[vertexName];
+
+ if (distFromStart < distance[vertexName]) {
+ pq.enqueue(vertexName, distFromStart);
+ distance[vertexName] = distFromStart;
+ previous[vertexName] = current;
+ }
+ }
+ visited[current] = true;
+ }
+
+ let node = end;
+
+ const route = [];
+ while (node) {
+ route.unshift(node);
+ node = previous[node];
+ }
+
+ return route;
+ },
+ };
+
+ this.addEdge = (source, target, weight) => {
+ WeightedGraph.addEdge(source, target, weight);
+ };
+
+ this.findShortestPath = (source, target) => {
+ return WeightedGraph.findShortestRoute(source, target);
+ };
+
+ this.addVertex = (vertex) => {
+ WeightedGraph.addVertex(vertex);
+ };
+
+ WeightedGraph.init();
+}
diff --git a/src/utils/display/display-utils.js b/src/utils/display/display-utils.js
new file mode 100644
index 0000000..80cd2a2
--- /dev/null
+++ b/src/utils/display/display-utils.js
@@ -0,0 +1,11 @@
+const parser = new DOMParser();
+
+export function makeStringToHTML(string) {
+ return parser.parseFromString(string, "text/html").body;
+}
+
+export function clearElement(element) {
+ if (element) {
+ element.innerHTML = "";
+ }
+}
diff --git a/src/utils/input/validator/input-validator.js b/src/utils/input/validator/input-validator.js
new file mode 100644
index 0000000..05bfe18
--- /dev/null
+++ b/src/utils/input/validator/input-validator.js
@@ -0,0 +1,47 @@
+import { lines } from "../../../data.js";
+
+function isValidStation(input) {
+ const allStationArray = [...allStations()];
+ let isValid = false;
+
+ if (!allStationArray.includes(input)) {
+ isValid = true;
+ }
+
+ return isValid;
+}
+
+function allStations() {
+ const allStations = [];
+ for (const line of lines) {
+ for (const station of line.stations) {
+ allStations.push(station.name);
+ }
+ }
+ const notDuplicatedStations = new Set([...allStations]);
+
+ return notDuplicatedStations;
+}
+
+export function validateInput(input) {
+ const MINIMUM_INPUT_LENGTH = 2;
+ const noSpaceInput = input.trim();
+
+ let isValid = false;
+
+ if (noSpaceInput.length < MINIMUM_INPUT_LENGTH) {
+ alert("2๊ธ์ ์ด์์ ์ญ ์ด๋ฆ์ ์
๋ ฅํ์
์ผ ํฉ๋๋ค!");
+ } else if (isValidStation(noSpaceInput)) {
+ alert("์กด์ฌํ์ง ์๋ ์ญ์
๋๋ค.");
+ } else {
+ isValid = true;
+ }
+
+ return isValid;
+}
+
+export function checkIfStartAndEndSame(startStation, endStation) {
+ if (startStation === endStation) {
+ alert("์ถ๋ฐ์ญ๊ณผ ๋์ฐฉ์ญ์ ๊ฐ์ ์ ์์ต๋๋ค.");
+ }
+}
diff --git a/src/utils/make-edges.js b/src/utils/make-edges.js
new file mode 100644
index 0000000..62fa870
--- /dev/null
+++ b/src/utils/make-edges.js
@@ -0,0 +1,21 @@
+import Dijkstra from "../utils/Dijkstra.js";
+import { lines } from "../data.js";
+export const dijkstraTime = new Dijkstra();
+export const dijkstraDistance = new Dijkstra();
+
+for (const line of lines) {
+ for (const station of line.stations) {
+ addEdge(station);
+ }
+}
+
+function addEdge(station) {
+ if (station.nextStation !== null) {
+ dijkstraDistance.addEdge(
+ station.name,
+ station.nextStation,
+ station.distance
+ );
+ dijkstraTime.addEdge(station.name, station.nextStation, station.time);
+ }
+}