extractStudents static method

List<Student> extractStudents(
  1. Excel excel,
  2. List<School> schools
)

Associe les écoles aux choix de chaque étudiant via la liste schools.

Lève une ExcelParsingException si la liste d'écoles est vide.

Implementation

static List<Student> extractStudents(Excel excel, List<School> schools) {
// Check if schools list is empty
if (schools.isEmpty) {
  throw ExcelParsingException("La liste des écoles est vide. Importez d'abord les écoles.");
}

Map<String, Student> tempStudentMap = {};
  int nextStudentId=1;

  if (excel.sheets.isEmpty) {
    print("Information: Le fichier Excel ne contient aucune feuille.");

    return [];
  }
  String sheetName = excel.sheets.keys.first; // Prend la première feuille par défaut
  var sheet = excel.tables[sheetName]; // Utilisez .tables pour la nouvelle version de la lib excel

  if (sheet == null) {
    print("Erreur: La feuille '$sheetName' n'a pas pu être chargée ou n'existe pas dans les tables.");
    return [];
  }

  if (sheet.maxRows < 2) {
    print("Information: La feuille '$sheetName' contient moins de 2 lignes (pas de données ou juste l'en-tête).");
    return [];
  }
  // Itérer sur les lignes, en commençant par la deuxième (index 1) pour sauter l'en-tête
  for (int rowIndex = 1; rowIndex < sheet.maxRows; rowIndex++) {
    var rowData = sheet.row(rowIndex); // Récupère les données de la ligne actuelle

    // Vérification minimale : le nom de l'étudiant doit être présent
    String studentName = _getStringCellData(rowData, _colStudentName);
    if (studentName.isEmpty) {
      // print("Ligne ${rowIndex + 1}: Nom de l'étudiant manquant, ligne ignorée.");
      continue; // Passer à la ligne suivante
    }

    // --- Récupération/Création de l'objet Student ---
    Student currentStudent;
    if (!tempStudentMap.containsKey(studentName)) {
      // Nouvel étudiant : lire ses informations spécifiques et le créer
      String specialization = _getStringCellData(rowData, _colSpecialization, defaultValue: "Non spécifiée");
      int rankingS1 = _getIntCellData(rowData, _colRankingS1);
      int ectsNumber = _getIntCellData(rowData, _colEctsNumber);
      String langLvl = _getStringCellData(rowData, _colLangLvl, defaultValue: "N/A");
      double missedHours = _getDoubleCellData(rowData, _colMissedHours);
      String comment = _getStringCellData(rowData, _colComment);
      // Lire d'autres champs de Student si nécessaire (post_comment, etc.)
      // String? postComment = _getStringCellData(rowData, _colPostComment, defaultValue: null); // Exemple

      currentStudent = Student(
          nextStudentId,
          studentName,
          {}, // Initialiser avec une Map de choix vide
          specialization,
          rankingS1,
          ectsNumber,
          langLvl,
          missedHours,
          comment
        // post_comment: postComment, // Si vous avez ce champ et l'avez lu
      );
      tempStudentMap[studentName] = currentStudent;
      nextStudentId++;
    } else {
      // Étudiant existant : le récupérer
      currentStudent = tempStudentMap[studentName]!;
      // Optionnel : mettre à jour des informations de l'étudiant si elles sont plus complètes
      // sur cette ligne, mais attention à ne pas écraser des données valides.
      // Exemple : si la spécialisation était "Non spécifiée" et qu'on en trouve une :
      if (currentStudent.specialization == "Non spécifiée") {
        String newSpecialization = _getStringCellData(rowData, _colSpecialization, defaultValue: "Non spécifiée");
        if (newSpecialization != "Non spécifiée") {
          currentStudent.specialization = newSpecialization;
          currentStudent.year_departement(newSpecialization); // Mettre à jour année/département
        }
      }
    }

    // --- Traitement du Vœu pour l'étudiant actuel ---
    String rawWishOrder = _getStringCellData(rowData, _colWishOrder);
    String country = _getStringCellData(rowData, _colCountry);
    String schoolName = _getStringCellData(rowData, _colSchoolName);
    String rawInterRanking = _getStringCellData(rowData, _colInterRanking);

    // Un vœu nécessite au moins un ordre, un nom d'école et un pays
    if (rawWishOrder.isEmpty || schoolName.isEmpty || country.isEmpty || rawInterRanking.isEmpty) {
      // print("Ligne ${rowIndex + 1} pour ${studentName}: Données de vœu incomplètes, vœu ignoré.");
      continue; // Passer si les informations essentielles du vœu sont manquantes
    }

    int? wishOrder = int.tryParse(rawWishOrder);
    double? interRanking = double.tryParse(rawInterRanking); // Votre Choice utilise double

    if (wishOrder == null || interRanking == null) {
      // print("Ligne ${rowIndex + 1} pour ${studentName}: Format numérique invalide pour l'ordre du vœu ou interRanking, vœu ignoré.");
      continue;
    }

    // Création de l'objet School
    School? school = schools.where((e) => e.name == schoolName).firstOrNull;
    if (school == null){
      print("The schools doesn't appear in the list of parsed school");
      return [];
    }
    // Création de l'objet Choice (en passant l'instance de Student, comme défini dans votre classe Choice)
    Choice choice = Choice(school, interRanking, currentStudent);

    // Ajout du choix à la map de choix de l'étudiant
    currentStudent.choices[wishOrder] = choice;
  }
  // Conversion de la map des étudiants en une liste triée par ID
  List<Student> finalStudentList = tempStudentMap.values.toList();
  finalStudentList.sort((a, b) => a.id.compareTo(b.id));

  // Add verification at specific points, for example:
  if (tempStudentMap.isEmpty) {
    throw ExcelParsingException("Aucun étudiant n'a été trouvé dans le fichier");
  }

  // Check if any student has no choices
  for (var student in tempStudentMap.values) {
    if (student.choices.isEmpty) {
      throw ExcelParsingException("L'étudiant ${student.name} n'a aucun choix d'école");
    }
  }

  return finalStudentList;
}