Showing
38 changed files
with
570 additions
and
100 deletions
LICENCE
0 → 100644
1 | + | ||
2 | +MIT License | ||
3 | + | ||
4 | +Copyright (c) 2020 Yong-Woo Song | ||
5 | + | ||
6 | +Permission is hereby granted, free of charge, to any person obtaining a copy | ||
7 | +of this software and associated documentation files (the "Software"), to deal | ||
8 | +in the Software without restriction, including without limitation the rights | ||
9 | +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
10 | +copies of the Software, and to permit persons to whom the Software is | ||
11 | +furnished to do so, subject to the following conditions: | ||
12 | + | ||
13 | +The above copyright notice and this permission notice shall be included in all | ||
14 | +copies or substantial portions of the Software. | ||
15 | + | ||
16 | +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
17 | +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
18 | +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
19 | +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
20 | +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
21 | +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
22 | +SOFTWARE. | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
No preview for this file type
No preview for this file type
1 | +# Jaksimsamil | ||
2 | + | ||
3 | +![issue badge](https://img.shields.io/github/issues/FacerAin/OSS-Jaksimsamil) | ||
4 | +![fork badge](https://img.shields.io/github/forks/FacerAin/OSS-Jaksimsamil) | ||
5 | +![star badge](https://img.shields.io/github/stars/FacerAin/OSS-Jaksimsamil) | ||
6 | +![license badge](https://img.shields.io/github/license/FacerAin/OSS-Jaksimsamil) | ||
7 | + | ||
8 | +## Project Overview | ||
9 | + | ||
10 | +> **Jaksaimsamil Algorithm Study Helper Service** | ||
11 | +> | ||
12 | +> 작심삼일 알고리즘 문제풀이 도우미 서비스<br/> | ||
13 | +> | ||
14 | +> > 알고리즘 문제 풀이 스터디를 꾸준히 할 수 있게 돕는 웹 서비스입니다. | ||
15 | +> > <br> [링크](http://facerain.dcom.club)에서 직접 사용해 보세요! | ||
16 | + | ||
17 | +![그림1](https://user-images.githubusercontent.com/16442978/85690047-236d1d00-b70e-11ea-8d2b-480593c0daf3.png) | ||
18 | + | ||
19 | +![그림2](https://user-images.githubusercontent.com/16442978/85690058-2536e080-b70e-11ea-98cd-45fdf04084ce.png) | ||
20 | + | ||
21 | +## Features (ver.1.0.0) | ||
22 | + | ||
23 | +- 회원가입/로그인 제공 | ||
24 | +- Online Judge 연동 가능 (Baekjoon) | ||
25 | +- 나의 학습 현황 한눈에 보기 | ||
26 | +- 추천 문제 제공 | ||
27 | +- Slack 알리미 | ||
28 | + | ||
29 | +## Upcoming Features | ||
30 | + | ||
31 | +- 친구 추가 | ||
32 | +- 친구와의 경쟁 | ||
33 | +- 그룹 추가 | ||
34 | +- 그룹 추천 | ||
35 | +- 개선된 문제 추천 (사용자 실력 맞춤형) | ||
36 | + | ||
37 | +## Usages | ||
38 | + | ||
39 | +#### 회원 | ||
40 | + | ||
41 | +1. 로그인하여 서비스에 접속 할 수 있습니다. | ||
42 | +2. 서비스가 처음이라면, 회원가입을 하세요. | ||
43 | + <br> | ||
44 | + | ||
45 | +#### 설정 | ||
46 | + | ||
47 | +1. 백준 아이디를 등록하고 동기화하세요. [상세]() | ||
48 | +2. 슬랙 HOOK URL을 등록하세요. [상세]() | ||
49 | +3. 일일 목표량을 등록하세요. | ||
50 | + | ||
51 | +## Getting Started | ||
52 | + | ||
53 | +1. Clone | ||
54 | + | ||
55 | +``` | ||
56 | +git clone https://github.com/FacerAin/OSS-Jaksimsamil.git | ||
57 | +``` | ||
58 | + | ||
59 | +2. Install MongoDB(Ubuntu) | ||
60 | + | ||
61 | +``` | ||
62 | +sudo apt-get update | ||
63 | +sudo apt-get install -y mongodb-org | ||
64 | +sudo service mongod start | ||
65 | +``` | ||
66 | + | ||
67 | +3. Set Serverfile | ||
68 | + | ||
69 | +``` | ||
70 | +cd Jaksimsamil-server | ||
71 | +touch .env | ||
72 | +---TYPE THIS IN FILE---- | ||
73 | +SERVER_PORT= ### | ||
74 | +MONGO_URL= ### | ||
75 | +JWT_SECRET= ### | ||
76 | +``` | ||
77 | + | ||
78 | +4. Start Node Server | ||
79 | + | ||
80 | +``` | ||
81 | +cd Jaksimsamil-server | ||
82 | +sudo npm install | ||
83 | +npm start | ||
84 | +``` | ||
85 | + | ||
86 | +[링크](/jaksimsamil-server/README.md)에서 API 제공 목록을 볼 수 있습니다. | ||
87 | +<br> | ||
88 | + | ||
89 | +5. Set Front-end page | ||
90 | + | ||
91 | +``` | ||
92 | +cd Jaksimsamil-server | ||
93 | +sudo npm install | ||
94 | +npm start #Start React | ||
95 | +``` | ||
96 | + | ||
97 | +## Contributing | ||
98 | + | ||
99 | +컨트리뷰션은 언제나 환영입니다. 다음 절차를 지켜주세요! | ||
100 | + | ||
101 | +1. Fork the Project | ||
102 | +2. Create your Feature Branch | ||
103 | +3. Commit our changes | ||
104 | +4. Push to Branch | ||
105 | +5. Open a Pull Request | ||
106 | + | ||
107 | +## License | ||
108 | + | ||
109 | +- MIT LICENCE | ... | ... |
SECURITY.md
0 → 100644
1 | +# Security Policy | ||
2 | + | ||
3 | +## Supported Versions | ||
4 | + | ||
5 | +Use this section to tell people about which versions of your project are | ||
6 | +currently being supported with security updates. | ||
7 | + | ||
8 | +| Version | Supported | | ||
9 | +| ------- | ------------------ | | ||
10 | +| 5.1.x | :white_check_mark: | | ||
11 | +| 5.0.x | :x: | | ||
12 | +| 4.0.x | :white_check_mark: | | ||
13 | +| < 4.0 | :x: | | ||
14 | + | ||
15 | +## Reporting a Vulnerability | ||
16 | + | ||
17 | +Use this section to tell people how to report a vulnerability. | ||
18 | + | ||
19 | +Tell them where to go, how often they can expect to get an update on a | ||
20 | +reported vulnerability, what to expect if the vulnerability is accepted or | ||
21 | +declined, etc. |
This diff could not be displayed because it is too large.
... | @@ -16,7 +16,7 @@ | ... | @@ -16,7 +16,7 @@ |
16 | "react-dom": "^16.13.1", | 16 | "react-dom": "^16.13.1", |
17 | "react-redux": "^7.2.0", | 17 | "react-redux": "^7.2.0", |
18 | "react-router-dom": "^5.2.0", | 18 | "react-router-dom": "^5.2.0", |
19 | - "react-scripts": "3.4.1", | 19 | + "react-scripts": "^3.4.3", |
20 | "redux": "^4.0.5", | 20 | "redux": "^4.0.5", |
21 | "redux-actions": "^2.6.5", | 21 | "redux-actions": "^2.6.5", |
22 | "redux-devtools-extension": "^2.13.8", | 22 | "redux-devtools-extension": "^2.13.8", | ... | ... |
... | @@ -5,6 +5,7 @@ import LoginPage from './pages/LoginPage'; | ... | @@ -5,6 +5,7 @@ import LoginPage from './pages/LoginPage'; |
5 | import RegisterPage from './pages/RegisterPage'; | 5 | import RegisterPage from './pages/RegisterPage'; |
6 | import HomePage from './pages/HomePage'; | 6 | import HomePage from './pages/HomePage'; |
7 | import SettingPage from './pages/SettingPage'; | 7 | import SettingPage from './pages/SettingPage'; |
8 | +import ChallengePage from './pages/ChallengePage'; | ||
8 | 9 | ||
9 | function App() { | 10 | function App() { |
10 | return ( | 11 | return ( |
... | @@ -13,6 +14,7 @@ function App() { | ... | @@ -13,6 +14,7 @@ function App() { |
13 | <Route component={LoginPage} path="/login" /> | 14 | <Route component={LoginPage} path="/login" /> |
14 | <Route component={RegisterPage} path="/register" /> | 15 | <Route component={RegisterPage} path="/register" /> |
15 | <Route component={SettingPage} path="/setting" /> | 16 | <Route component={SettingPage} path="/setting" /> |
17 | + <Route component={ChallengePage} path="/challenge" /> | ||
16 | </> | 18 | </> |
17 | ); | 19 | ); |
18 | } | 20 | } | ... | ... |
1 | +import React from 'react'; | ||
2 | +import { makeStyles } from '@material-ui/core/styles'; | ||
3 | +import Paper from '@material-ui/core/Paper'; | ||
4 | +import Grid from '@material-ui/core/Grid'; | ||
5 | +import palette from '../../lib/styles/palette'; | ||
6 | +const ChallengeForm = () => { | ||
7 | + return <div></div>; | ||
8 | +}; | ||
9 | + | ||
10 | +/* | ||
11 | +Todo | ||
12 | +챌린지 이름 | ||
13 | +챌린지 기간 (Start - End) | ||
14 | +챌린지 세션 정보 (일 간격과 목표 문제) | ||
15 | +그룹 원 정보. | ||
16 | +*/ | ||
17 | +export default ChallengeForm; |
... | @@ -3,42 +3,111 @@ import { makeStyles } from '@material-ui/core/styles'; | ... | @@ -3,42 +3,111 @@ import { makeStyles } from '@material-ui/core/styles'; |
3 | import Paper from '@material-ui/core/Paper'; | 3 | import Paper from '@material-ui/core/Paper'; |
4 | import Grid from '@material-ui/core/Grid'; | 4 | import Grid from '@material-ui/core/Grid'; |
5 | import palette from '../../lib/styles/palette'; | 5 | import palette from '../../lib/styles/palette'; |
6 | +import AuthForm from '../auth/AuthForm'; | ||
6 | const useStyles = makeStyles((theme) => ({ | 7 | const useStyles = makeStyles((theme) => ({ |
7 | root: { | 8 | root: { |
8 | flexGrow: 1, | 9 | flexGrow: 1, |
9 | background: palette.gray[2], | 10 | background: palette.gray[2], |
11 | + padding: theme.spacing(8), | ||
10 | }, | 12 | }, |
11 | paper: { | 13 | paper: { |
12 | - padding: theme.spacing(2), | 14 | + padding: theme.spacing(8), |
15 | + margin: 'auto', | ||
13 | textAlign: 'center', | 16 | textAlign: 'center', |
14 | color: theme.palette.text.secondary, | 17 | color: theme.palette.text.secondary, |
15 | }, | 18 | }, |
16 | })); | 19 | })); |
17 | -const HomeForm = () => { | 20 | +const HomeForm = ({ PSdata, goalNum }) => { |
18 | const classes = useStyles(); | 21 | const classes = useStyles(); |
19 | - return ( | 22 | + return PSdata ? ( |
20 | <div className={classes.root}> | 23 | <div className={classes.root}> |
21 | - <Grid container spacing={3}> | 24 | + <Grid container spacing={5}> |
22 | <Grid item xs={12}> | 25 | <Grid item xs={12}> |
23 | - <Paper className={classes.paper}>xs=12</Paper> | 26 | + <Paper className={classes.paper}> |
27 | + <h1>{PSdata.recommend_data.problem_number}</h1> | ||
28 | + <h1>{PSdata.recommend_data.problem_title}</h1> | ||
29 | + <a | ||
30 | + href={'http://www.boj.kr/' + PSdata.recommend_data.problem_number} | ||
31 | + > | ||
32 | + 바로가기 | ||
33 | + </a> | ||
34 | + | ||
35 | + <h3>오늘의 추천 문제</h3> | ||
36 | + </Paper> | ||
37 | + </Grid> | ||
38 | + <Grid item xs={6}> | ||
39 | + <Paper className={classes.paper}> | ||
40 | + <h1>{PSdata.presentNum + '/' + goalNum}</h1> | ||
41 | + <h3>오늘 푼 문제</h3> | ||
42 | + </Paper> | ||
24 | </Grid> | 43 | </Grid> |
25 | <Grid item xs={6}> | 44 | <Grid item xs={6}> |
26 | - <Paper className={classes.paper}>xs=6</Paper> | 45 | + <Paper className={classes.paper}> |
46 | + <h1>{PSdata.latestSolve.problem_number}</h1> | ||
47 | + <h1>{PSdata.latestSolve.problem_title}</h1> | ||
48 | + <h3>마지막으로 푼 문제</h3> | ||
49 | + </Paper> | ||
50 | + </Grid> | ||
51 | + | ||
52 | + <Grid item xs={4}> | ||
53 | + <Paper className={classes.paper}> | ||
54 | + <h1>{PSdata.weekNum}</h1> | ||
55 | + <h3>7일</h3> | ||
56 | + </Paper> | ||
57 | + </Grid> | ||
58 | + <Grid item xs={4}> | ||
59 | + <Paper className={classes.paper}> | ||
60 | + <h1>{PSdata.monthNum}</h1> | ||
61 | + <h3>30일</h3> | ||
62 | + </Paper> | ||
63 | + </Grid> | ||
64 | + <Grid item xs={4}> | ||
65 | + <Paper className={classes.paper}> | ||
66 | + <h1>{PSdata.totalNum}</h1> | ||
67 | + <h3>전체</h3> | ||
68 | + </Paper> | ||
69 | + </Grid> | ||
70 | + </Grid> | ||
71 | + </div> | ||
72 | + ) : ( | ||
73 | + <div className={classes.root}> | ||
74 | + <Grid container spacing={5}> | ||
75 | + <Grid item xs={12}> | ||
76 | + <Paper className={classes.paper}> | ||
77 | + <h1></h1> | ||
78 | + <h3>오늘의 추천 문제</h3> | ||
79 | + </Paper> | ||
27 | </Grid> | 80 | </Grid> |
28 | <Grid item xs={6}> | 81 | <Grid item xs={6}> |
29 | - <Paper className={classes.paper}>xs=6</Paper> | 82 | + <Paper className={classes.paper}> |
83 | + <h1></h1> | ||
84 | + <h3>오늘</h3> | ||
85 | + </Paper> | ||
30 | </Grid> | 86 | </Grid> |
31 | - <Grid item xs={3}> | 87 | + <Grid item xs={6}> |
32 | - <Paper className={classes.paper}>xs=3</Paper> | 88 | + <Paper className={classes.paper}> |
89 | + <h1></h1> | ||
90 | + <h3>마지막 날</h3> | ||
91 | + </Paper> | ||
33 | </Grid> | 92 | </Grid> |
34 | - <Grid item xs={3}> | 93 | + |
35 | - <Paper className={classes.paper}>xs=3</Paper> | 94 | + <Grid item xs={4}> |
95 | + <Paper className={classes.paper}> | ||
96 | + <h1></h1> | ||
97 | + <h3>7일</h3> | ||
98 | + </Paper> | ||
36 | </Grid> | 99 | </Grid> |
37 | - <Grid item xs={3}> | 100 | + <Grid item xs={4}> |
38 | - <Paper className={classes.paper}>xs=3</Paper> | 101 | + <Paper className={classes.paper}> |
102 | + <h1></h1> | ||
103 | + <h3>30일</h3> | ||
104 | + </Paper> | ||
39 | </Grid> | 105 | </Grid> |
40 | - <Grid item xs={3}> | 106 | + <Grid item xs={4}> |
41 | - <Paper className={classes.paper}>xs=3</Paper> | 107 | + <Paper className={classes.paper}> |
108 | + <h1></h1> | ||
109 | + <h3>전체</h3> | ||
110 | + </Paper> | ||
42 | </Grid> | 111 | </Grid> |
43 | </Grid> | 112 | </Grid> |
44 | </div> | 113 | </div> | ... | ... |
... | @@ -9,13 +9,16 @@ const useStyles = makeStyles((theme) => ({ | ... | @@ -9,13 +9,16 @@ const useStyles = makeStyles((theme) => ({ |
9 | margin: theme.spacing(1), | 9 | margin: theme.spacing(1), |
10 | }, | 10 | }, |
11 | }, | 11 | }, |
12 | + button: { | ||
13 | + margin: theme.spacing(1), | ||
14 | + }, | ||
12 | })); | 15 | })); |
13 | 16 | ||
14 | const BJIDForm = ({ onChange, onBJIDSubmit, profile, onSyncBJIDSubmit }) => { | 17 | const BJIDForm = ({ onChange, onBJIDSubmit, profile, onSyncBJIDSubmit }) => { |
15 | const classes = useStyles(); | 18 | const classes = useStyles(); |
16 | return ( | 19 | return ( |
17 | <div> | 20 | <div> |
18 | - <form onSubmit={onBJIDSubmit}> | 21 | + <form> |
19 | <TextField | 22 | <TextField |
20 | name="userBJID" | 23 | name="userBJID" |
21 | onChange={onChange} | 24 | onChange={onChange} |
... | @@ -23,11 +26,21 @@ const BJIDForm = ({ onChange, onBJIDSubmit, profile, onSyncBJIDSubmit }) => { | ... | @@ -23,11 +26,21 @@ const BJIDForm = ({ onChange, onBJIDSubmit, profile, onSyncBJIDSubmit }) => { |
23 | placeholder="백준 아이디" | 26 | placeholder="백준 아이디" |
24 | label="백준 아이디" | 27 | label="백준 아이디" |
25 | /> | 28 | /> |
26 | - <Button variant="outlined" type="submit"> | ||
27 | - 등록 | ||
28 | - </Button> | ||
29 | </form> | 29 | </form> |
30 | - <Button variant="outlined" onClick={onSyncBJIDSubmit}> | 30 | + <Button |
31 | + className={classes.button} | ||
32 | + variant="outlined" | ||
33 | + onClick={onBJIDSubmit} | ||
34 | + color="primary" | ||
35 | + > | ||
36 | + 등록 | ||
37 | + </Button> | ||
38 | + <Button | ||
39 | + className={classes.button} | ||
40 | + variant="outlined" | ||
41 | + onClick={onSyncBJIDSubmit} | ||
42 | + color="secondary" | ||
43 | + > | ||
31 | 동기화 | 44 | 동기화 |
32 | </Button> | 45 | </Button> |
33 | </div> | 46 | </div> | ... | ... |
... | @@ -10,13 +10,16 @@ const useStyles = makeStyles((theme) => ({ | ... | @@ -10,13 +10,16 @@ const useStyles = makeStyles((theme) => ({ |
10 | margin: theme.spacing(1), | 10 | margin: theme.spacing(1), |
11 | }, | 11 | }, |
12 | }, | 12 | }, |
13 | + button: { | ||
14 | + margin: theme.spacing(1), | ||
15 | + }, | ||
13 | })); | 16 | })); |
14 | 17 | ||
15 | const GoalNumForm = ({ onChange, profile, onGoalNumSubmit }) => { | 18 | const GoalNumForm = ({ onChange, profile, onGoalNumSubmit }) => { |
16 | const classes = useStyles(); | 19 | const classes = useStyles(); |
17 | return ( | 20 | return ( |
18 | <div> | 21 | <div> |
19 | - <form onSubmit={onGoalNumSubmit}> | 22 | + <form> |
20 | <TextField | 23 | <TextField |
21 | name="goalNum" | 24 | name="goalNum" |
22 | type="number" | 25 | type="number" |
... | @@ -28,10 +31,15 @@ const GoalNumForm = ({ onChange, profile, onGoalNumSubmit }) => { | ... | @@ -28,10 +31,15 @@ const GoalNumForm = ({ onChange, profile, onGoalNumSubmit }) => { |
28 | shrink: true, | 31 | shrink: true, |
29 | }} | 32 | }} |
30 | /> | 33 | /> |
31 | - <Button variant="outlined" type="submit"> | ||
32 | - 등록 | ||
33 | - </Button> | ||
34 | </form> | 34 | </form> |
35 | + <Button | ||
36 | + className={classes.button} | ||
37 | + onClick={onGoalNumSubmit} | ||
38 | + color="primary" | ||
39 | + variant="outlined" | ||
40 | + > | ||
41 | + 등록 | ||
42 | + </Button> | ||
35 | </div> | 43 | </div> |
36 | ); | 44 | ); |
37 | }; | 45 | }; | ... | ... |
... | @@ -13,11 +13,12 @@ const useStyles = makeStyles((theme) => ({ | ... | @@ -13,11 +13,12 @@ const useStyles = makeStyles((theme) => ({ |
13 | root: { | 13 | root: { |
14 | flexGrow: 1, | 14 | flexGrow: 1, |
15 | background: palette.gray[2], | 15 | background: palette.gray[2], |
16 | + padding: theme.spacing(8), | ||
16 | }, | 17 | }, |
17 | paper: { | 18 | paper: { |
19 | + padding: theme.spacing(8), | ||
18 | margin: 'auto', | 20 | margin: 'auto', |
19 | textAlign: 'center', | 21 | textAlign: 'center', |
20 | - padding: 30, | ||
21 | }, | 22 | }, |
22 | })); | 23 | })); |
23 | 24 | ||
... | @@ -45,14 +46,10 @@ const SettingForm = ({ | ... | @@ -45,14 +46,10 @@ const SettingForm = ({ |
45 | </LoadingParentStyle> | 46 | </LoadingParentStyle> |
46 | ) : ( | 47 | ) : ( |
47 | <div className={classes.root}> | 48 | <div className={classes.root}> |
48 | - <Grid container spacing={3}> | 49 | + <Grid container spacing={5}> |
49 | - <Grid item xs={12}> | 50 | + <Grid container item xs={6}> |
50 | - <Paper className={classes.paper}> | ||
51 | - <h3>{profile.username}</h3> | ||
52 | - </Paper> | ||
53 | - </Grid> | ||
54 | - <Grid container item xs={12}> | ||
55 | <Paper className={classes.paper} elevation={3}> | 51 | <Paper className={classes.paper} elevation={3}> |
52 | + <h1>백준 아이디</h1> | ||
56 | <BJIDForm | 53 | <BJIDForm |
57 | profile={profile} | 54 | profile={profile} |
58 | onChange={onChange} | 55 | onChange={onChange} |
... | @@ -62,8 +59,9 @@ const SettingForm = ({ | ... | @@ -62,8 +59,9 @@ const SettingForm = ({ |
62 | </Paper> | 59 | </Paper> |
63 | </Grid> | 60 | </Grid> |
64 | 61 | ||
65 | - <Grid container item xs={12}> | 62 | + <Grid container item xs={6}> |
66 | <Paper className={classes.paper} elevation={3}> | 63 | <Paper className={classes.paper} elevation={3}> |
64 | + <h1>슬랙 Hook URL</h1> | ||
67 | <SlackForm | 65 | <SlackForm |
68 | profile={profile} | 66 | profile={profile} |
69 | onChange={onChange} | 67 | onChange={onChange} |
... | @@ -72,8 +70,9 @@ const SettingForm = ({ | ... | @@ -72,8 +70,9 @@ const SettingForm = ({ |
72 | </Paper> | 70 | </Paper> |
73 | </Grid> | 71 | </Grid> |
74 | 72 | ||
75 | - <Grid container item xs={12}> | 73 | + <Grid container item xs={6}> |
76 | <Paper className={classes.paper} elevation={3}> | 74 | <Paper className={classes.paper} elevation={3}> |
75 | + <h1>일일 목표</h1> | ||
77 | <GoalNumForm | 76 | <GoalNumForm |
78 | profile={profile} | 77 | profile={profile} |
79 | onChange={onChange} | 78 | onChange={onChange} | ... | ... |
... | @@ -10,13 +10,16 @@ const useStyles = makeStyles((theme) => ({ | ... | @@ -10,13 +10,16 @@ const useStyles = makeStyles((theme) => ({ |
10 | margin: theme.spacing(1), | 10 | margin: theme.spacing(1), |
11 | }, | 11 | }, |
12 | }, | 12 | }, |
13 | + button: { | ||
14 | + margin: theme.spacing(1), | ||
15 | + }, | ||
13 | })); | 16 | })); |
14 | 17 | ||
15 | const SlackForm = ({ onChange, profile, onSlackURLSubmit }) => { | 18 | const SlackForm = ({ onChange, profile, onSlackURLSubmit }) => { |
16 | const classes = useStyles(); | 19 | const classes = useStyles(); |
17 | return ( | 20 | return ( |
18 | <div> | 21 | <div> |
19 | - <form onSubmit={onSlackURLSubmit}> | 22 | + <form> |
20 | <TextField | 23 | <TextField |
21 | name="slackWebHookURL" | 24 | name="slackWebHookURL" |
22 | onChange={onChange} | 25 | onChange={onChange} |
... | @@ -24,10 +27,16 @@ const SlackForm = ({ onChange, profile, onSlackURLSubmit }) => { | ... | @@ -24,10 +27,16 @@ const SlackForm = ({ onChange, profile, onSlackURLSubmit }) => { |
24 | placeholder="슬랙 Webhook URL" | 27 | placeholder="슬랙 Webhook URL" |
25 | label="슬랙 Webhook URL" | 28 | label="슬랙 Webhook URL" |
26 | /> | 29 | /> |
27 | - <Button variant="outlined" type="submit"> | ||
28 | - 등록 | ||
29 | - </Button> | ||
30 | </form> | 30 | </form> |
31 | + <Button | ||
32 | + className={classes.button} | ||
33 | + onClick={onSlackURLSubmit} | ||
34 | + variant="outlined" | ||
35 | + type="submit" | ||
36 | + color="primary" | ||
37 | + > | ||
38 | + 등록 | ||
39 | + </Button> | ||
31 | </div> | 40 | </div> |
32 | ); | 41 | ); |
33 | }; | 42 | }; | ... | ... |
1 | +import React from 'react'; | ||
2 | +import { useSelector, useDispatch } from 'react-redux'; | ||
3 | +import { withRouter } from 'react-router-dom'; | ||
4 | +import ChallengeForm from '../../components/challenge/ChallengeForm'; | ||
5 | + | ||
6 | +const ChallengeContainer = () => { | ||
7 | + return <div></div>; | ||
8 | +}; | ||
9 | + | ||
10 | +export default ChallengeContainer; |
... | @@ -2,22 +2,35 @@ import React, { useEffect } from 'react'; | ... | @@ -2,22 +2,35 @@ import React, { useEffect } from 'react'; |
2 | import { useDispatch, useSelector } from 'react-redux'; | 2 | import { useDispatch, useSelector } from 'react-redux'; |
3 | import { withRouter } from 'react-router-dom'; | 3 | import { withRouter } from 'react-router-dom'; |
4 | import HomeForm from '../../components/home/HomeForm'; | 4 | import HomeForm from '../../components/home/HomeForm'; |
5 | -import { getPROFILE } from '../../modules/profile'; | 5 | +import { getPROFILE, initializeProfile } from '../../modules/profile'; |
6 | const HomeContainer = ({ history }) => { | 6 | const HomeContainer = ({ history }) => { |
7 | const dispatch = useDispatch(); | 7 | const dispatch = useDispatch(); |
8 | const { user, profile } = useSelector(({ user, profile }) => ({ | 8 | const { user, profile } = useSelector(({ user, profile }) => ({ |
9 | user: user.user, | 9 | user: user.user, |
10 | profile: profile, | 10 | profile: profile, |
11 | })); | 11 | })); |
12 | + | ||
13 | + useEffect(() => { | ||
14 | + if (!user) { | ||
15 | + alert('로그인이 필요합니다 '); | ||
16 | + history.push('/login'); | ||
17 | + } else { | ||
18 | + let username = user.username; | ||
19 | + dispatch(getPROFILE({ username })); | ||
20 | + return () => { | ||
21 | + dispatch(initializeProfile()); | ||
22 | + }; | ||
23 | + } | ||
24 | + }, [dispatch, user, history]); | ||
12 | useEffect(() => { | 25 | useEffect(() => { |
13 | console.log(profile); | 26 | console.log(profile); |
14 | - }, [profile.solvedBJ]); | 27 | + }, [profile]); |
15 | useEffect(() => { | 28 | useEffect(() => { |
16 | if (user) { | 29 | if (user) { |
17 | let username = user.username; | 30 | let username = user.username; |
18 | dispatch(getPROFILE({ username })); | 31 | dispatch(getPROFILE({ username })); |
19 | } | 32 | } |
20 | }, [dispatch, user]); | 33 | }, [dispatch, user]); |
21 | - return <HomeForm />; | 34 | + return <HomeForm PSdata={profile.solvedBJ_date} goalNum={profile.goalNum} />; |
22 | }; | 35 | }; |
23 | export default withRouter(HomeContainer); | 36 | export default withRouter(HomeContainer); | ... | ... |
1 | import React, { useEffect, useState } from 'react'; | 1 | import React, { useEffect, useState } from 'react'; |
2 | import { useDispatch, useSelector } from 'react-redux'; | 2 | import { useDispatch, useSelector } from 'react-redux'; |
3 | + | ||
3 | import { withRouter } from 'react-router-dom'; | 4 | import { withRouter } from 'react-router-dom'; |
4 | import { | 5 | import { |
5 | changeField, | 6 | changeField, |
... | @@ -14,6 +15,7 @@ import SettingForm from '../../components/setting/SettingForm'; | ... | @@ -14,6 +15,7 @@ import SettingForm from '../../components/setting/SettingForm'; |
14 | 15 | ||
15 | const SettingContainer = ({ history }) => { | 16 | const SettingContainer = ({ history }) => { |
16 | const [isLoading, setLoading] = useState(false); | 17 | const [isLoading, setLoading] = useState(false); |
18 | + | ||
17 | const dispatch = useDispatch(); | 19 | const dispatch = useDispatch(); |
18 | const { user, profile, loading } = useSelector( | 20 | const { user, profile, loading } = useSelector( |
19 | ({ user, profile, loading }) => ({ | 21 | ({ user, profile, loading }) => ({ |
... | @@ -63,7 +65,7 @@ const SettingContainer = ({ history }) => { | ... | @@ -63,7 +65,7 @@ const SettingContainer = ({ history }) => { |
63 | useEffect(() => { | 65 | useEffect(() => { |
64 | if (!user) { | 66 | if (!user) { |
65 | alert('로그인이 필요합니다 '); | 67 | alert('로그인이 필요합니다 '); |
66 | - history.push('/'); | 68 | + history.push('/login'); |
67 | } else { | 69 | } else { |
68 | let username = user.username; | 70 | let username = user.username; |
69 | dispatch(getPROFILE({ username })); | 71 | dispatch(getPROFILE({ username })); |
... | @@ -81,16 +83,18 @@ const SettingContainer = ({ history }) => { | ... | @@ -81,16 +83,18 @@ const SettingContainer = ({ history }) => { |
81 | }, [dispatch, loading]); | 83 | }, [dispatch, loading]); |
82 | 84 | ||
83 | return ( | 85 | return ( |
84 | - <SettingForm | 86 | + <div> |
85 | - type="setting" | 87 | + <SettingForm |
86 | - onChange={onChange} | 88 | + type="setting" |
87 | - onBJIDSubmit={onBJIDSubmit} | 89 | + onChange={onChange} |
88 | - onSyncBJIDSubmit={onSyncBJIDSubmit} | 90 | + onBJIDSubmit={onBJIDSubmit} |
89 | - onSlackURLSubmit={onSlackURLSubmit} | 91 | + onSyncBJIDSubmit={onSyncBJIDSubmit} |
90 | - onGoalNumSubmit={onGoalNumSubmit} | 92 | + onSlackURLSubmit={onSlackURLSubmit} |
91 | - profile={profile} | 93 | + onGoalNumSubmit={onGoalNumSubmit} |
92 | - isLoading={isLoading} | 94 | + profile={profile} |
93 | - ></SettingForm> | 95 | + isLoading={isLoading} |
96 | + ></SettingForm> | ||
97 | + </div> | ||
94 | ); | 98 | ); |
95 | }; | 99 | }; |
96 | 100 | ... | ... |
jaksimsamil-page/src/pages/ChallengePage.js
0 → 100644
1 | +import React from 'react'; | ||
2 | +import HeaderContainer from '../containers/common/HeaderContainer'; | ||
3 | +import ChallengeContainer from '../containers/challenge/ChallengeContainer'; | ||
4 | +const ChallengePage = () => { | ||
5 | + return ( | ||
6 | + <div> | ||
7 | + <HeaderContainer /> | ||
8 | + <ChallengeContainer /> | ||
9 | + </div> | ||
10 | + ); | ||
11 | +}; | ||
12 | + | ||
13 | +export default ChallengePage; |
jaksimsamil-server/API.md
deleted
100644 → 0
1 | -# Jaksimsamil API Documentation | ||
2 | - | ||
3 | -## Overview | ||
4 | - | ||
5 | -- TBA | ||
6 | - | ||
7 | -## URL | ||
8 | - | ||
9 | -- TBA | ||
10 | - | ||
11 | -## Usage | ||
12 | - | ||
13 | -- TBA | ||
14 | - | ||
15 | -## Example | ||
16 | - | ||
17 | -- TBA | ||
18 | - | ||
19 | -## API Table | ||
20 | - | ||
21 | -| group | description | method | URL | Detail | Auth | | ||
22 | -| ------- | --------------------------------- | ------ | ----------------------- | -------- | --------- | | ||
23 | -| user | 유저 등록 | POST | api/user | 바로가기 | JWT Token | | ||
24 | -| user | 유저 삭제 | DELETE | api/user:id | 바로가기 | JWT Token | | ||
25 | -| user | 특정 유저 조회 | GET | api/user:id | 바로가기 | None | | ||
26 | -| user | 전체 유저 조회 | GET | api/user | 바로가기 | JWT Token | | ||
27 | -| friend | 유저 친구 등록 | POST | api/friend | 바로가기 | JWT Token | | ||
28 | -| friend | 유저의 친구 조회 | GET | api/friend:id | 바로가기 | None | | ||
29 | -| profile | 유저가 푼 문제 조회(백준) | GET | api/profile/solvedBJ:id | 바로가기 | None | | ||
30 | -| profile | 유저가 푼 문제 동기화(백준) | PATCH | api/profile/syncBJ | 바로가기 | None | | ||
31 | -| profile | 유저 정보 수정 | POST | api/profile/setprofile | 바로가기 | JWT TOKEN | | ||
32 | -| profile | 유저 정보 받아오기 | POST | api/profile/getprofile | 바로가기 | JWT | | ||
33 | -| profile | 추천 문제 조회 | POST | api/profile/recommend | 바로가기 | None | | ||
34 | -| notify | 슬랙 메시지 전송 요청 (성취여부) | POST | api/notify/goal | 바로가기 | Jwt Token | | ||
35 | -| notify | 슬랙 메시지 전송 요청 (문제 추천) | POST | api/notify/recommend | 바로가기 | None | | ||
36 | -| auth | 로그인 | POST | api/auth/login | 바로가기 | None | | ||
37 | -| auth | 로그아웃 | POST | api/auth/logout | 바로가기 | JWT Token | | ||
38 | -| auth | 회원가입 | POST | api/auth/register | 바로가기 | None | | ||
39 | -| auth | 로그인 확인 | GET | api/auth/check | 바로가기 | None | |
jaksimsamil-server/README.md
0 → 100644
1 | +# Jaksimsamil Server Documentation | ||
2 | + | ||
3 | +## Overview | ||
4 | + | ||
5 | +- KOA 프레임워크 기반의 REST-API로 동작합니다. | ||
6 | +- API 문서는 아래를 참고해주세요. | ||
7 | + | ||
8 | +## Usage | ||
9 | + | ||
10 | +- Starting Server | ||
11 | + | ||
12 | +``` | ||
13 | +npm install | ||
14 | +npm update | ||
15 | +node index.js | ||
16 | +``` | ||
17 | + | ||
18 | +## Example | ||
19 | + | ||
20 | +``` | ||
21 | +POST http://facerain.dcom.club/profile/getprofile | ||
22 | +{ | ||
23 | + username: 'syw5141', | ||
24 | +} | ||
25 | +``` | ||
26 | + | ||
27 | +## API Table | ||
28 | + | ||
29 | +| group | description | method | URL | Detail | Auth | | ||
30 | +| ------- | -------------------------------------- | ------ | ----------------------- | -------------------------------------- | --------- | | ||
31 | +| profile | 유저가 푼 문제 조회(백준) | GET | api/profile/solvedBJ:id | [바로가기](/src/api/profile/README.md) | None | | ||
32 | +| profile | 유저가 푼 문제 동기화(백준) | PATCH | api/profile/syncBJ | [바로가기](/src/api/profile/README.md) | None | | ||
33 | +| profile | 유저 정보 수정 | POST | api/profile/setprofile | [바로가기](/src/api/profile/README.md) | JWT TOKEN | | ||
34 | +| profile | 유저 정보 받아오기 | POST | api/profile/getprofile | [바로가기](/src/api/profile/README.md) | JWT | | ||
35 | +| profile | 추천 문제 조회 | POST | api/profile/recommend | [바로가기](/src/api/profile/README.md) | None | | ||
36 | +| profile | 친구 추가 | POST | /api/profile/addfriend | [바로가기](/src/api/profile/README.md) | JWT TOKEN | | ||
37 | +| notify | 슬랙 메시지 전송 요청 (목표 성취 여부) | POST | api/notify/goal | [바로가기](/src/api/notify/README.md) | Jwt Token | | ||
38 | +| notify | 슬랙 메시지 전송 요청 (문제 추천) | POST | api/notify/recommend | [바로가기](/src/api/notify/README.md) | None | | ||
39 | +| auth | 로그인 | POST | api/auth/login | [바로가기](/src/api/auth/README.md) | None | | ||
40 | +| auth | 로그아웃 | POST | api/auth/logout | [바로가기](/src/api/auth/README.md) | JWT Token | | ||
41 | +| auth | 회원가입 | POST | api/auth/register | [바로가기](/src/api/auth/README.md) | None | | ||
42 | +| auth | 로그인 확인 | GET | api/auth/check | [바로가기](/src/api/auth/README.md) | None | |
jaksimsamil-server/access.log
deleted
100644 → 0
This diff could not be displayed because it is too large.
jaksimsamil-server/npm-debug.log
0 → 100644
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
... | @@ -5,7 +5,7 @@ | ... | @@ -5,7 +5,7 @@ |
5 | "license": "MIT", | 5 | "license": "MIT", |
6 | "dependencies": { | 6 | "dependencies": { |
7 | "axios": "^0.19.2", | 7 | "axios": "^0.19.2", |
8 | - "bcrypt": "^4.0.1", | 8 | + "bcrypt": "^3.0.0", |
9 | "body-parser": "^1.19.0", | 9 | "body-parser": "^1.19.0", |
10 | "cheerio": "^1.0.0-rc.3", | 10 | "cheerio": "^1.0.0-rc.3", |
11 | "cookie-parser": "^1.4.5", | 11 | "cookie-parser": "^1.4.5", |
... | @@ -15,11 +15,11 @@ | ... | @@ -15,11 +15,11 @@ |
15 | "iconv": "^3.0.0", | 15 | "iconv": "^3.0.0", |
16 | "joi": "^14.3.1", | 16 | "joi": "^14.3.1", |
17 | "jsonwebtoken": "^8.5.1", | 17 | "jsonwebtoken": "^8.5.1", |
18 | - "koa": "^2.12.0", | 18 | + "koa": "^2.13.0", |
19 | "koa-bodyparser": "^4.3.0", | 19 | "koa-bodyparser": "^4.3.0", |
20 | "koa-morgan": "^1.0.1", | 20 | "koa-morgan": "^1.0.1", |
21 | "koa-router": "^9.0.1", | 21 | "koa-router": "^9.0.1", |
22 | - "mongoose": "^5.9.17", | 22 | + "mongoose": "^5.9.20", |
23 | "morgan": "^1.10.0", | 23 | "morgan": "^1.10.0", |
24 | "node-schedule": "^1.3.2", | 24 | "node-schedule": "^1.3.2", |
25 | "path": "^0.12.7", | 25 | "path": "^0.12.7", |
... | @@ -29,11 +29,11 @@ | ... | @@ -29,11 +29,11 @@ |
29 | }, | 29 | }, |
30 | "devDependencies": { | 30 | "devDependencies": { |
31 | "babel-eslint": "^10.1.0", | 31 | "babel-eslint": "^10.1.0", |
32 | - "eslint": "^7.1.0", | 32 | + "eslint": "^7.3.1", |
33 | "nodemon": "^2.0.4" | 33 | "nodemon": "^2.0.4" |
34 | }, | 34 | }, |
35 | "scripts": { | 35 | "scripts": { |
36 | - "start": "node src", | 36 | + "start": "node ./index.js", |
37 | "start:dev": "nodemon --watch src/ src/index.js" | 37 | "start:dev": "nodemon --watch src/ src/index.js" |
38 | } | 38 | } |
39 | } | 39 | } | ... | ... |
jaksimsamil-server/src/api/auth/README.md
0 → 100644
File mode changed
jaksimsamil-server/src/api/friend/README.md
0 → 100644
File mode changed
jaksimsamil-server/src/api/notify/README.md
0 → 100644
File mode changed
jaksimsamil-server/src/api/profile/README.md
0 → 100644
1 | +. |
jaksimsamil-server/src/api/user/README.md
0 → 100644
File mode changed
This diff could not be displayed because it is too large.
jaksimsamil-server/src/models/challenge.js
0 → 100644
1 | +const mongoose = require("mongoose"); | ||
2 | + | ||
3 | +const { Schema } = mongoose; | ||
4 | + | ||
5 | +const GroupSchema = new Schema({ | ||
6 | + members: { type: [String] }, | ||
7 | +}); | ||
8 | + | ||
9 | +const ChallengeSchema = new Schema({ | ||
10 | + challengeName: { type: String, required: true }, | ||
11 | + startDate: { type: Object, required: true }, | ||
12 | + endDate: { type: Object, required: true }, | ||
13 | + durationPerSession: { type: String, required: true }, // '1d' means one day per session, '2w' means 2 weeks per session, '3m' means 3 months per session. | ||
14 | + goalPerSession: { type: Number, required: true }, // number of problems for one session | ||
15 | + groups: { type: [GroupSchema], required: true }, // groups attending challenge, group of only one member supposed to be single | ||
16 | +}); | ||
17 | + | ||
18 | +ChallengeSchema.statics.findByChallengeName = function (challengeName) { | ||
19 | + return this.findOne({ challengeName: challengeName }); | ||
20 | +}; | ||
21 | + | ||
22 | +ChallengeSchema.methods.addNewGroup = function (group) { | ||
23 | + this.groups.push(group); | ||
24 | + return this.save(); | ||
25 | +}; | ||
26 | + | ||
27 | +ChallengeSchema.methods.removeGroup = function (group_id) { | ||
28 | + const idx = this.groups.findIndex((item) => item._id === group_id); | ||
29 | + this.groups.splice(idx, 1); | ||
30 | + return this.save(); | ||
31 | +}; | ||
32 | + | ||
33 | +ChallengeSchema.methods.getChallengeName = function () { | ||
34 | + return this.challengeName; | ||
35 | +}; | ||
36 | + | ||
37 | +ChallengeSchema.methods.getStartDate = function () { | ||
38 | + return this.startDate; | ||
39 | +}; | ||
40 | + | ||
41 | +ChallengeSchema.methods.getEndDate = function () { | ||
42 | + return this.endDate; | ||
43 | +}; | ||
44 | + | ||
45 | +ChallengeSchema.methods.getDurationPerSession = function () { | ||
46 | + return this.durationPerSession; | ||
47 | +}; | ||
48 | + | ||
49 | +ChallengeSchema.methods.getGoalPerSession = function () { | ||
50 | + return this.goalPerSession; | ||
51 | +}; | ||
52 | + | ||
53 | +ChallengeSchema.methods.getGroups = function () { | ||
54 | + return this.groups; | ||
55 | +}; | ||
56 | + | ||
57 | +ChallengeSchema.methods.serialize = function () { | ||
58 | + return this.toJSON(); | ||
59 | +}; | ||
60 | + | ||
61 | +const Challenge = mongoose.model("Challenge", ChallengeSchema); | ||
62 | +module.exports = Challenge; |
jaksimsamil-server/src/models/problem.js
0 → 100644
1 | +const mongoose=require('mongoose'); | ||
2 | + | ||
3 | +const {Schema}=mongoose; | ||
4 | + | ||
5 | +const ProblemSchema=new Schema({ | ||
6 | + problemNum: {type: Number, required: true, unique: true}, | ||
7 | + problemTitle: {type: String, required: true}, | ||
8 | + solvedacLevel: {type: Number}, | ||
9 | + sumbitNum: {type: Number, required: true}, | ||
10 | + correctNum: {type: Number, required: true}, | ||
11 | + category: {type:[String]} | ||
12 | +}); | ||
13 | + | ||
14 | +ProblemSchema.statics.findByProblemNum=function(problemNum){ | ||
15 | + return this.findOne({problemNum:problemNum}); | ||
16 | +} | ||
17 | + | ||
18 | +ProblemSchema.methods.addCategory=function(category){ | ||
19 | + this.category.push(category); | ||
20 | + return this.save(); | ||
21 | +} | ||
22 | + | ||
23 | +ProblemSchema.methods.removeCategory=function(category){ | ||
24 | + const idx=this.category.findIndex(item=>item===category); | ||
25 | + this.splice(idx,1); | ||
26 | + return this.save(); | ||
27 | +} | ||
28 | + | ||
29 | +ProblemSchema.methods.getProblemNum=function(){ | ||
30 | + return this.problemNum; | ||
31 | +} | ||
32 | + | ||
33 | +ProblemSchema.methods.getProblemTitle=function(){ | ||
34 | + return this.problemTitle; | ||
35 | +} | ||
36 | + | ||
37 | +ProblemSchema.methods.getSolvedacLevel=function(){ | ||
38 | + return this.solvedacLevel; | ||
39 | +} | ||
40 | + | ||
41 | +ProblemSchema.methods.getSumbitNum=function(){ | ||
42 | + return this.sumbitNum; | ||
43 | +} | ||
44 | + | ||
45 | +ProblemSchema.methods.getCorrectNum=function(){ | ||
46 | + return this.correctNum; | ||
47 | +} | ||
48 | + | ||
49 | +ProblemSchema.methods.getCategory=function(){ | ||
50 | + return this.category; | ||
51 | +} | ||
52 | + | ||
53 | +ProblemSchema.methods.serialize=function(){ | ||
54 | + return this.toJSON(); | ||
55 | +} | ||
56 | + | ||
57 | +const Problem=mongoose.model('Problem',ProblemSchema); | ||
58 | +module.exports=Problem; | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | let moment = require("moment"); | 1 | let moment = require("moment"); |
2 | - | 2 | +const problem_set = require("../data/problem_set"); |
3 | +const compareBJ = require("./compareBJ"); | ||
3 | exports.analyzeBJ = function (solvedBJ) { | 4 | exports.analyzeBJ = function (solvedBJ) { |
4 | try { | 5 | try { |
5 | if (solvedBJ) { | 6 | if (solvedBJ) { |
... | @@ -7,6 +8,7 @@ exports.analyzeBJ = function (solvedBJ) { | ... | @@ -7,6 +8,7 @@ exports.analyzeBJ = function (solvedBJ) { |
7 | let presentDate_str = presentDate.format("YYYYMMDD"); | 8 | let presentDate_str = presentDate.format("YYYYMMDD"); |
8 | let latestDate = moment(solvedBJ[0].solved_date, "YYYYMMDD"); | 9 | let latestDate = moment(solvedBJ[0].solved_date, "YYYYMMDD"); |
9 | let difflatest = presentDate.diff(latestDate, "days"); | 10 | let difflatest = presentDate.diff(latestDate, "days"); |
11 | + let latestSolve = solvedBJ[0]; | ||
10 | 12 | ||
11 | let solvedBJbyDATE = {}; | 13 | let solvedBJbyDATE = {}; |
12 | for (let i = 0; i < solvedBJ.length; i++) { | 14 | for (let i = 0; i < solvedBJ.length; i++) { |
... | @@ -23,12 +25,44 @@ exports.analyzeBJ = function (solvedBJ) { | ... | @@ -23,12 +25,44 @@ exports.analyzeBJ = function (solvedBJ) { |
23 | presentDate_str in solvedBJbyDATE | 25 | presentDate_str in solvedBJbyDATE |
24 | ? solvedBJbyDATE[presentDate_str].length | 26 | ? solvedBJbyDATE[presentDate_str].length |
25 | : 0; | 27 | : 0; |
28 | + | ||
29 | + let weekNUM = 0; | ||
30 | + let monthNUM = 0; | ||
31 | + let totalNUM = 0; | ||
32 | + for (let i = 0; i < solvedBJ.length; i++) { | ||
33 | + let diffDate = presentDate.diff( | ||
34 | + moment(solvedBJ[i].solved_date, "YYYYMMDD"), | ||
35 | + "days" | ||
36 | + ); | ||
37 | + if (diffDate <= 7) { | ||
38 | + weekNUM++; | ||
39 | + monthNUM++; | ||
40 | + totalNUM++; | ||
41 | + } else if (diffDate <= 31) { | ||
42 | + monthNUM++; | ||
43 | + totalNUM++; | ||
44 | + } else { | ||
45 | + totalNUM++; | ||
46 | + } | ||
47 | + } | ||
48 | + | ||
49 | + let unsolved_data = compareBJ.compareBJ( | ||
50 | + solvedBJ, | ||
51 | + problem_set.problem_set | ||
52 | + ); | ||
53 | + let recommend_data = compareBJ.randomItem(unsolved_data); | ||
54 | + | ||
26 | let returnOBJ = { | 55 | let returnOBJ = { |
27 | latestDate: latestDate.format("YYYYMMDD"), | 56 | latestDate: latestDate.format("YYYYMMDD"), |
28 | difflatest: difflatest, | 57 | difflatest: difflatest, |
29 | latestNum: latestNum, | 58 | latestNum: latestNum, |
30 | presentNum: presentNum, | 59 | presentNum: presentNum, |
60 | + weekNum: weekNUM, | ||
61 | + monthNum: monthNUM, | ||
62 | + totalNum: totalNUM, | ||
31 | solvedBJbyDATE: solvedBJbyDATE, | 63 | solvedBJbyDATE: solvedBJbyDATE, |
64 | + latestSolve: latestSolve, | ||
65 | + recommend_data: recommend_data, | ||
32 | }; | 66 | }; |
33 | 67 | ||
34 | return returnOBJ; | 68 | return returnOBJ; | ... | ... |
... | @@ -14,7 +14,6 @@ exports.compareBJ = function (solvedBJ_new, problem_set) { | ... | @@ -14,7 +14,6 @@ exports.compareBJ = function (solvedBJ_new, problem_set) { |
14 | new_obj.push(problem_set[i]); | 14 | new_obj.push(problem_set[i]); |
15 | } | 15 | } |
16 | } | 16 | } |
17 | - console.log(new_obj); | ||
18 | return new_obj; | 17 | return new_obj; |
19 | } catch (e) { | 18 | } catch (e) { |
20 | console.log(e); | 19 | console.log(e); | ... | ... |
This diff could not be displayed because it is too large.
This diff is collapsed. Click to expand it.
-
Please register or login to post a comment