웹사이트 링크:
https://codepen.io/pen?template=dPMMNVa
•
간단한 설명: 주식을 간단하게 즐길수 있는 주식 가상 모의 투자 게임
•
문제점: 실제로 수익을 낼수 없다는 점과 기능이 한정적임
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>주식 트레이드 시뮬레이터</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
body { font-family: Arial; background:#111; color:white; padding:20px; }
.container { display:flex; gap:20px; }
.left { width:700px; }
.right { width:300px; background:#222; padding:15px; border-radius:10px; }
button { width:100%; padding:10px; margin:5px 0; border:none; cursor:pointer; font-size:16px; border-radius:8px; }
.buy { background:#28a745; }
.sell { background:#dc3545; }
.short { background:#ff7700; }
.cover { background:#007bff; }
#history { height:200px; overflow-y:auto; background:#000; padding:10px; margin-top:10px; border-radius:8px; font-size:14px; }
</style>
</head>
<body>
<h1>📈 국내주식 50일 + 실시간 확장형 트레이드 시뮬레이터</h1>
<div class="container">
<div class="left">
<canvas id="stockChart" width="700" height="350"></canvas>
</div>
<div class="right">
<h2>거래 패널</h2>
<p id="dayText">Day: -</p>
<p id="priceText">현재가: -</p>
<p id="assetText">총자산: -</p>
<button class="buy" id="buyBtn">📈 매수(Buy)</button>
<button class="sell" id="sellBtn">📉 매도(Sell)</button>
<button class="short" id="shortSellBtn">🔻 공매도(Short)</button>
<button class="cover" id="shortCoverBtn">🔺 공매도 청산(Cover)</button>
<button id="nextDayBtn">➡ 다음날</button>
<h3>AI 예측</h3>
<button id="aiBtn">AI 예측 사용 (3회 남음)</button>
<h3>기록</h3>
<div id="history"></div>
</div>
</div>
<script>
let chart;
let day = 0;
let aiChance = 3;
let cash = 10000000;
let shares = 0;
let shortShares = 0;
let currentPrice = 0;
let priceData = [];
const FEE = 0.001;
function generate50Days(){
let base = 10000 + Math.random()*15000;
const arr = [];
for(let i=0;i<50;i++){
const r = (Math.random()*4 - 2);
base *= (1 + r/100);
arr.push(Math.round(base));
}
return arr;
}
function extendByOneDay(){
const last = priceData[priceData.length-1];
const r = (Math.random()*4 - 2);
const newPrice = Math.round(last * (1 + r/100));
priceData.push(newPrice);
}
function startGame(){
priceData = generate50Days();
day = 0;
cash = 10000000;
shares = 0;
shortShares = 0;
aiChance = 3;
updateTexts();
drawChart();
}
function nextDay(){
day++;
extendByOneDay();
updateTexts();
drawChart();
addHistory(`📅 Day ${day+1} 진행됨`);
}
function buy(){
currentPrice = priceData[day];
const qty = Math.floor(cash / (currentPrice * (1 + FEE)));
if(qty <= 0) return;
cash -= qty * currentPrice * (1 + FEE);
shares += qty;
addHistory(`매수 ${qty}주`);
updateTexts();
}
function sell(){
if(shares <= 0) return;
currentPrice = priceData[day];
cash += shares * currentPrice * (1 - FEE);
addHistory(`매도 ${shares}주`);
shares = 0;
updateTexts();
}
function shortSell(){
currentPrice = priceData[day];
const qty = Math.floor(cash / (currentPrice * (1 + FEE)));
if(qty <= 0) return;
shortShares += qty;
cash += qty * currentPrice * (1 - FEE);
addHistory(`공매도 ${qty}주`);
updateTexts();
}
function shortCover(){
if(shortShares <= 0) return;
currentPrice = priceData[day];
const cost = shortShares * currentPrice * (1 + FEE);
cash -= cost;
addHistory(`공매도 청산 ${shortShares}주`);
shortShares = 0;
updateTexts();
}
function useAI(){
if(aiChance <= 0) return alert("AI 사용 불가");
aiChance--;
const today = priceData[day];
const future = priceData[Math.max(0, day+1)];
const diff = future - today;
const rate = ((diff/today)*100).toFixed(2);
const msg = diff>0 ? `상승 +${rate}%` : `하락 ${rate}%`;
alert(`AI 예측 결과:\n내일 변동: ${msg}`);
document.getElementById("aiBtn").textContent = `AI 예측 사용 (${aiChance}회 남음)`;
}
function updateTexts(){
currentPrice = priceData[day];
const value = shares * currentPrice - shortShares * currentPrice;
const total = cash + value;
document.getElementById("dayText").textContent = `Day: ${day+1}`;
document.getElementById("priceText").textContent = `현재가: ${currentPrice.toLocaleString()}원`;
document.getElementById("assetText").textContent = `총자산: ${total.toLocaleString()}원`;
}
function drawChart(){
const ctx = document.getElementById("stockChart").getContext('2d');
if(chart) chart.destroy();
chart = new Chart(ctx, {
type:'line',
data:{
labels: priceData.map((_,i)=>i+1),
datasets:[{
label:'주가', data:priceData, borderColor:'cyan', pointRadius:0
}]
},
options:{ responsive:false }
});
}
function addHistory(text){
const box = document.getElementById("history");
box.innerHTML += `<div>${text}</div>`;
box.scrollTop = box.scrollHeight;
}
// 버튼 연결
document.getElementById("buyBtn").onclick = buy;
document.getElementById("sellBtn").onclick = sell;
document.getElementById("shortSellBtn").onclick = shortSell;
document.getElementById("shortCoverBtn").onclick = shortCover;
document.getElementById("nextDayBtn").onclick = nextDay;
document.getElementById("aiBtn").onclick = useAI;
startGame();
</script>
</body>
</html>
JavaScript
복사
2. ai를 활용한 인식 관련된 웹사이트 코드펜 작업
•
간단한 설명: 다양한 유형의 퀴즈를 손 인식으론 정답을 골라 맞추는 웹앱입니다
•
웹사이트 링크:
https://codepen.io/pen?template=LENNxwK
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>손가락 퀴즈 게임 (Hands Control)</title>
<style>
body { font-family: Arial; text-align: center; background: #f0f0f0; margin:0; padding:0;}
h1 { margin-top: 20px; }
#quiz-container { margin: 20px auto; padding: 20px; background: #fff; border-radius: 10px; width: 90%; max-width: 700px; box-shadow: 0 0 10px rgba(0,0,0,0.2);}
#feedback { font-size: 1.2em; margin: 10px;}
#videoElement { display:none; }
#canvas { border:1px solid black; border-radius:10px; margin-top:10px; }
#categorySelect { margin-bottom: 15px; padding: 5px; font-size: 1em;}
ul { text-align: left; list-style: none; padding-left: 0;}
li { margin: 5px 0; padding: 5px; background: #eee; border-radius: 5px;}
#fingerCount { font-size: 1.5em; margin: 10px; }
button { padding: 10px 20px; font-size: 1em; margin-top: 10px; cursor: pointer;}
</style>
</head>
<body>
<h1>손가락 퀴즈 게임</h1>
<div id="quiz-container">
<select id="categorySelect">
<option value="all">전체</option>
<option value="nonsense">넌센스</option>
<option value="korean_history">한국사</option>
<option value="world_history">세계사</option>
<option value="general">일반상식</option>
</select>
<div id="question">퀴즈 준비중...</div>
<ul id="options"></ul>
<div id="fingerCount">손가락: 0개</div>
<button id="submitBtn">정답 제출</button>
<div id="feedback"></div>
<video class="input_video" autoplay playsinline></video>
<canvas class="output_canvas" width="640" height="480"></canvas>
</div>
<script src="https://cdn.jsdelivr.net/npm/@mediapipe/hands/hands.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@mediapipe/camera_utils/camera_utils.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@mediapipe/drawing_utils/drawing_utils.js"></script>
<script>
// --- 퀴즈 문제 ---
const quizData = [
{category:'nonsense', q:"달이 뜨면 안 보이는 것은?", options:["달","해","별","구름","바람"], a:2},
{category:'nonsense', q:"먹으면 살이 안 찌는 음식은?", options:["사탕","과자","물","빵","밥"], a:3},
{category:'korean_history', q:"조선을 건국한 왕은?", options:["세종","태조","광해군","고려","정조"], a:2},
{category:'world_history', q:"피라미드가 있는 나라는?", options:["이집트","멕시코","인도","중국","그리스"], a:1},
{category:'general', q:"한국의 수도는?", options:["부산","서울","인천","대전","광주"], a:2},
];
let currentQuiz = 0;
let selectedCategory = "all";
let currentFingerCount = 0;
const questionEl = document.getElementById('question');
const optionsEl = document.getElementById('options');
const feedbackEl = document.getElementById('feedback');
const categorySelect = document.getElementById('categorySelect');
const fingerCountEl = document.getElementById('fingerCount');
const submitBtn = document.getElementById('submitBtn');
function getFilteredQuiz() {
return selectedCategory === "all" ? quizData : quizData.filter(q=>q.category===selectedCategory);
}
function showQuiz() {
const filteredQuiz = getFilteredQuiz();
if(filteredQuiz.length===0){
questionEl.innerText = "선택된 카테고리에 문제가 없습니다.";
optionsEl.innerHTML = "";
return;
}
if(currentQuiz >= filteredQuiz.length) currentQuiz = 0;
let quiz = filteredQuiz[currentQuiz];
questionEl.innerText = quiz.q;
optionsEl.innerHTML = "";
quiz.options.forEach((opt, idx) => {
let li = document.createElement('li');
li.innerText = `${idx+1}. ${opt}`;
optionsEl.appendChild(li);
});
feedbackEl.innerText = "";
}
// 손가락에 따른 옵션 하이라이트
function updateFingerSelection() {
fingerCountEl.innerText = `손가락: ${currentFingerCount}개`;
const filteredQuiz = getFilteredQuiz();
if(filteredQuiz.length===0) return;
const quiz = filteredQuiz[currentQuiz];
Array.from(optionsEl.children).forEach((li, idx)=>{
li.style.background = (currentFingerCount===idx+1) ? '#a0e0a0' : '#eee';
});
}
// 정답 제출
submitBtn.addEventListener('click',()=>{
const filteredQuiz = getFilteredQuiz();
if(filteredQuiz.length===0) return;
let quiz = filteredQuiz[currentQuiz];
if(currentFingerCount===quiz.a){
feedbackEl.style.color='green';
feedbackEl.innerText=`정답! 손가락 ${currentFingerCount}개`;
currentQuiz++;
setTimeout(showQuiz,1500);
} else {
feedbackEl.style.color='red';
feedbackEl.innerText=`오답! 손가락 ${currentFingerCount}개`;
}
});
categorySelect.addEventListener('change',()=>{
selectedCategory = categorySelect.value;
currentQuiz=0;
showQuiz();
});
showQuiz();
// ===== MediaPipe Hands =====
const videoElement = document.querySelector('.input_video');
const canvasElement = document.querySelector('.output_canvas');
const ctx = canvasElement.getContext('2d');
const hands = new Hands({
locateFile: (file) => `https://cdn.jsdelivr.net/npm/@mediapipe/hands/${file}`
});
hands.setOptions({
maxNumHands:1,
modelComplexity:1,
minDetectionConfidence:0.6,
minTrackingConfidence:0.6
});
hands.onResults(onResults);
const camera = new Camera(videoElement,{
onFrame: async()=>{ await hands.send({image:videoElement}); },
width:640, height:480
});
camera.start();
let lastStable = 0, lastTime = 0;
function onResults(results){
ctx.save();
ctx.clearRect(0,0,canvasElement.width,canvasElement.height);
ctx.drawImage(results.image,0,0,canvasElement.width,canvasElement.height);
if(results.multiHandLandmarks && results.multiHandLandmarks.length>0){
const lm = results.multiHandLandmarks[0];
drawConnectors(ctx,lm,HAND_CONNECTIONS,{color:'#00FF00',lineWidth:3});
drawLandmarks(ctx,lm,{color:'#FF0000',lineWidth:2});
const fingers = countFingers(lm);
// 안정화: 0.3초 유지 시만 확정
const now = performance.now();
if(fingers === lastStable){
lastTime = now;
} else if(now - lastTime > 300){
lastStable = fingers;
lastTime = now;
currentFingerCount = fingers;
updateFingerSelection();
}
ctx.font="bold 36px Arial";
ctx.fillStyle="#000";
ctx.fillText(`손가락: ${fingers}`,10,40);
}
ctx.restore();
}
function countFingers(lm){
let c=0;
if(lm[4].x < lm[3].x) c++; // 엄지
if(lm[8].y < lm[6].y) c++; // 검지
if(lm[12].y < lm[10].y) c++; // 중지
if(lm[16].y < lm[14].y) c++; // 약지
if(lm[20].y < lm[18].y) c++; // 새끼
return c;
}
</script>
</body>
</html>
JavaScript
복사



