# Generator CSV

Aby móc uruchomić aplikację w wersji developerskiej należy pobrać Pythona (wersja zalecana: 3.8.5) oraz wymagane biblioteki (wymienione w sekcji 'generator.pyw - Import bibliotek')

Biblioteki główne
W tej sekcji importowane są wszystkie biblioteki niezwiązane z interfejsem graficznych

- sys (SS) - używana tylko do zamykania programu
- os (OS) - odpowiedzialna za polecenia w terminalu
- time (TM) - używana do pobierania aktualnej daty i czasu
- codecs (CD) - odpowiedzialna za otwieranie i czytanie plików w odpowiednim kodowaniu
- pathlib (PT) - używana tylko do pozyskania ścieżki katalogu APPDATA
- shutil (SU) - odpowiedzialna za operacje na plikach i folderach

Biblioteki interfejsu graficznego
W tej sekcji importowane są wszystkie biblioteki związane z interfejsem graficznym

- tkinter (TK) - główne środowisko budowy interfejsu graficznego

- ttk (TKttk) - biblioteka odpowiedzialna za kontrolki i ich wygląd
- messagebox (TKmsb) - biblioteka odpowiedzialna za wyświetlanie komunikatów dialogowych
- filedialog (TKfld) - biblioteka odpowiedzialna za wyświetlanie okien wyboru plików

- PIL (PL), (PLitk), (PLimg) - biblioteka odpowiedzialna za wyświetlanie obrazów

Informacje o programie
`programName` - Zmienna definująca nazwę programu
`programVersion` - Zmienna definiująca główną wersję programu
`programVersionStage` - Zmienna definiująca etap rozwoju programu. Wersja stabilna definiowana jest przez pusty string
`programVersionBuild` - Zmienna definiująca numer buildu programu. Zapisany jest on w formacie '[ostatnie dwie cyfry roku][numer dnia w roku]'
`programCustomer` - Zmienna definiująca nazwę organizacji zlecającej stworzenie programu
`programAuthors` - Lista zawierająca nazwy osób rozwijających program.
`programToW` - Lista zawierająca informacje na temat czasu rozwoju programu. Format: ['miesiąc rozpoczęcia prac', 'rok rozpoczęcia prac', 'aktualny dla rozwoju danej wersji miesiąc', 'aktualny dla rozwoju danej wersji rok']
Dozwolone kodowanie plików
`allowedCoding` - Lista zawierająca wspierane kodowania plików. Są one wyświetlane w rozwijanych listach wyboru kodowania pliku.
Dozwolone znaki
`allowedCharactersInSeparator` - Lista zawierająca znaki które można wpisać w pola dotyczące separatorów osób, linii i danych
Katalog APPDATA
`appdataPath` - zmienna definiująca ścieżkę do folderu %appdata%

Lista komunikatów
Słownik `MSGlist` zawiera listę komunikatów. Format: '[kod dialogowy]' : '[komunikat]'. Kod dialogowy składa się z [jednoznakowego znacznika rodzaju okna dialogowego][czterocyfrowego numeru komunikatu]
Rodzaje okien dialogowych:

- E - komunikaty błędów
- I - komunikaty informacyjne
- W - komunikaty ostrzegające
- A - komunikaty zapytania

Funkcja odpowiedzialna za wywoływanie komunikatów dialogowych
Wywoływanie funkcji: `MSG(`[kod dialogowy]`,`[`True` - Zakończ działanie programu po zamknięciu okna dialogowego/`False` - Kontynuuj działanie programu po zamknięciu okna dialogowego]`,`[dodatkowe informacje wyświetlane w komunikacie - opcjonalnie]`)`
`try:
optionalInfo[0]
except:
optionalInfo = ['']
` Sprawdza czy zostały wpisane 'dodatkowe informacje wyświetlane w komunikacie' i jeżeli nie, definiuje listę, w której znajduje się pusty string (ma to na celu uniknięcia błędu podczas próby wywołania dodatkowych informacji przez dalszą część funkcji)
`if code[0] == 'E/I/W':
TKmsb.showerror/showinfo/showwarning('`[tytuł komunikatu]`', '%s\n%s' % (MSGlist[code], optionalInfo[0]))
` Wywoływanie danego rodzaju komunikatu na podstawie jednoznakowego znacznika rodzaju okna dialogowego.
`if terminate:
SS.exit(0)
` Zakończenie działania programu po zamknięciu okna dialogowego, jeżeli została ustawiona opdowiednia opcja.
`elif code[0] == 'A':
if TKmsb.askokcancel('Pytanie', '%s\n%s' % (MSGlist[code], optionalInfo[0])):
return True
else:
return False
` Funkcja zwraca wartość boolean w przypadku wywołania komunikatu zapytania

Klasa `checkAppdata` odpowiedzialna jest za sprawdzenie poprawności i, w razie potrzeby, doprowadzenie go do stanu poprawności.
Główna funkcja programu
1. Czy w folderze %appdata% istnieje folder programu (Generator CSV)?
Jeżeli nie istnieje, uruchamiana jest funckja `__buildAppdata` (odpowiedzialna za zbudowanie całości katalogu programu).
2. Czy w folderze programu istnieje plik 'version' (przechowuje on numer buildu programu, w którym został zbudowany katalog programu)?
Jeżeli nie istnieje, uruchamiane jest okno dialogowe zapytania z pytaniem czy pozwolić na zresetowanie katalogu programu i kontynuować ładowanie programu
3. Czy numer buildu programu w pliku 'version' jest zgodny z numerem buildu zawartym w zmiennej `VAR.programVersionBuild`
Jeżeli nie, uruchamiane jest okno dialogowe zapytania z pytaniem czy pozwolić na zresetowanie katalogu programu i kontynuować ładowanie programu
Jeżeli tak, sprawdzane są poszczególne pliki i foldery które powinny być zawarte w folderze, i jeżeli któryś plik/folder nie znajduje się w folderze, wywołuje się funkcje mające na celu przywrócenie/utworzenie tych plików/folderów (odpowiednio: `__restoreCFG` dla plików konfiguracyjnych, `__createFormatPresetsDir` dla folderu przechowującego format presety)
Budowanie katalogu programu (`__buildAppdata`)
Funkcja ta, jest odpowiedzialna za zbudowanie całości katalogu programu w folderze %appdata%.
1. Tworzenie katalogu 'Generator CSV'
2. Tworzenie pliku 'version' i zapisanie w nim numeru buildu.
3. Inicjacja funkcji `__restoreCFG` (w celu skopiowania pliku 'config.cfg' z głównego katalogu programu do katalogu 'Generator CSV' w folderze %appdata%).
4. Inicjacja funkcji `__restoreCFG` (w celu skopiowania pliku 'style.cfg' z głównego katalogu programu do katalogu 'Generator CSV' w folderze %appdata%).
5. Inicjacja funkcji `__createFormatPresetsDir` (w celu stworzenia folderu 'format-presets' przechowującego format presety)
Resetowanie katalogu programu (`__resetAppdata`)
Funkcja ta, jest odpowiedzialna za przywrócenie katalogu programu w folderze %appdata% do stanu podstawowego oraz stworzenie kopii zapasowej starego katalogu.
1. W przypadku gdy w katalogu istnieje jeszcze starsza kopia zapasowa folderu, kopia ta jest usuwana.
2. Nazwa katalogu programu jest zmieniana na taką z dopiskiem '_old'.
3. Inicjacja funkcji `__buildAppdata` w celu zbudowania nowego katalogu programu
4. Skopiowanie katalogu 'Generator CSV_old' do nowego katalogu 'Generator CSV'
Przywracanie plików konfiguracyjnych (`__restoreCFG`)
Funkcja ta, jest odpowiedzialna za skopiowanie pliku konfiguracyjnego (.cfg) o danej nazwie z głównego katalogu programu do katalogu programu w folderze %appdata%
Tworzenie katalogu przechowującego format presety (`__createFormatPresetsDir`)
Funkcja ta, jest odpowiedzialna za utworzenie folderu 'format-presets', przechowującego format presety, w katalogu programu w folderze %appdata%

Klasa `CFG` odpowiedzialna jest za zarządzanie plikiem konfiguracyjnym 'config.cfg'
Odczytywanie pojedyńczej zmiennej z pliku (`R`)
Funkcja ta, jest odpowiedzialna za odczytanie zawartości danego recordu i sprawdzenie jego poprawności
1. Inicjacja funkcji `__checkIfFileExist` w celu sprawdzenia czy plik 'config.cfg' istnieje
2. Zczytanie i zapisanie wszystkich danych z pliku 'config.cfg' do słownika `content` w formacie: 'nazwa zmiennej' : ['zmienna', 'typ zmiennej']
3. Inicjacja funckji `__checkIfRecordExist` w celu sprawdzenia czy w słowniku `content` znajduje się żądany record
4. Inicjacja, odpowiedniej dla typu zmiennej, funkcji mającej na celu sprawdzenie jej poprawności i jej przetworzenie
5. Funkcja zwraca wartość zmiennej.
Zapisywanie zmian w pliku (`W`)
Funkcja ta jest odpowiedzialna za sprawdzenie, przetworzenie i zapisanie zmian w pliku konfiguracyjnych.
1. Inicjacja funkcji `__checkIfFileExist` w celu sprawdzenia czy plik 'config.cfg' istnieje
2. Zczytanie i zapisanie wszystkich danych z pliku 'config.cfg' do słownika `content` w formacie: 'nazwa zmiennej' : ['zmienna', 'typ zmiennej']
3. Inicjacja, odpowiedniej dla typu zmiennej, funkcji mającej na celu sprawdzenie jej poprawności i jej przetworzenie, dla każdego recordu ze słownika `changes`
4. Nadpisanie zmiennej ze słownika content, wartością `var`.
5. Zapisanie zawartości słownika `content` w pliku 'config.cfg'
6. Funkcja zwraca `True` jeżeli operacja została wykonana pomyślnie lub `False` jeżeli wystąpił błąd
Funkcje sprawdzające istnienie
`__checkIfFileExist` - funkcja sprawdza czy plik istnieje i możliwe jest jego nadpisanie (w przypadku zapisu)
`__checkIfRecordExist` - funkcja sprawdza czy `record` istnieje w słowniku `content`
Funkcje sprawdzające poprawność recordu
Funkcje te odpowiadają za sprawdzenie poprawności zmiennej i w razie potrzeby przetwarzają ją na pożądaną formę.

Klasa `GUI` odpowiedzialna jest za zarządzanie plikiem konfiguracyjnym 'style.cfg'
Odczytywanie pojedyńczej zmiennej z pliku (`R`)
Funkcja ta, jest odpowiedzialna za odczytanie zawartości danego recordu i sprawdzenie jego poprawności
1. Inicjacja funkcji `__checkIfFileExist` w celu sprawdzenia czy plik 'style.cfg' istnieje
2. Zczytanie i zapisanie wszystkich danych z pliku 'style.cfg' do słownika `content` w formacie: 'nazwa zmiennej' : ['zmienna', 'typ zmiennej']
3. Inicjacja funkcji `__checkIfRecordExist` w celu sprawdzenia czy w słowniku `content` znajduje się żądany record
4. Inicjacja, odpowiedniej dla typu zmiennej, funkcji mającej na celu sprawdzenie jej poprawności i jej przetworzenie
Funkcja zwraca wartość zmiennej.
Funkcje sprawdzające istnienie
`__checkIfFileExist` - funkcja sprawdza czy plik istnieje
`__checkIfRecordExist` - funkcja sprawdza czy `record` istnieje w słowniku `content`
Funkcje sprawdzające poprawność recordu
Funkcje te odpowiadają za sprawdzenie poprawności zmiennej i w razie potrzeby przetwarzają ją na pożądaną formę.

Klasa `FMT` odpowiedzialna jest za zarządzanie plikami formatu (.fmt)
Odczytywanie pojedyńczej zmiennej z pliku (`R`)
Funkcja ta, jest odpowiedzialna za odczytanie zawartości danego recordu i sprawdzenie jego poprawności
1. Inicjacja funkcji `__checkIfFolderExist` w celu sprawdzenia czy folder 'format-presets' istnieje
2. Sprawdzenie czy podany plik formatu (`preset`) znajduje się w folderze 'format-presets' (funkcja `getList` zwraca listę plików formatu w folderze 'format-presets')
Jeżeli nie, wartość zmiennej jest wybierana ze słownika `content` (zawierającego podstawowe wartości zmiennych)
Jeżeli tak: 3. Zczytanie i zapisanie wszystkich danych z wybranego pliku formatu do słownika `content` w formacie: 'nazwa zmiennej' : ['zmienna', 'typ zmiennej']
4. Inicjacja funkcji `__checkIfRecordExist` w celu sprawdzenia czy w słowniku `content` znajduje się żądany record
5. Inicjacja, odpowiedniej dla typu zmiennej, funkcji mającej na celu sprawdzenie jej poprawności i jej przetworzenie
Funkcja zwraca wartość zmiennej.
Zapisywanie zmian w pliku (`W`)
Funkcja ta jest odpowiedzialna za sprawdzenie, przetworzenie i zapisanie zmian w pliku konfiguracyjnych.
1. Inicjacja funkcji `__checkIfFolderExist` w celu sprawdzenia czy folder 'format-presets' istnieje
2. Sprawdzenie czy podany plik formatu (`preset`) znajduje się w folderze 'format-presets' (funkcja `getList` zwraca listę plików formatu w folderze 'format-presets')
Jeżeli nie, tworzony jest słownik `content` z zawartością podstawową Jeżeli tak: Zczytanie i zapisanie wszystkich danych z wybranego pliku formatu do słownika `content` w formacie: 'nazwa zmiennej' : ['zmienna', 'typ zmiennej']
3. Inicjacja, odpowiedniej dla typu zmiennej, funkcji mającej na celu sprawdzenie jej poprawności i jej przetworzenie, dla każdego recordu ze słownika `changes`
4. Nadpisanie zmiennej ze słownika content, wartością `var`.
5. Zapisanie zawartości słownika `content` w pliku 'config.cfg'
6. Funkcja zwraca `True` jeżeli operacja została wykonana pomyślnie lub `False` jeżeli wystąpił błąd
Funkcja zwracająca listę presetów (`getList`)
Funkcja ta odpowiedzialna jest za stworzenie listy plików .fmt w folderze 'format-presets' oraz za jej zwrócenie.
Funkcje sprawdzające istnienie
`__checkIfFolderExist` - funkcja sprawdza czy folder 'format-presets' istnieje (inicjuje `checkAppdata`)
`__checkIfRecordExist` - funkcja sprawdza czy `record` istnieje w słowniku `content`
Funkcje sprawdzające poprawność recordu
Funkcje te odpowiadają za sprawdzenie poprawności zmiennej i w razie potrzeby przetwarzają ją na pożądaną formę.

Klasa `dataProcess` odpowiedzialna za przetwarzanie plików wejściowych i generowanie plików wyjściowych
Główna funkcja klasy (`start`)
Funkcja ta odpowiedzialna za zainicjowanie kolejnych funkcji w odpowiedniej kolejności oraz zwrócenie informacji o błędach lub pomyślnym wykonaniu polecenia
1. Inicjacja funkcji `__checkIfAtLeastOneInputFileIsFilled` w celu sprawdzenia czy przynajmniej jedno pole plików wejściowych zostało wypełnione
2. Inicjacja funkcji `__checkIfInputFilesIsReadable` w celu sprawdzenia czy pliki wejściowe, do których ścieżki zostały podane, są możliwe do odczytania
3. Inicjacja funkcji `__checkIfInputFilesFormatPresetsExist` w celu sprawdzenia czy format presety, które zostały wybrane, istnieją
4. Inicjacja funkcji `__getData` w celu zebrania danych z plików wejściowych
5. Dla każdego zbioru danych - `for x in data` (dla każdej osoby), inicjacja funkcji `__checkLogin`, `__checkFname`, `__checkLname`, oraz dla uczniów `__checkSchool`, `__checkClass`, w celu sprawdzenia poprawności danych
6. Inicjacja funkcji `__processData` w celu przetworzenia danych w linie gotowe do zapisania w plikach wyjściowych
7. Inicjacja funkcji `__checkIfCreatingOutputFilesIsPossible` w celu sprawdzenia czy możliwe jest utworzenie plików wyjściowych
8. Inicjacja funkcji `__saveData` w celu zapisania danych w plikach wyjściowych
Funkcja zwraca listę zawierającą zmienne boolean potwierdzające w którym momencie zakończyło się wykonywanie funkcji (z powodu błędu lub pomyślnego ukończenia operacji)
Funkcje sprawdzające istnienie
`__checkIfAtLeastOneInputFileIsFilled` - sprawdza czy przynajmniej jedno pole plików wejściowych zostało wypełnione oraz zwraca dane z wypełnionych pól
`__checkIfInputFilesIsReadable` - sprawdza czy pliki wejściowe są możliwe do odczytania
`__checkIfInputFilesFormatPresetsExist` - sprawdza czy wybrane format presety istnieją
`__checkIfCreatingOutputFilesIsPossible` - sprawdza czy utworzenie plików wyjściowych jest możliwe
Funkcje sprawdzające poprawność
Funkcje te sprawdzają poprawność określonych typów danych.
Wyodrębnienie danych z plików (`__getData`)
Funkcja odpowiedzialna jest za wyodrębnienie danych z pliku (`path`) na podstawie określonego format presetu (`format`) Dla każdego zbioru ścieżek plików wejściowych i format presetów (`for x in input`):
1. Pobranie danych z pliku formatu (za pomocą funkcji `FMT.R`)
2. Pobranie zawartości z pliku wyjściowego i podzielenie ich na zbiory danych pojedyńczych osób (`.split(personseparator)`)
Dla każdego zbioru danych pojedyńczych osób (`for x in file`):
3. Dzielenie zbioru danych na linie (`x.split(linesSeparator)`)
4. Dla każdej linii: dzielenie danych na pojedyńcze segmenty separatorami z listy `dataSeparators`
5. Wyodrębnienie wymaganych danych ze zbioru
6. Dodanie danych pojedyńczej osoby do listy `data`
Przetworzenie danych (`__processData`)
Funkcja odpowiedzialna jest za przetworzenie danych w linie gotowe do zapisania w plikach wyjściowych
Funkcja zwraca listę `[mailData, officeData]`
Zapisanie danych (`__saveData`)
Funkcja odpowiedzialna jest za zapisanie danych w plikach wyjściowych dla poczty i dla office

Klasa `GUI` odpowiada za interfejs programu
1. Główna funkcja programu
- Stworzenie okna
- Inicjacja styli kontrolek
- Kontrolki
Akcje przycisków
Funkcje inicjowane przez naciśnięcie przycisków