Esempio n. 1
0
class CC_Process(Process):
    def __init__(self, compare_func=strictly_compare, name: str = '', max_time: list = [], max_memery: list = [],
                 inputfiles: list = [], score: int = 100, sub_score: list = [],
                 anses: list = [], input_cc_code: str = '', tmp_cc_path: str = 'main.cpp', tmp_output_dir: str = './',
                 output_cc_file='./main', additional_args: list = [], compare_in_memory: bool = True,
                 load_ans: bool = False,exit_if_error:bool=True,
                 use_cc_file=False, enable_o2: bool = True,clean:bool=False):

        super().__init__()
        self.process = Process()
        self.compare_func = compare_func
        self.name = name
        self.max_time = max_time
        self.max_memory = max_memery
        self.inputfiles = inputfiles
        self.anses = anses
        self.input_cc_code = input_cc_code
        self.output_cc_file = output_cc_file
        self.additional_args = additional_args
        self.compare_in_memory = compare_in_memory
        self.use_cc_file = use_cc_file
        self.enable_o2 = enable_o2
        self.tmp_cc_path = tmp_cc_path
        self.tmp_output_dir = tmp_output_dir
        self.load_ans = load_ans
        self.tmp_output_files = []
        self.report = {'compile': {}, 'details': []}
        self.score = score
        self.sub_score = sub_score
        self._clean=clean
        self.exit_if_error=exit_if_error

    async def create_tasks(self):
        # self.process.add_block_task(await self.compile_cc_task())
        for i in range(len(self.anses)):
            if self.compare_in_memory:
                self.process.add_task_chain(self.run_cc_task(in_file=self.inputfiles[i], maxtime=self.max_time[i],
                                                             max_memory=self.max_memory[i]))
                self.process.add_nonblock_task(await self.compare_output(self.anses[i], ''))
            else:
                _out = self.tmp_output_dir + '/' + str(time.time())
                self.tmp_output_files.append(_out)
                self.process.add_block_task(
                    self.run_cc_task(in_file=self.inputfiles[i], out_file=_out, maxtime=self.max_time[i],
                                     max_memory=self.max_memory[i]))
                self.process.add_nonblock_task(await self.compare_output(self.anses[i], _out))
        for i in self.process.process:
            i[0].exit_if_error=self.exit_if_error

    async def run(self):
        logging.debug('Compiling')
        compile = await self.compile_cc_task()
        await compile.run()
        if compile.err:
            logging.debug('Compile error')
            # logging.debug(compile.report)
            # print(compile.err)
            self.report['compile']['state'] = STATE.CompileError.value
            self.report['compile']['info'] = compile.err_detail
            self.score = 0
            return STATE.CompileError
        self.report['compile']['state'] = STATE.CompileSuccess.value
        self.report['compile']['info'] = ''
        logging.debug('Create tasks')
        await self.create_tasks()
        # self.process.add_block_task(self.run_cc_task('test_example/1.in'))
        logging.debug('Start run process')
        await self.process.run()
        # os.unlink(self.tmp_cc_path)
        logging.debug('Finish run process')
        if self._clean:
            await self.clean()
        return await self.get_report()

    async def compile_cc_task(self):
        if not self.use_cc_file:
            async with aiofiles.open(self.tmp_cc_path, 'w') as f:
                await f.write(self.input_cc_code)
            self.input_cc_code = self.tmp_cc_path
        if self.enable_o2:
            operation = 'g++ -fno-asm -w -lm --static -std=c++11 -O2 {} -o {}'.format(self.input_cc_code,
                                                                                      self.output_cc_file)
        else:
            operation = 'g++ -fno-asm -w -lm --static -std=c++11 {} -o {}'.format(self.input_cc_code,
                                                                                  self.output_cc_file)
        # os.unlink(self.tmp_cc_path)
        return Lrun_task(operation=operation, cputime=5000, realtime=5000, exit_if_error=True)

    def run_cc_task(self, in_file: str, out_file: str = '', maxtime: int = 1000, max_memory: int = 128):
        if not self.compare_in_memory:
            operation = '{} <{} >{}'.format(self.output_cc_file, in_file, out_file)
        else:
            operation = '{} <{}'.format(self.output_cc_file, in_file)
        # operation=self.output_cc_file
        return Lrun_task(operation=operation, cputime=maxtime, realtime=maxtime, memory=max_memory)

    async def compare_output(self, _ans: str, _out):
        info = {}
        if self.load_ans:
            async with aiofiles.open(_ans) as f:
                info['ans'] = await f.read()
        else:
            info['ans'] = _ans
        if self.compare_in_memory:
            info['use_file'] = False
            return Function_task(args=[info], func=self.compare_func)
        else:
            info['use_file'] = True
            return Function_task(args=[info, _out], func=self.compare_func)

    async def clean(self):
        os.unlink(self.output_cc_file)
        if not self.use_cc_file:
            os.unlink(self.input_cc_code)
        if not self.compare_in_memory:
            for i in self.tmp_output_files:
                os.unlink(i)

    async def get_report(self):
        state = STATE.Accept
        # for i in self.report:
        #     print(i)
        max_time = 0
        max_memory = 0
        for i in range(0, len(self.process.process), 2):
            tmp = self.process.process[i][0].report
            # print(self.process.process[i][0].__class__.__name__)
            print(tmp)
            max_time = max(max_time, max(self.process.process[i][0].report['cputime'],
                                         self.process.process[i][0].report['realtime']))
            max_memory = max(max_memory, self.process.process[i][0].report['memory'])
            if self.process.process[i][0].err:
                state = self.process.process[i][0].err
                tmp['state'] = state
                self.score -= self.sub_score[i // 2]
            elif self.process.process[i + 1][0].err:
                state = self.process.process[i + 1][0].err
                tmp['state'] = state
                self.score -= self.sub_score[i // 2]
            else:
                tmp['state'] = STATE.Accept
            self.report['details'].append(tmp)
            if self.process.process[i][0].err != None and self.process.process[i][0].exit_if_error:
                break
            if self.process.process[i+1][0].err != None and self.process.process[i+1][0].exit_if_error:
                break
        self.report['ans'] = {'score': self.score, 'max_time': max_time, 'max_memory': max_memory, 'result': state}
        # print(self.report)
        return state