Chris Pollett >
Old Classes >
PIC40

   ( Print View )

Lecture Notes-PDF

Spring '01 Ad: Enrollment info

Course Info: Homework Assignments:
Practice Exams:
PIC:
                           












HW4 Solutions Page

Return to homework page.

<html>
<!--
	Filename: p40hw4file1.html

	Purpose: This file is the main document for our Toy Search Engine
                 site. It gives the opportunity to the user to search
                 the engine for an entry. It also has a link to the add a
                 page document (p40hw4file4.php).
-->

<head>

  <title>Toy Search Engine</title>
  <meta http-equiv="Content-Type" content="text/html;
        charset=iso-8859-1" />
  <meta name="Authors" content="Christopher Pollett" />
  <meta name="keywords" content="search engine" />

</head>

<body text="#000000" bgcolor="#99FFCC" link="#0000EE" vlink="#551A8B"
alink="#FF0000">


<h1 style="text-align:center">Toy Search Engine
</h1>

<!--The SSI that follows checks if the searchdb directory
    exists. If not it creates it. In the event that this document
    was accessed as the action of the add a page document's
    (p40hw4file4.php's) form, the SSI below adds the URL
    and description to the appropriate DBMS in the searchdb.
    It then prints out if this was successful.
-->

<!--#exec cgi="p40hw4file2.cgi" -->

<!-- Now we have the search form described in the purpose of this document.
-->

<form method="GET"
action="http://www.math.ucla.edu/~cpollett/hw4/p40hw4file1.php">

<div style="text-align:center">
<table border="0" cellpadding="0" >
  <tr>
   <td valign="center">Search database for a single keyword:
   </td>
   <td valign="bottom">
    <input type="text" name="searchfield" size="15" maxlength="80" />
   </td>
   <td valign="bottom">
    <input type="submit" name="submit1" value="Submit" />
   </td>
  </tr>
</table>
</form>

<!-- If this document was called as the action of the above form,
     then the next SSI checks the DBMs in the searchdb to see
     if there are any matches.
-->

<!--#exec cgi="p40hw4file3.cgi" -->
<br />

<a href="p40hw4file4.php" >Add a page to the database.</a>
<p>
This page was last modified <!--#flastmod file="p40hw4file1.php"-->.</p>
</div>

</body>
</html>


#!/usr/local/bin/perl
#
# Filename: p40hw4file2.cgi
#
# Purpose: This script is used by the Toy Search Engine to
#          associate a URL description pair with a list of
#          keywords. It is also called by the p40hw1file1.php
#          document to create the searchdb directory if it doesn't exist.
#

require "subparseform.lib";
Parse_Form();

#
# Begin Main Section
#

print "Content-type: text/html\n\n";

if(!$formdata{submit2})
	{CheckDir();} # if submit2 doesn't exist we check if need to create
                      # searchdb
else
	{AddPage();} # add URL description pairs to appropriate DBMs.
#
# End Main Section
#

#
# Function: CheckDir
#
# Purpose: creates the searchdb directory if it doesn't exist
#

sub CheckDir()
{
	if(-d "searchdb") {return;}
	mkdir("searchdb",0755);
}

#
# Function: AddPage
#
# Purpose: adds URL description row to a DBM hash for each keyword
#          passed in the keywords form variable.
#

sub AddPage()
{
	my @keywords= split(/\s/,$formdata{keywords}); #get list of keywords

	foreach $word (@keywords) #now add URL description row to
                                  #each keyword's DBM.
	{
		dbmopen(%urlTable,"searchdb/$word",0755);
		$urlTable{$formdata{url}}=$formdata{description};
		dbmclose(%urlTable);

	}
	print "<p>URL added to appropriate DBMs.</p>\n";
}

#!/usr/local/bin/perl
#
# Filename: p40hw4file3.cgi
#
# Purpose: This script presents the results a Toy Engine Search
#          on a given keyword.
#

require "subparseform.lib";
Parse_Form();

print "Content-type: text/html\n\n";

if(!$formdata{searchfield})
	{return;} #if the searchfield variable is not set
                  #then we haven't searched for anything yet so stop

#
# Now we check if the keyword exists as a DBM hash in the searchdb.
# If not print no matches. Otherwise, we open that hash and print
# the URL description pairs listed there.
#
if(-e "searchdb/$formdata{searchfield}.dir")
{
	dbmopen(%urlTable,"searchdb/$formdata{searchfield}",0755);

	print "<table>\n";

	#
        # The next while loop prints out the URL description pairs.
        #
	while( ($key, $value) = each(%urlTable))
	{
		print "<tr><td>\n";
		print "<a href=\"$key\">$key</a>\n";
		print "</td><tr><td>\n";
		print "Description:<br />\n$value\n";
		print "<br /><br /></td></tr>\n";
	}
	print "</table>\n";

	dbmclose(%urlTable);
}
else
{
	print "<p>Sorry, no matches.</p>\n";
}

<html>
<!--
	Filename: p40hw4file4.php

	Purpose: This document provides a form that allows the user
                 to associate a new URL description pair to a list of
                 keywords in th Toy Search Engine.
-->

<head>

  <title>Toy Search Engine -- add a page</title>
  <meta http-equiv="Content-Type" content="text/html;
        charset=iso-8859-1" />
  <meta name="Authors" content="Christopher Pollett" />
  <meta name="keywords" content="search engine" />

</head>

<body text="#000000" bgcolor="#99FFCC" link="#0000EE" vlink="#551A8B"
alink="#FF0000">

<div style="text-align:center">

<h1>Toy Search Engine -- add a page
</h1>

<!-- The action of the form on this page is p40hw4file1.html;
     however, the page is actually added by the cgi script
     p40hw4file2.cgi which is exec'd as an SSI in
     p40hw4file1.php
-->

<form method="GET"
action="http://www.math.ucla.edu/~cpollett/hw4/p40hw4file1.php">

  <table border="0" cellpadding="0" >
    <tr>
     <td>Enter a list of space separated keywords:</td>
    </tr>
    <tr>
     <td>
      <input type="text" name="keywords" size="40" maxlength="120" />
      <br /> <br />
     </td>
    </tr>
    <tr><td>Enter a URL:</td></tr>
    <tr>
    <td>
     <input type="text" name="url" size="40" maxlength="120" />
     <br /> <br />
    </td>
    </tr>
    <tr><td valign="top">Enter a description:</td></tr>
    <tr><td><textarea name="description" cols="40" rows="10">
        </textarea></td>
    </tr>
  </table>

  <input type="submit" name="submit2" value="Submit" />
  <input type="reset" name="Reset" />
</form>

<p>
This page was last modified <!--#flastmod file="p40hw4file4.php"-->.
</p>
</div>
</body>
</html>

#!/usr/local/bin/perl
#
# Name: NClock HW3 Bonus solutions
#
# Purpose: A simple PERL clock which sync's with the NIST atomic clock
#          or any internet clock which uses the RFC 867 time protocol.
#          Command line arguments: timezone, width, height, clockSite, sync frequency
#
# Example Uses: >NClock --- starts a 150x150 clock on PST using time-a.nist.gov
#                           syncing every 60 seconds.
#
#               >NClock -5 200 300 time-b.nist.gov 30
#                       --- starts a 200x300 clock on EST using time-b.nist.gov
#                           syncing every 30 seconds
#
# Author: Chris Pollett
#

#
# includes
#
use Tk;
use Socket;

#
# Globals
#

$PI=3.1415926535; # beloved constant

$zoneOffset = ($ARGV[0]) ? $ARGV[0] : -8; # timezones from Greenwich Mean Time

$clockSizeX = ($ARGV[1]) ? $ARGV[1] : 150; #clock width
$clockSizeY = ($ARGV[2]) ? $ARGV[2] : 150; #clock height

$syncClock = ($ARGV[3]) ? $ARGV[3] : "time-a.nist.gov"; #atomic clock to connect to
$syncFreq = ($ARGV[4]) ? $ARGV[4] : 300; # number of seconds between contacting atomic clock
$secCount=0; #counter used to tell when to resync with atomic clock

#
# Main Loop
#
$mw = MainWindow->new;

$mw->geometry("$clockSizeX"."x"."$clockSizeY");

$menu = $mw->Menu(-tearoff =>'0',
		-menuitems => [
		[ 'command' => "Greenwich",
                  -command=>sub{$zoneOffset = 0; $secCount=0;}],
		[ 'command' => "Maritime",
                  -command=>sub{$zoneOffset = -4; $secCount=0;}],
                [ 'command' => "Eastern",
                  -command=>sub{$zoneOffset = -5; $secCount=0;}],
		[ 'command' => "Central",
                  -command=>sub{$zoneOffset = -6; $secCount=0;}],
		[ 'command' => "Mountain",
                  -command=>sub{$zoneOffset = -7; $secCount=0;}],
		[ 'command' => "Pacific",
                  -command=>sub{$zoneOffset = -8; $secCount=0;}]
            ]);

$mw->bind("<Button-3>", sub{ $menu->Popup(-popover =>'cursor');});

$canvas = $mw->Canvas(-background => "white",
                      -height => $clockSizeX,
                      -width => $clockSizeY);
$canvas->pack(); #canvas on which clock drawn

$mw->repeat(1000,\&ReDraw);

MainLoop;


#
# Name: ReDraw($frame, $canvas);
#
# Purpose: computes current time (sync'd with atomic clock every $syncFreq seconds)
#          then draws clock based on this time
#

sub ReDraw
{
	#
	#get size of current window and resize clock accordingly
	#

	($clockSizeX,$clockSizeY)=split(/[x|+]/,$mw->geometry());

	$canvas->configure(-height => $clockSizeY,
                           -width => $clockSizeX);

	#
	# Now either sync with NIST time or assume a second has passed
	# and update time accordingly
	#

	if($secCount== 0)
        {
           $time = connectNIST();
	   ($hour,$minute,$second) =split(/:/,$time);

	   $hour =($hour+$zoneOffset)%24;

	   $ampm = ($hour<12)? "am" : "pm";
	   $hour %=12;

	}
	else
	{
	   $second = ($second+1)%60;
	   if($second == 0)
	   {
		$minute = ($minute+1)%60;
	        if($minute == 0)
		{$hour = ($hour+1)%12;}
	   }
	}

	#update title of clock then redraw clock face then sync update counter

	if (length($second)<2) {$second = "0$second";}
	if (length($minute)<2) {$minute = "0$minute";}

	$time = $hour.":".$minute.":".$second.$ampm;
        $mw->title($time);


	DrawClock($clockSizeX, $clockSizeY, $hour, $minute, $second);

	$secCount= ($secCount+1)%$syncFreq;
}

#
# Name: DrawClock($clockSizeX, $clockSizeY, $hour, $minute, $second)
#
# Purpose: Draws the picture of an analog clock according to the size
#          and time parameters passed
#

sub DrawClock
{

	#time to angle conversions

	$secondAng = $_[4]/30*$PI-$PI/2;
	$minuteAng = $_[3]/30*$PI+($secondAng+$PI/2)/60-$PI/2;
	$hourAng = $_[2]/6*$PI+($minuteAng+$PI/2)/12-$PI/2;

	#calculate border around clock and clock dimensions

	my $offSetX = $_[0]/15;
 	my $offSetY = $_[1]/15;
	my $diameterX = $_[0]-2*$offSetX;
	my $diameterY = $_[1]-2*$offSetY;
	my $radiusX = $diameterX/2;
	my $radiusY = $diameterY/2;
	my $centerX = $radiusX +$offSetX;
	my $centerY = $radiusY +$offSetY;

	#starting and ending positions of tick marks

	my $startTickX;
	my $startTickY;
	my $endTickX;
	my $endTickY;

	#lengths of ticks and of hands

	my $tickScaling = .85;
	my $secScaling = .85;
	my $minScaling = .75;
	my $hourScaling = .5;

	#
	#Clear screen & draw face
	#
	$canvas->delete("all");

	$canvas->createOval( $offSetX, $offSetY,
                             $diameterX+$offSetX,
                             $diameterY+$offSetY,
                             -width=>($offSetX+$offSetY)/4,
                             -outline=>"black");

	#
	#Draw Ticks
	#

	$tickWidth = ($offSetX+$offSetY)/8;
	for($theta=0; $theta< 2*$PI; $theta+= $PI/6)
	{
		$endTickX= $radiusX*cos($theta);
		$endTickY= $radiusY*sin($theta);
		$startTickX=  $tickScaling*$endTickX;
		$startTickY= $tickScaling*$endTickY;

		$canvas->createLine($centerX+$startTickX,
                                    $centerY+$startTickY,
                                    $centerX+$endTickX,
                                    $centerY+$endTickY,
                                    -fill=>"black",
                                    -width=>$tickWidth);
	}

	#
	#Draw Hour and Minutes then Seconds
	#

	$canvas->createLine($centerX+$hourScaling*$radiusX*cos($hourAng),
                            $centerY+$hourScaling*$radiusY*sin($hourAng),
 			    $centerX,
                            $centerY,
                            $centerX+$minScaling*$radiusX*cos($minuteAng),
                            $centerY+$minScaling*$radiusY*sin($minuteAng),
                            -fill=>"blue",
                            -width=>$tickWidth,
                            -joinstyle=>"bevel");

	$canvas->createLine($centerX+$secScaling*$radiusX*cos($secondAng),
                            $centerY+$secScaling*$radiusY*sin($secondAng),
 			    $centerX,
                            $centerY,
                            -fill=>"red",
                            -width=>$tickWidth/2,
                            -joinstyle=>"bevel");
}

#
# TCP Stuff
#

#
# Name: openTCP
#
# Purpose: given a stream, an internet address name, and a port opens a TCP
#          connection to that port. (Taken essentially from Client Web Programming Perl
#          book)
#

sub openTCP
{
	my ($FS, $dest, $port) = @_;

	my $protocol = getprotobyname('tcp');
	socket($FS, PF_INET, SOCK_STREAM, $protocol);
        my $sin =sockaddr_in($port, inet_aton($dest));
	connect($FS,$sin) || return undef;

	my $old_fh = select($FS);
	$| =1;
	select($old_fh);
	return 1;
}

#
# Name: connectNist
#
# Purpose: connects to a RFC-867 clock $syncClock grab its time string
#          and return hour, minute, second substring.
#

sub connectNIST
{
	my @time;
	my $timeString;

	#
	#connect to nist using RFC-867 protocol
	#get there time string and close connection
	#

	if(openTCP(F,$syncClock, 13) == undef)
	{
		print "Error connecting to server.\n";
		exit(-1);
	}

	$timeString="";
	$timeString .= $_ while (<F>);
	close(F);

	@time = split(/\s/, $timeString);


	return $time[3]; # return only hour:minute:second part of string

}