Interactive Tutoring Platform

// // // Socket.io connection const socket = io(); // Session management let currentSession = null; let username = null; let isHost = false; let peers = {}; // WebRTC peer connections // Join existing session or create new one function setupSession() { // Get username username = prompt('Enter your name:', 'User_' + Math.floor(Math.random() * 1000)); if (!username) username = 'Anonymous'; // Check URL for session ID const urlParams = new URLSearchParams(window.location.search); let sessionId = urlParams.get('session'); // Create new session if none exists if (!sessionId) { sessionId = generateSessionId(); history.pushState(null, '', `?session=${sessionId}`); } // Join session socket.emit('join-session', sessionId, username); currentSession = sessionId; } // Generate random session ID function generateSessionId() { return Math.random().toString(36).substring(2, 15); } // Handle successful session join socket.on('session-joined', (sessionData) => { console.log('Joined session:', sessionData.sessionId); // Store session data currentSession = sessionData.sessionId; isHost = sessionData.isHost; // Update UI with existing users Object.values(sessionData.users).forEach(user => { if (user.id !== socket.id) { addUserToUI(user); } }); // Load existing whiteboard shapes if (sessionData.shapes.length > 0) { shapes = sessionData.shapes; redrawCanvas(); } // Load existing chat messages sessionData.messages.forEach(message => { addMessageToChat(message); }); // Setup WebRTC for all existing users Object.values(sessionData.users).forEach(user => { if (user.id !== socket.id) { initiateCall(user.id); } }); // Update UI for host status if (isHost) { document.getElementById('host-controls').classList.remove('hidden'); } }); // Handle new user joining socket.on('user-joined', (user) => { console.log('User joined:', user.username); addUserToUI(user); // Wait for them to set up their connection, they'll initiate the call }); // Handle user leaving socket.on('user-left', (userId) => { console.log('User left:', userId); removeUserFromUI(userId); // Close peer connection if exists if (peers[userId]) { peers[userId].destroy(); delete peers[userId]; } }); // Handle becoming host socket.on('became-host', () => { console.log('You are now the host'); isHost = true; document.getElementById('host-controls').classList.remove('hidden'); }); // Handle incoming drawing actions socket.on('draw-action', (action) => { if (action.type === 'add-shape') { shapes.push(action.shape); redrawCanvas(); } else if (action.type === 'clear') { shapes = []; redrawCanvas(); } }); // Handle chat messages socket.on('chat-message', (message) => { addMessageToChat(message); }); // Send drawing actions to server function sendDrawAction(actionType, shapeData = null) { const action = { type: actionType, shape: shapeData }; socket.emit('draw-action', action); } // Modified stopDrawing function for collaboration function stopDrawing(e) { if (!isDrawing) return; isDrawing = false; if (['line', 'rect', 'circle'].includes(currentTool) && currentShape) { const rect = canvas.getBoundingClientRect(); const x = e.clientX - rect.left; const y = e.clientY - rect.top; currentShape.endX = x; currentShape.endY = y; if (currentTool === 'circle') { currentShape.radius = Math.sqrt( Math.pow(x - currentShape.startX, 2) + Math.pow(y - currentShape.startY, 2) ); } shapes.push(currentShape); // Send the shape to everyone else sendDrawAction('add-shape', currentShape); currentShape = null; } } // Modified clearWhiteboard function for collaboration function clearWhiteboard() { ctx.clearRect(0, 0, canvas.width, canvas.height); shapes = []; // Send clear action to everyone else sendDrawAction('clear'); } // WebRTC functionality socket.on('signal', (data) => { if (data.from && data.type) { console.log('Received signal:', data.type, 'from', data.from); if (data.type === 'offer') { handleOffer(data.from, data.data); } else if (data.type === 'answer') { handleAnswer(data.from, data.data); } else if (data.type === 'candidate') { handleCandidate(data.from, data.data); } } }); // Initiate WebRTC call to another user function initiateCall(userId) { console.log('Initiating call to:', userId); const peer = new SimplePeer({ initiator: true, trickle: true, stream: stream // Your local media stream }); peer.on('signal', data => { socket.emit('signal', { type: data.type, data: data, to: userId }); }); peer.on('stream', remoteStream => { addRemoteStreamToUI(userId, remoteStream); }); peer.on('error', err => { console.error('Peer error:', err); }); peers[userId] = peer; } // Handle WebRTC offer function handleOffer(userId, offer) { console.log('Handling offer from:', userId); const peer = new SimplePeer({ initiator: false, trickle: true, stream: stream // Your local media stream }); peer.on('signal', data => { socket.emit('signal', { type: data.type, data: data, to: userId }); }); peer.on('stream', remoteStream => { addRemoteStreamToUI(userId, remoteStream); }); peer.on('error', err => { console.error('Peer error:', err); }); peer.signal(offer); peers[userId] = peer; } // Handle WebRTC answer function handleAnswer(userId, answer) { if (peers[userId]) { peers[userId].signal(answer); } } // Handle ICE candidate function handleCandidate(userId, candidate) { if (peers[userId]) { peers[userId].signal({ candidate: candidate }); } } // Add remote video to UI function addRemoteStreamToUI(userId, stream) { // Create video element for remote stream const remoteVideo = document.createElement('video'); remoteVideo.id = 'remote-video-' + userId; remoteVideo.autoplay = true; remoteVideo.classList.add('remote-video'); remoteVideo.srcObject = stream; // Add to video container const remoteVideosContainer = document.getElementById('remote-videos'); remoteVideosContainer.appendChild(remoteVideo); } // UI functions for user management function addUserToUI(user) { // Add user to participants list const userElement = document.createElement('div'); userElement.id = 'user-' + user.id; userElement.classList.add('user-item'); userElement.innerHTML = ` ${user.username} ${user.isHost ? 'Host' : ''} `; document.getElementById('participants-list').appendChild(userElement); } function removeUserFromUI(userId) { // Remove user from participants list const userElement = document.getElementById('user-' + userId); if (userElement) { userElement.remove(); } // Remove remote video if exists const remoteVideo = document.getElementById('remote-video-' + userId); if (remoteVideo) { remoteVideo.remove(); } } // Chat functionality function sendChatMessage() { const messageInput = document.getElementById('chat-input'); const message = messageInput.value.trim(); if (message) { socket.emit('chat-message', message); messageInput.value = ''; } } function addMessageToChat(message) { const chatMessages = document.getElementById('chat-messages'); const messageElement = document.createElement('div'); messageElement.classList.add('chat-message'); // Add sender class if this message is from current user if (message.userId === socket.id) { messageElement.classList.add('own-message'); } messageElement.innerHTML = `
${message.username} ${formatTime(new Date(message.timestamp))}
${escapeHtml(message.text)}
`; chatMessages.appendChild(messageElement); chatMessages.scrollTop = chatMessages.scrollHeight; // Scroll to bottom } // Helper functions function formatTime(date) { return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); } function escapeHtml(text) { const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } // Initialize session on page load document.addEventListener('DOMContentLoaded', function() { // Add required HTML elements for collaboration setupCollaborationUI(); // Initialize session after media setup setupMedia().then(() => { setupSession(); }); }); function setupCollaborationUI() { // Create container for remote videos const remoteVideosContainer = document.createElement('div'); remoteVideosContainer.id = 'remote-videos'; remoteVideosContainer.classList.add('remote-videos-container'); document.querySelector('.video-container').appendChild(remoteVideosContainer); // Create participants list const participantsContainer = document.createElement('div'); participantsContainer.className = 'participants-container'; participantsContainer.innerHTML = `

Participants

`; document.querySelector('.main-content').appendChild(participantsContainer); // Create chat interface const chatContainer = document.createElement('div'); chatContainer.className = 'chat-container'; chatContainer.innerHTML = `

Chat

`; document.querySelector('.main-content').appendChild(chatContainer); // Host-only controls (initially hidden) const hostControls = document.createElement('div'); hostControls.id = 'host-controls'; hostControls.className = 'host-controls hidden'; hostControls.innerHTML = `

Host Controls

`; document.querySelector('.main-content').appendChild(hostControls); // Add event listener for chat document.getElementById('send-chat-btn').addEventListener('click', sendChatMessage); document.getElementById('chat-input').addEventListener('keydown', function(e) { if (e.key === 'Enter') { sendChatMessage(); } }); // Add styles const style = document.createElement('style'); style.textContent = ` .main-content { display: grid; grid-template-columns: 2fr 1fr; grid-template-rows: auto 1fr auto; gap: 20px; } .whiteboard-container { grid-column: 1; grid-row: 1 / span 3; } .video-container { grid-column: 2; grid-row: 1; } .remote-videos-container { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 10px; } .remote-video { width: 120px; height: 90px; background-color: #222; border-radius: 4px; } .participants-container { grid-column: 2; grid-row: 2; background-color: white; border: 1px solid #ddd; border-radius: 8px; padding: 10px; } .user-item { padding: 5px; display: flex; justify-content: space-between; align-items: center; } .host-badge { background-color: #4285f4; color: white; padding: 2px 5px; border-radius: 3px; font-size: 0.8em; } .chat-container { grid-column: 2; grid-row: 3; background-color: white; border: 1px solid #ddd; border-radius: 8px; padding: 10px; display: flex; flex-direction: column; } .chat-messages { height: 200px; overflow-y: auto; margin-bottom: 10px; padding: 5px; background-color: #f9f9f9; border-radius: 4px; } .chat-message { margin-bottom: 8px; padding: 5px; border-radius: 4px; background-color: #e3f2fd; } .own-message { background-color: #e8f5e9; text-align: right; } .message-header { display: flex; justify-content: space-between; font-size: 0.8em; margin-bottom: 3px; } .chat-input-container { display: flex; gap: 5px; } #chat-input { flex-grow: 1; padding: 5px; border: 1px solid #ddd; border-radius: 4px; } .host-controls { grid-column: 2; grid-row: 4; background-color: white; border: 1px solid #ddd; border-radius: 8px; padding: 10px; } .hidden { display: none; } `; document.head.appendChild(style); }

Welcome to CrazyWise Tutoring!

Unlock your academic potential with our personalized tutoring lessons. We offer expert guidance in various subjects to help you achieve your goals. Start your journey to success today!

Unlock Your Potential with CrazyWise Tutoring's Unmatched Educational Benefits

At CrazyWise Tutoring, we’re dedicated to providing exceptional educational support and resources. Discover how our tutoring services and study materials can help you achieve academic success and reach your full potential.

Focus

Personalized attention to address individual learning styles and needs.

Flexibility

Flexible scheduling to accommodate busy student lifestyles.

Find the Perfect Tutor and Excel in Your Studies Today!

At CrazyWise Tutoring, we connect you with experienced and qualified tutors who are passionate about helping you succeed. Whether you need help with math, science, or any other subject, we have the perfect tutor for you. Invest in your education with our tutoring lessons.

Expert Tutors

Our tutors are subject matter experts dedicated to your academic success.

Personalized Learning

Get customized lesson plans tailored to your unique learning style and goals.

Become a Tutor

Join our team of expert tutors and make a difference in students' lives. Share your knowledge and passion for learning.

Explore Our Lessons

Browse our wide range of tutoring lessons and find the perfect match for your learning needs. Expert instruction for all subjects and levels.
A split screen showing an interactive whiteboard on one side and a live webcam view of a tutor on the other, demonstrating a tutoring session.

Experience and Live Tutoring Today!

Our interactive whiteboard and live webcam view create a dynamic and engaging learning environment. Collaborate with your tutor in real-time, visualize concepts, and receive personalized guidance every step of the way. Join CrazyWise Tutoring for an effective learning experience.
A screenshot of an interactive whiteboard with math equations and diagrams, used for online tutoring.
A live webcam view of a tutor explaining a concept during an online tutoring session.

Graph Paper Pads (Pack of 3)

$11.99

Graph Paper Pads (Pack of 3)

- +
Category: Tag:

Description

This pack of three graph paper pads is perfect for math, science, and engineering projects. Each pad contains 100 sheets of high-quality graph paper, featuring a 1/4 inch grid for precise drawing and calculations. The pads are bound at the top for easy page turning and are ideal for both classroom and home use. A great resource for students who need to visualize their work.

Interactive Tutoring Platform

Interactive Tutoring Platform