diff --git a/README.md b/README.md index e6e2bd4..a026e58 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ Si hay alguna duda sobre cuál es su código de su Plan de Estudio, el Plan Doce
· **Connection**: Este apartado solo contiene los Headers de la petición, solo es necesario para usuarios que tengan algún problema, no debería ser necesario modificar los valores que se encuentran por defecto. -· **Información Básica**: Este apartado contiene información genérica sobre el estudiante, hay que rellenar esos campos con la información deseada. +· **Basic Information**: Este apartado contiene información genérica sobre el estudiante, hay que rellenar esos campos con la información deseada. | Nombre | Descripción | Ejemplos | |:-----------------:|:------------------------------------------------------------------:|:----------------------------------------------------------------:| @@ -66,7 +66,7 @@ Si hay alguna duda sobre cuál es su código de su Plan de Estudio, el Plan Doce | **CodigoEstudio** | Código identificador de la carrera que se está cursando. | CodigoEstudio=3377
CodigoEstudio=3370
CodigoEstudio=3378 | | **Curso** | Curso del que se hacen la mayoría de asignaturas. | Curso=1
Curso=2
Curso=3
Curso=4 | -· **Asignaturas**: Información sobre cada una de las asignaturas que se quiere añadir al horario.
+· **Subjects Information**: Información sobre cada una de las asignaturas que se quiere añadir al horario.
Se pueden añadir las asignaturas mediante dos métodos: #### Método Automático @@ -78,7 +78,7 @@ Se pueden añadir las asignaturas mediante dos métodos: 3. Añadir la ubicación del archivo HTML en el archivo de preferencias. (En este ejemplo se guarda en *ScrapingUPF/res/EspaiAulaFiles/Gestió de Grups i Aules.html*)

⚠ Usuarios Windows: En Windows es recomendable añadir la ruta completa del archivo como por ejemplo *C:/Users/ScrapingUPF/res/EspaiAulaFiles/Grups.html*, importante añadir las barras de separación de directorios como / y no como \. ```ini - [ASIGNATURAS] + [SUBJECTS_INFORMATION] Asignaturas=False GruposAsignaturas=False GruposPracticas=False @@ -98,7 +98,7 @@ Se pueden añadir tantas asignaturas como se quiera siempre que:
Para añadir la asignatura Bases de Datos (24303), del grupo 2 de teorías, 201 de prácticas y 202 de seminarios: ```ini -[ASIGNATURAS] +[SUBJECTS_INFORMATION] Asignaturas=24303 GruposAsignaturas=2 GruposPracticas=201 @@ -109,7 +109,7 @@ EspaiAulaFilePath=False Si se quiere añadir también Inteligencia Artificial (24304) con el grupo 1 de teorías, 101 de prácticas y 102 de seminarios: ```ini -[ASIGNATURAS] +[SUBJECTS_INFORMATION] Asignaturas=24303,24304 GruposAsignaturas=2,1 GruposPracticas=201,101 @@ -122,7 +122,7 @@ EspaiAulaFilePath=False Si queremos añadir las asignaturas de solo el de 10 de Octubre de 2021: ```ini -[FECHAS] +[DATES] Inicio=10/10/2021 Final=10/10/2021 ``` @@ -130,7 +130,7 @@ Final=10/10/2021 Si queremos añadir todo el mes de Octubre: ```ini -[FECHAS] +[DATES] Inicio=01/10/2021 Final=31/10/2021 ``` @@ -149,12 +149,17 @@ Al iniciar el programa se va a abrir una ventana con nuestro buscador que nos va ![](./res/RunningTheApplication.gif) #### Eliminar Asignaturas Añadidas -Si se quieren eliminar de Google Calendar asignaturas que se han añadido mediante el archivo UserPreferences.ini, se debe abrir el Application.py y establecer deleteMode=True. +Si se quieren eliminar de Google Calendar asignaturas que se han añadido mediante el archivo UserPreferences.ini, se debe abrir el Application.py y establecer replaceMode=False y deleteMode=True. De todas formas, el programa reemplaza asignaturas ya añadidas. ```python from Main import RunApplication -if __name__ == "__main__": RunApplication(deleteMode=True, replaceMode=False) +if __name__ == "__main__": + mainLoop = True + applicationIterator = RunApplication(deleteMode=True, replaceMode=False) + while mainLoop: + try: next(applicationIterator) + except StopIteration: mainLoop = False ``` A continuación hay que ejecutar el programa de la misma manera. diff --git a/UserPreferences.ini b/UserPreferences.ini index 47cb33f..c0a4a6b 100644 --- a/UserPreferences.ini +++ b/UserPreferences.ini @@ -1,25 +1,26 @@ [CONNECTION] -Headers = Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36 +headers = Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36 [BASIC_INFORMATION] -PlanEstudio = 634 -IdiomaPais = en.GB -Trimestre = 1 -PlanDocente = 2021 -CodigoCentro = 337 -CodigoEstudio = 3377 -Curso = 3 +planestudio = 634 +idiomapais = en.GB +trimestre = 1 +plandocente = 2021 +codigocentro = 337 +codigoestudio = 3377 +curso = 3 [SUBJECTS_INFORMATION] -Asignaturas = False -GruposAsignaturas = False -GruposPracticas = False -GruposSeminarios = False -EspaiAulaFilepath = ../res/EspaiAulaFiles/Grups.html +asignaturas = False +gruposasignaturas = False +grupospracticas = False +gruposseminarios = False +espaiaulafilepath = ../res/EspaiAulaFiles/Grups.html [DATES] -Inicio = 01/11/2021 -Final = 30/11/2021 +inicio = 01/11/2021 +final = 30/11/2021 [CALENDAR_CUSTOMIZATION] -CalendarID = primary +calendarid = primary + diff --git a/src/Application.py b/src/Application.py index f7f6e6f..2344e70 100644 --- a/src/Application.py +++ b/src/Application.py @@ -1,3 +1,8 @@ from Main import RunApplication -if __name__ == "__main__": RunApplication(deleteMode=False) +if __name__ == "__main__": + mainLoop = True + applicationIterator = RunApplication(deleteMode=False) + while mainLoop: + try: next(applicationIterator) + except StopIteration: mainLoop = False diff --git a/src/Main.py b/src/Main.py index e03d9c4..393b96d 100644 --- a/src/Main.py +++ b/src/Main.py @@ -8,7 +8,7 @@ def addLogInformation(logInformation, toStdOut=True): def extractRND(fromSoup): """ Extracts the RND number from the soup. - Whats the RND number? + --> Whats the RND number? <-- The RND number is a random number generated by the UPF server, you need it download any content from the server, so first of all we go to URL_RND and then to URL_JSON to get the jSON file. @@ -74,6 +74,9 @@ def deleteGeneratedEvents(MyCalendar, subjectsBlocks, calendarID, logMessages=No :param logMessages: File where we're going to save the log messages, if it's None, the output goes to stdout. :return: True if everything went well, False otherwise. """ + loadingStatus = 0 + loadingBarIncreaser = 100/len(subjectsBlocks) + accumulatedLoadingStatus = 0 try: descriptions = list(map(lambda x: x.getDescription(), subjectsBlocks)) events = MyCalendar.getEvents() @@ -94,10 +97,17 @@ def deleteGeneratedEvents(MyCalendar, subjectsBlocks, calendarID, logMessages=No f"that can be caused by some problems with Google Calendar API. " f"{ErrorCode}") return False - else: - addLogInformation(f"Skipped EventID: {eventID} | {eventDescription}") + else: + accumulatedLoadingStatus += loadingBarIncreaser + if accumulatedLoadingStatus >= 1: + loadingStatus += int(accumulatedLoadingStatus) + accumulatedLoadingStatus = accumulatedLoadingStatus - int(accumulatedLoadingStatus) + yield loadingStatus + + else: addLogInformation(f"Skipped EventID: {eventID} | {eventDescription}") addLogInformation("All events have been removed from the calendar.") + yield 100 return True def addGeneratedEvents(MyCalendar, subjectsBlocks, calendarID, subjectsColors, logMessages=None): @@ -110,6 +120,9 @@ def addGeneratedEvents(MyCalendar, subjectsBlocks, calendarID, subjectsColors, l :param logMessages: File where we're going to save the log messages, if it's None, the output goes to stdout. :return: True in case of success, False in case of error. """ + loadingStatus = 0 + loadingBarIncreaser = 100/len(subjectsBlocks) + accumulatedLoadingStatus = 0 for subject in subjectsBlocks: addLogInformation(f"Adding {subject.name} to the calendar.") try: @@ -121,13 +134,17 @@ def addGeneratedEvents(MyCalendar, subjectsBlocks, calendarID, subjectsColors, l f"that can be caused by a wrong CalendarID or a Google Calendar API problem. {ErrorCode}") return False else: + accumulatedLoadingStatus += loadingBarIncreaser + if accumulatedLoadingStatus >= 1: + loadingStatus += int(accumulatedLoadingStatus) + accumulatedLoadingStatus = accumulatedLoadingStatus - int(accumulatedLoadingStatus) addLogInformation(f"{subject.name} added to the calendar.") + yield loadingStatus addLogInformation("All events have been added to the calendar.") + yield 100 return True def RunApplication(deleteMode=False, replaceMode=True): - global loadingStatus - loadingStatus = 0 """ This function is the main function of the application, it's going to read the configuration file, then it's going to generate the events. @@ -137,14 +154,15 @@ def RunApplication(deleteMode=False, replaceMode=True): :param replaceMode: If this is true, the function will replace the events in the Google Calendar. :return: True in case of success, False in case of error. """ - yield loadingStatus + loadingStatus = 0 + yield loadingStatus # 0% # Checking the Python version, in this case we're going to use Python 3.8 or higher, since I'm using the Walrus Operator. if sys.version_info.major < PYTHON_VERSION['Major'] or (sys.version_info.major >= PYTHON_VERSION['Major'] and sys.version_info.minor < PYTHON_VERSION['Minor']): addLogInformation(f"You're using Python {sys.version_info.major}.{sys.version_info.minor}, required version is 3.8 or bigger.") return False - loadingStatus += 3 - yield loadingStatus + loadingStatus += 10 + yield loadingStatus # 10% # Checking if the configuration file exists, if it exists, we're going to read it. if os.path.isfile(CONFIG_FILE): @@ -152,8 +170,8 @@ def RunApplication(deleteMode=False, replaceMode=True): else: addLogInformation(f"UserPreferences.ini not found at {CONFIG_FILE}.") return False - loadingStatus += 12 - yield loadingStatus + loadingStatus += 20 + yield loadingStatus # 30% if isUsingEspaiAulaFilePath(userPreferences): # If the user is using the automatic mode, we're going to read the HTML file with user data. espaiAulaFile = HTML_LocalFile(getEspaiAulaFilePath(userPreferences), DECODE_HTML_FILE) @@ -161,19 +179,19 @@ def RunApplication(deleteMode=False, replaceMode=True): else: # If the user is using the manual mode, we're going to read the user groups and subjects from the user preferences file. fromGroups, fromSubjects, userSubjectsGroups, pGroups, sGroups = extractSubjectsPreferences(userPreferences) loadingStatus += 15 - yield loadingStatus + yield loadingStatus # 45% subjectsColors = dict(zip(fromSubjects, [str(x%GOOGLE_CALENDAR_API_MAX_COLORS+1) for x in range(len(fromSubjects))])) # Generating a dictionary[subjectCode] = assignedColor loadingStatus += 5 - yield loadingStatus + yield loadingStatus # 50% # Extracting the time information. basicInformation, timeRange = extractRequestInformation(userPreferences) DATA = generateData(fromSubjects, fromGroups, basicInformation) fromDate = int(time.mktime(datetime.datetime.strptime(timeRange[0], "%d/%m/%Y").timetuple())) toDate = int(time.mktime(datetime.datetime.strptime(timeRange[1], "%d/%m/%Y").timetuple())) - loadingStatus += 25 - yield loadingStatus + loadingStatus += 15 + yield loadingStatus # 65% """ At this point, we have all the user data and we checked if it's correct. @@ -190,25 +208,46 @@ def RunApplication(deleteMode=False, replaceMode=True): else: addLogInformation("Something went wrong generating blocks, closing program.") return False - loadingStatus += 15 - yield loadingStatus + loadingStatus += 30 + yield loadingStatus # 95% MyCalendar = Calendar() calendarID = getCalendarID(userPreferences) loadingStatus += 5 - yield loadingStatus + yield loadingStatus # 100% # Now, with all the information downloaded, we're going to work with Google Calendar API. if replaceMode: # In this case, we're deleting all the events in the calendar and then adding the new ones. - deleteGeneratedEvents(MyCalendar, subjectsBlocks, calendarID) - addGeneratedEvents(MyCalendar, subjectsBlocks, calendarID, subjectsColors) + mainLoop = True + functionIterator = deleteGeneratedEvents(MyCalendar, subjectsBlocks, calendarID) + while mainLoop: + try: loadingStatus = next(functionIterator) + except StopIteration: mainLoop = False + yield loadingStatus + + mainLoop = True + functionIterator = addGeneratedEvents(MyCalendar, subjectsBlocks, calendarID, subjectsColors) + while mainLoop: + try: loadingStatus = next(functionIterator) + except StopIteration: mainLoop = False + yield loadingStatus + else: if deleteMode: # Just deleting events. - deleteGeneratedEvents(MyCalendar, subjectsBlocks, calendarID) + mainLoop = True + functionIterator = deleteGeneratedEvents(MyCalendar, subjectsBlocks, calendarID) + while mainLoop: + try: loadingStatus = next(functionIterator) + except StopIteration: mainLoop = False + yield loadingStatus else: # Just adding events. - addGeneratedEvents(MyCalendar, subjectsBlocks, calendarID, subjectsColors) + mainLoop = True + functionIterator = addGeneratedEvents(MyCalendar, subjectsBlocks, calendarID, subjectsColors) + while mainLoop: + try: loadingStatus = next(functionIterator) + except StopIteration: mainLoop = False + yield loadingStatus addLogInformation("Everything has been done successfully.") - loadingStatus += 20 - yield loadingStatus - return True \ No newline at end of file + yield 100 # 100% + return True diff --git a/src/MainWindow.py b/src/MainWindow.py index 9c50023..9708fc8 100644 --- a/src/MainWindow.py +++ b/src/MainWindow.py @@ -375,9 +375,9 @@ def clickRemoveSubjectsButton(self): # Remove subjects from Google Calendar fromDate, toDate = self.startDateEdit.text(), self.endDateEdit.text() insertTimeRange(CONFIG_FILE, fromDate, toDate) mainLoop = True - applicationIterator = RunApplication(deleteMode=True) + applicationIterator = RunApplication(deleteMode=True, replaceMode=False) while mainLoop: - try: self.updateMainLoadingBar(next(applicationIterator)) + try: self.updateMainLoadingBar(round(next(applicationIterator))) except StopIteration: mainLoop = False def clickAddSubjectsButton(self): # Add subjects to Google Calendar @@ -386,7 +386,7 @@ def clickAddSubjectsButton(self): # Add subjects to Google Calendar mainLoop = True applicationIterator = RunApplication() while mainLoop: - try: self.updateMainLoadingBar(next(applicationIterator)) + try: self.updateMainLoadingBar(round(next(applicationIterator))) except StopIteration: mainLoop = False def clickVerificationButton(self):