owenmaule / contractor-test

PHP, SQL, Javascript & jQuery test for a contract role.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

contractor-test

PHP, SQL, Javascript & jQuery test for a contract role.

Owen Maule o@owen-m.com http://owen-m.com/

Answers summary

Q1. PHP - Complete remove_nonAtoZ()

function remove_nonAtoZ( $input )
{
	if( ! is_string( $input ) )
	{
		throw new Exception( 'Invalid parameter "input" to remove_nonAtoZ(): ' . var_export( $input, true ) );
	}

	// example data: $input = "BA'3Ndf$%^A&*(nN)A"; $output = "BANANA";
	return preg_replace( '/[^A-Z]/' , '', $input );
}

Q2. PHP - Complete table_columns()

function table_columns( $input, $cols )
{
	if( ! is_array( $input ) )
	{
		throw new Exception( 'Invalid parameter "input" to table_columns(): ' . var_export( $input, true ) );
	}
	# Array is allowed to be empty and will be processed
	if( ! (int) $cols )
	{
		throw new Exception( 'Invalid parameter "cols" to table_columns(): ' . var_export( $cols, true ) );
	}
	$cols = (int) $cols;

	// problem: array of values are ordered to fill an html table by *column* (ie second value should appear beneath the first etc)
	// task: reorder array so that the values are in the order they will be output in html, filling each *row* of table at a time
	// example inputs: $input = array('apple', 'orange', 'monkey', 'potato', 'cheese', 'badger', 'turnip'), $cols = 2
	// example output: array(array('apple', 'cheese'), array('orange','badger'),...)

	# Function is badly named - it returns the rows!

	# Calculate number of rows
	$rowCount = ceil( count( $input ) / $cols );
	$result = array ( );

	# These are named in the domain of the solution
	$rowIndex = 0; # Which row we are outputting

	# Lay the values out along the columns, and store them in rows
	foreach( $input as $value )
	{
		# Place values of column one into the first index of each row
		# Subsequent calls adding to the same row will be into the later columns
		$result[ $rowIndex ][] = $value;
		# When reaching the last row, move to next column
		if( ++$rowIndex == $rowCount )
		{
			# Proceed to next column, i.e. second index of each row and so on
			$rowIndex = 0;
		}
	}
	return $result;
}

Q3. PHP - Complete first_day_of_next_month() below

function first_day_of_next_month( $date )
{
	if( ! is_string( $date ) )
	{
		throw new Exception( 'Invalid parameter "date" to first_day_of_next_month(): ' . var_export( $date, true ) );
	}
	
	// Expect and validate $date in in the format "dd/mm/yyyy"
	// Note that dd and mm of the provided date may be either one or two digits in length
	// Return false if provided date is not in the expected format or is not a valid date
	// Convert to the first day of the next month
	// return the string of the same date in the format "yyyy-mm-dd 00:00:00" (month and day should be two digits always)

	$dateParts = explode( '/', $date );
	foreach( $dateParts as &$datePart )
	{
		$datePart = (int) $datePart;
	}
	
	# Validate since Unix Epoch (January 1 1970 00:00:00 GMT)
	# Set no upper limit on year - avoid the Y10K bug!
	$daysInMonth = 0;
	if( 3 != count( $dateParts )
		|| $dateParts[ 2 ] < 1970
		|| $dateParts[ 1 ] < 1 || $dateParts[ 1 ] > 12
		|| $dateParts[ 0 ] < 1
		|| $dateParts[ 0 ] > ( $daysInMonth = cal_days_in_month( CAL_GREGORIAN, $dateParts[ 1 ], $dateParts[ 2 ] ) )
	)
	{
		throw new Exception( 'Invalid parameter "date" to first_day_of_next_month(): ' . var_export( $date, true )
			. ' evaluted to ' . implode( '/', $dateParts ) );
	}
	
	if( ! $daysInMonth )
	{
		throw new Exception( 'Call to cal_days_in_month() failed in first_day_of_next_month(): ' . var_export( $date, true )
			. ' evaluted to ' . implode( '/', $dateParts ) );
	}

	# First day
	$dateParts[ 0 ] = 1;
	# of next month
	if( 13 == ++$dateParts[ 1 ] )
	{
		# Increment year also
		$dateParts[ 1 ] = 1;
		++$dateParts[ 2 ];
	}
	
	$dateTime = new DateTime();
	
	if( false === $dateTime->setDate( $dateParts[ 2 ], $dateParts[ 1 ], $dateParts[ 0 ] ) )
	{
		throw new Exception( 'Call to DateTime::setDate() failed in first_day_of_next_month(): ' . var_export( $date, true )
			. ' evaluted to ' . implode( '/', $dateParts ) );
	}

	# No need to include time of day in format string (H:i:s)
	return $dateTime->format( 'Y-m-d 00:00:00' );
}

Q4. MySQL - Write a query to summarise tasks for a team of develpers

/*
CREATE TABLE developers (id int auto_increment, name varchar(255), PRIMARY KEY (id));
CREATE TABLE tasks (id int auto_increment, developer_id int, subject varchar(255), priority enum ('1','2','3'), status enum('queued','completed', 'approved'), PRIMARY KEY (id));

Write a query to join the two tables together to get a listing:
- Where each row represents a developer/status combination
- Excludes those that are 'approved'
- Shows a count of tasks
- All 'queued' are listed before all 'completed'
- The list is ordered by developer name within a status
(ie The entire answer to this question is a single query that satisfys all of the above)
*/

SELECT `tasks`.`status`, `developers`.`name`, COUNT( * ) AS `task_count`
FROM `tasks`
JOIN `developers`
ON `developers`.`id` = `tasks`.`developer_id`
WHERE `tasks`.`status` != "approved"
GROUP BY `tasks`.`status`, `tasks`.`developer_id`
ORDER BY `tasks`.`status`, `developers`.`name` ASC;

Q5. Javascript (JQuery optional)

/*
<form class="add_option_form">
	<input type="text" class="option_name" name="option_name" />
	<input type="submit" class="add_button" value="Add" />
</form>
<div class="checklist">
	<label><input type="checkbox" /><span class="option_name">Option 1</span></label>
	<label><input type="checkbox" checked="checked" /><span class="option_name">Option 2</span></label>
</div>
<div class="selected_options"></div>

Write javascript that will:
(a) Allow adding new checkboxes to div.checklist by using the form at the top
(b) Make sure that div.selected_options always contains text consisting of the names of all selected checkboxes (including those added dynamically)

(Note that you can use JQuery if you prefer OR use pure Javascript)
*/

Q5a. Javascript

<script type="text/javascript">
	function showSelectedOptions()
	{
		var selectedOptions = document.getElementsByClassName( "selected_options" )[ 0 ],
			checklist = document.getElementsByClassName( "checklist" )[ 0 ],
			checkboxes = checklist.getElementsByTagName( "input" ),
			selectedOptionsText = "";

		while( selectedOptions.firstChild )
		{
			selectedOptions.removeChild( selectedOptions.firstChild );
		}

		for( var index = 0; index != checkboxes.length; ++index )
		{
			if( checkboxes[ index ].checked )
			{
				if( selectedOptionsText.length )
				{
					selectedOptionsText += ", ";
				}
				selectedOptionsText += checkboxes[ index ].nextSibling.innerHTML;
			}
		}
		selectedOptions.innerHTML = selectedOptionsText;
	}

	showSelectedOptions();
	var addOptionForm = document.getElementsByClassName( "add_option_form" )[ 0 ],
		addOptionInputs = addOptionForm.getElementsByTagName( "input" ),
		checklist = document.getElementsByClassName( "checklist" )[ 0 ];

	for( var index = 0; index != addOptionInputs.length; ++index )
	{
		if( "submit" == addOptionInputs[ index ].type )
		{
			addOptionInputs[ index ].onclick = function() {
				for( var index = 0; index != addOptionInputs.length; ++index )
				{
					if( "text" == addOptionInputs[ index ].type )
					{
						var label = document.createElement( "label" ),
							input = document.createElement( "input" ),
							span = document.createElement( "span" );

						input.type = "checkbox";
						input.onclick = function() { showSelectedOptions(); return true; }
						span.className = "option_name";
						span.innerHTML = addOptionInputs[ index ].value;
						label.appendChild( input );
						label.appendChild( span );
						checklist.appendChild( label );
					}
				}
				return false;
			}
		}
	}
	
	var checkboxes = checklist.getElementsByTagName( "input" );
	
	for( var index = 0; index != checkboxes.length; ++index )
	{
		checkboxes[ index ].onclick = function() { showSelectedOptions(); return true; }
	}
</script>

Q5b. jQuery

<script type="text/javascript" src="//code.jquery.com/jquery-2.1.4.min.js">
</script>
<script type="text/javascript">
	function showSelectedOptions()
	{
		var selectedOptions = $( "div.selected_options" ),
			selectedOptionsText = "";
		selectedOptions.empty();
		$( "div.checklist input:checked" ).each( function() {
			if( selectedOptionsText.length )
			{
				selectedOptionsText += ", ";
			}
			selectedOptionsText += $( this ).next().html();
		} );
		selectedOptions.html( selectedOptionsText );
	}

	$( function() {
		showSelectedOptions();
		$( "form.add_option_form input[type=submit]" ).click( function() {
			var value = $( "form.add_option_form input[name=\'option_name\']" ).val();
			$( "div.checklist" ).append( \'<label><input type="checkbox" /><span class="option_name">\' + value + \'</span></label>\' );
			$( "div.checklist label:last-child input" ).click( function() {
				showSelectedOptions();
				return true;
			} );
			return false;
		} );
		$( "div.checklist input[type=checkbox]" ).click( function() {
			showSelectedOptions();
			return true;
		} );
	} );
</script>

About

PHP, SQL, Javascript & jQuery test for a contract role.


Languages

Language:PHP 100.0%