|
|
<!DOCTYPE html>
|
|
|
<html lang="en">
|
|
|
<head>
|
|
|
<meta charset="UTF-8">
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
<title>ML Learning Platform</title>
|
|
|
<script src="https://cdn.tailwindcss.com"></script>
|
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
|
|
<style>
|
|
|
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
|
|
|
body {
|
|
|
font-family: 'Inter', sans-serif;
|
|
|
margin: 0;
|
|
|
overflow: hidden;
|
|
|
height: 100vh;
|
|
|
color: grey;
|
|
|
position: relative;
|
|
|
background-color: #ffffff;
|
|
|
}
|
|
|
|
|
|
|
|
|
#canvas {
|
|
|
position: fixed;
|
|
|
top: 0;
|
|
|
left: 0;
|
|
|
z-index: -1;
|
|
|
display: block;
|
|
|
background-color: transparent;
|
|
|
}
|
|
|
|
|
|
.button-hover {
|
|
|
transition: all 0.3s ease;
|
|
|
}
|
|
|
.button-hover:hover {
|
|
|
transform: translateY(-2px);
|
|
|
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
|
|
|
}
|
|
|
.stats-card {
|
|
|
background: rgba(255, 255, 255, 0.1);
|
|
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
|
}
|
|
|
.content-card {
|
|
|
background: rgba(255, 255, 255, 0.05);
|
|
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
|
backdrop-filter: blur(10px);
|
|
|
}
|
|
|
.modal {
|
|
|
background: rgba(0, 0, 0, 0.75);
|
|
|
}
|
|
|
.modal-content {
|
|
|
background: #1f2937;
|
|
|
border: 1px solid #374151;
|
|
|
}
|
|
|
|
|
|
|
|
|
main, footer, .content-container {
|
|
|
position: relative;
|
|
|
z-index: 1;
|
|
|
}
|
|
|
</style>
|
|
|
</head>
|
|
|
<body class="min-h-screen text-white">
|
|
|
|
|
|
<canvas id="canvas"></canvas>
|
|
|
|
|
|
|
|
|
<div class="container mx-auto px-4 py-8">
|
|
|
<div class="text-center mt-8">
|
|
|
<h1 class="text-4xl sm:text-5xl font-bold text-gray-800 mb-4">Machine Learning Platform</h1>
|
|
|
<p class="text-gray-600 text-sm sm:text-base">Explore the world of artificial intelligence and machine learning</p>
|
|
|
</div>
|
|
|
|
|
|
|
|
|
<div class="hidden md:grid grid-cols-1 md:grid-cols-2 gap-8 mb-12 mt-20">
|
|
|
|
|
|
<div class="content-card rounded-2xl p-6">
|
|
|
<h3 class="text-xl sm:text-2xl font-bold mb-3 text-green-600">Test Your Knowledge</h3>
|
|
|
<p class="text-sm mb-4 text-gray-600">"Test yourself and see what you know about ML"</p>
|
|
|
<p class="mb-4 text-xs sm:text-sm text-gray-500">Assess your current machine learning knowledge and identify areas for improvement</p>
|
|
|
<button onclick="takeQuiz()" class="button-hover bg-gradient-to-r from-green-500 to-teal-600 hover:from-green-600 hover:to-teal-700 text-white px-6 py-3 rounded-full font-semibold text-base shadow-lg w-full">
|
|
|
<i class="fas fa-graduation-cap mr-2"></i>Take Assessment
|
|
|
</button>
|
|
|
</div>
|
|
|
|
|
|
|
|
|
<div class="content-card rounded-2xl p-6">
|
|
|
<h3 class="text-xl sm:text-2xl font-bold mb-3 text-blue-600">Start Your ML Journey</h3>
|
|
|
<p class="text-sm mb-4 text-gray-600">"Start your ML learning with start button"</p>
|
|
|
<p class="mb-4 text-xs sm:text-sm text-gray-500">Build foundational skills and progress to advanced machine learning concepts</p>
|
|
|
<button onclick="startLearning()" class="button-hover bg-gradient-to-r from-blue-500 to-purple-600 hover:from-blue-600 hover:to-purple-700 text-white px-6 py-3 rounded-full font-semibold text-base shadow-lg w-full">
|
|
|
<i class="fas fa-rocket mr-2"></i>Start Learning
|
|
|
</button>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
|
|
|
<div class="block md:hidden mb-12 flex flex-col gap-4 mt-20">
|
|
|
<button onclick="takeQuiz()" class="button-hover bg-gradient-to-r from-green-500 to-teal-600 hover:from-green-600 hover:to-teal-700 text-white px-6 py-3 rounded-full font-semibold text-sm shadow-lg w-full">
|
|
|
<i class="fas fa-graduation-cap mr-2"></i>Test Your Knowledge
|
|
|
</button>
|
|
|
<button onclick="startLearning()" class="button-hover bg-gradient-to-r from-blue-500 to-purple-600 hover:from-blue-600 hover:to-purple-700 text-white px-6 py-3 rounded-full font-semibold text-sm shadow-lg w-full">
|
|
|
<i class="fas fa-rocket mr-2"></i>Start Learning
|
|
|
</button>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
|
|
|
<div id="messageModal" class="fixed inset-0 z-50 flex items-center justify-center modal hidden">
|
|
|
<div class="modal-content p-8 rounded-2xl shadow-lg max-w-sm w-full mx-4 transform transition-all scale-95 duration-300">
|
|
|
<h3 id="modalTitle" class="text-2xl font-bold mb-4 text-center"></h3>
|
|
|
<p id="modalMessage" class="text-gray-300 mb-6 text-center"></p>
|
|
|
<div class="flex justify-center">
|
|
|
<button onclick="hideMessage()" class="button-hover bg-gradient-to-r from-blue-500 to-purple-600 hover:from-blue-600 hover:to-purple-700 text-white px-8 py-3 rounded-full font-semibold shadow-lg">
|
|
|
OK
|
|
|
</button>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function showMessage(title, message) {
|
|
|
const modal = document.getElementById('messageModal');
|
|
|
const modalTitle = document.getElementById('modalTitle');
|
|
|
const modalMessage = document.getElementById('modalMessage');
|
|
|
|
|
|
modalTitle.textContent = title;
|
|
|
modalMessage.textContent = message;
|
|
|
|
|
|
modal.classList.remove('hidden');
|
|
|
document.body.style.overflow = 'hidden';
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function hideMessage() {
|
|
|
const modal = document.getElementById('messageModal');
|
|
|
modal.classList.add('hidden');
|
|
|
document.body.style.overflow = '';
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function startLearning() {
|
|
|
|
|
|
window.location.href = '/home';
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function takeQuiz() {
|
|
|
window.location.href = '/Test-home';
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const canvas = document.getElementById('canvas');
|
|
|
const ctx = canvas.getContext('2d');
|
|
|
canvas.width = window.innerWidth;
|
|
|
canvas.height = window.innerHeight;
|
|
|
|
|
|
|
|
|
class Ball {
|
|
|
constructor(name, x, y, dx, dy) {
|
|
|
this.name = name;
|
|
|
this.x = x;
|
|
|
this.y = y;
|
|
|
this.dx = dx;
|
|
|
this.dy = dy;
|
|
|
this.isControlled = false;
|
|
|
this.isHovered = false;
|
|
|
|
|
|
|
|
|
const fontSize = window.innerWidth < 768 ? '12px' : '16px';
|
|
|
|
|
|
const tempCanvas = document.createElement('canvas');
|
|
|
const tempCtx = tempCanvas.getContext('2d');
|
|
|
tempCtx.font = `bold ${fontSize} Arial`;
|
|
|
const metrics = tempCtx.measureText(this.name);
|
|
|
this.width = metrics.width;
|
|
|
this.height = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;
|
|
|
|
|
|
this.radius = Math.max(this.width, this.height) / 2;
|
|
|
this.mass = this.radius * 0.1;
|
|
|
}
|
|
|
|
|
|
draw() {
|
|
|
|
|
|
if (this.isHovered || this.isControlled) {
|
|
|
ctx.fillStyle = 'rgba(0, 153, 255, 0.3)';
|
|
|
ctx.beginPath();
|
|
|
ctx.roundRect(this.x - this.width/2 - 3, this.y - this.height/2 - 3, this.width + 6, this.height + 6, 5);
|
|
|
ctx.fill();
|
|
|
}
|
|
|
|
|
|
|
|
|
ctx.fillStyle = this.isControlled ? '#3498db' : '#555555';
|
|
|
const fontSize = window.innerWidth < 768 ? '12px' : '16px';
|
|
|
ctx.font = `bold ${fontSize} Arial`;
|
|
|
ctx.textAlign = 'center';
|
|
|
ctx.textBaseline = 'middle';
|
|
|
ctx.fillText(this.name, this.x, this.y);
|
|
|
}
|
|
|
|
|
|
update() {
|
|
|
if (!this.isControlled) {
|
|
|
this.x += this.dx;
|
|
|
this.y += this.dy;
|
|
|
|
|
|
if (this.x + this.width / 2 > canvas.width) {
|
|
|
this.dx *= -1;
|
|
|
this.x = canvas.width - this.width / 2;
|
|
|
}
|
|
|
if (this.x - this.width / 2 < 0) {
|
|
|
this.dx *= -1;
|
|
|
this.x = this.width / 2;
|
|
|
}
|
|
|
if (this.y + this.height / 2 > canvas.height) {
|
|
|
this.dy *= -1;
|
|
|
this.y = canvas.height - this.height / 2;
|
|
|
}
|
|
|
if (this.y - this.height / 2 < 0) {
|
|
|
this.dy *= -1;
|
|
|
this.y = this.height / 2;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
function rotate(dx, dy, angle) {
|
|
|
const rotatedVelocities = {
|
|
|
x: dx * Math.cos(angle) - dy * Math.sin(angle),
|
|
|
y: dx * Math.sin(angle) + dy * Math.cos(angle)
|
|
|
};
|
|
|
return rotatedVelocities;
|
|
|
}
|
|
|
|
|
|
function resolveCollision(ball1, ball2) {
|
|
|
const dx = ball1.x - ball2.x;
|
|
|
const dy = ball1.y - ball2.y;
|
|
|
const distance = Math.sqrt(dx * dx + dy * dy);
|
|
|
const sumOfRadii = ball1.radius + ball2.radius;
|
|
|
|
|
|
if (distance < sumOfRadii) {
|
|
|
const overlap = sumOfRadii - distance;
|
|
|
const pushBackVectorX = dx / distance * overlap * 0.5;
|
|
|
const pushBackVectorY = dy / distance * overlap * 0.5;
|
|
|
|
|
|
ball1.x += pushBackVectorX;
|
|
|
ball1.y += pushBackVectorY;
|
|
|
ball2.x -= pushBackVectorX;
|
|
|
ball2.y -= pushBackVectorY;
|
|
|
|
|
|
const angle = -Math.atan2(dy, dx);
|
|
|
const m1 = ball1.mass;
|
|
|
const m2 = ball2.mass;
|
|
|
|
|
|
const u1 = rotate(ball1.dx, ball1.dy, angle);
|
|
|
const u2 = rotate(ball2.dx, ball2.dy, angle);
|
|
|
|
|
|
const v1 = {
|
|
|
x: ((u1.x * (m1 - m2)) / (m1 + m2)) + ((u2.x * 2 * m2) / (m1 + m2)),
|
|
|
y: u1.y
|
|
|
};
|
|
|
const v2 = {
|
|
|
x: ((u2.x * (m2 - m1)) / (m1 + m2)) + ((u1.x * 2 * m1) / (m1 + m2)),
|
|
|
y: u2.y
|
|
|
};
|
|
|
|
|
|
const vFinal1 = rotate(v1.x, v1.y, -angle);
|
|
|
const vFinal2 = rotate(v2.x, v2.y, -angle);
|
|
|
|
|
|
ball1.dx = vFinal1.x;
|
|
|
ball1.dy = vFinal1.y;
|
|
|
ball2.dx = vFinal2.x;
|
|
|
ball2.dy = vFinal2.y;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
const algorithmNames = [
|
|
|
'Supervised', 'Unsupervised', 'Python', 'LLM', 'RAG', 'Agentic AI',
|
|
|
'Reinforcement Learning', 'Deep Learning', 'Computer Vision',
|
|
|
'Generative AI', 'Natural Language Processing', 'Vector Embeddings',
|
|
|
'Transformers', 'Prompt Engineering', 'Data Science', 'Machine Learning'
|
|
|
];
|
|
|
|
|
|
const mobileAlgorithmNames = [
|
|
|
'Supervised', 'Unsupervised', 'LLM', 'RAG','Deep Learning', 'Computer Vision',
|
|
|
'Generative AI', 'NLP', 'Vector Embeddings'
|
|
|
];
|
|
|
|
|
|
let balls = [];
|
|
|
|
|
|
function getRandomPosition() {
|
|
|
return {
|
|
|
x: Math.random() * (canvas.width * 0.8) + (canvas.width * 0.1),
|
|
|
y: Math.random() * (canvas.height * 0.8) + (canvas.height * 0.1)
|
|
|
};
|
|
|
}
|
|
|
|
|
|
function getRandomVelocity() {
|
|
|
const speed = 2;
|
|
|
const angle = Math.random() * 2 * Math.PI;
|
|
|
return {
|
|
|
dx: Math.cos(angle) * speed,
|
|
|
dy: Math.sin(angle) * speed
|
|
|
};
|
|
|
}
|
|
|
|
|
|
function initializeBalls() {
|
|
|
const names = window.innerWidth < 768 ? mobileAlgorithmNames : algorithmNames;
|
|
|
balls = names.map(name => {
|
|
|
const pos = getRandomPosition();
|
|
|
const vel = getRandomVelocity();
|
|
|
return new Ball(name, pos.x, pos.y, vel.dx, vel.dy);
|
|
|
});
|
|
|
}
|
|
|
|
|
|
let controlledBall = null;
|
|
|
let startX, startY;
|
|
|
|
|
|
function animate() {
|
|
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
|
|
|
|
for (let i = 0; i < balls.length; i++) {
|
|
|
balls[i].update();
|
|
|
balls[i].draw();
|
|
|
}
|
|
|
|
|
|
for (let i = 0; i < balls.length; i++) {
|
|
|
for (let j = i + 1; j < balls.length; j++) {
|
|
|
resolveCollision(balls[i], balls[j]);
|
|
|
}
|
|
|
}
|
|
|
requestAnimationFrame(animate);
|
|
|
}
|
|
|
|
|
|
canvas.addEventListener('mousedown', (event) => {
|
|
|
const mouseX = event.clientX;
|
|
|
const mouseY = event.clientY;
|
|
|
|
|
|
for (let i = 0; i < balls.length; i++) {
|
|
|
const ball = balls[i];
|
|
|
const distance = Math.sqrt((mouseX - ball.x) ** 2 + (mouseY - ball.y) ** 2);
|
|
|
if (distance < ball.radius) {
|
|
|
controlledBall = ball;
|
|
|
controlledBall.isControlled = true;
|
|
|
startX = controlledBall.x;
|
|
|
startY = controlledBall.y;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
|
|
|
canvas.addEventListener('mousemove', (event) => {
|
|
|
const mouseX = event.clientX;
|
|
|
const mouseY = event.clientY;
|
|
|
|
|
|
let isHovering = false;
|
|
|
balls.forEach(ball => {
|
|
|
const distance = Math.sqrt((mouseX - ball.x) ** 2 + (mouseY - ball.y) ** 2);
|
|
|
if (distance < ball.radius) {
|
|
|
ball.isHovered = true;
|
|
|
isHovering = true;
|
|
|
} else {
|
|
|
ball.isHovered = false;
|
|
|
}
|
|
|
});
|
|
|
|
|
|
if (isHovering || controlledBall) {
|
|
|
canvas.style.cursor = 'pointer';
|
|
|
} else {
|
|
|
canvas.style.cursor = 'default';
|
|
|
}
|
|
|
|
|
|
if (controlledBall) {
|
|
|
controlledBall.x = mouseX;
|
|
|
controlledBall.y = mouseY;
|
|
|
}
|
|
|
});
|
|
|
|
|
|
canvas.addEventListener('mouseup', () => {
|
|
|
if (controlledBall) {
|
|
|
const speedFactor = 0.1;
|
|
|
let dx = (controlledBall.x - startX) * speedFactor;
|
|
|
let dy = (controlledBall.y - startY) * speedFactor;
|
|
|
|
|
|
const maxSpeed = 10;
|
|
|
if (Math.sqrt(dx*dx + dy*dy) > maxSpeed) {
|
|
|
const angle = Math.atan2(dy, dx);
|
|
|
dx = Math.cos(angle) * maxSpeed;
|
|
|
dy = Math.sin(angle) * maxSpeed;
|
|
|
}
|
|
|
|
|
|
controlledBall.dx = dx;
|
|
|
controlledBall.dy = dy;
|
|
|
|
|
|
controlledBall.isControlled = false;
|
|
|
controlledBall = null;
|
|
|
}
|
|
|
});
|
|
|
|
|
|
|
|
|
function showMessage(title, message) {
|
|
|
const modal = document.getElementById('messageModal');
|
|
|
const modalTitle = document.getElementById('modalTitle');
|
|
|
const modalMessage = document.getElementById('modalMessage');
|
|
|
|
|
|
modalTitle.textContent = title;
|
|
|
modalMessage.textContent = message;
|
|
|
|
|
|
modal.classList.remove('hidden');
|
|
|
document.body.style.overflow = 'hidden';
|
|
|
}
|
|
|
|
|
|
function hideMessage() {
|
|
|
const modal = document.getElementById('messageModal');
|
|
|
modal.classList.add('hidden');
|
|
|
document.body.style.overflow = '';
|
|
|
}
|
|
|
|
|
|
function startLearning() {
|
|
|
window.location.href = '/home';
|
|
|
}
|
|
|
|
|
|
function takeQuiz() {
|
|
|
window.location.href = '/Test-home';
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
function resizeCanvas() {
|
|
|
canvas.width = window.innerWidth;
|
|
|
canvas.height = window.innerHeight;
|
|
|
|
|
|
|
|
|
initializeBalls();
|
|
|
}
|
|
|
|
|
|
window.addEventListener('resize', resizeCanvas);
|
|
|
|
|
|
|
|
|
initializeBalls();
|
|
|
animate();
|
|
|
</script>
|
|
|
</body>
|
|
|
</html>
|
|
|
|