218 lines
7.7 KiB
Python
Executable File
218 lines
7.7 KiB
Python
Executable File
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) |