MrMirror21

solve conflict

This diff is collapsed. Click to expand it.
......@@ -11679,6 +11679,11 @@
"picomatch": "^2.2.1"
}
},
"recoil": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/recoil/-/recoil-0.1.2.tgz",
"integrity": "sha512-hIRrHlkmW4yITlBFprVYjVPhzPKYrJKoaDrrJtAtbkMeXfXaa/XE5OlyR10n+rNfnKWNToCKb3Z4fo86IGjkzg=="
},
"recursive-readdir": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz",
......
......@@ -2,6 +2,7 @@
"name": "straight-up",
"version": "0.1.0",
"private": true,
"homepage": "http://khuhub.khu.ac.kr/2019102240/Straight-Up",
"dependencies": {
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0",
......@@ -19,12 +20,11 @@
"react-dom": "^17.0.1",
"react-router-dom": "^5.2.0",
"react-scripts": "4.0.1",
"recoil": "^0.1.2",
"web-vitals": "^0.2.4"
},
"scripts": {
"start": "npm-run-all --parallel start:**",
"start:client": "react-scripts start",
"start:server": "node ./server/app.js",
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
......
const express = require('express');
const bodyParser = require('body-parser')
const app = express();
const api = require('./routes/index');
app.use(bodyParser.json());
app.use('/api', api);
const port = 3001;
app.listen(port, () => console.log(`Listening on port ${port}`));
\ No newline at end of file
const express = require('express');
const router = express.Router();
router.get('/', (req, res) => res.json({data:'this is index.'}));
module.exports = router
\ No newline at end of file
......@@ -52,13 +52,13 @@ const checkStraight = (resData, position) => { //resData: API로 받은 JSON 객
var d_right = distance(x_position[ear + 1], y_position[ear + 1], x_position[shoulder + 1], y_position[shoulder + 1]);
var gap = difference(d_left, d_right);
if (gap >= 20) { //기운 각도가 20도를 넘을 경우
if (gap >= 15) { //기운 각도가 15도를 넘을 경우
if (d_left > d_right) { //오른쪽으로 기울인 경우
return 'leaning right by ' + gap + 'percent.';
} else if (d_left < d_right) { //왼쪽으로 기울인 경우
return 'leaning left by ' + gap + 'percent.';
}
} else { //기운 각도가 20도 미만인 경우
} else { //기운 각도가 15도 미만인 경우
return 'okay';
}
......
.App {
text-align: center;
}
.App-logo {
height: 40vmin;
pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
import React from 'react';
import {RecoilRoot} from 'recoil';
import { BrowserRouter as Router, Route, Switch, Redirect } from 'react-router-dom';
import Landing from './Landing';
import Main from './Main';
import Result from './Result';
class App extends React.Component {
render() {
return (
<Router>
<Switch>
<Route exact path="/landing" component={Landing} />
<Route exact path="/main" component={Main} />
<Redirect path="*" to="/landing" />
</Switch>
</Router>
<RecoilRoot>
<Router>
<Switch>
<Route exact path="/landing" component={Landing} />
<Route exact path="/main" component={Main} />
<Route exact path="/result" component={Result} />
<Redirect path="*" to="/landing" />
</Switch>
</Router>
</RecoilRoot>
);
}
}
......
......@@ -8,10 +8,14 @@ export default function Landing() {
<div className="Landingbg">
<Header />
<div className="mainTextContainer">
<h1 className="mainText">Welcome to Straight Up</h1>
<span className="mainText">We support posture correction for you.</span>
<Button />
<Button btnText="Get Started!" />
<div className="mainBtnContainer">
<a target="blank" href="http://khuhub.khu.ac.kr/2019102240/Straight-Up">
<button className="startBtn">Contact Us</button>
</a>
</div>
</div>
</div>
)
......
import React, { useState } from 'react'
import React, { useState } from 'react';
import { Link } from 'react-router-dom';
import { useRecoilState, useSetRecoilState } from 'recoil';
import Header from './components/Header';
import Checkbox from './components/Checkbox';
import checkStraight from './AnalysisPose';
import { selectedPosState, analysisResultState } from './store/Global';
import './style/Main.css';
require('dotenv').config();
const axios = require('axios');
const API_KEY = "1f14e860f7f53f39a4dfe0a2a919a8c7";
//process.env.api_key;
const API_KEY = process.env.REACT_APP_APIKEY;
console.log(API_KEY);
let imageFormData = new FormData();
export default function Main() {
const [imgBase64, setImgBase64] = useState("");
const [img, setImage] = useState(null);
const setAnalysisResult = useSetRecoilState(analysisResultState);
const [selectedPosition, setPosition] = useRecoilState(selectedPosState);
const handleChangeFile = (event) => {
let reader = new FileReader();
reader.onloadend = () => {
......@@ -40,10 +46,7 @@ export default function Main() {
}).then(function (response) {
const resdata = response.data[0].keypoints;
console.log(resdata[0]);
const result = checkStraight(resdata, 'front');
console.log(result);
// console.log(resdata[0] === )
setAnalysisResult(checkStraight(resdata, 'front'));
}).catch(function (error) {
if (error.response) {
// 요청이 이루어졌으며 서버가 2xx의 범위를 벗어나는 상태 코드로 응답했습니다.
......@@ -61,19 +64,38 @@ export default function Main() {
// 오류를 발생시킨 요청을 설정하는 중에 문제가 발생했습니다.
console.log('Error', error.message);
}
setAnalysisResult('error');
console.log(error.config);
});
}
return (
<div>
<div className="MainPageContainer">
<Header />
<span>This is Main Page</span>
<div className="Image-Preview-Container" style={{ "backgroundColor": "#efefef", "width": "400px", "height": "400px" }}>
<img className="Image-Preview" alt="preview" src={imgBase64}></img>
<div className="ImagePreviewContainer">
<img className="ImagePreview" alt="" src={imgBase64}></img>
<div className="ImageInput">
<input type="file" name="file" onChange={handleChangeFile} />
</div>
</div>
<div className="Image_input">
<input type="file" name="file" onChange={handleChangeFile} />
<button type="button" onClick={analysisImage} >Submit</button>
<div className="ImageInputSetting">
<div className="PositionSelector">
<h3>전면 사진</h3>
<Checkbox checked={selectedPosition === "front"} onChange={(isChecked) => { isChecked ? setPosition('front') : setPosition(undefined) }} />
<h3>측면 사진 - 왼쪽</h3>
<Checkbox checked={selectedPosition === "left"} onChange={(isChecked) => { isChecked ? setPosition('left') : setPosition(undefined) }} />
<h3>측면 사진 - 오른쪽</h3>
<Checkbox checked={selectedPosition === "right"} onChange={(isChecked) => { isChecked ? setPosition('right') : setPosition(undefined) }} />
</div>
<div className="Caution">
<p>-- 이미지 업로드 유의사항 --</p>
<p>1. 업로드 되는 이미지는 JPEG, PNG 포맷만 지원합니다.</p>
<p>2. 업로드할 있는 이미지의 최대 용량은 2MB입니다.</p>
<p>3. 이미지의 권장 비율은 가로:세로 기준 16:9 ~ 9:16 입니다.</p>
<p>4. 이미지의 가로와 세로 길이는 320px~2048px 범위 내여야 합니다.</p>
</div>
<Link to="/result">
<button className="startBtn" type="button" onClick={analysisImage}>Submit</button>
</Link>
</div>
</div>
)
......
import React from 'react'
import { useRecoilValue } from 'recoil';
import { analysisResultState } from './store/Global';
import Header from './components/Header';
import ResultContent from './components/ResultContent';
import './style/ResultContent.css';
const Result = () => {
const analysisResult = useRecoilValue(analysisResultState);
return (
<div className="resultPageContainer">
<Header />
<ResultContent
result={analysisResult}
/>
</div>
)
}
export default Result;
\ No newline at end of file
......@@ -2,11 +2,11 @@ import React from 'react'
import { Link } from 'react-router-dom';
import "../style/Landing.css";
const Button = () => {
const Button = (props) => {
return (
<div className="mainBtnContainer">
<Link to="/main">
<button className="startBtn">Get Started!</button>
<button className="startBtn">{props.btnText}</button>
</Link>
</div>
)
......
import React from 'react'
const Checkbox = (props) => {
return (
<input
className="Checkbox"
type="checkbox"
checked={props.checked}
onChange={(e) => props.onChange(e.target.checked)}
/>
)
}
export default Checkbox;
\ No newline at end of file
......@@ -11,7 +11,6 @@ const Header = () => {
background: '#2f3640'
}}
>
<div className="logo">
<Link to="/landing">
<img
......
import React from 'react'
import { useRecoilValue } from 'recoil';
import ResultForLn from './ResultForLn';
import ResultForErr from './ResultForErr';
import ResultForOk from './ResultForOk';
import ResultForBn from './ResultForBn';
import ResultForBb from './ResultForBb';
import ResultForErrTrust from './ResultForErrTrust';
import ResultLoading from './ResultLoading';
import { selectedPosState } from '../store/Global';
const ResultContent = (props) => {
const resultStr = props.result.toString();
const headLetters = resultStr.substr([0, 4]);
const direction = useRecoilValue(selectedPosState);
if (resultStr === "loading") {
return <ResultLoading />
}
else if (headLetters === 'error') {
return <ResultForErrTrust />;
}
else if (resultStr === "okay") {
return <ResultForOk />;
}
else if (headLetters === "leani") {
return <ResultForLn direction={direction} />
}
else if (resultStr === "bent-neck") {
return <ResultForBn />;
}
else if (resultStr === "bent-back") {
return <ResultForBb />;
}
else {
return <ResultForErr />;
}
}
export default ResultContent;
import React from 'react'
import RetryBtn from './RetryBtn';
import '../style/ResultContent.css';
const ResultForBb = () => {
return (
<div className="resultContainer">
<div className="resultPhoto Bb">
</div>
<div className="resultTextContainer">
<h1>분석 결과 : [굽은등] 증상이 의심됩니다.</h1>
<p>척추 자세를 바로잡아 등을 곧게 하고 어깨를 펴주세요.</p>
<p>주기적으로 일어나 척추 스트레칭이나 요가를 해주시면 도움이 됩니다.</p>
<a href="https://terms.naver.com/entry.nhn?docId=2119027&cid=51035&categoryId=51035" target="blank">https://terms.naver.com/entry.nhn?docId=2119027&cid=51035&categoryId=51035</a> <br />
<a href="https://www.youtube.com/watch?v=fFIL0rlRH78&feature=youtu.be" target="blank">https://www.youtube.com/watch?v=fFIL0rlRH78&feature=youtu.be</a>
<RetryBtn btnText="Try Again" />
</div>
</div>
)
}
export default ResultForBb;
\ No newline at end of file
import React from 'react'
import RetryBtn from './RetryBtn';
import '../style/ResultContent.css';
const ResultForBn = () => {
return (
<div className="resultContainer">
<div className="resultPhoto Bn">
</div>
<div className="resultTextContainer">
<h1>분석 결과 : [거북목] 증상이 의심됩니다.</h1>
<p>모니터에서 떨어져 목을 곧게 하고 어깨를 펴주세요.</p>
<p>20~30분마다 목을 뒤로 젖혀 주는 신전 운동을 해주시면 도움이 됩니다.</p>
<a href="https://terms.naver.com/entry.nhn?docId=927290&cid=51007&categoryId=51007" target="blank">https://terms.naver.com/entry.nhn?docId=927290&cid=51007&categoryId=51007</a> <br />
<a href="https://youtu.be/oYaal-ir9cc" target="blank">https://youtu.be/oYaal-ir9cc</a>
<RetryBtn btnText="Try Again" />
</div>
</div>
)
}
export default ResultForBn;
import React from 'react'
import RetryBtn from './RetryBtn';
import '../style/ResultContent.css';
const ResultForErr = () => {
return (
<div className="resultContainer">
<div className="resultPhoto Err">
</div>
<div className="resultTextContainer">
<h1>분석 결과 : 자세 분석 실패</h1>
<p>자세 분석에 실패했습니다.</p>
<p>다시 시도해주시기 바랍니다.</p>
<RetryBtn btnText="Try Again" />
</div>
</div>
)
}
export default ResultForErr;
import React from 'react'
import RetryBtn from './RetryBtn';
import '../style/ResultContent.css';
const ResultForErr = () => {
return (
<div className="resultContainer">
<div className="resultPhoto Err">
</div>
<div className="resultTextContainer">
<h1>분석 결과 : 자세 분석 실패</h1>
<p>자세 분석에 실패했습니다.</p>
<p>주의사항에 맞게 사진을 업로드했는지 확인해주세요.</p>
<RetryBtn btnText="Try Again" />
</div>
</div>
)
}
export default ResultForErr;
import React from 'react'
import RetryBtn from './RetryBtn';
import '../style/ResultContent.css';
const ResultForLn = (props) => {
const direction = props.direction === 'left' ? '왼쪽' : '오른쪽';
const conclusion = `어깨와 머리가 ${direction}으로 기울어져 있습니다.`;
return (
<div className="resultContainer">
<div className="resultPhoto Ln">
</div>
<div className="resultTextContainer">
<h1>분석 결과 : 어깨 비대칭</h1>
<p>{conclusion}</p>
<p>턱을 괴거나 삐딱하게 화면을 주시하는 경우가 많다면 어깨 비대칭을 의심해볼 있습니다.</p>
<p>주기적으로 어깨와 스트레칭을 해주시면 도움이 됩니다.</p>
<a href="https://terms.naver.com/entry.nhn?docId=3567879&cid=58904&categoryId=589109" target="blank">https://terms.naver.com/entry.nhn?docId=3567879&cid=58904&categoryId=58910</a><br />
<a href="https://youtu.be/n4T4bRINdp" target="blank">https://youtu.be/n4T4bRINdp</a>
<RetryBtn btnText="Try Again" />
</div>
</div>
)
}
export default ResultForLn;
\ No newline at end of file
import React from 'react'
import RetryBtn from './RetryBtn';
import '../style/ResultContent.css';
const ResultForOk = () => {
return (
<div className="resultContainer">
<div className="resultPhoto Ok">
</div>
<div className="resultTextContainer">
<h1>분석 결과 : 정상</h1>
<p>아주 건강한 자세를 유지하고 계시네요!</p>
<p>지금처럼 건강한 자세를 유지하는데 도움이 스트레칭을 추천해드릴게요!</p>
<a href="http://bakc.net/health/main/index.php?m_cd=109" target="blank">http://bakc.net/health/main/index.php?m_cd=109</a>
<RetryBtn btnText="Try Again" />
</div>
</div>
)
}
export default ResultForOk;
import React from 'react'
import '../style/ResultContent.css';
const ResultLoading = () => {
return (
<div className="resultContainer">
<div className="resultPhoto Loading">
</div>
<div className="resultTextContainer">
<h1>분석중..</h1>
<p></p>
<p>자세를 분석중입니다... 분석에는 5~10초가 소요됩니다.</p>
</div>
</div>
)
}
export default ResultLoading;
\ No newline at end of file
import React from 'react'
import { useSetRecoilState } from 'recoil';
import { Link } from 'react-router-dom';
import "../style/Landing.css";
import { selectedPosState, analysisResultState } from '../store/Global';
const RetryBtn = (props) => {
const setPosition = useSetRecoilState(selectedPosState);
const setResult = useSetRecoilState(analysisResultState);
const reset = () => {
setPosition('front');
setResult('loading');
}
return (
<div className="mainBtnContainer">
<Link to="/main">
<button className="startBtn" onClick={reset}>{props.btnText}</button>
</Link>
</div>
)
}
export default RetryBtn;
\ No newline at end of file
const proxy = require('http-proxy-middleware');
module.exports = function (app) {
app.use(
proxy('/api', {
target: 'http://localhost:3001/'
})
);
};
\ No newline at end of file
import { atom } from 'recoil';
export const selectedPosState = atom({
key: 'selectedPosState',
default: "front",
})
export const analysisResultState = atom({
key: 'analysisResultState',
default: "loading",
})
......@@ -16,20 +16,11 @@ body {
margin: 0;
width: 100vw;
height: 100vh;
text-align: center;
align-items: center;
justify-content: center;
}
/*
.Landingbg:after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: 0;
background: rgba(0,0,0,0.001);
box-shadow: inset 100px 100px 250px #000000, inset -100px -100px 250px #000000;
}
*/
.mainTextContainer{
text-align: center;
position: relative;
......
.Image-Preview{
width: 400px;
html, body {
width: 100vw;
height: 100vh;
}
body {
margin: 0;
}
.MainPageContainer {
background: url("Landing.jpg");
background-repeat: no-repeat;
background-size: cover;
background-position: center;
overflow: hidden;
margin: 0;
width: 100vw;
height: 100vh;
text-align: center;
align-items: center;
justify-content: center;
}
.ImagePreviewContainer{
display: inline-block;
background: lightgrey;
border-radius: 15px;
}
.ImagePreview{
width: 300px;
height: 400px;
}
\ No newline at end of file
background-color: #efefef;
border-radius: 15px;
}
.PositionSelector {
display: flex;
justify-content: center;
align-items: center;
}
.Checkbox {
padding: 1rem;
}
h3{
color: white;
padding: 1rem;
}
.Caution{
color: pink;
}
......
html, body {
width: 100vw;
height: 100vh;
}
body {
margin: 0;
}
a {
color: #4b70fd;
text-decoration : none;
}
.logo {
height: 100px;
}
.resultPageContainer{
text-align: center;
align-items: center;
justify-content: center;
}
.resultContainer{
background: url("Landing.jpg");
background-repeat: no-repeat;
background-size: cover;
background-position: center;
overflow: hidden;
margin: 0;
width: 100vw;
height: 100vh;
text-align: center;
align-items: center;
justify-content: center;
}
.resultPhoto {
margin: auto;
margin-top : 1rem;
width: 40vw;
height: 40vh;
}
.Bb {
background: url(bent-back.jpg);
background-repeat: no-repeat;
background-size: contain;
background-position: center;
}
.Bn {
background: url(bent-neck.jpg);
background-repeat: no-repeat;
background-size: contain;
background-position: center;
}
.Err {
background: url(oops.jpg);
background-repeat: no-repeat;
background-size: contain;
background-position: center;
}
.Ln {
background: url(lean.jpg);
background-repeat: no-repeat;
background-size: contain;
background-position: center;
}
.Loading {
background: url(Loading.JPG);
background-repeat: no-repeat;
background-size: contain;
background-position: center;
}
.Ok {
background: url(okay.jpg);
background-repeat: no-repeat;
background-size: contain;
background-position: center;
}
.resultTextContainer {
margin-left: 3rem;
margin-right: 3rem;
height : 350px;
text-align: center;
background-color: lightcyan;
color: black;
}
.mainBtnContainer {
display: flex;
align-items: center;
justify-content: center;
}