Send the result of a job back to the backend. Must be called *once and only once* for each job
        :exception JobNotRunningException: is raised when send_job_result is called more than once for a given job_id

async def send_job_result(self, job_id: BackendJobId, result: str, text: str = "", grade: float = None, problems: Dict[str, SPResult] = None,
                              tests: Dict[str, Any] = None, custom: Dict[str, Any] = None, state: str = "", archive: Optional[bytes] = None,
                              stdout: Optional[str] = None, stderr: Optional[str] = None):
        """
        Send the result of a job back to the backend. Must be called *once and only once* for each job
        :exception JobNotRunningException: is raised when send_job_result is called more than once for a given job_id
        """
        if job_id not in self.__running_job:
            raise JobNotRunningException()
        del self.__running_job[job_id]

        if grade is None:
            if result == "success":
                grade = 100.0
            else:
                grade = 0.0
        if problems is None:
            problems = {}
        if custom is None:
            custom = {}
        if tests is None:
            tests = {}

        await ZMQUtils.send(self.__backend_socket, AgentJobDone(job_id, (result, text), round(grade, 2), problems, tests, custom, state, archive, stdout, stderr))