Commit
·
961677f
1
Parent(s):
f9fc0ab
new index____
Browse files- main.py +55 -69
- templates/index.html +98 -10
main.py
CHANGED
@@ -117,95 +117,81 @@ def compute_answers():
|
|
117 |
@app.route('/compute_marks', methods=['POST'])
|
118 |
def compute_marks():
|
119 |
try:
|
120 |
-
# Get answers
|
121 |
a = request.form.get('answers')
|
122 |
if not a:
|
123 |
return jsonify({"error": "No answers provided"}), 400
|
124 |
|
125 |
-
print("Received answers:", a)
|
126 |
|
127 |
-
# Parse answers
|
128 |
a = json.loads(a)
|
129 |
answers = []
|
130 |
for i in a:
|
131 |
ans = i.split('\n\n')
|
132 |
answers.append(ans)
|
133 |
|
134 |
-
|
135 |
-
|
136 |
-
# Process uploaded files
|
137 |
-
files = request.files.getlist('files[]')
|
138 |
-
if not files:
|
139 |
-
return jsonify({"error": "No files uploaded"}), 400
|
140 |
-
|
141 |
data = {}
|
|
|
142 |
|
143 |
-
#
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
print("Processed files:", data) # Debug print
|
168 |
-
|
169 |
-
# Calculate vectors for answers
|
170 |
-
s_marks = {}
|
171 |
-
sen_vec_answers = []
|
172 |
-
word_vec_answers = []
|
173 |
-
|
174 |
-
for i in answers:
|
175 |
-
temp_v = []
|
176 |
-
temp_w = []
|
177 |
-
for j in i:
|
178 |
-
temp_v.append(question_vector_sentence(j))
|
179 |
-
temp_w.append(question_vector_word(j))
|
180 |
-
sen_vec_answers.append(temp_v)
|
181 |
-
word_vec_answers.append(temp_w)
|
182 |
-
|
183 |
-
# Process each student's answers
|
184 |
-
for student in data:
|
185 |
-
s_marks[student] = []
|
186 |
-
count = 0
|
187 |
-
for image_path in data[student]:
|
188 |
try:
|
|
|
189 |
s_answer = extract_text_from_image(image_path)
|
190 |
-
print(f"Extracted answer from {image_path}:", s_answer) # Debug print
|
191 |
-
|
192 |
-
tf_idf_word_values, max_tfidf = create_tfidf_values(answers[count])
|
193 |
-
m = marks(s_answer, sen_vec_answers[count], word_vec_answers[count],
|
194 |
-
tf_idf_word_values, max_tfidf, answers[count])
|
195 |
|
196 |
-
if
|
197 |
-
|
198 |
-
|
199 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
200 |
except Exception as e:
|
201 |
print(f"Error processing {image_path}: {str(e)}")
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
|
|
|
|
|
|
206 |
|
207 |
except Exception as e:
|
208 |
-
print("Error in compute_marks:", str(e))
|
209 |
return jsonify({"error": str(e)}), 500
|
210 |
|
211 |
|
|
|
117 |
@app.route('/compute_marks', methods=['POST'])
|
118 |
def compute_marks():
|
119 |
try:
|
120 |
+
# Get answers
|
121 |
a = request.form.get('answers')
|
122 |
if not a:
|
123 |
return jsonify({"error": "No answers provided"}), 400
|
124 |
|
125 |
+
print("Received answers:", a)
|
126 |
|
|
|
127 |
a = json.loads(a)
|
128 |
answers = []
|
129 |
for i in a:
|
130 |
ans = i.split('\n\n')
|
131 |
answers.append(ans)
|
132 |
|
133 |
+
# Process student folders and files
|
|
|
|
|
|
|
|
|
|
|
|
|
134 |
data = {}
|
135 |
+
parent_folder = "ans_image" # Your main folder
|
136 |
|
137 |
+
# Check if parent folder exists
|
138 |
+
if not os.path.exists(parent_folder):
|
139 |
+
return jsonify({"error": "ans_image folder not found"}), 400
|
140 |
+
|
141 |
+
# Process each student folder
|
142 |
+
for student_folder in os.listdir(parent_folder):
|
143 |
+
student_path = os.path.join(parent_folder, student_folder)
|
144 |
+
if os.path.isdir(student_path):
|
145 |
+
data[student_folder] = []
|
146 |
+
# Get all images in student folder
|
147 |
+
for image_file in sorted(os.listdir(student_path)):
|
148 |
+
if image_file.endswith(('.jpg', '.jpeg', '.png')):
|
149 |
+
image_path = os.path.join(student_path, image_file)
|
150 |
+
image_name = os.path.splitext(image_file)[0] # Get filename without extension
|
151 |
+
data[student_folder].append({
|
152 |
+
'path': image_path,
|
153 |
+
'name': image_name
|
154 |
+
})
|
155 |
+
|
156 |
+
# Calculate marks
|
157 |
+
results = []
|
158 |
+
for student_folder, images in data.items():
|
159 |
+
for idx, image_info in enumerate(images):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
160 |
try:
|
161 |
+
image_path = image_info['path']
|
162 |
s_answer = extract_text_from_image(image_path)
|
|
|
|
|
|
|
|
|
|
|
163 |
|
164 |
+
if idx < len(answers): # Make sure we have corresponding answer
|
165 |
+
tf_idf_word_values, max_tfidf = create_tfidf_values(answers[idx])
|
166 |
+
m = marks(s_answer, sen_vec_answers[idx], word_vec_answers[idx],
|
167 |
+
tf_idf_word_values, max_tfidf, answers[idx])
|
168 |
+
|
169 |
+
if isinstance(m, torch.Tensor):
|
170 |
+
m = m.item()
|
171 |
+
|
172 |
+
results.append({
|
173 |
+
'student': student_folder,
|
174 |
+
'image_name': image_info['name'],
|
175 |
+
'marks': round(m, 2)
|
176 |
+
})
|
177 |
+
else:
|
178 |
+
results.append({
|
179 |
+
'student': student_folder,
|
180 |
+
'image_name': image_info['name'],
|
181 |
+
'marks': 0
|
182 |
+
})
|
183 |
except Exception as e:
|
184 |
print(f"Error processing {image_path}: {str(e)}")
|
185 |
+
results.append({
|
186 |
+
'student': student_folder,
|
187 |
+
'image_name': image_info['name'],
|
188 |
+
'marks': 0
|
189 |
+
})
|
190 |
+
|
191 |
+
return jsonify({"message": results}), 200
|
192 |
|
193 |
except Exception as e:
|
194 |
+
print("Error in compute_marks:", str(e))
|
195 |
return jsonify({"error": str(e)}), 500
|
196 |
|
197 |
|
templates/index.html
CHANGED
@@ -464,6 +464,42 @@
|
|
464 |
min-height: 80px;
|
465 |
}
|
466 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
467 |
</style>
|
468 |
</head>
|
469 |
<body>
|
@@ -921,11 +957,11 @@
|
|
921 |
}
|
922 |
}
|
923 |
|
924 |
-
function displayMarks(
|
925 |
const container = document.getElementById('marks-table-container');
|
926 |
container.innerHTML = '';
|
927 |
|
928 |
-
if (!
|
929 |
container.innerHTML = '<p>No marks available</p>';
|
930 |
return;
|
931 |
}
|
@@ -934,9 +970,9 @@
|
|
934 |
table.innerHTML = `
|
935 |
<thead>
|
936 |
<tr>
|
937 |
-
<th>Student</th>
|
|
|
938 |
<th>Marks</th>
|
939 |
-
<th>Average</th>
|
940 |
</tr>
|
941 |
</thead>
|
942 |
<tbody>
|
@@ -944,18 +980,70 @@
|
|
944 |
`;
|
945 |
|
946 |
const tbody = table.querySelector('tbody');
|
947 |
-
|
948 |
-
|
|
|
|
|
|
|
|
|
949 |
const row = document.createElement('tr');
|
950 |
row.innerHTML = `
|
951 |
-
<td>${student}</td>
|
952 |
-
<td>${
|
953 |
-
<td>${
|
954 |
`;
|
955 |
tbody.appendChild(row);
|
956 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
957 |
|
958 |
container.appendChild(table);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
959 |
}
|
960 |
</script>
|
961 |
</body>
|
|
|
464 |
min-height: 80px;
|
465 |
}
|
466 |
}
|
467 |
+
|
468 |
+
/* Add to your existing CSS */
|
469 |
+
table {
|
470 |
+
width: 100%;
|
471 |
+
margin-top: 1rem;
|
472 |
+
border-collapse: collapse;
|
473 |
+
}
|
474 |
+
|
475 |
+
th, td {
|
476 |
+
padding: 0.75rem;
|
477 |
+
text-align: left;
|
478 |
+
border-bottom: 1px solid #dee2e6;
|
479 |
+
}
|
480 |
+
|
481 |
+
th {
|
482 |
+
background-color: #4361ee;
|
483 |
+
color: white;
|
484 |
+
font-weight: 500;
|
485 |
+
}
|
486 |
+
|
487 |
+
tr:hover {
|
488 |
+
background-color: #f8f9fa;
|
489 |
+
}
|
490 |
+
|
491 |
+
.marks-summary {
|
492 |
+
margin-top: 1rem;
|
493 |
+
padding: 1rem;
|
494 |
+
background-color: #e3f2fd;
|
495 |
+
border-radius: 8px;
|
496 |
+
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
497 |
+
}
|
498 |
+
|
499 |
+
.marks-summary h4 {
|
500 |
+
margin-top: 0;
|
501 |
+
color: #4361ee;
|
502 |
+
}
|
503 |
</style>
|
504 |
</head>
|
505 |
<body>
|
|
|
957 |
}
|
958 |
}
|
959 |
|
960 |
+
function displayMarks(results) {
|
961 |
const container = document.getElementById('marks-table-container');
|
962 |
container.innerHTML = '';
|
963 |
|
964 |
+
if (!results || results.length === 0) {
|
965 |
container.innerHTML = '<p>No marks available</p>';
|
966 |
return;
|
967 |
}
|
|
|
970 |
table.innerHTML = `
|
971 |
<thead>
|
972 |
<tr>
|
973 |
+
<th>Student Folder</th>
|
974 |
+
<th>Image Name</th>
|
975 |
<th>Marks</th>
|
|
|
976 |
</tr>
|
977 |
</thead>
|
978 |
<tbody>
|
|
|
980 |
`;
|
981 |
|
982 |
const tbody = table.querySelector('tbody');
|
983 |
+
|
984 |
+
// Group results by student for calculating averages
|
985 |
+
const studentGroups = {};
|
986 |
+
|
987 |
+
results.forEach(result => {
|
988 |
+
// Add row for individual marks
|
989 |
const row = document.createElement('tr');
|
990 |
row.innerHTML = `
|
991 |
+
<td>${result.student}</td>
|
992 |
+
<td>${result.image_name}</td>
|
993 |
+
<td>${result.marks}</td>
|
994 |
`;
|
995 |
tbody.appendChild(row);
|
996 |
+
|
997 |
+
// Collect data for averages
|
998 |
+
if (!studentGroups[result.student]) {
|
999 |
+
studentGroups[result.student] = {
|
1000 |
+
total: 0,
|
1001 |
+
count: 0
|
1002 |
+
};
|
1003 |
+
}
|
1004 |
+
studentGroups[result.student].total += result.marks;
|
1005 |
+
studentGroups[result.student].count++;
|
1006 |
+
});
|
1007 |
+
|
1008 |
+
// Add separator row
|
1009 |
+
const separatorRow = document.createElement('tr');
|
1010 |
+
separatorRow.innerHTML = '<td colspan="3" style="border-top: 2px solid #4361ee;"></td>';
|
1011 |
+
tbody.appendChild(separatorRow);
|
1012 |
+
|
1013 |
+
// Add average rows
|
1014 |
+
Object.entries(studentGroups).forEach(([student, data]) => {
|
1015 |
+
const averageRow = document.createElement('tr');
|
1016 |
+
const average = (data.total / data.count).toFixed(2);
|
1017 |
+
averageRow.innerHTML = `
|
1018 |
+
<td>${student}</td>
|
1019 |
+
<td><strong>Average</strong></td>
|
1020 |
+
<td><strong>${average}</strong></td>
|
1021 |
+
`;
|
1022 |
+
averageRow.style.backgroundColor = '#f8f9fa';
|
1023 |
+
tbody.appendChild(averageRow);
|
1024 |
+
});
|
1025 |
|
1026 |
container.appendChild(table);
|
1027 |
+
|
1028 |
+
// Add summary section
|
1029 |
+
const summary = document.createElement('div');
|
1030 |
+
summary.className = 'marks-summary';
|
1031 |
+
summary.style.marginTop = '1rem';
|
1032 |
+
summary.style.padding = '1rem';
|
1033 |
+
summary.style.backgroundColor = '#e3f2fd';
|
1034 |
+
summary.style.borderRadius = '8px';
|
1035 |
+
|
1036 |
+
const totalStudents = Object.keys(studentGroups).length;
|
1037 |
+
const overallAverage = Object.values(studentGroups)
|
1038 |
+
.reduce((acc, curr) => acc + (curr.total / curr.count), 0) / totalStudents;
|
1039 |
+
|
1040 |
+
summary.innerHTML = `
|
1041 |
+
<h4>Summary</h4>
|
1042 |
+
<p>Total Students: ${totalStudents}</p>
|
1043 |
+
<p>Overall Average: ${overallAverage.toFixed(2)}</p>
|
1044 |
+
`;
|
1045 |
+
|
1046 |
+
container.appendChild(summary);
|
1047 |
}
|
1048 |
</script>
|
1049 |
</body>
|