yamanavijayavardhan commited on
Commit
b2d0a56
·
1 Parent(s): ca13a3e

fix index.html

Browse files
Files changed (2) hide show
  1. main.py +74 -3
  2. templates/index.html +42 -40
main.py CHANGED
@@ -279,6 +279,44 @@ def compute_answers():
279
  error_msg = str(e).encode('ascii', 'ignore').decode('ascii')
280
  return jsonify({"error": error_msg}), 500
281
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
282
  @app.route('/compute_marks', methods=['POST'])
283
  def compute_marks():
284
  try:
@@ -307,8 +345,19 @@ def compute_marks():
307
  "message": "No files uploaded"
308
  }), 400
309
 
 
 
 
 
 
 
 
 
 
 
310
  # Create a temporary directory for processing
311
  base_temp_dir = tempfile.mkdtemp()
 
312
 
313
  # Dictionary to store results by student folder
314
  results = {}
@@ -320,31 +369,48 @@ def compute_marks():
320
  try:
321
  # Validate file
322
  if not file or not file.filename:
 
323
  continue
324
 
325
  # Get folder structure from file path
326
  path_parts = file.filename.split('/')
327
  if len(path_parts) < 2:
 
328
  continue
329
 
330
  student_folder = path_parts[-2]
331
  filename = path_parts[-1]
332
 
 
 
 
 
 
 
 
 
 
333
  if student_folder not in results:
334
  results[student_folder] = [0] * len(correct_answers)
 
335
 
336
  # Save and process file
337
  student_dir = os.path.join(base_temp_dir, student_folder)
338
  os.makedirs(student_dir, exist_ok=True)
339
  filepath = os.path.join(student_dir, filename)
 
 
 
340
  file.save(filepath)
 
341
 
342
  # Extract text
343
  extracted_text = extract_text_from_image(filepath)
344
  if not extracted_text:
 
345
  failed_files.append({
346
  "file": file.filename,
347
- "error": "No text could be extracted"
348
  })
349
  continue
350
 
@@ -381,6 +447,7 @@ def compute_marks():
381
 
382
  except Exception as score_error:
383
  error_msg = str(score_error).encode('ascii', 'ignore').decode('ascii')
 
384
  failed_files.append({
385
  "file": file.filename,
386
  "error": f"Error calculating scores: {error_msg}"
@@ -389,9 +456,11 @@ def compute_marks():
389
 
390
  marks = new_value(best_score, 0, 1, 0, 5)
391
  results[student_folder][best_answer_index] = round(marks, 2)
 
392
 
393
  except Exception as e:
394
  error_msg = str(e).encode('ascii', 'ignore').decode('ascii')
 
395
  failed_files.append({
396
  "file": file.filename,
397
  "error": error_msg
@@ -402,8 +471,9 @@ def compute_marks():
402
  # Clean up temp directory
403
  try:
404
  shutil.rmtree(base_temp_dir)
405
- except Exception:
406
- pass
 
407
 
408
  if not results:
409
  return jsonify({
@@ -429,6 +499,7 @@ def compute_marks():
429
 
430
  except Exception as e:
431
  error_msg = str(e).encode('ascii', 'ignore').decode('ascii')
 
432
  return jsonify({
433
  "error": "Server error",
434
  "message": f"Error computing marks: {error_msg}"
 
279
  error_msg = str(e).encode('ascii', 'ignore').decode('ascii')
280
  return jsonify({"error": error_msg}), 500
281
 
282
+ def validate_folder_structure(files):
283
+ """Validate the folder structure of uploaded files"""
284
+ try:
285
+ # Get unique student folders
286
+ student_folders = set()
287
+ for file in files:
288
+ if not file or not file.filename:
289
+ continue
290
+ path_parts = file.filename.split('/')
291
+ if len(path_parts) >= 2:
292
+ student_folders.add(path_parts[-2])
293
+
294
+ if not student_folders:
295
+ return False, "No valid student folders found"
296
+
297
+ # Check if each student folder has the same number of files
298
+ file_counts = {}
299
+ for file in files:
300
+ if not file or not file.filename:
301
+ continue
302
+ path_parts = file.filename.split('/')
303
+ if len(path_parts) >= 2:
304
+ student = path_parts[-2]
305
+ file_counts[student] = file_counts.get(student, 0) + 1
306
+
307
+ if not file_counts:
308
+ return False, "No valid files found in student folders"
309
+
310
+ # Check if all students have the same number of files
311
+ counts = list(file_counts.values())
312
+ if len(set(counts)) > 1:
313
+ return False, "Inconsistent number of files across student folders"
314
+
315
+ return True, f"Valid folder structure with {len(student_folders)} students and {counts[0]} files each"
316
+
317
+ except Exception as e:
318
+ return False, f"Error validating folder structure: {str(e)}"
319
+
320
  @app.route('/compute_marks', methods=['POST'])
321
  def compute_marks():
322
  try:
 
345
  "message": "No files uploaded"
346
  }), 400
347
 
348
+ # Validate folder structure
349
+ is_valid, message = validate_folder_structure(files)
350
+ if not is_valid:
351
+ return jsonify({
352
+ "error": "Invalid folder structure",
353
+ "message": message
354
+ }), 400
355
+
356
+ log_print(f"Folder structure validation: {message}")
357
+
358
  # Create a temporary directory for processing
359
  base_temp_dir = tempfile.mkdtemp()
360
+ log_print(f"Created temporary directory: {base_temp_dir}")
361
 
362
  # Dictionary to store results by student folder
363
  results = {}
 
369
  try:
370
  # Validate file
371
  if not file or not file.filename:
372
+ log_print("Skipping invalid file", "WARNING")
373
  continue
374
 
375
  # Get folder structure from file path
376
  path_parts = file.filename.split('/')
377
  if len(path_parts) < 2:
378
+ log_print(f"Invalid file path structure: {file.filename}", "WARNING")
379
  continue
380
 
381
  student_folder = path_parts[-2]
382
  filename = path_parts[-1]
383
 
384
+ # Validate file type
385
+ if not is_valid_image_file(filename):
386
+ log_print(f"Invalid file type: {filename}", "WARNING")
387
+ failed_files.append({
388
+ "file": file.filename,
389
+ "error": "Invalid file type. Only .jpg, .jpeg, and .png files are allowed."
390
+ })
391
+ continue
392
+
393
  if student_folder not in results:
394
  results[student_folder] = [0] * len(correct_answers)
395
+ log_print(f"Processing student folder: {student_folder}")
396
 
397
  # Save and process file
398
  student_dir = os.path.join(base_temp_dir, student_folder)
399
  os.makedirs(student_dir, exist_ok=True)
400
  filepath = os.path.join(student_dir, filename)
401
+
402
+ # Ensure filepath is secure
403
+ filepath = secure_filename(filepath)
404
  file.save(filepath)
405
+ log_print(f"Saved file: {filepath}")
406
 
407
  # Extract text
408
  extracted_text = extract_text_from_image(filepath)
409
  if not extracted_text:
410
+ log_print(f"No text extracted from: {filepath}", "WARNING")
411
  failed_files.append({
412
  "file": file.filename,
413
+ "error": "No text could be extracted from the image"
414
  })
415
  continue
416
 
 
447
 
448
  except Exception as score_error:
449
  error_msg = str(score_error).encode('ascii', 'ignore').decode('ascii')
450
+ log_print(f"Error calculating scores for {filepath}: {error_msg}", "ERROR")
451
  failed_files.append({
452
  "file": file.filename,
453
  "error": f"Error calculating scores: {error_msg}"
 
456
 
457
  marks = new_value(best_score, 0, 1, 0, 5)
458
  results[student_folder][best_answer_index] = round(marks, 2)
459
+ log_print(f"Processed {filename} for {student_folder}: {marks} marks")
460
 
461
  except Exception as e:
462
  error_msg = str(e).encode('ascii', 'ignore').decode('ascii')
463
+ log_print(f"Error processing file {file.filename}: {error_msg}", "ERROR")
464
  failed_files.append({
465
  "file": file.filename,
466
  "error": error_msg
 
471
  # Clean up temp directory
472
  try:
473
  shutil.rmtree(base_temp_dir)
474
+ log_print("Cleaned up temporary directory")
475
+ except Exception as e:
476
+ log_print(f"Warning: Could not clean up temporary directory: {e}", "WARNING")
477
 
478
  if not results:
479
  return jsonify({
 
499
 
500
  except Exception as e:
501
  error_msg = str(e).encode('ascii', 'ignore').decode('ascii')
502
+ log_print(f"Error in compute_marks: {error_msg}", "ERROR")
503
  return jsonify({
504
  "error": "Server error",
505
  "message": f"Error computing marks: {error_msg}"
templates/index.html CHANGED
@@ -879,41 +879,49 @@
879
 
880
  // Clear previous files
881
  selectedFiles.clear();
882
- folderStructure = createFolderStructure(files);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
883
 
884
  // Update the visual tree
885
  const treeContainer = document.getElementById('folder-tree');
886
  treeContainer.innerHTML = '';
887
 
888
- if (files.length === 0) {
889
- treeContainer.innerHTML = '<div class="no-files-message">No files uploaded yet</div>';
890
  return;
891
  }
892
 
893
  renderFolderStructure(folderStructure, treeContainer);
894
 
895
- // Count total image files
896
- let imageCount = 0;
897
- for (let file of files) {
898
- if (file.type.startsWith('image/')) {
899
- imageCount++;
900
- const pathParts = file.webkitRelativePath.split('/');
901
- selectedFiles.set(file.webkitRelativePath, {
902
- file: file,
903
- mainFolder: pathParts[0],
904
- studentFolder: pathParts[1],
905
- fileName: pathParts[pathParts.length - 1],
906
- fullPath: file.webkitRelativePath
907
- });
908
- }
909
- }
910
-
911
  // Show immediate feedback
912
- if (imageCount > 0) {
913
- alert(`Successfully loaded ${imageCount} image files`);
914
- } else {
915
- alert('No valid image files found in the selected folder');
916
- }
917
  });
918
 
919
  function removeFile(path) {
@@ -974,11 +982,13 @@
974
  formData.append('correct_answers[]', answer);
975
  });
976
 
977
- // Add files with their paths
978
  let validFiles = 0;
979
  selectedFiles.forEach((fileInfo, path) => {
980
  if (fileInfo.file.type.startsWith('image/')) {
981
- formData.append('file', fileInfo.file, path);
 
 
982
  validFiles++;
983
  }
984
  });
@@ -996,23 +1006,15 @@
996
  body: formData
997
  });
998
 
999
- console.log('Response status:', response.status);
1000
- console.log('Response headers:', Object.fromEntries(response.headers.entries()));
1001
-
1002
- // Check if the response is JSON
1003
- const contentType = response.headers.get('content-type');
1004
- if (!contentType || !contentType.includes('application/json')) {
1005
- console.error('Non-JSON response:', await response.text());
1006
- throw new Error('Server did not return JSON');
1007
  }
1008
 
1009
  const result = await response.json();
1010
  console.log('Parsed response:', result);
1011
 
1012
- if (!response.ok) {
1013
- throw new Error(result.message || result.error || `Server returned error ${response.status}`);
1014
- }
1015
-
1016
  if (result.error) {
1017
  throw new Error(result.message || result.error);
1018
  }
@@ -1055,7 +1057,7 @@
1055
  <thead>
1056
  <tr>
1057
  <th>Student Folder</th>
1058
- <th>Question Number</th>
1059
  <th>Marks</th>
1060
  </tr>
1061
  </thead>
@@ -1073,7 +1075,7 @@
1073
  const row = document.createElement('tr');
1074
  row.innerHTML = `
1075
  <td>${student}</td>
1076
- <td>Question ${index + 1}</td>
1077
  <td>${mark}</td>
1078
  `;
1079
  tbody.appendChild(row);
 
879
 
880
  // Clear previous files
881
  selectedFiles.clear();
882
+
883
+ // Validate file types
884
+ const validImageTypes = ['image/jpeg', 'image/jpg', 'image/png'];
885
+ let invalidFiles = [];
886
+
887
+ for (let file of files) {
888
+ if (file.type.startsWith('image/')) {
889
+ if (!validImageTypes.includes(file.type)) {
890
+ invalidFiles.push(file.name);
891
+ } else {
892
+ const pathParts = file.webkitRelativePath.split('/');
893
+ // Store the full relative path
894
+ const fullPath = file.webkitRelativePath;
895
+ selectedFiles.set(fullPath, {
896
+ file: file,
897
+ mainFolder: pathParts[0],
898
+ studentFolder: pathParts[1],
899
+ fileName: pathParts[pathParts.length - 1],
900
+ fullPath: fullPath
901
+ });
902
+ }
903
+ }
904
+ }
905
+
906
+ if (invalidFiles.length > 0) {
907
+ alert(`Warning: The following files are not valid image files (only .jpg, .jpeg, and .png are allowed):\n${invalidFiles.join('\n')}`);
908
+ }
909
+
910
+ folderStructure = createFolderStructure(Array.from(selectedFiles.values()).map(info => info.file));
911
 
912
  // Update the visual tree
913
  const treeContainer = document.getElementById('folder-tree');
914
  treeContainer.innerHTML = '';
915
 
916
+ if (selectedFiles.size === 0) {
917
+ treeContainer.innerHTML = '<div class="no-files-message">No valid image files uploaded yet</div>';
918
  return;
919
  }
920
 
921
  renderFolderStructure(folderStructure, treeContainer);
922
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
923
  // Show immediate feedback
924
+ alert(`Successfully loaded ${selectedFiles.size} valid image files`);
 
 
 
 
925
  });
926
 
927
  function removeFile(path) {
 
982
  formData.append('correct_answers[]', answer);
983
  });
984
 
985
+ // Add files with their folder structure
986
  let validFiles = 0;
987
  selectedFiles.forEach((fileInfo, path) => {
988
  if (fileInfo.file.type.startsWith('image/')) {
989
+ // Maintain the folder structure in the file path
990
+ const relativePath = fileInfo.fullPath;
991
+ formData.append('file', fileInfo.file, relativePath);
992
  validFiles++;
993
  }
994
  });
 
1006
  body: formData
1007
  });
1008
 
1009
+ if (!response.ok) {
1010
+ const errorText = await response.text();
1011
+ console.error('Server error:', errorText);
1012
+ throw new Error(`Server returned error ${response.status}: ${errorText}`);
 
 
 
 
1013
  }
1014
 
1015
  const result = await response.json();
1016
  console.log('Parsed response:', result);
1017
 
 
 
 
 
1018
  if (result.error) {
1019
  throw new Error(result.message || result.error);
1020
  }
 
1057
  <thead>
1058
  <tr>
1059
  <th>Student Folder</th>
1060
+ <th>Image Name</th>
1061
  <th>Marks</th>
1062
  </tr>
1063
  </thead>
 
1075
  const row = document.createElement('tr');
1076
  row.innerHTML = `
1077
  <td>${student}</td>
1078
+ <td>answer${index + 1}.jpg</td>
1079
  <td>${mark}</td>
1080
  `;
1081
  tbody.appendChild(row);