#!/usr/bin/python
#encoding: utf8

'''
Aplikacja konwertuje rzutowanie do wektorów uczących.
Wyjście zapisane jest do pliku.

Cechy to:
 - dziedzina plwn
 - dziedzina pwn
 - pojęcie SUMO
 - czy znaczenie plwn jest pisane z wielkiej litery?
 - relacja plwn-pwn
 - relacja pwn-SUMO
 - klasa: relacja plwn-SUMO

Wyjscie to plik w formacie:
	Naglowke rozdzielony zadanym separatorem (domuyslnie srednik)
	Kolejne mapowania i wydobyte z nich cechy (separator domyslny - srednik)

Np (średnik separatorem).
dziedzina_plwn;dziedzina_pwn;pojecie_sumo;plwn_z_duzej;rel_miedzyjezykowa;rel_sumo_pwn;klasa
por-7;por-7;Address;False;syn_pa;equivalent;equivalent 
'''

import argparse
import codecs, os, sys


# relations which will are skipped while conversion process.
FILTERED_PLWN_SUMO_RELS = ['r']

def make_parser():
    desc = 'Przekształca wyniki rzutowania na wektory uczace'
    parser = argparse.ArgumentParser(description=desc)
    parser.add_argument('-i', '--input-file', 
						dest = 'input_file',
                        required = True)
    parser.add_argument('-o', '--output-file', 
						dest='output_file', 
						required = True)
    parser.add_argument('-d', '--delimiter',
						dest = 'delimiter', default = ';');
    return parser

def read_mappings(input_file):
	"""Reads mapping file"""
	header = ''
	spl_lines = []
	first_line = True
	with codecs.open(input_file, 'rt') as infile:
		for line in infile:
			if first_line:
				header = line.strip().split(';')
				first_line = False
			else:
				spl_lines.append(line.strip().split(';'))
	return (header, spl_lines)

def _get_column_value(header, colname, mapping):
	try:
		_id = header.index(colname)
		return mapping[_id]
	except ValueError, e:
		return None

def get_plwn_domain(header, mapping):
	return _get_column_value(header, "dziedzina_plwn", mapping)

def get_pwn_domain(header, mapping):
	return _get_column_value(header, "dziedzina_pwn", mapping)

def get_sumo_concept(header, mapping):
	return _get_column_value(header, "pojecie_sumo", mapping)

def is_plwn_capital_first(header, mapping):
	plwnsyn = _get_column_value(header, "synset_str_plwn", mapping)
	if plwnsyn:
		return plwnsyn[0].isupper()
	return None

def get_plwn_pwn_i_relation(header, mapping):
	return _get_column_value(header, "rel_miedzyjezykowa", mapping)

def get_pwn_sumo_relation(header, mapping):
	return _get_column_value(header, "rel_sumo_pwn", mapping)

def get_class(mapping):
	return mapping[-1]

def get_features(header, mapping):
	"""For given mappinf returns the features
	   Available features are as follow:
	     * plwn domain
		 * pwn domain
		 * sumo concept
		 * plwn synset starts with capital letter?
		 * plwn-pwn relation
		 * pwn-SUMO relation
		 * class """
	return [
		get_plwn_domain(header, mapping),
		get_pwn_domain(header, mapping),
		get_sumo_concept(header, mapping),
		is_plwn_capital_first(header, mapping),
		get_plwn_pwn_i_relation(header, mapping),
		get_pwn_sumo_relation(header, mapping),
		get_class(mapping)]

def make_feature_header(header):
	return [
		"dziedzina_plwn", "dziedzina_pwn", 
		"pojecie_sumo", "plwn_z_duzej", 
		"rel_miedzyjezykowa", "rel_sumo_pwn",
		"klasa"]


def filter_mapping_relation(mapping):
	plwn_sumo_rel = get_class(mapping).lower()
	return plwn_sumo_rel in FILTERED_PLWN_SUMO_RELS

def filter_mapping(header, mapping):
	"""Based on the given filters, try to filter given mapping.
	   For example there we can filter mapping relation which 
	   will be converted to features - we can accept all relations
	   except R relation.

	   Return true if the mapping should be filtered, false if not"""
	return filter_mapping_relation(mapping)

def main(argv=None):
	parser = make_parser()
	args = parser.parse_args(argv)

	(header, mappings) = read_mappings(args.input_file)

	feature_header = make_feature_header(header)
	with codecs.open(args.output_file, 'wt') as fout:
		fout.write('%s\n' % 
			(('%s' % (args.delimiter)).join(str(fh) for fh in feature_header)))
		for mapping in mappings:
			if filter_mapping(header, mapping):
				continue
			features = get_features(header, mapping)
			if len(features) != len(feature_header):
				print >> sys.stderr, \
					'The number of the features colums '\
					'is different than the number of ' \
					'features in the header'
				exit(1)
			fout.write('%s\n' % 
				(('%s' % (args.delimiter)).join(str(f) for f in features)))

if __name__ == '__main__':
    main()

