Aryan
added all environment project
a244ac5
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Student Math Score Predictor</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
flex-direction: column;
padding: 0;
margin: 0;
}
/* Navigation Bar */
nav {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
padding: 1rem 2rem;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
width: 100%;
}
.nav-container {
max-width: 1200px;
margin: 0 auto;
display: flex;
justify-content: space-between;
align-items: center;
}
.nav-brand {
color: white;
font-size: 1.5em;
font-weight: bold;
text-decoration: none;
transition: opacity 0.3s;
}
.nav-brand:hover {
opacity: 0.8;
}
.nav-links {
display: flex;
gap: 2rem;
list-style: none;
align-items: center;
}
.nav-links a {
color: white;
text-decoration: none;
font-weight: 500;
transition: opacity 0.3s;
display: inline-block;
white-space: nowrap;
}
.nav-links a:hover:not(.nav-home-btn) {
opacity: 0.8;
}
.nav-home-btn {
background: white !important;
color: #667eea !important;
padding: 8px 16px !important;
border-radius: 20px !important;
font-weight: 600 !important;
text-decoration: none !important;
transition: all 0.3s ease !important;
display: inline-block !important;
font-size: 0.95em !important;
line-height: 1 !important;
}
.nav-home-btn:hover {
transform: translateY(-2px) !important;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2) !important;
opacity: 1 !important;
}
@media (max-width: 768px) {
.nav-links {
gap: 1rem;
font-size: 0.9em;
}
.nav-brand {
font-size: 1.2em;
}
}
.main-content {
display: flex;
justify-content: center;
align-items: center;
flex: 1;
padding: 20px;
}
.container {
background: white;
border-radius: 20px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
max-width: 900px;
width: 100%;
overflow: hidden;
}
.header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 40px;
text-align: center;
}
.header h1 {
font-size: 2.5em;
margin-bottom: 10px;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2);
}
.header p {
font-size: 1.1em;
opacity: 0.9;
}
.content {
padding: 40px;
}
.form-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 25px;
margin-bottom: 30px;
}
.form-group {
display: flex;
flex-direction: column;
}
.form-group label {
font-weight: 600;
margin-bottom: 8px;
color: #333;
font-size: 0.95em;
}
.form-group input,
.form-group select {
padding: 12px 15px;
border: 2px solid #e0e0e0;
border-radius: 8px;
font-size: 1em;
transition: all 0.3s ease;
background: white;
}
.form-group input:focus,
.form-group select:focus {
outline: none;
border-color: #667eea;
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
}
.form-group select {
cursor: pointer;
appearance: none;
background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23667eea' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e");
background-repeat: no-repeat;
background-position: right 10px center;
background-size: 20px;
padding-right: 35px;
}
@media (max-width: 768px) {
.form-grid {
grid-template-columns: 1fr;
}
}
.full-width {
grid-column: 1 / -1;
}
.button-group {
display: flex;
gap: 15px;
margin-bottom: 30px;
justify-content: center;
}
button {
padding: 14px 40px;
font-size: 1em;
font-weight: 600;
border: none;
border-radius: 8px;
cursor: pointer;
transition: all 0.3s ease;
text-transform: uppercase;
letter-spacing: 0.5px;
}
button[type="submit"] {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
flex: 1;
max-width: 250px;
}
button[type="submit"]:hover:not(:disabled) {
transform: translateY(-2px);
box-shadow: 0 10px 25px rgba(102, 126, 234, 0.4);
}
button[type="submit"]:disabled {
opacity: 0.6;
cursor: not-allowed;
}
button[type="reset"] {
background: #f0f0f0;
color: #333;
flex: 1;
max-width: 250px;
}
button[type="reset"]:hover {
background: #e0e0e0;
transform: translateY(-2px);
}
.result-card {
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
color: white;
padding: 30px;
border-radius: 15px;
text-align: center;
margin-bottom: 30px;
display: none;
animation: slideIn 0.5s ease;
}
.result-card.show {
display: block;
}
@keyframes slideIn {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.result-card h2 {
font-size: 1.2em;
margin-bottom: 15px;
opacity: 0.95;
}
.predicted-score {
font-size: 3.5em;
font-weight: bold;
margin: 20px 0;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2);
}
.score-range {
font-size: 1em;
opacity: 0.9;
margin-top: 15px;
}
.info-box {
background: #f8f9fa;
padding: 20px;
border-radius: 10px;
border-left: 4px solid #667eea;
margin-top: 30px;
color: #555;
line-height: 1.6;
}
.info-box h3 {
color: #667eea;
margin-bottom: 10px;
}
.model-info-box {
background: #f8f9fa;
padding: 20px;
border-radius: 10px;
border-left: 4px solid #764ba2;
margin-top: 20px;
color: #555;
line-height: 1.6;
}
.model-info-box h3 {
color: #764ba2;
margin-bottom: 15px;
font-size: 1.1em;
}
.model-info-box h4 {
color: #667eea;
margin-top: 15px;
margin-bottom: 10px;
font-size: 1em;
}
.models-list {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin: 15px 0;
justify-content: center;
}
.models-list span {
background: white;
padding: 8px 12px;
border-radius: 6px;
border-left: 3px solid #667eea;
font-size: 0.9em;
color: #555;
text-align: center;
}
.best-model {
background: linear-gradient(135deg, #667eea15 0%, #764ba215 100%);
padding: 15px;
border-radius: 8px;
margin-top: 15px;
border: 1px solid #667eea30;
}
.score-badge {
display: inline-block;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 4px 12px;
border-radius: 20px;
font-weight: 600;
font-size: 1.1em;
}
.error-message {
background: #fee;
color: #c33;
padding: 15px;
border-radius: 8px;
border-left: 4px solid #c33;
margin-bottom: 20px;
display: none;
}
.error-message.show {
display: block;
animation: slideIn 0.3s ease;
}
.success-message {
background: #efe;
color: #3c3;
padding: 15px;
border-radius: 8px;
border-left: 4px solid #3c3;
margin-bottom: 20px;
display: none;
}
.success-message.show {
display: block;
animation: slideIn 0.3s ease;
}
</style>
</head>
<body>
<!-- Navigation Bar -->
<nav>
<div class="nav-container">
<a href="/" class="nav-brand">📊 Math Score Predictor</a>
<ul class="nav-links">
<li><a href="/">🏠 Home</a></li>
<li><a href="/" class="nav-home-btn">📝 Prediction Form</a></li>
</ul>
</div>
</nav>
<div class="main-content">
<div class="container">
<div class="header">
<h1>📊 Math Score Predictor</h1>
<p>Predict student math performance based on their profile</p>
</div>
<div class="content">
<div class="error-message" id="errorMsg"></div>
<div class="success-message" id="successMsg"></div>
<form method="POST" action="/predict" id="predictionForm">
<div class="form-grid">
<div class="form-group">
<label for="gender">Gender</label>
<select name="gender" id="gender" required>
<option value="">Select Gender</option>
<option value="male">Male</option>
<option value="female">Female</option>
</select>
</div>
<div class="form-group">
<label for="race">Race/Ethnicity</label>
<select name="race" id="race" required>
<option value="">Select Race/Ethnicity</option>
<option value="group A">Group A</option>
<option value="group B">Group B</option>
<option value="group C">Group C</option>
<option value="group D">Group D</option>
<option value="group E">Group E</option>
</select>
</div>
<div class="form-group">
<label for="parental_education">Parental Level of Education</label>
<select name="parental_education" id="parental_education" required>
<option value="">Select Education Level</option>
<option value="some high school">Some High School</option>
<option value="high school">High School</option>
<option value="some college">Some College</option>
<option value="associate's degree">Associate's Degree</option>
<option value="bachelor's degree">Bachelor's Degree</option>
<option value="master's degree">Master's Degree</option>
</select>
</div>
<div class="form-group">
<label for="lunch">Lunch Type</label>
<select name="lunch" id="lunch" required>
<option value="">Select Lunch Type</option>
<option value="standard">Standard</option>
<option value="free/reduced">Free/Reduced</option>
</select>
</div>
<div class="form-group">
<label for="test_preparation_course">Test Preparation Course</label>
<select name="test_preparation_course" id="test_preparation_course" required>
<option value="">Select Status</option>
<option value="none">None</option>
<option value="completed">Completed</option>
</select>
</div>
<div class="form-group">
<label for="reading_score">Reading Score (0-100)</label>
<input type="number" name="reading_score" id="reading_score" min="0" max="100" required>
</div>
<div class="form-group">
<label for="writing_score">Writing Score (0-100)</label>
<input type="number" name="writing_score" id="writing_score" min="0" max="100" required>
</div>
</div>
<div class="button-group">
<button type="submit" id="submitBtn" class="btn-predict">🎯 Predict Math Score</button>
<button type="reset" id="resetBtn" class="btn-reset">🔄 Clear Form</button>
</div>
</form>
<div class="result-card" id="resultCard">
<h2>Predicted Math Score</h2>
<div class="predicted-score" id="predictedScore">--</div>
<div class="score-range" id="scoreRange"></div>
</div>
<div class="info-box">
<h3>ℹ️ How it works</h3>
<p>This predictor uses machine learning trained on historical student data to estimate math scores based on student demographics, socioeconomic factors, and existing test scores. The prediction is an estimate and may vary from actual results.</p>
</div>
<div class="model-info-box">
<h3>🤖 Model Selection & Performance</h3>
<p>To build this predictor, I tested multiple supervised learning algorithms including:</p>
<div class="models-list">
<span>Linear Regression</span>
<span>Ridge Regression</span>
<span>Lasso Regression</span>
<span>Decision Tree</span>
<span>Random Forest</span>
<span>Gradient Boosting</span>
<span>AdaBoost</span>
<span>Support Vector Regression (SVR)</span>
<span>K-Neighbors</span>
<span>CatBoost</span>
<span>XGBRegressor</span>
</div>
<div class="best-model">
<h4>✨ Best Model Selected: Ridge Regression</h4>
<p><strong>R² Score:</strong> <span class="score-badge">0.8806</span></p>
<p style="margin-top: 10px; font-size: 0.9em; color: #666;">Ridge Regression provides the best balance between accuracy and generalization, making it ideal for predicting student math scores with high reliability.</p>
</div>
</div>
</div>
</div>
<script>
document.getElementById('predictionForm').addEventListener('submit', async function(e) {
e.preventDefault();
const errorMsg = document.getElementById('errorMsg');
const successMsg = document.getElementById('successMsg');
const resultCard = document.getElementById('resultCard');
const submitBtn = document.getElementById('submitBtn');
// Clear previous messages
errorMsg.classList.remove('show');
successMsg.classList.remove('show');
resultCard.classList.remove('show');
// Show loading state
const originalText = submitBtn.textContent;
submitBtn.textContent = '⏳ Processing...';
submitBtn.disabled = true;
try {
// Collect form data
const formData = new FormData(this);
const data = Object.fromEntries(formData);
// Convert scores to numbers
data.reading_score = parseFloat(data.reading_score);
data.writing_score = parseFloat(data.writing_score);
// Send POST request to Flask backend
const response = await fetch('/predict', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data)
});
const result = await response.json();
if (!response.ok || result.error) {
throw new Error(result.error || 'Prediction failed');
}
// Display result
const predictedScore = Math.round(result.predicted_math_score);
document.getElementById('predictedScore').textContent = predictedScore;
document.getElementById('scoreRange').textContent =
`Score Range: ${Math.max(0, predictedScore - 8)}-${Math.min(100, predictedScore + 8)}`;
resultCard.classList.add('show');
successMsg.textContent = '✅ Prediction completed successfully!';
successMsg.classList.add('show');
} catch (error) {
errorMsg.textContent = '❌ Error: ' + error.message;
errorMsg.classList.add('show');
console.error('Error:', error);
} finally {
// Restore button
submitBtn.textContent = originalText;
submitBtn.disabled = false;
}
});
document.getElementById('resetBtn').addEventListener('click', function() {
document.getElementById('errorMsg').classList.remove('show');
document.getElementById('successMsg').classList.remove('show');
document.getElementById('resultCard').classList.remove('show');
});
</script>
</body>
</html>