PageRenderTime 26ms CodeModel.GetById 35ms RepoModel.GetById 0ms app.codeStats 0ms

/manager/manager.cpp

https://github.com/luizribeiro/smaco.old
C++ | 421 lines | 351 code | 43 blank | 27 comment | 117 complexity | fb422949c0c182441d51532b5be926b1 MD5 | raw file
  1. #include <algorithm>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cstring>
  5. #include <curl/curl.h>
  6. #include <curl/types.h>
  7. #include <curl/easy.h>
  8. #include <map>
  9. #include <mysql.h>
  10. #include <set>
  11. #include <string>
  12. #include <unistd.h>
  13. using namespace std;
  14. /* MYSQL {{{ */
  15. #define NR(x) mysql_fetch_row(x)
  16. const char *host = "home.luizribeiro.org";
  17. const char *user = "smaco";
  18. const char *pwd = "senha";
  19. const char *database = "smaco";
  20. MYSQL mysql, *conn;
  21. MYSQL_RES* query(const char *q){
  22. int q_st = mysql_query(conn, q);
  23. MYSQL_RES * r;
  24. if(q_st) return NULL;
  25. r = mysql_store_result(conn);
  26. return r;
  27. }
  28. bool connect(){
  29. mysql_init(&mysql);
  30. conn = mysql_real_connect(&mysql, host, user, pwd, database, 0, 0, 0);
  31. if(conn != NULL) query("SET SESSION time_zone = '+0:00';");
  32. return conn != NULL;
  33. }
  34. string itos(int k){
  35. string s;
  36. do {
  37. s += (char)(k % 10 + '0');
  38. k /= 10;
  39. } while(k);
  40. reverse(s.begin(), s.end());
  41. return s;
  42. }
  43. MYSQL_RES* get_ids(int jid, int cid){
  44. string q = string("SELECT id FROM userids WHERE EXISTS(") +
  45. string("SELECT uid FROM users WHERE EXISTS(") +
  46. string("SELECT uid FROM participates WHERE EXISTS(") +
  47. string("SELECT contestid FROM running_contests AS rc") +
  48. string(" WHERE rc.contestid = participates.contestid") +
  49. string(" AND participates.uid = users.uid AND") +
  50. string(" users.uid = userids.uid AND userids.judgeid = ") +
  51. itos(jid) + string(" AND rc.contestid = ") + itos(cid) +
  52. string(")))");
  53. return query(q.c_str());
  54. }
  55. MYSQL_RES* get_probs(string cid, string jid){
  56. string p = string("SELECT problemid FROM problems, running_contests WHERE ") +
  57. string("problems.contestid = running_contests.contestid AND ") +
  58. string("problems.contestid = ") + cid +
  59. string(" AND running_contests.judgeid = ") + jid;
  60. return query(p.c_str());
  61. }
  62. int get_judgeid(int cid){
  63. string c = "select judgeid from running_contests where contestid = " +
  64. itos(cid);
  65. MYSQL_RES * jnum_q = query(c.c_str());
  66. MYSQL_ROW jnum_r = NR(jnum_q);
  67. return atoi(jnum_r[0]);
  68. }
  69. int get_uid(string uid, string judgeid){
  70. string c = "select uid from userids where id = " + uid +
  71. " AND judgeid = " + judgeid;
  72. MYSQL_RES * unum_q = query(c.c_str());
  73. MYSQL_ROW unum_r = NR(unum_q);
  74. return atoi(unum_r[0]);
  75. }
  76. int get_pid(string pid, string cid){
  77. string c = "select pid from problems where problemid = " + pid +
  78. " AND contestid = " + cid;
  79. MYSQL_RES * pnum_q = query(c.c_str());
  80. MYSQL_ROW pnum_r = NR(pnum_q);
  81. return atoi(pnum_r[0]);
  82. }
  83. /* }}} */
  84. /* PARSER {{{1 */
  85. #define CURL_STATICLIB
  86. #define IN getc( stdin )
  87. bool spec[128];
  88. char line[2048];
  89. char part[256];
  90. FILE *stt;
  91. const char *url[2] = {
  92. "http://acmicpc-live-archive.uva.es/nuevoportal/status.php",
  93. "http://uva.onlinejudge.org/index.php?option=onlinejudge&Itemid=19"
  94. };
  95. void adapt(){
  96. for(char *p = part; *p; ++p) *p = tolower(*p);
  97. if(!strcmp(part,"accepted")) strcpy(part, "AC");
  98. else if(!strcmp(part, "wrong answer")) strcpy(part, "WA");
  99. else if(!strcmp(part, "time limit exceeded")) strcpy(part, "TL");
  100. else if(!strcmp(part, "runtime error")) strcpy(part, "RE");
  101. else if(!strcmp(part, "presentation error")) strcpy(part, "PE");
  102. else if(!strcmp(part, "compile error")) strcpy(part, "CE");
  103. else if(!strcmp(part, "compilation error")) strcpy(part, "CE");
  104. else if(!strcmp(part, "restricted function")) strcpy(part, "RF");
  105. else if(!strcmp(part, "memory limit exceeded")) strcpy(part, "ML");
  106. else if(!strcmp(part, "output limit exceeded")) strcpy(part, "OL");
  107. else strcpy(part, "IG");
  108. }
  109. /* Live Archive Parser {{{2 */
  110. void parseLA(){
  111. bool y[15] = {0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0};
  112. int ic;
  113. for(int k = 0; k < 28; ++k) fgets(line, 2048, stdin);
  114. register char c;
  115. for(int i = 0; i < 25; ++i){
  116. ic = 0;
  117. for(int cnt = 0; cnt < 15; ++cnt){
  118. while(IN != '<');
  119. if(!cnt && (c = IN) == '/') goto out;
  120. else ungetc(c, stdin);
  121. while(IN != '>');
  122. char *p = part;
  123. if(y[cnt]) {
  124. for(c = IN; c != EOF && c != '<'; c = IN){
  125. if(c == '&') {
  126. while(IN != ';');
  127. c = IN;
  128. }
  129. if(spec[c]) continue;
  130. *p++ = c;
  131. }
  132. *p = 0;
  133. if(ic == 2) adapt();
  134. if(ic) fputc('\t', stt);
  135. fprintf(stt, "%s", part);
  136. ic++;
  137. } else while(IN != '<');
  138. ungetc('<', stdin);
  139. }
  140. fputc(10, stt);
  141. }
  142. out:
  143. while(fgets(line, 2048, stdin));
  144. }
  145. /* }}}2 */
  146. /* UVa Parser {{{2 */
  147. void parseUVA(){
  148. bool y[25];
  149. for(int i = 0; i < 25; ++i) y[i] = 0;
  150. y[1] = y[4] = y[15] = y[17] = y[19] = y[22] = 1;
  151. for(int i = 0; i < 231; ++i) fgets(line, 2048, stdin);
  152. int ic, k;
  153. register char c;
  154. for(int i = 0; i < 50; ++i){
  155. ic = 0;
  156. for(int cnt = 0; cnt < 25; ++cnt){
  157. char *p = part;
  158. while(IN != '<');
  159. if(cnt != 12) {
  160. for(c = IN, k = 1; ; c = IN){
  161. k += (c == '<');
  162. k -= (c == '>');
  163. if(!k) break;
  164. }
  165. } else {
  166. for(c = IN; !isdigit(c); c = IN);
  167. while(isdigit(c)) *p++ = c, c = IN;
  168. *p = 0;
  169. fprintf(stt, "\t%5s", part);
  170. }
  171. if(y[cnt]) {
  172. for(c = IN; c != EOF && c != '<'; c = IN){
  173. if(c == '&') {
  174. while(IN != ';');
  175. c = IN;
  176. }
  177. if(spec[c]) continue;
  178. *p++ = c;
  179. }
  180. *p = 0;
  181. if(ic == 2) adapt();
  182. if(ic == 3)
  183. if(!strcmp(part, "ANSI C")) strcpy(part,"C");
  184. if(ic) fputc('\t', stt);
  185. fprintf(stt, "%5s", part);
  186. ic++;
  187. } else while(IN != '<');
  188. ungetc('<', stdin);
  189. }
  190. fputc(10, stt);
  191. }
  192. while(fgets(line, 2048, stdin));
  193. }
  194. /* }}}2 */
  195. size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream) {
  196. size_t written;
  197. written = fwrite(ptr, size, nmemb, stream);
  198. return written;
  199. }
  200. void parse(int judge){
  201. CURL *curl;
  202. FILE *fp;
  203. CURLcode res;
  204. curl = curl_easy_init();
  205. if (curl) {
  206. fp = fopen("status","wb");
  207. curl_easy_setopt(curl, CURLOPT_URL, url[judge]);
  208. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
  209. curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
  210. res = curl_easy_perform(curl);
  211. curl_easy_cleanup(curl);
  212. fclose(fp);
  213. }
  214. freopen("status", "r", stdin);
  215. stt = fopen("parsed.txt","wb");
  216. printf("Parsing...");
  217. switch(judge){
  218. case 0: parseLA(); break;
  219. case 1: parseUVA(); break;
  220. }
  221. printf("DONE\n");
  222. fclose(stt);
  223. }
  224. void init_parser(){
  225. for(int i = 0; i < 128; ++i) spec[i] = 0;
  226. spec['\t'] = spec['\n'] = 1;
  227. }
  228. /* }}} */
  229. /* UPDATE {{{1 */
  230. const char *judge_name[2] = {"Live Archive", "UVa"};
  231. int pid, sid, uid;
  232. char ans[8], day[16], hour[16], lang[8], runtime[16];
  233. set < int > s, u;
  234. string jla = string("0"), juva = string("1");
  235. void insert_ids(int jid, int cid){
  236. u.clear();
  237. MYSQL_RES * ids = get_ids(jid, cid);
  238. if(ids == NULL) {
  239. printf("FAIL: Getting contestants id's.\n");
  240. return;
  241. }
  242. MYSQL_ROW id = NR(ids);
  243. if(id != NULL){
  244. printf("Contestants: [");
  245. while(id != NULL){
  246. printf(" %d",atoi(id[0]));
  247. u.insert(atoi(id[0]));
  248. id = NR(ids);
  249. if(id != NULL) putc(',', stdout);
  250. else putc(32, stdout);
  251. }
  252. printf("]\n");
  253. } else printf("No contestants.\n");
  254. mysql_free_result(ids);
  255. }
  256. void insert_probs(int jid, int cid){
  257. s.clear();
  258. MYSQL_RES * probs = get_probs(itos(cid), itos(jid));
  259. if(probs == NULL) {
  260. printf("FAIL: Selecting problems\n");
  261. return;
  262. }
  263. MYSQL_ROW r = NR(probs);
  264. if(r != NULL){
  265. printf("Problems [");
  266. while(r != NULL){
  267. printf(" %d", atoi(r[0]));
  268. s.insert(atoi(r[0]));
  269. r = NR(probs);
  270. if(r != NULL) putc(',', stdout);
  271. else putc(32, stdout);
  272. }
  273. printf("]\n");
  274. } else printf("No problems.\n");
  275. mysql_free_result(probs);
  276. }
  277. void insert_run(string jid, string cid){
  278. if(!strcmp(ans,"IG") || s.find(pid) == s.end() || u.find(uid) == u.end())
  279. return;
  280. printf("Inserting run %d by %d, prob %d (%s)\n", sid, uid, pid, ans);
  281. int pn = get_pid(itos(pid), cid);
  282. int un = get_uid(itos(uid), jid);
  283. /* Insere a submissao no BD */
  284. string cmd = string("insert into runs (runid, judgeid, uid, ") +
  285. string("pid, date, answer, runtime, language) VALUES (")
  286. + itos(sid) + ", " + jid + ", " + itos(un) + ", " +
  287. itos(pn) + ", '" + string(day) + " " + string(hour) +
  288. "', '" + string(ans) + "', " + string(runtime)
  289. + ", '" + string(lang) + "');";
  290. #ifdef DEBUG_INSERT_RUN
  291. printf("Command (%s)\n", cmd.c_str());
  292. #endif
  293. query(cmd.c_str());
  294. }
  295. /* Live Archive update RUNS {{{2 */
  296. void updateLA(int cid){
  297. string _cid = itos(cid);
  298. while(scanf("%d %s %s %s %s %d %s %d", &sid, day, hour, ans,
  299. runtime, &uid, lang, &pid) != EOF){
  300. insert_run(jla, _cid);
  301. }
  302. }
  303. /* }}}2 */
  304. /* UVa update RUNS {{{2 */
  305. void updateUVa(int cid){
  306. string _cid = itos(cid);
  307. while(scanf("%d %d %d %s %s %s %s %s", &sid, &pid, &uid, ans,
  308. lang, runtime, day, hour) != EOF){
  309. insert_run(juva, _cid);
  310. }
  311. }
  312. /* }}}2 */
  313. void update(int judge, int cid){
  314. printf("[%s]\n", judge_name[judge]);
  315. insert_ids(judge, cid);
  316. insert_probs(judge, cid);
  317. freopen("parsed.txt", "r", stdin);
  318. switch(judge){
  319. case 0: updateLA(cid); break;
  320. case 1: updateUVa(cid); break;
  321. }
  322. }
  323. /* }}}1 */
  324. /* SCORE {{{ */
  325. void score(int jid, int cid){
  326. /* Mapeia um id para 0 <= x <= N -> numero de participantes */
  327. map < int , int > m;
  328. int uc = 0;
  329. string q;
  330. }
  331. /* }}} */
  332. /* main {{{ */
  333. set < int > was, is;
  334. int main(void){
  335. if(!connect()){
  336. printf("FATAL: Couldn't connect\n");
  337. return 0;
  338. }
  339. init_parser();
  340. while(1){
  341. /* 5 segundos sem fazer nada */
  342. sleep(5);
  343. /* Verifica se algum contest esta rodando */
  344. MYSQL_RES * res = query("SELECT judgeid, nome, contestid FROM running_contests");
  345. if(res == NULL){
  346. printf("FAIL: selecting from running_contests\n");
  347. continue;
  348. }
  349. MYSQL_ROW r = NR(res);
  350. if(r == NULL) printf("No running contests.\n");
  351. /* Tem pelo menos um contest rodando */
  352. is.clear();
  353. while(r != NULL){
  354. printf("\n~~~~~~~~~~ \"%s\" ~~~~~~~~~~\n\n", r[1]);
  355. /* Pega o judgeid e o contestid */
  356. int j_id = atoi(r[0]), c_id = atoi(r[2]);
  357. is.insert(c_id);
  358. /* Roda o parser */
  359. parse(j_id);
  360. /* Interpreta a saida do parser e atualiza runs */
  361. update(j_id, c_id);
  362. r = NR(res);
  363. }
  364. for(set < int > :: iterator it = was.begin(); it != was.end(); it++)
  365. if(is.find(*it) == is.end()){
  366. printf("Contest %d just ended\n", *it);
  367. int judge = get_judgeid(*it);
  368. score(judge, *it);
  369. }
  370. was.clear();
  371. for(set < int > :: iterator it = is.begin(); it != is.end(); it++)
  372. was.insert(*it);
  373. /* Libera a memoria utilizada pela query */
  374. mysql_free_result(res);
  375. }
  376. return 0;
  377. }
  378. /* }}} */