run_tournois.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. /* $Id: run_tournois.c,v 1.6 2001/05/07 02:41:36 kilobug Exp $ */
  2. #include "mclient.h"
  3. #include "tournois.h"
  4. #include <signal.h>
  5. #define ALLOWED_CHARS "_+-$&*!@#~.éáàèëïûôêîìä"
  6. static rt_t *gl_rt;
  7. static void trn_start_new_match(rt_t *rt);
  8. static void trn_display_line(rt_t *rt, const char *buf)
  9. {
  10. GtkAdjustment *adj;
  11. int l;
  12. if (rt->textarea == NULL)
  13. return;
  14. gtk_text_freeze(GTK_TEXT(rt->textarea));
  15. l = gtk_text_get_length(GTK_TEXT(rt->textarea));
  16. l -= 5000;
  17. if (l > 0)
  18. {
  19. while ((GTK_TEXT_INDEX(GTK_TEXT(rt->textarea), l) != '\n') && l > 0)
  20. l--;
  21. if (l > 0)
  22. {
  23. gtk_text_set_point(GTK_TEXT(rt->textarea), 0);
  24. gtk_text_forward_delete(GTK_TEXT(rt->textarea), l);
  25. gtk_text_set_point(GTK_TEXT(rt->textarea),
  26. gtk_text_get_length(GTK_TEXT(rt->textarea)));
  27. }
  28. }
  29. gtk_text_insert(GTK_TEXT(rt->textarea), NULL,
  30. NULL, NULL, buf, -1);
  31. gtk_text_thaw(GTK_TEXT(rt->textarea));
  32. adj = GTK_TEXT(rt->textarea)->vadj;
  33. gtk_adjustment_set_value(adj, adj->upper);
  34. }
  35. static void trn_end(rt_t *rt)
  36. {
  37. int r, i, j, class, class2;
  38. char buf[MYSQL_BUFFER_SIZE];
  39. char *s;
  40. alarm(0);
  41. if (rt->gdki > 0)
  42. {
  43. gdk_input_remove(rt->gdki);
  44. close(rt->fd);
  45. }
  46. rt->gdki = -1;
  47. if (!rt->timeout)
  48. for (i = 0; i < rt->nbp; i++)
  49. if (rt->scores[i] != 0)
  50. {
  51. class2 = class = 1;
  52. for (j = 0; j < rt->nbp; j++)
  53. if (rt->scores[j] > rt->scores[i])
  54. {
  55. class *= 2;
  56. class2++;
  57. }
  58. r = rt->nbp * 100 / class;
  59. mysql_do_query(gl_config->mysql,
  60. "UPDATE Champions "
  61. "SET nbmap=nbmap+1, total=total+%d "
  62. "WHERE id=%d",
  63. r, rt->champ[rt->chmp[i]]);
  64. mysql_do_query(gl_config->mysql,
  65. "UPDATE Champions "
  66. "SET score=total/nbmap, best=GREATEST(best, %f) "
  67. "WHERE id=%d", rt->scores[i],
  68. rt->champ[rt->chmp[i]]);
  69. s = mysql_get_str(gl_config->mysql,
  70. "SELECT login FROM Bitmaps B, Champions C "
  71. "WHERE B.id = C.auteur AND C.id=%d",
  72. rt->champ[rt->chmp[i]]);
  73. g_snprintf(buf, MYSQL_BUFFER_SIZE, "Joueur %s: %f (%d) => %d.\n",
  74. s, rt->scores[i], class2, r);
  75. trn_display_line(rt, buf);
  76. g_free(s);
  77. }
  78. trn_start_new_match(rt);
  79. }
  80. static void sigalarm(int foo)
  81. {
  82. gl_rt->timeout = TRUE;
  83. system("killall server");
  84. fprintf(stderr, "!!!!!!! Timeout.\n");
  85. trn_end(gl_rt);
  86. }
  87. static void nothing(int foo)
  88. {
  89. }
  90. static void trn_check_score(rt_t *rt, const char *buf)
  91. {
  92. int i;
  93. float f;
  94. char *s;
  95. if (strncmp(buf, "<server> Player ", 16))
  96. return;
  97. i = strtol(buf + 16, &s, 10);
  98. s += 3;
  99. f = atof(s);
  100. mysql_do_query(gl_config->mysql,
  101. "INSERT INTO Scores SET champion=%d, score='%f', match_id=%d",
  102. rt->champ[rt->chmp[i - 1]], f, rt->mysql_id);
  103. rt->scores[i - 1] = f;
  104. }
  105. static gboolean trn_treat_line(rt_t *rt, const char *buf)
  106. {
  107. alarm(10);
  108. if (!strcmp(buf, "Bye!\n"))
  109. {
  110. trn_display_line(rt, "\nMatch terminé.\n");
  111. trn_end(rt);
  112. return FALSE;
  113. }
  114. if (strncmp(buf, "<server>", 8))
  115. trn_display_line(rt, buf);
  116. else
  117. trn_check_score(rt, buf);
  118. return TRUE;
  119. }
  120. static void trn_get_data(rt_t *rt, int fd, GdkInputCondition foo)
  121. {
  122. char buf[MYSQL_BUFFER_SIZE], *s, *p;
  123. int sz;
  124. gboolean r;
  125. if (rt == NULL)
  126. return;
  127. sz = read(fd, buf, MYSQL_BUFFER_SIZE - 1);
  128. if (sz == -1)
  129. {
  130. trn_end(rt);
  131. return;
  132. }
  133. buf[sz] = 0;
  134. s = g_strconcat(rt->buf, buf, NULL);
  135. g_free(rt->buf);
  136. rt->buf = s;
  137. while ((p = strchr(rt->buf, '\n')) != NULL)
  138. {
  139. s = rt->buf;
  140. rt->buf = g_strdup(p + 1);
  141. p[1] = 0;
  142. r = trn_treat_line(rt, s);
  143. g_free(s);
  144. if (!r)
  145. break;
  146. }
  147. }
  148. static void trn_do_start_match(rt_t *rt)
  149. {
  150. int i, j;
  151. char buf[11];
  152. char buf2[MYSQL_BUFFER_SIZE];
  153. int fd[2];
  154. char *s, *n, *f;
  155. fprintf(stderr, "\nStarting match %d of %d between: ", rt->cur, rt->nbm);
  156. for (i = 0; i < rt->nbp; i++)
  157. {
  158. fprintf(stderr, "%d ", rt->chmp[i]);
  159. }
  160. fprintf(stderr, "\n");
  161. g_snprintf(buf2, MYSQL_BUFFER_SIZE,
  162. "INSERT INTO Matchs SET map=%d, host='%s', port=%d, statut=1,"
  163. " joueurs=%d, auteur=%d, public=%d",
  164. rt->mapid,
  165. (gl_config->host == NULL) ? gl_config->hostname : gl_config->host,
  166. 4242, rt->nbp, getuid(), FALSE);
  167. mysql_query_gtk(gl_config->mysql, buf2);
  168. rt->mysql_id = mysql_insert_id(gl_config->mysql);
  169. pipe(fd);
  170. if (!fork())
  171. {
  172. g_snprintf(buf, 11, "%d", rt->nbt);
  173. close(1);
  174. dup2(fd[1], 1);
  175. close(fd[0]);
  176. /* Memory leak mais suivi d'un execlp */
  177. s = g_strconcat(gl_config->server, " -n ", buf, " -m ", rt->map, " -q ",
  178. rt->cmd, " ", NULL);
  179. for (i = 0; i < rt->nbp; i++)
  180. {
  181. n = mysql_get_str(gl_config->mysql,
  182. "SELECT nom FROM Champions "
  183. "WHERE id=%d",
  184. rt->champ[rt->chmp[i]]);
  185. for (j = 0; n[j]; j++)
  186. if (!isalnum(n[j]) && (strchr(ALLOWED_CHARS, n[j]) == NULL))
  187. n[j] = '_';
  188. f = mysql_get_str(gl_config->mysql,
  189. "SELECT fichier FROM Champions "
  190. "WHERE id=%d",
  191. rt->champ[rt->chmp[i]]);
  192. if ((n != NULL) && (f != NULL))
  193. s = g_strconcat(s, " ", n, ":", f, NULL);
  194. g_free(n);
  195. g_free(f);
  196. }
  197. sleep(1);
  198. if (gl_config->host == NULL)
  199. execlp("sh", "sh", "-c", s, NULL);
  200. else
  201. execlp("ssh", "ssh", gl_config->host, s, NULL);
  202. _exit(1);
  203. }
  204. close(fd[1]);
  205. fcntl(fd[0], F_SETFL, O_NONBLOCK);
  206. for (i = 0; i < rt->nbp; i++)
  207. rt->scores[i] = 0;
  208. rt->fd = fd[0];
  209. rt->gdki = gdk_input_add(fd[0], GDK_INPUT_READ,
  210. (GdkInputFunction) (trn_get_data), rt);
  211. alarm(20);
  212. }
  213. typedef struct _trn_comb_t
  214. {
  215. int *max_allowed;
  216. int *cnt;
  217. } trn_comb_t;
  218. typedef struct _trn_rand_t
  219. {
  220. int *cnt;
  221. } trn_rand_t;
  222. static void trn_make_rand(rt_t *rt)
  223. {
  224. int i;
  225. int max;
  226. trn_rand_t *randd;
  227. randd = rt->data;
  228. max = rt->nbm * rt->nbp / rt->nbc + 1;
  229. for (i = 0; i < rt->nbp; i++)
  230. {
  231. do
  232. rt->chmp[i] = random() % rt->nbc;
  233. while (randd->cnt[rt->chmp[i]] >= max);
  234. randd->cnt[rt->chmp[i]]++;
  235. }
  236. }
  237. static void trn_make_comb(rt_t *rt)
  238. {
  239. trn_comb_t *comb;
  240. int j, i;
  241. comb = rt->data;
  242. for (i = 0; i < rt->nbp; i++)
  243. rt->chmp[i] = comb->cnt[i];
  244. for (j = rt->nbp - 1; j > 0; j--)
  245. if (comb->cnt[j] < comb->max_allowed[j])
  246. break;
  247. comb->cnt[j]++;
  248. if (comb->cnt[j] > comb->max_allowed[j])
  249. for (i = 0; i < rt->nbp; i++)
  250. comb->cnt[i] = i;
  251. else
  252. for (j++; j < rt->nbp - 1; j++)
  253. comb->cnt[j] = comb->cnt[j - 1] + 1;
  254. }
  255. static void trn_start_new_match(rt_t *rt)
  256. {
  257. if (rt->cur >= rt->nbm)
  258. {
  259. trn_display_line(rt, "\nTournois terminé.\n");
  260. rt->run = FALSE;
  261. trn_free(rt);
  262. return;
  263. }
  264. rt->timeout = FALSE;
  265. gl_rt = rt;
  266. rt->cur++;
  267. switch (rt->methode)
  268. {
  269. case met_rand:
  270. trn_make_rand(rt);
  271. break;
  272. case met_comb:
  273. trn_make_comb(rt);
  274. break;
  275. case met_pyr:
  276. trn_make_rand(rt);
  277. break;
  278. case met_rot:
  279. trn_make_rand(rt);
  280. break;
  281. default:
  282. fprintf(stderr, "Internal error in trn_init. Aborting.\n");
  283. exit(1);
  284. break;
  285. }
  286. trn_do_start_match(rt);
  287. }
  288. void trn_init(rt_t *rt)
  289. {
  290. int i;
  291. trn_comb_t *comb;
  292. trn_rand_t *rand;
  293. switch (rt->methode)
  294. {
  295. case met_rand:
  296. rt->data = rand = g_malloc(sizeof(*rand));
  297. rand->cnt = g_malloc(sizeof(int) * rt->nbc);
  298. bzero(rand->cnt, sizeof(int) * rt->nbc);
  299. break;
  300. case met_pyr:
  301. case met_rot:
  302. rt->data = NULL;
  303. break;
  304. case met_comb:
  305. rt->data = comb = g_malloc(sizeof(*comb));
  306. comb->cnt = g_malloc(sizeof(int) * rt->nbp);
  307. comb->max_allowed = g_malloc(sizeof(int) * rt->nbp);
  308. for (i = 0; i < rt->nbp; i++)
  309. {
  310. comb->cnt[i] = i;
  311. comb->max_allowed[i] = rt->nbc - (rt->nbp - i);
  312. }
  313. break;
  314. default:
  315. fprintf(stderr, "Internal error in trn_init. Aborting.\n");
  316. exit(1);
  317. break;
  318. }
  319. rt->gdki = -1;
  320. gl_rt = rt;
  321. signal(SIGALRM, sigalarm);
  322. trn_start_new_match(rt);
  323. }
  324. void trn_free(rt_t *rt)
  325. {
  326. trn_comb_t *comb;
  327. trn_rand_t *rand;
  328. if (rt->run || rt->disp)
  329. return;
  330. switch (rt->methode)
  331. {
  332. case met_rand:
  333. rand = rt->data;
  334. g_free(rand->cnt);
  335. g_free(rand);
  336. break;
  337. case met_pyr:
  338. case met_rot:
  339. break;
  340. case met_comb:
  341. comb = rt->data;
  342. g_free(comb->cnt);
  343. g_free(comb->max_allowed);
  344. g_free(comb);
  345. break;
  346. default:
  347. fprintf(stderr, "Internal error in trn_init. Aborting.\n");
  348. exit(1);
  349. break;
  350. }
  351. g_free(rt->cmd);
  352. g_free(rt->chmp);
  353. g_free(rt->map);
  354. if (rt->buf != NULL)
  355. g_free(rt->buf);
  356. g_free(rt->scores);
  357. g_free(rt);
  358. }