/*
  Copyright(C) 2007-2012 National Institute of Information and Communications Technology
*/

/*
  svmtools
  *.fv to *.sv converter
*/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "exception.h"
#include "split.h"
#include "svm_common.h"
#include "svm_fv.h"


#define BUF_SIZE (32 * 1024)
#define MODE_EXAMPLE 0
#define MODE_MODEL 1
#define DUP_UNIQ 0
#define DUP_SUM 1


int main(int argc, char **argv) {
  int i;
  SVM_FT *ft;
  SVM_SV sv;
  SVM_FV fv;
  FILE *fp;
  int buf_size;
  char *buf;
  int nelem;
  char **elem;
  int sv_size;
  int mode;
  int dup;
  int line;
  char *s;
  int len;
  int label;

  mode = MODE_EXAMPLE;
  dup = DUP_UNIQ;
  for (i = 1; i < argc; i++) {
    if (strcmp(argv[i], "-model") == 0) {
      mode = MODE_MODEL;
    } else if (strcmp(argv[i], "-sum") == 0) {
      dup = DUP_SUM;
    } else {
      break;
    }
  }
  if (argc - i != 1) {
    fprintf(stderr, "usage: %s [-model] [-sum] <*.ft> < <*.sv> > <*.fv>\n", argv[0]);
    return 1;
  }

  /* 初期化 */
  buf_size = BUF_SIZE;
  buf = smalloc(sizeof(char) * buf_size);
  elem = smalloc(sizeof(char *) * (buf_size / 2));
  sv_size = 0;
  sv.idx = NULL;
  sv.val = NULL;
  fv.ftr = NULL;
  fv.val = NULL;

  /* 素性テーブルの読み込み */
  fp = fopen(argv[argc - 1], "rt");
  exception(fp == NULL, "cannot open the *.ft file");
  ft = svm_fv_readft(fp);
  exception(ft == NULL, "cannot read the *.ft file");
  fclose(fp);

  /* 一行ずつ読んで変換 */
  for (line = 1; ; line++) {
    /* ベクトルの読み込み(メモリの動的確保) */
    if (fgets(buf, buf_size, stdin) == NULL) break;
    while (buf[(len = strlen(buf)) - 1] != '\n') {
      buf_size = 2 * buf_size + 1;
      buf = srealloc(buf, sizeof(char) * buf_size);
      elem = srealloc(elem, sizeof(char *) * (buf_size / 2));
      exception(fgets(buf + len, buf_size - len, stdin) == NULL, "unexpected EOF (line: %d)", line);
    }
    buf[--len] = '\0';
    if (len > 0 && buf[len - 1] == '\r') buf[--len] = '\0';
    if (len > 0 && buf[len - 1] == ' ') buf[--len] = '\0';

    /* モデルデータの場合 */
    if (mode == MODE_MODEL && line <= 9) {
      printf("%s\n", buf);
      continue;
    }

    /* コメント */
    if (buf[0] == '#') {
      printf("%s\n", buf);
      continue;
    }

    /* 分割 */
    nelem = split(buf, ' ', elem, buf_size / 2);

    /* ラベル */
    label = atoi(elem[0]);

    /* ベクトル */
    while (nelem - 1 > sv_size) {
      sv_size = 2 * sv_size + 1;
      sv.idx = srealloc(sv.idx, sizeof(int) * sv_size);
      sv.val = srealloc(sv.val, sizeof(float) * sv_size);
      fv.ftr = srealloc(fv.ftr, sizeof(char *) * sv_size);
      fv.val = srealloc(fv.val, sizeof(float) * sv_size);
    }
    for (i = 1, fv.num = 0; i < nelem; i++) {
      if (elem[i][0] == '\0') continue;	/* 2つ以上スペースがある場合 */
      s = rindex(elem[i], ':');
      exception(s == NULL, "invalid data (no colon) (line: %d)\n", line);

      *(s++) = '\0';
      fv.ftr[fv.num] = elem[i];
      fv.val[fv.num] = (float)atof(s);
      if (fv.val[fv.num] == 0.0f) continue;
      fv.num++;
    }

    /* 変換 */
    svm_fv_fv2sv(ft, &fv, &sv, 0, dup);

    /* 出力 */
    printf("%d", label);
    for (i = 0; i < sv.num; i++) {
      printf(" %d:%.7g", sv.idx[i], sv.val[i]);
    }
    printf("\n");
  }

  return 0;
}
