<style>
	.wait {
		position: fixed;
		width: 50px;
		height: 10px;
		background: #424242;
		top: calc(50% - 50px);
		left: 50%;
		margin-left: -25px;
		animation: wait 0.6s ease-out alternate infinite;
	}

	@keyframes wait {
		100% {
			transform: translateY(-30px) rotate(360deg)
		}
	}

	main h2 {
		border-bottom: 4px solid #0069d9;
		grid-column: 1 / -1;
		margin-bottom: 2px;
	}

	main {
		font-family: Verdana, Geneva, Tahoma, sans-serif;
		margin-right: 16px;
		padding: 8px;
		border-radius: 12px;
		background: #717171;
		display: flex;
		flex-wrap: wrap;
		gap: 8px;
	}

	section {
		background: #dbccb8;
		padding: 8px;
		border-radius: 8px;
	}

	.moitemoite {
		display: grid;
		grid-template-columns: 1fr 1fr;
		gap: 8px;
	}

	@media screen and (max-width: 1000px) {
		.moitemoite {
			grid-template-columns: 1fr;
		}
	}

	.notes {
		opacity: 0.4;
		pointer-events: none;
	}

	.parcours,
	.notes {
		display: inline-grid;
		grid-template-columns: auto auto;
		align-items: center;
		grid-row-gap: 4px;
		grid-column-gap: 16px;
		margin-bottom: 16px;
		background: #FFF;
		border: 1px solid #0069d9;
		border-radius: 8px;
		padding: 8px 16px;
	}

	h3,
	.resultats small {
		grid-column: 1 / -1;
		margin: 4px 0;
	}

	.parcours form {
		display: inline;
	}

	.parcours input {
		padding: 4px 8px;
		border: 1px solid #aaa;
		border-radius: 4px;
		width: 40px;
	}

	.dropZone {
		border: 2px dashed #0069d9;
		padding: 8px 16px;
		text-align: center;
	}

	.notes select {
		padding: 4px 8px;
	}

	.donnees,
	.resultats {
		display: inline-grid;
	}

	.donnees {
		background: #aaa;
		padding: 4px;
		border-radius: 4px;
	}

	.donnees>* {
		border-radius: 4px;
		border: 1px solid #aaa;
	}

	.donnees>*,
	.resultats>*:not(h2, button) {
		background: #fff;
		outline: 1px solid #aaa;
		padding: 4px 8px;
	}

	.entete {
		background: #0069d9 !important;
		color: #FFF;
	}

	.criteres {
		text-align: right;
	}

	.criteres:not(.criteres+.criteres),
	.voeux:not(.voeux+.voeux),
	.entete+.entete {
		margin-left: 8px;
	}

	small {
		display: block;
		margin-bottom: 4px;
		padding: 2px 4px;
		background: #fff;
		border-radius: 4px;
		font-style: italic;
	}

	button {
		background: rgb(134, 179, 0);
		color: #FFF;
		font-size: 16px;
		padding: 16px 32px;
		border: none;
		border-radius: 4px;
		box-shadow: 0 2px 2px rgba(0, 0, 0, 0.26);
		cursor: pointer;
	}

	button:hover {
		color: #ddd;
	}

	button:active {
		transform: translateY(2px);
		box-shadow: initial;
	}

	.grid {
		display: grid;
		grid-template-columns: 1fr 1fr;
		gap: 4px;
	}

	button.autre {
		background: #0c9;
	}

	.resultats button {
		background: #90c;
		margin-bottom: 4px;
	}

	b {
		color: #000;
	}

	.moitemoite input:invalid,
	[contenteditable]:empty {
		animation: focus .5s alternate infinite;
	}

	@keyframes focus {
		0% {
			outline: 1px solid rgba(204, 0, 153, 0)
		}

		100% {
			outline: 1px solid rgba(204, 0, 153, 1)
		}
	}

	[data-actif] {
		cursor: pointer;
	}

	[data-actif=false] {
		background: #ccc;
	}

	[data-highlight=true] {
		outline: 2px solid #90c !important;
		border-radius: 4px;
		z-index: 1;
	}
</style>

<main class="moitemoite">
	<div class="wait"></div>
	<section>
		<h2>Données</h2>
		<div class="parcours"></div>
		<div class="notes"></div>
		<div style="display:flex; gap: 8px;">
			<button onclick="exportData()">Exporter les données</button>
			<!--<form class="dropZone">
				<div><b>Importer les données</b></div>
				<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#0099cc" stroke-width="2" stroke-linecap="round"><path pathlength="100" d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"></path></svg>
				Déposez une fichier ou <br>
				<label><input type="file" accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"></label>
			</form>-->
		</div>
		<small style="margin-top: 4px">💡 Vous pouvez ensuite copier / coller, dans les cases blanches ci-dessous, les
			"notes" et "voeux", directement depuis le tableur.</small>
		<small>💡 Les voeux doivent être une série d'entiers en partant de 1 - exemple : 3, 1 et 2.</small>
		<small>💡 Cliquez sur un étudiant pour qu'il ne fasse pas parti du tri.</small>
		<div class="donnees"></div>
	</section>

	<section>
		<h2>Résultats</h2>
		<div class=grid>
			<button class="actionTri" data-tri="notes">Trier uniquement par <b>notes</b></button>
			<button class="actionTri" data-tri="voeux">Trier par <b>voeux</b> puis par notes</button>
		</div>
		<small>
			💡 Vous pouvez exporter les résultats pour les utiliser dans l'éditeur de groupes/partitions.
		</small>
		<div class="resultats"></div>
	</section>

</main>

<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx-populate/1.21.0/xlsx-populate.min.js"></script>
<script>
	/************************/
	/* A générer par Scodoc */
	/************************/
	let choixNotes = [
		"RCUE1",
		"RCUE2",
		"RCUE3",
		"RCUE4",
		"RCUE5"
	]
	let formsemestre;
	let parcours = {};
	let nbParcours;
	/*let parcours = {
		1448: {
			nom: "Communication",
			places: 28,	// Modifiable par l'utilisateur
			etudiants: []	// Résultat du tri
		},
		1449: {
			nom: "Création numérique",
			places: 28,	// Modifiable par l'utilisateur
			etudiants: []	// Résultat du tri
		},
		1450: {
			nom: "Développement Web",
			places: 28,	// Modifiable par l'utilisateur
			etudiants: []	// Résultat du tri
		}
	}*/
	let etudiants = {};
	/*let etudiants = {
		123: {
			actif: true,
			nom: "Jean Bono",
			criteres: {
				1448: 10,		// Modifiable par l'utilisateur
				1449: 12,	// Modifiable par l'utilisateur
				1450: 8		// Modifiable par l'utilisateur
			},
			voeux: {
				1448: 1,		// Modifiable par l'utilisateur
				1449: 3,		// Modifiable par l'utilisateur
				1450: 2		// Modifiable par l'utilisateur
			}
		},
		124: {
			actif: true,
			nom: "Etudiant 2",
			criteres: {
				1448: 11,		// Modifiable par l'utilisateur
				1449: 12.5,	// Modifiable par l'utilisateur
				1450: 8		// Modifiable par l'utilisateur
			},
			voeux: {
				1448: 2,		// Modifiable par l'utilisateur
				1449: 1,		// Modifiable par l'utilisateur
				1450: 3		// Modifiable par l'utilisateur
			}
		},
		125: {
			actif: true,
			nom: "Etudiant 3",
			criteres: {
				1448: 10,		// Modifiable par l'utilisateur
				1449: 12.5,	// Modifiable par l'utilisateur
				1450: 15		// Modifiable par l'utilisateur
			},
			voeux: {
				1448: 3,		// Modifiable par l'utilisateur
				1449: 2,		// Modifiable par l'utilisateur
				1450: 1		// Modifiable par l'utilisateur
			}
		}
	}*/

	/************************/
	/* Chargement des datas */
	/************************/
	go();
	async function go() {
		document.querySelector('.wait').style.display = "";
		let params = (new URL(document.location)).searchParams;
		formsemestre = params.get('formsemestre_id');

		let parcoursRaw = await fetchData("/ScoDoc/{{formsemestre.departement.acronym}}/api/formsemestre/" + formsemestre + "/partitions");
		let etudiantsRaw = await fetchData("/ScoDoc/{{formsemestre.departement.acronym}}/api/formsemestre/" + formsemestre + "/etudiants");
		//let decisionsRaw = await fetchData("/ScoDoc/{{formsemestre.departement.acronym}}/api/formsemestre/" + formsemestre + "/decisions_jury");
		let savedData = await getFromScodoc();

		etudiantsRaw.sort((a, b) => {
			return (a.nom + a.prenom).localeCompare(b.nom + b.prenom)
		});

		processParcours(parcoursRaw, savedData);
		processNotes();
		processEtudiants(etudiantsRaw, savedData);
		processEvents();

		document.querySelector("body").classList.add("loaded");
		document.querySelector('.wait').style.display = "none";
	}

	function fetchData(request) {
		return fetch(request)
			.then(r => { return r.json() })
			.then(data => {
				return data;
			}).catch(error => {
				document.querySelector("main").innerHTML = "<h2>Une erreur s'est produite lors du transfert des données.</h2>";
				throw 'Fin du script - données invalides';
			})
	}

	/************************/
	/* Génération du front  */
	/************************/
	function processParcours(parcoursRaw, savedData) {

		Object.values(parcoursRaw).forEach(partition => {
			if (partition.partition_name == "Parcours") {
				Object.values(partition.groups).forEach(group => {
					parcours[group.id] = {
						nom: group.group_name,
						places: savedData.parcours?.[group.id].places || 28,
						etudiants: []	// Résultat du tri
					}
				})
			}

		})

		nbParcours = Object.keys(parcours).length;
		/* Zones parcours */
		let output = "<h3>Places</h3>";
		Object.entries(parcours).forEach(([idParcours, dataParcours]) => {
			output += `
					<div data-idparcours=${idParcours}>${dataParcours.nom}</div>
					<div><form onsubmit="return false;"><input type=number required min=0 data-idparcours="${idParcours}" value="${dataParcours.places}"></form> places</div>
				`;
		})
		document.querySelector(".parcours").innerHTML = output;
	}

	function processNotes() {
		/* Zones critère de notes */
		let output = "<h3>Appliquer les notes</h3>";
		Object.entries(parcours).forEach(([idParcours, dataParcours]) => {
			output += `
					<div data-idparcours=${idParcours}>${dataParcours.nom}</div>
					<div>
						<select data-idparcours=${idParcours}>
							${(
					() => {
						let output = "<option>-</option>";
						choixNotes.forEach(notes => {
							output += `<option value="${notes}">${notes}</option>`;
						})
						return output;
					}
				)()}
						</select>
					</div>
				`;
		})
		document.querySelector(".notes").innerHTML = output;
	}

	function processEtudiants(etudiantsRaw, savedData) {
		/*id123: {
			actif: true,
			nom: "Jean Bono",
			criteres: {
				1448: 10,		// Modifiable par l'utilisateur
				1449: 12,	// Modifiable par l'utilisateur
				1450: 8		// Modifiable par l'utilisateur
			},
			voeux: {
				1448: 1,		// Modifiable par l'utilisateur
				1449: 3,		// Modifiable par l'utilisateur
				1450: 2		// Modifiable par l'utilisateur
			}
		},*/
		etudiantsRaw.forEach(etudiant => {
			saved = savedData.etudiants?.['id' + etudiant.id] || {};
			etudiants['id' + etudiant.id] = {
				actif: saved.actif == false ? false : true,
				nom: etudiant.nom + " " + etudiant.prenom,
				criteres: saved.criteres || {},
				voeux: saved.voeux || {}
			};

			if (Object.keys(saved).length == 0)
				Object.keys(parcours).forEach((idParcours, index) => {
					etudiants['id' + etudiant.id].criteres[idParcours] = 10;
					etudiants['id' + etudiant.id].voeux[idParcours] = index + 1;
				})
		})

		/* Zone étudiants */
		let output = `
				<div class=entete>Etudiants</div>
				<div class=entete style="grid-column: span ${nbParcours}">Notes</div>
				<div class=entete style="grid-column: span ${nbParcours}">Voeux</div>`;
		Object.entries(etudiants).forEach(([id, etudiant]) => {
			output += `
					<div data-actif=${etudiant.actif}>${etudiant.nom}</div>
					${display(id, etudiant, "criteres", true)}
					${display(id, etudiant, "voeux", true)}
				`;
		})

		document.querySelector(".donnees").style.gridTemplateColumns = `repeat(${1 + nbParcours * 2}, auto)`;
		document.querySelector(".donnees").innerHTML = output;
	}

	/**********************************/
	/* Affichage des critères / voeux */
	/**********************************/
	function display(id, datas, key, editable) {
		let output = "";
		Object.entries(datas[key]).forEach(([idParcours, data]) => {
			output += `<div class=${key}  data-id=${id} data-idParcours=${idParcours} contenteditable=${editable}>${data}</div>`;
		})
		return output;
	}

	/**********************************/
	/* Gestion des événements         */
	/**********************************/
	function processEvents() {
		document.querySelectorAll(".parcours input").forEach(e => e.addEventListener("change", changeNbParcours));
		document.querySelectorAll(".notes select").forEach(e => e.addEventListener("change", changeNotes));
		document.querySelectorAll(".actionTri").forEach(e => e.addEventListener("click", processData));
		document.querySelectorAll(".donnees>.criteres, .donnees>.voeux").forEach(e => e.addEventListener("paste", pasteData));
		document.querySelectorAll("[data-actif]").forEach(e => e.addEventListener("mousedown", event => { event.preventDefault() }));
		document.querySelectorAll("[data-actif]").forEach(e => e.addEventListener("click", changeActif));
		document.querySelectorAll("[contenteditable]").forEach(e => e.addEventListener("keypress", changeListe));
		document.querySelectorAll("[contenteditable]").forEach(e => e.addEventListener("keyup", saveLocal));
		document.querySelectorAll("[contenteditable]").forEach(e => e.addEventListener("keyup", saveToScodoc));
		document.querySelectorAll("[data-idparcours]").forEach(e => e.addEventListener("mouseover", setHighlight));
		document.querySelectorAll("[data-idparcours]").forEach(e => e.addEventListener("mouseleave", resetHighlight));
	}


	/***************************************/
	/* Traitement des entrées utilisateurs */
	/***************************************/
	function changeNbParcours() {
		let idParcours = this.dataset.idparcours;
		let places = this.value;
		parcours[idParcours].places = places;
		saveToScodoc();
	}
	function changeNotes() {
		let idParcours = this.dataset.idparcours;
		let notes = this.value;
		/******* SCODOC - récupérer et modifier les valeurs des notes ******/
	}
	function changeActif() {
		let statut = this.dataset.actif;
		if (statut == "true") {
			statut = false;
		} else {
			statut = true;
		}
		this.dataset.actif = statut;
		etudiants[this.nextElementSibling.dataset.id].actif = statut;
		saveToScodoc();
	}
	function changeListe(event) {
		let type = this.className;

		/* Vérification des touches */
		if (type == "criteres") {
			if (!/[0-9.]/.test(event.key)) {
				event.preventDefault();
			}
		} else {
			if (!/[0-9]/.test(event.key)) {
				event.preventDefault();
			}
		}
		if (event.key == "." && /[.]/.test(this.innerText)) {
			event.preventDefault();
		}
	}

	function saveLocal(event) {
		/* Enregistement des données */
		let type = this.className;
		let parcours = this.dataset.idparcours;
		let id = this.dataset.id;
		etudiants[id][type][parcours] = parseFloat(this.innerText);
	}

	/*function importList(semestre) {
		console.log(parcours);
		/******* SCODOC - enregistrer la répartition des étudiants dans le parcours ******/
	/*document.querySelector(".resultats>h2").innerHTML += `<div>✔️ Groupes importés dans le ${semestre}</div>`;
}*/
	function setHighlight() {
		document.querySelectorAll(`[data-idparcours="${this.dataset.idparcours}"]`).forEach(e => {
			e.dataset.highlight = true;
		})
	}
	function resetHighlight() {
		document.querySelectorAll(`[data-highlight=true]`).forEach(e => {
			e.dataset.highlight = false;
		})
	}

	function saveToScodoc() {
		let data = {
			parcours: parcours,
			etudiants: etudiants
		};
		fetch(
			"/ScoDoc/{{formsemestre.departement.acronym}}/api/formsemestre/" + formsemestre + "/save_groups_auto_assignment",
			{
				method: "POST",
				headers: {
					"Content-Type": "application/json",
				},
				body: JSON.stringify(data)
			}
		);

	}

	async function getFromScodoc() {
		let dataRaw = await fetch("/ScoDoc/{{formsemestre.departement.acronym}}/api/formsemestre/" + formsemestre + "/get_groups_auto_assignment");
		let data = await dataRaw.text();
		if (data == "") {
			return {};
		}
		return JSON.parse(data);
	}
	/***************/
	/* Algo de tri */
	/***************/
	function processData() {

		let typeTri = this.dataset.tri;

		// Vérifications nombre de place
		let placesTotales = 0;
		Object.values(parcours).forEach(p => { placesTotales += p.places })
		if (placesTotales < Object.keys(etudiants).length) {
			document.querySelector(".resultats").innerHTML = "<h2>⚠️ Le nombre de places est inférieur au nombre d'étudiants ⚠️</h2>";
			return;
		}

		// Vérification champs non remplis
		if (typeTri == "notes") {
			var recherche = ".moitemoite input:invalid";
		} else {
			var recherche = ".moitemoite input:invalid, [contenteditable]:empty";
		}
		if (document.querySelector(recherche)) {
			document.querySelector(".resultats").innerHTML = "<h2>⚠️ Veuillez remplir tous les champs ⚠️</h2>";
			return;
		}

		// Remise à 0 des résultats
		Object.values(parcours).map(p => p.etudiants = []);

		// Liste des étudiants à traiter
		let etudiantsID = Object.keys(etudiants);

		/* Pour chaque niveau de voeux */
		for (let numVoeux = 1; numVoeux < nbParcours + 1; numVoeux++) {
			/* Ce qu'il restera à traiter au round suivant */
			let aTraiter = [];
			etudiantsID.forEach(id => {
				if (etudiants[id].actif == false) return;
				if (typeTri == "notes") {
					// Récupère le parcours en fonction des notes et du round
					var groupe = Object.entries(etudiants[id].criteres).sort(([, a], [, b]) => b - a)[numVoeux - 1][0];
				} else {
					// Trouve le parcours qui correspond au numéro du voeux
					var groupe = Object.keys(etudiants[id].voeux).find(key => etudiants[id].voeux[key] == numVoeux);
				}

				if (!groupe) {
					sco_message("Il semblerait que les voeux de " + etudiants[id].nom + " ne soit pas consécutifs en partant de 1.");
				}

				if (parcours[groupe].places == 0) {
					aTraiter.push(id);
				} else if (parcours[groupe].etudiants.length < parcours[groupe].places) {
					// Le groupe n'est pas plein, on y ajoute l'étudiant
					parcours[groupe].etudiants.push(id);
				} else {
					aTraiter.push(groupePlein(groupe, id));
				}
			})
			etudiantsID = aTraiter;
		}

		showResults();
	}

	function groupePlein(groupe, id) {
		// Trie des étudiants dans le parcours par rapport au critère
		parcours[groupe].etudiants = parcours[groupe].etudiants.sort((a, b) => {
			return etudiants[a].criteres[groupe] - etudiants[b].criteres[groupe];
		})

		// Si les deux étudiants ont le même niveau : aléatoire
		let diff = etudiants[parcours[groupe].etudiants[0]].criteres[groupe] - etudiants[id].criteres[groupe];
		if (diff == 0) {
			if (Math.random() < 0.5) {
				diff = 1;
			} else {
				diff = -1;
			}
		}

		// On ajoute dans le parcours le meilleur et on met à traiter l'autre
		if (diff < 0) {
			parcours[groupe].etudiants.push(id);
			return parcours[groupe].etudiants.shift();
		} else {
			return id;
		}
	}

	/***************************/
	/* Affichage des résultats */
	/***************************/
	function showResults() {
		let output = `
			<button class="autre" onclick="exportResults()">Exporter les résultats</button>`;
			/*`
				<h2>
					Importer les résultats dans Scodoc<br>
					<button onclick='importList("S1")'>S1</button>
					<button onclick='importList("S2")'>S2</button>
					<button onclick='importList("S3")'>S3</button>
					<button onclick='importList("S4")'>S4</button>
					<button onclick='importList("S5")'>S5</button>
					<button onclick='importList("S6")'>S6</button>
				</h2>
				`*/;

		Object.values(parcours).forEach(p => {
			output += `<h2>${p.nom} - ${p.etudiants.length}</h2>
					<div class=entete>Etudiants</div>
					<div class=entete style="grid-column: span ${nbParcours}">Notes</div>
					<div class=entete style="grid-column: span ${nbParcours}">Voeux</div>`;
			p.etudiants.forEach(id => {
				output += `<div>${etudiants[id].nom}</div>
					${display(id, etudiants[id], "criteres", false)}
					${display(id, etudiants[id], "voeux", false)}
				`;
			})
		})

		document.querySelector(".resultats").style.gridTemplateColumns = `repeat(${1 + nbParcours * 2}, auto)`;
		document.querySelector(".resultats").innerHTML = output;
	}

	/*****************************/
	/* Copier / coller des datas */
	/*****************************/
	function pasteData(event) {
		event.preventDefault();

		let data = event.clipboardData.getData('Text');
		let lignes = data.split(/\r\n|\r|\n/g);

		currentTarget = this;

		// Calcul du décalage dans la grille
		let offset = -1;
		do {
			offset++;
			currentTarget = currentTarget.previousElementSibling;
		} while (currentTarget.className != "")

		// Collage des données
		currentTarget = this;

		lignes.forEach(ligne => {
			let zone = ligne.split(/\t/g);
			for (let i = 0; i < zone.length; i++) {
				if (!currentTarget) return;
				currentTarget.innerText = zone[i];
				currentTarget = currentTarget.nextElementSibling;
				if (currentTarget?.className == "") {
					for (let j = 0; j <= offset; j++) {
						currentTarget = currentTarget.nextElementSibling;
					}
					return;
				}
			}
		})

		updateStudentsDatas();
	}

	function updateStudentsDatas() {
		document.querySelectorAll(".criteres, .voeux").forEach(e => {
			etudiants[e.dataset.id][e.className][e.dataset.idparcours] = parseFloat(e.innerText);
		})
		saveStudentsData();
	}

	function saveStudentsData() {
		/******* SCODOC - enregistrer les données étudiantes ******/
		console.log(etudiants);
	}

	/***************/
	/* Export xlsx */
	/***************/
	function saveFile(name, workbook) {
		workbook.outputAsync()
			.then(function (blob) {
				var url = window.URL.createObjectURL(blob);
				var a = document.createElement("a");
				document.body.appendChild(a);
				a.href = url;
				a.download = name + ".xlsx";
				a.click();
				window.URL.revokeObjectURL(url);
				document.body.removeChild(a);
			});
	}

	function changeChar(char, nb) {
		return String.fromCharCode(char.charCodeAt(0) + nb);
	}

	async function exportData() {
		XlsxPopulate.fromBlankAsync()
			.then(workbook => {
				const sheet = workbook.sheet(0);
				sheet.name("Données");
				sheet.cell("A1").value("id");
				sheet.cell("B1").value("Actif");
				sheet.cell("C1").value("Nom");

				Object.values(parcours).forEach((p, index) => {
					sheet.cell(changeChar("D", index) + "1").value("Note " + p.nom);
					sheet.cell(changeChar("D", index + nbParcours) + "1").value("Voeu " + p.nom);
					sheet.cell(changeChar("D", index + nbParcours) + "2").value(p.places);
				})

				Object.entries(etudiants).forEach(([id, etudiant], index) => {
					sheet.cell("A" + (index + 3)).value(id.slice(2));
					sheet.cell("B" + (index + 3)).value(etudiant.actif);
					sheet.cell("C" + (index + 3)).value(etudiant.nom);
					let offset = 0;
					Object.values(etudiant.criteres).forEach(critere => {
						sheet.cell(changeChar("D", offset) + (index + 3)).value(critere);
						offset++;
					})
					Object.values(etudiant.voeux).forEach(voeux => {
						sheet.cell(changeChar("D", offset) + (index + 3)).value(voeux);
						offset++;
					})
				})

				sheet.column("A").width(5);
				sheet.column("B").width(5);
				sheet.column("C").width(20);
				sheet.column("D").width(20);
				sheet.column("E").width(20);
				sheet.column("F").width(20);
				sheet.column("G").width(20);
				sheet.column("H").width(20);
				sheet.column("I").width(20);
				sheet.column("J").width(20);
				sheet.column("K").width(20);
				sheet.column("L").width(20);

				saveFile("Donnees groupes - " + formsemestre, workbook);
			});
	}

	async function exportResults() {
		XlsxPopulate.fromBlankAsync()
			.then(workbook => {
				const sheet = workbook.sheet(0);
				sheet.name("Résultats");

				let colonne = 1;
				Object.values(parcours).forEach((dataParcours, index) => {
					let ligne = 1;
					sheet.row(ligne++).cell(colonne).value(dataParcours.nom).style("bold", true);
					sheet.row(ligne).cell(colonne).value("id").style("bold", true);
					sheet.row(ligne++).cell(colonne + 1).value("Nom").style("bold", true).column().width(30);

					dataParcours.etudiants.forEach(etudiant => {
						sheet.row(ligne).cell(colonne).value(etudiant.slice(2));
						sheet.row(ligne++).cell(colonne + 1).value(etudiants[etudiant].nom);
					})
					colonne += 3;
				})

				saveFile("Resultats groupes - " + formsemestre, workbook);
			});
	}

</script>