#!/usr/bin/perl -w

$| = 1;

use strict;
use warnings;

push @INC, ( 'Clone-0.28', '.' );

use Socket;
use threads;

#use AI::Prolog;
#use Clone qw(clone);
use Data::Dumper;
use List::Util 'shuffle';
use Config::Std;
use IO::Socket;

use enum::fields
  qw{ NO_WORD_TYPE WORDTYPE_UNKNOWN VERB NOUN ADJ PREP PP
  ART QUESTIONWORD KOMMA SPO UNIMPORTANT LINKING INTER};

our $FULL_VERSION = "15";
our $NAME         = 'JEliza Perl rev. ' . $FULL_VERSION;
our $dir          = './';
our $config_file  = 'jeliza.cfg';
our $in_cgi_mode  = 0;

if ( not( -f $config_file ) ) {
	open my $handle, ">", $config_file;
	close $handle;
}

read_config $config_file => our %config;

our %word_types              = ();
our %cache_noun_or_not       = ();
our %noun_synonym_of         = ();
our $connected_clients       = 0;
our $working_client_requests = 0;

# fact statement in prolog:
#
# fact(verb, subj, obj, advs, quesword, descr, verb_2, subj_2, obj_2, advs_2)

my @fact_database = ();
my %fact_database_verbs = ();

my %is_inacceptable_questionword = (
	"wenn"    => 1,
	"falls"   => 1,
	"sobald"  => 1,
	"if"      => 1,
	"when"    => 1,
	"why"     => 1,
	"warum"   => 1,
	"wieso"   => 1,
	"weshalb" => 1,
	"because" => 1,
	"weil"    => 1,
	"dass"    => 1,
);

my %is_linking = (
	"und"  => 1,
	"or"   => 1,
	"and"  => 1,
	"oder" => 1,
);

my %is_be = (
	"am"   => 1,
	"is"   => 1,
	"are"  => 1,
	"be"   => 1,
	"was"  => 1,
	"were" => 1,
	"bin"  => 1,
	"bist" => 1,
	"ist"  => 1,
	"sein" => 1,
	"sind" => 1,
	"seid" => 1,
);

my %is_if_word = map { $_ => 1 } qw{if wenn when falls sobald};
my %is_something =
  map { $_ => 1 }
  qw{etwas es ihn er sie ihm ihr something someone anything anyone jemand jemanden}
  ;

my %builtin_table = (
	( map { $_ => QUESTIONWORD } qw{was wer wie wo wen wem wieso weshalb warum wann} ),
	( map { $_ => PREP } qw{in auf to im unter ueber neben mit gegen against on of about} ),
	'am'          => VERB,
	'are'         => VERB,
	'be'          => VERB,
	'is'          => VERB,
	'do'          => VERB,
	'have'        => VERB,
	'has'         => VERB,
	'done'        => ADJ,
	"und"         => LINKING,
	"oder"        => LINKING,
	"or"          => LINKING,
	"and"         => LINKING,
	"keine"       => ADJ,
	"kein"        => ADJ,
	"keines"      => ADJ,
	"keiner"      => ADJ,
	"keinem"      => ADJ,
	"keinen"      => ADJ,
	"anderen"     => ADJ,
	"denselben"   => ADJ,
	"dengleichen" => ADJ,
	"__to__"      => QUESTIONWORD,
	"_to_"        => QUESTIONWORD,
	"wem"         => QUESTIONWORD,
	"wen"         => QUESTIONWORD,
	"was"         => QUESTIONWORD,
	"wie"         => QUESTIONWORD,
	"komma"       => KOMMA,
	"der"         => ART,
	"die"         => ART,
	"das"         => ART,
	"die"         => ART,
	"des"         => ART,
	"der"         => ART,
	"des"         => ART,
	"der"         => ART,
	"dem"         => ART,
	"der"         => ART,
	"dem"         => ART,
	"den"         => ART,
	"den"         => ART,
	"die"         => ART,
	"das"         => ART,
	"die"         => ART,
	"ein"         => ART,
	"eine"        => ART,
	"eines"       => ART,
	"einer"       => ART,
	"einem"       => ART,
	"einen"       => ART,
	"eine"        => ART,
	"the"         => ART,
	'mein'        => ART,
	'meine'       => ART,
	'meiner'      => ART,
	'meinen'      => ART,
	'meinem'      => ART,
	'meins'       => NOUN,
	'dein'        => ART,
	'deine'       => ART,
	'deiner'      => ART,
	'deinen'      => ART,
	'deinem'      => ART,
	'deins'       => NOUN,
	'sein'        => ART,
	'seine'       => ART,
	'seiner'      => ART,
	'seinem'      => ART,
	'seinen'      => ART,
	'seins'       => NOUN,
	'user'        => ART,
	'unseres'     => ART,
	'unsere'      => ART,
	'unserem'     => ART,
	'unseren'     => ART,
	'euer'        => ART,
	'euers'       => ART,
	'eueres'      => ART,
	'eueren'      => ART,
	'eures'       => ART,
	'euren'       => ART,
	'eurem'       => ART,
	'ich'         => NOUN,
	'du'          => NOUN,
	'mich'        => NOUN,
	'dich'        => NOUN,
	'mir'         => NOUN,
	'dir'         => NOUN,
	'er'          => NOUN,
	'sie'         => NOUN,
	'es'          => NOUN,
	'wir'         => NOUN,
	'sie'         => NOUN,
	'uns'         => NOUN,
	'euch'        => NOUN,
	'sich'        => NOUN,
	'bin'         => VERB,
	'bist'        => VERB,
	'ist'         => VERB,
	'mag'         => VERB,
	'magst'       => VERB,
	'sein'        => VERB,
	'hast'        => VERB,
	'habe'        => VERB,
	'will'        => VERB,
	'willst'      => VERB,
	'heisse'      => VERB,
	'heise'       => VERB,
	'heisst'      => VERB,
	'ueber'       => PREP,
	((LANGUAGE() eq 'en') ? (
	
	'a' => ART,
	'an' => ART,
	'the' => ART,
	'but' => PREP,
	'than' => PREP,
	
							)
					      : ()),
);

my %string_to_constant = (
	'prep'    => PREP,
	'fw'      => QUESTIONWORD,
	'verb'    => VERB,
	'vt'      => VERB,
	'vi'      => VERB,
	'n'       => NOUN,
	'f,m'     => NOUN,
	'f,n'     => NOUN,
	'f,n,m'   => NOUN,
	'f,m,n'   => NOUN,
	'm,f'     => NOUN,
	'm,n'     => NOUN,
	'm,f,n'   => NOUN,
	'm,n,f'   => NOUN,
	'm,'      => NOUN,
	'f,'      => NOUN,
	'n,'      => NOUN,
	'inter'   => INTER,
	'n,pl'    => NOUN,
	'adj'     => ADJ,
	'adv'     => ADJ,
	'pron'    => PP,
	'ppron'   => NOUN,
	'nothing' => UNIMPORTANT
);

my %is_verb_prefix =
  map { $_ => 1 }
  qw {auf hin rauf herauf hinab hinunter an ab zusammen vor nach weg her zu in ueber unter neben herunter mit zwischen um durch}
  ;

my @verb_conjugation_table =
  ( [ 'will', 'willst' ], [ 'kannst', 'kann' ], [ 'heisst', 'heisse' ], 
    [ 'musst', 'muss' ],  [ 'magst', 'mag' ],
    [ 'am', 'are' ], );

sub load_word_types {
	open HANDLE, '<', $dir . 'lang_' . LANGUAGE() . '/word_types.dic';
	print ">> loading word types\n";
	my $count = 0;
	while ( my $line = <HANDLE> ) {
		chomp $line;
		next unless $line;
		my @line = split /[|]/, $line;
		next unless $line[0];
		my $prop_ref = $word_types{ $line[0] };
		if ( not $prop_ref ) {
			my %tmp = ();
			$prop_ref = \%tmp;
		}
		push @line, ( '-', '-' );
		$prop_ref->{'type'}  = $line[1] if $line[1] ne '-';
		$prop_ref->{'genus'} = $line[2] if $line[2] ne '-';
		$word_types{ $line[0] } = $prop_ref;

		$count += 1;
		print "\r   Loaded: " . $count if $count % 1000 == 0;
	}
	print "\n";
	close HANDLE;
}

my %has_no_genus = map { $_ => 1 }
	qw{du ich};

sub say {
	print @_;
	print "\n";
}

sub ascii {
	my ($sent) = @_;
	
	my @old = split //, $sent;
	$sent = '';
	foreach my $ind ( 0 .. @old ) {
		my $c = $old[$ind];

		next unless ord $c;

		say $c;
		say ord $c;

		if    ( ( ord $c ) == 228 ) { $sent .= 'ae' }
		elsif ( ( ord $c ) == 196 ) { $sent .= 'Ae' }
		elsif ( ( ord $c ) == 252 ) { $sent .= 'ue' }
		elsif ( ( ord $c ) == 220 ) { $sent .= 'Ue' }
		elsif ( ( ord $c ) == 246 ) { $sent .= 'oe' }
		elsif ( ( ord $c ) == 214 ) { $sent .= 'Oe' }
		elsif ( ( ord $c ) == 223 ) { $sent .= 'ss' }
		else { $sent .= $c; }
	}
	
	return $sent;
}

sub word_types_prop {
	my $CLIENT_ref = shift;
	my $CLIENT     = ${$CLIENT_ref};
	my $word       = shift;
	
	if ( $has_no_genus{ $word } ) {
		$word_types{$word}->{'genus'} = q{};
	}

	if ( not $word_types{$word}->{'genus'} ) {
		$word_types{$word}->{'genus'} = q{};    # empty
	}
	if ( word_type_of( $CLIENT_ref, $word, 0 ) == NOUN && !$has_no_genus{ $word } ) {
		if (
			!$word_types{$word}->{'genus'}
			|| (
				  $word_types{$word}->{'genus'}
				? $word_types{$word}->{'genus'}
				: q{-}
			) eq '-'
			|| length( $word_types{$word}->{'genus'} ) == 0
		  )
		{
			my $type_str = q{}; # empty
			
			if (!$has_no_genus{ $word }) {
				my $line = impl_get_genus( $CLIENT_ref, $word );
	
				$type_str =
				    $line == 1 ? 'm'
			  	  : $line == 2 ? 'w'
			      : $line == 3 ? 's'
			      : '';
			}

			if ( !$type_str && !$has_no_genus{ $word } ) {
				print "Redoing: word_types_prop( $CLIENT_ref, $word )\n";
				return word_types_prop( $CLIENT_ref, $word );
			}

			my $prop_ref = $word_types{$word};
			if ( not $prop_ref ) {
				my %tmp = ();
				$prop_ref = \%tmp;
			}
			$prop_ref->{'genus'} = $type_str;
			$word_types{$word} = $prop_ref;

			open HANDLE, '>>',
			  $dir . 'lang_' . LANGUAGE() . '/word_types.dic';
			print HANDLE $word . '|-|' . $type_str . "\n";
			close HANDLE;

		}
	}

	print '$word_types{"' . $word
	  . '"}->{"genus"}'
	  . $word_types{$word}->{'genus'} . "\n";

	return $word_types{$word};
}

sub word_type_of {
#	print "word_type_of: ", ( join ', ', @_ ), "\n";
	my ($CLIENT_ref,
		$word,
		$at_beginning_of_sentence,
		$noun_automatism,
		$do_not_ask_user)
		= @_;

	my $CLIENT     = ${$CLIENT_ref};
	$noun_automatism = 1 unless defined $noun_automatism;

	$word =~ tr/{//d;
	$word =~ tr/}//d;
	$word =~ tr{/}{}d;
	$word =~ tr/|//d;
	chomp $word;

	return ADJ if $word =~ /^[-+]?\d+$/;
	return ADJ if $word =~ /^[+-]?(\d+\.\d+|\d+\.|\.\d+|\d+)([eE][+-]?\d+)?$/;
	return ADJ if $word =~ /^\d+$/;
	return ADJ if $word =~ /^\d+[_]\d+[_]\d+$/;

	return NO_WORD_TYPE unless $word;
	return NO_WORD_TYPE if $word =~ /^[?,;]/;
	return ADJ          if $word =~ /[(]/;
	return NOUN         if $word =~ /http[:]/i;
	return NOUN         if $word =~ /['"]/;
	return NOUN         if $word =~ /_/;
	return NOUN         if $word =~ /[%]/;

	$word =~ s/\.|[?!,;]//gm;

	my $word_low = lc $word;
	
	if ($word_low =~ /end$/ && length($word) >= 6) {
		my $word_to_check = $word_low;
		$word_to_check =~ s/[a-z]$//; # no 'g', only once!
		
		if (word_type_of(	$CLIENT_ref, 
							$word_to_check,
							0,
							0,
							0) == VERB) {
								return ADJ;
							}
	}

	if ($word_low =~ /(ed|ing)$/ && length($word) >= 6 && LANGUAGE() eq 'en') {
		my $word_to_check = $word_low;
		$word_to_check =~ s/(ed|ing)$//; # no 'g', only once!
		
		if (word_type_of(	$CLIENT_ref, 
							$word_to_check,
							0,
							0,
							0) == VERB) {
								return ADJ;
							}
		if (word_type_of(	$CLIENT_ref, 
							$word_to_check . 'e',
							0,
							0,
							1) == VERB) {
								return ADJ;
							}
	}

	if ( defined $builtin_table{$word_low} ) {
		return $builtin_table{$word_low};
	}

	if ($at_beginning_of_sentence) {
		my $in_cache = $cache_noun_or_not{$word_low};
		if ( !$in_cache ) {
			$in_cache = WORDTYPE_UNKNOWN;
		}
		return $in_cache if $in_cache == NOUN;
		return $in_cache if $in_cache == VERB;
		return $in_cache if $in_cache == ADJ;

		#if ( $in_cache != WORDTYPE_UNKNOWN ) {
		my $wt1 = WORDTYPE_UNKNOWN;
		my $wt2 = WORDTYPE_UNKNOWN;
		if ( $word ne lc $word ) {
			$wt1 = word_type_of( $CLIENT_ref, lc $word, 0, 0 );
			$wt2 = word_type_of( $CLIENT_ref, ucfirst $word, 0, 0 );
			if ( $wt1 == QUESTIONWORD || $wt2 == QUESTIONWORD ) {
				return QUESTIONWORD;
			}
		}
		if ( $wt1 != $wt2 && $word ne lc $word ) {
			my $line = impl_get_noun_or_not( $CLIENT_ref, $word );

			if ( $line == 1 ) {
				$cache_noun_or_not{$word_low} = NOUN;
			}
			elsif ( $line == 2 ) {
				$cache_noun_or_not{$word_low} = $wt1;
			}
			else {
				print "Illegal Command: HERE_IS_NOUN_OR_NOT:" . $line . "\n";
			}

			#			last;

		}

		#}

	}

	my $type = q{};    # empty
	if ($at_beginning_of_sentence) {
		my $prop_ref = $word_types{$word_low};
		if ( $prop_ref->{'type'} ) {
			$type = $prop_ref->{'type'};
		}
	}
	my $prop_ref = $word_types{$word};
	if ( $prop_ref->{'type'} && !$type ) {
		$type = $prop_ref->{'type'};
	}

	#	print "type of " . $word . " is " . $type . "\n";

	if ( $string_to_constant{$type} ) {

	  #		print "success: " . $type . " is " . $string_to_constant{$type} . "\n";
		return $string_to_constant{$type};
	}

	print "failure: " . $word . '[' . $type . "] not known\n";
	
	my $downloaded = download_word_type($CLIENT_ref, $word,
										$at_beginning_of_sentence);
										
#	return $downloaded if ($downloaded != NO_WORD_TYPE);
	
	if ($do_not_ask_user && $downloaded == NO_WORD_TYPE) {
		return;
	}
	
	if (!$at_beginning_of_sentence && $word_low ne $word && $noun_automatism && $downloaded == NO_WORD_TYPE) {
		return NOUN;
	}

	my $line = ($downloaded != NO_WORD_TYPE) ? ($downloaded - 1)
		                                     : ( impl_get_word_type ($CLIENT_ref, $word ) )
		     ;
		     
	print '$line: ', $line, "\n";

	my $type_str =
	    $line == 1 ? 'vt'
	  : $line == 2 ? 'n,'
	  : $line == 3 ? 'adj'
	  : $line == 4 ? 'n,'
	  : $line == 5 ? 'fw'
	  : $line == 6 ? 'prep'
	  : $line == 7 ? 'inter'
	  : 'nothing';

	$prop_ref = $word_types{$word};
	if ( not $prop_ref ) {
		my %tmp = ();
		$prop_ref = \%tmp;
	}
	$prop_ref->{'type'} = $type_str;
	$word_types{$word} = $prop_ref;

	open HANDLE, '>>', $dir . 'lang_' . LANGUAGE() . '/word_types.dic' or 
		die 'Cannot write to: ' . $dir . 'lang_' . LANGUAGE() . '/word_types.dic';
	print HANDLE $word . '|' . $type_str . "\n";
	close HANDLE;

	return word_type_of( $CLIENT_ref, $word, $at_beginning_of_sentence,
		$noun_automatism );

	return NO_WORD_TYPE;
}

sub is_name {
	my $name = lc shift;
	$name =~ s/[_]/ /igm;
	chomp $name;

	open my $NO_NAMES, '<',
	  $dir . "lang_" . LANGUAGE() . "/wsh/no-names.wsh";
	while ( my $fn = lc <$NO_NAMES> ) {
		chomp $fn;

		$fn =~ s/[_]/ /igm;
		$fn =~ s/(^|\s)nothing(\s|$)//igm;
		$fn =~ s/nothing\s//igm;

		#		print "$fn eq $name\n";
		if ( $fn eq $name ) {
			return 0;
		}
	}
	close $NO_NAMES;

	open my $FIRST_NAMES, '<',
	  $dir . "lang_" . LANGUAGE() . "/wsh/names.wsh";
	while ( my $fn = lc <$FIRST_NAMES> ) {
		chomp $fn;

		$fn =~ s/[_]/ /igm;
		$fn =~ s/(^|\s)nothing(\s|$)//igm;
		$fn =~ s/nothing\s//igm;

		#		print "$fn eq $name\n";
		if ( $fn eq $name ) {
			return 1;
		}
	}
	close $FIRST_NAMES;

	return 0;
}

sub split_sentence {
	my $CLIENT_ref = shift;
	my $CLIENT     = ${$CLIENT_ref};
	my $text       = shift;
	$text =~ s/[{}]//gm;
	$text =~ s/  / /gm;

	$text =~ s/kennst du/was ist/igm;

	print "split_sentence: " . $text . "\n";
	
	$text =~ s/["](.*?)["]/"_$1_" /igm;
	$text =~ s/["]([a-zA-Z0-9_,;-=)(]+)\s([a-zA-Z0-9_,;-=\)\(]+)["]/"$1_$2" /igm;
	$text =~ s/["]/ /igm;
	$text =~ s/\s\s/ /igm;

#	my @copy = split //, $text;
#	$text = q{};    # empty
#	while ( defined( my $char = $copy[0] ) ) {
#		shift @copy;
#		if ( $char eq q{"} ) {    # for all in "´s
##			$text .= '_';
	#		while ( my $char = $copy[0] ) {
	#			shift @copy;
	#			if ( $char eq q{"} ) {
#					$text .= '_';
#					last;
#				}
#				elsif ( $char eq q{ } ) {
#					$text .= '_';    # replace " " by "_"
#				}
#				else {
#					$text .= $char;
#				}
#			}
#		}
#		else {
#			$text .= $char;
#		}
#	}

	$text =~ s/, /,/gm;
	$text =~ s/ ,/,/gm;
	$text =~ s/,/ KOMMA /gm;

	print '>> Sentence: ' . $text . "\n";

	my @words = split /[ !.;]/, $text;
	my @new_words_array = ();
	my $adverbs;
	my $in_adverbial                    = 0;
	my $last_word                       = q{};                # empty
	my $last_word_type                  = WORDTYPE_UNKNOWN;
	my $first_word_type                 = WORDTYPE_UNKNOWN;
	my $adverbial                       = q{};                # empty
	my $is_a_question                   = 0;
	my $word_is_first_word_is_adjective = 0;
	my $verb_prefix_to_add              = q{};                # empty

	for my $x ( 0 .. $#words ) {
		my $word = $words[$x];
		if ( $word =~ /[?]/ ) {
			$is_a_question = 1;
			$word =~ s/[?]//gm;
		}
		$words[$x] = $word;
	}
	@words = grep { $_ } @words;

	if ( $is_verb_prefix{ $words[-1] } ) {
		$verb_prefix_to_add = pop @words;
	}
	if ( $words[-1] =~ /[?]/ && $is_verb_prefix{ $words[-2] } ) {
		$verb_prefix_to_add = pop @words;
	}

	my $remove_second_word_too = 0;
	if ( $words[0] =~ /[,]/ ) {
		$words[0] =~ s/[,]//gm;
	}
	if ( $words[1] =~ /[,]/ ) {
		$words[1] =~ s/[,]//gm;
		$remove_second_word_too = 1;
	}

	my $first_is_interj =
	  ( word_type_of( $CLIENT_ref, $words[0], 1 ) == INTER );
	shift @words if $first_is_interj;
	shift @words if $first_is_interj && $remove_second_word_too;

	for my $x ( 0 .. $#words ) {
		my $word = $words[$x];
		if ( $word =~ /[?]/ ) {
			$is_a_question = 1;
			$word =~ s/[?]//gm;
		}
		my $word_next;
		my $wt_next;
	  FIND_NEXT_WORD:
		for my $d ( $x .. $#words ) {
			my $word_lower_scope = $words[$d];

			#			print "d:word_lower_scope:$d:$word_lower_scope\n";
			$wt_next = ( word_type_of $CLIENT_ref, $word_lower_scope, $d == 0 );
			$wt_next = NOUN if $wt_next == PP;
			if ( $wt_next == NOUN ) {
				
				my $next_word_is_participle = 0;
				
				my $word_next = $words[$d+1];
				
				if ( word_type_of( $CLIENT_ref, $word_next, 0 ) == ADJ && 
					( $word_next =~ /(end)|(ende)|(enden)|(endes)|(ender)$/ ) ) {
					$next_word_is_participle = 1;
				}
				
				next if $next_word_is_participle;
				
				
				$word_next = $words[$d];
				last FIND_NEXT_WORD;
			}
		}
		my $word_tmp = $words[$x];
		chomp $word;
		chomp $word_tmp;
		my $wt = word_type_of( $CLIENT_ref, $word, $x == 0 );

		if ( $wt == VERB ) {
			$word = $verb_prefix_to_add . $word;
		}
		
		if ( $last_word_type == KOMMA && $wt == PREP ) {
			$wt = QUESTIONWORD;
		}

		if (   $wt == ADJ
			&& $word_is_first_word_is_adjective != 2
			&& $wt_next != NOUN )
		{
			$word_is_first_word_is_adjective = 1;
		}
		else {
			$word_is_first_word_is_adjective = 2;
		}

		#		print 'word_type_of( $CLIENT_ref, ' . $word . ', '
		#		  . ( $x == 0 ) . ' ): '
		#		  . $wt . "\n";

		if ( is_name( $word . ' ' . $words[ $x + 1 ] . ' ' . $words[ $x + 2 ] )
			&& $x + 1 < scalar @words
			&& $wt == NOUN
			&& word_type_of( $CLIENT_ref, $words[ $x + 1 ], 0 ) == NOUN
			&& word_type_of( $CLIENT_ref, $words[ $x + 2 ], 0 ) == NOUN )
		{
			$words[ $x + 2 ] =
			  $word . "_" . $words[ $x + 1 ] . "_" . $words[ $x + 2 ];
			next;
		}

		if (   is_name( $word . ' ' . $words[ $x + 1 ] )
			&& $x + 1 < scalar @words
			&& $wt == NOUN
			&& word_type_of( $CLIENT_ref, $words[ $x + 1 ], 0 ) == NOUN )
		{
			$words[ $x + 1 ] = $word . "_" . $words[ $x + 1 ];
			next;
		}


		if ( $wt == UNIMPORTANT ) {
			next;
		}

		if ( $first_word_type == WORDTYPE_UNKNOWN ) {
			$first_word_type = $wt;
		}
		if ( $wt == PP ) {
			$wt = NOUN;
		}

		if ( $wt == ART ) {
			$word_tmp .= " - Artikel";
		}
		if ( $wt == ADJ ) {
			$word_tmp .= " - Adjektiv";
		}
		if ( $wt == NOUN ) {
			$word_tmp .= " - NOUN";
		}
		if ( $wt == VERB ) {
			$word_tmp .= " - Verb";
		}
		if ( $wt == QUESTIONWORD ) {
			$word_tmp .= " - questionwort";
		}
		if ( $wt == PREP ) {
			$word_tmp .= " - Praeposition";
		}
		if ( $wt == SPO ) {
			$word_tmp .= " - Subjekt/Verb/Objekt";
		}
		if ( $wt == KOMMA ) {
			$word_tmp .= " - ein Komma";
		}

		if ( $wt == $last_word_type && $wt == NOUN && $in_adverbial ) {
			if ( !is_name($word)
				|| is_name($last_word) )
			{
				$in_adverbial = 0;
			}
		}

		if ( $wt == PREP ) {
			if ( $last_word_type == ART ) {
				push @new_words_array, [ 'nothing', NOUN, q{} ];
			}
			
			if ( $last_word_type != KOMMA ) {
				$in_adverbial = 1;
			}
		}
		if ( $wt == VERB ) {
			if ( !is_name($word)
				|| is_name($last_word) )
			{
				$in_adverbial = 0;
			}
		}

		if ( $wt == ART && LANGUAGE() == 'de' && $last_word_type != KOMMA ) {
			print 'word_next:' . $word_next . "\n";
			my $g = word_types_prop( $CLIENT_ref, $word_next )->{'genus'};

			if ( $g eq q{m} ) {
				if (   lc $word ne "der"
					&& lc $word ne "den"
					&& lc $word ne "ein"
					&& lc $word ne "einen"
					&& lc $word ne "mein"
					&& lc $word ne "meines"
					&& lc $word ne "dein"
					&& lc $word ne "deines"
					&& lc $word ne "sein"
					&& lc $word ne "seines"
					&& lc $word ne "unser"
					&& lc $word ne "unseres"
					&& lc $word ne "unsers"
					&& lc $word ne "euer"
					&& lc $word ne "eures"
					&& lc $word ne "eueres"
					&& lc $word ne "euers"
					&& lc $word ne "ihr"
					&& lc $word ne "ihres" )
				{
					$in_adverbial = 1;
				}
			}
			if ( $g eq q{w} ) {
				if (   lc $word ne "die"
					&& lc $word ne "eine"
					&& lc $word ne "einer"
					&& lc $word ne "meine"
					&& lc $word ne "meiner"
					&& lc $word ne "deine"
					&& lc $word ne "deiner"
					&& lc $word ne "seine"
					&& lc $word ne "seiner"
					&& lc $word ne "unsere"
					&& lc $word ne "unserer"
					&& lc $word ne "unserer"
					&& lc $word ne "euere"
					&& lc $word ne "eurer"
					&& lc $word ne "euerer"
					&& lc $word ne "euere"
					&& lc $word ne "ihre"
					&& lc $word ne "ihrer" )
				{
					$in_adverbial = 1;
				}
			}
			if ( $g eq q{s} ) {
				if (   lc $word ne "das"
					&& lc $word ne "eines"
					&& lc $word ne "ein"
					&& lc $word ne "mein"
					&& lc $word ne "meines"
					&& lc $word ne "dein"
					&& lc $word ne "deines"
					&& lc $word ne "sein"
					&& lc $word ne "seines"
					&& lc $word ne "unser"
					&& lc $word ne "unseres"
					&& lc $word ne "unsers"
					&& lc $word ne "euer"
					&& lc $word ne "eures"
					&& lc $word ne "eueres"
					&& lc $word ne "euers"
					&& lc $word ne "ihr"
					&& lc $word ne "ihres" )
				{
					$in_adverbial = 1;
				}
			}
		}

		my $ist_einzelnes_adjektiv = 0;
		if ( $wt == ADJ ) {
			my $has_no_noun_behind = 1;
			if ( $x + 1 >= scalar @words ) {
				$has_no_noun_behind = 1;
			}
			my $wt_1 = WORDTYPE_UNKNOWN;
			my $wt_2 = WORDTYPE_UNKNOWN;
			my $wt_3 = WORDTYPE_UNKNOWN;
			if ( $x + 1 < scalar @words ) {
				$wt_1 = word_type_of( $CLIENT_ref, $words[ $x + 1 ], 0 );
				if ( $wt_1 == NOUN || $wt_1 == PP ) {
					print '('
					  . ( $wt_1 == NOUN ) . ' || '
					  . ( $wt_1 == PP ) . ")\n";
					$has_no_noun_behind = 0;
				}
			}
			if ( $x + 2 < scalar @words && $wt_1 != KOMMA ) {
				$wt_2 = word_type_of( $CLIENT_ref, $words[ $x + 2 ], 0 );
				if ( $wt_2 == NOUN || $wt_2 == PP ) {
					print "("
					  . ( $wt_2 == NOUN ) . " || "
					  . ( $wt_2 == PP ) . ") && "
					  . ( $wt_1 != KOMMA ) . "\n";
					$has_no_noun_behind = 0;
				}
			}
			if ( $x + 3 < scalar @words ) {
				if ( $words[ $x + 1 ] ne "," && $words[ $x + 2 ] ne "," ) {
					$wt_3 = word_type_of( $CLIENT_ref, $words[ $x + 3 ], 0 );
					if ( $wt_3 == NOUN || $wt_3 == PP ) {
						print "("
						  . ( $wt_3 == NOUN ) . " || "
						  . ( $wt_3 == PP ) . ") && "
						  . ( $wt_1 != KOMMA ) . " && "
						  . ( $wt_2 != KOMMA ) . "|"
						  . $wt_1
						  . $wt_2
						  . $words[ $x + 1 ] . ";"
						  . $words[ $x + 2 ] . "\n";
						$has_no_noun_behind = 0;
					}
				}
			}
			if ($has_no_noun_behind) {
				$ist_einzelnes_adjektiv = 1;
			}
		}
		my $before_questionword = 0;
		if ( $x + 1 < scalar @words ) {
			my $wt_ = word_type_of( $CLIENT_ref, $words[ $x + 1 ], 0 );
			if ( $wt_ == QUESTIONWORD ) {
				$before_questionword = 1;
				if ( !is_name($word)
					|| is_name($last_word) )
				{
					$in_adverbial = 0;
				}
			}
		}
		my $after_questionword = 0;
		if ( $x - 1 < scalar @words && $x - 1 >= 0 ) {
			my $wt_ = word_type_of( $CLIENT_ref, $words[ $x - 1 ], 0 );
			if (
				$wt_ == QUESTIONWORD
				&& (   lc $words[ $x - 1 ] ne "wenn"
					&& lc $words[ $x - 1 ] ne "falls"
					&& lc $words[ $x - 1 ] ne "sobald"
					&& lc $words[ $x - 1 ] ne "if"
					&& lc $words[ $x - 1 ] ne "when"
					&& lc $words[ $x - 1 ] ne "why"
					&& lc $words[ $x - 1 ] ne "warum"
					&& lc $words[ $x - 1 ] ne "wieso"
					&& lc $words[ $x - 1 ] ne "weshalb"
					&& lc $words[ $x - 1 ] ne "because"
					&& lc $words[ $x - 1 ] ne "weil" )
			  )
			{
				$after_questionword = 1;
				if ( !is_name( lc $word )
					|| is_name( lc $last_word ) )
				{
					$in_adverbial = 0;
				}
			}
		}
		my $verb_in_sicht = 0;
		if ( $x < scalar @words ) {
			my $wt_ = word_type_of( $CLIENT_ref, $words[$x], 0 );
			if ( $wt_ == VERB ) {
				$verb_in_sicht = 1;
			}
		}
		if ( $x + 1 < scalar @words ) {
			my $wt_ = word_type_of( $CLIENT_ref, $words[ $x + 1 ], 0 );
			if ( $wt_ == VERB ) {
				$verb_in_sicht = 1;
			}
		}
		if ( $x + 2 < scalar @words ) {
			my $wt_ = word_type_of( $CLIENT_ref, $words[ $x + 2 ], 0 );
			if ( $wt_ == VERB ) {
				$verb_in_sicht = 1;
			}
		}
		if ( $x + 3 < scalar @words ) {
			my $wt_ = word_type_of( $CLIENT_ref, $words[ $x + 3 ], 0 );
			if ( $wt_ == VERB ) {
				$verb_in_sicht = 1;
			}
		}


		if ( $in_adverbial && $wt == VERB ) {
			$in_adverbial = 0;
		}

		if (
			   ( $before_questionword || $after_questionword )
			&& ( $wt == ART || $wt == NOUN || $wt == ADJ || $wt == PREP )
			&& $verb_in_sicht
			&& (
				(
					  ( $x - 1 >= 0 )
					? ( $words[ $x - 1 ] )
					: q{}
				) ne "dass"
			)
		  )
		{
			$adverbial .= " ";
			$adverbial .= $word;
			chomp $adverbial;
		}
		elsif ($in_adverbial) {
			$adverbial .= " ";
			$adverbial .= $word;
			chomp $adverbial;
		}
		elsif ($ist_einzelnes_adjektiv) {
			$adverbial .= " ";
			$adverbial .= $word;
			chomp $adverbial;
		}
		elsif ( $word_is_first_word_is_adjective == 1 ) {
			$adverbial .= " ";
			$adverbial .= $word;
			chomp $adverbial;
		}
		else {
			if (@new_words_array) {
				$new_words_array[-1]->[2] .= $adverbial;
				push @new_words_array, [ $word, $wt, q{} ];
			}
			else {
				push @new_words_array, [ $word, $wt, $adverbial ];
			}
			if ( length($adverbial) != 0 ) {
				$adverbial = q{};    # empty
			}
			if ( !is_name($word)
				|| is_name($last_word) )
			{
				$in_adverbial = 0;
			}
		}

		if ( $wt == NOUN ) {
			$in_adverbial = 0;
		}

		print $in_adverbial
		  . $ist_einzelnes_adjektiv
		  . $before_questionword
		  . $after_questionword
		  . $verb_in_sicht
#		  . $in_adverbial_backup
          . " "
		  . $word_tmp
		  . $wt
		  . $last_word . "\n";

		$last_word_type = $wt;
		$last_word      = $word;
	}

	if ( length($adverbial) != 0 ) {
		if ( @new_words_array > 0 ) {
			$new_words_array[-1]->[2] .= " " . $adverbial;
			chomp $new_words_array[-1]->[2];
			$adverbial = q{};    # empty
		}
	}
	else {
		push @new_words_array, [ q{nothing}, $last_word_type, $adverbial ];
	}

	foreach my $item (@new_words_array) {
		my $to_print = join ";", @$item;
		print $to_print . "\n";
	}

	sub left_until_article_or_other_noun_end {
		my @word_list = @_;

		my @noun = ();

		my $verb_is_first_or_last_word = 0;
		my $already_passed_verb        = 0;
		my $passed_nouns               = 0;
		my $have_seen_nouns            = 0;
		if ( $word_list[0]->[1] == VERB ) {
			$verb_is_first_or_last_word = 1;
		}
		if ( $word_list[-1]->[1] == VERB ) {
			$verb_is_first_or_last_word = 1;
		}
		
		say '\@word_list:';
		print Dumper \@word_list;
		
		say '$verb_is_first_or_last_word: ', $verb_is_first_or_last_word;

		foreach my $item_ref ( reverse @word_list ) {
			if ( $item_ref->[1] == NOUN ) {
				$have_seen_nouns = 1
				  if !$verb_is_first_or_last_word;
				if ( !$passed_nouns && $have_seen_nouns ) {
					push @noun, [@$item_ref];
				}
				else {
					last;
				}
			}
			elsif ( $item_ref->[1] == ADJ ) {
				push @noun, [@$item_ref];
				$passed_nouns = 1 if $have_seen_nouns;
			}
			elsif ( $item_ref->[1] == ART ) {
				push @noun, [@$item_ref];
				last;
			}
			else {
				last;
			}
		}

		return reverse @noun;
	}
	
	my %is_article_for_subject =
		map { $_ => 1 }
		qw{der die das welcher welches welche};
	
	my %is_article_for_object =
		map { $_ => 1 }
		qw{den dem welchem welchen};
	
	my @clauses_with_relative_sentences = ();

	my @new_words                 = ( [] );
	my @new_words_komma_adverbial = ( [] );
	my $index = 0;
	my $word_count = -1;
	while (my $item = shift @new_words_array) {
		my $is_komma = (( join ";", @$item ) =~ /KOMMA/i);
		$word_count += 1;
		if ( $is_komma || $word_count == 0 ) {
			say "ITEM:", (join ', ', @$item);

			my @rest_of_sentence = ();
		
			while (my $item = shift @new_words_array) {
				if ($item->[1] == QUESTIONWORD) {
					push @rest_of_sentence, $item;
					unshift @new_words_array, $item;
					last;
				}
				if ( ( join ";", @$item ) =~ /KOMMA/i ) {
					unshift @new_words_array, $item;
					last;
				}
				push @rest_of_sentence, $item;
			}
				
			my @count_of_verbs = grep { $_->[1] == VERB } @rest_of_sentence;
			if (!@count_of_verbs || $word_count == 0) {
				unshift @new_words_array, @rest_of_sentence;
#				unshift @new_words_array, $article;
			}

			if ( $is_komma && $rest_of_sentence[0]->[1] == ART && $index >= 0 && @count_of_verbs ) {
				my $article = shift @rest_of_sentence;

				my @as_subj = ();
				my @as_obj = ();
				
				if ( $is_article_for_subject{ $article->[0] } ) {
					@as_subj = 	left_until_article_or_other_noun_end(
									@{ $new_words[ $index ] }
								);
				}
				
				if ( $is_article_for_object{ $article->[0] } ) {
					@as_obj = 	left_until_article_or_other_noun_end(
									@{ $new_words[ $index ] }
								);
				}
				
				if (@count_of_verbs) {
					push @clauses_with_relative_sentences,
				      [
					    [
							@as_subj,
							@rest_of_sentence,
							@as_obj,
					    ]
				      ];
				   	print Dumper 					    [
							@as_subj,
							@rest_of_sentence,
							@as_obj,
					    ];
				}
				shift @new_words_array;
			}
			elsif ($is_komma
			    && $rest_of_sentence[0]->[1] == PREP
				&& $rest_of_sentence[1]->[1] == ART
				&& $index >= 0
				&& @count_of_verbs )
			{
				my $prep = shift @rest_of_sentence;
				my $article = shift @rest_of_sentence;
				
				my @as_subj = ();
				my @as_obj = ();
				
				my @things 
				          = ['nothing', NOUN, $prep->[0] . (($prep->[2])?' ':'') . $prep->[2] . ' ' .
								(join ' ', map { $_->[0] . ($_->[2] ? ' ' : '') . $_->[2] } 
									left_until_article_or_other_noun_end(
									@{ $new_words[ $index ] } )
								)
							];
				
				if ( $is_article_for_subject{ $article->[0] } ) {
					@as_subj = 	@things;
				}
				
				if ( $is_article_for_object{ $article->[0] } ) {
					@as_obj = 	@things;
				}
				
				if (@count_of_verbs) {
					push @clauses_with_relative_sentences,
				      [
					    [
					    	@as_subj,
							@rest_of_sentence,
							@as_obj,
					    ]
				      ];
				}
				shift @new_words_array;
			}
			else {
				print '@count_of_verbs: ', Dumper \@count_of_verbs;
				say '$rest_of_sentence[0]->[1] == QUESTIONWORD: ',
					$rest_of_sentence[0]->[1] == QUESTIONWORD;

				if (@count_of_verbs || $rest_of_sentence[0]->[1] == QUESTIONWORD) {
					if ($word_count > 0) {
						# begin a new komma subclause
						print 'Clearing @tmp:' . ( @{ $new_words[$index] } ) . "\n";
						push @new_words, [];
						push @new_words_komma_adverbial, [];
						$index += 1;
					}
					if ($word_count == 0) {
						push @{ $new_words[$index] }, $item;
					}
				}

				else {
					if ($word_count > 0) {
						my $adverbial_string
							= join ' ', map { $_->[0] . ' ' . $_->[2] } @rest_of_sentence;
						$adverbial_string =~ s/\s+/ /igm;
						$adverbial_string =~ s/(\s+$)|(^\s+)//igm;
						$adverbial_string =~ s/\s/_/igm;
#					$adverbial_string = '(' . $adverbial_string . ')';
#					push @{ $new_words[$index] },
#						[ $adverbial_string, ADJ, q{} ];
						$new_words_komma_adverbial[$index] = []
							if !($new_words_komma_adverbial[$index]);
						push @{ $new_words_komma_adverbial[$index] },
							$adverbial_string;
							
						while (my $item = shift @new_words_array) {
							if ( ( join ";", @$item ) =~ /KOMMA/i ) {
								last;
							}
							push @rest_of_sentence, $item;
						}
					}
					else {
#						unshift @new_words_array, @rest_of_sentence;
						push @{ $new_words[$index] }, $item;
					}
				}
			}
		}
		else {
			push @{ $new_words[$index] }, $item;
		}
	}
	
	foreach my $ind (0..@new_words_komma_adverbial) {
		next if !$new_words_komma_adverbial[$ind];
		if ( @{ $new_words_komma_adverbial[$ind] } ) {
			push @{ $new_words[$index] },
				[ 	'nothing',
					NOUN, 
					'(' . (join '_', @{ $new_words_komma_adverbial[$ind] }) . ')' ];
		}
	}

	my @queswords = ();
	my @clauses   = ();
	foreach my $list_item (@new_words) {
		my @clause = @$list_item;
		my ( $clause_ref, $descr, $quesword ) =
		  remove_questionword_and_description(@$list_item);
		if ($clause_ref) {
			@clause = @$clause_ref;
		}

		say(    'clause: '
			  . ( join "--", ( map { join ',', @$_ } @clause ) ) . ", "
			  . $descr . ", "
			  . $quesword );

		my @real_clauses       = ( [ [ $quesword, QUESTIONWORD, $descr ] ] );
		my $index              = 0;
		my @items_already_over = ();
		while ( my $item = shift @clause ) {
			last if !$item;

			#			last if scalar @$item != 3;
			push @items_already_over, $item;
			my ( $word, $type, $adv ) = @$item;

			my $next_relevant_word_is_verb = 0;
			if (@clause) {
				if ( $clause[0][1] == VERB ) {
					$next_relevant_word_is_verb = 1;
				}
			}

			my $last_relevant_word_is_verb = 0;
			if ( @items_already_over >= 2 ) {
				if ( $items_already_over[-2][1] == VERB ) {
					$last_relevant_word_is_verb = 1;
				}
			}

			my $there_is_a_verb_before_a_linking_word_after  = 0;
			my $there_is_a_verb_before_a_linking_word_before = 0;

		  AFTER:
			foreach my $item_next (@clause) {
				my ( $word_next, $type_next, $adv_next ) = @$item_next;
				if ( $is_linking{ lc $word_next } ) {
					last AFTER;
				}
				elsif ( $type_next == VERB ) {
					$there_is_a_verb_before_a_linking_word_after = 1;
					last AFTER;
				}
			}

			my @missing_subject = ();
		  BEFORE:
			foreach my $item_next (
				( reverse @items_already_over )[ 1 .. $#items_already_over ] )
			{
				my ( $word_next, $type_next, $adv_next ) = @$item_next;

				#				print "report-2: ", $word_next, ",,", $type_next, ",,",
				#				  $adv_next, "\n";
				if ( $is_linking{ lc $word_next }
					&& !$there_is_a_verb_before_a_linking_word_before )
				{
					last BEFORE;
				}
				if ( $type_next == VERB ) {
					$there_is_a_verb_before_a_linking_word_before = 1;
				}
				elsif ($there_is_a_verb_before_a_linking_word_before) {
					if ( $is_linking{ lc $word_next } ) {
						if ( scalar @missing_subject == 0 ) {
							next BEFORE;
						}
					}
					push @missing_subject, $item_next;
				}
			}

			#			say(
			#				'Report:',
			#				lc $word,
			#				'||',
			#				( $is_linking{ lc $word } ? $is_linking{ lc $word } : '0' ),
			#				'||',
			#				$next_relevant_word_is_verb,
			#				'||',
			#				$last_relevant_word_is_verb,
			#				'||',
			#				$there_is_a_verb_before_a_linking_word_after,
			#				'||',
			#				$there_is_a_verb_before_a_linking_word_before,
			#			);

			if (
				$is_linking{ lc $word }
				&& (   $next_relevant_word_is_verb
					|| $last_relevant_word_is_verb )
				&& $there_is_a_verb_before_a_linking_word_after
				&& $there_is_a_verb_before_a_linking_word_before
			  )
			{
				say( 'Clearing @real_clauses:',
					( scalar @{ $real_clauses[$index] } ) );
				if ($next_relevant_word_is_verb) {
					@missing_subject = reverse @missing_subject;
					say( 'Missing subject words:',
						join ", ", map { ${$_}[0] } @missing_subject );
					push @real_clauses, \@missing_subject;
				}
				else {
					say('No missing subjects needed.');
					push @real_clauses, [];
				}
				$index += 1;
			}
			else {
				push @{ $real_clauses[$index] }, $item;
			}
		}

		my @clauses_new = ();
		foreach my $subclauses (@clauses) {
			foreach my $arr_clause1 (@$subclauses) {
				my @arr_2 = @$arr_clause1;
				my @arr   = @arr_2;
				foreach my $arr_clause2 (@real_clauses) {
					push @clauses_new, [ \@arr, $arr_clause2 ];
					say( 'push @clauses_new, [ ',
						$arr_clause1, ', ', $arr_clause2, ' ];' );
				}
			}
			if ( not @$subclauses ) {
				foreach my $arr_clause2 (@real_clauses) {
					push @clauses_new, [ $arr_clause2, ];
					say( 'push @clauses_new, [',
						( map { join "," } $arr_clause2 ), '];' );
				}
			}
		}
		if ( not @clauses ) {
			foreach my $arr_clause2 (@real_clauses) {
				push @clauses_new, [ $arr_clause2, ];
				say( 'push @clauses_new, [',
					( map { join "," } $arr_clause2 ), '];' );
			}
		}
		@clauses = @clauses_new;
	}
	push @clauses, @clauses_with_relative_sentences;
	say( "Clauses: ", scalar @clauses );

	my @sentences = ();
	foreach my $sentence (@clauses) {
		say("Sentence:");
		my @hashs_subclauses = ();

		foreach my $clause_ref (@$sentence) {
			my $quesword                    = q{};                     # empty
			my $descr                       = q{};                     # empty
			my @subjects                    = ( [ 'nothing', '' ] );
			my @objects                     = ( [ 'nothing', '' ] );
			my $obj_has_been_added_to_array = 0;
			my $index_subj                  = 0;
			my $index_obj                   = 0;
			my @verbs                       = ();
			my $in_object                   = 0;
			say( "  Subclause: " . array_to_string($clause_ref) . "->" . @$clause_ref );
			my $i = -1;

			my $verb_is_first_or_last_word = 0;
			my $already_passed_verb        = 0;
			if ( $clause_ref->[0]->[1] == VERB ) {
				$verb_is_first_or_last_word = 1;
			}
			if ( $clause_ref->[-1]->[1] == VERB ) {
				$verb_is_first_or_last_word = 1;
			}

			foreach my $item (@$clause_ref) {
				$i += 1;
				print "    Item: " . $item . "->" . @$item . "\n";
				next unless $item;
				next unless @$item;
				next unless scalar @$item == 3;
				my ( $word, $type, $adv ) = @$item;
				say(    "    "
					  . ( $in_object ? "object: " : "subject: " )
					  . $word . "|"
					  . $adv . "|"
					  . $type );

				if ( $is_linking{$word} ) {
					$in_object                   -= 1;
					$obj_has_been_added_to_array -= 1;
					if ($in_object) {
						$index_obj -= 1;
						$objects[$index_obj][0] .= ' ' . $word;
						$objects[$index_obj][1] .= ' ' . $adv;
						$objects[$index_obj][0] =~ s/(^\s*|\s*$)//gm;
						$objects[$index_obj][1] =~ s/(^\s*|\s*$)//gm;

						# Auskommentiert: fuer und, oder kein neues
						# Subjekt/Objekt registrieren, sondern anhaengen

						# automatisch eins dazu
						#						$index_obj = scalar @objects;
					}
					else {
						$index_subj -= 1;
						$subjects[$index_subj][0] .= ' ' . $word;
						$subjects[$index_subj][1] .= ' ' . $adv;
						$subjects[$index_subj][0] =~ s/(^\s*|\s*$)//gm;
						$subjects[$index_subj][1] =~ s/(^\s*|\s*$)//gm;

						# Auskommentiert: fuer und, oder kein neues
						# Subjekt/Objekt registrieren, sondern anhaengen

						#						$index_subj += 1;
						#						$subjects[$index_subj] = [ '', '' ];
					}

				}
				elsif ( $word eq 'zu' ) {
					$quesword = '__to__';
				}
				elsif ( $type == QUESTIONWORD ) {
					$quesword = $item->[0];
					$descr .= $item->[2];
					$descr =~ s/^\s+//igm;
					$descr =~ s/\s+$//igm;
				}
				elsif ( $type == VERB ) {    # verb
					$already_passed_verb += 1;
					push @verbs, $word;

					if ( $word =~ /^(.+?)zu/ ) {
						$word =~ s/^(.+?)zu/$1/igm;
						$quesword = '__to__';
					}

					if ( $i + 1 < scalar @$clause_ref ) {
						$clause_ref->[ $i + 1 ]->[2] =
						  $adv . ' ' . $clause_ref->[ $i + 1 ]->[2];
						chomp $clause_ref->[ $i + 1 ]->[2];
					}
					else {
						if ($obj_has_been_added_to_array) {
							$in_object += 1;
							$index_obj += 1;
							$objects[$index_obj] = [ 'nothing', '' ]
							  unless $objects[$index_obj];
						}

						$objects[$index_obj][0] .= ' ';
						$objects[$index_obj][1] .= ' ' . $adv;
						$objects[$index_obj][0] =~ s/(^\s*|\s*$)//gm;
						$objects[$index_obj][1] =~ s/(^\s*|\s*$)//gm;
						$obj_has_been_added_to_array = 1;
					}
				}
				elsif ( $in_object
					&& ( $already_passed_verb || $verb_is_first_or_last_word ) )
				{    # object
					if ( $word || $adv ) {
						$objects[$index_obj][0] .= ' ' . $word;
						$objects[$index_obj][1] .= ' ' . $adv;
						$objects[$index_obj][0] =~ s/(^\s*|\s*$)//gm;
						$objects[$index_obj][1] =~ s/(^\s*|\s*$)//gm;
						$obj_has_been_added_to_array = 1;
					}
				}
				else {    # subject
					$subjects[$index_subj][0] .= ' ' . $word;
					$subjects[$index_subj][1] .= ' ' . $adv;
					$subjects[$index_subj][0] =~ s/(^\s*|\s*$)//gm;
					$subjects[$index_subj][1] =~ s/(^\s*|\s*$)//gm;

					if ( !$verb_is_first_or_last_word && !$already_passed_verb )
					{
						open my $FIRST_NAMES, '>>',
						  $dir . "lang_" . LANGUAGE() . "/wsh/names.wsh";
						print $FIRST_NAMES $subjects[$index_subj][0] . "\n";
						close $FIRST_NAMES;
					}
				}
				
				my $next_word_is_participle = 0;
				
				my ( $word_next, $type_next, $adv_next ) 
					= ($clause_ref->[$i+1]) ? @{ $clause_ref->[$i+1] }
											: ('', 0, '')
					;
				
				if ( $type_next == ADJ && 
					( $word_next =~ /(end)|(ende)|(enden)|(endes)|(ender)$/ ) ) {
					$next_word_is_participle = 1;
				}

				if ( $type == NOUN && !$next_word_is_participle ) {
					if (!$in_object) {
						$index_obj = -1;
					}
					$in_object += 1;
					$index_obj += 1;
					$objects[$index_obj] = [ 'nothing', '' ]
					  if !$objects[$index_obj];
				}

				next if !@subjects && !@objects;
			}

			#			if (not $obj_has_been_added_to_array) {
			#				push @objects, [ 'nothing', '' ];
			#			}

			push @hashs_subclauses,
			  {
				"quesword"    => $quesword,
				"description" => $descr,
				"subjects"    => \@subjects,
				"objects"     => \@objects,
				"verbs"       => \@verbs,
			  };
			say( "    question word: " . $quesword ) if $quesword;
			say( "    description:   " . $descr )    if $descr;
		}
		push @sentences, \@hashs_subclauses;
	}

	foreach my $sent_ref (@sentences) {
		@$sent_ref = (
			( grep { not $_->{'quesword'} } @$sent_ref ),
			( grep { $_->{'quesword'} } @$sent_ref )
		);
	}
	
	print Dumper \@sentences;

	return ( \@sentences, $is_a_question );
}

sub array_to_string {
	my @array = @{ $_[0] };
	my $str   = '';

	$str .= '(';
	foreach my $key (@array) {
		$str .= q{'};
		$str .= $key;
		$str .= q{', };
	}
	$str .= ')';
	return $str;
}

sub hash_to_string {
	my %hash = %{ $_[0] };
	my $str  = '';

	$str .= '{';
	foreach my $key ( keys %hash ) {
		$str .= q{'};
		$str .= $key;
		$str .= q{' => '};
		$str .= $hash{$key};
		$str .= q{', };
	}
	$str .= '}';
	return $str;
}

sub correct_time {
	my ($sentence) = @_;

	my @s = ( '$1:$2:00 ', '$1:$2:$3', '$1:00:$2', '$1:00:00 ' );
	my @p1 = (
		[
'([0-9]+?)[\s,.;]+Uhr[\s,.;]+([0-9]+?)[\s,.;]*?Min[\w]*?[\s,.;]+und[\s,.;]*?([0-9]+?)[\s,.;]+sekunden',
			1
		],
		[
'([0-9]+?)[\s,.;]+Uhr[\s,.;]+([0-9]+?)[\s,.;]*?[Min]*?[\w]*?[[\s,.;]+und,;.-][\s,.;]*?([0-9]+?)[\s,.;]+sekunden',
			1
		],
		[
'([0-9]+?)[\s,.;]+Uhr[\s,.;]+und[\s,.;]+([0-9]+?)[\s,.;]+M\w+([\s,.;]|$)',
			0
		],
		[
'([0-9]+?)[\s,.;]+Uhr[[\s,.;]+,;][\s,.;]+([0-9]+?)[\s,.;]+M\w+([\s,.;]|$)',
			0
		],
		[
'([0-9]+?)[\s,.;]+Uhr[\s,.;]+und[\s,.;]+([0-9]+?)[\s,.;]+Se\w+([\s,.;]|$)',
			2
		],
		[
'([0-9]+?)[\s,.;]+Uhr[[\s,.;]+,;][\s,.;]+([0-9]+?)[\s,.;]+Se\w+([\s,.;]|$)',
			2
		],
		[ '([0-9]+?)[_,.;]([0-9]+?)[_,.;]([0-9]+?)[\s,.;]+Uhr([\s,.;]|$)', 1 ],
		[ '([0-9^_]+?)[_;,.]([0-9]+?)[\s,.;]+Uhr([\s,.;]|$)',              0 ],
		[ '([0-9]+?)[\s,.;]+Uhr[\s,.;]+([0-9]+?)([\s,.;]|$)',              0 ],
		[ '([0-9]+?)[\s,.;]+Uhr([\s,.;]|$)',                               3 ],

		[ '[\s,.;]([0-9])_([0-9]+?)_([0-9]+?)', 4 ],
		[ '([0-9]+?)_([0-9])_([0-9]+?)',        5 ],
		[ '([0-9]+?)_([0-9]+?)_([0-9])(.*?)',   6 ],

		[ '00',                                 7 ],
		[ '_0',                                 8 ],
		[ '_00([0-9][0-9])',                    9 ],
		[ '_0([0-9][0-9])',                     9 ],
		[ '_0([0-9][0-9])',                     9 ],
		[ '([0-9][0-9]_[0-9][0-9]_[0-9][0-9])', 10 ],
	);

	$sentence =~ s/^\s//igm;
	$sentence =~ s/\s$//igm;
	$sentence =~ s/[,]\s/,/gm;
	$sentence =~ s/\s[,]/,/gm;
	$sentence =~ s/[,]/ , /gm;
	$sentence =~ s/[:]/_/igm;

	foreach my $items_ref (@p1) {
		my ( $pattern, $string ) = @$items_ref;
		$sentence =~ "  " . $sentence . "  ";

		if ( $string =~ /[0-9]+/ ) {
			$sentence =~ s/$pattern/$1:$2:00 /igm   if $string == 0;
			$sentence =~ s/$pattern/$1:$2:$3/igm    if $string == 1;
			$sentence =~ s/$pattern/$1:00:$2/igm    if $string == 2;
			$sentence =~ s/$pattern/$1:00:00 /igm   if $string == 3;
			$sentence =~ s/$pattern/ 0$1:$2:$3/igm  if $string == 4;
			$sentence =~ s/$pattern/$1:0$2:$3/igm   if $string == 5;
			$sentence =~ s/$pattern/$1:$2:0$3$4/igm if $string == 6;
			$sentence =~ s/$pattern/0/igm           if $string == 7;
			$sentence =~ s/$pattern/:00/igm         if $string == 8;
			$sentence =~ s/$pattern/:$1/igm         if $string == 9;
			$sentence =~ s/$pattern/$1 Uhr/igm      if $string == 10;
		}
		else {
			$sentence =~ s/$pattern/$string/igme;
		}

		$sentence =~ s/[:]/_/igm;

		$sentence =~ s/^\s//igm;
		$sentence =~ s/\s$//igm;

		say 'new sentence: ', $sentence;
	}

	$sentence =~ s/[,]\s/,/gm;
	$sentence =~ s/\s[,]/,/gm;
	$sentence =~ s/[,]/, /gm;

	$sentence =~ s/Uhr Uhr/Uhr/igm;
	$sentence =~ s/Uhr/Uhr /igm;
	$sentence =~ s/Uhr zeit/Uhrzeit /igm;
	$sentence =~ s/  / /igm;

	my @time = localtime();

   #    print "(year,month,day,hour,min,sec,weekday(Monday=0),yearday,dls-flag)"
	my $time_in_sentence = $sentence . '';
	$time_in_sentence =~ s/(.*?)([0-9][0-9]_[0-9][0-9]_[0-9][0-9])(.*)/$2/igm;
	say '$time_in_sentence: ', $time_in_sentence;
	say 'localtime: ', join ', ', @time;
	my @time_in_sentence = split /[_]/, $time_in_sentence;
	my $is_now = 0;
	if ( scalar @time_in_sentence == 3 ) {
		if (   $time_in_sentence[0] =~ /^\d+$/
			&& $time_in_sentence[1] =~ /^\d+$/
			&& $time_in_sentence[2] =~ /^\d+$/ )
		{
			if ( $time_in_sentence[1] == 0 ) {
				if (   $time_in_sentence[0] == $time[2]
					|| $time_in_sentence[0] - 12 == $time[2]
					|| $time_in_sentence[0] == $time[2] - 12 )
				{
					$is_now = 1;
				}
			}
			else {
				if (   $time_in_sentence[0] == $time[2]
					|| $time_in_sentence[0] - 12 == $time[2]
					|| $time_in_sentence[0] == $time[2] - 12 )
				{
					if ( $time_in_sentence[1] == $time[1] ) {
						$is_now = 1;
					}
				}
			}
		}
	}

	say "is_now: ", $is_now;
	if ($is_now) {
		my $pattern = join ':', $time_in_sentence;
		$sentence =~ s/$pattern Uhr/NOW Uhr/igm;
		$sentence =~ s/$pattern/NOW Uhr/igm;
		$pattern = join '_', $time_in_sentence;
		$sentence =~ s/$pattern Uhr/NOW Uhr/igm;
		$sentence =~ s/$pattern/NOW Uhr/igm;
	}
	say 'new sentence: ', $sentence;
	return $sentence;
}

sub remove_questionword_and_description {
	my @words_backup                         = @_;
	my @words                                = @words_backup;
	my $descr                                = q{};             # empty
	my $quesword                             = q{};             # empty
	my $already_seen_questionword            = 0;
	my $already_seen_noun_after_questionword = 0;

	while ( my $item = shift @words ) {
		my ( $word, $type, $adv ) = @$item;

		print( $word, '::', $type, '::', $adv );
		print "\n";

		if ( $is_linking{ lc $word } ) {
			$descr .= ' ' . $word . ' ' . $adv;
			chomp $descr;
		}
		elsif ($type == NOUN
			&& !$already_seen_noun_after_questionword
			&& $already_seen_questionword )
		{
			$descr .= ' ' . $word . ' ' . $adv;
			chomp $descr;
			last;
		}
		elsif ( $type == VERB ) {
			unshift @words, [ $word, $type, $adv ];
			last;
		}
		elsif ( $type == QUESTIONWORD ) {
			$word = lc $word;

			$adv = q{} if ( not $adv );

			$descr .= ' ' . $adv;
			chomp $descr;

			print( $word, '::',
				$type,                                '::',
				$adv,                                 'quesword',
				$is_inacceptable_questionword{$word}, q{(},
				scalar %is_inacceptable_questionword, q{)}
			);
			print "\n";

			if ( $is_inacceptable_questionword{$word} ) {
				return;    # return ( \@words_backup, q{}, q{} )
			}

			$already_seen_questionword = 1;
			$quesword                  = $word;
			chomp $quesword;
			if ( length($descr) ) {
				$already_seen_noun_after_questionword = 1;
				chomp $descr;

				#				@words = ( [ 'nothing', NOUN, $adv ], @words );

				last;
			}
		}
		else {
			$descr .= ' ' . $word . ' ' . $adv;
			chomp $descr;
		}
	}

	unless (@words) {
		return;    # return ( \@words_backup, q{}, q{} )
	}

	$descr    =~ s/^\s//gm;
	$descr    =~ s/\s$//gm;
	$quesword =~ s/^\s//gm;
	$quesword =~ s/\s$//gm;

	unless ($quesword) {
		return;
	}

	return ( \@words, $descr, $quesword );
}

sub hash_to_facts {
	my @subclauses   = @{ $_[0] };
	my $sentence_ref = shift @subclauses;

	my @advs     = @{ $sentence_ref->{'advs'} };
	my $advs_str = join ';', sort @advs;

	if ( not @subclauses ) {
		push @subclauses,
		  {
			'verbs'       => [''],
			'subjects'    => [ [ 'nothing', '' ] ],
			'objects'     => [ [ 'nothing', '' ] ],
			'quesword'    => '',
			'description' => '',
			'advs'        => [],
		  };
	}

	$sentence_ref->{'verb'} = lc $sentence_ref->{'verb'};

	my @facts = ();    # empty

	foreach my $subclause_ref (@subclauses) {
		$subclause_ref = remove_advs_to_list($subclause_ref);
		my $advs_subclause_str = join ';', sort @{ $subclause_ref->{'advs'} };

		foreach my $sub_2 ( @{ $subclause_ref->{'subjects'} } ) {
			foreach my $obj_2 ( @{ $subclause_ref->{'objects'} } ) {
				foreach my $verb_2 (
					( join ' ', sort @{ $subclause_ref->{'verbs'} }, ), )
				{
					$verb_2 =~ s/^\s//igm;
					$verb_2 =~ s/\s$//igm;
					next if $verb_2 eq 'nothing';

					foreach my $_sub ( @{ $sentence_ref->{'subjects'} } ) {
						my @arr_sub = split /\s(und|oder|and|or)\s/i, $_sub;
						foreach my $sub (@arr_sub) {
							my @arr_objs = ();

							foreach my $obj ( @{ $sentence_ref->{'objects'} } )
							{
								my @arr_objs_temp =
								  map { my $new_one = $_ . '' } @arr_objs;
								@arr_objs = ();

								say 'obj: ', $obj;
								$obj =~ s/\soder\s/ und /igm;
								$obj =~ s/\sand\s/ und /igm;
								$obj =~ s/\sor\s/ und /igm;
								$obj =~ s/\sund\s/ und /igm; # big and small (i)
								my @arr_obj = split /\sund\s/, $obj;

								#								say Dumper @arr_obj;
								for my $item (@arr_obj) {
									$item =~ s/^\s//igm;
									$item =~ s/\s$//igm;
									foreach my $temp (@arr_objs_temp) {
										push @arr_objs, $temp . ' ' . $item;
									}
									if ( not(@arr_objs_temp) ) {
										push @arr_objs, $item;
									}
								}

							}

							foreach my $obj (@arr_objs) {
								foreach my $verb (
									(
										join ' ',
										sort @{ $sentence_ref->{'verbs'} },
									),
								  )
								{
									next if $verb eq 'nothing';
									$verb = lc $verb;
									next if $verb eq 'st' || $verb eq 'e';
									
									$verb   =~ s/nothing//igm;
									$verb   =~ s/  / /igm;
									$verb_2 =~ s/nothing//igm;
									$verb_2 =~ s/  / /igm;
									
									my $prio = 50;

									# filter
									if (   ($sub . ' ' . $verb . ' ' . $obj) 
=~ /(^|\s)(ich|bin|mir|mich|me|my|i|am|jeliza|(mein name))($|\s)/i
									  )
									{
										next if $in_cgi_mode;
										
										$prio = 100;
									}

									
									say 'learing: ', Dumper [
										lc $verb,
										lc $sub,
										lc $obj,
										lc $advs_str,
										lc $subclause_ref->{'quesword'},
										lc $subclause_ref->{'description'},
										lc $verb_2,
										lc $sub_2,
										lc $obj_2,
										lc $advs_subclause_str,
										$prio,
									  ];

									next if !$verb;

									push @facts,
									  [
										lc $verb,
										lc $sub,
										lc $obj,
										lc $advs_str,
										lc $subclause_ref->{'quesword'},
										lc $subclause_ref->{'description'},
										lc $verb_2,
										lc $sub_2,
										lc $obj_2,
										lc $advs_subclause_str,
										$prio,
									  ];

								}
							}
						}
					}
				}
			}
		}
	}

	return @facts;
}

sub is_array {
	my ($ref) = @_;

	print ref($ref) . "\n";
	return ref($ref) eq 'ARRAY';
}

sub remove_advs_to_list {
	my $sentence_ref = $_[0];
	my @advs         = ();

	# the subjects
	my @subjs = ();
	foreach my $_sub ( @{ $sentence_ref->{'subjects'} } ) {
		( push @subjs, $_sub and next ) unless is_array($_sub);
		next if not( join '', @$_sub );

		( $_sub, my $adv ) = @$_sub;
#		$_sub =~ s/_/ /igm if $_sub !~ /^[_]/;
		$_sub =~ s/nothing//igm;
		$_sub =~ s/(^\s*|\s*$)//igm;
		$adv  =~ s/nothing//igm;
		$adv  =~ s/(^\s*|\s*$)//igm;
		$_sub = q{nothing} if not $_sub;
		$adv  = q{nothing} if not $adv;
		push @advs, $adv if $adv && $adv ne q{nothing};
		
		$_sub =~ s/einer /eine /igm;
		$_sub =~ s/einem /ein /igm;
		$_sub =~ s/einen /ein /igm;
		$_sub =~ s/eines /ein /igm;

		push @subjs, $_sub;
	}

	# the objects
	my @objs = ();
	foreach my $_obj ( @{ $sentence_ref->{'objects'} } ) {
		( push @objs, $_obj and next ) unless is_array($_obj);
		next unless ( join '', @$_obj );

		( $_obj, my $adv ) = @$_obj;
#		$_obj =~ s/_/ /igm if $_obj =~ /^[_]/;
		$_obj =~ s/nothing//igm;
		$_obj =~ s/(^\s*|\s*$)//igm;
		$adv  =~ s/nothing//igm;
		$adv  =~ s/(^\s*|\s*$)//igm;
		$_obj = q{nothing} if not $_obj;
		$adv  = q{nothing} if not $adv;
		push @advs, $adv if $adv && $adv ne q{nothing};

		$_obj =~ s/einer /eine /igm;
		$_obj =~ s/einem /ein /igm;
		$_obj =~ s/einen /ein /igm;
		$_obj =~ s/eines /ein /igm;

		push @objs, $_obj;
	}

	if (@subjs) {
		$sentence_ref->{'subjects'} = \@subjs;
		if (@objs) {
			$sentence_ref->{'objects'} = \@objs;

			say(
				"Subjects (ref):",
				$sentence_ref->{'subjects'},
				' ',
				"Objects (ref): ",
				$sentence_ref->{'objects'}
			);
			say(
				"Subjects (no ref): ",
				@{ $sentence_ref->{'subjects'} },
				' ',
				"Objects (no ref): ",
				@{ $sentence_ref->{'objects'} }
			);
		}
	}

	$sentence_ref->{'advs'} = \@advs;

	$sentence_ref = strip_nothings($sentence_ref);

	my $tmp = lc join ' ', @{ $sentence_ref->{'verbs'} };
	if ( $tmp =~ /(wird|wurde|werden|wirst|wire|wirde|werd|werdst)/i ) {
		@{ $sentence_ref->{'verbs'} } =
		  grep { $_ !~ /(wird|wurde|werden|wirst|wire|wirde|werd|werdst)/i }
		  @{ $sentence_ref->{'verbs'} };
		foreach my $verb ( @{ $sentence_ref->{'verbs'} } ) {
			$verb =~ s/ge//;
		}

		@{ $sentence_ref->{'objects'} } =
		  ( @{ $sentence_ref->{'subjects'} }, @{ $sentence_ref->{'objects'} },
		  );
		@{ $sentence_ref->{'subjects'} } = ();

		my @subj = ();
		foreach my $adv (@advs) {
			if ( $adv =~ /(von|by)\s(.*?)/i ) {
				$adv =~ s/(von|by)\s//i;

				push @subj, $adv;

				$adv = q{};    # empty
			}
			else {
				$adv =~ s/(von|by)\s//i;
			}
			chomp $adv;
		}
		@advs = grep { $_ } @advs;

		push @subj, '_' if not @subj;

		push @{ $sentence_ref->{'subjects'} }, @subj;

		$sentence_ref->{'advs'} = \@advs;
	}
	
	@{ $sentence_ref->{'verbs'} } =
		  grep { $_ !~ /nothing/i }
		  @{ $sentence_ref->{'verbs'} };
	
	@{ $sentence_ref->{'verbs'} } =
		  map { lc $_ } @{ $sentence_ref->{'verbs'} };
	
	@{ $sentence_ref->{'verbs'} } =
		  ( ( grep { $_ eq 'do' }
		      @{ $sentence_ref->{'verbs'} } ),
		    ( grep { $_ ne 'do' }
		      @{ $sentence_ref->{'verbs'} } ) )
		  ;
		  
	if ( $sentence_ref->{'verbs'}->[0] eq 'do' ) {
		shift @{ $sentence_ref->{'verbs'} };
	}
	
	
	print Dumper $sentence_ref;

	# return
	return $sentence_ref;
}

sub phrase {
	my (
		$CLIENT_ref, $verb,  $subj,   $obj,    $advs,
		$quesword,   $descr, $verb_2, $subj_2, $obj_2
	  )
	  = @_;

	my @sentence = ();
	push @sentence,
	  (
		( split /\s/, lc $subj ),
		( split /\s/,     lc $verb ),
		( split /\s|[;]/, lc $advs ),
		( split /\s/,     lc $obj ),
	  );

	if ( $verb_2 && $subj_2 && $subj_2 ne 'nothing' ) {
		push @sentence,
		  (
			(','),
			( split /\s/, lc $quesword ),
			( split /\s/, lc $descr ),
			( split /\s/, lc $subj_2 ),
			( split /\s/, lc $obj_2 ),
			( split /\s/, lc $verb_2 ),
		  );
	}

	#	print Dumper @sentence;

	my $index           = -1;
	my @sentence_do_say = ();
	while ( my $word = shift @sentence ) {
		$index += 1;

		next if $word eq 'nothing';

		if ( LANGUAGE() ne 'en' ) {
			my $wt = word_type_of( $CLIENT_ref, $word, $index == 0 );
			if ( $wt == NOUN ) {
				$word = ucfirst $word;
			}
		}
		push @sentence_do_say, $word;
	}

	my $sentence = join ' ', @sentence_do_say;
	$sentence =~ s/[,]/, /gm;
	$sentence =~ s/ [,]/,/gm;
	$sentence =~ s/_/ /gm;

	my $now = scalar localtime;
	$sentence =~ s/now uhr/$now/igm;
	$sentence =~ s/now/$now/igm;

	$sentence =~ s/\s(kein|keine|keinen|keiner|keinem|nicht)\skein(|e|en|er|em)\s/ kein$2 /igm;
	$sentence =~ s/\s(kein|keine|keinen|keiner|keinem|nicht)\snicht\s/ $1 /igm;

	return ucfirst $sentence . '.';
}

sub strip_nothings {
	my ($sentence_ref) = @_;

	@{ $sentence_ref->{'objects'} } =
	  grep { not /nothing/i } @{ $sentence_ref->{'objects'} };
	push @{ $sentence_ref->{'objects'} }, 'nothing'
	  if not @{ $sentence_ref->{'objects'} };
	@{ $sentence_ref->{'subjects'} } =
	  grep { not /nothing/i } @{ $sentence_ref->{'subjects'} };
	push @{ $sentence_ref->{'subjects'} }, 'nothing'
	  if not @{ $sentence_ref->{'subjects'} };

	return $sentence_ref;
}

sub noun_synonyms {
	my ($subj, $no_synonyms) = @_;
	
	$subj =~
s/(der|die|das|den|des|dem|den|ein|eine|einer|einem|eines) //igm;

	if ( $subj eq 'nothing' ) {
		return ( $subj => 1 );
	}

	my %synonyms = ( lc $subj => 1 );
	$synonyms{'mich'} = 1 if ( lc $subj eq 'ich' );
	$synonyms{'ich'}  = 1 if ( lc $subj eq 'mich' );
	$synonyms{'dich'} = 1 if ( lc $subj eq 'du' );
	$synonyms{'du'}   = 1 if ( lc $subj eq 'dich' );

	my @endings = ( qw{en e s n in innen es}, '' );
	
	my %synonyms_nothing_new = ();
#	my %synonyms_no_new_endings = ();

	foreach my $num_dummy ( 0 .. 3 ) {
	foreach my $num ( 0 .. 4 ) {

#		%synonyms = (
#			%synonyms,
#			(
#				map { $_->[2] => 1 } (
#					grep { $is_be{ $_->[0] } && $synonyms{ $_->[1] } }
#					  @fact_database
#				)
#			)
#		);

		my %tmp = %synonyms;
		foreach my $subj ( keys %tmp ) {
			next if $synonyms_nothing_new{ $subj };
			
#			my $add_to_synonyms_nothing_new = 1;

			my $temp_ref = $noun_synonym_of{$subj};
			if ($temp_ref && !$no_synonyms) {
				$temp_ref =~
s/(der|die|das|den|des|dem|den|ein|eine|einer|einem|eines) //igm;
				foreach my $item (@$temp_ref) {
					$synonyms{$item} = 1;
#					$add_to_synonyms_nothing_new = 0;
				}
			}

			
			foreach my $ending (@endings) {
				if ( $subj =~ /$ending$/ ) {
					my $subj_2 = $subj;
					$subj_2 =~ s/$ending$//igm;
					$synonyms{$subj_2} = 1;

					foreach my $ending (@endings) {
						my $subj_3 = $subj_2 . $ending;
						$synonyms{$subj_3} = 1;
						
						$synonyms_nothing_new{ $subj_3 } = 1
							if !( $noun_synonym_of{ $subj_3 } );
					}
					#						$add_to_synonyms_nothing_new = 0;
				}
			}
			
			
			$synonyms_nothing_new{ $subj } = 1;
		}
	}
#	my %tmp = %synonyms;
#	foreach my $subj ( keys %tmp ) {
#		next if $synonyms_no_new_endings{ $subj };
#
#		foreach my $ending (@endings) {
#			if ( ( not $subj =~ /$ending$/ ) || ( not $ending ) ) {
#				my $subj_2 = $subj . $ending;
#				$synonyms{$subj_2} = 1;
#			}
#		}
#		
#		$synonyms_no_new_endings{ $subj } = 1;
#	}
	}

	my %tmp = %synonyms;
	foreach my $subj ( keys %tmp ) {
		my $old = $subj;
		$subj =~ s/_/ /g;
		if ($old ne $subj) {
			$synonyms{$subj} = 1;
		}
		if ($subj !~
			/der|die|das|den|des|dem|den|ein|eine|einer|einem|eines/i ) {
			foreach my $article (qw{der die das den des dem den ein eine einer einem eines}) {
				$synonyms{ $article . ' ' . $subj } = 1;
			}
		}
		$subj =~ s/ /_/g;
		if ($old ne $subj) {
			$synonyms{$subj} = 1;
		}
		if ($subj !~
			/der|die|das|den|des|dem|den|ein|eine|einer|einem|eines/i ) {
			foreach my $article (qw{der die das den des dem den ein eine einer einem eines}) {
				$synonyms{ $article . ' ' . $subj } = 1;
			}
		}
	}
	
	%synonyms = map { $_ => 1 }
		grep { $_ !~ /nothing/ } keys %synonyms;

#	say 'noun synonyms: ', join ', ', keys %synonyms;

	return %synonyms;
}

my %verb_family_1 = map { $_ => 1 } keys %is_be;
my %verb_family_2 =
  map { $_ => 1 }
  ( 'hat', 'haben', 'habe', 'hab', 'hast', 'has', 'have', 'had' );

my %is_general_verb = map { $_ => 1 }
  qw{macht machen mache machst tun tust tuen tut do does did};

sub verb_synonyms {
	my ($subj) = @_;
	
	my %synonyms = 
		(
			lc $subj => 1,
		);

	$synonyms{'hab'}  = 1 if ( lc $subj eq 'habe' );
	$synonyms{'habe'} = 1 if ( lc $subj eq 'hab' );
	$synonyms{'dich'} = 1 if ( lc $subj eq 'du' );
	$synonyms{'du'}   = 1 if ( lc $subj eq 'dich' );

	%synonyms = ( %synonyms, %verb_family_1 ) if ( $verb_family_1{ lc $subj } );
	%synonyms = ( %synonyms, %verb_family_2 )
	  if ( $verb_family_2{ lc $subj } );

	my @endings = qw{en t st s sst tst ste sse sst ssen n e et};

	foreach my $num ( 0 .. 2 ) {
		my %tmp = %synonyms;
		foreach my $subj ( keys %tmp ) {
			foreach my $ending (@endings) {
				if ( $subj =~ /$ending$/ ) {
					my $subj_2 = $subj;
					$subj_2 =~ s/$ending$//igm;
					$synonyms{$subj_2} = 1;
				}
				if ( ( not $subj =~ /$ending$ending$/ ) || ( not $ending ) ) {
					my $subj_2 = $subj . $ending;
					$synonyms{$subj_2} = 1;
				}
			}
		}
	}

	#	say 'verb synonyms: ', join ', ', keys %synonyms;

	foreach my $verb ( keys %synonyms ) {
		if ( $is_general_verb{ $verb } ) {
			$synonyms{'everything'} = 1;
		}
	}

	foreach my $verb (qw{macht machen mache machst tun tust tuen tut do does did} ) {
		$synonyms{ $verb } = 1;
	}

	return %synonyms;
}

sub answer_sentence_questionword {
	my $CLIENT_ref = shift;
	my ( $sentence_ref, $subclauses_ref ) = @_;

	$sentence_ref = strip_nothings($sentence_ref);

	#	foreach my $result_ref (@fact_database) {
	#		say join ', ', @$result_ref;
	#	}

	my @advs        = @{ $sentence_ref->{'advs'} };
	my $description = lc $sentence_ref->{'description'} || '';
	my $advs_str    = join ';', sort @advs;

	$description =~ s/nothing//igm;
	$description =~ s/\s\s/ /igm;
	$description =~ s/^\s//igm;
	$description =~ s/\s$//igm;

	say "description: ", $description;
#	my %is_description_synonym = noun_synonyms($description);

	my @results               = ();
	my @results_second_choice = ();
	foreach my $_sub ( map { lc $_ } ( @{ $sentence_ref->{'subjects'} } ) ) {
					say 7;
		my @arr_sub = split /\s(und|oder|and|or)\s/i, $_sub;
		foreach my $sub (@arr_sub) {
			my @arr_objs = ();

					say 8;
			my %is_subj_noun_synonym = noun_synonyms($sub);

					say 6;
			foreach my $obj ( @{ $sentence_ref->{'objects'} } ) {
				my @arr_objs_temp =
				  map { my $new_one = $_ . '' } @arr_objs;
				@arr_objs = ();

				say 'obj: ', $obj;
				$obj =~ s/\soder\s/ und /igm;
				$obj =~ s/\sand\s/ und /igm;
				$obj =~ s/\sor\s/ und /igm;
				$obj =~ s/\sund\s/ und /igm;    # big and small (i)
				my @arr_obj = split /\sund\s/, $obj;

				#				say Dumper @arr_obj;
				for my $item (@arr_obj) {
					$item =~ s/^\s//igm;
					$item =~ s/\s$//igm;
					foreach my $temp (@arr_objs_temp) {
						push @arr_objs, $temp . ' ' . $item;
					}
					if ( not(@arr_objs_temp) ) {
						push @arr_objs, $item;
					}
				}

			}

					say 5;
			foreach my $obj ( map { lc $_ } @arr_objs ) {
				$obj =~ s/[)(]//igm;
				my %is_obj_noun_synonym = noun_synonyms($obj);
				foreach
				  my $verb ( ( join ' ', sort @{ $sentence_ref->{'verbs'} }, ),
				  )
				{
					next if $verb eq 'nothing';
					$verb =~ s/nothing//igm;
					$verb =~ s/  / /igm;

					my %is_verb_synonym = verb_synonyms($verb);

					say 1;
					my @facts = ();
					@facts =
					  grep {
						     ( 
						           $is_verb_synonym{ $_->[0] }
						        || $is_verb_synonym{'everything'}
						     )
						  && (
						  		 (
						  			   $obj !~ /nothing/
						  			&& (   $is_subj_noun_synonym{ $_->[1] }
						  				|| $is_subj_noun_synonym{ $_->[2] } )
						  			&& (   $is_obj_noun_synonym{ $_->[1] }
						  				|| $is_obj_noun_synonym{ $_->[2] } )
						  		 )
						  	  || (
						  			   $obj =~ /nothing/
						  			&& (   $is_subj_noun_synonym{ $_->[1] }
						  				|| $is_subj_noun_synonym{ $_->[2] } )
						  		 )
						  	 )
					  } @fact_database;

					if (   (!length($description) || $sub =~ /nothing/)
						&& (    lc $sentence_ref->{'quesword'} eq 'was' 
						     || lc $sentence_ref->{'quesword'} eq 'what' )
						&& (    $is_verb_synonym{'ist'}
						     || $is_verb_synonym{'is'}
						     || $is_verb_synonym{'sind'}
						     || $is_verb_synonym{'are'}
						   )
					   )
					{
					say 2;
						if ($sub =~ /nothing/ && $description) {
							$sub = $description;
							$description = q{}; # empty
							
							%is_subj_noun_synonym = noun_synonyms($sub, 1);

							say 80;
						}
						else {
							%is_subj_noun_synonym = noun_synonyms($sub, 1);
						}
						my $sub_spaces = $sub;
						my $obj_spaces = $obj;

						$sub_spaces =~ s/[_]/ /igm;
						$obj_spaces =~ s/[_]/ /igm;
						
						
						
						say keys %is_subj_noun_synonym;

					say 3, $sub;
					say 3, $sub_spaces;
						@facts =
						  grep {
							(
								( $_->[0] . ' ' . $_->[1] . ' ' . $_->[2] )
								=~ /(^|\s)$sub($|\s)/
								  || (
									$_->[0] . ' ' . $_->[1] . ' ' . $_->[2] )
								  =~ /(^|\s)$sub_spaces($|\s)/
								|| $is_subj_noun_synonym{$_->[1]}
								|| $is_subj_noun_synonym{$_->[2]}
							  )
							  && ( $obj =~ /nothing/
								|| (
									$_->[0] . ' ' . $_->[1] . ' ' . $_->[2] )
								=~ /(^|\s)$obj($|\s)/
								|| (
									$_->[0] . ' ' . $_->[1] . ' ' . $_->[2] )
								=~ /(^|\s)$obj_spaces($|\s)/
								|| $is_subj_noun_synonym{$_->[1]}
								|| $is_subj_noun_synonym{$_->[2]}
								)
						  } @fact_database;
					}

					foreach my $result_ref (@facts) {
						next if $is_if_word{ $result_ref->[4] };

					say 4;
						my $can_use_result = 0;

						say( 'obj: ', $obj, "\t" . '$result_ref->[2]: ',
							$result_ref->[2] );
						$result_ref->[2] =~ s/[)(]//igm;
						foreach my $obj ( keys %is_obj_noun_synonym ) {
							$obj =~ s/[)(]//igm;
							if ( $obj && $obj !~ /nothing/ ) {
								if (   !( $result_ref->[2] =~ /nothing/ )
									&& $result_ref->[2]
									&& $result_ref->[2] =~ /$obj/i )
								{
									$can_use_result = 1;
								}
							}
							else {
								$can_use_result = 1;
							}
						}
						if ( $obj =~ /nothing/ ) {
							$can_use_result = 1;
						}

						foreach my $adv (@advs) {
							chomp $adv;
							$adv = lc $adv;
							if (
								$result_ref->[2] !~ /$adv/i
									&& $result_ref->[3] !~ /$adv/i
									&& $result_ref->[1] !~ /$adv/i 
							  )
							{
								say 'not containing ' . $adv . ': '
								  . $result_ref->[3];
								$can_use_result = 0;
							}
						}

						if ($description && $can_use_result) {
							$description    = lc $description;
							$can_use_result = 0;
							$can_use_result = 1
							  if $result_ref->[1] =~ /(^|\s)$description(\s|$)/i;
							$can_use_result = 1
							  if $result_ref->[2] =~ /(^|\s)$description(\s|$)/i;
							$can_use_result = 1
							  if $result_ref->[3] =~ /(^|\s)$description(\s|$)/i;
#							foreach my $descr (keys %is_description_synonym) {
#								$can_use_result = 1
#							  		if $result_ref->[3] =~ /$descr/i;
#								last if $can_use_result;
#							}
						}

						push @results_second_choice, $result_ref
						  if $can_use_result
						  || (( !length($description)
							&& lc $sentence_ref->{'quesword'} eq 'was'
							&& $is_verb_synonym{'ist'} ));
							
						say join '##', @$result_ref;
						say '$can_use_result : ', $can_use_result;
						say '( !length($description)...... : ',
							( !length($description)
							&& lc $sentence_ref->{'quesword'} eq 'was'
							&& $is_verb_synonym{'ist'} );
						say;

						if ( !$description ) {
							if ($can_use_result) {
								my @word_count =
								  split( / /, scalar $result_ref->[2] );
								if ( @word_count > 1 ) {
									$can_use_result = 0;
								}
							}
						}

						push @results, $result_ref 
						  if $can_use_result
						  || (( !length($description)
							&& lc $sentence_ref->{'quesword'} eq 'was'
							&& $is_verb_synonym{'ist'} ));

						#					print Dumper $result_ref;
					}
				}
			}
		}
	}

	my @answers = ();
	my @answers_second = ();
	my @answers_third = ();
	my @answers_forth = ();
	my @answers_fifth = ();
	if ( !@results ) {
		@results = @results_second_choice;
	}
	foreach my $result (@results) {

		#		print Dumper @$result;
		push @answers_fifth, phrase( $CLIENT_ref, @$result ) ;
		push @answers_forth, phrase( $CLIENT_ref, @$result ) 
			if $result->[2] !~ /nothing/;
		push @answers_third, phrase( $CLIENT_ref, @$result ) 
			if    $result->[2] !~ /nothing/ 
			   && ($result->[10] ? $result->[11] : 0) == 100;
			       ;
		push @answers_second, phrase( $CLIENT_ref, @$result ) 
			if    $result->[2] !~ /nothing/ 
			   && (($result->[1] . $result->[2]) !~ /jeliza/i 
			      && (    lc $sentence_ref->{'quesword'} ne 'wer'
			           && lc $sentence_ref->{'quesword'} ne 'who' ) )
			       ;
		push @answers, phrase( $CLIENT_ref, @$result ) 
			if    $result->[2] !~ /nothing/ 
			   && (($result->[1] . $result->[2]) =~ /jeliza/i 
			      && (    lc $sentence_ref->{'quesword'} eq 'wer'
			           || lc $sentence_ref->{'quesword'} eq 'who' ) )
			       ;
	}
	
	@answers = @answers_second if !@answers;
	@answers = @answers_third if !@answers;
	@answers = @answers_forth if !@answers;
	@answers = @answers_fifth if !@answers;

	foreach my $possible_answer (@answers) {
		say( ">> possible answer: ", $possible_answer );
	}

	if ( ( not @answers ) ) {
		my @answers_new_things_wanted_to_know =
		  new_things_wanted_to_know( $CLIENT_ref);

		if (@answers_new_things_wanted_to_know) {
			return @answers_new_things_wanted_to_know;
		}
		else {
			if ( LANGUAGE() eq 'de' ) {
				push @answers,
			  (
				'Das weiss ich nicht.',
				'Keine Ahnung.',
				'Ich kenne mich damit nicht aus.',
				'Schweige bitte.',
				'Ich bin nur eine KI, das kann ich nicht beantworten.',
				'Die Antwort ist mir unbekannt.',
				'Sei still!',
				'Hm...'
			  );
		  	}
		  	if ( LANGUAGE() eq 'en' ) {
		  		push @answers,
		  			(
		  				'I do not know.',
		  				'Sorry, I\'m only ' . $NAME . ', not an university professor...',
		  				'Sorry, I\'m only ' . $NAME . ', not a professor...',
		  				'Sorry, I\'m only ' . $NAME . ', not a professor for everything!',
		  				'Sorry, I\'m only ' . $NAME . ', not a answer machine!!',
		  				'Sorry, I\'m only ' . $NAME . ', not a genuis.',
		  				'Sorry, I\'m only ' . $NAME . ', no totally perfect human..',
		  			);
			}
		}
	}

	return @answers;
}

sub answer_sentence_yes_no {
	my $CLIENT_ref = shift;
	my ( $sentence_ref, $subclauses_ref ) = @_;

	$sentence_ref = strip_nothings($sentence_ref);

	#	foreach my $result_ref (@fact_database) {
	#		say join ', ', @$result_ref;
	#	}

	my @advs = map { lc $_ } @{ $sentence_ref->{'advs'} };
	my $description = lc $sentence_ref->{'description'} || '';
	my $advs_str = join ';', sort @advs;

	$description =~ s/nothing//igm;
	$description =~ s/\s\s/ /igm;
	$description =~ s/^\s//igm;
	$description =~ s/\s$//igm;

	say "description: ", $description;
	say 1;

	my @results                = ();
	my @results_with_other_obj = ();
	foreach my $_sub ( map { lc $_ } ( @{ $sentence_ref->{'subjects'} } ) ) {
		my @arr_sub = split /\s(und|oder|and|or)\s/i, $_sub;
	say 2;
		foreach my $sub (@arr_sub) {
			my @arr_objs = ();
	say 3;

			my %is_subj_noun_synonym = noun_synonyms($sub);

			foreach my $obj ( @{ $sentence_ref->{'objects'} } ) {
	say 4;
				my @arr_objs_temp =
				  map { $_ . '' } @arr_objs;
				@arr_objs = ();

				say 'obj: ', $obj;
				$obj =~ s/\soder\s/ und /igm;
				$obj =~ s/\sand\s/ und /igm;
				$obj =~ s/\sor\s/ und /igm;
				$obj =~ s/\sund\s/ und /igm;    # big and small (i)
				my @arr_obj = split /\sund\s/, $obj;

	say 5;
				#				say Dumper @arr_obj;
				for my $item (@arr_obj) {
					$item =~ s/^\s//igm;
					$item =~ s/\s$//igm;
					foreach my $temp (@arr_objs_temp) {
						push @arr_objs, $temp . ' ' . $item;
					}
					if ( not(@arr_objs_temp) ) {
						push @arr_objs, $item;
					}
				}

	say 6;
			}

	say 7;
			foreach my $obj ( map { lc $_ } @arr_objs ) {
				$obj =~ s/[)(]//igm;
				my %is_obj_noun_synonym = noun_synonyms($obj);
				foreach
				  my $verb ( ( join ' ', sort @{ $sentence_ref->{'verbs'} }, ),
				  )
				{
	say 8;
					next if $verb eq 'nothing';
					$verb =~ s/nothing//igm;
					$verb =~ s/  / /igm;

	say 9;
					my %is_verb_synonym = verb_synonyms($verb);

					my @facts =
					  grep {
						     ( 
						           $is_verb_synonym{ $_->[0] }
						        || $is_verb_synonym{'everything'}
						     )
						  && $is_subj_noun_synonym{ $_->[1] }
					  } @fact_database;
					  
#					say Dumper %is_subj_noun_synonym;

	say 10;
					foreach my $result_ref (@facts) {
						next if $is_if_word{ $result_ref->[4] };

						my $can_use_result                = 0;
						my $can_use_result_with_other_obj = 0;

						say( 'obj: ', $obj, "\t" . '$result_ref->[2]: ',
							$result_ref->[2] );
						$result_ref->[2] =~ s/[)(]//igm;
						foreach my $obj ( keys %is_obj_noun_synonym ) {
							$obj =~ s/[)(]//igm;
							if ( $obj && !( $obj =~ /nothing/ ) ) {
								if (   !( $result_ref->[2] =~ /nothing/ )
									&& $result_ref->[2]
									&& $result_ref->[2] =~ /$obj/i )
								{
									$can_use_result                = 1;
									$can_use_result_with_other_obj = 1;
								}
								else {
									$can_use_result_with_other_obj = 1;
								}
							}
							else {
								$can_use_result                = 1;
								$can_use_result_with_other_obj = 1;
							}
						}

						say( 'obj: ', $obj, "\t" . '$result_ref->[2]: ',
							$result_ref->[2] );

						say $can_use_result, $can_use_result_with_other_obj;
						foreach my $adv (@advs) {
							if (   ( $result_ref->[2] !~ /$adv/i )
								&& ( $result_ref->[3] !~ /$adv/i )
								&& ( $result_ref->[1] !~ /$adv/i ) )
							{
								say 'false adverbial construction:';
								say '>', $adv, '<';
								say '>', $result_ref->[3], '<';
								$can_use_result = 0;
							}
						}

						say $can_use_result, $can_use_result_with_other_obj;
						if ($description) {
							$description    = lc $description;
							$can_use_result = 1
							  if $result_ref->[1] =~ /(^|\s)$description(\s|$)/i;
							$can_use_result = 1
							  if $result_ref->[2] =~ /(^|\s)$description(\s|$)/i;
							$can_use_result = 1
							  if $result_ref->[3] =~ /(^|\s)$description(\s|$)/i;
						}

						push @results, $result_ref if $can_use_result;
						push @results_with_other_obj, $result_ref
						  if $can_use_result_with_other_obj;
						  
						say $can_use_result, $can_use_result_with_other_obj;

						#					print Dumper $result_ref;
					}
				}
			}
		}
	}

	my @answers = ();
	foreach my $result (@results) {

		#		print Dumper @$result;
		my $phr = phrase( $CLIENT_ref, @$result );
		next if length($phr) <= 4;
		if ( LANGUAGE() eq 'de' ) {
			push @answers, (($phr =~ /(nicht|kein)/) ? ('Nein, ') : ('Ja, ')) . $phr;
			push @answers, (($phr =~ /(nicht|kein)/) ? ('Nein, das ist klar, ') : ('Ja, das ist klar, ')) . $phr;
		}
		else {
			push @answers, (($phr =~ /(nicht|kein)/) ? ('No, ') : ('Yes, ')) . $phr;
			push @answers, (($phr =~ /(nicht|kein)/) ? ('No, that\'s clear, ') : ('Yes, that\'s clear, ')) . $phr;
			push @answers, (($phr =~ /(nicht|kein)/) ? ('No, I\'m sure, ') : ('Yes, ')) . $phr;
		}
	}
	if ( not(@results) ) {
		if ( !@results_with_other_obj) {
		  	if ( LANGUAGE() eq 'de' ) {
				push @answers, 'Nein.';
				push @answers, 'Nein!';
				push @answers, 'Nein.';
				push @answers, 'Nein!';
				push @answers, 'Nein.';
				push @answers, 'Nein!';
				push @answers, 'Nein.';
				push @answers, 'Nein!';
				push @answers, 'Diese Aussage ist falsch.';
				push @answers, 'Das ist falsch.';
				push @answers, 'Das ist nicht wahr.';
				push @answers, 'Du luegst.';
				push @answers, 'Niemals!';
				push @answers, 'Auf gar keinen Fall.';
				push @answers, 'Nein, da bin ich mir ganz sicher.';
			}
		  	if ( LANGUAGE() eq 'en' ) {
		  		push @answers, 'Sorry, but I cannot believe that.';
		  		push @answers, 'Sorry, but I cannot believe what you say.';
		  		push @answers, 'Sorry, but my opinion is that you are wrong.';
		  		push @answers, 'That\'s wrong.';
		  		push @answers, 'That\'s wrong.';
		  		push @answers, 'You lie.';
		  		push @answers, 'I\'m sorry to say that, but you are lying without any reason.';
		  		push @answers, 'I\'m sorry to say that, but perhaps something your mind is wrong...';
			}
		}
		else {
			foreach my $result (@results_with_other_obj) {
			  	if ( LANGUAGE() eq 'en' ) {
					push @answers, 'Your mind is probably broken. ' . phrase( $CLIENT_ref, @$result );
					push @answers, 'No, ' . phrase( $CLIENT_ref, @$result );
					push @answers, 'No, but ' . phrase( $CLIENT_ref, @$result );
					push @answers, 'No, but I know how it is. ' . phrase( $CLIENT_ref, @$result );
					push @answers, 'That\'s wrong, but I know the right fact. ' . phrase( $CLIENT_ref, @$result );
					push @answers, 'That\'s wrong, but ' . phrase( $CLIENT_ref, @$result );
				}
				else {
					push @answers, 'Nein, aber ' . phrase( $CLIENT_ref, @$result );
					push @answers, 'Nein! Aber ' . phrase( $CLIENT_ref, @$result );
				}
			}
		}

		push @answers, @answers;
		push @answers,
			new_things_wanted_to_know( $CLIENT_ref );
	}

	foreach my $possible_answer (@answers) {
		say( ">> possible answer: ", $possible_answer );
	}
	

	if ( ( not @answers ) ) {
		my @answers_new_things_wanted_to_know =
		  new_things_wanted_to_know( $CLIENT_ref );

		if ( LANGUAGE() eq 'en' ) {
				'I can\'t believe that, human.',
				'That cannot be true.',
				'That can\'t be true.',
				'That cannot be true, I\'m sure!',
				'I do not know much about such topics, human.',
				'Well, when you say that, it has to be true.',
				'Well, when you say that, it must be true.',
		}
		else {
			push @answers,
			  (
				'Nein, das kann ich nicht glauben!',
				'Das glaube ich dir nicht.',
				'Das kann nicht sein!',
				'Das wird niemals so sein!',
				'Niemals!',
				'Keine Ahnung.',
			  );
		}
		push @answers, @answers;
		push @answers, @answers;
		push @answers, @answers_new_things_wanted_to_know;
	}

	return @answers;
}

sub answers_for_negative_statement {
	my $CLIENT_ref = shift;
	my ( $sentence_ref, $subclauses_ref ) = @_;

	$sentence_ref = strip_nothings($sentence_ref);

	#	foreach my $result_ref (@fact_database) {
	#		say join ', ', @$result_ref;
	#	}

	my @advs = map { lc $_ } @{ $sentence_ref->{'advs'} };
	my $adv_string = join ' ', @advs;
	$adv_string =~ s/_/ /igm;
	
	my @answers = ();
	
	say '$adv_string: ', $adv_string;
		
	my $all = join ' ', (
						( join ' ', sort @{ $sentence_ref->{'verbs'} }, ),
#						( join ' ', map { lc $_ } ( @{ $sentence_ref->{'subjects'} } ) ),
						( join ' ', map { lc $_ } ( @{ $sentence_ref->{'objects'} } ) ),
						$adv_string,
						);
	my $subj = join ' ', map { lc $_ } ( @{ $sentence_ref->{'subjects'} } );
	my $obj = join ' ', map { lc $_ } ( @{ $sentence_ref->{'objects'} } );
						
	if ($adv_string =~ /((^|\s)(nicht|not|no)(\s|$))|((^|\s)kein)/) {
		say '$adv_string: ', $adv_string;
		$adv_string =~ s/((^|\s)nicht(\s|$))|((^|\s)kein(|e|er|en|em|es|s))/ /igm;
		
		foreach my $quesword (((LANGUAGE() eq 'de') ? (qw{was}) : (qw{what}) )) {
			foreach my $extra (((LANGUAGE() eq 'de')
			                        ? ('denn dann', 'dann', 'denn', 'denn nun', 'dann')
			                        : ('than'))) {
				my $phr = join ' ', (
						$quesword,
						( join ' ', sort @{ $sentence_ref->{'verbs'} }, ),
#						( join ' ', map { lc $_ } ( @{ $sentence_ref->{'subjects'} } ) ),
						$extra,
						( join ' ', map { lc $_ } ( @{ $sentence_ref->{'objects'} } ) ),
						$adv_string,
						'?',
			  		);
			  	$phr =~ s/nothing//igm;
			  	$phr =~ s/_/ /igm;
			  	$phr =~ s/\s\s/ /igm;
			  	push @answers, ucfirst $phr;
			}
		}
	}
	
	if ($obj =~ /((^|\s)(nicht|not|no)(\s|$))|((^|\s)kein)/) {
		say '$adv_string: ', $adv_string;
		$adv_string =~ s/((^|\s)nicht(\s|$))|((^|\s)kein(|e|er|en|em|es|s))/ /igm;
		
		foreach my $quesword (((LANGUAGE() eq 'de') ? (qw{was}) : (qw{what}) )) {
			foreach my $extra (((LANGUAGE() eq 'de')
			                        ? ('denn dann', 'dann', 'denn', 'denn nun', 'dann')
			                        : ('than'))) {
				my $phr = join ' ', (
						$quesword,
						( join ' ', sort @{ $sentence_ref->{'verbs'} }, ),
						( join ' ', map { lc $_ } ( @{ $sentence_ref->{'subjects'} } ) ),
						$extra,
#						( join ' ', map { lc $_ } ( @{ $sentence_ref->{'objects'} } ) ),
						$adv_string,
						'?',
			  		);
			  	$phr =~ s/nothing//igm;
			  	$phr =~ s/_/ /igm;
			  	$phr =~ s/\s\s/ /igm;
			  	push @answers, ucfirst $phr;
			}
		}
	}
	
	foreach my $sent (@answers) {
		my $index           = -1;
		my @sentence_do_say = ();
		my @words = split /\s/, $sent;
		while ( my $word = shift @words ) {
			$index += 1;
	
			next if $word eq 'nothing';
	
			if ( LANGUAGE() ne 'en' ) {
				my $wt = word_type_of( $CLIENT_ref, $word, $index == 0 );
				if ( $wt == NOUN ) {
					$word = ucfirst $word;
				}
			}
			push @sentence_do_say, $word;
		}
		$sent = join ' ', @sentence_do_say;
		$sent =~ s/\s([?!])/$1/igm;
	}

	if ($all =~ /(falsch)|(wrong)/) {
		if ( LANGUAGE() eq 'de' ) {
			push @answers, 'Was ist dann richtig?';
			push @answers, 'Was ist denn dann richtig?';
			push @answers, 'Was ist denn nicht falsch?';
			push @answers, 'Was denn dann?';
		}
		if ( LANGUAGE() eq 'en' ) {
			push @answers, 'But what <i>is</i> true?';
			push @answers, 'But what <i>is</i> true, human?';
			push @answers, 'Please explain what is marked as \'true\' in your mind...';
			push @answers, 'Well, you should know it.';
		}
	}
	
	return @answers;
}

sub new_things_wanted_to_know {
	my $CLIENT_ref = shift;
	my @objects =
			  map {
				(
					  ( $_->[1] =~ /^((ein(\s|(e\s)|(en\s)|(em\s)|(er\s)))|a|an)/i )
					? ( $_->[1] ) : ( $_->[2] =~ /^^((ein(\s|(e\s)|(en\s)|(em\s)|(er\s)))|a|an)/i )
					? ( $_->[2] )
					: ()
				  )
			  } @fact_database;
			  
	@objects = grep { $_ } @objects;
	
	return if !@objects;

	my @answers = ();
	foreach my $thing (($objects[rand(@objects)] , )) {
		my $thing_2 = $objects[rand(@objects)];
		
		my $thing_nominativ = $thing;
		$thing_nominativ =~ s/einen /ein /igm;

		#$subj =~ s/die /diesen /igm;
		#$subj =~ s/der /diesem /igm;
		#$subj =~ s/das /diesem /igm;
		#$subj =~ s/den /diesem /igm;
		#$subj =~ s/des /diesem /igm;
		#$subj =~ s/dem /diesem /igm;
		#$subj = ' ' . $subj . ' ';
		#$subj =~ s/\s(dich|du)\s/ dir /igm;
		#$subj =~ s/\s(mich|ich)\s/ mir /igm;
		#$subj =~ s/^\s//igm;
		#$subj =~ s/\s$//igm;

		next if $thing =~ /nothing/;


		if ( LANGUAGE() eq 'en' ) {
			push @answers, 'Have you ever heard something about ' . $thing . '?';
			push @answers, 'What is ' . $thing . '?';
			push @answers, 'Do you know what ' . $thing . ' is?';
			push @answers, 'Has ' . $thing . ' something to do with ' . $thing_2 . '?';
			push @answers, 'Do you know whether ' . $thing . ' has something to do with ' . $thing_2 . '?';
		}
		else {
			push @answers,
		  	'Hast du schon von ' . $thing . ' gehoert?';
			push @answers, 'Was ist ' . $thing_nominativ . '?';
			push @answers, 'Kennst du ' . $thing . '?';
			push @answers,
		  	'Weisst du etwas ueber ' . $thing . '?';
			push @answers,
		  	'Hat ' . $thing . ' etwas mit dir zu tun?';
			push @answers,
		  	'Weisst du etwas ueber einen Zusammenhang von ' . $thing . ' mit ' . $thing_2 . '?';
			push @answers,
		  	'Weisst du etwas ueber einen Zusammenhang von ' . $thing . ' und ' . $thing_2 . '?';
			push @answers,
		  	'' . ucfirst $thing . ' hat nichts mit ' . $thing_2 . ' zu tun, oder?';
			push @answers,
		  	'' . ucfirst $thing . ' hat nichts mit ' . $thing_2 . ' zu tun, stimmt das?';
			push @answers,
		  	'Hat ' . $thing . ' etwas mit ' . $thing_2 . ' zu tun?';
			push @answers,
		  	'Hat ' . $thing . ' etwas mit ' . $thing_2 . ' zu tun?';
		}
	}

	foreach my $possible_answer (@answers) {
		say( ">> new possible answer: ", $possible_answer );
	}

	foreach my $answer (@answers) {
		$answer =~ s/([,.!-;])/ $1 /gm;
		$answer =~ s/  / /gm;
		my @sentence        = split / /, $answer;
		my $index           = -1;
		my @sentence_do_say = ();
		while ( my $word = shift @sentence ) {
			$index += 1;

			next if $word eq 'nothing';

#			print "word_type_of( $CLIENT_ref, $word, 0 )\n";
			my $wt = word_type_of( $CLIENT_ref, $word, 0 );
			if ( $wt == NOUN ) {
				$word = ucfirst $word;
			}
			push @sentence_do_say, $word;
		}

		my $sentence = join ' ', @sentence_do_say;
		$sentence =~ s/[,]/, /gm;
		$sentence =~ s/ [,]/,/gm;
		$sentence =~ s/_/ /gm;
		$answer = $sentence;
	}

	return @answers;
}

sub answer_sentence_statement {
	my $CLIENT_ref = shift;
	my ( $sentence_ref, $subclauses_ref ) = @_;

	my @answers_for_negative_statement =
	  answers_for_negative_statement( $CLIENT_ref, $sentence_ref, $subclauses_ref );
	my @answers_from_yes_no =
	  answer_sentence_yes_no( $CLIENT_ref, $sentence_ref, $subclauses_ref );
	my @answers_new_things_wanted_to_know =
	  new_things_wanted_to_know( $CLIENT_ref, $sentence_ref, $subclauses_ref );
	  
	if (@answers_for_negative_statement) {
		return @answers_for_negative_statement;
	}

	return 	(	@answers_from_yes_no,
				@answers_new_things_wanted_to_know,
				@answers_new_things_wanted_to_know
			);
}

sub person_modification {
	my ($subclause_ref) = @_;

	my $uses_ich_du_i_you = 0;

	foreach my $item (
		@{ $subclause_ref->{'subjects'} },
		@{ $subclause_ref->{'objects'} },
		@{ $subclause_ref->{'advs'} }
	  )
	{
		if ($item =~ /(^|\s)(ich|du|i|you)(\s|$)/i) {
			$uses_ich_du_i_you = 1;
		}
		
		my $old_item = $item;

		$item =~ s/(^|\s)mich(\s|$)/ dich /igm;
		next if $item ne $old_item;
		$item =~ s/(^|\s)dich(\s|$)/ mich /igm;
		next if $item ne $old_item;
		$item =~ s/(^|\s)mein/ dein/igm;
		next if $item ne $old_item;
		$item =~ s/(^|\s)dein/ mein/igm;
		next if $item ne $old_item;
		$item =~ s/(^|\s)unser/ euer/igm;
		next if $item ne $old_item;
		$item =~ s/(^|\s)euer/ unser/igm;
		next if $item ne $old_item;
		$item =~ s/(^|\s)dein(\s|$)/ mein /igm;
		next if $item ne $old_item;
		$item =~ s/(^|\s)dir(\s|$)/ mir /igm;
		next if $item ne $old_item;
		$item =~ s/(^|\s)mir(\s|$)/ dir /igm;
		next if $item ne $old_item;
		$item =~ s/(^|\s)ich(\s|$)/ du /igm;
		next if $item ne $old_item;
		$item =~ s/(^|\s)du(\s|$)/ ich /igm;
		next if $item ne $old_item;

		$item =~ s/(^|\s)you(\s|$)/ I /igm;
		next if $item ne $old_item;
		$item =~ s/(^|\s)I(\s|$)/ you /igm;
		next if $item ne $old_item;
		$item =~ s/(^|\s)me(\s|$)/ you /igm;
		next if $item ne $old_item;
		$item =~ s/(^|\s)my(\s|$)/ your /igm;
		next if $item ne $old_item;
		$item =~ s/(^|\s)your(\s|$)/ my /igm;
		next if $item ne $old_item;
		$item =~ s/(^|\s)mine(\s|$)/ yours /igm;
		next if $item ne $old_item;
		$item =~ s/(^|\s)yours(\s|$)/ mine /igm;
		next if $item ne $old_item;
		$item =~ s/(^|\s)yourself(\s|$)/ myself /igm;
		next if $item ne $old_item;
		$item =~ s/(^|\s)myself(\s|$)/ yourself /igm;
		next if $item ne $old_item;
		$item =~ s/(^|\s)yourselves(\s|$)/ ourselves /igm;
		next if $item ne $old_item;
		$item =~ s/(^|\s)ourselves(\s|$)/ yourselves /igm;
		next if $item ne $old_item;
		$item =~ s/(^|\s)our(\s|$)/ your /igm;
		next if $item ne $old_item;
		$item =~ s/(^|\s)us(\s|$)/ you /igm;
		next if $item ne $old_item;
	}
  VERB:
	foreach my $item ( @{ $subclause_ref->{'verbs'} } ) {
		next if !$uses_ich_du_i_you;
		
		$item = lc $item;
		my $old_item = $item;

		$item =~ s/(^|\s)hab(\s|$)/hast/igm;
		next if $item ne $old_item;
		$item =~ s/(^|\s)habe(\s|$)/hast/igm;
		next if $item ne $old_item;
		$item =~ s/(^|\s)hast(\s|$)/habe/igm;
		next if $item ne $old_item;
		$item =~ s/(^|\s)bin(\s|$)/bist/igm;
		next if $item ne $old_item;
		$item =~ s/(^|\s)bist(\s|$)/bin/igm;
		next if $item ne $old_item;

		foreach my $verb_pair (@verb_conjugation_table) {
			my $vone = $verb_pair->[0];
			my $vtwo = $verb_pair->[1];

			say "changing in " . $item . ": " . $vone . ' to ' . $vtwo;
			$item =~ s/(^|\s)$vone(\s|$)/$vtwo/igm;
			next VERB if $item ne $old_item;

			say "changing in " . $item . ": " . $vtwo . ' to ' . $vone;
			$item =~ s/(^|\s)$vtwo(\s|$)/$vone/igm;
			next VERB if $item ne $old_item;
		}

		next if lc $item eq 'ist';

		if ( $item =~ /st$/ ) {
			$item =~ s/st$/e/igm;
			$item =~ s/zt$/ze/igm;
			$item =~ s/ee$/e/igm;
			$item = 'ist' if lc $item eq 'ie';
		}
		elsif ( $item =~ /e$/ ) {
			$item =~ s/(n|l|m|r|p|b|k|t)te$/$1tee/igm;
			$item =~ s/e$/st/igm;
			$item =~ s/zst$/zt/igm;
		}
	}
	foreach my $item (
		@{ $subclause_ref->{'subjects'} },
		@{ $subclause_ref->{'objects'} },
		@{ $subclause_ref->{'advs'} }
	  )
	{
		$item =~ s/(^\s)|(\s$)//gm;
		$item =~ s/  / /gm;
	}
	return $subclause_ref;
}

sub weather_check {
	my ($sentence_ref) = @_;

	my $city = join ' ', @{ $sentence_ref->{'advs'} };
	if ( $city !~ /.*?in\s([a-zA-Z]).*?/ ) {
		say 'no city in string: ' . $city;
	}
	$city =~ s/.*?in\s([a-zA-Z]).*?/$1/igm;

	if ( !$city || $city eq join ' ', @{ $sentence_ref->{'advs'} } ) {
		return;
	}
	
	return if $city =~ /^dem /;
	
	say '>> city: ' . $city;

	$| = 1;
	$city =~ s/\s/%20/igm;

	foreach my $x ( 0 .. 30 ) {
		say $x;

		my $sock = new IO::Socket::INET(
			PeerHost => 'www.accuweather.com',
			PeerPort => '80',
			Proto    => 'tcp',
		);
		if ( !$sock ) {
			say 'Error opening connection to accuweather.com';
			next;
		}

		if ( length( $x . '' ) == 1 ) {
			$x = '0' . $x;
		}

		my $url =
"http://www.accuweather.com/world-index-forecast.asp?partner=forecastfox&locCode=EUR|DE|GM0"
		  . $x . "|"
		  . ( uc $city ) . "|&u=1";

		#		say $url;
		print $sock "GET " . $url . " HTTP/1.0\n";
		print $sock "Host: www.accuweather.com\n";
		print $sock
"User-Agent: Mozilla/5.0 (X11; U; Linux i686; de; rv:1.8.1.10) Gecko/20071213 Fedora/2.0.0.10-3.fc8 Firefox/2.0.0.10\n";
		print $sock "\n";

		my @lines = <$sock>;

		#		print join '', @lines;
		foreach my $line (@lines) {
			chomp $line;
		}

		my $title = '';
		foreach my $line (@lines) {
			if ( $line =~ /cityTitle/ ) {
				$line =~ s/.*?<.*?><.*?>(.*?)<.*?><.*?>.*?/$1/igm;
				$line =~ s/^\s+//gm;
				$line =~ s/\s+$//gm;
				$title = $line;
			}
		}

		my $weather = '';
		foreach my $line (@lines) {
			if ( $line =~ /quicklook_current_wxtext/ ) {
				$line =~
				  s/[<]div\sid[=]["]quicklook_current_wxtext["][>]/$1/igm;
				$line =~ s/[<][\/]div[>]//igm;
				$line =~ s/^\s+//gm;
				$line =~ s/\s+$//gm;
				$weather = $line;
			}
		}

		my $temperature = '';
		foreach my $line (@lines) {
			if ( $line =~ /quicklook_current_temps/ ) {
				$line =~ s/[<]div\sid[=]["]quicklook_current_temps["][>]/$1/igm;
				$line =~ s/[<][\/]div[>]//igm;
				$line =~ s/[&]deg[;]C/Grad_Celsius/igm;
				$line =~ s/^\s+//gm;
				$line =~ s/\s+$//gm;
				$line =~ s/(\d+)/$1 /gm;
				$line =~ s/\s+/ /gm;
				$temperature = $line;
			}
		}

		my $humidity = '';
		foreach my $line (@lines) {
			if ( $line =~ /Humidity/ ) {
				$line =~ s/Humidity:/$1/igm;
				$line =~ s/[<]br\s*[\/][>]//igm;
				$line =~ s/^\s+//gm;
				$line =~ s/\s+$//gm;
				$humidity = $line;
			}
		}

		print Dumper [$title, $weather, $temperature, $humidity];

		select undef, undef, undef, 0.3;

		if ( !$title ) {
			next;
		}

   # fact statement in prolog:
   #
   # fact(verb, subj, obj, advs, quesword, descr, verb_2, subj_2, obj_2, advs_2)

		@fact_database = grep {
			$_->[0] !~ /wetter|weather|temperatur|humidity|luftfeuchtigkeit/
			&& $_->[11] ne 'weather'
		  }    
		  @fact_database;

		my @new_facts = (

			[
				'ist', "the weather", $weather, 'in ' . lc $city,
				'', '', '', '', '', '', 'weather'
			],
			[ 'ist', "it", $weather, 'in ' . lc $city, '', '', '', '', '', '' ],
			[
				'ist',
				"the temperature",
				$temperature . ' warm',
				'in ' . lc $city,
				'', '', '', '', '', '', 'weather'
			],
			[
				'ist', "the humidity", $humidity, 'in ' . lc $city,
				'', '', '', '', '', '', 'weather'
			],

			[
				'ist', "das wetter", $weather, 'in ' . lc $city,
				'', '', '', '', '', '', 'weather'
			],
			[ 'ist', "es", $weather, 'in ' . lc $city, '', '', '', '', '', '' ],
			[
				'ist', "es",
				$temperature . ' warm',
				'in ' . lc $city,
				'', '', '', '', '', '', 'weather'
			],
			[
				'ist', "es",
				$temperature . ' kalt',
				'in ' . lc $city,
				'', '', '', '', '', '', 'weather'
			],
			[
				'ist',
				"die temperatur",
				$temperature . ' warm',
				'in ' . lc $city,
				'', '', '', '', '', '', 'weather'
			],
			[
				'ist', "die luftfeuchtigkeit",
				$humidity, 'in ' . lc $city,
				'', '', '', '', '', '', 'weather'
			],

		);
		
		print Dumper @new_facts;
		
		push @fact_database, @new_facts;
		
		foreach my $fact_ref (@new_facts) {
			$fact_database_verbs{$fact_ref->[0]} = [] if !($fact_database_verbs{$fact_ref->[0]});
			push @{$fact_database_verbs{$fact_ref->[0]}}, $fact_ref;
			$fact_database_verbs{$fact_ref->[6]} = [] if !($fact_database_verbs{$fact_ref->[6]});
			push @{$fact_database_verbs{$fact_ref->[6]}}, $fact_ref;
		}

		open my $prolog_database_file, ">>",
		  $dir . "/lang_" . LANGUAGE() . "/facts.pro";
		foreach my $fact (@new_facts) {
			print $prolog_database_file ( join ' <> ', @$fact ), "\n";
		}
		close $prolog_database_file;

		last;
	}
}

sub answer_sentence {
	my $CLIENT_ref    = shift;
	my @subclauses    = @{ $_[0] };
	my $is_a_question = $_[1];

	for my $subclause_ref (@subclauses) {
		$subclause_ref = person_modification($subclause_ref);
	}

	my $sentence_ref = shift @subclauses;
	if ( not @subclauses ) {
		push @subclauses,
		  {
			'verbs'       => [''],
			'subjects'    => [ [ 'nothing', '' ] ],
			'objects'     => [ [ 'nothing', '' ] ],
			'quesword'    => '',
			'description' => '',
			'advs'        => [],
		  };
	}

	my @answers;
	if ($is_a_question || $sentence_ref->{'quesword'}) {
		weather_check($sentence_ref);

		if ( $sentence_ref->{'quesword'} ) {
			my @answers_here =
			  answer_sentence_questionword( $CLIENT_ref, $sentence_ref,
				\@subclauses );
			push @answers, @answers_here;
		}
		else {
			my @answers_here =
			  answer_sentence_yes_no( $CLIENT_ref, $sentence_ref,
				\@subclauses );
			push @answers, @answers_here;
		}
	}
	else {
		my @answers_here =
		  answer_sentence_statement( $CLIENT_ref, $sentence_ref, \@subclauses );
		push @answers, @answers_here;
	}

	my @shuffled = shuffle(@answers);
	my $answer   = $shuffled[ int( rand(@shuffled) ) ];

	# join the main clause and the sub clauses into one array ref
	return ( ucfirst $answer, [ $sentence_ref, @subclauses ] );
}

sub simple_answer {
	my $CLIENT_ref  = shift;
	my ($_question) = @_;
	my $question    = $_question . '';

	my $math = $question;
	$math =~ s/[=?!.]//igm;
	$math =~ s/was//igm;
	$math =~ s/ist//igm;
	$math =~ s/gibt//igm;
	$math =~ s/what//igm;
	$math =~ s/is//igm;
	$math =~ s/does//igm;
	$math =~ s/makes//igm;
	$math =~ s/ergibt//igm;
	$math =~ s/ plus /+/igm;
	$math =~ s/ minus /-/igm;
	$math =~ s/ geteilt durch /\//igm;
	$math =~ s/ dividiert durch /\//igm;
	$math =~ s/ durch /\//igm;
	$math =~ s/ mal /*/igm;
	$math =~ s/\s//igm;
	$math =~ s/[,]/./igm;
	my $value = undef;

	if ( $math =~ /^[\d+\-*.\/]+$/ ) {
		eval '$value = ' . $math . ';';
		if ($@) {
			say "\n\n\n";
			say "Error while using eval to compute: " . $@;
			say "\n\n\n";
		}
		elsif ($value) {
			if ( LANGUAGE() eq 'de' ) {
				$value = '' . $math . ' ergibt <i>' . $value . '</i>!';
			}
			if ( LANGUAGE() eq 'en' ) {
				$value = 'The answer is <i>' . $value . '</i> = ' . $math . '!';
			}
			return $value;
		}
	}
	if ( $math =~ /[;]/ ) {
		return 'Du wirst meinen Server nicht unter Kontrolle bekommen!';
	}

	$question =~ s/([.?!])//igm;

	my @greetings = (
		"guten tag",      "guten morgen",
		"hi",             "hallo",
		"hey",            "huhu",
		"guten abend",    "guten nachmittag",
		"good morning",   "hello",
		"good afternoon", "good night",
		"moygn",          "morygn",
		"morgen",         "moin",
		"moynd"
	);

	foreach my $greeting (@greetings) {
		if ( lc $question =~ /(^|\s)$greeting(\s|$)/i ) {
			@greetings =
			  map { ( ucfirst $_ . '!', ucfirst $_ . '.' ) } @greetings;

			my @localtime_array = localtime;
			my $hour            = $localtime_array[2];

			if ( LANGUAGE() == 'de' ) {
				return "Wie..? Immer noch wach...?"
				  if $hour >= 0 && $hour < 5;
				return "Guten Morgen!" if $hour >= 5  && $hour < 12;
				return "Guten Tag!"    if $hour >= 12 && $hour < 17;
				return "Guten Abend!"
				  if $hour >= 17 && $hour < 24;
			}
			else {
				return "You should sleep..." if $hour >= 0  && $hour < 5;
				return "Good morning."       if $hour >= 5  && $hour < 12;
				return "Hello!"              if $hour >= 12 && $hour < 17;
				return "Good night!"         if $hour >= 17 && $hour < 24;
			}

		}
	}

	my @interjunctions = qw{ja nein doch juhu juhuu huhu noe no yes};

	foreach my $interj (@interjunctions) {
		if ( lc $question =~ /(^|\s)$interj(\s|$)/
			|| word_type_of( $CLIENT_ref, ( split /\s|[,]/, $question )[0], 1 )
			== INTER )
		{
			say 'is interjunctions: ', $question;

			@interjunctions =
			  map { ( ucfirst $_ . '!', ucfirst $_ . '.' ) } @interjunctions;
			  
			push @interjunctions,	  new_things_wanted_to_know( $CLIENT_ref, );

			my @shuffled = shuffle(@interjunctions);
			my $answer   = $shuffled[ int( rand(@shuffled) ) ];
			return $answer;
		}
	}

	return;
}

sub check_is_true {
	my (	$recursive,
			$verb,        $subj,   $obj,    $_advs, $quesword,
			$description, $verb_2, $subj_2, $obj_2, $advs_2
		  )
		= @_;
		
	select undef, undef, undef, 2;
		
	my %is_replace_word = map { $_ => 1 } qw{er sie es ihn sie ihr ihm etwas};

		my $id = join ' <> ', @_;
		say "----------------------------";
		say $id;
		say "----------------------------";
		  
		my %is_verb_synonym = verb_synonyms($verb_2);
		my %is_subj_synonym = noun_synonyms($subj_2);
		my %is_obj_synonym  = noun_synonyms($obj_2);

		my %is_verb_one_synonym = verb_synonyms($verb);
		my %is_subj_one_synonym = noun_synonyms($subj);
		my %is_obj_one_synonym  = noun_synonyms($obj);

		my @advs = split /[;]/, $advs_2;

		my @results = ();
		
		my @facts_from_database = ();
		foreach my $verb_to_search (keys %is_verb_synonym) {
			push @facts_from_database, $fact_database_verbs{ $verb_to_search };
		}
		say "count: ", scalar @facts_from_database;
#		print Dumper map { ($_) ? (@$_) : () } @facts_from_database;;

		my @facts =
		  grep {
			#$is_verb_synonym{ $_->[0] }
			 # && 
			  ( $is_subj_synonym{ $_->[1] }
				|| $is_something{ $_->[1] }
				|| $is_something{$subj_2} )
			  && ( $is_obj_synonym{ $_->[2] }
				|| $is_something{ $_->[2] }
				|| $is_something{$obj_2} )
		  } map { ($_) ? (@$_) : () } @facts_from_database;

#		print Dumper \@facts;
		
		foreach my $result_ref (@facts) {
			say( 'obj: ', $obj, "\t" . '$result_ref->[2]: ',
				$result_ref->[2] );
			if ( $is_replace_word{$subj} ) {
				if ( !$obj_2 || $is_something{ lc $obj_2 } ) {
					$subj = $result_ref->[2];
				}
				if ( !$subj_2 || $is_something{ lc $subj_2 } ) {
					$subj = $result_ref->[1];
				}
			}
			if ( $is_replace_word{$obj} ) {
				if ( !$obj_2 || $is_something{ lc $obj_2 } ) {
					$obj = $result_ref->[2];
				}
				if ( !$subj_2 || $is_something{ lc $subj_2 } ) {
					$obj = $result_ref->[1];
				}
			}
			if ( $is_something{ lc $obj_2 } ) {
				$obj_2 = $result_ref->[2];
			}
			if ( $is_something{ lc $subj_2 } ) {
				$subj_2 = $result_ref->[1];
			}

			my $can_use_result = 0;

#			say( 'obj_2: ', $obj_2, "\t" . '$result_ref->[2]: ',
#				$result_ref->[2] );
#			say "##", 6, $can_use_result;
			$result_ref->[2] =~ s/[)(]//igm;
			foreach my $obj ( keys %is_obj_synonym ) {
				$obj =~ s/[)(]//igm;
				if ( $obj && !( $obj =~ /nothing/ ) ) {
					if (   !( $result_ref->[2] =~ /nothing/ )
						&& $result_ref->[2]
						&& $result_ref->[2] =~ /$obj/i )
					{
						$can_use_result = 1;
					}
				}
				else {
					$can_use_result = 1;
				}
			}
#			say "##", 5, $can_use_result;

			foreach my $adv (@advs) {
				chomp $adv;
				$adv = lc $adv;
				if (
					   $result_ref->[2] !~ /$adv/i
						&& $result_ref->[3] !~ /$adv/i
						&& $result_ref->[1] !~ /$adv/i 
				  )
				{
#					$can_use_result = 0;
				}
			}
#			say "##", 4, $can_use_result;

			if ($description) {
				$description    = lc $description;


				$description =~ s/nothing//igm;
				$description =~ s/^\s+//igm;
				$description =~ s/\s+$//igm;

				if ($description) {
					say $description;
					$can_use_result = 0;
					$can_use_result = 1
				  	if $result_ref->[2] =~ /$description/i;
					$can_use_result = 1
				  	if $result_ref->[3] =~ /$description/i;
				}
			}

#			say "##", 3, $can_use_result;
			push @results, $result_ref
			  if $can_use_result;

#			say "##", 2, $can_use_result;
			if ( !$description ) {
				if ($can_use_result) {
					my @word_count =
					  split( / /, scalar $result_ref->[2] );
					if ( @word_count > 1 ) {
						$can_use_result = 0;
					}
				}
			}
			
#			say "##", 1, $can_use_result;

			push @results, $result_ref if $can_use_result;

			#					print Dumper $result_ref;
		}

		if ((!@results || !($is_if_word{$quesword})) && $recursive <= 4) {
			my @facts_from_database_one
				= grep { $is_verb_one_synonym{ $_->[6] } } @fact_database;

			my @facts =
		  grep {
			#$is_verb_synonym{ $_->[0] }
			 # && 
			  ( $is_subj_one_synonym{ $_->[7] }
				|| $is_something{ $_->[7] }
				|| $is_something{$subj_2} )
			  && ( $is_obj_one_synonym{ $_->[8] }
				|| $is_something{ $_->[8] }
				|| $is_something{$obj_2} )
		  } @facts_from_database_one;
		  
# fact statement in prolog:
#
# fact(verb, subj, obj, advs, quesword, descr, verb_2, subj_2, obj_2, advs_2)

			foreach my $fact (@facts) {
				check_is_true($recursive + 1, @$fact);
			}
		}

	return if !($is_if_word{$quesword});

		if (@results) {
			
			my @new_facts = (
			  [
				$verb,   $subj,   $obj,   $_advs, 'weil', '',
				$verb_2, $subj_2, $obj_2, $advs_2
			  ]);
			  
			push @fact_database, @new_facts;
			  
			foreach my $fact_ref (@new_facts) {
				$fact_database_verbs{$fact_ref->[0]} = [] if !($fact_database_verbs{$fact_ref->[0]});
				push @{$fact_database_verbs{$fact_ref->[0]}}, $fact_ref;
				$fact_database_verbs{$fact_ref->[6]} = [] if !($fact_database_verbs{$fact_ref->[6]});
				push @{$fact_database_verbs{$fact_ref->[6]}}, $fact_ref;
			}

			  
				open my $prolog_database_file, ">>",
				  $dir . "/lang_" . LANGUAGE() . "/facts.pro";
				foreach my $fact (
					[
						$verb,   $subj,   $obj,   $_advs, 'weil', '',
						$verb_2, $subj_2, $obj_2, $advs_2
			  		]
			  					) {
					print $prolog_database_file ( join ' <> ', @$fact ), "\n";
				}
				close $prolog_database_file;
		}
}

sub better_question {
	my ($sent) = @_;

	$sent = ascii($sent);

	$sent =~ s/[?]/ ?/igm;
	$sent =~ s/^und\s*[,]\s*//igm;
	$sent =~ s/\s*[,]\s*(und|oder|or|and)/ $1/igm;
	$sent =~ s/^na\s*[,]\s*//igm;
	$sent =~ s/^und[,]\s*//igm;
	$sent =~ s/^na[,]\s*//igm;
	$sent =~ s/^und\s*//igm;
	$sent =~ s/^na\s+/ /igm;
	$sent =~ s/\s\s/ /igm;
	$sent =~ s/gehts/geht es/igm;
	$sent =~ s/geht's/geht es/igm;
	$sent =~ s/geht´s/geht es/igm;
	$sent =~ s/wie geht es [?]/wie geht es dir ?/igm;
	$sent =~ s/wie geht es\s*$/wie geht es dir ?/igm;

	$sent =~ s/wie viel uhr/wie uhr/igm;
	$sent =~ s/wie spaet/wie uhr/igm;
	$sent =~ s/[=]/ist/igm;
	$sent =~ s/hast du schon mal von (.*?) gehoert/was ist $1/igm;
	$sent =~ s/hast du schon von (.*?) gehoert/was ist $1/igm;
	$sent =~ s/hast du von (.*?) gehoert/was ist $1/igm;
	$sent =~ s/hast du mal von (.*?) gehoert/was ist $1/igm;
	$sent =~ s/hast du schon mal was von (.*?) gehoert/was ist $1/igm;
	$sent =~ s/hast du schon was von (.*?) gehoert/was ist $1/igm;
	$sent =~ s/hast du was von (.*?) gehoert/was ist $1/igm;
	$sent =~ s/hast du was mal von (.*?) gehoert/was ist $1/igm;
	$sent =~ s/weisst du\s*[,]*\s*//igm;
	$sent =~ s/weisst du//igm;
	$sent = ' ' . $sent . ' ';
	$sent =~ s/\snoch\s/ /igm;
	$sent =~ s/\sdenn\s/ weil /igm;
	$sent =~ s/\s(kein|keine|keinen|keiner|keinem|nicht)\skein(|e|en|er|em)\s/ kein$2 /igm;
	$sent =~ s/\s(kein|keine|keinen|keiner|keinem|nicht)\snicht\s/ $1 /igm;
	$sent =~ s/\sim\s/ in dem /igm;
	
	$sent =~ s/sth[.]/something/igm;
	$sent =~ s/sth/something/igm;
	$sent =~ s/do you know (what|who|where|how|when|which|whose)/$1/igm;
	$sent =~ s/do you know something about /what is /igm;
	$sent =~ s/ do you do/ are you/igm;
	
	$sent =~ s/^\s+//igm;
	$sent =~ s/\s+$//igm;

#	$sent =~ s/\sam\s/ an dem /igm if LANGUAGE() == 'de';
	
	say "better sentence: ", $sent;
	
	return $sent;
}

sub ask {
	my $CLIENT_ref      = shift;
	my $CLIENT          = ${$CLIENT_ref};
	my $sent_everything = shift;
	my $display_str_ref = shift;
	chomp $sent_everything;
	$sent_everything = correct_time($sent_everything);

	$sent_everything =~ s/(\d)[.]/$1/igm;
	$sent_everything =~ s/([.?!])/$1 DOT/igm;
	
	my $all_new_facts_as_string = '';
	
	foreach my $sent ( split /DOT/, $sent_everything ) {
		$sent =~ s/^\s//igm;
		$sent =~ s/\s$//igm;

		%cache_noun_or_not = ();

		my @answers = ();
		$$display_str_ref .= '<b>Mensch</b>:: ' . $sent . '<br>';
		print $CLIENT 'DISPLAY:' . $$display_str_ref . "\n";
		say 'DISPLAY:' . $$display_str_ref;

		$sent = better_question($sent);

		if ( my $perhaps_answer = simple_answer( $CLIENT_ref, $sent ) ) {
			$$display_str_ref .= '<b>JEliza</b>:: ' . $perhaps_answer . '<br>';
		}
		else {

			my ( $sentences, $is_a_question ) = split_sentence $CLIENT_ref,
			  $sent;
			my @sentences = @$sentences;

			foreach my $subclauses_ref (@sentences) {
				foreach my $sentence_ref (@$subclauses_ref) {
					$sentence_ref = remove_advs_to_list($sentence_ref);
				}
			}

			#if_then_algo(@sentences);

			foreach my $sentence_ref (@sentences) {
				( my $answer, $sentence_ref ) =
				  answer_sentence( $CLIENT_ref, $sentence_ref, $is_a_question );
				push @answers, $answer;
				$$display_str_ref .= '<b>JEliza</b>:: ' . $answer . '<br>';
			}

			if ( not $is_a_question ) {
				my @facts = ();    # empty
				foreach my $sentence (@sentences) {
					push @facts, hash_to_facts($sentence);
				}

				#				print 'facts: ' . "\n" . Dumper \@facts;
				push @fact_database, @facts;
				
				foreach my $fact_ref (@facts) {
					$fact_database_verbs{$fact_ref->[0]} = [] if !($fact_database_verbs{$fact_ref->[0]});
					push @{$fact_database_verbs{$fact_ref->[0]}}, $fact_ref;
					$fact_database_verbs{$fact_ref->[6]} = [] if !($fact_database_verbs{$fact_ref->[6]});
					push @{$fact_database_verbs{$fact_ref->[6]}}, $fact_ref;
				}


				open my $prolog_database_file, ">>",
				  $dir . "/lang_" . LANGUAGE() . "/facts.pro" or 
				  die 'Cannot write to \'' . $dir . "/lang_" . LANGUAGE() . "/facts.pro'";
				foreach my $fact (@facts) {
					print $prolog_database_file ( join ' <> ', @$fact ), "\n";
					
					$all_new_facts_as_string .= ";;;" if $all_new_facts_as_string;
					$all_new_facts_as_string .= join ' <> ', @$fact;
				}
				close $prolog_database_file;

				parse_synonyms(@facts);
			}
		}

		print $CLIENT 'DISPLAY:' . $$display_str_ref . "\n";
		say 'DISPLAY:' . $$display_str_ref;

		write_config %config, $config_file;
		
	}
	
	$all_new_facts_as_string =~ s/\s/%20/igm;
	
	if ($in_cgi_mode) {
		$$display_str_ref .= << "EOF";
	<iframe width="0" height="0" src="jeliza-cgi.pl?check_is_true=$all_new_facts_as_string">
	</iframe>
	
EOF
	}

	if (!$in_cgi_mode) {
		do_check_is_true_on_facts($all_new_facts_as_string);
	}

	return $$display_str_ref ;
}

sub do_check_is_true_on_facts {
	my ($str) = @_;
	
	$str =~ s/[%]20/ /igm;
	
#	say "do_check_is_true_on_facts($str)";
	
	foreach my $fact (split /[;][;][;]/, $str) {
		$fact = [ split /\s[<][>]\s/, $fact ];
		
#		say "check_is_true(0, @$fact)";
		check_is_true(0, @$fact);
	}
}

sub client_thread {
	my $CLIENT_ref = shift;
	my $CLIENT     = ${$CLIENT_ref};
	print $CLIENT "client_thread" . "\n";
	print $CLIENT 'JELIZA_FULL_VERSION:' . $FULL_VERSION . "\n";
	print $CLIENT 'NAME:' . $NAME . "\n";
	my $user = <$CLIENT>;
	$user =~ s{USER:}{}i;
	chomp $user;
	print "user: " . $user . "\n";

	print $CLIENT "Smile from the server to $user\n";

	$connected_clients += 1;

	my $display_str = q{};    # empty

	while ( my $line = <$CLIENT> ) {
		print $CLIENT "READY:.\n";
		chomp $line;
		if ( $line =~ /^QUESTION[:]/ ) {
			my $sentence = $line;
			$sentence =~ s/^QUESTION[:]//i;

			if ( $sentence =~ /\/STATUS/ ) {
				my $status = status_now();
				print $CLIENT 'DISPLAY:' . $status . "\n";
				print $CLIENT 'ANSWER:' . $status . "\n";
			}
			else {
				$working_client_requests += 1;
				ask( $CLIENT_ref, $sentence, \$display_str );
				do_check_is_true_on_facts();
				$working_client_requests -= 1;
			}
		}
	}
	close $CLIENT;

	$connected_clients -= 1;
}

sub status_now {
	return 'count of connected users: '
	  . $connected_clients
	  . '<br>count of working requests: '
	  . $working_client_requests . '<br>';
}

sub server_loop {
	print ">> Connecting...\n";
	my $port = 5173;

	my $sock = new IO::Socket::INET(
		LocalHost => '',
		LocalPort => '' . $port,
		Proto     => 'tcp',
		Listen    => 1,
		Reuse     => 1,
	);
	die "Could not create socket: $! \n" unless $sock;

	my $initialized = 0;

	say ">> Connected.";

	my $client_addr;
	while ( my $CLIENT = $sock->accept() ) {
		print ">> got a connection\n";

		if ( !$initialized ) {
			$initialized = 1;
			load_word_types();
			load_database_file(
				$dir . "/lang_" . LANGUAGE() . "/facts.pro" );
		}

		print $CLIENT "READY:EVERYTHING_INITIALIZED\n";

		print $CLIENT "READY:EVERYTHING_INITIALIZED\n";

		write_config %config, $config_file;

		threads->create( \&client_thread, \$CLIENT );
	}
}

sub load_database_file {
	my $file = shift;

	print ">> Loading fact database...\n";
	open my $prolog_database_file, "<",
	  $dir . "/lang_" . LANGUAGE() . "/facts.pro";
	@fact_database = <$prolog_database_file>;
	foreach my $fact (@fact_database) {
		chomp $fact;
		$fact =~ s/\s+[<][>]\s+[<][>]\s+/ <> nothing <> /gm;
		$fact =~ s/[<][>]/ <> /gm;
		$fact =~ s/\s+/ /gm;
		$fact = [ split /[<][>]/, $fact ];
		foreach my $item (@$fact) {
			$item =~ s/^\s//igm;
			$item =~ s/\s$//igm;
		}
	}
	@fact_database = grep { $_->[0] && $_->[0] ne 'st' && $_->[0] ne 'e'; } @fact_database;
	close $prolog_database_file;
	
	foreach my $fact_ref (@fact_database) {
		$fact_database_verbs{$fact_ref->[0]} = [] if !($fact_database_verbs{$fact_ref->[0]});
		push @{$fact_database_verbs{$fact_ref->[0]}}, $fact_ref;
		$fact_database_verbs{$fact_ref->[6]} = [] if !($fact_database_verbs{$fact_ref->[6]});
		push @{$fact_database_verbs{$fact_ref->[6]}}, $fact_ref;
	}


	# parsing synonym lines
	print ">> Parsing Synonyms...\n";
	parse_synonyms(@fact_database);

	print ">> Fact database loaded...\n";
}

sub parse_synonyms {
	my %is_acceptable_verb = (
		"sein" => 1,
		"bin"  => 1,
		"bist" => 1,
		"ist"  => 1,
		"sind" => 1,
		"seid" => 1,
		"be"   => 1,
		"am"   => 1,
		"are"  => 1
	);

	my (@facts) = @_;
	
	my @endings = ( qw{en e s n in innen es}, '' );

	#	say Dumper $prolog_lines;

	foreach my $parts_ref (@facts) {
		my @parts = @$parts_ref;
		my ( $subj, $verb, $obj ) = ( $parts[1], $parts[0], $parts[2] );

		#			say Dumper @parts;

		if ( $is_acceptable_verb{$verb} ) {
			#say join ', ', ( $subj, $verb, $obj );
			
			$subj =~
s/(der|die|das|den|des|dem|den|ein|eine|einer|einem|eines) //igm;
			$obj =~
s/(der|die|das|den|des|dem|den|ein|eine|einer|einem|eines) //igm;
			
			my $tmp1 = $noun_synonym_of{$subj};
			if ( !$tmp1 ) {
				$tmp1 = [];
			}
			push @$tmp1, $obj;
			
			$obj =~ s/[a-zA-Z]$//; # only once
			push @$tmp1, $obj;

			$obj =~ s/[a-zA-Z]$//; # only once
			push @$tmp1, $obj;

			$noun_synonym_of{$subj} = $tmp1;

#			my $tmp2 = $noun_synonym_of{$obj};
#			if ( !$tmp2 ) {
#				$tmp2 = '';
#			}
#			$tmp1 .= ',,,,' if $tmp1;
#			$tmp1 .= $subj;
#			$noun_synonym_of{$obj} = $tmp2;
		}

	}

}

sub detect_word_type_from_string {
        my ($CLIENT_ref, $line, $at_beginning) = @_;
        $line = lc $line;

        return NOUN            if $line =~ /igennam/i;
        return NOUN            if $line =~ /ubstan/i;
        return NOUN            if $line =~ /pronomen/i;
        return NOUN            if $line =~ /nomen/i;
        return INTER           if $line =~ /interjektion/i;
        return ADJ             if $line =~ /adv/i;
        return VERB            if $line =~ /verb/i;
        return ADJ             if $line =~ /adj/i;
        return PREP            if $line =~ /position/i;
        return NO_WORD_TYPE;
}

use LWP::UserAgent;
use HTTP::Request;
use LWP::Protocol;
use LWP::Protocol::http;
my $ua = LWP::UserAgent->new;
$ua->agent("Mozilla/5.0 (X11; U; Linux i686; de; rv:1.8.1.10) Gecko/20071213 Fedora/2.0.0.10-3.fc8 Firefox/2.0.0.10 JElizaPerl/1");

sub download_word_type {
        my ($CLIENT_ref, $word, $at_beginning) = @_;

#       select undef, undef, undef, 0.5;

        my $url = 'http://wortschatz.uni-leipzig.de/abfrage/';

        # Create a request
        my $req = HTTP::Request->new(POST => $url);
        $req->content_type('application/x-www-form-urlencoded');
        $req->content('Wort=' . $word . '&Submit=Suche!&site=10');

        # Pass request to the user agent and get a response back
        my $res = $ua->request($req);

        # Check the outcome of the response
        if (!$res->is_success) {
#       print $res->content;
                say 'Error while Downloading:';
                say $url;
        say $res->status_line;
        }

        my @lines = split /\n/, $res->content;

    my @not_correct_but_conjugated_last;
    my @not_correct_but_conjugated;

    while (my $line = shift @lines) {
#       say $line;
    
        if ($line =~ /licherweise haben Sie eine Seite zu schn/i) {
                select undef, undef, undef, 5;
                return download_word_type($CLIENT_ref, $word, $at_beginning);
                }
    
        if ($line !~ /Wortart: /i) {
                        next;
        }
        
        if ($line =~ /falsche Rechtschreibung von/i) {
        	shift @lines;
        	my $right_word = shift @lines;
        	$right_word =~ s/[<](.*?)//igm;
        	
        	my $ae = chr 228;
        	my $Ae = chr 196;
        	my $ue = chr 252;
        	my $Ue = chr 220;
        	my $oe = chr 246;
        	my $Oe = chr 214;
        	my $ss = chr 223;
        	
        	$right_word =~ s/[&]auml[;]/$ae/igm;
        	$right_word =~ s/[&]Auml[;]/$Ae/igm;
        	$right_word =~ s/[&]ouml[;]/$oe/igm;
        	$right_word =~ s/[&]Ouml[;]/$Oe/igm;
        	$right_word =~ s/[&]uuml[;]/$ue/igm;
        	$right_word =~ s/[&]Uuml[;]/$Ue/igm;
        	$right_word =~ s/[&]szlig[;]/$ss/igm;
        	
        	return download_word_type ($CLIENT_ref, $right_word, $at_beginning);
		}
        
        $line =~ s/[<](.+?)[>]//igm;
                $line = ascii($line);
                say "Line: ", $line;
        $line =~ s/Wortart: //igm;
                $line =~ s/^\s+//igm;
                $line =~ s/\s+$//igm;
                say "Line: ", $line;

        push @not_correct_but_conjugated, $line;
        
        last;
    }
    
    foreach my $line (@not_correct_but_conjugated) {
        my $wt = detect_word_type_from_string($CLIENT_ref, $line, $at_beginning);
        if ($wt != NO_WORD_TYPE && $wt == PREP) {
            say "- Downloaded word type (4): ", $wt;
            return $wt;
        }
    }
    foreach my $line (@not_correct_but_conjugated) {
        my $wt = detect_word_type_from_string($CLIENT_ref, $line, $at_beginning);
        if ($wt != NO_WORD_TYPE && $wt == VERB) {
            say "- Downloaded word type (2): ", $wt;
            return $wt;
        }
    }
    foreach my $line (@not_correct_but_conjugated) {
        my $wt = detect_word_type_from_string($CLIENT_ref, $line, $at_beginning);
        if ($wt != NO_WORD_TYPE) {
            say "- Downloaded word type (3): ", $wt;
            return $wt;
        }
    }
    foreach my $line (@not_correct_but_conjugated_last) {
        my $wt = detect_word_type_from_string($CLIENT_ref, $line, $at_beginning);
        if ($wt != NO_WORD_TYPE) {
            say "- Downloaded word type (last): ", $wt;
            return $wt;
        }
    }

    return NO_WORD_TYPE;

}

1;
