Compare commits

..

4 Commits

8 changed files with 22 additions and 16 deletions

View File

@@ -4,6 +4,8 @@ Blackboard Gradebook Organiser - main (functional) changes and new features log
## **Notable updates** ## **Notable updates**
2024-04-30 Restructure documentation - separate *Inspect by hash*
2024-03-01 Allow customisation of default settings - most useful default to edit is `IGNORE_DIRS`: the list of names for directories, or files, to ignore when extracting from compressed files 2024-03-01 Allow customisation of default settings - most useful default to edit is `IGNORE_DIRS`: the list of names for directories, or files, to ignore when extracting from compressed files
2023-07-17 Documentation updated and web docs added at [docs.vangef.net/BBGradebookOrganiser](https://docs.vangef.net/BBGradebookOrganiser) 2023-07-17 Documentation updated and web docs added at [docs.vangef.net/BBGradebookOrganiser](https://docs.vangef.net/BBGradebookOrganiser)

View File

@@ -46,7 +46,7 @@ Optionally, you can inspect the submissions for identical files (by generating a
## **Instructions** ## **Instructions**
See the documentation for [Setup](instructions/setup.md) and [Usage](instructions/usage.md) instructions, and more information & details about [***Inspect by hash***](inspect/about.md). See the documentation for [Requirements & Settings](instructions/requirements-settings.md) and [Usage](instructions/usage.md) instructions, and more information & details about [***Inspect by hash***](inspect/about.md).
## **General notes** ## **General notes**

View File

@@ -26,4 +26,4 @@ With **Inspect by hash** you can inspect the submissions for identical files (by
- File names and paths listed in the generated CSV files have hyperlinks to the actual files for a quick inspection of the file contents (or running the files, if executable) - File names and paths listed in the generated CSV files have hyperlinks to the actual files for a quick inspection of the file contents (or running the files, if executable)
*Note:* Further analysis needs to be done manually by inspecting and filtering the generated output, depending on the submission and its files. *Note:* Further analysis needs to be done manually by inspecting and filtering the generated output, depending on the submission and its files.

View File

@@ -0,0 +1,9 @@
# **Inspect by hash** :mag:
## **Requirements**
The ***inspect*** scripts require the `pandas` package - if it's not already installed, run:
```console
python -m pip install pandas
```

View File

@@ -1,13 +1,5 @@
# **Using Inspect by hash** :mag: # **Using Inspect by hash** :mag:
## **Requirements**
Before running the *inspect* scripts for the first time, you also need to install the *pandas* package:
```console
python -m pip install pandas
```
## **Inspect gradebook** ## **Inspect gradebook**
If you haven't already, extract the downloaded from *Blackboard* gradebook in a new directory inside *BB_gradebooks* If you haven't already, extract the downloaded from *Blackboard* gradebook in a new directory inside *BB_gradebooks*

View File

@@ -22,7 +22,7 @@ python -m pip install -r requirements.txt
- `brew install rar` for Mac - `brew install rar` for Mac
## (Optional) **Edit defaults** ## (Optional) **Edit settings**
You can change the default settings by editing *utils/settings.py*. The main setting you might want to edit is `IGNORE_DIRS` - the list of names for directories, or files, to ignore when extracting from compressed files. You can change the default settings by editing *utils/settings.py*. The main setting you might want to edit is `IGNORE_DIRS` - the list of names for directories, or files, to ignore when extracting from compressed files.
@@ -34,4 +34,4 @@ Ignored directories by default:
- `node_modules` (npm) - `node_modules` (npm)
- `vendor` (composer / laravel) - `vendor` (composer / laravel)

View File

@@ -54,7 +54,7 @@ def generate_hashes_gradebook(gradebook_dir_path: str) -> str: # main function
csv_file_name = f'{gradebook_dir_name}_gradebook_file_hashes_{datetime.now().strftime("%Y%m%d-%H%M%S")}.csv' csv_file_name = f'{gradebook_dir_name}_gradebook_file_hashes_{datetime.now().strftime("%Y%m%d-%H%M%S")}.csv'
csv_file_path = os.path.join(CSV_DIR, csv_file_name) csv_file_path = os.path.join(CSV_DIR, csv_file_name)
with open(csv_file_path, 'w', newline='') as csvfile: # open the output CSV file for writing with open(csv_file_path, 'w', newline='', encoding='utf-8') as csvfile: # open the output CSV file for writing
fieldnames = ['Student ID', 'filename', 'sha256 hash'] fieldnames = ['Student ID', 'filename', 'sha256 hash']
writer = csv.DictWriter(csvfile, fieldnames=fieldnames) writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader() writer.writeheader()
@@ -86,7 +86,7 @@ def generate_hashes_submissions(submissions_dir_path: str) -> str: # main funct
csv_file_name = f'{submissions_dir_name}_submissions_file_hashes_{datetime.now().strftime("%Y%m%d-%H%M%S")}.csv' csv_file_name = f'{submissions_dir_name}_submissions_file_hashes_{datetime.now().strftime("%Y%m%d-%H%M%S")}.csv'
csv_file_path = os.path.join(CSV_DIR, csv_file_name) csv_file_path = os.path.join(CSV_DIR, csv_file_name)
with open(csv_file_path, 'w', newline='') as csvfile: # open the output CSV file for writing with open(csv_file_path, 'w', newline='', encoding='utf-8') as csvfile: # open the output CSV file for writing
fieldnames = ['Student ID', 'filepath', 'filename', 'sha256 hash'] fieldnames = ['Student ID', 'filepath', 'filename', 'sha256 hash']
writer = csv.DictWriter(csvfile, fieldnames=fieldnames) writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader() writer.writeheader()

View File

@@ -77,7 +77,10 @@ def organise_file_per_student(src_dir: str, dest_dir: str, file_name: str, stude
with open(comments_filename, 'a') as f: with open(comments_filename, 'a') as f:
f.write(f'\nStudent number: {student_no} - Student name: {name}\nFile: {file_path}\nComment: {comment}\n') f.write(f'\nStudent number: {student_no} - Student name: {name}\nFile: {file_path}\nComment: {comment}\n')
else: else:
file_name = file_name.split('_attempt_')[1].split('_', 1)[1] # rename any remaining files before moving - remove the BB generated info added to the original file name try:
file_name = file_name.split('_attempt_', 1)[1].split('_', 1)[1] # rename any remaining files before moving - remove the BB generated info added to the original file name
except IndexError as e:
print(f'Cannot process file - possible incorrect format of filename')
new_file_path = os.path.join(student_dir, os.path.basename(file_name)) new_file_path = os.path.join(student_dir, os.path.basename(file_name))
shutil.move(file_path, new_file_path) # move the file to student directory shutil.move(file_path, new_file_path) # move the file to student directory
@@ -95,7 +98,7 @@ def organise_gradebook(src_dir: str, dest_dir: str) -> None:
for file_name in os.listdir(src_dir): # iterate through all files in the directory for file_name in os.listdir(src_dir): # iterate through all files in the directory
if BAD_DIR_NAME not in file_name: # ignore dir BAD_DIR_NAME (created after first run if corrupt compressed files found) if BAD_DIR_NAME not in file_name: # ignore dir BAD_DIR_NAME (created after first run if corrupt compressed files found)
student_no = file_name.split('_attempt_')[0].split('_')[-1] # get student number from file name !! pattern might need adjusting if file name format from blackboard changes !! student_no = file_name.split('_attempt_', 1)[0].split('_')[-1] # get student number from file name !! pattern might need adjusting if file name format from blackboard changes !!
students_numbers.append(student_no) students_numbers.append(student_no)
organise_file_per_student(src_dir, dest_dir, file_name, student_no) organise_file_per_student(src_dir, dest_dir, file_name, student_no)