├── .gitignore ├── README.md ├── aojtools ├── __init__.py ├── generated.py ├── libxmlload.py ├── parse.py ├── settings.py └── submit.py ├── scripts ├── aojcategories ├── aojprepare ├── aojrun ├── aojsolvedlist └── aojsubmit ├── setup.py └── util └── generator.js /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # aojtools 2 | 3 | ![aojtools](https://img.shields.io/pypi/v/aojtools.svg) 4 | ![aojtools](https://img.shields.io/badge/wheel-yes-brightgreen.svg) 5 | 6 | ## what's this? 7 | 8 | aojtoolsはAOJ(Aizu Online Judge http://judge.u-aizu.ac.jp/onlinejudge/ )のためのツールセットです。以下を含みます。 9 | 10 | - APIへの透過的なアクセスライブラリ 11 | - サーバへのsubmit機能ライブラリ 12 | - コマンドラインスクリプト 13 | 14 | aojtools is a library and toolset for aoj, aizu online judge system (http://judge.u-aizu.ac.jp/onlinejudge/ ) 15 | including 16 | 17 | - library for accessing API transparently 18 | - library for submitting solution to server 19 | - some CLI script 20 | 21 | ## requirements 22 | 23 | - python 2.x (python 2.6 or higher) 24 | 25 | ## install 26 | ```bash 27 | pip install aojtools 28 | ``` 29 | 30 | -------------------------------------------------------------------------------- /aojtools/__init__.py: -------------------------------------------------------------------------------- 1 | import generated as api 2 | import submit 3 | -------------------------------------------------------------------------------- /aojtools/generated.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/python2.6 2 | # coding: utf-8 3 | 4 | import time 5 | import parse 6 | import settings 7 | 8 | 9 | def time2date(s): 10 | return time.gmtime(int(s) / 1000.) 11 | def date2str(d): 12 | return time.strftime('%Y/%m/%d %H:%M:%S', d) 13 | def to_list(l): 14 | return isinstance(l, list) and l or [l] 15 | def UserSearchAPI(id, **kwargs): 16 | # type check 17 | if type(id) not in [str, unicode]: 18 | raise Exception('parameter \'id\' must be string') 19 | # initialize url, fill if necessary 20 | url = 'http://judge.u-aizu.ac.jp/onlinejudge/webservice/user' 21 | # set parameter 22 | prm = kwargs.copy() 23 | prm['id'] = id 24 | # call api 25 | rsp = parse.fromweb(url, prm) 26 | # format 27 | rsp.id = str(rsp.id) 28 | rsp.name = str(rsp.name) 29 | rsp.affiliation = str(rsp.affiliation) 30 | rsp.registerdate = time2date(rsp.registerdate) 31 | rsp.lastsubmitdate = time2date(rsp.lastsubmitdate) 32 | s = rsp.status 33 | s.submission = int(s.submission) 34 | s.solved = int(s.solved) 35 | s.accepted = int(s.accepted) 36 | s.wronganswer = int(s.wronganswer) 37 | s.timelimit = int(s.timelimit) 38 | s.memorylimit = int(s.memorylimit) 39 | s.outputlimit = int(s.outputlimit) 40 | s.runtimeerror = int(s.runtimeerror) 41 | s.compileerror = int(s.compileerror) 42 | rsp.solved_list.problem = to_list(rsp.solved_list.problem) 43 | for p in rsp.solved_list.problem: 44 | p.id = str(p.id) 45 | p.submissiondate = time2date(p.submissiondate) 46 | p.language = str(p.language) 47 | p.cputime = int(p.cputime) 48 | p.memory = int(p.memory) 49 | p.code_size = int(p.code_size) 50 | return rsp 51 | 52 | def ProblemSearchAPI(id, **kwargs): 53 | # type check 54 | #if type(id) not in [str, unicode]: 55 | # raise Exception('parameter \'id\' must be string') 56 | if type(id) not in [str, unicode]: 57 | id = '%04d'% id 58 | if 'status' in kwargs and type(kwargs['status']) not in [str, unicode]: 59 | raise Exception('parameter \'status\' must be string') 60 | # initialize url, fill if necessary 61 | url = 'http://judge.u-aizu.ac.jp/onlinejudge/webservice/problem' 62 | # set parameter 63 | prm = kwargs.copy() 64 | prm['id'] = id 65 | # call api 66 | rsp = parse.fromweb(url, prm) 67 | # format 68 | rsp.id = str(rsp.id) 69 | rsp.name = str(rsp.name) 70 | rsp.available = int(rsp.available) 71 | rsp.problemtimelimit = int(rsp.problemtimelimit) 72 | rsp.problemmemorylimit = int(rsp.problemmemorylimit) 73 | s = rsp.status 74 | s.submission = int(s.submission) 75 | s.accepted = int(s.accepted) 76 | s.wronganswer = int(s.wronganswer) 77 | s.timelimit = int(s.timelimit) 78 | s.memorylimit = int(s.memorylimit) 79 | s.outputlimit = int(s.outputlimit) 80 | s.runtimeerror = int(s.runtimeerror) 81 | rsp.solved_list.user = to_list(rsp.solved_list.user) 82 | for user in rsp.solved_list.user: 83 | user.id = str(user.id) 84 | user.submissiondate = time2date(user.submissiondate) 85 | user.language = str(user.language) 86 | user.cputime = int(user.cputime) 87 | user.memory = int(user.memory) 88 | user.code_size = int(user.code_size) 89 | return rsp 90 | def ProblemListSearchAPI(volume, **kwargs): 91 | # type check 92 | if type(volume) not in [int, long]: 93 | raise Exception('parameter \'volume\' must be integer') 94 | # initialize url, fill if necessary 95 | url = 'http://judge.u-aizu.ac.jp/onlinejudge/webservice/problem_list' 96 | # set parameter 97 | prm = kwargs.copy() 98 | prm['volume'] = volume 99 | # call api 100 | rsp = parse.fromweb(url, prm) 101 | # format 102 | for p in rsp.problem: 103 | p.id = str(p.id) 104 | p.name = str(p.name) 105 | p.problemtimelimit = int(p.problemtimelimit) 106 | p.problemmemorylimit = int(p.problemmemorylimit) 107 | return rsp 108 | def AllUserListSearchAPI(**kwargs): 109 | # type check 110 | if 'criteria' in kwargs and type(kwargs['criteria']) not in [int, long]: 111 | raise Exception('parameter \'criteria\' must be integer') 112 | if 'affiliation' in kwargs and type(kwargs['affiliation']) not in [str, unicode]: 113 | raise Exception('parameter \'affiliation\' must be string') 114 | if 'solved_min' in kwargs and type(kwargs['solved_min']) not in [int, long]: 115 | raise Exception('parameter \'solved_min\' must be integer') 116 | if 'solved_max' in kwargs and type(kwargs['solved_max']) not in [int, long]: 117 | raise Exception('parameter \'solved_max\' must be integer') 118 | # initialize url, fill if necessary 119 | url = 'http://judge.u-aizu.ac.jp/onlinejudge/webservice/user_list' 120 | # set parameter 121 | prm = kwargs.copy() 122 | # call api 123 | rsp = parse.fromweb(url, prm) 124 | # format 125 | rsp.user = to_list(rsp.user) 126 | for user in rsp.user: 127 | user.rank = int(user.rank) 128 | user.id = str(user.id) 129 | user.name = str(user.name) 130 | user.affiliation = str(user.affiliation) 131 | user.solved = int(user.solved) 132 | user.rating = float(user.rating) 133 | return rsp 134 | def SolvedRecordSearchAPI(**kwargs): 135 | # type check 136 | if 'user_id' in kwargs and type(kwargs['user_id']) not in [str, unicode]: 137 | raise Exception('parameter \'user_id\' must be string') 138 | if 'problem_id' in kwargs and type(kwargs['problem_id']) not in [str, unicode]: 139 | #raise Exception('parameter \'problem_id\' must be string') 140 | kwargs['problem_id'] = '%04d' % kwargs['problem_id'] 141 | if 'language' in kwargs and type(kwargs['language']) not in [str, unicode]: 142 | raise Exception('parameter \'language\' must be string') 143 | if 'date_begin' in kwargs and type(kwargs['date_begin']) not in [int, long]: 144 | raise Exception('parameter \'date_begin\' must be integer') 145 | if 'date_end' in kwargs and type(kwargs['date_end']) not in [int, long]: 146 | raise Exception('parameter \'date_end\' must be integer') 147 | # initialize url, fill if necessary 148 | url = 'http://judge.u-aizu.ac.jp/onlinejudge/webservice/solved_record' 149 | # set parameter 150 | prm = kwargs.copy() 151 | # call api 152 | rsp = parse.fromweb(url, prm) 153 | # format 154 | rsp.solved = to_list(rsp.solved) 155 | for s in rsp.solved: 156 | s.run_id = int(s.run_id) 157 | s.user_id = str(s.user_id) 158 | s.problem_id = str(s.problem_id) 159 | s.date = time2date(s.date) 160 | s.language = str(s.language) 161 | s.cputime = int(s.cputime) 162 | s.memory = int(s.memory) 163 | s.code_size = int(s.code_size) 164 | return rsp 165 | def StatusLogSearchAPI(**kwargs): 166 | # type check 167 | if 'user_id' in kwargs and type(kwargs['user_id']) not in [str, unicode]: 168 | raise Exception('parameter \'user_id\' must be string') 169 | if 'problem_id' in kwargs and type(kwargs['problem_id']) not in [str, unicode]: 170 | #raise Exception('parameter \'problem_id\' must be string') 171 | kwargs['problem_id'] = '%04d' % kwargs['problem_id'] 172 | if 'start' in kwargs and type(kwargs['start']) not in [int, long]: 173 | raise Exception('parameter \'start\' must be integer') 174 | if 'limit' in kwargs and type(kwargs['limit']) not in [int, long]: 175 | raise Exception('parameter \'limit\' must be integer') 176 | # initialize url, fill if necessary 177 | url = 'http://judge.u-aizu.ac.jp/onlinejudge/webservice/status_log' 178 | # set parameter 179 | prm = kwargs.copy() 180 | # call api 181 | rsp = parse.fromweb(url, prm) 182 | # format 183 | for s in rsp.status: 184 | s.run_id = int(s.run_id) 185 | s.user_id = str(s.user_id) 186 | s.problem_id = str(s.problem_id) 187 | s.submission_date = time2date(s.submission_date) 188 | s.status = str(s.status) 189 | s.language = str(s.language) 190 | s.cputime = int(s.cputime) 191 | s.memory = int(s.memory) 192 | s.code_size = int(s.code_size) 193 | return rsp 194 | def JudgeDetailSearchAPI(id, **kwargs): 195 | # type check 196 | if type(id) not in [str, unicode]: 197 | #raise Exception('parameter \'id\' must be string') 198 | id = '%04d' % id 199 | # initialize url, fill if necessary 200 | url = 'http://judge.u-aizu.ac.jp/onlinejudge/webservice/judge' 201 | # set parameter 202 | prm = kwargs.copy() 203 | prm['id'] = id 204 | # call api 205 | rsp = parse.fromweb(url, prm) 206 | # format 207 | rsp.judge_id = str(rsp.judge_id) 208 | rsp.judge_type_code = int(rsp.judge_type_code) 209 | rsp.judge_type = str(rsp.judge_type) 210 | rsp.submissiondate = time2date(rsp.submissiondate) 211 | rsp.judgedate = time2date(rsp.judgedate) 212 | rsp.language = str(rsp.language) 213 | rsp.cuptime = int(rsp.cuptime) 214 | rsp.memory = int(rsp.memory) 215 | rsp.code_size = int(rsp.code_size) 216 | rsp.status = int(rsp.status) 217 | rsp.accuracy = str(rsp.accuracy) 218 | rsp.problem_id = str(rsp.problem_id) 219 | rsp.problem_title = str(rsp.problem_title) 220 | rsp.submissions = int(rsp.submissions) 221 | rsp.accepted = int(rsp.accepted) 222 | rsp.user_id = str(rsp.user_id) 223 | rsp.user_name = str(rsp.user_name) 224 | rsp.affiliation = str(rsp.affiliation) 225 | return rsp 226 | def ProblemCategorySearchAPI(**kwargs): 227 | # type check 228 | if 'id' in kwargs and type(kwargs['id']) not in [str, unicode]: 229 | #raise Exception('parameter \'id\' must be string') 230 | kwargs['id'] = '%04d' % kwargs['id'] 231 | if 'category' in kwargs and type(kwargs['category']) not in [str, unicode]: 232 | raise Exception('parameter \'category\' must be string') 233 | # initialize url, fill if necessary 234 | url = 'http://judge.u-aizu.ac.jp/onlinejudge/webservice/problem_category' 235 | # set parameter 236 | prm = kwargs.copy() 237 | # call api 238 | rsp = parse.fromweb(url, prm) 239 | # format 240 | def fn(p): 241 | p.id = str(p.id) 242 | p.category = str(p.category) 243 | p.score = float(p.score) 244 | if type(rsp.problem) is list: 245 | for p in rsp.problem: 246 | fn(p) 247 | else: 248 | fn(rsp.problem) 249 | rsp.problem = [rsp.problem] 250 | return rsp 251 | def SourceSearchAPI(id, **kwargs): 252 | # type check 253 | if type(id) not in [str, unicode]: 254 | #raise Exception('parameter \'id\' must be string') 255 | id = '%04d' % id 256 | # initialize url, fill if necessary 257 | url = 'http://judge.u-aizu.ac.jp/onlinejudge/webservice/source' 258 | # set parameter 259 | prm = kwargs.copy() 260 | prm['id'] = id 261 | # call api 262 | rsp = parse.fromweb(url, prm) 263 | # format 264 | rsp.id = str(rsp.id) 265 | rsp.title = str(rsp.title) 266 | rsp.subtitle = str(rsp.subtitle) 267 | rsp.place = str(rsp.place) 268 | rsp.abbr = str(rsp.abbr) 269 | rsp.author1 = str(rsp.author1) 270 | rsp.author2 = str(rsp.author2) 271 | rsp.year = str(rsp.year) 272 | rsp.month = str(rsp.month) 273 | rsp.day = str(rsp.day) 274 | rsp.note = str(rsp.note) 275 | rsp.url = str(rsp.url) 276 | rsp.judge = str(rsp.judge) 277 | return rsp 278 | def ContestListSearchAPI(**kwargs): 279 | # type check 280 | # initialize url, fill if necessary 281 | url = 'http://judge.u-aizu.ac.jp/onlinejudge/webservice/contest_list' 282 | # set parameter 283 | prm = kwargs.copy() 284 | # call api 285 | rsp = parse.fromweb(url, prm) 286 | # format 287 | return rsp 288 | def ContestInfoSearchAPI(id, **kwargs): 289 | # type check 290 | # initialize url, fill if necessary 291 | url = 'http://judge.u-aizu.ac.jp/onlinejudge/webservice/contest_info' 292 | # set parameter 293 | prm = kwargs.copy() 294 | prm['id'] = id 295 | # call api 296 | rsp = parse.fromweb(url, prm) 297 | # format 298 | return rsp 299 | def ContestStandingSearchAPI(id, **kwargs): 300 | # type check 301 | # initialize url, fill if necessary 302 | url = 'http://judge.u-aizu.ac.jp/onlinejudge/webservice/contest_standing' 303 | # set parameter 304 | prm = kwargs.copy() 305 | prm['id'] = id 306 | # call api 307 | rsp = parse.fromweb(url, prm) 308 | # format 309 | return rsp 310 | def ContestProblemSearchAPI(id, **kwargs): 311 | # type check 312 | # initialize url, fill if necessary 313 | url = 'http://judge.u-aizu.ac.jp/onlinejudge/webservice/contest_problem' 314 | # set parameter 315 | prm = kwargs.copy() 316 | prm['id'] = id 317 | # call api 318 | rsp = parse.fromweb(url, prm) 319 | # format 320 | return rsp 321 | def ContestStatusLogSearchAPI(id, **kwargs): 322 | # type check 323 | # initialize url, fill if necessary 324 | url = 'http://judge.u-aizu.ac.jp/onlinejudge/webservice/contest_status_log' 325 | # set parameter 326 | prm = kwargs.copy() 327 | prm['id'] = id 328 | # call api 329 | # call api 330 | rsp = parse.fromweb(url, prm) 331 | # format 332 | return rsp 333 | 334 | 335 | # TODO: implement. 336 | 337 | 338 | def ThreadSearchAPI(**kwargs): 339 | # type check 340 | if 'id' in kwargs and type(kwargs['id']) not in [int, long]: 341 | raise Exception('parameter \'id\' must be integer') 342 | # initialize url, fill if necessary 343 | url = 'http://rose.u-aizu.ac.jp/aojbbs/webservice/thread/$.xml' 344 | url = url.replace('$', kwargs['id'], 1) 345 | # set parameter 346 | prm = kwargs.copy() 347 | # call api 348 | rsp = parse.fromweb(url, prm) 349 | # format 350 | rsp.id = int(rsp.id) 351 | rsp.name = str(rsp.name) 352 | rsp.problem_id = str(rsp.problem_id) 353 | rsp.user_id = str(rsp.user_id) 354 | rsp.update_time = date2str(rsp.update_time) 355 | return rsp 356 | def GETRecentThreadAPI(**kwargs): 357 | # type check 358 | if 'number' in kwargs and type(kwargs['number']) not in [int, long]: 359 | raise Exception('parameter \'number\' must be integer') 360 | # initialize url, fill if necessary 361 | url = 'http://rose.u-aizu.ac.jp/aojbbs/webservice/recent/thread/$' 362 | url = url.replace('$', kwargs['number'], 1) 363 | # set parameter 364 | prm = kwargs.copy() 365 | # call api 366 | rsp = parse.fromweb(url, prm) 367 | # format 368 | rsp.problem_id = str(rsp.problem_id) 369 | rsp.user_id = str(rsp.user_id) 370 | rsp.update_time = date2str(rsp.update_time) 371 | return rsp 372 | def MessageSearchAPI(**kwargs): 373 | # type check 374 | if 'id' in kwargs and type(kwargs['id']) not in [int, long]: 375 | raise Exception('parameter \'id\' must be integer') 376 | # initialize url, fill if necessary 377 | url = 'http://rose.u-aizu.ac.jp/aojbbs/webservice/message/$.xml' 378 | url = url.replace('$', kwargs['id'], 1) 379 | # set parameter 380 | prm = kwargs.copy() 381 | # call api 382 | rsp = parse.fromweb(url, prm) 383 | # format 384 | rsp.id = int(rsp.id) 385 | rsp.thread_id = int(rsp.thread_id) 386 | rsp.problem_id = str(rsp.problem_id) 387 | rsp.user_id = str(rsp.user_id) 388 | rsp.content = str(rsp.content) 389 | rsp.url = str(rsp.url) 390 | rsp.update_time = date2str(rsp.update_time) 391 | return rsp 392 | def ThreadSeachfromproblemIDAPI(**kwargs): 393 | # type check 394 | if 'problem_id' in kwargs and type(kwargs['problem_id']) not in [int, long]: 395 | raise Exception('parameter \'problem_id\' must be integer') 396 | # initialize url, fill if necessary 397 | url = 'http://rose.u-aizu.ac.jp/aojbbs/webservice/thread/problem/$.xml' 398 | url = url.replace('$', kwargs['problem_id'], 1) 399 | # set parameter 400 | prm = kwargs.copy() 401 | # call api 402 | rsp = parse.fromweb(url, prm) 403 | # format 404 | rsp.id = int(rsp.id) 405 | rsp.name = str(rsp.name) 406 | rsp.problem_id = int(rsp.problem_id) 407 | rsp.user_id = str(rsp.user_id) 408 | rsp.update_time = date2str(rsp.update_time) 409 | return rsp 410 | def MessageSearchfromThreadIDAPI(**kwargs): 411 | # type check 412 | if 'id' in kwargs and type(kwargs['id']) not in [int, long]: 413 | raise Exception('parameter \'id\' must be integer') 414 | # initialize url, fill if necessary 415 | url = 'http://rose.u-aizu.ac.jp/aojbbs/webservice/message/thread/$.xml' 416 | url = url.replace('$', kwargs['id'], 1) 417 | # set parameter 418 | prm = kwargs.copy() 419 | # call api 420 | rsp = parse.fromweb(url, prm) 421 | # format 422 | rsp.id = int(rsp.id) 423 | rsp.thread_id = int(rsp.thread_id) 424 | rsp.problem_id = str(rsp.problem_id) 425 | rsp.user_id = str(rsp.user_id) 426 | rsp.content = str(rsp.content) 427 | rsp.url = str(rsp.url) 428 | rsp.update_time = date2str(rsp.update_time) 429 | return rsp 430 | def GETRecentMessageAPI(**kwargs): 431 | # type check 432 | if 'id' in kwargs and type(kwargs['id']) not in [int, long]: 433 | raise Exception('parameter \'id\' must be integer') 434 | # initialize url, fill if necessary 435 | url = 'http://rose.u-aizu.ac.jp/aojbbs/webservice/recent/message/$.xml' 436 | url = url.replace('$', kwargs['id'], 1) 437 | # set parameter 438 | prm = kwargs.copy() 439 | # call api 440 | rsp = parse.fromweb(url, prm) 441 | # format 442 | rsp.id = int(rsp.id) 443 | rsp.thread_id = int(rsp.thread_id) 444 | rsp.problem_id = str(rsp.problem_id) 445 | rsp.user_id = str(rsp.user_id) 446 | rsp.content = str(rsp.content) 447 | rsp.url = str(rsp.url) 448 | rsp.update_time = date2str(rsp.update_time) 449 | return rsp 450 | 451 | 452 | # for aojtools v0.1 compatible 453 | user = UserSearchAPI 454 | problem = ProblemSearchAPI 455 | problemlist = ProblemListSearchAPI 456 | alluserlist = AllUserListSearchAPI 457 | solvedrecord = SolvedRecordSearchAPI 458 | statuslog = StatusLogSearchAPI 459 | problemcategory = ProblemCategorySearchAPI 460 | -------------------------------------------------------------------------------- /aojtools/libxmlload.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | import urllib 3 | from xml.etree.ElementTree import * 4 | 5 | class Node(object): 6 | def __init__(self, name, info): 7 | self.__dict__['_info'] = info 8 | self.__dict__['_name'] = name 9 | def __getattr__(self, name): 10 | if name in self.__dict__['_info']: 11 | return self.__dict__['_info'][name] 12 | return self.__dict__[name] 13 | def __setattr__(self, name, value): 14 | self.__dict__['_info'][name] = value 15 | def __iter__(self): 16 | return self._info.iteritems() 17 | def __repr__(self): 18 | args = self._name, ','.join(self._info.keys()) 19 | return "<%s keys=%s>" % args 20 | #def __dict__(self): 21 | # return self.__dict__['_info'] 22 | 23 | def xmltrans(xmlnode): 24 | node = Node(xmlnode.tag, {}) 25 | for child in xmlnode: 26 | key = child.tag 27 | if len(child) == 0: 28 | val = child.text 29 | if val is not None: 30 | val = val.strip() 31 | assign(node._info, key, val) 32 | else: 33 | assign(node._info, key, xmltrans(child)) 34 | return node 35 | 36 | def assign(info, key, value): 37 | if key in info: 38 | if isinstance(info[key], list): 39 | info[key].append(value) 40 | else: 41 | info[key] = [info[key], value] 42 | else: 43 | info[key] = value 44 | 45 | def urlopen(url): 46 | # http access 47 | conn = urllib.urlopen(url) 48 | xmlstr = conn.read() 49 | # create xml 50 | xmldoc = fromstring(xmlstr) 51 | # xml to object tree 52 | otree = xmltrans(xmldoc) 53 | return otree 54 | 55 | def parse(filepath): 56 | fobj = open(filepath) 57 | xmlstr = fobj.read() 58 | xmldoc = fromstring(xmlstr) 59 | otree = xmltrans(xmldoc) 60 | return otree 61 | -------------------------------------------------------------------------------- /aojtools/parse.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/python2.6 2 | # coding: utf-8 3 | import urllib 4 | from xml.etree.ElementTree import fromstring 5 | 6 | class dictex(dict): 7 | # pretty dict 8 | def __init__(self, tag): 9 | self.__dict__['_tag'] = tag 10 | def __getattr__(self, name): 11 | return self.get(name, None) 12 | def __setattr__(self, key, val): 13 | dict.__setitem__(self, key, val) 14 | 15 | def fromxml(xmlnode): 16 | fun = lambda x: len(c) and fromxml(x) or (x.text and x.text.strip() or '') 17 | d = dictex(xmlnode.tag) 18 | for c in xmlnode: 19 | k = c.tag 20 | if k in d: 21 | d[k] = isinstance(d[k], list) and d[k] or [d[k]] 22 | d[k].append(fun(c)) 23 | else: 24 | d[k] = fun(c) 25 | return d 26 | 27 | def fromweb(url, prm={}): 28 | try: 29 | enc = '&'.join('%s=%s' % (k, prm[k]) for k in prm) 30 | purl = url + (enc and '?' + enc or '') 31 | if False: 32 | print purl 33 | cont = urllib.urlopen(purl).read() 34 | cont = unicode(cont, 'cp1252') 35 | tree = fromxml(fromstring(cont)) 36 | return tree 37 | except Exception, e: 38 | raise e 39 | 40 | if __name__ == '__main__': 41 | url = 'http://judge.u-aizu.ac.jp/onlinejudge/webservice/problem_list?volume=10' 42 | tree = fromxml(fromstring(urllib.urlopen(url).read())) 43 | -------------------------------------------------------------------------------- /aojtools/settings.py: -------------------------------------------------------------------------------- 1 | # webpage encoding 2 | SITEENCODING = 'utf-8' 3 | 4 | LANG_C = 'C' 5 | LANG_CPP = 'C++' 6 | LANG_CPP11 = 'C++11' 7 | LANG_JAVA = 'JAVA' 8 | -------------------------------------------------------------------------------- /aojtools/submit.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | import urllib 3 | import time 4 | import socket 5 | 6 | import generated as api 7 | 8 | def submit_noresult(info, timeout=None): 9 | assert sorted(info.keys()) == sorted(['user_id', 'code', 'problem_id', 'lang', 'password']), 'first argument must have keys ["user_id", "code", "problem_id", "lang", "password"]' 10 | assert (timeout is None) or (isinstance(timeout, int) and timeout > 0), 'timout must be a positive integer' 11 | if isinstance(info['problem_id'], int): 12 | info['problem_id'] = '%04d' % info['problem_id'] 13 | #assert len(info['problem_id']) == 4, 'problem id must be a positive integer or four-length string' 14 | assert info['lang'] in ['C', 'C++', 'C++11', 'JAVA'], 'lang must be "C", "C++", "C++11" or "JAVA"' 15 | 16 | url = 'http://judge.u-aizu.ac.jp/onlinejudge/servlet/Submit' 17 | info = { 18 | 'userID': info['user_id'], 19 | 'sourceCode': info['code'], 20 | 'problemNO': info['problem_id'], 21 | 'language': info['lang'].upper(), 22 | 'password': info['password'], 23 | } 24 | postdata = urllib.urlencode(info) 25 | if not timeout is None: 26 | socket.setefaulttimeout(timeout) 27 | resp = urllib.urlopen(url, postdata).read() 28 | return resp 29 | 30 | 31 | 32 | def tryntimes(fun, nmax = 10, interval = 2, timeout = 10): 33 | try: 34 | return fun() 35 | except Exception, e: 36 | if nmax: 37 | time.sleep(interval) 38 | return tryntimes(fun, nmax - 1, interval, timeout) 39 | else: 40 | raise Exception('maximum try times exceed') 41 | 42 | def lastrunid(info): 43 | resp = api.StatusLogSearchAPI(user_id=info['user_id']) 44 | return resp.status[0], resp.status[0].run_id 45 | 46 | 47 | def submit(info, timeout=None, waittime=2, maxtry=10): 48 | """ 49 | usage: 50 | info = { 51 | 'user_id': (user id), 52 | 'password': (password), 53 | 'code': (source code), 54 | 'problem_id': (problem id, integer or string), 55 | 'lang': (language "C","C++","C++11"or"JAVA") 56 | } 57 | submit(info) 58 | #submit(info, timeout=3) # seconds 59 | """ 60 | # check last runid 61 | resp, rid = lastrunid(info) 62 | # submit 63 | try: 64 | submit_noresult(info, timeout) 65 | except Exception, e: 66 | raise e 67 | if 'UserID or Password is Wrong.' in resp: 68 | raise Exception('userid or password is wrong.') 69 | # wait until update 70 | def fun(): 71 | resp, new_rid = lastrunid(info) 72 | if new_rid > rid: 73 | return resp 74 | else: 75 | raise Exception('fun') 76 | return tryntimes(fun, maxtry, waittime, timeout) 77 | -------------------------------------------------------------------------------- /scripts/aojcategories: -------------------------------------------------------------------------------- 1 | #! /usr/bin/python 2 | # coding: utf-8 3 | 4 | import os 5 | import sys 6 | from aojtools import api 7 | 8 | if len(sys.argv) < 2: 9 | ps = api.problemcategory() 10 | d = {} 11 | for p in ps.problem: 12 | if p.category in d: 13 | d[p.category] += 1 14 | else: 15 | d[p.category] = 0 16 | for k in d: 17 | print k.ljust(15), d[k] 18 | elif sys.argv[1] == 'help': 19 | print 'usage %s (|category-name|problem-id)' % os.path.basename(__file__) 20 | elif sys.argv[1].isdigit(): 21 | pid = sys.argv[1] 22 | p = api.problemcategory(id=pid) 23 | print p.problem[0].category 24 | else: 25 | ps = api.problemcategory(category=sys.argv[1]) 26 | for i,p in enumerate(sorted(ps.problem, key=lambda p: p.id)): 27 | print '%04d %f' % (p.id, p.score) 28 | -------------------------------------------------------------------------------- /scripts/aojprepare: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # coding: utf-8 3 | 4 | import sys 5 | import codecs 6 | 7 | from urlparse import urlunparse 8 | from urllib import urlencode, urlopen 9 | from lxml import etree 10 | from aojtools import settings 11 | 12 | sys.stdout = codecs.getwriter('utf_8')(sys.stdout) 13 | 14 | 15 | def make_url(problem_id): 16 | q = urlencode({"id":problem_id}) 17 | parts = ("http", "judge.u-aizu.ac.jp", "onlinejudge/description.jsp", "", q, "") 18 | return urlunparse(parts) 19 | 20 | 21 | def get(problem_id): 22 | url = make_url(problem_id) 23 | 24 | print 'getting:', url 25 | 26 | h = urlopen(url) 27 | g = codecs.getreader('shift_jis')(h) 28 | return g.read() 29 | 30 | 31 | def parse_and_save(problem_id, got): 32 | t = etree.HTML(got) 33 | find_h2= etree.XPath('''//div[@class="description"]/h2''') 34 | for h2 in find_h2(t): 35 | if h2.text == "Sample Input": 36 | "

Sample Input

" 37 | candi = h2.getnext() 38 | if candi.tag == 'pre': 39 | with open(problem_id+".input", 'w') as f: 40 | f.write(candi.text.lstrip()) 41 | print 'wrote %s.input'%(problem_id,) 42 | 43 | if h2.text == "Output for the Sample Input": 44 | "

Output for the Sample Input

" 45 | candi = h2.getnext() 46 | if candi.tag == 'pre': 47 | with open(problem_id+".output", 'w') as f: 48 | f.write(candi.text.lstrip()) 49 | print 'wrote %s.output'%(problem_id,) 50 | 51 | def make_template(problem_id): 52 | t = """\ 53 | /* AOJ %s 54 | * 55 | * %s 56 | * 57 | */ 58 | 59 | #include 60 | 61 | int main(){ 62 | 63 | return 0; 64 | } 65 | """ 66 | try: 67 | with open(problem_id+".c", "r") as f: 68 | print "has .c file. do nothing." 69 | except: 70 | with open(problem_id+".c", "w") as g: 71 | g.write(t%(problem_id, make_url(problem_id))) 72 | print "made .c file." 73 | 74 | 75 | 76 | if __name__ == "__main__": 77 | if not len(sys.argv) == 2: 78 | print "please specify problem id" 79 | sys.exit(0) 80 | x = int(sys.argv[1]) 81 | problem_id = "%04d"%(x,) 82 | print 'working on "%s"'%(problem_id,) 83 | got = get(problem_id) 84 | print "received", len(got), "bytes" 85 | parse_and_save(problem_id, got) 86 | make_template(problem_id) 87 | 88 | 89 | -------------------------------------------------------------------------------- /scripts/aojrun: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # coding: utf-8 3 | 4 | 5 | import sys 6 | import time 7 | import exceptions 8 | import subprocess 9 | 10 | 11 | MAXOUTPUT = 10*1024 #byte 12 | TIMELIMIT = 1.0 #s 13 | TIMESLICE = 0.01 14 | 15 | class FileLimitExceedException(Exception): 16 | pass 17 | 18 | class TimeLimitExceedException(Exception): 19 | pass 20 | 21 | class ReturnCodeException(Exception): 22 | pass 23 | 24 | class Runner: 25 | def __init__(self, problem_id): 26 | self.input = open(problem_id+".input", "rb") 27 | self.output = open(problem_id+".result", "wb") 28 | self.errput = open(problem_id+".log", "wb") 29 | self.process = None 30 | self.problem_id = problem_id 31 | self.onstart = None 32 | 33 | def __enter__(self): 34 | return self 35 | 36 | def __exit__(self, exc_type, exc_value, traceback): 37 | self.input.close() 38 | self.output.close() 39 | self.errput.close() 40 | if self.process.poll() is None: 41 | self.process.kill() 42 | 43 | def start(self): 44 | self.process = subprocess.Popen("./"+self.problem_id, stdin=self.input, stdout=self.output, stderr=self.errput) 45 | 46 | def elapse(self): 47 | if self.onstart is not None: 48 | return time.time() - self.onstart 49 | else: 50 | self.onstart = time.time() 51 | return 0.0 52 | 53 | def check_quota(self, f): 54 | if f.tell() > MAXOUTPUT: 55 | raise FileLimitExceedException() 56 | 57 | def run(self): 58 | self.start() 59 | while True: 60 | time.sleep(TIMESLICE) 61 | if self.elapse() > TIMELIMIT: 62 | raise TimeLimitExceedException() 63 | self.check_quota(self.output) 64 | self.check_quota(self.input) 65 | self.check_quota(self.errput) 66 | r = self.process.poll() 67 | if r is not None: 68 | if r != 0: 69 | raise ReturnCodeException 70 | return r 71 | 72 | 73 | if __name__ == "__main__": 74 | if not len(sys.argv) == 2: 75 | print "please specify problem id" 76 | sys.exit(0) 77 | x = int(sys.argv[1]) 78 | problem_id = "%04d"%(x,) 79 | with Runner(problem_id) as r: 80 | r.run() 81 | print "done. took about", r.elapse() 82 | 83 | -------------------------------------------------------------------------------- /scripts/aojsolvedlist: -------------------------------------------------------------------------------- 1 | #! /usr/bin/python 2 | # coding: utf-8 3 | 4 | import os 5 | import sys 6 | from aojtools import api 7 | 8 | if len(sys.argv) < 2: 9 | path = os.path.basename(__file__) 10 | print '%s user-id' % path 11 | else: 12 | user = api.UserSearchAPI(sys.argv[1]) 13 | solved_ids = [p.id for p in user.solved_list.problem] 14 | for solved_id in solved_ids: 15 | print solved_id 16 | -------------------------------------------------------------------------------- /scripts/aojsubmit: -------------------------------------------------------------------------------- 1 | #! /usr/bin/python 2 | # coding: utf-8 3 | 4 | import os 5 | import sys 6 | import re 7 | from optparse import OptionParser 8 | 9 | import aojtools 10 | api = aojtools.api 11 | 12 | def convert(s): 13 | for enc in ['utf-8', 'cp932', 'sjis', 'euc-jp', 'iso-2022-jp']: 14 | try: 15 | t = s.decode(enc) 16 | return t.encode(aojtools.settings.SITEENCODING) 17 | return t.encode('sjis') 18 | except Exception, e: 19 | pass 20 | raise Exception('unknown file encoding.') 21 | 22 | def guess_lang(filepath): 23 | ext = os.path.splitext(filepath)[1] 24 | if ext == '': 25 | raise Exception('unknown format') 26 | pairs = [('.c', api.settings.LANG_C), ('.cpp.cxx.cc.cp', api.settings.LANG_CPP), ('.java', api.settings.LANG_JAVA)] 27 | for exts, cst in pairs: 28 | if ext in exts: 29 | return cst 30 | raise Exception('unknown format') 31 | 32 | def guess_pid(filepath): 33 | import re 34 | lst = re.findall('AOJ\D?(\d+).*', open(filepath).readline(), re.I) 35 | if len(lst) > 0: 36 | return lst[0] 37 | filepath 38 | 39 | def build_parser(): 40 | parser = OptionParser(usage='%prog [options] file') 41 | parser.add_option('-u', '--userid', dest='uid', metavar='USERID', default='') 42 | parser.add_option('-p', '--password', dest='pwd', metavar='PASSWORD', default='') 43 | parser.add_option('-l', '--language', dest='lang', metavar='LANGUAGE', choices=['c','cpp','cpp11','java']) 44 | parser.add_option('-i', '--problem_id', dest='pid', metavar='PROBLEM_ID', type=int) 45 | parser.add_option('-v', '--verbose', dest='verbose', action='store_true', default=False) 46 | return parser 47 | 48 | def main(): 49 | parser = build_parser() 50 | opts, args = parser.parse_args() 51 | 52 | path = '' 53 | uid = '' if opts.uid is None else opts.uid 54 | pwd = '' if opts.pwd is None else opts.pwd 55 | lang = '' if opts.lang is None else opts.lang 56 | pid = '' if opts.pid is None else opts.pid 57 | 58 | if len(args) < 1: 59 | parser.error('program file is required') 60 | else: 61 | path = args[0] 62 | 63 | if uid == '' or pwd == '': 64 | rcpath = os.path.join(os.path.expandvars('$HOME'), '.aojsubmitrc') 65 | if not os.path.exists(rcpath): 66 | parser.error('userid and password must be specified, or put .aojsubmitrc file to home directory. show option -h') 67 | lst = open(rcpath).read().split() 68 | if len(lst) != 2: 69 | print 'invalid rcfile. show file', rcpath 70 | sys.exit() 71 | uid, pwd = lst 72 | 73 | info = {} 74 | try: 75 | if lang == '': 76 | lang = guess_lang(path) 77 | else: 78 | lang = {'c':api.settings.LANG_C, 'cpp':api.settings.LANG_CPP, 'cpp11':api.settings.LANG_CPP11, 'java':api.settings.LANG_JAVA}[lang] 79 | if pid == '': 80 | pid = guess_pid(path) 81 | code = convert(open(path).read()) 82 | info = { 83 | 'user_id': uid, 84 | 'password': pwd, 85 | 'code': code, 86 | 'problem_id': pid, 87 | 'lang': lang, 88 | } 89 | except Exception, e: 90 | parser.error(e) 91 | 92 | if parser.values.verbose: 93 | print 'user id :', info['user_id'] 94 | print 'lang :', info['lang'] 95 | print 'problem id:', info['problem_id'] 96 | 97 | try: 98 | status = aojtools.submit.submit(info) 99 | print status.status 100 | except Exception, e: 101 | print '******************** ERROR *********************' 102 | print e 103 | 104 | if __name__ == '__main__': 105 | main() 106 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | import glob 3 | 4 | desc = "api client library and scripts for aizu online judge system." 5 | ldesc = """aojtools is a toolset written in Python for aoj, aizu online judge system(http://judge.u-aizu.ac.jp/onlinejudge/) , including transparently API acccess, problem submit library and CLI script. 6 | """ 7 | 8 | setup( 9 | name='aojtools' 10 | , version='0.2.4' 11 | , description=desc 12 | , long_description=ldesc 13 | , classifiers = [ 14 | 'Programming Language :: Python' 15 | , 'Topic :: Internet :: WWW/HTTP' 16 | , 'Topic :: Software Development :: Libraries :: Python Modules' 17 | ] 18 | , author='yatt' 19 | , keywords=['competitive programming'] 20 | , author_email='darknesssharp@gmail.com' 21 | , packages=['aojtools'] 22 | , scripts=[ 23 | 'scripts/aojcategories', 24 | 'scripts/aojprepare', 25 | 'scripts/aojrun', 26 | 'scripts/aojsolvedlist', 27 | 'scripts/aojsubmit', 28 | ] 29 | , license='MIT' 30 | , url='https://github.com/yatt/aojtools' 31 | ) 32 | -------------------------------------------------------------------------------- /util/generator.js: -------------------------------------------------------------------------------- 1 | // ----------------------------------------------------------------------------- 2 | // title : aojapi.js 3 | // author : brainfs/yatt 4 | // date : 2012/05/23 5 | // license: MIT 6 | // desc : 7 | // aoj (aizu online judge)のAPIリファレンスから、APIクライアントコード 8 | // 生成に使う情報を抽出、フォーマット関数を呼び出します。 9 | // usage : 10 | // chrome等で 11 | // http://judge.u-aizu.ac.jp/onlinejudge/api.jsp 12 | // を開いてコンソールで以下を実行してください。 13 | // ----------------------------------------------------------------------------- 14 | 15 | (function(formatter){ 16 | 17 | var main = function(){ 18 | // apiのテーブルを一覧取得 19 | var api = $(".infoBack") 20 | .filter(function(i, item){ return item.children.length > 0 }) 21 | .map(function(i,n){ n=$(n); return { 22 | parameter: prmfn($(n.find('table')[0])), 23 | response: bdyfn($(n.find('table')[1])), 24 | name: n.find('h3')[0].innerText.replace(/ /g, ''), 25 | desc: n.find('p')[0].innerText, 26 | url: n.find('p')[1].innerText 27 | // .xml only 28 | .split('\n')[0] 29 | // replace parameter string to format string 30 | .replace(//g, '$') 31 | .replace(//g, '$') 32 | .replace(//g, '$') 33 | .replace(//g, '$') 34 | .replace(//g, '$') 35 | }}) 36 | formatter(api) 37 | } 38 | 39 | var fn = function(t,i){ return t.children[i] && t.children[i].innerText || ''} 40 | 41 | // ---------------------------------- 42 | // リスエスト側 43 | // ---------------------------------- 44 | var prmfn = function(req){ 45 | return req 46 | .find("tr") 47 | .filter(function(i){ return i > 0 }) 48 | .map(function(i,item){ return { 49 | name: fn(item,0), 50 | desc: fn(item,1), 51 | type: fn(item,2), 52 | required: fn(item,3) == 'yes', 53 | sample: fn(item,4) 54 | }}) 55 | .filter(function(i,n){ return n.name !== '' }) 56 | } 57 | 58 | // ---------------------------------- 59 | // レスポンス側 60 | // ---------------------------------- 61 | var bdyfn = function(bdy){ 62 | // パラメータの取得 63 | 64 | // Thread Search API移行はfrequencyが無い 65 | var speccase = bdy.find('tr')[0].innerText.indexOf('Freq') == -1 66 | 67 | bdy = bdy 68 | .find("tr") 69 | .filter(function(i){ return i > 0 }) 70 | .map(function(i,item){ var fn0=fn(item,0); return { 71 | name: fn0.indexOf('-') == -1 72 | ? fn0 73 | : fn0.substring(fn0.indexOf('-') + 2, fn0.length), 74 | desc: fn(item,1), 75 | type: fn(item,2), 76 | freq: speccase ? '1': fn(item,3), 77 | sample: fn(item, speccase ? 3: 4), 78 | depth: fn0.indexOf('-') == -1 ? 0: fn0.indexOf('-') / 2, 79 | path: '', 80 | }}) 81 | .filter(function(i,n){ return n.name !== '' }) 82 | 83 | // attribute_id以下にパラメータではない4つの説明がある。その部分を削除 84 | var loop = bdy.length; 85 | for (var i = 0; i < loop; i++) { 86 | if (bdy[i].name == 'attribute_id') { 87 | bdy = bdy.slice(0, i).add( bdy.slice(i + 5) ) 88 | break 89 | } 90 | } 91 | var recursion = function (idx, stk){ 92 | /* 93 | console.log(idx); 94 | console.log(bdy[idx].name); 95 | console.log(stk); 96 | */ 97 | var path = (stk.length>0?'/':'') + stk.join('/') + '/' + idx 98 | bdy[idx].path = path 99 | 100 | if (idx + 1 === bdy.length) 101 | return 102 | 103 | var n = bdy[idx + 1].depth - bdy[idx].depth 104 | if (n === 0) 105 | recursion(idx + 1, stk) 106 | else 107 | if (n > 0) 108 | recursion(idx + 1, stk.concat([idx])) 109 | else 110 | recursion(idx + 1, stk.slice(0, -n)) 111 | } 112 | if (bdy.length) 113 | recursion(0, []) 114 | //console.log(bdy); 115 | 116 | return bdy 117 | } 118 | 119 | main() 120 | 121 | })(function(api){ 122 | // ------------------------------------------------------------- 123 | // replace content of this function 124 | // ------------------------------------------------------------- 125 | 126 | console.log('#! /usr/bin/python2.6') 127 | console.log('# coding: utf-8') 128 | console.log('') 129 | console.log('import parse') 130 | console.log('') 131 | console.log('def time2date(s):') 132 | console.log(' return time.gmtime(int(s) / 1000.)') 133 | console.log('def date2str(d):') 134 | console.log(' return time.strftime(\'%Y/%m/%d %H:%M:%S\', d)') 135 | console.log('') 136 | console.log('') 137 | console.log('') 138 | for (var i = 0; i < api.length; i++){ 139 | 140 | var prm = api[i].parameter 141 | // param 142 | var required = $.makeArray( 143 | $(api[i].parameter) 144 | .filter(function(i, n){ return n.required }) 145 | .map(function(i,n){ return n.name }) 146 | ) 147 | console.log('def ' + api[i].name + '(' + required.join(', ') + (required.length > 0 ? ', ' : '') + '**kwargs):') 148 | 149 | // format check 150 | console.log(' # type check') 151 | for (var j = 0; j < prm.length; j++){ 152 | var repr = { 153 | true: prm[j].name, 154 | false: 'kwargs[\'' + prm[j].name + '\']', 155 | }[prm[j].required] 156 | 157 | var selection = { 158 | 'string': '[str, unicode]', 159 | 'integer': '[int, long]', 160 | 'long integer': '[int, long]', 161 | }[prm[j].type] 162 | 163 | var mustbe = { 164 | 'string': 'string', 165 | 'integer': 'integer', 166 | 'long integer': 'integer', 167 | }[prm[j].type] 168 | 169 | var r = (prm[j].required ? '': '\'' + prm[j].name + '\' in kwargs and ') 170 | 171 | console.log(' if ' + r + 'type(' + repr + ') not in ' + selection + ':') 172 | console.log(' raise Exception(\'parameter \\\'' + prm[j].name + '\\\' must be ' + mustbe + '\')') 173 | } 174 | 175 | console.log(' # initialize url, fill if necessary') 176 | // set parameter 177 | var url = api[i].url 178 | var prm2 = prm 179 | console.log(' url = \'' + api[i].url + '\'') 180 | while (url.indexOf('$') > -1){ 181 | var repr = { 182 | true: prm2[0].name, 183 | false: 'kwargs[\'' + prm2[0].name + '\']', 184 | }[prm2[0].required] 185 | console.log(' url = url.replace(\'$\', ' + repr + ', 1)') 186 | 187 | prm2 = prm2.slice(1) 188 | url = url.replace('$', '') 189 | } 190 | 191 | console.log(' # set parameter') 192 | console.log(' prm = kwargs.copy()') 193 | for (var j = 0; j < prm2.length; j++){ 194 | if (prm[j].required) 195 | console.log(' prm[\'' + prm2[j].name + '\'] = ' + prm2[j].name) 196 | } 197 | 198 | console.log(' # call api') 199 | console.log(' rsp = parse.fromweb(url, prm)') 200 | 201 | // normalize response xml 202 | console.log(' # format') 203 | var rsp = api[i].response 204 | var fn = { 205 | 'string': 'str', 206 | 'integer': 'int', 207 | 'long integer': i<14 ? 'time2date': 'int', 208 | 'long': i<14 ? 'time2date': 'int', 209 | 'float': 'float', 210 | 'Date': 'date2str', 211 | } 212 | 213 | var makerepr = function(idx, stk){ 214 | stk = stk || [] 215 | var lst = rsp[idx].path.slice(1).split('/') 216 | //lst = $.makeArray($(lst).map(function(i,n){ return rsp[n].name })) 217 | lst = $.makeArray($(lst).map(function(i,n){ 218 | var idx = stk.indexOf(parseInt(n)) 219 | 220 | return idx === -1 ? rsp[n].name: rsp[n].name + '[i' + idx + ']' 221 | })) 222 | return repr = 'rsp.' + lst.join('.') 223 | } 224 | var rec = function(j, stk){ 225 | var d = rsp[j].depth 226 | var head = new Array(d + 2).join(' ') 227 | // TODO: 1回のみ出現の場合に正しく  228 | if (rsp[j].type === '') { 229 | console.log(head + 'for i' + d + ' in len(' + makerepr(j) + '):') 230 | for (var k = j + 1; k < rsp.length && d !== rsp[k].depth; k++) 231 | if (d + 1 == rsp[k].depth) 232 | rec(k, stk.concat([j])) 233 | }else 234 | if (stk.legnth === 0){ 235 | console.log(head + makerepr(j) + ' = ' + fn[rsp[j].type] + '(' + repr + ')') 236 | }else{ 237 | console.log(head + makerepr(j,stk) + ' = ' + fn[rsp[j].type] + '(' + repr + ')') 238 | } 239 | } 240 | for (var j = 0; j < rsp.length; j++) 241 | if (rsp[j].depth == 0) 242 | rec(j, []) 243 | 244 | 245 | console.log(' return rsp') 246 | // 247 | console.log('') 248 | } 249 | /* 250 | for (var i = 0; i < api.length; i++){ 251 | console.log('=======================================') 252 | console.log(i) 253 | console.log(api[i].name) 254 | console.log(api[i].url[0]) 255 | console.log('=======================================') 256 | 257 | console.log('parameter:') 258 | var prm = api[i].parameter 259 | for (var j = 0; j < prm.length; j++) 260 | console.log(' ' + prm[j].name) 261 | 262 | console.log('response:') 263 | var rsp = api[i].response 264 | for (var j = 0; j < rsp.length; j++){ 265 | var head = new Array(rsp[j].depth + 2).join(' ') 266 | console.log(head + (rsp[j].freq == '1' ? '': '+ ') + rsp[j].name) 267 | } 268 | } 269 | */ 270 | }) 271 | --------------------------------------------------------------------------------