This repository has been archived on 2025-01-29. You can view files and clone it, but cannot push or open issues or pull requests.

218 lines
7.7 KiB
Python
Raw Permalink Normal View History

import json, requests, os, socket
from datetime import datetime as dt
class InvalidJsonData(Exception):
pass
def readJson(input):
""" Trying to read JSON from given input.
Interpreting input as path to json file first,
then interpreting input as json string.
If both failed, raise InvalidJsonData Exception
"""
#try to read input data as path
try:
with open(input, "r") as f:
return json.load(f)
except:
pass
#try to read input data as json string
try:
return json.loads(input)
except:
pass
#if nothing found, return None
raise InvalidJsonData()
class Exercise:
def __init__(self, data):
""" Constructor for exercise object.
Args:
data: exercise data parsed by readJson
"""
# elements retrieved with .get are optional and
# return None if not found
self.postTime = data["Exercise"]["postTime"]
self.ttl = data["Exercise"].get("TTL")
self.identifier = data["Exercise"]["identifier"]
self.department = data["Exercise"].get("department")
self.comment = data["Exercise"].get("comment")
self.name = data["Exercise"].get("name")
self.description = data["Exercise"].get("description")
self.elements = data["Exercise"]["elements"]
self.environment = data["Exercise"].get("environment")
self.routing = data["Exercise"].get("routing")
self.elementMap = data["Exercise"].get("elementMap")
self.elementProperties = data["Exercise"].get("elementProperties")
tmp = data["Exercise"].get("config")
if tmp is not None:
self.lang = list(tmp.keys())[0]
self.config = tmp[self.lang]
# adding language of Exercise
def createJson(self):
""" Creates a JSON out of the exercise object
Returns:
A string containing the JSON data
"""
#struct with all possible data
data = {
"Exercise" : {
"postTime" : self.postTime,
"ttl" : self.ttl,
"identifier" : self.identifier,
"department" : self.department,
"comment" : self.comment,
"name" : self.name,
"description" : self.description,
"elements" : self.elements,
"environment" : self.environment,
"routing" : self.routing,
"elementMap" : self.elementMap,
"elementProperties" : self.elementProperties,
"config" : self.config
}
}
#removes optional entries if no value is given
for d in data["Exercise"]:
if d is None:
data["Exercise"].pop(d, None)
return json.dumps(data, indent=4)
def getCompilingCommand(self):
""" retrieving compiling command """
compiler = self.config["compiling"]["compiler"]
if compiler is None or compiler == "":
compiler = "gcc" if self.lang == "C" else "g++"
if self.config['compiling']['flags']:
return f"{compiler} {self.config['compiling']['flags']}"
else:
return compiler
class Solution:
""" Solution object
Documentation:
https://campusconnect.tik.uni-stuttgart.de/HeikoBernloehr/FreeLancer/ECS/ecs2/NumLab/solutions
"""
def __init__(self, data, exercise : Exercise = None):
""" Constructor for solution object.
Args:
data (str): solution data parsed by readJson
exercise (Exercise): optional exercise object. If not given, it will
try to retrieve it from exercise url
"""
self.postTime = data["Solution"]["postTime"]
self.id = data["Solution"]["ID"]
self.evaluationService = data["Solution"].get("evaluationService")
self.comment = data["Solution"].get("comment")
self.exerciseUrl = data["Solution"]["exercise"]
self.exerciseModifications = data["Solution"].get("exerciseModifications")
self.exercise = self.getExercise() if exercise == None else exercise
def getExercise(self):
""" Retrieves the given exercise json and creates exercise object
"""
r = requests.get(self.exerciseUrl)
return Exercise(r.json())
def createJson(self):
""" Creates a JSON out of the solution object
Returns:
A string containing the JSON data
"""
#struct with all possible data
data = {
"Solution" : {
"postTime" : self.postTime,
"ID" : self.id,
"evaluationService" : self.evaluationService,
"comment" : self.comment,
"exercise" : self.exerciseUrl,
"exerciseModifications" : self.exerciseModifications
}
}
#removes optional entries if no value is given
for d in data["Solution"]:
if d is None:
data["Solution"].pop(d, None)
return json.dumps(data, indent=4)
class Result:
""" Result object
Documentation:
https://campusconnect.tik.uni-stuttgart.de/HeikoBernloehr/FreeLancer/ECS/ecs2/NumLab/results
"""
def __init__(self, solution : str, comment : str = None,
status : str = "final"):
""" Constructor for result object.
Args:
solution (str): JSON string containing the solution data
comment (str): optional comment
status (str): has to be "final" or "intermediate"
"""
self.time = dt.now()
self.solution = solution
self.id = dt.strftime(self.time, "%Y-%m-%d %H:%M:%S")
self.comment = comment
self.status = status
self.index = None
self.computation = {
"startTime" : dt.strftime(self.time, "%Y-%m-%d %H:%M:%S"),
"CC_versionLong" : "",
"CC_version" : "",
"chain_version" : "",
"technicalInfo" : {
"host" : socket.gethostname(),
"PID" : os.getpid(),
"ID" : "#1"
},
"userInfo" : {"elements": []}
}
self.elements = []
def setId(self, id: int):
self.computation["technicalInfo"]["ID"] = f"#{id}"
def calculateComputationTime(self):
""" Adds finish time and time delta to computation dict
"""
time = dt.now()
self.computation["finishTime"] = dt.strftime(time, "%Y-%m-%d %H:%M:%S")
self.computation["duration"] = time - self.time
def createJson(self):
""" Creates a JSON out of the result object
Returns:
A string containing the JSON data
"""
#struct with all possible data
data = {
"Result" : {
"ID" : self.id,
"comment" : self.comment,
"status" : self.status,
"index" : self.index,
"computation" : self.computation,
"Solution" : self.solution,
"elements" : self.elements
}
}
#removes optional entries if no value is given
if data["Result"].get("comment") is None:
data["Result"].pop("comment", None)
if data["Result"].get("index") is None:
data["Result"].pop("index", None)
return json.dumps(data, indent=4, default=str)