
    var white  = "#FFFFFF";
    var cblack  = "#000000";
    //var blue   = "#0000FF";
    var blue   = "#007FFF";
    var green  = "#008000";
    var red    = "#FF0000";
    var yellow = "#FFE303";
    var aqua   = "#00FFFF";
    var gray   = "#BEBEBE";
    var lime   = "#00FF00";
    var navy   = "#000080";
    var purple = "#800080";
    var silver = "#C0C0C0";
    var maroon = "#800000";
    var olive  = "#808000";
    var teal   = "#008080";
    var orange = "#FF6103";
    var chartreuse  = "#76EE00";
    var fuchsia  = "#FF00FF";
    var hotpink  = "#FF69B4";
    var grape  = "#CC00FF";

    var colors = new Array(0);
    colors.push(red);
    colors.push(blue);
    colors.push(aqua);
    colors.push(yellow);
    colors.push(fuchsia);
    colors.push(hotpink);
    colors.push(orange);
    colors.push(purple);
    colors.push(lime);
    colors.push(teal);
    colors.push(grape);
    colors.push(navy);
    colors.push(olive);
    colors.push(green);
    colors.push(maroon);
    colors.push(cblack);
    colors.push(white);

    var routeMap ;

    //var pbTrackpoints = [];
    var pbTrackpoints = new Array(0);

    var tracklineArray = new Array(0);
    var tracklineVisible = new Array(0);

    var timepointArray = new Array(0);
    var timepointArrayIndices = new Array(0);
    var timepointsPerTeamMax = 100;

    var checkpointMarkerArray = new Array(0);
    
    function onLoad() {
        if (GBrowserIsCompatible()) {
            // Setup Topo map option 
            CustomGetTileUrl =
                function(a,b,c) {
                    var lULP = new GPoint(a.x*256,(a.y+1)*256);
                    var lLRP = new GPoint((a.x+1)*256,a.y*256);
                    var lUL = G_NORMAL_MAP.getProjection().fromPixelToLatLng(lULP,b,c);
                    var lLR = G_NORMAL_MAP.getProjection().fromPixelToLatLng(lLRP,b,c);
                    var lBbox = lUL.x+","+lUL.y+","+lLR.x+","+lLR.y;
                    var lSRS = "EPSG:4326";
                    var lURL = this.myBaseURL;
                    lURL+="&REQUEST=GetMap";
                    lURL+="&SERVICE=WMS";
                    lURL+="&reaspect=false&VERSION=1.1.1";
                    lURL+="&LAYERS="+this.myLayers;
                    lURL+="&STYLES=default"; 
                    lURL+="&FORMAT="+this.myFormat;
                    lURL+="&BGCOLOR=0xFFFFFF";
                    lURL+="&TRANSPARENT=TRUE";
                    lURL+="&SRS="+lSRS;
                    lURL+="&BBOX="+lBbox;
                    lURL+="&WIDTH=256";
                    lURL+="&HEIGHT=256";
                    lURL+="&GroupName="+this.myLayers;
                    return lURL;
                }
            var tileDRG = new GTileLayer(new GCopyrightCollection(""),1,17);
            tileDRG.myLayers='DRG';
            tileDRG.myFormat='image/jpeg';
            tileDRG.myBaseURL='http://www.terraserver-usa.com/ogcmap6.ashx?';
            tileDRG.getTileUrl=CustomGetTileUrl;
            var topoLayer = [tileDRG];
            var topoMap = new GMapType(topoLayer, G_SATELLITE_MAP.getProjection(), "Topo", G_SATELLITE_MAP);

            // Build the map itself
            routeMap = new GMap2(document.getElementById("map")); 
            routeMap.addControl(new GLargeMapControl());
            routeMap.setCenter(new GLatLng(mapCenterLat, mapCenterLng), initialMapScale); 
            routeMap.addControl(new GLargeMapControl());
            routeMap.addControl(new GMapTypeControl());
            routeMap.addControl(new GScaleControl());
            routeMap.addControl(new ToggleTeamRoute());
            routeMap.addMapType(topoMap);

            AddCheckpoints("checkpoints.xml");
            for (var i = 0; i < numRoutes; i++) {
                var fileName = "team" + i + ".xml";
                AddTrack(fileName, colors[i], i, 2);
            }
        }
    } ;

    function AddCheckpoints(xmlFileName) {
        GDownloadUrl(xmlFileName, 
                     function(data) {
                         var xmlContents = GXml.parse(data);
                         // Parse out the checkpoints
                         var checkpointsContents = xmlContents.documentElement.getElementsByTagName("checkpoint");
                         var cparrayLast = 0;
                         for (var i = 0; i < checkpointsContents.length; i++) {
                             var chkpt = new GLatLng(parseFloat(checkpointsContents[i].getAttribute("lat")),
                                                  parseFloat(checkpointsContents[i].getAttribute("lng")));
                             if (cpDataContainsCPNums == 1) {
                                 cparrayLast = checkpointMarkerArray.push(
                                                   createCheckPointMarker(parseInt(checkpointsContents[i].getAttribute("cpnum")), 
                                                                          chkpt, checkpointsContents[i].getAttribute("clue")));
                             } else {
                                 cparrayLast = checkpointMarkerArray.push(
                                                   createCheckPointMarker(i+1, chkpt, checkpointsContents[i].getAttribute("clue")));
                             }
                             routeMap.addOverlay(checkpointMarkerArray[cparrayLast-1]);
                         }
                     }
                    );
    };

    // Creates a marker at the given point with the given number label
    function createCheckPointMarker(cpNum, point, clue) {
        var checkpointIcon = new GIcon();
        checkpointIcon.image = "../../images/cp" + cpNum + ".png";
        checkpointIcon.iconSize = new GSize(32, 32);
        checkpointIcon.iconAnchor = new GPoint(16, 32);
        checkpointIcon.infoWindowAnchor = new GPoint(16,30);
      
        var marker = new GMarker(point, checkpointIcon);
        GEvent.addListener(marker, "click", 
                           function() {
                               marker.openInfoWindowHtml("Checkpoint # " +  cpNum + "<p>" + 
                                                         "clue = " + clue );
                           }
                          );
        return marker;
    };


    function AddTrack(xmlFileName, trackColor, tNum, trackWeight) {
        GDownloadUrl(xmlFileName, 
                     function(data) {
                         var xmlContents = GXml.parse(data);

                         // Parse out the trackpoints
                         var trackpointsContents = xmlContents.documentElement.getElementsByTagName("trackpoint");
                         if (tNum == 0) {
                             for (var i = 0; i < trackpointsContents.length; i++) {
                                 pbTrackpoints.push(new GLatLng(parseFloat(trackpointsContents[i].getAttribute("lat")),
                                                                parseFloat(trackpointsContents[i].getAttribute("lng"))));
                             }
                             tracklineArray[tNum] = (new GPolyline(pbTrackpoints, trackColor, trackWeight, "0.8"));
                         } else {
                             var trackpoints = [];
                             for (var i = 0; i < trackpointsContents.length; i++) {
                                 trackpoints.push(new GLatLng(parseFloat(trackpointsContents[i].getAttribute("lat")),
                                                              parseFloat(trackpointsContents[i].getAttribute("lng"))));
                             }
                             tracklineArray[tNum] = (new GPolyline(trackpoints, trackColor, trackWeight, "0.8"));
                         }
                         //ENC var encPolylineString = encodePolylinePoints(trackpoints);
                         //ENC var encPolylineLevels = encodePolylineLevels(trackpoints);
                         //ENC tracklineArray[tNum] = (new GPolyline.fromEncoded({color: trackColor, 
                         //ENC                                                    weight: trackWeight, 
                         //ENC                                                    points: encPolylineString,
                         //ENC                                                    levels: encPolylineLevels,
                         //ENC                                                    zoomFactor: 16,
                         //ENC                                                    numLevels: 4}));
//var checkpoint = new GLatLng(30.274444,-97.774557);
//map.addOverlay(createCheckPointMarker(18, checkpoint, encPolylineLevels));
             
                         tracklineVisible[tNum] = 0;
                         //routeMap.addOverlay(tracklineArray[tNum]);

                         // Parse out the timepoints
                         var timepointsContents = xmlContents.documentElement.getElementsByTagName("timepoint");
                         for (var i = 0; i < timepointsContents.length; i++) {
                             var timept = new GLatLng(parseFloat(timepointsContents[i].getAttribute("lat")),
                                                         parseFloat(timepointsContents[i].getAttribute("lng")));
                             timepointArray[(tNum*timepointsPerTeamMax) + i] = (createTimeMarker(timept, 
                                                                                parseFloat(timepointsContents[i].getAttribute("elaptime")),
                                                                                parseFloat(timepointsContents[i].getAttribute("dist"))));
                             routeMap.addOverlay(timepointArray[(tNum*timepointsPerTeamMax) + i]);
                             routeMap.removeOverlay(timepointArray[(tNum*timepointsPerTeamMax) + i]);
                         }
                         timepointArrayIndices[tNum] = i;
                     }
                    );
    };
             
    function encodePolylinePoints(points) {
        var encoded_points = "";
        var plat = 0;
        var plng = 0;
        var dlat = 0;
        var dlng = 0;
        
        for(var i = 0; i < points.length; ++i) {
          var point = points[i];
      
          var late5 = Math.floor(point.lat() * 1e5);
          var lnge5 = Math.floor(point.lng() * 1e5);
      
          dlat = late5 - plat;
          dlng = lnge5 - plng;
      
          plat = late5;
          plng = lnge5;
      
          encoded_points += encodeSignedNumber(dlat) + encodeSignedNumber(dlng);
        }
        return encoded_points;
    };

    function encodePolylineLevels(points) {
        var encoded_levels = "";
        for(var i = 0; i < points.length; ++i) {
          //var point = points[i];
          var level = 3;
          encoded_levels += encodeNumber(level);
        }
        return encoded_levels;
    };

    // Encode a signed number in the encode format.
    function encodeSignedNumber(num) {
      var sgn_num = num << 1;
    
      if (num < 0) {
        sgn_num = ~(sgn_num);
      }
    
      return(encodeNumber(sgn_num));
    };
    
    // Encode an unsigned number in the encode format.
    function encodeNumber(num) {
      var encodeString = "";
    
      while (num >= 0x20) {
        encodeString += (String.fromCharCode((0x20 | (num & 0x1f)) + 63));
        num >>= 5;
      }
    
      encodeString += (String.fromCharCode(num + 63));
      return encodeString;
    };


    // Creates a marker at the given point with the given number label
    function createTimeMarker(point, hourNum, dist) {
        var timemarkIcon = new GIcon();
        timemarkIcon.image = "../../images/timemarker.png";
        timemarkIcon.iconSize = new GSize(32, 32);
        timemarkIcon.iconAnchor = new GPoint(16, 32);
        timemarkIcon.infoWindowAnchor = new GPoint(16, 30);
    
        var marker = new GMarker(point, timemarkIcon);
        GEvent.addListener(marker, "click", 
                           function() {
                               marker.openInfoWindowHtml("Elapsed Time = " + 
                                                         ((Math.round(hourNum/36))/100) + " hours" + 
                                                         "<p> Total Distance = " + ((Math.round(dist * 100))/100) + 
                                                         " meters (which = " + 
                                                         ((Math.round(dist * 0.062))/100) + " miles)");
                           }
                          );
        return marker;
    };

    function ToggleTeamRoute() {
    };

    ToggleTeamRoute.prototype = new GControl();

    function AddRemoveOverlay(tNum) {
        var i;
        if (tracklineVisible[tNum]) {
            routeMap.removeOverlay(tracklineArray[tNum]);
            for (i = (tNum*timepointsPerTeamMax); i < (tNum*timepointsPerTeamMax) + timepointArrayIndices[tNum]; i++) {
                routeMap.removeOverlay(timepointArray[i]);
            }
            tracklineVisible[tNum] = 0;
        } else {
            if (tNum == 0) {
                //routeMap.removeOverlay(tracklineArray[tNum]);
                var j;
                var junk;
                var polyLineArray = new Array(0);
                var curPolyLine;
                var tempTrackpoints = [];
                tempTrackpoints[0] = pbTrackpoints[0];
                tempTrackpoints[1] = pbTrackpoints[1];
                tempTrackpoints[2] = pbTrackpoints[2];
                tempTrackpoints[3] = pbTrackpoints[3];
                tempTrackpoints[4] = pbTrackpoints[4];
                tempTrackpoints[5] = pbTrackpoints[5];
                tempTrackpoints[6] = pbTrackpoints[6];
                tempTrackpoints[7] = pbTrackpoints[7];
                tempTrackpoints[8] = pbTrackpoints[8];
                tempTrackpoints[9] = pbTrackpoints[9];
                curPolyLine = (new GPolyline(tempTrackpoints, red, 2, "0.8"));
                curPolyLine.hide();
                polyLineArray.push(curPolyLine);

                //curPolyLine = (new GPolyline(pbTrackpoints, red, 2, "0.8"));
                routeMap.addOverlay(curPolyLine);
                for (i = 10; i < pbTrackpoints.length; i = i + 10) {
                    for (j = 0; j < 10; j++) {
                        tempTrackpoints[j] = pbTrackpoints[i+j];
                    }
                    delete curPolyLine;
                    curPolyLine = (new GPolyline(tempTrackpoints, red, 2, "0.8"));
                    curPolyLine.hide();
                    polyLineArray.push(curPolyLine);
                    routeMap.addOverlay(curPolyLine);
                }
                for (i = 0; i < polyLineArray.length; i++) {
                    polyLineArray[i].show();
                    for (j = 0; j < 100000; j++) {
                        junk = j * i;
                    }
                }
                //for (i = 0; i < polyLineArray.length; i++) {
                //    routeMap.removeOverlay(polyLineArray[i]);
                //}
            } else {
                routeMap.addOverlay(tracklineArray[tNum]);
                for (i = (tNum*timepointsPerTeamMax); i < (tNum*timepointsPerTeamMax) + timepointArrayIndices[tNum]; i++) {
                    routeMap.addOverlay(timepointArray[i]);
                }
                tracklineVisible[tNum] = 1;
            }
        }
    };

    // Creates a one DIV for each of the buttons and places them in a container
    // DIV which is returned as our control element. We add the control to
    // to the map container and return the element for the map class to
    // position properly.
    ToggleTeamRoute.prototype.initialize = function(map) {
        var i = 0;
        var container = document.createElement("div");

        if (numRoutes > 0) {
            var t0Toggle = document.createElement("div");
            this.setButtonStyle_(t0Toggle, colors[0]);
            container.appendChild(t0Toggle);
            t0Toggle.appendChild(document.createTextNode(teamNames[0]));
            GEvent.addDomListener(t0Toggle, "click", function() { AddRemoveOverlay(0); });
        }

        if (numRoutes > 1) {
            var t1Toggle = document.createElement("div");
            this.setButtonStyle_(t1Toggle, colors[1]);
            container.appendChild(t1Toggle);
            t1Toggle.appendChild(document.createTextNode(teamNames[1]));
            GEvent.addDomListener(t1Toggle, "click", function() { AddRemoveOverlay(1); });
        }

        if (numRoutes > 2) {
            var t2Toggle = document.createElement("div");
            this.setButtonStyle_(t2Toggle, colors[2]);
            container.appendChild(t2Toggle);
            t2Toggle.appendChild(document.createTextNode(teamNames[2]));
            GEvent.addDomListener(t2Toggle, "click", function() { AddRemoveOverlay(2); });
        }

        if (numRoutes > 3) {
            var t3Toggle = document.createElement("div");
            this.setButtonStyle_(t3Toggle, colors[3]);
            container.appendChild(t3Toggle);
            t3Toggle.appendChild(document.createTextNode(teamNames[3]));
            GEvent.addDomListener(t3Toggle, "click", function() { AddRemoveOverlay(3); });
        }

        if (numRoutes > 4) {
            var t4Toggle = document.createElement("div");
            this.setButtonStyle_(t4Toggle, colors[4]);
            container.appendChild(t4Toggle);
            t4Toggle.appendChild(document.createTextNode(teamNames[4]));
            GEvent.addDomListener(t4Toggle, "click", function() { AddRemoveOverlay(4); });
        }

        if (numRoutes > 5) {
            var t5Toggle = document.createElement("div");
            this.setButtonStyle_(t5Toggle, colors[5]);
            container.appendChild(t5Toggle);
            t5Toggle.appendChild(document.createTextNode(teamNames[5]));
            GEvent.addDomListener(t5Toggle, "click", function() { AddRemoveOverlay(5); });
        }

        if (numRoutes > 6) {
            var t6Toggle = document.createElement("div");
            this.setButtonStyle_(t6Toggle, colors[6]);
            container.appendChild(t6Toggle);
            t6Toggle.appendChild(document.createTextNode(teamNames[6]));
            GEvent.addDomListener(t6Toggle, "click", function() { AddRemoveOverlay(6); });
        }

        if (numRoutes > 7) {
            var t7Toggle = document.createElement("div");
            this.setButtonStyle_(t7Toggle, colors[7]);
            container.appendChild(t7Toggle);
            t7Toggle.appendChild(document.createTextNode(teamNames[7]));
            GEvent.addDomListener(t7Toggle, "click", function() { AddRemoveOverlay(7); });
        }

        if (numRoutes > 8) {
            var t8Toggle = document.createElement("div");
            this.setButtonStyle_(t8Toggle, colors[8]);
            container.appendChild(t8Toggle);
            t8Toggle.appendChild(document.createTextNode(teamNames[8]));
            GEvent.addDomListener(t8Toggle, "click", function() { AddRemoveOverlay(8); });
        }

        if (numRoutes > 9) {
            var t9Toggle = document.createElement("div");
            this.setButtonStyle_(t9Toggle, colors[9]);
            container.appendChild(t9Toggle);
            t9Toggle.appendChild(document.createTextNode(teamNames[9]));
            GEvent.addDomListener(t9Toggle, "click", function() { AddRemoveOverlay(9); });
        }

        if (numRoutes > 10) {
            var t10Toggle = document.createElement("div");
            this.setButtonStyle_(t10Toggle, colors[10]);
            container.appendChild(t10Toggle);
            t10Toggle.appendChild(document.createTextNode(teamNames[10]));
            GEvent.addDomListener(t10Toggle, "click", function() { AddRemoveOverlay(10); });
        }

        if (numRoutes > 11) {
            var t11Toggle = document.createElement("div");
            this.setButtonStyle_(t11Toggle, colors[11]);
            container.appendChild(t11Toggle);
            t11Toggle.appendChild(document.createTextNode(teamNames[11]));
            GEvent.addDomListener(t11Toggle, "click", function() { AddRemoveOverlay(11); });
        }

        if (numRoutes > 12) {
            var t12Toggle = document.createElement("div");
            this.setButtonStyle_(t12Toggle, colors[12]);
            container.appendChild(t12Toggle);
            t12Toggle.appendChild(document.createTextNode(teamNames[12]));
            GEvent.addDomListener(t12Toggle, "click", function() { AddRemoveOverlay(12); });
        }

        if (numRoutes > 13) {
            var t13Toggle = document.createElement("div");
            this.setButtonStyle_(t13Toggle, colors[13]);
            container.appendChild(t13Toggle);
            t13Toggle.appendChild(document.createTextNode(teamNames[13]));
            GEvent.addDomListener(t13Toggle, "click", function() { AddRemoveOverlay(13); });
        }

        if (numRoutes > 14) {
            var t14Toggle = document.createElement("div");
            this.setButtonStyle_(t14Toggle, colors[14]);
            container.appendChild(t14Toggle);
            t14Toggle.appendChild(document.createTextNode(teamNames[14]));
            GEvent.addDomListener(t14Toggle, "click", function() { AddRemoveOverlay(14); });
        }

        map.getContainer().appendChild(container);
        return container;
    };

    // By default, the control will appear in the bottom right corner of the
    // map with 7 pixels of padding.
    ToggleTeamRoute.prototype.getDefaultPosition = function() {
        return new GControlPosition(G_ANCHOR_BOTTOM_RIGHT, new GSize(7, 7));
    };

    // Sets the proper CSS for the given button element.
    ToggleTeamRoute.prototype.setButtonStyle_ = function(button, bgColor) {
        button.style.color = "#0000cc";
        //button.style.backgroundColor = "#FFFFFF";
        button.style.backgroundColor = bgColor;
        button.style.font = "small Arial";
        button.style.border = "2px solid black";
        button.style.padding = "2px";
        button.style.marginBottom = "3px";
        button.style.textAlign = "center";
        button.style.width = "7em";
        button.style.cursor = "pointer";
    };


