# Author: Mete Rodoper

# Difference between random walk with wrapping and this one is; this has $runningTime limitation.
# 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';

#############################################################################################################
######################################## Input the values below #############################################
#############################################################################################################

$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 direcion
$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 = 50; # Number of destinations before script terminates
$runningTime = 100; # Running time bound for the script. when this equals to 0, program terminates

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

$mobileNumber = 0;
$previousNode = "";

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

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

$endMainLoop = 0;

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

	$noOfHops = $walkDuration/$speed;

	while ($noOfHops > 0 && $endMainLoop == 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 + 1;
			$newY = $floorY % 20 + 1;

			$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 + 1;
			$newY = $floorY % 20 + 1;

			$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 + 1;
			$newY = $ceilingY % 20 + 1;

			$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 + 1;
			$newY = $ceilingY % 20 + 1;

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

		if ($runningTime == 0)
		{
			print "The chosen distance is reached. Ending Simulation...\n";
			$endMainLoop = 1;
		}
		$noOfHops--;
	}

	if ($endMainLoop == 0)
	{
		$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;
$nodeNumber = $mobileNumberIterator + 1;

while (${$store{$mobileNumberIterator}}[$j] ne ())
{
	$tempWrite = ${$store{$mobileNumberIterator}}[$j];
	system("echo $tempWrite >> VM$nodeNumber.txt");
	$j = $j + 1;
}


