use strict;
use warnings;


    # 使い方
    # perl metricsWithNoWgt.pl mergePajFile 1th_Netfile 2th_NetFile
    # 時期(***)が同じPajファイルと2つのNetファイルが必要
    # ただし3-andmanには対応していない（要検討）

	my (@sortSubCommunity,@subCommunity,$subCommunity_1,$subCommunity_2,$andman);
	# Pajファイル，Netファイル(subCommunity_1またはsubCommunity_2)を読み込んでNode情報やArcs，Partition情報をそれぞれ配列に割り振るためのフラグ
	my ($flag4PajFile,$flag4NetFile1,$flag4NetFile2);
	# Pajファイル，Netファイル(subCommunity_1またはsubCommunity_2)を一行ずつ一時保存(？)するための変数
	my ($line,$line1,$line2);
	# Pajファイルの情報をそれぞれ保存するための変数ならびに配列
	my (@nodeNoInPajFile,@nodeNameInPajFile,@fromInPajFile,@toInPajFile,@numInPajFile,@arcListInPajFile,@partition,$arcsNumInPajFile,$nodeNumInPajFile);
	# 1番目のNetファイルの情報をそれぞれ保存するための変数ならびに配列
	my (@nodeNoInNetFile1,@nodeNameInNetFile1,@fromInNetFile1,@toInNetFile1,@numInNetFile1,@arcListInNetFile1,$arcsNumInNetFile1,$nodeNumInNetFile1);
	# 2番目のNetファイルの情報をそれぞれ保存するための変数ならびに配列
	my (@nodeNoInNetFile2,@nodeNameInNetFile2,@fromInNetFile2,@toInNetFile2,@numInNetFile2,@arcListInNetFile2,$arcsNumInNetFile2,$nodeNumInNetFile2);
	# PajファイルのIDとNetファイルのIDを対応確認時に利用する変数
	my ($fromID_NetFile1,$toID_NetFile1,$fromID_NetFile2,$toID_NetFile2);
	# ループ処理で使う変数
	my ($i,$j,$m,$n,$p,$q,$s,$t);
	# エッジを分類するための変数
	my (@sum_subCommunity_1toAndman,@sum_subCommunity_2toAndman,@sum_andmanToSubCommunity_1,@sum_andmanToSubCommunity_2);
	# andmanのメール総数を保存するための変数
	my ($sumSendMailNumToSubCommuinty_1,$sumSendMailNumToSubCommuinty_2,$sumReceiveMailNumFromSubCommuinty_1,$sumReceiveMailNumFromSubCommuinty_2);


################ subCommunity名を調べる(思いっきりきめうちｗ)　※どのandmanを調べるか決める ####################

	$subCommunity_1 = $ARGV[1];
	$subCommunity_2 = $ARGV[2];

	$subCommunity_1 =~ s/(.+)\_(.+)/$1/;
	push(@subCommunity, $subCommunity_1);
	$subCommunity_2 =~ s/(.+)\_(.+)/$1/;
	push(@subCommunity, $subCommunity_2);

	# 頭悪いけど応急処置
	# 1番目のsubCommunity（2番目の引数）
	if($subCommunity[0] eq "bug"){
		$subCommunity[0] = 1;
		$subCommunity_1 = 1;
	}
	elsif($subCommunity[0] eq "usr"){
		$subCommunity[0] = 2;
		$subCommunity_1 = 2;
	}
	elsif($subCommunity[0] eq "dev"){
		$subCommunity[0] = 3;
		$subCommunity_1 = 3;
	}

	# 2番目のsubCommunity（3番目の引数）
	if($subCommunity[1] eq "bug"){
		$subCommunity[1] = 1;
		$subCommunity_2 = 1;
	}
	elsif($subCommunity[1] eq "user"){
		$subCommunity[1] = 2;
		$subCommunity_2 = 2;
	}
	elsif($subCommunity[1] eq "dev"){
		$subCommunity[1] = 3;
		$subCommunity_2 = 3;
	}

	# 1番目と2番目のsubCommunity名から対象となるandmanを決める
	@sortSubCommunity = sort { $a cmp $b } @subCommunity;
	if($sortSubCommunity[0] == 1 && $sortSubCommunity[1] == 2){
		# バグ報告者とユーザのandman
		$andman = 4;
	}
	elsif($sortSubCommunity[0] == 2 && $sortSubCommunity[1] == 3){
		# ユーザと開発者のandman
		$andman = 5;
	}
	elsif($sortSubCommunity[0] == 1 && $sortSubCommunity[1] == 3){
		# バグ報告者と開発者のandman
		$andman = 6;
	}


############### Pajファイル，Netファイルを読み込んで必要な情報を取得 #########################


	$flag4PajFile = 0;

	# Pajファイルで必要なのは，Node情報(アドレス)とArcs情報，Partition情報
	open PAJ,$ARGV[0] or die "file open error: $ARGV[0]";
	while($line = <PAJ>){
		chomp($line);
		$line =~ s/\x0D\x0A|\x0D|\x0A/\n/g; 
		if($line =~ /\*Network/i){
			next;
		}
		elsif($line =~ /\*Arcs/i){
			$flag4PajFile = 1;
			next;
		}
		elsif($line =~ /\*Partition/i){
			unless($line =~ /\*Partition high\.clu/i){
				$flag4PajFile = 2;
				next;
			}
		}

		# OSSコミュニティ参加者のアドレス一覧
		# $nodeNoInPajFile[0]には*Verticesが入る
		# $nodeNameInPajFile[0]にはノード数が入る
		# e.g.) 1 "aaa@aaa.co.jp"　の場合，$nodeNoInPajFile[1]=1 $nodeNamePajFile[1]="aaa@aaa.co.jp"が入る
		if($flag4PajFile == 0){
			my($nodeNoInPajFile, $nodeNameInPajFile) = split / /, $line;
			#push(@nodeNoInPajFile, $nodeNoInPajFile);
			push(@nodeNameInPajFile, $nodeNameInPajFile);
		}

		# Arcs情報の取得 e.g.) 1 2 3 ⇒　fromInPajFile=1,toInPajFile=2,numInPajFile=3
		# $fromInPajFile[0]，$toInPajFile[0]，$numInPajFile[0]から順番に保存される
		elsif($flag4PajFile == 1){
			my($fromInPajFile, $toInPajFile, $numInPajFile) = split/ /, $line;
			# from to num の3要素に分けて配列へ
			push(@fromInPajFile, $fromInPajFile);
			push(@toInPajFile, $toInPajFile);
			push(@numInPajFile, $numInPajFile);
			push(@arcListInPajFile,"$fromInPajFile $toInPajFile $numInPajFile");
		}

		# partition情報の取得  e.g.) IDが1の人のpartition情報はpartition[1]に格納される
		# *Partition　○○.pajの次の行が*Vertices ノード数 なので，$partition[0]には"*Vertices ノード数"の文字列が入ってる
		elsif($flag4PajFile == 2){
			push(@partition, $line);
		}
	}

	# Pajファイルの*Arcsの総行数
	$arcsNumInPajFile = @arcListInPajFile;
	# Pajファイルの全ノード数
	$nodeNumInPajFile = $nodeNameInPajFile[0];


############### Netファイル(subCommunity_1)を読み込んで指標を取得する上で必要な情報を配列に保存 #################


	$flag4NetFile1 = 0;

	# Netファイル(subCommunity_1)で必要なのは，Node情報とArcs情報
	open NetFile1,$ARGV[1] or die "file open error: $ARGV[1]";
	while($line1 = <NetFile1>){
		chomp($line1);
		$line1 =~ s/\x0D\x0A|\x0D|\x0A/\n/g; 
		if($line1 =~ /\*Network/i){
			next;
		}
		elsif($line1 =~ /\*Arcs/i){
			$flag4NetFile1 = 1;
			next;
		}

		# 開発者ML参加者のアドレス一覧
		# $nodeNoInNetFile1[0]には*Verticesが入る
		# $nodeNameInNetFile1[0]にはノード数が入る
		if($flag4NetFile1 == 0){
			my($nodeNoInNetFile1, $nodeNameInNetFile1) = split / /, $line1;
			#push(@nodeNoInNetFile1, $nodeNoInNetFile1);
			push(@nodeNameInNetFile1, $nodeNameInNetFile1);
		}
		# Arcs情報の取得 e.g.) 1 2 3 ⇒　fromInPajFile=1,toInPajFile=2,numInPajFile=3
		# $fromInNetFile1[0]，$toInNetFile1[0]，$numInNetFile1[0]から順番に保存される
		elsif($flag4NetFile1 == 1){
			# from to num の3要素に分けて配列へ
			my($fromInNetFile1, $toInNetFile1, $numInNetFile1) = split/ /, $line1;
			push(@fromInNetFile1, $fromInNetFile1);
			push(@toInNetFile1, $toInNetFile1);
			push(@numInNetFile1, $numInNetFile1);
			push(@arcListInNetFile1,"$fromInNetFile1 $toInNetFile1 $numInNetFile1");
		}
	}
	# Netファイル(subCommunity_1)の*Arcsの総行数
	$arcsNumInNetFile1 = @arcListInNetFile1;
	# Netファイル(subCommunity_1)の全ノード数
	$nodeNumInNetFile1 = $nodeNameInNetFile1[0];


############### Netファイル(subCommunity_2)を読み込んで指標を取得する上で必要な情報を配列に保存 #################


	$flag4NetFile2 = 0;

	# Netファイル(subCommunity_2)で必要なのは，Node情報とArcs情報
	open NetFile2,$ARGV[2] or die "file open error: $ARGV[2]";
	while($line2 = <NetFile2>){
		chomp($line2);
		$line2 =~ s/\x0D\x0A|\x0D|\x0A/\n/g; 
		if($line2 =~ /\*Network/i){
			next;
		}
		elsif($line2 =~ /\*Arcs/i){
			$flag4NetFile2 = 1;
			next;
		}

		# ユーザML参加者のアドレス一覧
		# $nodeNoInNetFile2[0]には*Verticesが入る
		# $nodeNameInNetFile2[0]にはノード数が入る
		if($flag4NetFile2 == 0){
			my($nodeNoInNetFile2, $nodeNameInNetFile2) = split / /, $line2;
			#push(@nodeNoInNetFile2, $nodeNoInNetFile2);
			push(@nodeNameInNetFile2, $nodeNameInNetFile2);
		}
		# Arcs情報の取得 e.g.) 1 2 3 ⇒　fromInPajFile=1,toInPajFile=2,numInPajFile=3)
		# $fromInNetFile2[0]，$toInNetFile2[0]，$numInNetFile2[0]から順番に保存される
		elsif($flag4NetFile2 == 1){
			my($fromInNetFile2, $toInNetFile2, $numInNetFile2) = split/ /, $line2;
			push(@fromInNetFile2, $fromInNetFile2);
			push(@toInNetFile2, $toInNetFile2);
			push(@numInNetFile2, $numInNetFile2);
			push(@arcListInNetFile2,"$fromInNetFile2 $toInNetFile2 $numInNetFile2");
		}
	}
	# Netファイル(subCommunity_2)の*Arcsの総行数
	$arcsNumInNetFile2 = @arcListInNetFile2;
	# Netファイル(subCommunity_2)の全ノード数
	$nodeNumInNetFile2 = $nodeNameInNetFile2[0];


############## 指標値を算出するための前準備 (アンドマンのエッジを入次数と出次数とに分ける) ###########


	# andman(Partition = 3)から出ているエッジか、andmanに入っているエッジかで分けて考える
	for($j=0;$j<$arcsNumInPajFile;$j++){
		# andman ⇔　andmanだけを抽出した後，開発者ML内でのやりとりなのかユーザML内でのやりとりなのかを区別する
		if(($partition[$fromInPajFile[$j]] == $andman) && ($partition[$toInPajFile[$j]] == $andman)){
			# ちゃんとアンドマン同士のやりとりを抽出できてるかの確認f(^ ^;)
			#print $arcListInPajFile[$j],"\n";
			#print $fromInPajFile[$j]," --- ";
			#print $toInPajFile[$j],"\n";

			# 送信者・受信者がともにsubCommunity_1の場合
			# PajファイルでのIDとNetファイル(subCommunity_1)でのIDの対応関係を調べる
			for($m=1;$m<=$nodeNumInNetFile1;$m++){
				# ここではメッセージ送信者($from)のIDの対応関係を調べる
				if($nodeNameInPajFile[$fromInPajFile[$j]] eq $nodeNameInNetFile1[$m]){
					# PajファイルでIDが$fromInPajFile[$j]の人は，Netファイル(subCommunity_1)ではIDが$fromID_NetFile1
					$fromID_NetFile1 = $m;
				}
			}
			for($m=1;$m<=$nodeNumInNetFile1;$m++){
				# ここではメッセージ受信者($to)のIDの対応関係を調べる
				if($nodeNameInPajFile[$toInPajFile[$j]] eq $nodeNameInNetFile1[$m]){
					# PajファイルでIDが$toInPajFile[$j]の人は，Netファイル(subCommunity_1)ではIDが$toID_NetFile1
					$toID_NetFile1 = $m;
				}
			}

			for($n=1;$n<$arcsNumInNetFile1;$n++){
				unless(!defined($fromID_NetFile1) || !defined($toID_NetFile1)){
					if($fromInNetFile1[$n] == $fromID_NetFile1 && $toInNetFile1[$n] == $toID_NetFile1){
						# メッセージの送受信回数を数えるので条件に一致したものだけを加算していく
						# メッセージの送信者($from)をアンドマンとした場合　andman⇒subCommunity_1eloper(出次数)
						$sum_andmanToSubCommunity_1[$fromInPajFile[$j]] += $numInNetFile1[$n];
						# メッセージの受信者($to)をアンドマンとした場合　subCommunity_1⇒andman(入次数)
						$sum_subCommunity_1toAndman[$toInPajFile[$j]] += $numInNetFile1[$n];
					}
				}
			}

			# 送信者・受信者がともにsubCommunity_2の場合
			for($p=1;$p<=$nodeNumInNetFile2;$p++){
				# ここではメッセージ送信者($from)のIDの対応関係を調べる
				if($nodeNameInPajFile[$fromInPajFile[$j]] eq $nodeNameInNetFile2[$p]){
					# PajファイルでIDが$fromInPajFile[$j]の人は，Netファイル(subCommunity_2)ではIDが$fromID_NetFile2
					$fromID_NetFile2 = $p;
				}
			}
			for($p=1;$p<=$nodeNumInNetFile2;$p++){
				# ここではメッセージ受信者($to)のIDの対応関係を調べる
				if($nodeNameInPajFile[$toInPajFile[$j]] eq $nodeNameInNetFile2[$p]){
					# PajファイルでIDが$toInPajFile[$j]の人は，Netファイル(subCommunity_2)ではIDが$toID_NetFile2
					$toID_NetFile2 = $p;
				}
			}

			for($q=1;$q<$arcsNumInNetFile2;$q++){
				unless(!defined($fromID_NetFile2) || !defined($toID_NetFile2)){
					if($fromInNetFile2[$q] == $fromID_NetFile2 && $toInNetFile2[$q] == $toID_NetFile2){
						# メッセージの送受信回数を数えるので条件に一致したものだけを加算していく
						# メッセージの送信者($from)をアンドマンとした場合　andman⇒subCommunity_2(出次数)
						$sum_andmanToSubCommunity_2[$fromInPajFile[$j]] += $numInNetFile2[$q];
						# メッセージの受信者($to)をアンドマンとした場合　subCommunity_2⇒andman(入次数)
						$sum_subCommunity_2toAndman[$toInPajFile[$j]] += $numInNetFile2[$q];
					}
				}
			}
		}

		# andman ⇒ subCommunity_1 or subCommunity_2の場合(出次数)
		# andman ⇒ subCommunity_1 のパターン
		elsif($partition[$fromInPajFile[$j]] == $andman){
			if($partition[$toInPajFile[$j]] == $subCommunity_1){
				# エッジの本数を数えるので条件に一致したものだけを加算していく
				$sum_andmanToSubCommunity_1[$fromInPajFile[$j]] += $numInPajFile[$j];
			}
			
		# andman ⇒ subCommunity_2 のパターン
			elsif($partition[$toInPajFile[$j]] == $subCommunity_2){
				# エッジの本数を数えるので条件に一致したものだけを加算していく
				$sum_andmanToSubCommunity_2[$fromInPajFile[$j]] += $numInPajFile[$j];
			}
		}

		# subCommunity_1 or subCommunity_2r ⇒ andman　の場合(入次数)
		elsif($partition[$toInPajFile[$j]] == $andman){
			# subCommunity_1 ⇒ andman のパターン
			if($partition[$fromInPajFile[$j]] == $subCommunity_1){
				# エッジの本数を数えるので条件に一致したものだけを加算していく
				$sum_subCommunity_1toAndman[$toInPajFile[$j]] += $numInPajFile[$j];
			}
			# subCommunity_2 ⇒ andman のパターン
			elsif($partition[$fromInPajFile[$j]] == $subCommunity_2){
				# エッジの本数を数えるので条件に一致したものだけを加算していく
				$sum_subCommunity_2toAndman[$toInPajFile[$j]] += $numInPajFile[$j];
			}
		}
	}


################################# andmanのメール数をカウント #####################################


	# 初期化f(^ ^;)
	$sumSendMailNumToSubCommuinty_1 = 0;
	$sumSendMailNumToSubCommuinty_2 = 0;
	$sumReceiveMailNumFromSubCommuinty_1 = 0;
	$sumReceiveMailNumFromSubCommuinty_2 = 0;

	for($t=1;$t<=$nodeNumInPajFile;$t++){
		if($partition[$t] == $andman){
			# メール送信総数(andman⇒subCommunity_1)
			if(defined($sum_andmanToSubCommunity_1[$t])){
				$sumSendMailNumToSubCommuinty_1 += $sum_andmanToSubCommunity_1[$t];
			}
			# メール送信総数(andman⇒subCommunity_2)
			if(defined($sum_andmanToSubCommunity_2[$t])){
				$sumSendMailNumToSubCommuinty_2 += $sum_andmanToSubCommunity_2[$t];
			}

			# メール受信総数(andman⇒subCommunity_1)
			if(defined($sum_subCommunity_1toAndman[$t])){
				$sumReceiveMailNumFromSubCommuinty_1 += $sum_subCommunity_1toAndman[$t];
			}
			# メール受信総数(subCommunity_2⇒andman)
			if(defined($sum_subCommunity_2toAndman[$t])){
				$sumReceiveMailNumFromSubCommuinty_2 += $sum_subCommunity_2toAndman[$t];
			}
		}
	}


############## ファイルの出力 ###########################################################################


	# メール送信総数(一応，andmanToSubCommunity_1とandmanToSubCommunity_2の2つに分けている)
	print "***************** andmanのメール送信総数 *****************\n";
	print "andmanのメール総数(ToSubCommunity_1)：　",$sumSendMailNumToSubCommuinty_1,"\n";
	print "andmanのメール総数(ToSubCommunity_2)：　",$sumSendMailNumToSubCommuinty_2,"\n";
	print "andmanのメール総数(ToSubCommunity_1And2)：　",$sumSendMailNumToSubCommuinty_1 + $sumSendMailNumToSubCommuinty_2,"\n";

	# メール受信総数(一応，subCommunity_1ToAndmanとsubCommunity_2ToAndmanの2つに分けている)
	# メール受信総数は今回は不要なので無視
	print "***************** andmanのメール受信総数 *****************\n";
	print "andmanのメール総数(FromSubCommunity_1)：　",$sumReceiveMailNumFromSubCommuinty_1,"\n";
	print "andmanのメール総数(FromSubCommunity_2)：　",$sumReceiveMailNumFromSubCommuinty_2,"\n";
	print "andmanのメール総数(FromsubCommunity_1And2)：　",$sumReceiveMailNumFromSubCommuinty_1 + $sumReceiveMailNumFromSubCommuinty_2,"\n";


