Home - Marvic1130/BlinkingRecognitionProject GitHub Wiki
-
๊ฐ์ ์์ด๋์ด๋ฅผ ํ๋์ฉ ๊ฐ์ ธ์ค๊ธฐ๋ก ํด์ ์์ด๋์ด ํ์ ํ ๊ฐ์ฅ ์ธ๊ธฐ๊ฐ ์ข์๋ ์์ด๋์ด์ธ "์ธ๊ณต์ง๋ฅ์ ์ด์ฉํ ๋ ๊น๋นก์ ํ์๋ฅผ ํตํด ์ง์ค๋๋ฅผ ๊ฒ์ถํ๋ ํ๋ก์ ํธ" ์ ์
-
์นด๋ฉ๋ผ๋ก ์ฌ๋์ ๋ ๊น๋ฐ์ ํ์๋ ๋์ ๊ฐ๊ณ ์๋ ์๊ฐ๋ฑ์ ์ธก์ ํ์ฌ ์์ or ๊ฐ์์ ์ง์ค๋๋ฅผ ์น์ ๋ฐ์ดํฐ๋ก ํ์ํ๋ ํ๋ก์ ํธ
๋ฐ์ดํฐ ์์ง -> ์ ์ฒ๋ฆฌ -> ๋ผ๋ฒจ๋ง -> ํ์ต ์์๋ก ์งํ ์์
๋จผ์ ๋ ๊น๋นก์์ ํ์ต์ํค๊ธฐ ์ํด ๋์ ๋ฌ ์ฌ์ง๊ณผ ๋์ ๊ฐ๊ณ ์๋ ์ฌ์ง์ ๊ฐ๊ฐ ํ์ต์์ผ์ผ ํ๋ค.
๋ฐ์ดํฐ ์ ์ฒ๋ฆฌ๋ฅผ ์ํด Open Cv๋ฅผ ์ด์ฉํ์ฌ ์ฌ์ง or ์์์์ ์ผ๊ตด์ ์ธ์ํ์ฌ ์ผ๊ตด ๋ถ๋ถ์ ํฌ๋กญํด์ ์ ์ฅํด์ผํ๋ค.
1์ฃผ์ฐจ์ ์ฌ์ฉํ ์ฝ๋์์๋ haarcascade๋ฅผ ์ฌ์ฉํ๋๋ฐ ๋ง์คํฌ๋ฅผ ์ฐ๊ณ ์์ผ๋ฉด ์ผ๊ตด๋ก ์ธ์ํ์ง ์๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ค.
์ด๋ฒ ์ฃผ๋ ํ์ด์ง ๋ ์ด์์์ ๊ฐ์ด ๋์์ธํ๋ค. ์์ผ๋ก๋ ์์ง ๋ฏธ์์ฑ์ธ ํ์ด์ง ๋ ์ด์์์ ๋ค๋ฌ๊ณ ์ผ๊ตด์ธ์์ด ๋์ด ๋์จ ์ฌ์ง ํ์ผ๋ค์ ๋ผ๋ฒจ๋ง ํ์ฌ ํ๋ก๊ทธ๋จ์ ํ์ต ์ํฌ ๊ณํ์ด๋ค.
์ฒ์์๋ ๋ก๊ทธ์ธ ๊ธฐ๋ฅ์ ํ์๋ค(ํ์)๊ณผ ๊ด๋ฆฌ์(๊ต์ or ์ ์)์ผ๋ก ๊ตฌ์ํ์์ผ๋ ์์ ์ง์ค๋๋ฅผ ๋ฐ์ดํฐ๋ก ๋ณด์ฌ์ฃผ๋๋ฐ ๊ตณ์ด ๋ก๊ทธ์ธ ์์คํ ์ ๋ ๊ฐ์ง๋ก ๋๋ ํ์๊ฐ ์๋ค๊ณ ํ๋จํ์ฌ ๋ก๊ทธ์ธ์ ๊ด๋ฆฌ์๋ง ๊ฐ๋ฅํ๋๋ก ๋ณ๊ฒฝํ๊ณ ๊ด๋ฆฌ์๋ ์์ ์ ๋ฑ๋กํ๋ ๊ธฐ๋ฅ๊ณผ ์์ ์ ์์ ๋ค์ ๊ด๋ฆฌํ ์ ์๋ ๊ธฐ๋ฅ์ผ๋ก ํธ์ฑํ๋ค.
์ง๋์ฃผ์ ๋ง์คํฌ, ๋ชจ์ ๋ฑ์ผ๋ก ์ผ๊ตด์ด ๊ฐ๋ ค์ง๋ฉด ์ธ์์ด ์๋์๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์ฌ ์ด์ ๋ง์คํฌ ๋ชจ์๋ฑ์ผ๋ก ์ผ๊ตด์ด ๊ฐ๋ ค์ ธ๋ ์ผ๊ตด์ธ์์ ๋ฌธ์ ๊ฐ ์๋ค.
- ๋ฐฑ์๋ ์งํ ์ํฉ
- ์๋ฒ ๊ตฌ์ถ(node.js ์ express)
- mysql db ์ฐ๋ ๋ฐ model ๊ตฌ์กฐํ ์์
- user model
- class model
- ํ๋ก ํธ ์งํ ์ํฉ
- ๋ฉ์ธํ์ด์ง html, css ์์
- ์์ ํ๋ฉฐ ๋ ์ด์์ ์์
-
ํ๋ก์ ํธ ์์
๋ ๊น๋ฐ์๊ณผ ํ๊ฒฝ๋ณ์๋ฅผ ํตํ ์ง์ค๋ ํ ์คํธ -> ๋ ๊น๋ฐ์๊ณผ ์ง์ญ๋ณ์๋ฅผ ํตํ์ฌ ๊ฐ์ ํ๊ฐ์ ์ ํ์ฑ ์ธก์ ํ ์ ์๋ ๊ฐ์ ํ๊ฐ ์ฌ์ดํธ ์ ์ -
๋ณ๊ฒฝ ์ด์
ํ๋ก์ ํธ๋ฅผ ์งํํจ์ ์์ด์ ํ์คํ ๋ชฉ์ ์ฑ์ด ์์ด ํ๋ก์ ํธ๊ฐ ์ ๋์ ์ผ๋ก ๋ณํ๊ณ ๊ทธ์ ๋ฐ๋ผ UI๊ฐ ๊ณ์์ ์ผ๋ก ๋ณํด, ํ์คํ ๋ชฉ์ ์ฑ์ด ์๋ ํ๋ก์ ํธ๋ก ๋ณ๊ฒฝ
<์ด๊ธฐ ํ์ด์ง>
<ํ์๊ฐ์
ํ์ด์ง>
๊ต์ ํ์๊ฐ์
๊ณผ ํ์ ํ์๊ฐ์
๋ถ๋ฅ
<ํ์ ํ์ด์ง>
<๊ต์ ํ์ด์ง>
- ๋ฐฑ์๋ ์งํ ์ํฉ
- ํ๋ก์ ํธ ์์ ์ ๋ฐ๋ฅธ user DB๋ชจ๋ธ ์์
- Routers ์์ฑ ๋ฐ ๋ชจ๋ํ๋ฅผ ์ํด Controllers์ ์ฝ๋ฐฑ ํจ์ ์์ฑ
- ํ๋ก ํธ ์งํ ์ํฉ
- ๋ก๊ทธ์ธ ํ์ด์ง ์์
- ์์ ํ๋ฉฐ ์๋ก์ด ๋ ์ด์์ ์์ ์งํ์ค
- ํ๋ก ํธ ์งํ ์ฌํญ
- ํ์ ์์ ๋ฑ๋ก ํ์ด์ง ์์ ์๋ฃ (๊ต์์ ํ์ ์์ ๋ฑ๋ก ํ์ด์ง ๊ตฌ๋ถ)
- ํ๋ก ๋ ํต์ฌ ์ฝ๋ ๋ฆฌ๋ทฐ
-> ํ์์๋ ์จ๊ฒจ์ ธ ์๋ ์์ ๋ฑ๋ก UI๋ฅผ +๋ฒํผ์ ํด๋ฆญํ๋ฉด ๋ํ๋๊ณ ์์ ์ ์ ํํ๊ณ ๋ฑ๋ก ์๋ฃ ๋ฒํผ์ ํด๋ฆฌํ๋ฉด ์์ ๋ชฉ๋ก์ ์๋ก์ด ์๋ฆฌ๋จผํธ๋ก ๋ฒํผ์ด ์ถ๊ฐ๋๋ ๊ตฌ์กฐ์ ๋๋ค.
main branch : ํ๋ก์ ํธ๊ฐ ์์ฑ๋์์ ๋ ์ต์ข
์ ์ผ๋ก ๋ณํฉํ๊ธฐ ์ํ ๋ธ๋์น
jaeyoun miji hyemi yeseong jungseok branch: ๊ฐ์ ์ด๋ฆ์ผ๋ก ๋ธ๋์น๋ฅผ ๊ตฌ์ฑํ์ฌ ๊ฐ์ ์์ ์ด ๋ง๋ ํํธ๋ณ ์์
์ ์งํํ๋ ๋ธ๋์น
back branch : backend ๊ธฐ๋ฅ ๊ตฌํ์ด ๋ชจ๋ ์๋ฃ ๋์์ ๋ ๋ณํฉ์ ์ํ ๋ธ๋์น
์ต๊ทผ ๋ธ๋์น ์ด๋๊ฒฝ๋ก
1. class ๋ฑ๋ก api ์์ฑ
2. ๊ฒ์ ๊ธฐ๋ฅ ๊ตฌํ ์๋ฃ
3. token์ ์ ํจ์ฑ์ ๊ฒ์ฌํ๋ middleware ์์ฑ
1.class ๋ฑ๋ก
const { className, professor, department, classTime, place, people } = req.body;
try {
await Class.create({
className,
professor,
department,
classTime,
place,
people,
});
return res.json({className, professor, department, classTime, place, people}).redirect("/")
} catch (err) {
console.log(err);};
- ๊ฒ์ ๊ธฐ๋ฅ
module.exports.find = async (req, res) => {
const { keyword } = req.query;
try {
const item = await Class.findAll({
where: {
[Op.or]: [
{
className: {
[Op.like]: `%${keyword}%`,
},
},
{
professor: {
[Op.like]: `%${keyword}%`,
},
},
],
},
});
if (item.length === 0) {
return res.status(401).json({ message: "์ผ์นํ๋ ์์
์ด ์์ต๋๋ค!" });
}
return res.json({ item });
} catch (err) {
; console.log(err)
}
};
3.token์ ์ ํจ์ฑ์ ๊ฒ์ฌํ๋ middleware
if(req.headers.authorization){
//Request์ header์ Authorization์์ ํ ํฐ์ ์ถ์ถ
let header = req.headers["authorization"]
//Authorization์์ 'Bearer'๊ฐ ํฌํจ๋์ด ์์ผ๋ฏ๋ก split ์ฌ์ฉ!!
let token = header && header.split("")[1]
//์ ํจ์ฑ๊ฒ์ฌ
jwt.verify(token, process.env.ACCESS_SECRET, (err,user)=>{
if(err) {
res.status(404).json(err)
}else{
req.user = user;
next();
}
})
}else{
res.status(401).json({error: "Auth Error"})
}
//class๋ฅผ ๋ฑ๋กํ ๋ token์ ์ ํจ์ฑ์ ๊ฒ์ฌํ ์ ์๋๋ก middleware ์ค์ ํ๊ธฐ
classRouter.route("/register").all(authToken).post(classes.register)
->accessToken์ด ๋ง๋ฃ๋์์๋ ์ฌ๋ฐํํ๋ ์ฝ๋ ํ์!
-> ๋ก์ปฌ์๋ฒ์์ ์ฌ์ฉ๊ฐ๋ฅ ํ์๊ฐ์ ์ ๋ก์ปฌ DB์ ํ์์ ๋ณด๊ฐ ์ ์ฅ๋๊ณ ์์ ๋ชฉ๋ก ํ์ด์ง๊ฐ ๋ธ
- html
<!-- ์์
๋ฑ๋ก -->
<div class="registration-container">
<div class="classBox">
<h1 class="title">๊ฐ์ํ๊ฐ</h1>
<div class="formBox">
<!-- <form method="POST"> -->
<label for="classTitle" id="titleLabel"
>1. ๊ฐ์์ ์ผ๋ง๋ ์ง์ค ํ๋์?</label
><br />
<!-- ์ ์ฒด ์์ญ -->
<div class="progress1">
<!-- ํ๋ก๊ทธ๋์ค ๋ฐ -->
<div class="state1"><span id="percentage1"></span></div>
</div>
<label for="classTime" id="timeLabel">
2. ๊ฐ์์์ ์ป์ ์ ์๋ ์ ์ด ์์๋์?</label
><br />
<!-- ์ ์ฒด ์์ญ -->
<div class="progress2">
<!-- ํ๋ก๊ทธ๋์ค ๋ฐ -->
<div class="state2"><span id="percentage2"></span></div>
</div>
<label for="department" id="departmentLabel">
3. ๊ฐ์๊ฐ ๋ง์กฑ์ค๋ฌ์ ๋์?</label
><br />
<!-- ์ ์ฒด ์์ญ -->
<div class="progress3">
<!-- ํ๋ก๊ทธ๋์ค ๋ฐ -->
<div class="state3"><span id="percentage3"></span></div>
</div>
<button id="registrationBtn">์ ์ถํ๊ธฐ</button>
<!-- </form> -->
</div>
</div>
</div>
- css
/* ํ๋ก๊ทธ๋์ค ๋ฐ */
.progress1, .progress2, .progress3 {
width: 75%;
height: 50px;
position: relative;
top: 0;
left: 0;
overflow-x: hidden;
cursor: pointer;
border: 1px solid black;
margin: 0 auto;
border-radius: 2px;
}
.state1, .state2, .state3 {
width: 0;
height: 50px;
position: absolute;
top: 0;
left: 0;
background-color: #448593;
}
#percentage1, #percentage2, #percentage3 {
line-height: 50px;
vertical-align: middle;
}
- javascript
$(document).ready(function () {
//ํ๋ก๊ทธ๋์ค ๋ฐ๋ฅผ ํด๋ฆญ
$(".progress1").click(function (e) {
// ๋ณ์ x๋ .progress์ left๊ฐ์์ ํด๋ฆญํ ์์น์ X๊ฐ์ ๋บ๋ค.
// e.pageX๋ ํ๋ฉด์์ ํด๋ฆญํ X์ ์์น๋ฅผ ๊ฐ์ ธ์จ๋ค.
var x = e.pageX - $(".progress1").offset().left;
//๋ณ์ clickPercentage๋ ๋ณ์ x / .progress.๋๋น
clickPercentage = x / $(".progress1").width();
//.state์ ๋๋น๋ (.progress์ ๋๋น์์ ๋ณ์ clickPercentage๋ฅผ ๊ณฑํ ๊ฐ);
$(".state1").width($(".progress1").width() * clickPercentage);
var percentage = clickPercentage * 100;
//Math.floor() ์์์ ๋ฒ๋ฆผ, ์ ์๋ฅผ ๋ฐํํ๋ ํจ์
$("#percentage1").text(Math.floor(percentage));
});
});
ํ์ต์ ์งํํ ๋ ๋๋ฌด ๋ง์ epoch๋ overfitting์ ์ผ์ผํค๊ณ ๋๋ฌด ์ ์ epoch๋ underfitting์ ์ผ์ผํค๋๋ฐ, ์ด๋ฌํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด Early Stopping์ ์ฌ์ฉํ๋ค.
early_stopping_calback = EarlyStopping(monitor='loss', patience=10)
checkpointer = ModelCheckpoint(filepath=modelpath, monitor='loss', verbose=0, save_best_only=True)
hist = model.fit(X_train, Y_train, batch_size=64, epochs=200, callbacks=[early_stopping_calback, checkpointer])
patience=10
patience=5
patience=3
patience=1
ํ์ต๋ ๋ชจ๋ธ์ ํ๊ฐํ๋ ๋ฐฉ๋ฒ์ ์ฌ๋ฌ ๋ฐฉ๋ฒ์ด ์๋ค.
- ์ ํ๋(Accuracy)
์ ์ฒด ๋ฐ์ดํฐ ์ค์ ์ ํํ๊ฒ ์์ธกํ ๋ฐ์ดํฐ์ ์
ACC = TP + TN / TP + TN + FP + FN
- Log Loss
์ค์ ๋ต์์ ํด๋นํ๋ ํ๋ฅ ๊ฐ์ ์์ ๋ก๊ทธ๋ฅผ ์ทจํ ํ ๋ชจ๋ ๋ํ ๊ฐ์ ํ๊ท
100%์ ํ๋ฅ (ํ์ )๋ก ๋ต์ ๊ตฌํ ๊ฒฝ์ฐ log loss๋ -log(1.0) = 0, 80% ํ๋ฅ ์ ๊ฒฝ์ฐ์๋ -log(0.8) = 0.22314, 60% ํ๋ฅ ์ ๊ฒฝ์ฐ์๋ -log(0.6) = 0.51082 ์ด ๊ฐ๋ค์ ํ๊ท
- ์ ๋ฐ๋(Precison)
์์ฑ์ผ๋ก ํ๋จํ ๊ฒ ์ค ์ง์ง ์์ฑ ๋น์จ
PREC = TP / TP + FP
- ์ฌํ์จ(ReCall)
์ง์ง ์์ฑ์ธ ๊ฒ๋ค ์ค์์ ์ฌ๋ฐ๋ฅด๊ฒ ์์ฑ์ผ๋ก ํ๋จํ ๋น์จ
ReCall = TP / TP + FN
- F1 Score
F1 Score๋ ์ ๋ฐ๋์ ์ฌํ์จ์ ๊ฒฐํฉํ์ฌ ๋ง๋ ์งํ์ด๋ค. ์ ๋ฐ๋์ ์ฌํ์จ์ ์กฐํํ๊ท
F1 Score = 2 * Prec * Recall/(Price + Recall)
print('Test accuracy:', accuracy_score(Y_test, Y_pred))
print('Test loss:', log_loss(Y_test, y_predicted))
print("F1-score: {:.2%}".format(f1_score(Y_test, Y_pred, average='macro')))
๊ฒฐ๊ณผ ํ๋ฉด
-> ์ค์ ์์ ์ ์ง์ค๋์ ํ์์ด ๊ฐ์ํ๊ฐ์์ ํ๊ฐํ ์ง์ค๋ ๋ฐ์ดํฐ๋ฅผ ์์นํํด ๊ทธ๋ํ๋ก ํํ
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>
<canvas id="canvas" style="display: inline-block; width: 450px; height: 350px; position: relative; right: 45px;"></canvas
><br />
<div class="labelBoxStick">
<label for="realDataStick" id="realDataStick">์ค์ ์ง์ค๋</label>
<br />
<label for="lectureDataStick" id="lectureDataStick"
>๊ฐ์ํ๊ฐ ์ง์ค๋</label
><br />
</div>
<div class="progress-bar-real">
<div class="progressReal"></div>
</div>
<div class="progress-bar-lecture">
<div class="progressLecture"></div>
</div>
// chart
new Chart(document.getElementById("canvas"), {
type: "line",
data: {
labels: ["1", "2", "3", "4", "5", "6", "7"],
datasets: [
{
label: "์์
์ง์ค๋",
data: [10, 3, 30, 23, 10, 5, 50],
borderColor: "rgba(255, 201, 14, 1)",
fill: true,
lineTension: 0, // ์ง์ ์ ๊ทธ๋ฆฌ๋ ค๋ฉด 0
},
{
label: "๊ฐ์ํ๊ฐ ์ง์ค๋",
data: [1, 3, 15, 10, 25, 30, 5],
borderColor: "skyblue",
fill: true,
lineTension: 0,
},
],
},
options: {
responsive: false, // false๋ฉด ์ฐจํธ ํฌ๊ธฐ ์กฐ์ ๊ฐ๋ฅ
title: {
display: true,
text: "์์
+ ๊ฐ์ํ๊ฐ ์ง์ค๋",
},
tooltips: {
// ๊ทธ๋ํ์ ๋ง์ฐ์ค ๋๋ฉด ๋ฐ์ดํฐ ํ
์คํธ๋ก ๋ณด์ฌ์ฃผ๋ ํดํ
mode: "index", // ๋์ผํ ์ธ๋ฐ์ค์ธ ํญ๋ชฉ์ ์ฐพ์ต๋๋ค.
intersect: false, // ํดํ ๋ชจ๋๋ ๋ง์ฐ์ค ์์น๊ฐ ์์๋ฅผ ๊ต์ฐจํ ๋๋ง ์ ์ฉ
},
hover: {
mode: "nearest", // ์ ๊ณผ ๊ฐ์ฅ ๊ฐ๊น์ด ๊ฑฐ๋ฆฌ์ ์๋ ํญ๋ชฉ๋ค์ ๊ฐ์ ธ์ต๋๋ค.
intersect: true,
},
scales: {
xAxes: [
{
// x์ถ
display: true,
scaleLabel: {
display: true,
labelString: "hour",
},
},
],
yAxes: [
{
// y์ถ
display: true,
ticks: {
suggestedMin: 0,
},
scaleLabel: {
display: true,
labelString: "concentration",
},
},
],
},
},
});
// ๋ง๋ ๊ทธ๋ํ
const progressReal = document.querySelector(".progressReal");
const progressLecture = document.querySelector(".progressLecture");
let realData = 80;
let lectureData = 20;
progressReal.style.width = realData;
progressReal.innerHTML = `<span>${realData}%</span>`;
progressLecture.style.width = realData;
progressLecture.innerHTML = `<span>${lectureData}%</span>`;
-> ๋ฐฑ์๋์ ์ฐ๊ณํ๋ ์์ ์ ์ฃผ๋ก ํ ์์ ์ด๊ณ ์นํ์ด์ง๊ฐ ์์ฑ๋๋ฉด ์์งํ ๋ฐ์ดํฐ๋ก ํ ์คํธ ์ํํด ๋ณผ ์์
1.passport ๋ก๊ทธ์ธ ๊ตฌํ 2. ๊ฐ์ ํ๊ฐ DBํ ์ด๋ธ ๊ตฌ์ถ
const passport = require("passport");
const { Strategy: LocalStrategy } = require("passport-local");
const bcrypt = require("bcrypt");
const Student = require("../models/Student");
const passportConfig = { usernameField: "id", passwordField: "pw" };
const passportVerify = async (id, pw, done) => {
try {
const user = await Student.findOne({ where: { id } });
if (!user) {
done(null, false, { message: "์กด์ฌํ์ง ์๋ ์ฌ์ฉ์ ์
๋๋ค." });
return;
}
const compareResult = await bcrypt.compare(pw, user.pw);
if (compareResult) {
done(null, user);
return;
}
done(null, false, { reason: "์ฌ๋ฐ๋ฅด์ง ์์ ๋น๋ฐ๋ฒํธ ์
๋๋ค." });
} catch (error) {
console.error(error);
done(error);
}
};
module.exports = () => {
passport.use("local", new LocalStrategy(passportConfig, passportVerify));
};
module.exports.login = async (req, res) => {
try {
// ์๊น local๋ก ๋ฑ๋กํ ์ธ์ฆ๊ณผ์ ์คํ
passport.authenticate("local", (passportError, user, info) => {
// ์ธ์ฆ์ด ์คํจํ๊ฑฐ๋ ์ ์ ๋ฐ์ดํฐ๊ฐ ์๋ค๋ฉด ์๋ฌ ๋ฐ์
if (passportError || !user) {
res.status(400).json({ message: info });
return;
}
// user๋ฐ์ดํฐ๋ฅผ ํตํด ๋ก๊ทธ์ธ ์งํ
req.login(user, { session: false }, (loginError) => {
if (loginError) {
res.send(loginError);
return;
}
// ํด๋ผ์ด์ธํธ์๊ฒ JWT์์ฑ ํ ๋ฐํ
const token = jwt.sign(
{ id: user.id, name: user.name, auth: user.auth },
process.env.ACCESS_SECRET,
{ expiresIn: "1m", issuer: "jungseok" }
);
const refresh = jwt.sign(
{
id: user.id,
name: user.name,
auth: user.auth,
},
process.env.REFRESH_SECRET,
{ expiresIn: "10m", issuer: "jungseok" }
);
console.log("token: ", token);
console.log("refresh:", refresh);
res.redirect("/main");
});
})(req, res);
} catch (error) {
console.error(error);
next(error);
}
};
2.๊ฐ์ํ๊ฐ DB๊ตฌ์ถ
const Sequelize = require("sequelize");
//
module.exports = class User extends Sequelize.Model {
static init(sequelize) {
return super.init(
{
q1: {
type: Sequelize.INTEGER(20),
allowNull: false,
},
q2: {
type: Sequelize.INTEGER(20),
allowNull: false,
},
q3: {
type: Sequelize.INTEGER(20),
allowNull: false,
},
q4: {
type: Sequelize.INTEGER(20),
allowNull: false,
},
q5: {
type: Sequelize.INTEGER(20),
allowNull: false,
},
q6: {
type: Sequelize.STRING(255),
allowNull: false,
},
},
{
sequelize,
timestamps: false,
underscored: false,
modelName: "Evaluation", // ๋ชจ๋ธ ์ด๋ฆ์ ์ค์ , ๋
ธ๋ ํ๋ก์ ํธ์์ ์ฌ์ฉ
tableName: "Evaluation",
paranoid: false,
charset: "utf8", //ํ๊ธ์ ์
๋ ฅํ๊ธฐ ์ํ ์ค์
collate: "utf8_general_ci", //ํ๊ธ์ ์
๋ ฅํ๊ธฐ ์ํ ์ค์
}
);
}
static associate(db) {
db.Evaluation.belongsTo(db.Class, {
foreignKey: "CevaluationId",
sourceKey: "id",
});
}
};
์ ๋ฒ์ฃผ์๋ ์ฝ 3000๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ง๊ณ ํ์ตํ์ฌ ์๋์ ๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์์๋ค.
์ด๋ฒ์ฃผ์๋ ์ฝ 4000๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ํ์ตํ์ฌ ์๋์ ๊ฐ์ ๊ฒฐ๊ณผ๊ฐ ๋์๋ค.