Fix bug with multiple file upload. Fixed bug with printing the same TC number. Updated docs to reflect on submit implementation.

This commit is contained in:
Boyan 2024-04-08 22:28:01 +02:00
parent 3c63a64eac
commit df8429d811
6 changed files with 272 additions and 18 deletions

View File

@ -134,8 +134,21 @@ Downloads all test cases in the exercise group to a directory `path`. Defaults t
``` ```
#### `submit(files)` #### `submit(files)`
Submits the files to the exercise group. (This is not implemented yet) Submits the files to the exercise group. Default arguments are `judge=True`, `wait=True` and `silent=True`. `judge` will judge the submission instantly, and `wait` will wait for the submission to finish. Turning off `silent` will print the submission status dynamically.
```python ```python
assignment.submit(["file1.py", "file2.py"]) suitcase[7].exercises[1].submit("suitcase.py", silent=False)
>>> 1: ✅
>>> 2: ✅
>>> 3: ✅
>>> 4: ✅
>>> 5: ✅
>>> 6: ✅
>>> 7: ✅
>>> 8: ✅
>>> 9: ✅
>>> 10: ✅
``` ```

View File

@ -118,38 +118,57 @@ class ExerciseGroup:
return None return None
return [ return [
ExerciseGroup(f"https://themis.housing.rug.nl{x['href']}", x, session, self) ExerciseGroup(f"https://themis.housing.rug.nl{x['href']}", x, self.session, self)
for x in folders for x in folders
] ]
def __parseTable(self, soup, url): # Account for judge
def __raceCondition(self, soup, url:str, verbose:bool):
self.session.get(url.replace("submission", "judge"))
return self.__waitForResult(url, verbose, [])
def __parseTable(self, soup, url:str, verbose:bool, __printed:list):
cases = soup.find_all('tr', class_='sub-casetop') cases = soup.find_all('tr', class_='sub-casetop')
fail_pass = {} fail_pass = {}
i = 1 i = 1
for case in cases: for case in cases:
name = case.find('td', class_='sub-casename').text
status = case.find('td', class_='status-icon') status = case.find('td', class_='status-icon')
if "pending" in status.get("class"):
return self.__raceCondition(soup,url,verbose)
# queued status-icon # queued status-icon
if "queued" in status.get("class"): if "queued" in status.get("class"):
sleep(1) # <- 🗿 sleep(1) # <- 🗿
return self.__waitForResult(url) return self.__waitForResult(url, verbose, __printed)
if "Passed" in status.text: if "Passed" in status.text:
fail_pass[i] = True fail_pass[int(name)] = True
if int(name) not in __printed:
print(f"{name}: ✅")
elif "Wrong output" in status.text: elif "Wrong output" in status.text:
fail_pass[i] = False fail_pass[int(name)] = False
if int(name) not in __printed:
print(f"{name}: ❌")
elif ("No status" or "error") in status.text: elif ("No status" or "error") in status.text:
fail_pass[i] = None fail_pass[int(name)] = None
if int(name) not in __printed:
print(f"{name}:🐛")
__printed.append(int(name))
i += 1 i += 1
return fail_pass return fail_pass
def __waitForResult(self, url): def __waitForResult(self, url:str, verbose:bool, __printed:list):
# This waits for result and returns a bundled info package # This waits for result and returns a bundled info package
r = self.session.get(url) r = self.session.get(url)
soup = BeautifulSoup(r.text, "lxml") soup = BeautifulSoup(r.text, "lxml")
return self.__parseTable(soup, url) return self.__parseTable(soup, url, verbose, __printed)
# Submit # Submit
def submit(self, files: list, judge=True, wait=True): def submit(self, files: list, judge=True, wait=True, silent=True):
# Find the form with submit and store the action as url # Find the form with submit and store the action as url
# Store then the data-suffixes as file_types - dictionary # Store then the data-suffixes as file_types - dictionary
@ -188,13 +207,9 @@ class ExerciseGroup:
# Close each file # Close each file
i = 0 i = 0
for f in packaged_files: for f in packaged_files:
if i == 1: f[1][1].close()
f[1].close()
i = 0
else:
i += 1
if not wait: if not wait:
return resp.url if "@submissions" in resp.url else None return resp.url if "@submissions" in resp.url else None
return self.__waitForResult(resp.url) return self.__waitForResult(resp.url, not silent, [])

25
src/main.py Normal file
View File

@ -0,0 +1,25 @@
from Themis import Themis
def main():
# Debug
themis = Themis("s5230837","Bobit0Drog@231")
year = themis.getYear(2023, 2024)
# pf = year.getCourse("Programming Fundamentals (for CS)")
# pf = pf.getExerciseGroups()
# print(pf[1].exercises[1].submit("main.c")) # <- this should throw error
# no_folders = year.getCourse("Computer Architecture")
# ca_ass = no_folders.getExerciseGroups()
ai = year.getCourse("Imperative Programming (for AI)")
ai = ai.getExerciseGroups()
print(ai[7].exercises[1].submit("suitcase.py", silent=False))
ads = year.getCourse("Algorithms and Data Structures for CS")
ads = ads.getExerciseGroups()
# print(ads[0].folders)
print(ads[0].folders[5].folders[0].exercises[0].submit(["texteditor.c", "texteditor.h"], silent=False))
# for ass in ca_ass:
# print(ass.exercises)
if __name__ == "__main__":
main()

28
src/suitcase.py Normal file
View File

@ -0,0 +1,28 @@
def suitcase(maxVolume, sizes, values, n):
dp = [[0 for _ in range(maxVolume + 1)] for _ in range(n + 1)]
for i in range(1, n + 1):
for j in range(1, maxVolume + 1):
if sizes[i - 1] <= j:
dp[i][j] = max(values[i - 1] + dp[i - 1][j - sizes[i - 1]], dp[i - 1][j])
else:
dp[i][j] = dp[i - 1][j]
return dp[n][maxVolume]
def main():
n, maxVolume = map(int, input().split())
sizes = []
values = []
for _ in range(n):
item, size, value = input().split()
sizes.append(int(size))
values.append(int(value))
maxSatisfaction = suitcase(maxVolume, sizes, values, n)
print(maxSatisfaction)
if __name__ == "__main__":
main()

159
src/texteditor.c Normal file
View File

@ -0,0 +1,159 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "EditOperation.h"
#include "texteditor.h"
#include "LibStack.h"
TextEditor* createTextEditor(void) {
TextEditor *editor = malloc(sizeof(*editor));
// Don't forget to initialize the data structure(s) here
editor->text = malloc(10 * sizeof(*editor->text));
editor->length = 0;
editor->capacity = 10;
return editor;
}
// Think this is correct
void insertCharacter(TextEditor* editor, int pos, char character) {
// Implement the insert operation
if (editor->length == editor->capacity) {
editor->text = realloc(editor->text, 2 * editor->capacity * sizeof(*editor->text));
editor->capacity *= 2;
}
// Shift all characters to the right
for (int i = editor->length; i > pos; i--) {
editor->text[i] = editor->text[i - 1];
}
editor->text[pos] = character;
editor->length++;
}
// This too
void deleteCharacter(TextEditor* editor, int pos) {
// Implement the delete operation
if (editor->length == 0) {
return;
}
// Shift all characters to the left
for (int i = pos; i < editor->length - 1; i++) {
editor->text[i] = editor->text[i + 1];
}
editor->length--;
}
// The issue lies within the mem allocation of the stacks
void undo(TextEditor* editor, Stack* undoStack, Stack* redoStack) {
// Optional for the bonus exercise
if (isEmptyStack(*undoStack)) {
return;
}
EditOperation operation = pop(undoStack);
if (operation.type == INSERT) {
deleteCharacter(editor, operation.position);
} else {
insertCharacter(editor, operation.position, operation.character);
}
push(operation, redoStack);
}
void redo(TextEditor* editor, Stack* undoStack, Stack* redoStack) {
// Optional for the bonus exercise
if (isEmptyStack(*redoStack)) {
return;
}
EditOperation operation = pop(redoStack);
if (operation.type == INSERT) {
insertCharacter(editor, operation.position, operation.character);
} else {
deleteCharacter(editor, operation.position);
}
push(operation, undoStack);
}
void destroyTextEditor(TextEditor* editor) {
// Free the memory allocated for the data structure(s)
free(editor->text);
free(editor);
}
void printText(TextEditor* editor) {
// Handle empty case
if (editor->length == 0) {
printf("EMPTY\n");
return;
}
// Print the text stored in the editor
for (int i = 0; i < editor->length; i++) {
printf("%c", editor->text[i]);
}
printf("\n");
}
int main(int argc, char *argv[]) {
TextEditor* editor = createTextEditor();
char command;
int pos;
char character;
// Initialize stacks
Stack undoStack;
Stack redoStack;
undoStack = newStack(1);
redoStack = newStack(1);
while(1) {
scanf(" %c", &command);
switch (command) {
// Insert a character at a given position
case 'i':
scanf("%d %c", &pos, &character);
insertCharacter(editor, pos, character);
EditOperation operation = {INSERT, character, pos};
// Stack operations
doubleStackSize(&undoStack);
push(operation, &undoStack);
break;
// Delete a character at a given position
case 'd':
scanf("%d", &pos);
character = editor->text[pos];
deleteCharacter(editor, pos);
EditOperation operation1 = {DELETE, character, pos};
doubleStackSize(&undoStack);
push(operation1, &undoStack);
break;
// Undo the last operation
case 'u':
undo(editor, &undoStack, &redoStack);
break;
// Redo the last operation
case 'r':
redo(editor, &undoStack, &redoStack);
break;
// Print and quit
case 'q':
printText(editor);
destroyTextEditor(editor);
freeStack(undoStack);
freeStack(redoStack);
return 0;
// Unknown command
default:
printf("Unknown command.\n");
break;
}
}
return 0;
}

14
src/texteditor.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef TEXTEDITOR_H
#define TEXTEDITOR_H
#include "LibStack.h"
typedef struct TextEditor {
// Store the data structure in here
char *text;
int length;
int capacity;
} TextEditor;
#endif