# Author: Mete Rodoper

# For more detail refer the How to code and use Various Mobility Model Scripts to Emulate Mobility at ORBIT tutorial

#!/usr/bin/perl

use Math::Round qw(:all);
use Math::Trig 'deg2rad';

#############################################################################################################
######################################## Enter the values here ##############################################
#############################################################################################################

$sourceXValue = 2; # Source X value
$sourceYValue = 2; # Source Y value

$walkDuration = 1000; # Walk duration in unit time in one direction. When this time elapses change direction
$speed = 100; # Average speed of the VMs  
$angle = 360; # Angle randomness of the movements
$randomnessInterval = 2; # Maximum distance that a node can jump at an iteration
$numberOfStops = 3;  # Number of destinations before script terminates

#############################################################################################################
#############################################################################################################
#############################################################################################################

$mobileNumber = 0;

$previousNode = "";


$numberOfStopsMax = $numberOfStops;
$mobileNumberIterator = $mobileNumber;
$intervalTime = 0;

$pointX = $sourceXValue;
$pointY = $sourceYValue;

while ($numberOfStops > 0)
{
	$speedChosen = int(rand($speed));
	$angleChosen = int(rand($angle));
	
	$angleRad = deg2rad($angleChosen);

	$noOfHops = $walkDuration/$speed;

	while ($noOfHops > 0)
	{
		$pointX = $pointX + cos($angleRad);
		$pointY = $pointY + sin($angleRad);

		$fractionX = abs($pointX - int($pointX));
		$fractionY = abs($pointY - int($pointY));

		$firstQuarter = $fractionY * $fractionY + $fractionX * $fractionX;
		$secondQuarter = $fractionY * $fractionY + (1-$fractionX) * (1-$fractionX);
		$thirdQuarter = (1-$fractionY) * (1-$fractionY) + (1-$fractionX) * (1-$fractionX);
		$fourthQuarter = (1-$fractionY) * (1-$fractionY) + $fractionX * $fractionX;

		$floorX = int($pointX);
		$floorY = int($pointY);
	


		if($pointX < 0)
		{
			$ceilingX = $floorX - 1;	
		}
		else
		{	
			$ceilingX = $floorX + 1;
		}

		if($pointY < 0)
		{
			$ceilingY = $floorY - 1;	
		}
		else
		{	
			$ceilingY = $floorY + 1;
		}

		$minDistance = $firstQuarter;
		$min = "1";
		if ($secondQuarter < $minDistance)
		{
			$min = "2";
			$minDistance = $secondQuarter;
		}
		if ($thirdQuarter < $minDistance)
		{
			$min = "3";
			$minDistance = $thirdQuarter;
		}
		if ($fourthQuarter < $minDistance)
		{
			$min = "4";
		}

		if ($min == "1")
		{
			$newX = $floorX % 20;
			$newY = $floorY % 20;

			$nodeNameAndTime = "node$newX-$newY";
			if ($previousNode ne $nodeNameAndTime)
			{
				$toFile = "$intervalTime $nodeNameAndTime";
				print "$toFile\n";;
				push @{$store{$mobileNumber}}, $toFile;
				$previousNode = $nodeNameAndTime;
				$runningTime--;
				$intervalTime = $intervalTime + $speed;
			}
		}
		elsif ($min == "2")
		{
			$newX = $ceilingX % 20;
			$newY = $floorY % 20;

			$nodeNameAndTime = "node$newX-$newY";
			if ($previousNode ne $nodeNameAndTime)
			{
				$toFile = "$intervalTime $nodeNameAndTime";
				print "$toFile\n";;
				push @{$store{$mobileNumber}}, $toFile;
				$previousNode = $nodeNameAndTime;
				$runningTime--;
				$intervalTime = $intervalTime + $speed;
			}
		}
		elsif ($min == "3")
		{
			$newX = $ceilingX % 20;
			$newY = $ceilingY % 20;

			$nodeNameAndTime = "node$newX-$newY";
			if ($previousNode ne $nodeNameAndTime)
			{
				$toFile = "$intervalTime $nodeNameAndTime";
				print "$toFile\n";;
				push @{$store{$mobileNumber}}, $toFile;
				$previousNode = $nodeNameAndTime;
				$runningTime--;
				$intervalTime = $intervalTime + $speed;
			}
		}
		elsif ($min == "4")
		{
			$newX = $floorX % 20;
			$newY = $ceilingY % 20;

			$nodeNameAndTime = "node$newX-$newY";
			if ($previousNode ne $nodeNameAndTime)
			{
				$toFile = "$intervalTime $nodeNameAndTime";
				print "$toFile\n";;
				push @{$store{$mobileNumber}}, $toFile;
				$previousNode = $nodeNameAndTime;
				$runningTime--;
				$intervalTime = $intervalTime + $speed;
			}
		}

		$noOfHops--;
	}

	$numberOfStopsToPrint = $numberOfStopsMax + 1 - $numberOfStops;
	$mobileNumberIteratorToPrint = $mobileNumberIterator +1;
	print "Destination No : $numberOfStopsToPrint is Reached for Mobile Node Number : $mobileNumberIteratorToPrint\n";	

	$pointX = $newX;
	$pointY = $newY;

	$numberOfStops--;
}

$mobileNumberIterator = 0;
$printNode = $mobileNumberIterator + 1;


while (${$store{$mobileNumberIterator}}[$j] ne ())
{
	$tempWrite = ${$store{$mobileNumberIterator}}[$j];
	#print "$tempWrite\n";
	system("echo $tempWrite >> VM$printNode.txt");
	$j = $j + 1;
}
$mobileNumberIterator--;
$j = 0;

