Showing
5 changed files
with
395 additions
and
0 deletions
nodejs/.gitignore
0 → 100644
nodejs/package.json
0 → 100644
1 | +{ | ||
2 | + "name": "holiday-counter-recommend-activity", | ||
3 | + "version": "1.0.0", | ||
4 | + "description": "", | ||
5 | + "main": "server.js", | ||
6 | + "scripts": { | ||
7 | + "test": "echo \"Error: no test specified\" && exit 1", | ||
8 | + "start": "node server.js" | ||
9 | + }, | ||
10 | + "repository": { | ||
11 | + "type": "git", | ||
12 | + "url": "http://khuhub.khu.ac.kr/teamPARK/holiday-counter-recommand-activity.git" | ||
13 | + }, | ||
14 | + "author": "", | ||
15 | + "license": "ISC", | ||
16 | + "dependencies": { | ||
17 | + "dotenv": "^16.0.1", | ||
18 | + "ejs": "^3.1.8", | ||
19 | + "express": "^4.18.1", | ||
20 | + "request": "^2.88.2", | ||
21 | + "xml2js": "^0.4.23" | ||
22 | + } | ||
23 | +} |
nodejs/public/css/main.css
0 → 100644
1 | +.circle { | ||
2 | + margin: 0 auto; | ||
3 | + width: 500px; | ||
4 | + height: 500px; | ||
5 | + border: 15px solid rgb(163, 151, 198); | ||
6 | + border-radius: 50%; | ||
7 | + line-height: 3em; | ||
8 | +} | ||
9 | +.dday { | ||
10 | + padding: 50px 0; | ||
11 | +} | ||
12 | + | ||
13 | +.wrapper { | ||
14 | + margin: 0 auto; | ||
15 | + padding: 30px; | ||
16 | + max-width: 1170px; | ||
17 | +} | ||
18 | +h1 { | ||
19 | + font-size: 50px; | ||
20 | + color : tomato; | ||
21 | + font-family: 'Gowun Dodum', sans-serif; | ||
22 | + margin-bottom: 10px; | ||
23 | +} | ||
24 | +h2 { | ||
25 | + color :white; | ||
26 | + font-weight: lighter; | ||
27 | + font-family: 'Gowun Dodum', sans-serif; | ||
28 | +} | ||
29 | + | ||
30 | +#title { | ||
31 | + color: rgb(191, 185, 211); | ||
32 | + font-size: 70px; | ||
33 | + font-family: 'Tiro Devanagari Marathi', serif; | ||
34 | + font-weight: 600; | ||
35 | + text-shadow: 4px 2px 2px rgba(178, 104, 180, 0.61); | ||
36 | + letter-spacing: 0.05em; | ||
37 | +} | ||
38 | +#comment { | ||
39 | + width: fit-content; | ||
40 | + background-color: rgba(190, 125, 87, 0.39); | ||
41 | + border-radius: 40px 80px / 80px 40px; | ||
42 | + | ||
43 | +} | ||
44 | +#detail { | ||
45 | + width:1000px; | ||
46 | + height:fit-content; | ||
47 | + border-radius: 40px 80px / 80px 40px; | ||
48 | + background-color: rgba(190, 87, 168, 0.39); | ||
49 | +} | ||
50 | +body { | ||
51 | + margin-top: 100px; | ||
52 | + margin-bottom: 100px; | ||
53 | + margin-left: 50px; | ||
54 | + margin-right: 50px; | ||
55 | + background-color: rgb(78, 76, 76); | ||
56 | +} | ||
57 | +#background{ | ||
58 | + width : 80%; | ||
59 | + height : 80%; | ||
60 | + border: 15px solid rgb(229, 220, 231); | ||
61 | + border-radius : 30px 30px / 30px 30px; | ||
62 | + | ||
63 | +} | ||
64 | +.box { | ||
65 | + margin : 50px; | ||
66 | + padding : 20px; | ||
67 | + border : 1px solid rgb(248, 239, 249); | ||
68 | + border-radius : 20px; | ||
69 | + background-color: rgb(255, 255, 255); | ||
70 | +} | ||
71 | + | ||
72 | +/* button style*/ | ||
73 | +.frame { | ||
74 | + width: 90%; | ||
75 | + margin: 40px auto; | ||
76 | + text-align: center; | ||
77 | +} | ||
78 | +button { | ||
79 | + margin: 20px; | ||
80 | +} | ||
81 | +.custom-btn { | ||
82 | + width: 130px; | ||
83 | + height: 40px; | ||
84 | + color: #fff; | ||
85 | + border-radius: 5px; | ||
86 | + padding: 10px 25px; | ||
87 | + font-family: 'Lato', sans-serif; | ||
88 | + font-weight: 500; | ||
89 | + background: transparent; | ||
90 | + cursor: pointer; | ||
91 | + transition: all 0.3s ease; | ||
92 | + position: relative; | ||
93 | + display: inline-block; | ||
94 | + box-shadow:inset 2px 2px 2px 0px rgba(255,255,255,.5), | ||
95 | + 7px 7px 20px 0px rgba(0,0,0,.1), | ||
96 | + 4px 4px 5px 0px rgba(0,0,0,.1); | ||
97 | + outline: none; | ||
98 | +} | ||
99 | +.btn-12{ | ||
100 | + position: relative; | ||
101 | + right: 20px; | ||
102 | + bottom: 20px; | ||
103 | + border:none; | ||
104 | + box-shadow: none; | ||
105 | + width: 130px; | ||
106 | + height: 40px; | ||
107 | + line-height: 42px; | ||
108 | + -webkit-perspective: 230px; | ||
109 | + perspective: 230px; | ||
110 | +} | ||
111 | +.btn-12 span { | ||
112 | + background: rgb(0,172,238); | ||
113 | +background: linear-gradient(0deg, rgba(0,172,238,1) 0%, rgba(2,126,251,1) 100%); | ||
114 | + display: block; | ||
115 | + position: absolute; | ||
116 | + width: 130px; | ||
117 | + height: 40px; | ||
118 | + box-shadow:inset 2px 2px 2px 0px rgba(255,255,255,.5), | ||
119 | + 7px 7px 20px 0px rgba(0,0,0,.1), | ||
120 | + 4px 4px 5px 0px rgba(0,0,0,.1); | ||
121 | + border-radius: 5px; | ||
122 | + margin:0; | ||
123 | + text-align: center; | ||
124 | + -webkit-box-sizing: border-box; | ||
125 | + -moz-box-sizing: border-box; | ||
126 | + box-sizing: border-box; | ||
127 | + -webkit-transition: all .3s; | ||
128 | + transition: all .3s; | ||
129 | +} | ||
130 | +.btn-12 span:nth-child(1) { | ||
131 | + box-shadow: | ||
132 | + -7px -7px 20px 0px #fff9, | ||
133 | + -4px -4px 5px 0px #fff9, | ||
134 | + 7px 7px 20px 0px #0002, | ||
135 | + 4px 4px 5px 0px #0001; | ||
136 | + -webkit-transform: rotateX(90deg); | ||
137 | + -moz-transform: rotateX(90deg); | ||
138 | + transform: rotateX(90deg); | ||
139 | + -webkit-transform-origin: 50% 50% -20px; | ||
140 | + -moz-transform-origin: 50% 50% -20px; | ||
141 | + transform-origin: 50% 50% -20px; | ||
142 | +} | ||
143 | +.btn-12 span:nth-child(2) { | ||
144 | + -webkit-transform: rotateX(0deg); | ||
145 | + -moz-transform: rotateX(0deg); | ||
146 | + transform: rotateX(0deg); | ||
147 | + -webkit-transform-origin: 50% 50% -20px; | ||
148 | + -moz-transform-origin: 50% 50% -20px; | ||
149 | + transform-origin: 50% 50% -20px; | ||
150 | +} | ||
151 | +.btn-12:hover span:nth-child(1) { | ||
152 | + box-shadow:inset 2px 2px 2px 0px rgba(255,255,255,.5), | ||
153 | + 7px 7px 20px 0px rgba(0,0,0,.1), | ||
154 | + 4px 4px 5px 0px rgba(0,0,0,.1); | ||
155 | + -webkit-transform: rotateX(0deg); | ||
156 | + -moz-transform: rotateX(0deg); | ||
157 | + transform: rotateX(0deg); | ||
158 | +} | ||
159 | +.btn-12:hover span:nth-child(2) { | ||
160 | + box-shadow:inset 2px 2px 2px 0px rgba(255,255,255,.5), | ||
161 | + 7px 7px 20px 0px rgba(0,0,0,.1), | ||
162 | + 4px 4px 5px 0px rgba(0,0,0,.1); | ||
163 | + color: transparent; | ||
164 | + -webkit-transform: rotateX(-90deg); | ||
165 | + -moz-transform: rotateX(-90deg); | ||
166 | + transform: rotateX(-90deg); | ||
167 | +} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
nodejs/server.js
0 → 100644
1 | +const express = require("express"); | ||
2 | +const app = express(); | ||
3 | +const request = require("request"); | ||
4 | +const xml2js = require("xml2js"); | ||
5 | +const static = require("serve-static"); | ||
6 | +require("dotenv").config(); | ||
7 | + | ||
8 | +// Modify the values as needed | ||
9 | +var year = "2022"; | ||
10 | +var month = "09"; | ||
11 | +var operation = "getRestDeInfo"; | ||
12 | + | ||
13 | +// Do not modify the values | ||
14 | +var SERVEICE_KEY = process.env.API_KEY; | ||
15 | +var url = "http://apis.data.go.kr/B090041/openapi/service/SpcdeInfoService/"; | ||
16 | +var queryParams = "?" + "solYear" + "=" + year; | ||
17 | +queryParams += "&" + "solMonth" + "=" + month; | ||
18 | +queryParams += "&" + "ServiceKey" + "=" + SERVEICE_KEY; | ||
19 | +let requestUrl = url + operation + queryParams; | ||
20 | + | ||
21 | +// Empty variables | ||
22 | +var text = ""; | ||
23 | +var dateName = []; | ||
24 | +var locdate = []; | ||
25 | +var tempArr = []; | ||
26 | + | ||
27 | +// To run EJS engine | ||
28 | +app.set("views", __dirname + "/views"); | ||
29 | +app.set("view engine", "ejs"); | ||
30 | +app.use(static(__dirname)); | ||
31 | + | ||
32 | +// To get today date by using Date | ||
33 | +function getTodayDate() { | ||
34 | + var today = new Date(); | ||
35 | + var year = today.getFullYear(); | ||
36 | + var month = ("0" + (today.getMonth() + 1)).slice(-2); | ||
37 | + var day = ("0" + today.getDate()).slice(-2); | ||
38 | + var dateString = year + "-" + month + "-" + day; | ||
39 | + //return "2022-06-02"; // 테스트용 날짜를 입력하세요. *** 테스트가 끝나면 주석처리하고 커밋해주세요. *** ex) 2022-09-12, 2022-09-15, 2022-10-04 | ||
40 | + return dateString; | ||
41 | +} | ||
42 | + | ||
43 | +// To get modified date from locdate | ||
44 | +function getModifiedDate(locdate) { | ||
45 | + return ( | ||
46 | + locdate.substr(0, 4) + | ||
47 | + "-" + | ||
48 | + locdate.substr(4, 2) + | ||
49 | + "-" + | ||
50 | + locdate.substr(6, 2) | ||
51 | + ); | ||
52 | +} | ||
53 | + | ||
54 | +// To get remaining days from locdate | ||
55 | +function getLeftDate(locdate) { | ||
56 | + var today = new Date(getTodayDate()); // today date | ||
57 | + var holiday = new Date(getModifiedDate(locdate)); // holiday date | ||
58 | + var diffDate = today.getTime() - holiday.getTime(); | ||
59 | + var dday = Math.abs(diffDate / (1000 * 3600 * 24)); | ||
60 | + return dday; | ||
61 | +} | ||
62 | + | ||
63 | +// To change parameter | ||
64 | +function changeParams(year, month, operation) { | ||
65 | + queryParams = "?" + "solYear" + "=" + year; | ||
66 | + queryParams += "&" + "solMonth" + "=" + month; | ||
67 | + queryParams += "&" + "ServiceKey" + "=" + SERVEICE_KEY; | ||
68 | + requestUrl = url + operation + queryParams; | ||
69 | +} | ||
70 | + | ||
71 | +// To check is this left holiday | ||
72 | +function cmpDate(date) { | ||
73 | + var today = getTodayDate().replace(/\-/g, ""); | ||
74 | + if (Number(today) <= Number(date)) { | ||
75 | + return true; | ||
76 | + } | ||
77 | +} | ||
78 | + | ||
79 | +// To get data from holiday api by using parmas | ||
80 | +function getData() { | ||
81 | + request.get(requestUrl, (err, res, body) => { | ||
82 | + if (err) { | ||
83 | + console.log("err => " + err); | ||
84 | + } else { | ||
85 | + if (res.statusCode == 200) { | ||
86 | + // Read url success | ||
87 | + var result = body; | ||
88 | + var parser = new xml2js.Parser(); | ||
89 | + parser.parseString(result, function (err, res) { | ||
90 | + text = JSON.stringify(res); | ||
91 | + // Get dataName method | ||
92 | + dateName = []; | ||
93 | + var idx = text.indexOf("dateName", 0); | ||
94 | + while (idx != -1) { | ||
95 | + var start = text.indexOf("[", idx) + 2; | ||
96 | + var end = text.indexOf("]", idx) - 1; | ||
97 | + var tempStr = text.substring(start, end); | ||
98 | + dateName.push(tempStr); | ||
99 | + idx = text.indexOf("dateName", idx + 1); | ||
100 | + } | ||
101 | + console.log(dateName); | ||
102 | + // Get locdate method | ||
103 | + locdate = []; | ||
104 | + idx = text.indexOf("locdate", 0); | ||
105 | + while (idx != -1) { | ||
106 | + var start = text.indexOf("[", idx) + 2; | ||
107 | + var end = text.indexOf("]", idx) - 1; | ||
108 | + var tempStr = text.substring(start, end); | ||
109 | + locdate.push(tempStr); | ||
110 | + idx = text.indexOf("locdate", idx + 1); | ||
111 | + } | ||
112 | + console.log(locdate); | ||
113 | + var holiArr = []; | ||
114 | + for (var i = 0; i < dateName.length; i++) { | ||
115 | + holiArr.push(getLeftDate(locdate[i])); | ||
116 | + } | ||
117 | + console.log(holiArr); | ||
118 | + // Create tempArr to save dateName and locdate and leftDate at once | ||
119 | + tempArr = []; | ||
120 | + // To check left holiday | ||
121 | + var check = false; | ||
122 | + for (var i = 0; i < locdate.length; i++) { | ||
123 | + if (cmpDate(locdate[i])) { | ||
124 | + check = true; | ||
125 | + tempArr.push(dateName[i]); // Get recent holiday name | ||
126 | + tempArr.push(locdate[i]); // Get recent holiday date | ||
127 | + tempArr.push(holiArr[i]); // Get leftDate through locdate | ||
128 | + break; | ||
129 | + } | ||
130 | + } | ||
131 | + console.log(tempArr); | ||
132 | + if (!check) { | ||
133 | + // If there are no holidays left this month | ||
134 | + console.log( | ||
135 | + "이번 달에는 남은 공휴일이 없습니다. 다음달 데이터를 불러옵니다." | ||
136 | + ); | ||
137 | + if (Number(month) < 12) { | ||
138 | + // Get next month data | ||
139 | + month = String(Number(month) + 1).padStart(2, "0"); | ||
140 | + } else { | ||
141 | + // Get next year data | ||
142 | + year = String(Number(year) + 1).padStart(4, "0"); | ||
143 | + month = "01"; | ||
144 | + } | ||
145 | + changeParams(year, month, operation); | ||
146 | + getData(); | ||
147 | + } | ||
148 | + console.log("* api로부터 데이터를 불러왔습니다."); | ||
149 | + console.log("오늘의 날짜는", getTodayDate(), "입니다."); | ||
150 | + console.log( | ||
151 | + "가장 가까운 공휴일인 [" + | ||
152 | + tempArr[0] + | ||
153 | + "]의 날짜는 [" + | ||
154 | + tempArr[1] + | ||
155 | + "]이고, [" + | ||
156 | + tempArr[2] + | ||
157 | + "]일 남았습니다." | ||
158 | + ); | ||
159 | + }); | ||
160 | + } | ||
161 | + } | ||
162 | + }); | ||
163 | +} | ||
164 | + | ||
165 | +// To initialize datas when calling webpage | ||
166 | +function init() { | ||
167 | + // Intialize Year, Month | ||
168 | + var date = getTodayDate().split("-"); | ||
169 | + year = date[0]; | ||
170 | + month = date[1]; | ||
171 | + operation = "getRestDeInfo"; | ||
172 | + changeParams(year, month, operation); | ||
173 | + // Get data from holiday api | ||
174 | + getData(); | ||
175 | +} | ||
176 | + | ||
177 | +// Get request for web service | ||
178 | +app.get("/", function (req, res) { | ||
179 | + init(); | ||
180 | + // Send data from nodejs to ejs | ||
181 | + res.render("data.ejs", { data: tempArr }, function (err, html) { | ||
182 | + if (err) { | ||
183 | + console.log(err); | ||
184 | + } | ||
185 | + res.end(html); // End response | ||
186 | + }); | ||
187 | + // send data.ejs | ||
188 | + res.sendFile(__dirname + "/views/data.ejs"); | ||
189 | +}); | ||
190 | + | ||
191 | +// Get request for app service(Send main data) | ||
192 | +app.get("/app", function (req, res) { | ||
193 | + init(); | ||
194 | + res.send( | ||
195 | + getTodayDate() + "," + tempArr[0] + "," + tempArr[1] + "," + tempArr[2] | ||
196 | + ); | ||
197 | +}); | ||
198 | + | ||
199 | +init(); | ||
200 | + | ||
201 | +const port = 8080; | ||
202 | +app.listen(port, () => console.log("Listening on port " + port)); |
nodejs/views/data.ejs
0 → 100644
This diff is collapsed. Click to expand it.
-
Please register or login to post a comment