Compare commits

...

5 Commits

9 changed files with 392 additions and 13 deletions

1
.gitignore vendored
View File

@@ -2,3 +2,4 @@ node_modules
vars.js
.idea
*.xlsx
utils/results.json

13
config.js Normal file
View File

@@ -0,0 +1,13 @@
module.exports = {
excelFilename: "DashboardResults.xlsx",
//Selectors for the dashboard page
tableBodySelector: "#QQ_RPT_OIS_TEMP\\$scroll\\$0 tbody",
iframeSelector: 'iframe[title="Hoofdinhoud"]',
//Selectors for the AA-page
uitvouwenSelector: 'input[id="DERIVED_SAA_DPR_SSS_EXPAND_ALL"]',
collapsArrowSelector:'a.PSHYPERLINK.PTCOLLAPSE_ARROW',
excludeFromCollapsingSelector: 'a[title="Sectie samenvouwen AFSTUDEERVEREISTEN BACHELOR GESCHIEDENIS"]',
excludedTitle: 'Sectie samenvouwen AFSTUDEERVEREISTEN BACHELOR GESCHIEDENIS',
}

108
coursesEnrolled.js Normal file
View File

@@ -0,0 +1,108 @@
const puppeteer = require('puppeteer');
const IFRAME_SELECTOR = 'iframe[title="Hoofdinhoud"]';
const wait = require("./wait");
const config = require("./config.js");
//Er zijn een aantal helperfuncties die nog verwijderd moeten worden
//zo is de functie van de contentFrame te verwijderen want staat dubbel in evaluatestartpakket.js
//de iframeselector is eveneens van belang om te verwijderen want staat ook dubbel in evaluatestartpakket.js
async function coursesEnrolled(page) {
/*connection to local host
const browser = await puppeteer.connect({
browserURL: "http://localhost:9222", // Connect to the browser's debugging address
});
// Get all open pages (tabs)
const pages = await browser.pages();
console.log(`Found ${pages.length} open pages on the browser.`);
// Interact with the last tab (or any tab of choice)
let page = pages[pages.length - 1]; // Choose the last opened tab
console.log("Current URL:", page.url()); */
let contentFrame= await getContentFrame(page);
const uitvouwenButton = await contentFrame.$(config.uitvouwenSelector);
if (uitvouwenButton) {
await uitvouwenButton.click();
console.log("uitvouwen button clicked");
await wait(2000);
contentFrame= await getContentFrame(page)
}
//logic to collapse all sections except the one with the excluded title
const collapseArrows = await contentFrame.$$(config.collapsArrowSelector);
const excludedArrow = await contentFrame.$(config.excludeFromCollapsingSelector);
const excludedTbody = await excludedArrow.evaluate(el => el.closest('tbody'));
for (const arrow of collapseArrows) {
const isExcluded = await arrow.evaluate((el, excludedTbody) => {
const title = el.getAttribute('title');
const tbody = el.closest('tbody');
return title === 'Sectie samenvouwen AFSTUDEERVEREISTEN BACHELOR GESCHIEDENIS' || tbody === excludedTbody;
}, excludedTbody);
if (!isExcluded) {
const isStillInDOM = await arrow.evaluate(el => document.body.contains(el));
if (isStillInDOM) {
await arrow.click();
await wait(500); // Adjust the wait time as needed
}
}
}
contentFrame= await getContentFrame(page)
const rowData = await contentFrame.$$eval(
'span',
(spans) => {
const uniqueEntries = new Set();
return spans
.filter((span) => span.innerText.trim().includes('Academiejaar'))
.map((span) => {
const tr = span.closest('tr');
if (!tr) return null;
const tds = tr.querySelectorAll('td');
const getInnerHtml = (element) => {
const aElement = element.querySelector('a');
return aElement ? aElement.innerHTML.trim() : element.innerHTML.trim();
};
const studiegidsNummer = tds[0] ? getInnerHtml(tds[0].querySelector('span')) : '';
const opleidingsOnderdeel = tds[1] ? getInnerHtml(tds[1].querySelector('span')) : '';
const studiepunten = tds[2] ? getInnerHtml(tds[2].querySelector('span')) : '';
if (uniqueEntries.has(studiegidsNummer)) return null;
uniqueEntries.add(studiegidsNummer);
return {
studiegidsNummer,
opleidingsOnderdeel,
studiepunten,
};
})
.filter((entry) => entry);
}
);
const totalStudiepunten = sumStudiepunten(rowData);
return {rowData, totalStudiepunten};
}
function sumStudiepunten(rowData) {
return rowData.reduce((total, row) => {
const studiepunten = parseFloat(row.studiepunten) || 0;
return total + studiepunten;
}, 0);
}
async function getContentFrame(page) {
await page.waitForSelector(IFRAME_SELECTOR);
const iframe = await page.$(IFRAME_SELECTOR);
if (!iframe) {
throw new Error("Could not find iframe on the AA-page");
}
console.log("iframe found on AA-page");
return await iframe.contentFrame();
}
module.exports = coursesEnrolled;

View File

@@ -2,6 +2,7 @@
open chrome in debug modus
start chrome --remote-debugging-port=9222 --user-data-dir="C:\ChromeDebug"
navigeer naar het dashboard en roep de lijst met startpakket studenten op die relevant zijn voor de test
wees er zeker van dat de tab waarin je moet werken de meest rechtse tab is in de tabbladenbalk
start dan het script
*/
const puppeteer = require("puppeteer");
@@ -10,11 +11,15 @@ const fs = require("fs");
const saveResultsToExcel = require("./saveResultsToExcel");
const appendToExcel = require("./appendResultsToExcel");
const wait = require("./wait");
const courseEnrolled = require("./coursesEnrolled");
const parseCourseResults = require('./utils/parseCourseResults');
const config = require("./config.js");
const updateResultsDatabase = require("./utils/updateResultsDatabase");
async function iterateOverDashboardTable() {
/*connection to local host */
const browser = await puppeteer.connect({
browserURL: "http://localhost:9222", // Connect to the browser's debugging address
browserURL: "http://localhost:9222"
});
//array to store results for Excel export
@@ -31,7 +36,7 @@ async function iterateOverDashboardTable() {
// Select the table body by ID
const iframeElement = await page.waitForSelector(
'iframe[title="Hoofdinhoud"]'
config.iframeSelector
);
const iframe = await iframeElement.contentFrame();
@@ -40,11 +45,8 @@ async function iterateOverDashboardTable() {
return;
}
// Select the table body within the iframe
const tableBodySelector = "#QQ_RPT_OIS_TEMP\\$scroll\\$0 tbody";
// Check if the table exists inside the iframe
const tableExists = await iframe.$(tableBodySelector);
const tableExists = await iframe.$(config.tableBodySelector);
if (!tableExists) {
console.log("Table not found inside iframe!");
return;
@@ -53,7 +55,7 @@ async function iterateOverDashboardTable() {
// Get all rows within the table body
const links = await iframe.$$(
`${tableBodySelector} tr span[title="AA-rapport"] a`
`${config.tableBodySelector} tr span[title="AA-rapport"] a`
);
console.log(`Found ${links.length} AA-links to process.`);
@@ -68,12 +70,12 @@ async function iterateOverDashboardTable() {
console.log(`Processing link ${i + 1}`);
const iframeElement = await page.waitForSelector(
'iframe[title="Hoofdinhoud"]'
config.iframeSelector
);
const iframe = await iframeElement.contentFrame();
const links = await iframe.$$(
`${tableBodySelector} tr span[title="AA-rapport"] a`
`${config.tableBodySelector} tr span[title="AA-rapport"] a`
);
// Get the parent row of the current link
const parentRow = await links[i].evaluateHandle((link) =>
@@ -109,6 +111,7 @@ async function iterateOverDashboardTable() {
try {
const evaluationResult = await isStartPakketAvailable(newPage);
const coursesResult = await courseEnrolled(newPage)
//Save results for Excel
result = {
@@ -119,8 +122,11 @@ async function iterateOverDashboardTable() {
IsCollapsedKeuze: evaluationResult.isCollapsed_keuze ? "Yes" : "No",
IsCollapsedMain: evaluationResult.isCollapsed_main ? "Yes" : "No",
ContainsVZP: evaluationResult.containsVZP ? "Yes" : "No",
ContainsVZPKeuze: evaluationResult.containsVZP_keuze ? "Yes" : "No"
ContainsVZPKeuze: evaluationResult.containsVZP_keuze ? "Yes" : "No",
coursesResult: parseCourseResults(coursesResult.rowData),
totalStudiepunten: coursesResult.totalStudiepunten
};
console.log("Courses enrolled: ", coursesResult.rowData);
console.log(`Link ${i + 1} processed successfully.`);
} catch (error) {
console.error(`Error processing link ${i + 1}:`, error.message);
@@ -141,10 +147,12 @@ async function iterateOverDashboardTable() {
}
results.push(result);
appendToExcel(result, filename);
updateResultsDatabase(result)
}
console.log("All links processed.");
saveResultsToExcel(results, "DashboardResults.xlsx");
saveResultsToExcel(results, config.excelFilename);
console.log("Results saved successfully to DashboardResults.xlsx");
}

View File

@@ -1,7 +1,28 @@
const xlsx = require("xlsx");
function saveResultsToExcel(data, filename) {
const workbook = xlsx.utils.book_new(); // Create a new workbook
const worksheet = xlsx.utils.json_to_sheet(data); // Convert data to worksheet
const worksheetData = [];
data.forEach(item => {
const courses = item.coursesResult.split('. ').filter(course => course.trim() !== '');
courses.forEach(course => {
worksheetData.push({
LinkNumber: item.LinkNumber,
StudentName: item.StudentName,
StudentID: item.StudentID,
IsCollapsed: item.IsCollapsed,
IsCollapsedKeuze: item.IsCollapsedKeuze,
IsCollapsedMain: item.IsCollapsedMain,
ContainsVZP: item.ContainsVZP,
ContainsVZPKeuze: item.ContainsVZPKeuze,
Course: course.trim(),
TotalStudiepunten: item.totalStudiepunten
});
});
});
const worksheet = xlsx.utils.json_to_sheet(worksheetData); // Convert data to worksheet
xlsx.utils.book_append_sheet(workbook, worksheet, "Results"); // Add worksheet to workbook
// Write workbook to file

7
todo.md Normal file
View File

@@ -0,0 +1,7 @@
# TODO
## High Priority
- [ ] adviesrapport geeft geen buizen weer voor het huidige aj. Vakken verschijnen dan ook niet in de functie
coursesenrolled. Hoe oplossen? Rapport deliberatie?
- dit is eig geen probleem voor het begin van het aj wanneer nog geen examenperiode heeft
plaatsgevonden.

View File

@@ -0,0 +1,13 @@
const parseCourseResults = (listOfObj) => {
result = listOfObj.map(obj => {
const studiegidsNummer = obj.studiegidsNummer.slice(-10);
return `${studiegidsNummer} ${obj.opleidingsOnderdeel} - ${obj.studiepunten}SP, `;
});
return result.join("\n");
}
module.exports = parseCourseResults;

169
utils/results.json Normal file
View File

@@ -0,0 +1,169 @@
[
{
"LinkNumber": 1,
"StudentName": "William Van Dessel",
"StudentID": "20001044",
"IsCollapsed": "Yes",
"IsCollapsedKeuze": "Yes",
"IsCollapsedMain": "Yes",
"ContainsVZP": "No",
"ContainsVZPKeuze": "No",
"coursesResult": "1010FLWGES Gesch. van de middeleeuwen - 6.00SP, \n1011FLWGES Gesch. van de nieuwe tijd - 6.00SP, \n1014FLWGES Inleiding wereldgeschiedenis - 6.00SP, \n1053FLWGES Hist oef 1 - 6.00SP, ",
"totalStudiepunten": 24
},
{
"LinkNumber": 2,
"StudentName": "Joren Van Roy",
"StudentID": "20141999",
"IsCollapsed": "No",
"IsCollapsedKeuze": "Yes",
"IsCollapsedMain": "No",
"ContainsVZP": "No",
"ContainsVZPKeuze": "No",
"coursesResult": "1011FLWGES Gesch. van de nieuwe tijd - 6.00SP, \n1014FLWGES Inleiding wereldgeschiedenis - 6.00SP, \n1300PSWSOC Inleiding tot de Sociologie - 6.00SP, \n1087FLWGES Central and Eastern Europe - 3.00SP, \n1013FLWGES Eigentijdse geschiedenis - 6.00SP, \n1200PSWPOL Inleiding tot de Politicologie - 6.00SP, \n1104TEWVSG Inl. tot het recht - 6.00SP, \n1300PSWSFP Samenleving, feiten, problemen - 6.00SP, \n1302TEWVSG Levensbesch., mens en markt - 3.00SP, ",
"totalStudiepunten": 48
},
{
"LinkNumber": 4,
"StudentName": "Zeynep Öcbe",
"StudentID": "20193168",
"IsCollapsed": "No",
"IsCollapsedKeuze": "No",
"IsCollapsedMain": "No",
"ContainsVZP": "No",
"ContainsVZPKeuze": "No",
"coursesResult": "1011FLWGES Gesch. van de nieuwe tijd - 6.00SP, \n1014FLWGES Inleiding wereldgeschiedenis - 6.00SP, \n1053FLWGES Hist oef 1 - 6.00SP, \n1067FLWGES Byzantijnse gesch. - 3.00SP, \n1001IOBGJU Global Justice - 3.00SP, ",
"totalStudiepunten": 24
},
{
"LinkNumber": 5,
"StudentName": "Jens Aelbrecht",
"StudentID": "20213047",
"IsCollapsed": "No",
"IsCollapsedKeuze": "Yes",
"IsCollapsedMain": "No",
"ContainsVZP": "No",
"ContainsVZPKeuze": "No",
"coursesResult": "1002FLWGES Inleiding tot de economie - 6.00SP, \n1005FLWGES Oefeningen paleografie - 3.00SP, \n1011FLWGES Gesch. van de nieuwe tijd - 6.00SP, \n1014FLWGES Inleiding wereldgeschiedenis - 6.00SP, \n1053FLWGES Hist oef 1 - 6.00SP, \n1300PSWSOC Sociologie - 6.00SP, \n1054FLWGES Inleiding wijsbegeerte - 6.00SP, \n1067FLWGES Byzantijnse gesch. - 3.00SP, \n1000PSWPUB Publiekrecht - 3.00SP, \n1013FLWGES Eigentijdse geschiedenis - 6.00SP, \n1200PSWPOL Politicologie - 6.00SP, \n1001CPGVKA Levensbeschouwing & wet - 3.00SP, ",
"totalStudiepunten": 60
},
{
"LinkNumber": 6,
"StudentName": "Hadi Dagher",
"StudentID": "20221279",
"IsCollapsed": "No",
"IsCollapsedKeuze": "No",
"IsCollapsedMain": "No",
"ContainsVZP": "No",
"ContainsVZPKeuze": "No",
"coursesResult": "1002FLWGES Inleiding tot de economie - 6.00SP, \n1005FLWGES Oefeningen paleografie - 3.00SP, \n1053FLWGES Hist oef 1 - 6.00SP, \n1011FLWGES Gesch. van de nieuwe tijd - 6.00SP, \n1014FLWGES Inleiding wereldgeschiedenis - 6.00SP, ",
"totalStudiepunten": 27
},
{
"LinkNumber": 7,
"StudentName": "Casper Janssens",
"StudentID": "20221960",
"IsCollapsed": "No",
"IsCollapsedKeuze": "Yes",
"IsCollapsedMain": "No",
"ContainsVZP": "No",
"ContainsVZPKeuze": "No",
"coursesResult": "1002FLWGES Inleiding tot de economie - 6.00SP, \n1003FLWGES Historische methode - 6.00SP, \n1005FLWGES Oefeningen paleografie - 3.00SP, \n1010FLWGES Gesch. van de middeleeuwen - 6.00SP, \n1011FLWGES Gesch. van de nieuwe tijd - 6.00SP, \n1014FLWGES Inleiding wereldgeschiedenis - 6.00SP, \n1053FLWGES Hist oef 1 - 6.00SP, \n1000RECPOL Politicologie - 3.00SP, \n1300PSWSOC Sociologie - 6.00SP, \n1000RECGPR Geschiedenis privaatrecht - 6.00SP, \n1200RECTEN Taalgebruik Engels - 3.00SP, ",
"totalStudiepunten": 57
},
{
"LinkNumber": 8,
"StudentName": "Hanne De Win",
"StudentID": "20223846",
"IsCollapsed": "No",
"IsCollapsedKeuze": "Yes",
"IsCollapsedMain": "No",
"ContainsVZP": "No",
"ContainsVZPKeuze": "No",
"coursesResult": "1002FLWGES Inleiding tot de economie - 6.00SP, \n1003FLWGES Historische methode - 6.00SP, \n1005FLWGES Oefeningen paleografie - 3.00SP, \n1011FLWGES Gesch. van de nieuwe tijd - 6.00SP, \n1014FLWGES Inleiding wereldgeschiedenis - 6.00SP, \n1053FLWGES Hist oef 1 - 6.00SP, \n1102FLWTLT Geschiedenis van de film 1 - 3.00SP, \n1300PSWSOC Sociologie - 6.00SP, \n1082FLWGES Geschiedenis van België - 3.00SP, ",
"totalStudiepunten": 45
},
{
"LinkNumber": 9,
"StudentName": "Axl Legon",
"StudentID": "20223927",
"IsCollapsed": "Yes",
"IsCollapsedKeuze": "Yes",
"IsCollapsedMain": "Yes",
"ContainsVZP": "No",
"ContainsVZPKeuze": "No",
"coursesResult": "1067FLWGES Byzantijnse gesch. - 3.00SP, \n1083FLWGES Gesch. van de Nederlanden - 3.00SP, \n1002FLWGES Inleiding tot de economie - 6.00SP, \n1300PSWSOC Sociologie - 6.00SP, \n1054FLWGES Inleiding wijsbegeerte - 6.00SP, \n1003FLWGES Historische methode - 6.00SP, \n1005FLWGES Oefeningen paleografie - 3.00SP, \n1072FLWGES Inleiding historiografie - 3.00SP, \n1053FLWGES Hist oef 1 - 6.00SP, \n1010FLWGES Gesch. van de middeleeuwen - 6.00SP, \n1011FLWGES Gesch. van de nieuwe tijd - 6.00SP, \n1014FLWGES Inleiding wereldgeschiedenis - 6.00SP, \n1066FLWGES History islamic world - 6.00SP, \n1082FLWGES Geschiedenis van België - 3.00SP, \n1200PSWPOL Politicologie - 6.00SP, \n1002FLWALG Keuzeruimte - 3.00SP, ",
"totalStudiepunten": 78
},
{
"LinkNumber": 11,
"StudentName": "Error",
"StudentID": "Error",
"IsCollapsed": "Error",
"IsCollapsedKeuze": "Error",
"IsCollapsedMain": "Error",
"ContainsVZP": "Error",
"ContainsVZPKeuze": "Error",
"ErrorStr": "Cannot read properties of null (reading 'evaluate')"
},
{
"LinkNumber": 12,
"StudentName": "Tom Grohmann",
"StudentID": "20230664",
"IsCollapsed": "No",
"IsCollapsedKeuze": "Yes",
"IsCollapsedMain": "No",
"ContainsVZP": "No",
"ContainsVZPKeuze": "No",
"coursesResult": "1002FLWGES Inleiding tot de economie - 6.00SP, \n1005FLWGES Oefeningen paleografie - 3.00SP, \n1011FLWGES Gesch. van de nieuwe tijd - 6.00SP, \n1014FLWGES Inleiding wereldgeschiedenis - 6.00SP, \n1053FLWGES Hist oef 1 - 6.00SP, \n1067FLWGES Byzantijnse gesch. - 3.00SP, ",
"totalStudiepunten": 30
},
{
"LinkNumber": 14,
"StudentName": "Lien Arras",
"StudentID": "20231250",
"IsCollapsed": "No",
"IsCollapsedKeuze": "Yes",
"IsCollapsedMain": "No",
"ContainsVZP": "No",
"ContainsVZPKeuze": "No",
"coursesResult": "1002FLWGES Inleiding tot de economie - 6.00SP, \n1005FLWGES Oefeningen paleografie - 3.00SP, \n1011FLWGES Gesch. van de nieuwe tijd - 6.00SP, \n1014FLWGES Inleiding wereldgeschiedenis - 6.00SP, \n1053FLWGES Hist oef 1 - 6.00SP, \n1038FLWGES Inleiding tot het Latijn - 3.00SP, ",
"totalStudiepunten": 30
},
{
"LinkNumber": 15,
"StudentName": "Oliwier Rogozinski",
"StudentID": "20232813",
"IsCollapsed": "Yes",
"IsCollapsedKeuze": "Yes",
"IsCollapsedMain": "Yes",
"ContainsVZP": "No",
"ContainsVZPKeuze": "No",
"coursesResult": "1002FLWGES Inleiding tot de economie - 6.00SP, \n1003FLWGES Historische methode - 6.00SP, \n1005FLWGES Oefeningen paleografie - 3.00SP, \n1010FLWGES Gesch. van de middeleeuwen - 6.00SP, \n1011FLWGES Gesch. van de nieuwe tijd - 6.00SP, \n1014FLWGES Inleiding wereldgeschiedenis - 6.00SP, \n1053FLWGES Hist oef 1 - 6.00SP, \n1066FLWGES History islamic world - 6.00SP, \n1300PSWSOC Sociologie - 6.00SP, \n1054FLWGES Inleiding wijsbegeerte - 6.00SP, \n1083FLWGES Gesch. van de Nederlanden - 3.00SP, ",
"totalStudiepunten": 60
},
{
"LinkNumber": 16,
"StudentName": "Milan Van De Velde",
"StudentID": "20233391",
"IsCollapsed": "No",
"IsCollapsedKeuze": "No",
"IsCollapsedMain": "No",
"ContainsVZP": "No",
"ContainsVZPKeuze": "No",
"coursesResult": "1002FLWGES Inleiding tot de economie - 6.00SP, \n1005FLWGES Oefeningen paleografie - 3.00SP, \n1011FLWGES Gesch. van de nieuwe tijd - 6.00SP, \n1014FLWGES Inleiding wereldgeschiedenis - 6.00SP, \n1053FLWGES Hist oef 1 - 6.00SP, \n1300PSWSOC Sociologie - 6.00SP, ",
"totalStudiepunten": 33
},
{
"LinkNumber": 17,
"StudentName": "Briek Piessens",
"StudentID": "20233905",
"IsCollapsed": "Yes",
"IsCollapsedKeuze": "Yes",
"IsCollapsedMain": "Yes",
"ContainsVZP": "No",
"ContainsVZPKeuze": "No",
"coursesResult": "1002FLWGES Inleiding tot de economie - 6.00SP, \n1003FLWGES Historische methode - 6.00SP, \n1005FLWGES Oefeningen paleografie - 3.00SP, \n1010FLWGES Gesch. van de middeleeuwen - 6.00SP, \n1011FLWGES Gesch. van de nieuwe tijd - 6.00SP, \n1014FLWGES Inleiding wereldgeschiedenis - 6.00SP, \n1053FLWGES Hist oef 1 - 6.00SP, \n1066FLWGES History islamic world - 6.00SP, \n1300PSWSOC Sociologie - 6.00SP, \n1054FLWGES Inleiding wijsbegeerte - 6.00SP, \n1118FLWTLA Taal tussen natuur en cultuur - 3.00SP, \n1104FLWTLN Cultuurgesch.v/d Lage Landen 2 - 3.00SP, \n1101FLWTLN Nederlandse TB1: basisvaardigh - 6.00SP, ",
"totalStudiepunten": 69
}
]

View File

@@ -0,0 +1,39 @@
const fs = require("fs");
const path = require("path");
const resultsFilePath = path.join(__dirname, "results.json");
// Flag to track if the file has been reset
let isFileReset = false;
function updateResultsDatabase(newResult) {
// Check if the file needs to be reset
if (!isFileReset) {
if (fs.existsSync(resultsFilePath)) {
const fileContent = fs.readFileSync(resultsFilePath, "utf-8");
if (fileContent.trim()) {
// Reset the file to an empty array
fs.writeFileSync(resultsFilePath, JSON.stringify([], null, 2));
console.log("Old data removed from results.json.");
}
}
isFileReset = true; // Mark the file as reset
}
// Read existing results or initialize an empty array
let results = [];
if (fs.existsSync(resultsFilePath)) {
const fileContent = fs.readFileSync(resultsFilePath, "utf-8");
if (fileContent.trim()) {
results = JSON.parse(fileContent);
}
}
// Add the new result to the array
results.push(newResult);
// Write the updated results back to the file
fs.writeFileSync(resultsFilePath, JSON.stringify(results, null, 2));
}
module.exports = updateResultsDatabase;