<?
// Author: Roger Banks - ke5aqd@ke5aad.com
// Date: 05 April 2005
// File: log.php
// Language: PHP
//
// Usage: "http://.../log.php[?source=1]
//
// Description:
// This script parses a exported XML file from jLog
// and outputs a formatted HTML Ham radio contact log.
// The format of the XML input file is:
// <ADIF>
// <header>
// <version></version>
// <description></description>
// <exported-by>
// <program></program>
// <version></version>
// <contacts></contacts>
// </exported-by>
// </header>
// <qso>
// <qso-date></qso-date>
// <time-on></time-on>
// <call></call>
// <band></band>
// <mode></mode>
// <tx-pwr></tx-pwr>
// <rst-sent></rst-sent>
// <rst-rcvd></rst-rcvd>
// <time-off></time-off>
// <name></name>
// <qth></qth>
// <qsl-sdate></qsl-sdate>
// <qsl-rcvd></qsl-rcvd>
// <sat-name></sat-name>
// <comment></comment>
// <dcxx></dcxx>
// <ituz></ituz>
// <cqz></cqz>
// <pfx></pfx>
// <cont></cont>
// <state></state>
// <cnty></cnty>
// <gridsquare></gridsquare>
// </qso>
// </ADIF>
//
// Change Log:
// 05 Apr 2005 Started Project
// 08 Apr 2005 Gutted some more leftovers. Importing just the call now.
// Added support for alternating row colors.
// 11 Apr 2005 Added unique contacts count, fixed bug causing blank grid field
// to contain data from previous entry.
// 12 Apr 2005 Added distance column.
// 13 Apr 2005 Added source display. Added DXCC and State counts. reformated
// name and QTH fields.
// 16 Apr 2005 Added prefix count. Reformatted totals section.
// 19 Apr 2005 added global decl to 'end_element' so that '$qsl_rcvd' is output
// 28 Apr 2005 Added QSLs Sent and QSLs Rcvd outputs along with % returned.
// Made callsign field into link to QRZ page.
// 02 May 2005 Added gridsquare count.
// 14 May 2005 Fixed Table header order.
// 08 Aug 2005 Added count of satellite contacts.
// 03 Oct 2005 Added PSK31 count.
// 19 Oct 2005 Added RTTY count.
//
// Todo:
// 11 Apr 2005 Better format for date and time.
// 16 Apr 2005 Count unique zones.
// 02 May 2005 Need to create script that takes an array and a string and
// generates a sorted table listing the array with the title of
// string. Generic lister for states, grids, prefixes, etc.
$source = 'log.php'; // name of this source file
$filename = 'log.xml'; // input file
if ($_REQUEST["SOURCE"] != "" || $_REQUEST["source"] != "") {
echo "<HTML><HEAD><TITLE>log.php source</TITLE></HEAD><BODY><FONT SIZE=1>";
show_source($source);
echo "</FONT></BODY></HTML>";
exit;
}
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=x-mac-roman">
<title>KE5AQD Logbook</title>
<meta name="generator" content="BBEdit 6.5.3">
<link rel="stylesheet" type="text/css" href="css/geo.css" />
</head>
<body>
<center><H1>KE5AQD Logbook</H1></center>
<P>
<?
require("mh_functions.php"); // gridsquare routines from
// http://www.viestikallio.fi/tools/maidenheadfuncs.php?source=1
if (file_exists($filename)) {
echo "This log is current as of: ";
echo date ("F d Y H:i:s.", filemtime($filename));
}
echo "<BR><TABLE cellspacing=0 cellpadding=3>" .
"<TR><TH>Date</TH><TH>UTC</TH><TH>Callsign</TH><TH>Band</TH>" .
"<TH>Mode</TH><TH>Pwr</TH><TH>Name</TH><TH>QTH</TH>" .
"<TH>Grid</TH><TH>QSL<BR>Sent</TH><TH>QSL<BR>Rcvd</TH>" .
"<TH>Dist<BR>(mi)</TH></TR>";
// initialize global variables
$call = ""; // callsign
$qso_date = ""; // qso date
$time_on = ""; // qso start time
$band = ""; // frequency band
$mode = ""; // mode
$tx_pwr = ""; // transmitter power
$name = ""; // station name
$qth = ""; // station location
$grid = ""; // gridsquare
$qsl_sent = ""; // date qsl card sent
$qsl_rcvd = ""; // date qsl card received
$dxcc = ""; // dxcc
$state = ""; // state
$prefix = ""; // prefix
$sat_name = ""; // satellite name
$callsigns = ""; // array of $calls
$dxccs = ""; // array of dxccs
$states = ""; // array of states
$prefixes = ""; // array of prefixes
$gridsquares = ""; // array of gridsquares
$qsls_sent = 0; // count of qsls sent
$qsls_rcvd = 0; // count of qsls rcvd
$cw_count = 0; // count of cw mode qsos
$sat_count = 0; // count of satellite contacts
$psk_count = 0; // count of PSK31 contacts
$rtty_count = 0; // count of RTTY contacts
$current_tag = ""; // the name of the current XML tag being processed
$row_count = 0;
///////////////////////////////////////////////////////////////////////////////
//
// Function: isEven
// Date: 13 Apr 2005
// Description:
// Determines if input is even.
// Inputs:
// string $num number to test
// Outputs:
// boolean, true if $num is even.
// Side effects:
// none
//
///////////////////////////////////////////////////////////////////////////////
function isEven ( $num ) {
return !($num % 2);
}
///////////////////////////////////////////////////////////////////////////////
//
// Function: format_name
// Date: 13 Apr 2005
// Description:
// Reformats person names and city, start names to correct capitalization.
// Inputs:
// string $str The string to reformat
// Outputs:
// string containing reformated string
// Side effects:
// none
//
///////////////////////////////////////////////////////////////////////////////
function format_name($str) {
$parts = explode(',', $str);
$name = ucwords(strtolower($parts[0]));
$suffix = trim(strtoupper($parts[1]));
if($suffix == "") return $name;
else if($suffix == 'JR') $suffix = 'Jr';
return $name . ', ' . $suffix;
}
///////////////////////////////////////////////////////////////////////////////
//
// Function: create_parser
// Date: 07 May 2003
// Description:
// This function opens an XML file and creates a parser to read it
// Inputs:
// string $filename The name of the XML file to parse
// Outputs:
// array return value: indicates successful file open and parser
// creation
// Side effects:
// none
//
///////////////////////////////////////////////////////////////////////////////
function create_parser ($filename) {
$fp = fopen($filename, 'r');
$parser = xml_parser_create();
xml_set_element_handler($parser, 'start_element', 'end_element');
xml_set_character_data_handler($parser, 'character_data');
//xml_set_processing_instruction_handler($parser, 'processing_instruction');
//xml_set_default_handler($parser, 'default');
return array($parser, $fp);
} // create_parser
///////////////////////////////////////////////////////////////////////////////
//
// Function: parse
// Date: 07 May 2003
// Description:
// This function parses the lines of an XML file
// Inputs:
// $parser Pointer to parser
// $fp file pointer
// Outputs:
// array return value: indicates successful parse operation
// Side effects:
// none
//
///////////////////////////////////////////////////////////////////////////////
function parse($parser, $fp) {
$blocksize = 4 * 1024;
while($data = fread($fp, $blocksize)) {
if(!xml_parse($parser, $data, feof($fp))) {
echo 'Parse Error: ' .
xml_error_string($parser) .
" at line " .
xml_get_current_line_number($parser);
return FALSE;
}
}
return TRUE;
} // parse
///////////////////////////////////////////////////////////////////////////////
//
// Function: start_element
// Date: 07 May 2003
// Description:
// This function handles start elements passed from the parser
// Inputs:
// pointer $parser pointer to parser
// string $element the name of the element
// array $attributes the elements attributes
// Outputs:
// none
// Side effects:
// sets values for globals
//
///////////////////////////////////////////////////////////////////////////////
function start_element($parser, $element, &$attributes) {
global $call;
global $current_tag;
$current_tag = $element;
//echo "Current Tag: $current_tag<BR>";
} // start_element
///////////////////////////////////////////////////////////////////////////////
//
// Function: end_element
// Date: 07 May 2003
// Description:
// This function handles end elements passed from the parser.
// Formats $lat and $lon to display five significant digits.
// Inputs:
// pointer $parser pointer to parser
// string $element the name of the element
// Outputs:
// html table row containing log information
// Side effects:
// sets value for globals
//
///////////////////////////////////////////////////////////////////////////////
function end_element($parser, $element) {
global $qso_date;
global $time_on;
global $call;
global $band;
global $mode;
global $tx_pwr;
global $name;
global $qth;
global $grid;
global $qsl_sent;
global $qsl_rcvd;
global $dxcc;
global $state;
global $prefix;
global $current_tag;
global $row_count;
global $callsigns;
global $dxccs;
global $states;
global $prefixes;
global $gridsquares;
global $qsls_sent; // count of qsls sent
global $qsls_rcvd; // count of qsls rcvd
global $cw_count; // count of cw qso
global $sat_count; // count of satellite contacts
global $psk_count;
global $rtty_count;
global $sat_name;
$current_tag = ""; // This is important, otherwise character data will
// be cleared before next 'waypoint' end tag.
//echo "$element<BR>";
if($element == "QSO") {
if($grid != "") {
$my_qth_coords = parsemaidenhead("EM10dj");
$station_coords = parsemaidenhead($grid);
$dist = maidenhead_km_distance($my_qth_coords, $station_coords);
$miles = $dist[s] * 0.621371192; // convert to miles
$idist = sprintf('%d',$miles);
}
$row_count++;
$callsigns[] = $call;
$states[] = $state;
$prefixes[] = $prefix;
$gridsquares[] = substr($grid, 0, 4); // Only the first four characters
// are significant
if($dxcc != 291) $dxccs[]= $dxcc; // Don't count CONUS
if($qsl_sent != "") $qsls_sent++;
if($qsl_rcvd != "") $qsls_rcvd++;
if($mode == "CW") $cw_count++;
if($sat_name != "") $sat_count++;
if($mode == "PSK31") $psk_count++;
if($mode == "RTTY") $rtty_count++;
if(isEven($row_count)) $color = "#CCFFCC"; // was 33FFFF
else $color = "White";
$table_row = "<TR bgcolor=$color>" .
"<TD>$qso_date</TD>" .
"<TD>$time_on</TD>" .
"<TD><A href=http://www.qrz.com/$call>$call</A></TD>" .
"<TD>$band</TD>" .
"<TD>$mode</TD>" .
"<TD>$tx_pwr</TD>" .
"<TD>$name</TD>" .
"<TD>$qth</TD>" .
"<TD>$grid</TD>" .
"<TD>$qsl_sent</TD>" .
"<TD>$qsl_rcvd</TD>" .
"<TD align=right>$idist</TD>";
$table_row .= "</TR>";
echo $table_row;
//echo "end<BR>";
$grid = "";
$qsl_sent = "";
$qsl_rcvd = "";
$state = "";
$dxcc = "";
$prefix = "";
$sat_name = "";
$name = "";
$qth = "";
}
//echo "End Element: $element<BR>";
} // end_element
///////////////////////////////////////////////////////////////////////////////
//
// Function: character_data
// Date: 07 May 2003
// Description:
// This function handles the character data from the parser.
// Inputs:
// pointer $parser pointer to parser
// string $data the cdata
// Outputs:
// none
// Side effects:
// sets values for globals
//
///////////////////////////////////////////////////////////////////////////////
function character_data($parser, $data) {
global $qso_date;
global $time_on;
global $call;
global $band;
global $mode;
global $tx_pwr;
global $name;
global $qth;
global $grid;
global $qsl_sent;
global $qsl_rcvd;
global $dxcc;
global $state;
global $prefix;
global $current_tag;
global $row_count;
global $sat_name;
//echo "Current Tag: $current_tag Data: -$data-<BR>";
if($current_tag == "CALL") $call = $data;
else if($current_tag == "QSO-DATE") $qso_date = $data;
else if($current_tag == "TIME-ON") $time_on = $data;
else if($current_tag == "BAND") $band = $data;
else if($current_tag == "MODE") $mode = $data;
else if($current_tag == "TX-PWR") $tx_pwr = $data;
//else if($current_tag == "NAME") $name = ucwords(strtolower($data));
else if($current_tag == "NAME") $name = format_name($data);
//else if($current_tag == "QTH") $qth = ucwords(strtolower($data));
else if($current_tag == "QTH") $qth = format_name($data);
else if($current_tag == "GRIDSQUARE") $grid = $data;
else if($current_tag == "QSL-SDATE") $qsl_sent = $data;
else if($current_tag == "QSL-RDATE") $qsl_rcvd = $data;
else if($current_tag == "DXCC") $dxcc = $data;
else if($current_tag == "STATE") $state = $data;
else if($current_tag == "PFX") $prefix = $data;
else if($current_tag == "SAT-NAME") $sat_name = $data;
//echo "Character Data: $data<BR>";
} //character_data
/*
function processing_instruction() {
}
function default() {
}
*/
// main program
if(list($parser, $fp) = create_parser($filename)) {
parse($parser, $fp);
fclose($fp);
xml_parser_free($parser);
} // main
?>
</TABLE>
<HR>
<P>
<?
echo "<TABLE><TR><TD align=left>Total Contacts:</TD>";
echo "<TD align=right>$row_count</TD>";
echo "<TD> </TD><TD align=left>DXCC Count:</TD>";
printf('<TD align=right>%d</TD>', count(array_unique($dxccs)));
echo "<TD> </TD><TD align=left>Prefix Count:</TD>";
printf('<TD align=right>%d</TD>', count(array_unique($prefixes)));
echo "<TD> </TD><TD align=left>QSLs Sent:</TD>";
echo "<TD align=right>$qsls_sent</TD></TR>";
echo "<TR><TD>Unique Contacts:</TD>";
printf('<TD align=right>%d</TD>', count(array_unique($callsigns)));
echo "<TD> </TD><TD align=left>State Count:</TD>";
printf('<TD align=right>%d</TD>', count(array_unique($states)));
echo "<TD> </TD><TD align=left>Gridsquares:</TD>";
printf('<TD align = right>%d</TD>', count(array_unique($gridsquares)));
echo "<TD> </TD><TD align=left>QSLs Rcvd:</TD>";
echo "<TD align=right>$qsls_rcvd</TD></TR>";
echo "<TR><TD>CW QSOs:</TD><TD align = right>$cw_count</TD><TD></TD>";
echo "<TD>Satellite Contacts:</TD><TD align=right>$sat_count</TD>";
echo "<TD></TD><TD></TD><TD></TD><TD></TD><TD>Return rate:</TD>";
printf('<TD align=right>%0.1f%%</TD>', $qsls_rcvd / $qsls_sent * 100);
echo "</TR>";
echo "<TR><TD>PSK31 Contacts:</TD><TD align=right>$psk_count</TD></TR>";
echo "<TR><TD>RTTY Contacts:</TD><TD align=right>$rtty_count</TD></TR>";
echo "</TABLE><P>";
if (file_exists($source)) {
echo "This file was last modified: " . date ("F d Y H:i:s.", filemtime($source));
echo " <a href=$source?source=1>(show source)</A>";
}
?>
<BR>
<address>Maintained by <a href="http://ccwf.cc.utexas.edu/~banks/">Roger Banks </a>
( <a href="mailto:ke5aqd@ke5aqd.com">ke5aqd@ke5aqd.com</a> )</address>
<BR>
This page was generated on: <?= date ("l, F d Y \a\\t h:i:s a.") ?> <BR>
<TABLE width=100%>
<TR>
<TD align="left"><A href="http://www.php.net">
<img src="../images/logos/php_logo.gif" alt="php logo" border=0></A></TD>
<TD align="right"><A href="http://www.barebones.com">
<img src="../images/logos/built_with_bbedit_01.gif" alt="bbedit logo" border=0></A></TD>
</TR>
</TABLE>
</body>
</html>