#!/usr/bin/perl 

#########################################
##### Author:		Sebastian Enger / B.Sc
##### CopyRight:	Sebastian Enger / B.Sc
##### LastModified	7.01.2007
##### Function:		Dublicated Content Filter für Google
##### Todo:			
########################################

# todo:
# statische synonym textdatei nehmen und diese dann abarbeiten, wenn kein treffer gefunden wurde dann benutze das langsame my $result	= Lingua::DE::Wortschatz::use_service('T', $_);
# StringManipulation ist mir noch zu krass, der text wird extrem unleserlich bis jetzt noch
###	amazon content grabbing + adding

# string::approx benutzen 
# TheCerial: my $ApproxMatchingQuantifier   = "40%";
# TheCerial: $matched						= amatch($FileName, $ApproxMatchingQuantifier, $TemporarySearchQuery);

# my $sentences			= get_sentences($text);				# returns an array ref
# my $FullContentArray	= &Main( $sentences	);
# $WordCount				= $#FullContent;

# synonyme in format bringen
# synonyme vergleichen mit textdate und zu modifizierendem text
# wenn syn. nicht in text datei vorhanden dann benutze webservice
# ergebnisse vom webservice dann auch in unsere syn. datei hinzufügen


# perl -MCPAN -e 'install "Text::German"'
# perl -MCPAN -e 'install "Text::English"'
# perl -MCPAN -e 'install "Lingua::EN:Inflect"'
# perl -MCPAN -e 'install "Lingua::DE::Wortschatz"'
# perl -MCPAN -e 'install "Lingua::DE::Num2Word"'
# perl -MCPAN -e 'install "Lingua::DE::ASCII"'
# perl -MCPAN -e 'install "Lingua::DE::Sentence"'
# perl -MCPAN -e 'install "Lingua::DE::TypoGenerator"'
# perl -MCPAN -e 'install "String::Approx"'
# perl -MCPAN -e 'install "Text::Levenshtein"'


# reniceing to 20 !
# system ("renice 20 $$");


use strict;
use Text::German;
# use Text::English;
use Lingua::DE::ASCII;
# use Lingua::EN::Inflect;
use Lingua::DE::Sentence;
use Lingua::DE::Num2Word;
use Lingua::DE::Wortschatz;	# 
# use String::Approx 'amatch';		# amatch
use Lingua::DE::TypoGenerator;		# generate typing errors from given keyword

use Data::Dumper;
use Text::Levenshtein qw(fastdistance);

# random initilisation
srand();


# variables
my $text						= "";
my $TextWordCounter				= 1;
my $ModifiedWordcounter			= 1;
my $FullContentArray			= "";
my $SynonymContent				= {};

my %SynonymContent				= ();
my @SynonymContent				= ();
my @FullContent					= ();
my @array						= ();

my $SrcFile						= "src-en.txt";	# quell	
my $ModFile						= "mod.txt";	# .. zielfile
my $SynFile						= "synonym-db/synonym-en.txt";
my $now_string					= localtime;

# src file einlesen
open( RH, "<$SrcFile" ) or die "sudden flaming death\n";
	flock(RH, 2);
	$text = do { local( $/ ) ; <RH> } ;
close RH;


open(SYN,"<$SynFile") or die;
	flock(SYN,2);
	@SynonymContent = <SYN>;
close SYN;


@FullContent			= split(' ', $text);
my $TextWordCounter		= $#FullContent; 
my $FullContentArray	= &Main( \@FullContent );
my $ModifiedText		= sprintf("%.5f", $ModifiedWordcounter / $TextWordCounter )  * 100;



# mod file schreiben
open( WH, ">$ModFile" ) or die "sudden flaming death\n";
	flock(WH, 2);
	for ( @{$FullContentArray} ) {	# todo: content ordnen: sprich nach 5 sätzen ( eg nach 5 .) ein \n schreiben
		print WH " $_";
	};
close WH;


my $now1_string = localtime;
# 	print "[$ModifiedText %] Modified Text - [$CurrentWordCount] Current Word / [$ModifiedWordcounter] Modified Words\n";
print "[$ModifiedText %] Modified Percentage of Text - [$TextWordCounter] Words in Text / [$ModifiedWordcounter] Modified Words\n";

print "Start at $now_string\n";
print "Finish at $now1_string\n";

exit;


########
### Main(): rufe alle wichtige funktionen geordnet auf

sub Main(){

	my $FullContent = shift;

	
		#	for ( @{$FullContent} ) {
		#		$_ = Zahl2Wort( $_ ) if ( $_ =~ /\d/ && rand() >= 0.6 );		# zahl in wort umwandeln, wenn quellzeichen eine zahl ist und rand > 0.6
		#	};
	
	$FullContent = &SynonymManipulation( $FullContent );				### SynonymManipulation(): zufälliges ersetzen von deutschen wörtern mit einem zufälligem synonym zum ursprünglichen wort	
	
		#	$FullContent = &TextBlowup( $FullContent );							### TextBlowup(): füge satzkombinationen zum array hinzu

	return $FullContent;

}; # Main()



###########
### SynonymManipulation(): zufälliges ersetzen von deutschen wörtern mit einem zufälligem synonym zum ursprünglichen wort

sub SynonymManipulation(){

	# todo: funktion um array content in datei zu schreiben in unserem db format / um content aus unserem db format in ein array einzulesen
	# danach: zuerst den leipzig word service querys stellen und erst danach auf unsere text datei zurückgreifen

	my $FullContentArray = shift;
	my $CurrentWordCount = 0;

	my @grepNames = grep( /bountiful/, @SynonymContent);
	print "@grepNames";
	exit;

	NEXTLOOP:
	for ( @{$FullContentArray} ) {
		
		$CurrentWordCount++;

		my $WordToModify		= $_;
		my $WordToModifyTemp	= $_;
		$WordToModifyTemp		=~ s/[;,?!.(){}&%$"]//g;

		for ( @SynonymContent ) {
			
			my $SynonymContentEntry = $_;

			my @SynTempEntrys = split("," , $SynonymContentEntry );

			for ( @SynTempEntrys ) {
				
				my $SynEntry	= $_;
				$SynEntry		=~ s/[;,?!.(){}&%$"]//g;
				
				chomp($SynEntry);

				my $LevenshteinDistance = fastdistance($WordToModifyTemp, $SynEntry) if length $WordToModify > 3;
				# print "$WordToModifyTemp MATCH $SynEntry\n";
				if ( $WordToModifyTemp =~ /$SynEntry/i && length $WordToModify > 3 && $LevenshteinDistance <= 2 ) {
						
					my $SynReplace = @SynTempEntrys[ int(rand($#SynTempEntrys)) ];

					# print "[$LevenshteinDistance] $WordToModify matches [$SynEntry]\n";
					# print "\tErsetze [$WordToModify] mit $SynReplace\n";
				
					my $ModifiedText = sprintf("%.4f", $ModifiedWordcounter / $TextWordCounter ) * 100;
					print "[$ModifiedText %] Modified Text - [$CurrentWordCount] Current Word / [$ModifiedWordcounter / $TextWordCounter] Modified Words\n";

					$ModifiedWordcounter++;
					# sleep 1;

					next NEXTLOOP;

				}; # if ( $WordToModify =~ /$SynEntry/i && length $WordToModify > 3 && $LevenshteinDistance <= 2 ) {

			}; # for ( @SynTempEntrys ) {

		}; # for ( @SynonymContent ) {


	#	my $random = rand();
	#	if ( $random > 0.975 ) {
	#		
	#		my $old		= $_;
	#		my $result;
	#		eval {
	#			$result	= Lingua::DE::Wortschatz::use_service('T', $_);
	#		};
	#		my @lines	= $result->hashrefs();
	#		my $String	= @lines[ rand(@lines) ] ;
	#		$_			= $String->{Synonym} if ( length($String->{Synonym}) > 1 );		
	#		print "Old: $old --- New: $_\n";
	#
	#	};

	}; # for ( @FullContentArray ) {

	return $FullContentArray;

}; # sub SynonymManipulation(){



############
### TextBlowup(): füge satzkombinationen zum array hinzu

sub TextBlowup(){
	
	my $FullContentArray = shift;

	for ( @{$FullContentArray} ) {
		
		my $random = rand();
		if ( $random > 0.95 ) {
			my @alpha_sorted = ();									# lege neues array an
			
			for (my $i=0; $i<=int(rand(20)); $i++ ) {				# für 0 bis rand(30) fülle ein das neue array @alpha_sorted mit zufälligen werten aus dem arrays @FullContent
				push(@alpha_sorted, @FullContent[ int(rand($#FullContent)) ] );
			};
		
			@alpha_sorted	= sort { $b cmp $a } (@alpha_sorted);	# führe  sort aus ...
					
			# later: splice the content of @alpha_sorted as a string somewhere in the rand(middle) of @FullContent

			for (@alpha_sorted) {
				push(@{$FullContentArray}, $_);						# ... und schaufele die geordneten daten wieder ans ende von  @FullContent
			};

		}; # if ( $random > 0.95 ) {

	}; # for ( @FullContent ) {

	return $FullContentArray;

}; # sub GrundformManipulation(){


###########
### Zahl2Wort(): wandele eine zahl in ein deutsches wort um

sub Zahl2Wort(){

	my $zahl = shift;
	my $text = Lingua::DE::Num2Word::num2de_cardinal( $zahl );
	if ( length ($text) >= length ($zahl) ) {
		return $text;
	} else {
		return $zahl;
	};

}; # sub Zahl2Wort(){









###########################################
##### folgenden code nicht verwenden
###########################################


### wörter falsch schreiben 
# use Lingua::DE::TypoGenerator;
# my $ldt = Lingua::DE::TypoGenerator->new();
# my @typos = $ldt->typos("Harry Potter");
# print join " \n", , @typos;



#	$FullContent = StringManipulation( $FullContent );					### StringManipulation(): buchstaben, zeichen, wörter spiegeln, vertauschen, löschen, ersetzen ...
#	$FullContent = &GrundformManipulation( $FullContent );				### GrundformManipulation(): reduzierung von deutschen wörtern auf ihre grundform

my @letters		= (	"a", "b", "c", "d", "e", "f", "g", "h",
					"i", "j", "k", "l", "m", "n", "o", "p",
					"q", "r", "s", "t", "u", "v", "w", "x",
					"y", "z" );

my @numbers		= ( "0", "1", "2", "3", "4", "5", "6", "7",
					"8", "9" );

my @characters	= (	"+", "-", "&", " ", "(", ")", "@", "!",
					"%" );


############
### GrundformManipulation(): reduzierung von deutschen wörtern auf ihre grundform

sub GrundformManipulation(){
	
	my $FullContentArray = shift;

	for ( @{$FullContentArray} ) {
		
		my $random = rand();

		if ( $random > 0.5 ) {
			$_ = Text::German::reduce($_);			
		};

	}; # for ( @FullContentArray ) {

	return $FullContentArray;

}; # sub GrundformManipulation(){





############
### StringManipulation(): buchstaben, zeichen, wörter spiegeln, vertauschen, löschen, ersetzen ...


sub StringManipulation(){
	
	my $FullContentArray = shift;

	for ( @{$FullContentArray} ) {


		# für jede Anweisung wird eine neue zufällige Zahl erstellt
		

		###
		# Erste Buchstaben groß/klein schreiben
		###

		my $random = rand();
		if ( $random > 0.4 && $random < 0.5 ) {
			$_ = ucfirst();		# zufällig ersten Buchstaben groß schreiben
		} elsif ( $random > 0.5 && $random < 0.6 ) {
			$_ = lcfirst();		# zufällig ersten Buchstaben klein schreiben
		};


		###
		# Wort groß/klein schreiben
		###

		my $random = rand();
		if ( $random >= 0.3 && $random <= 0.4 ) {
			$_ = uc();		# zufällig Wort groß schreiben
		} elsif ( $random >= 0.7 && $random <= 0.8 ) {
			$_ = lc();		# zufällig Wort klein schreiben
		};


		###
		# zufälliges Zeichen einfügen
		###

		my $random			= rand();
		my $replaceString	= @characters[ rand(@characters) ] ;
		
		if ( $random < 0.09 ) {
			substr($_, rand(length), 0 ) = "$replaceString";
		};
		
		
		###
		# zufällige Nummer einfügen
		###

		my $random			= rand();
		my $replaceString	= @numbers[ rand(@numbers) ] ;
		
		if ( $random < 0.09 ) {
			substr($_, rand(length), 0 ) = "$replaceString";
		};


		###
		# zufälligen Buchstaben einfügen
		###

		my $random			= rand();
		my $replaceString	= @letters[ rand(@letters) ] ;
		
		if ( $random < 0.09 ) {
			substr($_, rand(length), 0 ) = "$replaceString";	
		};


		###
		# Wörter zufällig verdoppeln
		###

		my $random = int(rand(30));
			
		if ( $random == 5 ) {
			$_ .= $_;
		};


		###
		# Wörter zufällig verdoppeln und das vedoppelte spiegeln
		###

		my $random = int(rand(30));
			
		if ( $random == 6 ) {
			$_ .= reverse $_;
		};


		###
		# Wörter zufällig spiegeln
		###

		my $random = int(rand(30));
			
		if ( $random == 7 ) {
			$_ = reverse $_;
		};


		###
		# zeichen aus einem Wort zufällig löschen
		###

		my $random	= rand();
		my $length  = length($_);
	
		if ( $length > 0 ) {
		
			if ( $random < 1/$length ) {
				substr($_, rand(length), rand(length) ) = "";
			}; # if ( $random < 1/$length ) {
		
		}; # if ( $length > 0 ) {
		
		###
		# Deutsche Umlaute zufällig ersetzen
		###

		my $random = int(rand(30));
			
		if ( $random == 1 ) {
			eval {
				$_ = to_ascii($_) if ( length($_) > 3 );
			};
		};


		###
		# Wort zufällig mit unsinnigen zeichen füllen
		###

		my $random	= rand();
		my $length  = length($_);
		
		if ( $length > 0 ) {

			if ( $random < 3/length ) {

				my $cp = $_;
				$_  = "";

				for ( length($cp) ) {
					
					my $random = int(rand(127));
					$_ .= chr($random);

				}; # for
			}; # if ( $random
		}; # if ( $length > 0 ) {
	
	}; # for ( @FullContent ) {

	return $FullContentArray;

}; # sub StringManipulation(){




# bringe die synonyme in ein hash ein
#for ( @SynonymContent ) {
#	# my @SynTempEntrys = split("," , $_ );
#	for ( split("," , $_ ) ) {
#		chomp;
#		# print "adde $_\n";
#		$SynonymContent->{ lc($_) } = undef;
#	}; # for ( @SynTempEntrys ) {
#}; # for ( @SynonymContent ) {

#print Dumper($SynonymContent); 
#exit;


1;