Ejemplo n.º 1
0
static int
print_banner_page(const serve_state_t state,
                  const unsigned char *banner_path, int run_id,
                  int user_id, int is_privileged)
{
  struct run_entry info;
  FILE *f = 0;
  time_t start_time;
  unsigned char *s;
  int i, variant, virt_variant;
  struct teamdb_export teaminfo;

  if (run_id < 0 || run_id >= run_get_total(state->runlog_state)) goto cleanup;
  run_get_entry(state->runlog_state, run_id, &info);
  if (info.status == RUN_VIRTUAL_START
      || info.status == RUN_VIRTUAL_STOP
      || info.status == RUN_EMPTY) {
    return -1;
  }
  if (teamdb_export_team(state->teamdb_state, info.user_id, &teaminfo) < 0)
    return -1;
  start_time = run_get_start_time(state->runlog_state);

  if (!(f = fopen(banner_path, "w"))) goto cleanup;
  fprintf(f, "\n\n\n\n\n\n\n\n\n\n");
  fprintf(f, "Run ID:           %d\n", info.run_id);
  fprintf(f, "Submission time:  %s\n",
          duration_str(1, info.time, start_time, 0, 0));
  fprintf(f, "Contest time:     %s\n",
          duration_str(0, info.time, start_time, 0, 0));
  if (is_privileged) {
    fprintf(f, "Originator IP:    %s\n", xml_unparse_ip(info.a.ip));
  }
  fprintf(f, "Size:             %u\n", info.size);
  if (is_privileged) {
    fprintf(f, "Hash code (SHA1): ");
    s = (unsigned char *) &info.sha1;
    for (i = 0; i < 20; i++) fprintf(f, "%02x", *s++);
    fprintf(f, "\n");
  }
  fprintf(f, "User ID:          %d\n", info.user_id);
  fprintf(f, "User login:       %s\n", teamdb_get_login(state->teamdb_state,
                                                        info.user_id));
  fprintf(f, "User name:        %s\n", teamdb_get_name(state->teamdb_state,
                                                       info.user_id));
  fprintf(f, "Problem:          %s\n", state->probs[info.prob_id]->short_name);
  if (state->probs[info.prob_id]->variant_num > 0) {
    variant = info.variant;
    if (!variant) {
      variant = find_variant(state, info.user_id, info.prob_id,
                             &virt_variant);
    }
    if (is_privileged && virt_variant != variant) {
      fprintf(f, "Variant:          %d (%d)\n", virt_variant, variant);
    } else {
      fprintf(f, "Variant:          %d\n", virt_variant);
    }
  }
  fprintf(f, "Language:         %s\n",
          (state->langs[info.lang_id])?((char*)state->langs[info.lang_id]->short_name):"");
  if (teaminfo.user && teaminfo.user->cnts0 && teaminfo.user->cnts0->location) {
    fprintf(f, "Location:         %s\n", teaminfo.user->cnts0->location);
  }
  fprintf(f, "Status:           %s\n", run_status_str(info.status, 0, 0, 0, 0));
  fclose(f);

  return 0;

 cleanup:
  if (f) fclose(f);
  return -1;
}
Ejemplo n.º 2
0
static int
do_print_run(const serve_state_t state, int run_id,
             int is_privileged, int user_id)
{
  const struct section_global_data *global = state->global;
  unsigned char *banner_path = 0;
  unsigned char *ps_path = 0;
  unsigned char *log_path = 0;
  unsigned char *sfx = "";
  int arch_flags = 0, pages_num = -1, x, i;
  path_t run_arch;
  struct run_entry info;
  tpTask tsk = 0;
  unsigned char in_buf[1024];
  size_t in_buf_len;
  FILE *f = 0;
  int errcode = -SRV_ERR_SYSTEM_ERROR;
  struct teamdb_export teaminfo;
  const unsigned char *printer_name = 0, *user_name = 0, *location = 0;
  const struct userlist_user_info *ui = 0;
  unsigned char program_path[PATH_MAX];

  program_path[0] = 0;

  if (run_id < 0 || run_id >= run_get_total(state->runlog_state)) {
    errcode = -SRV_ERR_BAD_RUN_ID;
    goto cleanup;
  }
  run_get_entry(state->runlog_state, run_id, &info);
  if (info.status == RUN_VIRTUAL_START
      || info.status == RUN_VIRTUAL_STOP
      || info.status == RUN_EMPTY) {
    errcode = -SRV_ERR_BAD_RUN_ID;
    goto cleanup;
  }
  if (!is_privileged) {
    if (info.user_id != user_id) {
      errcode = -SRV_ERR_NO_PERMS;
      goto cleanup;
    }
    if (!global->enable_printing) {
      errcode = -SRV_ERR_NO_PERMS;
      goto cleanup;
    }
    if (info.pages > 0) {
      errcode = -SRV_ERR_ALREADY_PRINTED;
      goto cleanup;
    }
  }

  if (teamdb_export_team(state->teamdb_state, info.user_id, &teaminfo) < 0)
    return -1;
  if (teaminfo.user) ui = teaminfo.user->cnts0;

  if (!is_privileged) {
    if (ui && ui->printer_name)
      printer_name = ui->printer_name;
  }

  if (global->disable_banner_page <= 0) {
    banner_path = (unsigned char*) alloca(strlen(global->print_work_dir) + 64);
    sprintf(banner_path, "%s/%06d.txt", global->print_work_dir, run_id);
    if (print_banner_page(state, banner_path, run_id, user_id,
                          is_privileged) < 0) {
      goto cleanup;
    }
  }

  if (global->disable_banner_page > 0) {
    if (state->langs[info.lang_id]) sfx = state->langs[info.lang_id]->src_sfx;
    if (global->printout_uses_login > 0) {
      user_name = teamdb_get_login(state->teamdb_state, info.user_id);
    } else {
      user_name = teamdb_get_name_2(state->teamdb_state, info.user_id);
    }
    if (!user_name) user_name = "";
    location = "";
    if (ui && ui->location)
      location = ui->location;
    unsigned char fixed_user_name[PATH_MAX];
    unsigned char fixed_location[PATH_MAX];
    fix_path_component(fixed_user_name, sizeof(fixed_user_name), user_name);
    fix_path_component(fixed_location, sizeof(fixed_location), location);

    snprintf(program_path, sizeof(program_path),
             "%s/%06d_%s_%s%s", global->print_work_dir, run_id,
             fixed_user_name, fixed_location, sfx);
  } else {
    if (state->langs[info.lang_id]) sfx = state->langs[info.lang_id]->src_sfx;
    snprintf(program_path, sizeof(program_path),
             "%s/%06d%s", global->print_work_dir, run_id, sfx);
  }

  arch_flags = serve_make_source_read_path(state, run_arch, sizeof(run_arch), &info);
  if (arch_flags < 0) {
    goto cleanup;
  }
  if (generic_copy_file(arch_flags, 0, run_arch, "", 0, 0, program_path, 0) < 0) {
    goto cleanup;
  }

  ps_path = (unsigned char*) alloca(strlen(global->print_work_dir) + 64);
  sprintf(ps_path, "%s/%06d.ps", global->print_work_dir, run_id);

  log_path = (unsigned char*) alloca(strlen(global->print_work_dir) + 64);
  sprintf(log_path, "%s/%06d.out", global->print_work_dir, run_id);

  if (!(tsk = task_New())) goto cleanup;
  task_AddArg(tsk, global->a2ps_path);
  if (global->a2ps_args) {
    for (i = 0; global->a2ps_args[i]; i++)
      task_AddArg(tsk, global->a2ps_args[i]);
  } else {
    task_AddArg(tsk, "-1");
    task_AddArg(tsk, "-E");
    /*
    task_AddArg(tsk, "-X");
    task_AddArg(tsk, "koi8-r");
    */
  }
  task_AddArg(tsk, "-o");
  task_AddArg(tsk, ps_path);
  if (global->disable_banner_page <= 0) {
    task_AddArg(tsk, banner_path);
  }
  task_AddArg(tsk, program_path);
  task_SetPathAsArg0(tsk);
  task_SetRedir(tsk, 2, TSR_FILE, log_path, O_WRONLY|O_CREAT|O_TRUNC, 0777);
  task_ClearEnv(tsk);
  if (task_Start(tsk) < 0) goto cleanup;
  task_Wait(tsk);
  task_Delete(tsk);
  tsk = 0;

  if (!(f = fopen(log_path, "r"))) goto cleanup;
  while (fgets(in_buf, sizeof(in_buf), f)) {
    in_buf_len = strlen(in_buf);
    if (in_buf_len > sizeof(in_buf) - 5) continue;
    if (!strncmp(in_buf, "[Total:", 7)) {
      if (sscanf(in_buf, "[Total: %d pages", &x) == 1 && x >= 1 && x < 100000) {
        pages_num = x;
        break;
      } 
    }
  }
  fclose(f);
  f = 0;
  if (pages_num <= 0) goto cleanup;

  if (!is_privileged) {
    if (pages_num + run_get_total_pages(state->runlog_state, info.user_id) > global->team_page_quota) {
      errcode = -SRV_ERR_PAGES_QUOTA;
      goto cleanup;
    }
    run_set_pages(state->runlog_state, run_id, pages_num);
  }

  if (!(tsk = task_New())) goto cleanup;
  task_AddArg(tsk, global->lpr_path);
  if (global->lpr_args) {
    for (i = 0; global->lpr_args[i]; i++)
      task_AddArg(tsk, global->lpr_args[i]);
  }
  if (printer_name) {
    task_AddArg(tsk, "-P");
    task_AddArg(tsk, printer_name);
  }
  task_AddArg(tsk, ps_path);
  task_SetPathAsArg0(tsk);
  if (task_Start(tsk) < 0) goto cleanup;
  task_Wait(tsk);
  task_Delete(tsk); tsk = 0;

  unlink(banner_path);
  unlink(program_path);
  unlink(ps_path);
  unlink(log_path);
  return pages_num;

 cleanup:
  if (tsk) task_Delete(tsk);
  if (banner_path) unlink(banner_path);
  if (program_path[0]) unlink(program_path);
  if (ps_path) unlink(ps_path);
  if (log_path) unlink(log_path);
  return errcode;
}
Ejemplo n.º 3
0
int
find_variant(
        const serve_state_t state,
        int user_id,
        int prob_id,
        int *p_virtual_variant)
{
  int i, new_vint;
  struct variant_map *pmap = state->global->variant_map;
  struct variant_map_item *vi;
  const struct section_problem_data *prob = NULL;

  if (!pmap) return 0;
  if (prob_id <= 0 || prob_id > state->max_prob || !(prob = state->probs[prob_id])) return 0;
  if (prob->variant_num <= 0) return 0;
  if (!pmap->prob_map[prob_id]) return 0;

  teamdb_refresh(state->teamdb_state);
  new_vint = teamdb_get_vintage(state->teamdb_state);
  if (new_vint != pmap->vintage || !pmap->user_map_size || !pmap->user_map) {
    info("find_variant: new vintage: %d, old: %d, updating variant map",
         new_vint, pmap->vintage);
    xfree(pmap->user_map);
    pmap->user_map_size = 0;
    pmap->user_map = 0;

    if (state->global->disable_user_database > 0) {
      pmap->user_map_size = run_get_max_user_id(state->runlog_state) + 1;
    } else {
      pmap->user_map_size = teamdb_get_max_team_id(state->teamdb_state) + 1;
    }
    XCALLOC(pmap->user_map, pmap->user_map_size);

    for (i = 0; i < pmap->u; i++) {
      pmap->v[i].user_id = teamdb_lookup_login(state->teamdb_state, pmap->v[i].login);
      if (pmap->v[i].user_id < 0) pmap->v[i].user_id = 0;
      if (!pmap->v[i].user_id) continue;
      if (pmap->v[i].user_id >= pmap->user_map_size) continue;
      pmap->user_map[pmap->v[i].user_id] = &pmap->v[i];
    }
    pmap->vintage = new_vint;
  }

  if (user_id <= 0 || user_id >= pmap->user_map_size) return 0;
  if ((vi = pmap->user_map[user_id])) {
    if (vi->real_variant) {
      if (p_virtual_variant) {
        if (vi->virtual_variant) *p_virtual_variant = vi->virtual_variant;
        else *p_virtual_variant = vi->real_variant;
      }
      // safety check
      if (vi->real_variant < 0 || vi->real_variant > prob->variant_num)
        return 0;
      return vi->real_variant;
    }
    if (p_virtual_variant)
      *p_virtual_variant = vi->variants[pmap->prob_map[prob_id]];
    int v = vi->variants[pmap->prob_map[prob_id]];
    if (!v && prob->autoassign_variants > 0) {
      v = random_range(1, prob->variant_num + 1);
      variant_map_set_variant(pmap, user_id,
                              teamdb_get_login(state->teamdb_state, user_id),
                              prob_id,
                              v);
      // FIXME: handle errors
      variant_map_save(stderr, pmap, state->global->variant_map_file, 1);
    }
    if (v < 0 || v > prob->variant_num)
      return 0;
    return v;
  } else if (prob->autoassign_variants > 0) {
    int v = random_range(1, prob->variant_num + 1);
    variant_map_set_variant(pmap, user_id,
                            teamdb_get_login(state->teamdb_state, user_id),
                            prob_id,
                            v);
    // FIXME: handle errors
    variant_map_save(stderr, pmap, state->global->variant_map_file, 1);
    if (v < 0 || v > prob->variant_num)
      return 0;
    return v;
  }
  return 0;
}
Ejemplo n.º 4
0
void
generate_daily_statistics(
        const struct contest_desc *cnts,
        const serve_state_t state,
        FILE *f,
        time_t from_time,
        time_t to_time,
        int utf8_mode)
{
  int u_max, u_tot;
  int *u_ind, *u_rev;
  int p_max, p_tot, i, j;
  int *p_ind, *p_rev;
  int row_sz, row_sh;
  unsigned char *solved = 0;
  int r_tot, u, p, idx, max_u_total;
  const struct run_entry *runs, *rcur;
  int *u_total = 0, *u_ok = 0, *u_failed = 0, *u_afterok = 0, *u_errors = 0;
  int *u_trans = 0, *u_cf = 0, *u_ac = 0, *u_ign = 0, *u_disq = 0, *u_pend = 0;
  int *u_ce = 0, *u_sort = 0;
  int *l_total = 0, *l_ok = 0, *l_ce = 0;
  int *p_total = 0, *p_ok = 0;
  unsigned char *u_reg = 0;
  struct teamdb_export uinfo;
  int *sort_num, *sort_idx;

  int total_empty = 0;
  int total_errors = 0;
  int total_status[128];
  int total_pseudo = 0;
  int total_afterok = 0;
  int total_trans = 0;
  int total_ok = 0;
  int total_failed = 0;
  int total_cf = 0;
  int total_ac = 0;
  int total_ign = 0;
  int total_disq = 0;
  int total_pend = 0;
  int total_ce = 0;
  int total_reg = 0;
  int total_runs = 0;
  int w, y;

  unsigned char *login, *name, probname[256], langname[256];

  int clar_total = 0, clar_total_today = 0, clar_from_judges = 0;
  int clar_to_judges = 0;
  time_t clar_time;
  struct clar_entry_v2 clar;

  /* u_tot             - total number of teams in index array
   * u_max             - maximal possible number of teams
   * u_ind[0..u_tot-1] - index array:   team_idx -> team_id
   * u_rev[0..u_max-1] - reverse index: team_id -> team_idx
   */
  if (state->global->disable_user_database > 0) {
    u_max = run_get_max_user_id(state->runlog_state) + 1;
  } else {
    u_max = teamdb_get_max_team_id(state->teamdb_state) + 1;
  }
  XALLOCAZ(u_ind, u_max);
  XALLOCAZ(u_rev, u_max);
  XALLOCAZ(u_reg, u_max);
  for (i = 1, u_tot = 0; i < u_max; i++) {
    u_rev[i] = -1;
    if (teamdb_lookup(state->teamdb_state, i)
        && teamdb_export_team(state->teamdb_state, i, &uinfo) >= 0) {
      if (is_registered_today(cnts, uinfo.user, from_time, to_time)) {
        total_reg++;
        u_reg[u_tot] = 1;
      }
      u_rev[i] = u_tot;
      u_ind[u_tot++] = i;
    }
  }

  /* p_tot             - total number of problems in index array
   * p_max             - maximal possible number of problems
   * p_ind[0..p_tot-1] - index array:   prob_idx -> prob_id
   * p_rev[0..p_max-1] - reverse index: prob_id -> prob_idx
   */
  p_max = state->max_prob + 1;
  XALLOCAZ(p_ind, p_max);
  XALLOCAZ(p_rev, p_max);
  for (i = 1, p_tot = 0; i < p_max; i++) {
    p_rev[i] = -1;
    if (state->probs[i]) {
      p_rev[i] = p_tot;
      p_ind[p_tot++] = i;
    }
  }

  r_tot = run_get_total(state->runlog_state);
  runs = run_get_entries_ptr(state->runlog_state);

  if (!u_tot || !p_tot || !r_tot) return;

  /* calculate the power of 2 not less than p_tot */
  for (row_sz = 1, row_sh = 0; row_sz < p_tot; row_sz <<= 1, row_sh++);
  /* all two-dimensional arrays will have rows of size row_sz */

  XCALLOC(solved, row_sz * u_tot);
  memset(total_status, 0, sizeof(total_status));
  XALLOCAZ(u_total, u_tot);
  XALLOCAZ(u_ok, u_tot);
  XALLOCAZ(u_failed, u_tot);
  XALLOCAZ(u_afterok, u_tot);
  XALLOCAZ(u_errors, u_tot);
  XALLOCAZ(u_trans, u_tot);
  XALLOCAZ(u_cf, u_tot);
  XALLOCAZ(u_ac, u_tot);
  XALLOCAZ(u_ign, u_tot);
  XALLOCAZ(u_disq, u_tot);
  XALLOCAZ(u_pend, u_tot);
  XALLOCAZ(u_ce, u_tot);
  XALLOCA(u_sort, u_tot);

  XALLOCAZ(l_total, state->max_lang + 1);
  XALLOCAZ(l_ok, state->max_lang + 1);
  XALLOCAZ(l_ce, state->max_lang + 1);

  XALLOCAZ(p_total, p_tot);
  XALLOCAZ(p_ok, p_tot);

  for (i = 0, rcur = runs; i < r_tot; i++, rcur++) {
    if (rcur->time >= to_time) break;
    if (rcur->time < from_time) {
      if (rcur->status == RUN_EMPTY) continue;
      if (rcur->status != RUN_OK) continue;
      if (rcur->user_id <= 0 || rcur->user_id >= u_max || u_rev[rcur->user_id] < 0)
        continue;
      if (rcur->prob_id <= 0 || rcur->prob_id >= p_max
          || p_rev[rcur->prob_id] < 0)
        continue;
      solved[(u_rev[rcur->user_id] << row_sh) + p_rev[rcur->prob_id]] = 1;
      continue;
    }

    // ok, collect statistics
    if ((rcur->status > RUN_MAX_STATUS && rcur->status < RUN_PSEUDO_FIRST)
        || (rcur->status>RUN_PSEUDO_LAST && rcur->status<RUN_TRANSIENT_FIRST)
        || (rcur->status > RUN_TRANSIENT_LAST)) {
      fprintf(f, "error: run %d has invalid status %d\n", i, rcur->status);
      total_errors++;
      continue;
    }
    if (rcur->status == RUN_EMPTY) {
      total_empty++;
      continue;
    }
    if (rcur->user_id <= 0 || rcur->user_id >= u_max || (u = u_rev[rcur->user_id]) < 0) {
      fprintf(f, "error: run %d has invalid user_id %d\n",
              i, rcur->user_id);
      total_errors++;
      continue;
    }
    if (rcur->status >= RUN_PSEUDO_FIRST && rcur->status <= RUN_PSEUDO_LAST) {
      total_status[rcur->status]++;
      total_pseudo++;
      u_total[u]++;
      continue;
    }
    if (rcur->prob_id <= 0 || rcur->prob_id >= p_max
        || (p = p_rev[rcur->prob_id]) < 0) {
      fprintf(f, "error: run %d has invalid prob_id %d\n",
              i, rcur->prob_id);
      total_errors++;
      u_errors[u]++;
      u_total[u]++;
      continue;
    }
    idx = (u << row_sh) + p;
    if (solved[idx]) {
      u_afterok[u]++;
      u_total[u]++;
      total_afterok++;
      continue;
    }
    if (rcur->lang_id) {
      if (rcur->lang_id < 0 || rcur->lang_id > state->max_lang
          || !state->langs[rcur->lang_id]) {
        fprintf(f, "error: run %d has invalid lang_id %d\n",
                i, rcur->lang_id);
        total_errors++;
        u_errors[u]++;
        u_total[u]++;
        continue;
      }
    }
    if (rcur->status >= RUN_TRANSIENT_FIRST
        && rcur->status <= RUN_TRANSIENT_LAST) {
      total_trans++;
      u_total[u]++;
      u_trans[u]++;
      continue;
    }

    switch (rcur->status) {
    case RUN_OK:
      total_ok++;
      u_ok[u]++;
      u_total[u]++;
      l_total[rcur->lang_id]++;
      l_ok[rcur->lang_id]++;
      p_total[p]++;
      p_ok[p]++;
      solved[idx] = 1;
      break;

    case RUN_COMPILE_ERR:
    case RUN_STYLE_ERR:
    case RUN_REJECTED:
      total_ce++;
      u_ce[u]++;
      u_total[u]++;
      l_total[rcur->lang_id]++;
      l_ce[rcur->lang_id]++;
      p_total[p]++;
      break;

    case RUN_RUN_TIME_ERR:
    case RUN_TIME_LIMIT_ERR:
    case RUN_WALL_TIME_LIMIT_ERR:
    case RUN_PRESENTATION_ERR:
    case RUN_WRONG_ANSWER_ERR:
    case RUN_MEM_LIMIT_ERR:
    case RUN_SECURITY_ERR:
    case RUN_PARTIAL:
      total_failed++;
      u_failed[u]++;
      u_total[u]++;
      l_total[rcur->lang_id]++;
      p_total[p]++;
      total_status[rcur->status]++;
      break;

    case RUN_CHECK_FAILED:
      total_cf++;
      u_cf[u]++;
      u_total[u]++;
      break;

    case RUN_ACCEPTED:
    case RUN_PENDING_REVIEW:
      total_ac++;
      u_ac[u]++;
      u_total[u]++;
      break;

    case RUN_IGNORED:
      total_ign++;
      u_ign[u]++;
      u_total[u]++;
      break;

    case RUN_DISQUALIFIED:
      total_disq++;
      u_disq[u]++;
      u_total[u]++;
      break;

    case RUN_PENDING:
      total_pend++;
      u_pend[u]++;
      u_total[u]++;
      break;

    default:
      abort();
    }
  }

  clar_total = clar_get_total(state->clarlog_state);
  for (i = 0; i < clar_total; i++) {
    if (clar_get_record(state->clarlog_state, i, &clar) < 0) continue;
    if (clar.id < 0) continue;
    clar_time = clar.time;
    if (clar_time >= to_time) break;
    if (clar_time < from_time) continue;

    clar_total_today++;
    if (!clar.from) clar_from_judges++;
    else clar_to_judges++;
  }

  if (total_reg > 0) {
    fprintf(f, "New users registered: %d\n", total_reg);
    for (i = 0; i < u_tot; i++) {
      if (!u_reg[i]) continue;
      u = u_ind[i];
      if (!(login = teamdb_get_login(state->teamdb_state, u))) login = "";
      if (!(name = teamdb_get_name(state->teamdb_state, u))) name = "";
      w = 30; y = 0;
      if (utf8_mode) w = utf8_cnt(name, w, &y);
      fprintf(f, "  %-6d %-15.15s %-*.*s\n", u, login, w + y, w, name);
    }
    fprintf(f, "\n");
  }

  total_runs = total_empty + total_pseudo + total_afterok + total_trans
    + total_ok + total_failed + total_cf
    + total_ac + total_ign + total_disq + total_pend + total_ce;
  if (total_runs > 0)
    fprintf(f, "Total new runs:            %d\n", total_runs);
  if (total_empty > 0)
    fprintf(f, "  Empty (cleared) records: %d\n", total_empty);
  if (total_pseudo > 0)
    fprintf(f, "  Virtual records:         %d\n", total_pseudo);
  if (total_trans > 0)
    fprintf(f, "  Currently being tested:  %d\n", total_trans);
  if (total_afterok > 0)
    fprintf(f, "  Submits after success:   %d\n", total_afterok);
  if (total_ok > 0)
    fprintf(f, "  Successful submits:      %d\n", total_ok);
  if (total_failed > 0)
    fprintf(f, "  Unsuccessful submits:    %d\n", total_failed);
  if (total_status[RUN_RUN_TIME_ERR] > 0)
    fprintf(f, "    Run-time error:        %d\n", total_status[RUN_RUN_TIME_ERR]);
  if (total_status[RUN_TIME_LIMIT_ERR] > 0)
    fprintf(f, "    Time-limit exceeded:   %d\n", total_status[RUN_TIME_LIMIT_ERR]);
  if (total_status[RUN_PRESENTATION_ERR] > 0)
    fprintf(f, "    Presentation error:    %d\n", total_status[RUN_PRESENTATION_ERR]);
  if (total_status[RUN_WRONG_ANSWER_ERR] > 0)
    fprintf(f, "    Wrong answer:          %d\n", total_status[RUN_WRONG_ANSWER_ERR]);
  if (total_status[RUN_MEM_LIMIT_ERR] > 0)
    fprintf(f, "    Memory limit exceeded: %d\n", total_status[RUN_MEM_LIMIT_ERR]);
  if (total_status[RUN_SECURITY_ERR] > 0)
    fprintf(f, "    Security violation:    %d\n", total_status[RUN_SECURITY_ERR]);
  if (total_status[RUN_WALL_TIME_LIMIT_ERR] > 0)
    fprintf(f, "    Wall time-limit exceeded:%d\n", total_status[RUN_WALL_TIME_LIMIT_ERR]);
  if (total_status[RUN_PARTIAL] > 0)
    fprintf(f, "    Partial solution:      %d\n", total_status[RUN_PARTIAL]);
  if (total_ce > 0)
    fprintf(f, "  Compilation error:       %d\n", total_ce);
  if (total_cf > 0)
    fprintf(f, "  Checking failed:         %d\n", total_cf);
  if (total_ac > 0)
    fprintf(f, "  Accepted for testing:    %d\n", total_ac);
  if (total_ign > 0)
    fprintf(f, "  Ignored:                 %d\n", total_ign);
  if (total_disq > 0)
    fprintf(f, "  Disqualified:            %d\n", total_disq);
  if (total_pend > 0)
    fprintf(f, "  Pending check:           %d\n", total_pend);
  if (total_runs > 0)
    fprintf(f, "\n");

  if (total_runs > 0) {
    fprintf(f, "%-40.40s %-7.7s %-7.7s\n", "Problem", "Total", "Success");
    for (i = 0; i < p_tot; i++) {
      p = p_ind[i];
      snprintf(probname, sizeof(probname), "%s: %s",
               state->probs[p]->short_name, state->probs[p]->long_name);
      w = 40; y = 0;
      if (utf8_mode) w = utf8_cnt(probname, w, &y);
      fprintf(f, "%-*.*s %-7d %-7d\n", w + y, w, probname, p_total[i],
              p_ok[i]);
    }
    fprintf(f, "\n");
  }

  if (total_runs > 0) {
    fprintf(f, "%-40.40s %-7.7s %-7.7s %-7.7s\n",
            "Language", "Total", "CE", "Success");
    if (l_total[0] > 0) {
      fprintf(f, "%-40.40s %-7d %-7d %-7d\n",
              "N/A (0)", l_total[0], l_ce[0], l_ok[0]);
    }
    for (i = 1; i <= state->max_lang; i++) {
      if (!state->langs[i]) continue;
      snprintf(langname, sizeof(langname), "%s - %s",
               state->langs[i]->short_name,
               state->langs[i]->long_name);
      w = 40; y = 0;
      if (utf8_mode) w = utf8_cnt(langname, w, &y);
      fprintf(f, "%-*.*s %-7d %-7d %-7d\n", w + y, w, langname, l_total[i],
              l_ce[i], l_ok[i]);
    }
    fprintf(f, "\n");
  }

  // sort users by decreasing order of user's submit
  max_u_total = 0;
  for (i = 0; i < u_tot; i++)
    if (u_total[i] > max_u_total)
      max_u_total = u_total[i];
  XALLOCAZ(sort_num, max_u_total + 1);
  XALLOCAZ(sort_idx, max_u_total + 1);
  for (i = 0; i < u_tot; i++)
    sort_num[u_total[i]]++;
  sort_idx[max_u_total] = 0;
  for (i = max_u_total - 1; i >= 0; i--)
    sort_idx[i] = sort_idx[i + 1] + sort_num[i + 1];
  for (i = 0; i < u_tot; i++)
    u_sort[sort_idx[u_total[i]]++] = i;

  if (total_runs > 0) {
    fprintf(f, "%-7.7s %-24.24s %-7.7s %-7.7s %s\n",
            "Id", "User", "Total", "Success", "Other");
    for (i = 0; i < u_tot; i++) {
      j = u_sort[i];
      if (!u_total[j]) break;

      u = u_ind[j];
      name = teamdb_get_name(state->teamdb_state, u);
      if (!name || !*name) name = teamdb_get_login(state->teamdb_state, u);
      if (!name) name = "";

      w = 24; y = 0;
      if (utf8_mode) w = utf8_cnt(name, w, &y);
      fprintf(f, "%-7d %-*.*s %-7d %-7d %-7d %d/%d/%d %d/%d/%d/%d/%d/%d\n",
              u, w + y, w, name, u_total[j], u_ok[j], u_failed[j],
              u_cf[j], u_ce[j], u_ign[j],
              u_afterok[j], u_errors[j], u_trans[j],
              u_ac[j], u_disq[j], u_pend[j]);
    }
    fprintf(f, "\n");
  }

  if (clar_total_today > 0) {
    fprintf(f,
            "Clarification requests: %d\n"
            "To judges:              %d\n"
            "From judges:            %d\n\n",
            clar_total_today, clar_to_judges, clar_from_judges);
  }
  
  xfree(solved);
}
Ejemplo n.º 5
0
void
write_runs_dump(const serve_state_t state, FILE *f, const unsigned char *url,
                unsigned char const *charset)
{
  int total_runs, i, j;
  struct run_entry re;
  struct tm *pts;
  time_t start_time, dur;
  unsigned char *s;
  unsigned char statstr[128];
  time_t tmp_time;

  if (url && *url) {
    fprintf(f, "Content-type: text/plain; charset=%s\n\n", charset);
  }

  fprintf(f,
          "Run_Id"
          ";Time;Nsec;Time2;Date;Year;Mon;Day;Hour;Min;Sec"
          ";Dur;Dur_Day;Dur_Hour;Dur_Min;Dur_Sec"
          ";Size"
          ";IPV6_Flag;IP;SSL_Flag"
          ";Sha1"
          ";User_Id;User_Login;User_Name"
          ";User_Inv;User_Ban;User_Lock"
          ";Prob;Variant"
          ";Lang;Content_Type"
          ";Stat_Short;Status;Score;Score_Adj;Test"
          ";Import_Flag;Hidden_Flag;RO_Flag;Locale_Id;Pages;Judge_Id"
          "\n");

  total_runs = run_get_total(state->runlog_state);
  start_time = run_get_start_time(state->runlog_state);
  for (i = 0; i < total_runs; i++) {
    if (run_get_entry(state->runlog_state, i, &re) < 0) {
      fprintf(f, "%d;Cannot read entry!\n", i);
      continue;
    }
    if (!run_is_valid_status(re.status)) {
      fprintf(f, "%d;Invalid status %d!\n", i, re.status);
      continue;
    }
    if (re.status == RUN_EMPTY) continue;

    fprintf(f, "%d;", i);
    fprintf(f, "%lld;%09d;", re.time, re.nsec);
    tmp_time = re.time;
    pts = localtime(&tmp_time);
    fprintf(f, "%04d%02d%02d%02d%02d%02d;",
            pts->tm_year + 1900,
            pts->tm_mon + 1,
            pts->tm_mday,
            pts->tm_hour,
            pts->tm_min,
            pts->tm_sec);
    fprintf(f, "%04d%02d%02d;",
            pts->tm_year + 1900,
            pts->tm_mon + 1,
            pts->tm_mday);
    fprintf(f, "%04d;%02d;%02d;%02d;%02d;%02d;",
            pts->tm_year + 1900,
            pts->tm_mon + 1,
            pts->tm_mday,
            pts->tm_hour,
            pts->tm_min,
            pts->tm_sec);
    if (state->global->is_virtual) {
      start_time = run_get_virtual_start_time(state->runlog_state, re.user_id);
    }

    dur = re.time - start_time;
    if (dur < 0) dur = 0;
    fprintf(f, "%ld;", dur);
    pts->tm_sec = dur % 60;
    dur /= 60;
    pts->tm_min = dur % 60;
    dur /= 60;
    pts->tm_hour = dur % 24;
    dur /= 24;
    fprintf(f, "%ld;%02d;%02d;%02d;",
            dur, pts->tm_hour, pts->tm_min, pts->tm_sec);

    fprintf(f, "%u;", re.size);
    fprintf(f, "%d;%s;%d;", re.ipv6_flag, xml_unparse_ip(re.a.ip), re.ssl_flag);

    s = (unsigned char*) re.sha1;
    for (j = 0; j < 20; j++) fprintf(f, "%02x", *s++);
    fprintf(f, ";");

    fprintf(f, "%d;", re.user_id);
    if (!(s = teamdb_get_login(state->teamdb_state, re.user_id))) {
      fprintf(f, "!INVALID TEAM!;");
    } else {
      fprintf(f, "%s;", s);
    }
    if (!(s = teamdb_get_name(state->teamdb_state, re.user_id))) {
      fprintf(f, "!INVALID TEAM!;");
    } else {
      fprintf(f, "%s;", s);
    }
    j = teamdb_get_flags(state->teamdb_state, re.user_id);
    s = "";
    if ((j & TEAM_INVISIBLE)) s = "I";
    fprintf(f, "%s;", s);
    s = "";
    if ((j & TEAM_BANNED)) s = "B";
    fprintf(f, "%s;", s);
    s = "";
    if ((j & TEAM_LOCKED)) s = "L";
    fprintf(f, "%s;", s);

    if (re.status == RUN_VIRTUAL_START || re.status == RUN_VIRTUAL_STOP) {
      //fprintf(f, "<problem>;<variant>;<lang_short>;<mime_type>;<short_status>;<status>;<score>;<score_adj>;<test>;<is_imported>;<is_hidden>;<is_readonly>;<locale_id>;<pages>;<judge_id>\n");
      fprintf(f, ";;;;");
      run_status_to_str_short(statstr, sizeof(statstr), re.status);
      fprintf(f, "%s;", statstr);
      run_status_str(re.status, statstr, sizeof(statstr), 0, 0);
      fprintf(f, "%s;", statstr);
      fprintf(f, ";;;;;;;;\n");
      continue;
    }

    if (re.prob_id > 0 && re.prob_id <= state->max_prob
        && state->probs[re.prob_id] && state->probs[re.prob_id]->short_name) {
      fprintf(f, "%s;", state->probs[re.prob_id]->short_name);
    } else {
      fprintf(f, "!INVALID PROBLEM %d!;", re.prob_id);
    }
    fprintf(f, "%d;", re.variant);

    if (!re.lang_id) {
      fprintf(f, ";%s;", mime_type_get_type(re.mime_type));
    } else if (re.lang_id > 0 && re.lang_id <= state->max_lang
        && state->langs[re.lang_id] && state->langs[re.lang_id]->short_name) {
      fprintf(f, "%s;;", state->langs[re.lang_id]->short_name);
    } else {
      fprintf(f, "!INVALID LANGUAGE %d!;", re.lang_id);
    }

    run_status_to_str_short(statstr, sizeof(statstr), re.status);
    fprintf(f, "%s;", statstr);
    run_status_str(re.status, statstr, sizeof(statstr), 0, 0);
    fprintf(f, "%s;", statstr);
    fprintf(f, "%d;%d;", re.score, re.score_adj);
    fprintf(f, "%d;", re.test);
    fprintf(f, "%d;", (re.passed_mode > 0));
    fprintf(f, "%d;", re.is_imported);
    fprintf(f, "%d;", re.is_hidden);
    fprintf(f, "%d;", re.is_readonly);
    fprintf(f, "%d;%d;%d", re.locale_id, re.pages, re.judge_id);

    fprintf(f, "\n");
  }
}
Ejemplo n.º 6
0
static int
do_eval(struct filter_env *env,
        struct filter_tree *t,
        struct filter_tree *res)
{
  int c;
  struct filter_tree r1, r2;
  int lang_id, prob_id, user_id, flags;
  const struct userlist_user *u;
  const struct userlist_member *m;
  const unsigned char *s;

  memset(res, 0, sizeof(*res));
  switch (t->kind) {
  case TOK_LOGOR:
    res->kind = TOK_BOOL_L;
    res->type = FILTER_TYPE_BOOL;
    if ((c = do_eval(env, t->v.t[0], &r1)) < 0) return c;
    ASSERT(r1.kind == TOK_BOOL_L);
    if (!r1.v.b) {
      if ((c = do_eval(env, t->v.t[1], &r2)) < 0) return c;
      ASSERT(r2.kind == TOK_BOOL_L);
      res->v.b = r2.v.b;
    } else {
      res->v.b = 1;
    }
    break;
    
  case TOK_LOGAND:
    res->kind = TOK_BOOL_L;
    res->type = FILTER_TYPE_BOOL;
    if ((c = do_eval(env, t->v.t[0], &r1)) < 0) return c;
    ASSERT(r1.kind == TOK_BOOL_L);
    if (r1.v.b) {
      if ((c = do_eval(env, t->v.t[1], &r2)) < 0) return c;
      ASSERT(r2.kind == TOK_BOOL_L);
      res->v.b = r2.v.b;
    } else {
      res->v.b = 0;
    }
    break;

    /* binary */
  case '^':
  case '|':
  case '&':
  case '*':
  case '/':
  case '%':
  case '+':
  case '-':
  case '>':
  case '<':
  case TOK_EQ:
  case TOK_NE:
  case TOK_LE:
  case TOK_GE:
  case TOK_ASL:
  case TOK_ASR:
  case TOK_REGEXP:
    if ((c = do_eval(env, t->v.t[0], &r1)) < 0) return c;
    if ((c = do_eval(env, t->v.t[1], &r2)) < 0) return c;
    return filter_tree_eval_node(env->mem, t->kind, res, &r1, &r2);

    /* unary */
  case '~':
  case '!':
  case TOK_UN_MINUS:
    if ((c = do_eval(env, t->v.t[0], &r1)) < 0) return c;
    return filter_tree_eval_node(env->mem, t->kind, res, &r1, 0);

  case TOK_TIME:
  case TOK_DUR:
  case TOK_SIZE:
  case TOK_HASH:
  case TOK_UUID:
  case TOK_IP:
  case TOK_PROB:
  case TOK_UID:
  case TOK_LOGIN:
  case TOK_NAME:
  case TOK_GROUP:
  case TOK_LANG:
  case TOK_ARCH:
  case TOK_RESULT:
  case TOK_SCORE:
  case TOK_TEST:
  case TOK_IMPORTED:
  case TOK_HIDDEN:
  case TOK_READONLY:
  case TOK_MARKED:
  case TOK_SAVED:
  case TOK_VARIANT:
  case TOK_RAWVARIANT:
  case TOK_USERINVISIBLE:
  case TOK_USERBANNED:
  case TOK_USERLOCKED:
  case TOK_USERINCOMPLETE:
  case TOK_USERDISQUALIFIED:
  case TOK_LATEST:
  case TOK_LATESTMARKED:
  case TOK_AFTEROK:
  case TOK_EXAMINABLE:
  case TOK_CYPHER:
  case TOK_MISSINGSOURCE:
  case TOK_JUDGE_ID:
  case TOK_PASSED_MODE:
  case TOK_EOLN_TYPE:
  case TOK_STORE_FLAGS:
  case TOK_TOKEN_FLAGS:
  case TOK_TOKEN_COUNT:
    if ((c = do_eval(env, t->v.t[0], &r1)) < 0) return c;
    ASSERT(r1.kind == TOK_INT_L);
    if (r1.v.i < 0) r1.v.i = env->rtotal + r1.v.i;
    if (r1.v.i >= env->rtotal) return -FILTER_ERR_RANGE;
    if (r1.v.i < 0) return -FILTER_ERR_RANGE;
    switch (t->kind) {
    case TOK_TIME:
      res->kind = TOK_TIME_L;
      res->type = FILTER_TYPE_TIME;
      res->v.a = env->rentries[r1.v.i].time;
      break;
    case TOK_DUR:
      res->kind = TOK_DUR_L;
      res->type = FILTER_TYPE_DUR;
      res->v.u = env->rentries[r1.v.i].time - env->rhead.start_time;
      break;
    case TOK_SIZE:
      res->kind = TOK_SIZE_L;
      res->type = FILTER_TYPE_SIZE;
      res->v.z = env->rentries[r1.v.i].size;
      break;
    case TOK_HASH:
      res->kind = TOK_HASH_L;
      res->type = FILTER_TYPE_HASH;
      memcpy(res->v.h, env->rentries[r1.v.i].sha1, sizeof(env->cur->sha1));
      break;
    case TOK_UUID:
      res->kind = TOK_STRING_L;
      res->type = FILTER_TYPE_STRING;
      res->v.s = envdup(env, ej_uuid_unparse(&env->rentries[r1.v.i].run_uuid, ""));
      break;
    case TOK_IP:
      res->kind = TOK_IP_L;
      res->type = FILTER_TYPE_IP;
      run_entry_to_ipv6(&env->rentries[r1.v.i], &res->v.p);
      break;
    case TOK_PROB:
      res->kind = TOK_STRING_L;
      res->type = FILTER_TYPE_STRING;
      prob_id = env->rentries[r1.v.i].prob_id;
      if (prob_id <= 0 || prob_id > env->maxprob || !env->probs[prob_id]) {
        res->v.s = envdup(env, "");
      } else {
        res->v.s = envdup(env, env->probs[prob_id]->short_name);
      }
      break;
    case TOK_UID:
      res->kind = TOK_INT_L;
      res->type = FILTER_TYPE_INT;
      res->v.i = env->rentries[r1.v.i].user_id;
      break;
    case TOK_LOGIN:
      res->kind = TOK_STRING_L;
      res->type = FILTER_TYPE_STRING;
      user_id = env->rentries[r1.v.i].user_id;
      if (!user_id) {
        res->v.s = envdup(env, "");
      } else {
        res->v.s = envdup(env, teamdb_get_login(env->teamdb_state, user_id));
      }
      break;
    case TOK_NAME:
      res->kind = TOK_STRING_L;
      res->type = FILTER_TYPE_STRING;
      user_id = env->rentries[r1.v.i].user_id;
      if (!user_id) {
        res->v.s = envdup(env, "");
      } else {
        res->v.s = envdup(env, teamdb_get_name(env->teamdb_state, user_id));
      }
      break;
    case TOK_GROUP:
      res->kind = TOK_STRING_L;
      res->type = FILTER_TYPE_STRING;
      user_id = env->rentries[r1.v.i].user_id;
      if (user_id > 0
          && (u = teamdb_get_userlist(env->teamdb_state, user_id))
          && u->cnts0
          && (m = userlist_members_get_first(u->cnts0->members))) {
        res->v.s = envdup(env, m->group);
      } else {
        res->v.s = envdup(env, "");
      }
      break;
    case TOK_LANG:
      res->kind = TOK_STRING_L;
      res->type = FILTER_TYPE_STRING;
      lang_id = env->rentries[r1.v.i].lang_id;
      if (lang_id <= 0 || lang_id > env->maxlang || !env->langs[lang_id]) {
        res->v.s = envdup(env, "");
      } else {
        res->v.s = envdup(env, env->langs[lang_id]->short_name);
      }
      break;
    case TOK_ARCH:
      res->kind = TOK_STRING_L;
      res->type = FILTER_TYPE_STRING;
      lang_id = env->rentries[r1.v.i].lang_id;
      if (lang_id <= 0 || lang_id > env->maxlang || !env->langs[lang_id]) {
        res->v.s = envdup(env, "");
      } else {
        res->v.s = envdup(env, env->langs[lang_id]->arch);
      }
      break;
    case TOK_RESULT:
      res->kind = TOK_RESULT_L;
      res->type = FILTER_TYPE_RESULT;
      res->v.r = env->rentries[r1.v.i].status;
      break;
    case TOK_SCORE:
      res->kind = TOK_INT_L;
      res->type = FILTER_TYPE_INT;
      res->v.i = env->rentries[r1.v.i].score;
      break;
    case TOK_TEST:
      res->kind = TOK_INT_L;
      res->type = FILTER_TYPE_INT;
      res->v.i = env->rentries[r1.v.i].test;
      break;
    case TOK_IMPORTED:
      res->kind = TOK_BOOL_L;
      res->type = FILTER_TYPE_BOOL;
      res->v.b = env->rentries[r1.v.i].is_imported;
      break;
    case TOK_HIDDEN:
      res->kind = TOK_BOOL_L;
      res->type = FILTER_TYPE_BOOL;
      res->v.b = env->rentries[r1.v.i].is_hidden;
      break;
    case TOK_READONLY:
      res->kind = TOK_BOOL_L;
      res->type = FILTER_TYPE_BOOL;
      res->v.b = env->rentries[r1.v.i].is_readonly;
      break;
    case TOK_MARKED:
      res->kind = TOK_BOOL_L;
      res->type = FILTER_TYPE_BOOL;
      res->v.b = env->rentries[r1.v.i].is_marked;
      break;
    case TOK_SAVED:
      res->kind = TOK_BOOL_L;
      res->type = FILTER_TYPE_BOOL;
      res->v.b = env->rentries[r1.v.i].is_saved;
      break;
    case TOK_VARIANT:
      res->kind = TOK_INT_L;
      res->type = FILTER_TYPE_INT;
      c = env->rentries[r1.v.i].variant;
      if (!c) {
        c = find_variant(env->serve_state, env->rentries[r1.v.i].user_id,
                         env->rentries[r1.v.i].prob_id, 0);
      }
      res->v.i = c;
      break;
    case TOK_RAWVARIANT:
      res->kind = TOK_INT_L;
      res->type = FILTER_TYPE_INT;
      c = env->rentries[r1.v.i].variant;
      res->v.i = c;
      break;
    case TOK_USERINVISIBLE:
      res->kind = TOK_BOOL_L;
      res->type = FILTER_TYPE_BOOL;
      user_id = env->rentries[r1.v.i].user_id;
      if (!user_id) {
        res->v.b = 0;
      } else if ((flags = teamdb_get_flags(env->teamdb_state, user_id)) < 0) {
        res->v.b = 0;
      } else if ((flags & TEAM_INVISIBLE)) {
        res->v.b = 1;
      } else {
        res->v.b = 0;
      }
      break;
    case TOK_USERBANNED:
      res->kind = TOK_BOOL_L;
      res->type = FILTER_TYPE_BOOL;
      user_id = env->rentries[r1.v.i].user_id;
      if (!user_id) {
        res->v.b = 0;
      } else if ((flags = teamdb_get_flags(env->teamdb_state, user_id)) < 0) {
        res->v.b = 0;
      } else if ((flags & TEAM_BANNED)) {
        res->v.b = 1;
      } else {
        res->v.b = 0;
      }
      break;
    case TOK_USERLOCKED:
      res->kind = TOK_BOOL_L;
      res->type = FILTER_TYPE_BOOL;
      user_id = env->rentries[r1.v.i].user_id;
      if (!user_id) {
        res->v.b = 0;
      } else if ((flags = teamdb_get_flags(env->teamdb_state, user_id)) < 0) {
        res->v.b = 0;
      } else if ((flags & TEAM_LOCKED)) {
        res->v.b = 1;
      } else {
        res->v.b = 0;
      }
      break;
    case TOK_USERINCOMPLETE:
      res->kind = TOK_BOOL_L;
      res->type = FILTER_TYPE_BOOL;
      user_id = env->rentries[r1.v.i].user_id;
      if (!user_id) {
        res->v.b = 0;
      } else if ((flags = teamdb_get_flags(env->teamdb_state, user_id)) < 0) {
        res->v.b = 0;
      } else if ((flags & TEAM_INCOMPLETE)) {
        res->v.b = 1;
      } else {
        res->v.b = 0;
      }
      break;
    case TOK_USERDISQUALIFIED:
      res->kind = TOK_BOOL_L;
      res->type = FILTER_TYPE_BOOL;
      user_id = env->rentries[r1.v.i].user_id;
      if (!user_id) {
        res->v.b = 0;
      } else if ((flags = teamdb_get_flags(env->teamdb_state, user_id)) < 0) {
        res->v.b = 0;
      } else if ((flags & TEAM_DISQUALIFIED)) {
        res->v.b = 1;
      } else {
        res->v.b = 0;
      }
      break;
    case TOK_LATEST:
      res->kind = TOK_BOOL_L;
      res->type = FILTER_TYPE_BOOL;
      res->v.b = is_latest(env, r1.v.i);
      break;
    case TOK_LATESTMARKED:
      res->kind = TOK_BOOL_L;
      res->type = FILTER_TYPE_BOOL;
      res->v.b = is_latestmarked(env, r1.v.i);
      break;
    case TOK_AFTEROK:
      res->kind = TOK_BOOL_L;
      res->type = FILTER_TYPE_BOOL;
      res->v.b = is_afterok(env, r1.v.i);
      break;
    case TOK_EXAMINABLE:
      res->kind = TOK_BOOL_L;
      res->type = FILTER_TYPE_BOOL;
      //res->v.b = env->rentries[r1.v.i].is_examinable;
      res->v.b = 0;
      break;
    case TOK_CYPHER:
      res->kind = TOK_STRING_L;
      res->type = FILTER_TYPE_STRING;
      user_id = env->rentries[r1.v.i].user_id;
      u = 0; s = 0;
      if (user_id > 0) u = teamdb_get_userlist(env->teamdb_state, user_id);
      if (u && u->cnts0) s = u->cnts0->exam_cypher;
      res->v.s = envdup(env, s);
      break;
    case TOK_MISSINGSOURCE:
      res->kind = TOK_BOOL_L;
      res->type = FILTER_TYPE_BOOL;
      res->v.b = is_missing_source(env, &env->rentries[r1.v.i]);
      break;
    case TOK_JUDGE_ID:
      res->kind = TOK_INT_L;
      res->type = FILTER_TYPE_INT;
      res->v.i = env->rentries[r1.v.i].judge_id;
      break;
    case TOK_PASSED_MODE:
      res->kind = TOK_BOOL_L;
      res->type = FILTER_TYPE_BOOL;
      res->v.i = !!env->rentries[r1.v.i].passed_mode;
      break;
    case TOK_EOLN_TYPE:
      res->kind = TOK_INT_L;
      res->type = FILTER_TYPE_INT;
      res->v.i = !!env->rentries[r1.v.i].eoln_type;
      break;
    case TOK_STORE_FLAGS:
      res->kind = TOK_INT_L;
      res->type = FILTER_TYPE_INT;
      res->v.i = !!env->rentries[r1.v.i].store_flags;
      break;
    case TOK_TOKEN_FLAGS:
      res->kind = TOK_INT_L;
      res->type = FILTER_TYPE_INT;
      res->v.i = !!env->rentries[r1.v.i].token_flags;
      break;
    case TOK_TOKEN_COUNT:
      res->kind = TOK_INT_L;
      res->type = FILTER_TYPE_INT;
      res->v.i = !!env->rentries[r1.v.i].token_count;
      break;
    default:
      abort();
    }
    break;

  case TOK_INT:
  case TOK_STRING:
  case TOK_BOOL:
  case TOK_TIME_T:
  case TOK_DUR_T:
  case TOK_SIZE_T:
  case TOK_RESULT_T:
  case TOK_HASH_T:
  case TOK_IP_T:
    if ((c = do_eval(env, t->v.t[0], &r1)) < 0) return c;
    return filter_tree_eval_node(env->mem, t->kind, res, &r1, 0);

    /* variables */
  case TOK_ID:
    res->kind = TOK_INT_L;
    res->type = FILTER_TYPE_INT;
    res->v.i = env->rid;
    break;
  case TOK_CURTIME:
    res->kind = TOK_TIME_L;
    res->type = FILTER_TYPE_TIME;
    res->v.a = env->cur->time;
    break;
  case TOK_CURDUR:
    res->kind = TOK_DUR_L;
    res->type = FILTER_TYPE_DUR;
    res->v.u = env->cur->time - env->rhead.start_time;
    break;
  case TOK_CURSIZE:
    res->kind = TOK_SIZE_L;
    res->type = FILTER_TYPE_SIZE;
    res->v.z = env->cur->size;
    break;
  case TOK_CURHASH:
    res->kind = TOK_HASH_L;
    res->type = FILTER_TYPE_HASH;
    memcpy(res->v.h, env->cur->sha1, sizeof(env->cur->sha1));
    break;
  case TOK_CURUUID:
    res->kind = TOK_STRING_L;
    res->type = FILTER_TYPE_STRING;
    res->v.s = envdup(env, ej_uuid_unparse(&env->cur->run_uuid, ""));
    break;
  case TOK_CURIP:
    res->kind = TOK_IP_L;
    res->type = FILTER_TYPE_IP;
    run_entry_to_ipv6(env->cur, &res->v.p);
    break;
  case TOK_CURPROB:
    res->kind = TOK_STRING_L;
    res->type = FILTER_TYPE_STRING;
    if (env->cur->prob_id <= 0 || env->cur->prob_id > env->maxprob || !env->probs[env->cur->prob_id]) {
      res->v.s = envdup(env, "");
    } else {
      res->v.s = envdup(env, env->probs[env->cur->prob_id]->short_name);
    }
    break;
  case TOK_CURUID:
    res->kind = TOK_INT_L;
    res->type = FILTER_TYPE_INT;
    res->v.i = env->cur->user_id;
    break;
  case TOK_CURLOGIN:
    res->kind = TOK_STRING_L;
    res->type = FILTER_TYPE_STRING;
    if (!env->cur->user_id) {
      res->v.s = envdup(env, "");
    } else {
      res->v.s = envdup(env, teamdb_get_login(env->teamdb_state, env->cur->user_id));
    }
    break;
  case TOK_CURNAME:
    res->kind = TOK_STRING_L;
    res->type = FILTER_TYPE_STRING;
    if (!env->cur->user_id) {
      res->v.s = envdup(env, "");
    } else {
      res->v.s = envdup(env, teamdb_get_name(env->teamdb_state, env->cur->user_id));
    }
    break;
  case TOK_CURGROUP:
    res->kind = TOK_STRING_L;
    res->type = FILTER_TYPE_STRING;
    user_id = env->cur->user_id;
    if (user_id > 0
        && (u = teamdb_get_userlist(env->teamdb_state, user_id))
        && u->cnts0
        && (m = userlist_members_get_first(u->cnts0->members))) {
      res->v.s = envdup(env, m->group);
    } else {
      res->v.s = envdup(env, "");
    }
    break;
  case TOK_CURLANG:
    res->kind = TOK_STRING_L;
    res->type = FILTER_TYPE_STRING;
    if (env->cur->lang_id <= 0 || env->cur->lang_id > env->maxlang || !env->langs[env->cur->lang_id]) {
      res->v.s = envdup(env, "");
    } else {
      res->v.s = envdup(env, env->langs[env->cur->lang_id]->short_name);
    }
    break;
  case TOK_CURARCH:
    res->kind = TOK_STRING_L;
    res->type = FILTER_TYPE_STRING;
    if (env->cur->lang_id <= 0 || env->cur->lang_id > env->maxlang || !env->langs[env->cur->lang_id]) {
      res->v.s = envdup(env, "");
    } else {
      res->v.s = envdup(env, env->langs[env->cur->lang_id]->arch);
    }
    break;
  case TOK_CURRESULT:
    res->kind = TOK_RESULT_L;
    res->type = FILTER_TYPE_RESULT;
    res->v.r = env->cur->status;
    break;
  case TOK_CURSCORE:
    res->kind = TOK_INT_L;
    res->type = FILTER_TYPE_INT;
    res->v.i = env->cur->score;
    break;
  case TOK_CURTEST:
    res->kind = TOK_INT_L;
    res->type = FILTER_TYPE_INT;
    res->v.i = env->cur->test;
    break;
  case TOK_CURIMPORTED:
    res->kind = TOK_BOOL_L;
    res->type = FILTER_TYPE_BOOL;
    res->v.b = env->cur->is_imported;
    break;
  case TOK_CURHIDDEN:
    res->kind = TOK_BOOL_L;
    res->type = FILTER_TYPE_BOOL;
    res->v.b = env->cur->is_hidden;
    break;
  case TOK_CURREADONLY:
    res->kind = TOK_BOOL_L;
    res->type = FILTER_TYPE_BOOL;
    res->v.b = env->cur->is_readonly;
    break;
  case TOK_CURMARKED:
    res->kind = TOK_BOOL_L;
    res->type = FILTER_TYPE_BOOL;
    res->v.b = env->cur->is_marked;
    break;
  case TOK_CURSAVED:
    res->kind = TOK_BOOL_L;
    res->type = FILTER_TYPE_BOOL;
    res->v.b = env->cur->is_saved;
    break;
  case TOK_CURVARIANT:
    res->kind = TOK_INT_L;
    res->type = FILTER_TYPE_INT;
    c = env->cur->variant;
    if (!c) c = find_variant(env->serve_state, env->cur->user_id,
                             env->cur->prob_id, 0);
    res->v.i = c;
    break;
  case TOK_CURRAWVARIANT:
    res->kind = TOK_INT_L;
    res->type = FILTER_TYPE_INT;
    c = env->cur->variant;
    res->v.i = c;
    break;
  case TOK_CURUSERINVISIBLE:
    res->kind = TOK_BOOL_L;
    res->type = FILTER_TYPE_BOOL;
    user_id = env->cur->user_id;
    if (!user_id) {
      res->v.b = 0;
    } else if ((flags = teamdb_get_flags(env->teamdb_state, user_id)) < 0) {
      res->v.b = 0;
    } else if ((flags & TEAM_INVISIBLE)) {
      res->v.b = 1;
    } else {
      res->v.b = 0;
    }
    break;
  case TOK_CURUSERBANNED:
    res->kind = TOK_BOOL_L;
    res->type = FILTER_TYPE_BOOL;
    user_id = env->cur->user_id;
    if (!user_id) {
      res->v.b = 0;
    } else if ((flags = teamdb_get_flags(env->teamdb_state, user_id)) < 0) {
      res->v.b = 0;
    } else if ((flags & TEAM_BANNED)) {
      res->v.b = 1;
    } else {
      res->v.b = 0;
    }
    break;
  case TOK_CURUSERLOCKED:
    res->kind = TOK_BOOL_L;
    res->type = FILTER_TYPE_BOOL;
    user_id = env->cur->user_id;
    if (!user_id) {
      res->v.b = 0;
    } else if ((flags = teamdb_get_flags(env->teamdb_state, user_id)) < 0) {
      res->v.b = 0;
    } else if ((flags & TEAM_LOCKED)) {
      res->v.b = 1;
    } else {
      res->v.b = 0;
    }
    break;
  case TOK_CURUSERINCOMPLETE:
    res->kind = TOK_BOOL_L;
    res->type = FILTER_TYPE_BOOL;
    user_id = env->cur->user_id;
    if (!user_id) {
      res->v.b = 0;
    } else if ((flags = teamdb_get_flags(env->teamdb_state, user_id)) < 0) {
      res->v.b = 0;
    } else if ((flags & TEAM_INCOMPLETE)) {
      res->v.b = 1;
    } else {
      res->v.b = 0;
    }
    break;
  case TOK_CURUSERDISQUALIFIED:
    res->kind = TOK_BOOL_L;
    res->type = FILTER_TYPE_BOOL;
    user_id = env->cur->user_id;
    if (!user_id) {
      res->v.b = 0;
    } else if ((flags = teamdb_get_flags(env->teamdb_state, user_id)) < 0) {
      res->v.b = 0;
    } else if ((flags & TEAM_DISQUALIFIED)) {
      res->v.b = 1;
    } else {
      res->v.b = 0;
    }
    break;
  case TOK_CURLATEST:
    res->kind = TOK_BOOL_L;
    res->type = FILTER_TYPE_BOOL;
    res->v.b = is_latest(env, env->cur->run_id);
    break;
  case TOK_CURLATESTMARKED:
    res->kind = TOK_BOOL_L;
    res->type = FILTER_TYPE_BOOL;
    res->v.b = is_latestmarked(env, env->cur->run_id);
    break;
  case TOK_CURAFTEROK:
    res->kind = TOK_BOOL_L;
    res->type = FILTER_TYPE_BOOL;
    res->v.b = is_afterok(env, env->cur->run_id);
    break;
  case TOK_CUREXAMINABLE:
    res->kind = TOK_BOOL_L;
    res->type = FILTER_TYPE_BOOL;
    //res->v.b = env->cur->is_examinable;
    res->v.b = 0;
    break;
  case TOK_CURCYPHER:
    res->kind = TOK_STRING_L;
    res->type = FILTER_TYPE_STRING;
    user_id = env->cur->user_id;
    u = 0; s = 0;
    if (user_id > 0) u = teamdb_get_userlist(env->teamdb_state, user_id);
    if (u && u->cnts0) s = u->cnts0->exam_cypher;
    res->v.s = envdup(env, s);
    break;
  case TOK_CURMISSINGSOURCE:
    res->kind = TOK_BOOL_L;
    res->type = FILTER_TYPE_BOOL;
    res->v.b = is_missing_source(env, env->cur);
    break;
  case TOK_CURJUDGE_ID:
    res->kind = TOK_INT_L;
    res->type = FILTER_TYPE_INT;
    res->v.i = env->cur->judge_id;
    break;
  case TOK_CURPASSED_MODE:
    res->kind = TOK_BOOL_L;
    res->type = FILTER_TYPE_BOOL;
    res->v.i = !!env->cur->passed_mode;
    break;
  case TOK_CUREOLN_TYPE:
    res->kind = TOK_INT_L;
    res->type = FILTER_TYPE_INT;
    res->v.i = env->cur->eoln_type;
    break;
  case TOK_CURSTORE_FLAGS:
    res->kind = TOK_INT_L;
    res->type = FILTER_TYPE_INT;
    res->v.i = env->cur->store_flags;
    break;
  case TOK_CURTOKEN_FLAGS:
    res->kind = TOK_INT_L;
    res->type = FILTER_TYPE_INT;
    res->v.i = env->cur->token_flags;
    break;
  case TOK_CURTOKEN_COUNT:
    res->kind = TOK_INT_L;
    res->type = FILTER_TYPE_INT;
    res->v.i = env->cur->token_count;
    break;
  case TOK_CURTOTAL_SCORE:
    res->kind = TOK_INT_L;
    res->type = FILTER_TYPE_INT;
    res->v.i = serve_get_user_result_score(env->serve_state,env->cur->user_id);
    break;

  case TOK_NOW:
    res->kind = TOK_TIME_L;
    res->type = FILTER_TYPE_TIME;
    res->v.a = env->cur_time;
    break;
  case TOK_START:
    res->kind = TOK_TIME_L;
    res->type = FILTER_TYPE_TIME;
    res->v.a = env->rhead.start_time;
    break;
  case TOK_FINISH:
    res->kind = TOK_TIME_L;
    res->type = FILTER_TYPE_TIME;
    res->v.a = env->rhead.stop_time;
    break;
  case TOK_TOTAL:
    res->kind = TOK_INT_L;
    res->type = FILTER_TYPE_INT;
    res->v.i = env->rtotal;
    break;

  case TOK_INT_L:
  case TOK_STRING_L:
  case TOK_BOOL_L:
  case TOK_TIME_L:
  case TOK_DUR_L:
  case TOK_SIZE_L:
  case TOK_RESULT_L:
  case TOK_HASH_L:
  case TOK_IP_L:
    *res = *t;
    return 0;

  case TOK_EXAMINATOR:
    if ((c = do_eval(env, t->v.t[0], &r1)) < 0) return c;
    ASSERT(r1.kind == TOK_INT_L);
    if (r1.v.i < 0) r1.v.i = env->rtotal + r1.v.i;
    if (r1.v.i >= env->rtotal) return -FILTER_ERR_RANGE;
    if (r1.v.i < 0) return -FILTER_ERR_RANGE;
    if ((c = do_eval(env, t->v.t[1], &r2)) < 0) return c;
    ASSERT(r2.kind == TOK_INT_L);
    res->kind = TOK_BOOL_L;
    res->type = FILTER_TYPE_BOOL;
    res->v.b = 0;
    /*
    for (c = 0; c < 3; c++) {
      if (env->rentries[r1.v.i].examiners[c] == r2.v.i) {
        res->v.b = 1;
        break;
      }
    }
    */
    break;

  case TOK_CUREXAMINATOR:
    if ((c = do_eval(env, t->v.t[0], &r1)) < 0) return c;
    ASSERT(r1.kind == TOK_INT_L);
    res->kind = TOK_BOOL_L;
    res->type = FILTER_TYPE_BOOL;
    res->v.b = 0;
    /*
    for (c = 0; c < 3; c++) {
      if (env->cur->examiners[c] == r1.v.i) {
        res->v.b = 1;
        break;
      }
    }
    */
    break;

  case TOK_INUSERGROUP:
    if ((c = do_eval(env, t->v.t[0], &r1)) < 0) return c;
    ASSERT(r1.kind == TOK_STRING_L);
    if ((c = find_user_group(env, r1.v.s)) < 0) return c;
    t->kind = TOK_INUSERGROUPINT;
    t->v.t[0] = filter_tree_new_int(env->mem, c);
    res->kind = TOK_BOOL_L;
    res->type = FILTER_TYPE_BOOL;
    res->v.b = check_user_group(env, env->cur->user_id, c);
    break;

  case TOK_INUSERGROUPINT:
    if ((c = do_eval(env, t->v.t[0], &r1)) < 0) return c;
    ASSERT(r1.kind == TOK_INT_L); 
    res->kind = TOK_BOOL_L;
    res->type = FILTER_TYPE_BOOL;
    res->v.b = check_user_group(env, env->cur->user_id, r1.v.i);
    break;   

  default:
    SWERR(("unhandled kind: %d", t->kind));
  }

  return 0;
}