<?php
/*=======================================================================
 *
 * ranking.inc.php
 *
 * Autor: Marc Vollmann
 *
 =======================================================================*/


include_once ("../include/mcglobal.inc.php");
include_once ("../include/inc_pnpoly.inc.php");
if (!isset($standalone)) :
   include_once ("../include/auth.inc.php");
else :
   $hq_id = getParameterValue("0", "HQ_ID_DEFAULT", "1");
   if ($hq_id == "") :
      $hq_id = "1";
   endif;
endif;


// Gets courier lists according to the selected mode
// 0. Get ALL available couriers (with [1. is set!] or without blocked)                    	              returned in $retArray[0]
// 1. Get blocked couriers of the customers of a specified job                             	              returned in $retArray[1]
// 2. Get favoured couriers of the customers of a specified job                            	              returned in $retArray[2]
// 3. Get couriers of the mediation area (automatic guided by MODE_INTERMEDIATION)         	              returned in $retArray[3]
// 4. Get couriers of the neighbour mediation areas (automatic guided by MODE_INTERMEDIATION)             returned in $retArray[4]
// 5. Get neighbours of a specified mediation area (automatic guided by MODE_INTERMEDIATION)              returned in $retArray[5]
// 6. Get all courier filters of a specified job                                           	              returned in $retArray[6]
// 7. Get favoured couriers (like 2.!) but filtered all couriers being inside the areas        	          returned in $retArray[2] !!!
// 8. Get ALL available couriers (with [1. is set!] or without blocked) according to mandatory rights   	returned in $retArray[0] !!!

function getCourierByRanking($zipcode, $mode, $jobId, $neighbourLevel = "", $currentHqId = "", $radiusKm = 0) {
  global $db, $hq_id;
  global $logFile;
  $retArray = array(array(),array(),array(),array(),array(),array(),array(),array(),array());
  
  global $db2;
  getDb2Connection();     // Try to connect request server because of performance  

  if ($jobId != "") :
     if ($currentHqId == "" || $currentHqId == "0") :
        $currentHqId = getFieldValueFromId("job", "jb_id", $jobId, "hq_id_dispo");
     endif;
     if ($currentHqId == "" || $currentHqId == "0") :
        $currentHqId = getFieldValueFromId("job", "jb_id", $jobId, "hq_id");
     endif;
  endif;
  if ($currentHqId == "" || $currentHqId == "0") :
     $currentHqId = $hq_id;
  endif;
  $f_hq_id = explode(",", $currentHqId);

  if ($mode == "") : $mode = "1111111111"; endif;
  if (!is_numeric($jobId)) : $jobId == ""; endif;
  if ($neighbourLevel != "" && !is_numeric($neighbourLevel)) : $neighbourLevel = ""; endif;

  // MEDIATION MODE
  // Check job being longhaul
  $jbLonghaul = "0";
  if ($jobId != "") :
     $jbLonghaul = getFieldValueFromId("job", "jb_id", $jobId, "jb_longhaul");
  endif;
  // Get the general mediation mode for the headquarter for NO LONGHAUL jobs
  if ($jbLonghaul == "1") :
     $mediationMode = "4";
  else :
     $mediationMode = getParameterValue("0", "MODE_INTERMEDIATION", $currentHqId);
     if ($mediationMode == "") :
        $mediationMode = getFieldValueFromId("headquarters", "hq_id", $currentHqId, "hq_invmode");
     endif;
  endif;

  $blockedCouriersClause = "";
  $favouredCouriersClause = "";
  $mandatoryCourierFilterClause = "";
  $jb2crvhClause = "";
  
  // $whereClauseHqId = " cr.hq_id = '" . $currentHqId . "' AND ";
  $whereClauseHqId = "";
  
  $occupiedCourierClause = "";
  if (FALSE) : $occupiedCourierClause = " cr.cr_occupied = '0' AND "; endif;
  
  $rankingCr2CrvhMultiRelation = getParameterValue("0", "RANKING_CR2CRVH_MULTI_RELATION", $currentHqId);
  $cr2crvhClause = " cr.cr_id = crvh.cr_id AND ";
  if ($rankingCr2CrvhMultiRelation == "1") : $cr2crvhClause = " "; endif;
  
 
  // Get specific job data
  if ($jobId != "") :
     $tmpFields = getFieldsValueFromId("job","jb_id",$jobId,array("vht_id","jb_weight","jb_outlay","jb_cr_filter","jb_crvh_length","jb_crvh_width","jb_crvh_height","jb_crvh_position"));
     $jbVhtId   = $tmpFields[0];
     $jbWeight  = $tmpFields[1];
     $jbOutlay  = $tmpFields[2];    

     // Get all filter for checking the filter type
     $filterArr = getColVectorFromDB2ArrayByClause("courierfilter", "crf_type", "crf_type IN (0,1)", "crf_short", "crf_short", "", "");     

     // Check type of selected filters and define clause
     $jbCourierFilters = $tmpFields[3];
     $jbCourierFilters = ereg_replace (" ", "", $jbCourierFilters);
     $tmpArray = spliti(",",$jbCourierFilters);
     $tmpArrayLen = count($tmpArray);
     for ($i = 0; $i < $tmpArrayLen; $i++) :
         $tmpArray[$i] = trim($tmpArray[$i]);
         if ($tmpArray[$i] != "") :
            if ($filterArr[$tmpArray[$i]] == "0") :
               $mandatoryCourierFilterClause .= " AND crvh.crvh_filter LIKE '%," . $tmpArray[$i] . ",%' ";
            elseif ($filterArr[$tmpArray[$i]] == "1") :
               $mandatoryCourierFilterClause .= " AND cr.cr_filter LIKE '%," . $tmpArray[$i] . ",%' ";
            endif;
         endif;
     endfor;

     $jbCrvhLength   = $tmpFields[4];
     $jbCrvhWidth    = $tmpFields[5];
     $jbCrvhHeight   = $tmpFields[6];
     $jbCrvhPosition = $tmpFields[7];

     $rankingJb2CrvhMeasure = getParameterValue("0", "RANKING_JB2CRVH_MEASURE", $currentHqId);
     if ($rankingJb2CrvhMeasure == "1") : 
        $jb2crvhClause = " crvh.crvh_payload >= '" . $jbWeight . "' AND" .
                         " crvh.crvh_length >= '" . $jbCrvhLength . "' AND" .
                         " crvh.crvh_width >= '" . $jbCrvhWidth . "' AND" .
                         " crvh.crvh_height >= '" . $jbCrvhHeight . "' AND" .
                         " crvh.crvh_position >= '" . $jbCrvhPosition . "' AND ";
     endif;

     if (substr($mode,6,1) == "1") :
        $retArray[6] = $tmpArray;
     endif;
  endif;
      

  // Check for existence of zipcode and job id for favoured and blocked couriers according to the job
  if ($zipcode != "" && $jobId != "") :

     // ************************************************************************************
     // * Get all couriers which are blocked for the involved customers of the current job *
     // ************************************************************************************     
     if (substr($mode,1,1) == "1") :
        $blockedCourierArray = array();
        if ($jobId != "") :
           $constRankingBlockedCrForStation = getParameterValue("0", "RANKING_BLOCKED_COURIER_FOR_STATION", $currentHqId);
           if ($constRankingBlockedCrForStation == "") :
              $constRankingBlockedCrForStation = getParameterValue("0", "RANKING_BLOCKED_COURIER_FOR_STATION", "0");
           endif;
           $constRankingBlockedCrForPayer = getParameterValue("0", "RANKING_BLOCKED_COURIER_FOR_PAYER", $currentHqId);
           if ($constRankingBlockedCrForPayer == "") :
              $constRankingBlockedCrForPayer = getParameterValue("0", "RANKING_BLOCKED_COURIER_FOR_PAYER", "0");
           endif;
        
           // Ranking blocked courier for STATION
           if ($constRankingBlockedCrForStation == "1") :           
                                 
              $tmpSqlquery = "SELECT DISTINCT cscr.cr_id"
                             . " FROM tour AS tr, costcenter AS csc, customercourier AS cscr"
                             . " WHERE tr.jb_id = '" . $jobId . "' AND"
                             . "       tr.csc_id = csc.csc_id      AND"
                             . "       csc.cs_id = cscr.cs_id      AND"
                             . "       cscr.cscr_relation = '0'"
                             . " ORDER BY cscr.cr_id";
   
              $result = $db2->query($tmpSqlquery);
              if (DB::isError($result)) die ("$PHP_SELF 4: {$tmpSqlquery} " . $result->getMessage());
              while ($row = $result->fetch_assoc()):
                    $blockedCourierArray[] = $row["cr_id"];
              endwhile;
              $result->free();
           endif;

           // Ranking blocked courier for PAYER
           if ($constRankingBlockedCrForPayer == "1") :

              // Check first job is a cashpayer one
              $cscIdPayer = getFieldValueFromId("job", "jb_id", $jobId, "csc_id_payer");
              
              $constCscIdPayerCash = getParameterValue("0", "CSC_ID_PAYER_CASH", $currentHqId);
              if (($cscIdPayer != "") && ($cscIdPayer == $constCscIdPayerCash || $cscIdPayer == "-1" )) :
                 // Job is cashpayer one => Get id of the cashpayer
                 $tmpSqlquery = "SELECT DISTINCT cscr.cr_id"
                                . " FROM job AS jb, costcenter AS csc, customercourier AS cscr"
                                . " WHERE jb.jb_id = '" . $jobId . "'         AND"
                                . "       jb.csc_id_payer_cash = csc.csc_id   AND"
                                . "       csc.cs_id = cscr.cs_id              AND"
                                . "       cscr.cscr_relation = '0'"
                                . " ORDER BY cscr.cr_id";
              else :
                 // Job is an invoice one
                 $tmpSqlquery = "SELECT DISTINCT cscr.cr_id"
                                . " FROM tourservice AS trs, costcenter AS csc, customercourier AS cscr"
                                . " WHERE trs.jb_id = '" . $jobId . "'    AND"
                                . "       trs.csc_id = csc.csc_id         AND"
                                . "       csc.cs_id = cscr.cs_id          AND"
                                . "       cscr.cscr_relation = '0'"
                                . " ORDER BY cscr.cr_id";
              endif;

              $result = $db2->query($tmpSqlquery);
              if (DB::isError($result)) die ("$PHP_SELF 4: {$tmpSqlquery} " . $result->getMessage());           
              while ($row = $result->fetch_assoc()):
                    $blockedCourierArray[] = $row["cr_id"];
              endwhile;
              $result->free();
           endif;           
           
           if (count($blockedCourierArray) > 0) :
              $blockedCouriersClause = " cr.cr_id NOT IN (" . implode(",", $blockedCourierArray) . ") AND ";
           endif;
        endif;
        $retArray[1] = $blockedCourierArray;
     endif;
     

     // *************************************************************************************
     // * Get all couriers which are favoured for the involved customers of the current job *
     // *************************************************************************************    
     if (substr($mode,2,1) == "1" || substr($mode,7,1) == "1") :
        $favouredCourierArray = array();
        if ($jobId != "") :
           $constRankingFavCrForStation = getParameterValue("0", "RANKING_FAVOURED_COURIER_FOR_STATION", $currentHqId);
           if ($constRankingFavCrForStation == "") :
              $constRankingFavCrForStation = getParameterValue("0", "RANKING_FAVOURED_COURIER_FOR_STATION", "0");
           endif;
           $constRankingFavCrForPayer = getParameterValue("0", "RANKING_FAVOURED_COURIER_FOR_PAYER", $currentHqId);
           if ($constRankingFavCrForPayer == "") :
              $constRankingFavCrForPayer = getParameterValue("0", "RANKING_FAVOURED_COURIER_FOR_PAYER", "0");
           endif;
           
           // Consider restrictions by job filter regarding vehicle filter if activated
           $fromClauseFavCr = "";
           $whereClauseFavCr = "";
           if ($mandatoryCourierFilterClause != "") :
              $constRankingFavCrConsiderFilter = getParameterValue("0", "RANKING_FAVOURED_COURIER_FILTER", $currentHqId);
              if ($constRankingFavCrConsiderFilter == "") :
                 $constRankingFavCrConsiderFilter = getParameterValue("0", "RANKING_FAVOURED_COURIER_FILTER", "0");
              endif;
              if ($constRankingFavCrConsiderFilter == "1") :
                 $fromClauseFavCr = ", couriervehicle AS crvh";
                 $whereClauseFavCr = " AND cr.cr_sid = crvh.crvh_sid " . $mandatoryCourierFilterClause;
              endif;
           endif;
           // Consider restrictions by job measures regarding vehicle measures if activated
           $fromClauseFavCr2 = "";
           $whereClauseFavCr2 = "";
           if ($jb2crvhClause != "") :
              $constRankingFavCrConsiderCrvh = getParameterValue("0", "RANKING_FAVOURED_COURIER_CRVH", $currentHqId);
              if ($constRankingFavCrConsiderCrvh == "") :
                 $constRankingFavCrConsiderCrvh = getParameterValue("0", "RANKING_FAVOURED_COURIER_CRVH", "0");
              endif;
              if ($constRankingFavCrConsiderCrvh == "1") :
                 $fromClauseFavCr2 = ", couriervehicle AS crvh";
                 $whereClauseFavCr2 = " cr.cr_sid = crvh.crvh_sid AND " . $jb2crvhClause;
              endif;
           endif;
           if ($fromClauseFavCr == "") : $fromClauseFavCr = $fromClauseFavCr2; endif;

           
           // Ranking favoured courier for STATION
           if ($constRankingFavCrForStation == "1") :

              $tmpSqlquery = "SELECT DISTINCT cscr.cr_id"
                             . " FROM tour AS tr, costcenter AS csc, customercourier AS cscr, courier AS cr" . $fromClauseFavCr
                             . " WHERE tr.jb_id = '" . $jobId . "'     AND"
                             . "       tr.csc_id = csc.csc_id          AND"
                             . "       csc.cs_id = cscr.cs_id          AND"
                             . "       cscr.cr_id = cr.cr_id           AND"
                             . "       cr.cr_available = '1'           AND"
                             . "       cr.vht_id >= '" . $jbVhtId . "' AND"
                             .         $whereClauseFavCr2
                             . "       cscr.cscr_relation = '1'" . $whereClauseFavCr
                             . " ORDER BY cr.cr_availabletime";

              $result = $db2->query($tmpSqlquery);
              if (DB::isError($result)) die ("$PHP_SELF 5: {$tmpSqlquery} " . $result->getMessage());           
              while ($row = $result->fetch_assoc()):
                    // Check for filter only being in areas or concerning ALL favoured couriers
                    if (substr($mode,7,1) == "1") :
                       $crCurrentLocation = getLocationCourier($row["cr_id"], $zipcode, $currentHqId, "");
                       if ($crCurrentLocation != "0") :
                          $favouredCourierArray[] = $row["cr_id"];
                       endif;
                    else :
                       $favouredCourierArray[] = $row["cr_id"];
                    endif;
              endwhile;
              $result->free();
           endif;

           // Ranking favoured courier for PAYER
           if ($constRankingFavCrForPayer == "1") :

              // Check first job is a cashpayer one
              $cscIdPayer = getFieldValueFromId("job", "jb_id", $jobId, "csc_id_payer");
              
              $constCscIdPayerCash = getParameterValue("0", "CSC_ID_PAYER_CASH", $currentHqId);
              if (($cscIdPayer != "") && ($cscIdPayer == $constCscIdPayerCash || $cscIdPayer == "-1" )) :
                 // Job is cashpayer one => Get id of the cashpayer
                 $tmpSqlquery = "SELECT DISTINCT cscr.cr_id"
                                . " FROM job AS jb, costcenter AS csc, customercourier AS cscr, courier AS cr" . $fromClauseFavCr
                                . " WHERE jb.jb_id = '" . $jobId . "'         AND"
                                . "       jb.csc_id_payer_cash = csc.csc_id   AND"
                                . "       csc.cs_id = cscr.cs_id              AND"
                                . "       cscr.cr_id = cr.cr_id               AND"
                                . "       cr.cr_available = '1'               AND"
                                . "       cr.vht_id >= '" . $jbVhtId . "'     AND"
                                .         $whereClauseFavCr2
                                . "       cscr.cscr_relation = '1'" . $whereClauseFavCr
                                . " ORDER BY cr.cr_availabletime";
              else :
                 // Job is an invoice one
                 $tmpSqlquery = "SELECT DISTINCT cscr.cr_id"
                                . " FROM tourservice AS trs, costcenter AS csc, customercourier AS cscr, courier AS cr" . $fromClauseFavCr
                                . " WHERE trs.jb_id = '" . $jobId . "'    AND"
                                . "       trs.csc_id = csc.csc_id         AND"
                                . "       csc.cs_id = cscr.cs_id          AND"
                                . "       cscr.cr_id = cr.cr_id           AND"
                                . "       cr.cr_available = '1'           AND"
                                . "       cr.vht_id >= '" . $jbVhtId . "' AND"
                                .         $whereClauseFavCr2
                                . "       cscr.cscr_relation = '1'" . $whereClauseFavCr
                                . " ORDER BY cr.cr_availabletime";
              endif;
              $result = $db2->query($tmpSqlquery);
              if (DB::isError($result)) die ("$PHP_SELF 5: {$tmpSqlquery} " . $result->getMessage());           
              while ($row = $result->fetch_assoc()):
                    // Check for filter only being in areas or concerning ALL favoured couriers
                    if (substr($mode,7,1) == "1") :
                       $crCurrentLocation = getLocationCourier($row["cr_id"], $zipcode, $currentHqId, "");
                       if ($crCurrentLocation != "0") :
                          $favouredCourierArray[] = $row["cr_id"];
                       endif;
                    else :
                       $favouredCourierArray[] = $row["cr_id"];
                    endif;
              endwhile;
              $result->free();
           endif;
        endif;
        if (count($favouredCourierArray) > 0) : 
           $favouredCouriersClause = " cr.cr_id NOT IN (" . implode(",", $favouredCourierArray) . ") AND ";
        endif;
        $retArray[2] = $favouredCourierArray;
     endif;
  endif;


  $sqlquery = "";
  $fieldClause = "";
  $whereClause = "";
  $orderByClause = "";
  $limitClause = "";


  // Check for SERVICE_MODE to be the service by matrix of zipcodes or matrix of mediation areas
  if ($zipcode != "" && ($mediationMode == "1" || $mediationMode == "2" || $mediationMode == "3" || $mediationMode == "4")) :
     
     // *********************************
     // * Service by matrix of zipcodes *
     // *********************************
     if ($mediationMode == "1") :

        if (substr($mode,3,1) == "1") :

           $whereClause .= "cr.cr_locationzipcode = '" . $zipcode . "'    AND ";
           
           $sqlquery = "SELECT cr.cr_id, cr.cr_sid, cr.cr_eid, mt.mt_value, cr.cr_locationzipcode AS name, cr.cr_availabletime, cr.cr_filter, crvh.crvh_filter"
	                     . " FROM courier AS cr, couriervehicle AS crvh, metatype AS mt, company AS cmp"
                       . " WHERE " . $whereClause . $blockedCouriersClause
                       .         $whereClauseHqId
                       . "       cr.cr_sid != ''                               AND"
                       . "       cr.cr_available = '1'                         AND"
                       .         $occupiedCourierClause
                       . "       cr.cmp_id = cmp.cmp_id                        AND"
                       . "       cmp.cmp_authenticated = '1'                   AND"
                       . "       cr.vht_id >= '" . $jbVhtId . "'               AND"
                       . "       cr.cr_outlay >= '" . $jbOutlay . "'           AND"
                       .         $cr2crvhClause
                       .         $jb2crvhClause
                       . "       cr.cr_sid = crvh.crvh_sid                        "
                       .         $mandatoryCourierFilterClause . "             AND"
                       . "       crvh.vht_id = mt.mt_sort                      AND"
                       . "       mt.mt_type = 'vehicletype'                       "
                       . " ORDER BY cr.cr_availabletime";

           $result = $db2->query($sqlquery);
           if (DB::isError($result)) die ("$PHP_SELF 6: {$sqlquery} " . $result->getMessage());

           $crArray = array();
           // Table with header      
           while ($row = $result->fetch_assoc()):
	            $crArray[] = array($row["cr_id"], $row["cr_sid"], $row["cr_eid"], $row["mt_value"], $row["name"], $row["cr_availabletime"], $row["crvh_filter"], $row["cr_filter"]);
           endwhile;
           $result->free();
           $retArray[3] = $crArray;
        endif;
        
        // If requested get all neighbours of the current zipcode
        if (substr($mode,4,1) == "1" || substr($mode,5,1) == "1") :
           
           // Get ID of the zipcode
           $srvp_id = getFieldValueFromId("serviceplz", "srvp_plz", $zipcode, "srvp_id");
           
           // Get neighbours of the zipcode(-IDs)
           $tmpSqlquery = "SELECT srvp.srvp_plz"
                          . " FROM serviceplzneighbour AS srvpn, serviceplz AS srvp"
                          . " WHERE srvpn.srvp_id = '" . $srvp_id . "' AND"
                          . "       srvpn.srvp2_id = srvp.srvp_id      AND"
                          . "       srvpn.hq_id = '" . $currentHqId . "'"
                          . " ORDER BY srvpn.srvpn_sort";

           $result = $db2->query($tmpSqlquery);

           if (DB::isError($result)) die ("$PHP_SELF 7: {$tmpSqlquery} " . $result->getMessage());
           // Set new whereClause
           $tmpArray = array();
           $whereClause = "";
           while ($row = $result->fetch_assoc()):
	            $tmpArray[] = "cr.cr_locationzipcode = '" . $row["srvp_plz"] . "'";
	            $retArray[5][] = $row["srvp_plz"];
           endwhile;
           if (count($tmpArray) > 0) : 
              $whereClause = "(";
              $whereClause .= implode(" || ",$tmpArray);
              $whereClause .= ") AND";
           endif;                                 

           $crArray = array();
           if (substr($mode,4,1) == "1" && $whereClause != "") :

              $sqlquery = "SELECT cr.cr_id, cr.cr_sid, cr.cr_eid, mt.mt_value, cr.cr_locationzipcode AS name, cr.cr_availabletime, cr.cr_filter, crvh.crvh_filter"
	                        . " FROM courier AS cr, couriervehicle AS crvh, metatype AS mt, company AS cmp"
                          . " WHERE " . $whereClause . $blockedCouriersClause
                          .         $whereClauseHqId
                          . "       cr.cr_sid != ''                               AND"
                          . "       cr.cr_available = '1'                         AND"
                          .         $occupiedCourierClause
                          . "       cr.cmp_id = cmp.cmp_id                        AND"
                          . "       cmp.cmp_authenticated = '1'                   AND"
                          . "       cr.vht_id >= '" . $jbVhtId . "'               AND"
                          . "       cr.cr_outlay >= '" . $jbOutlay . "'           AND"
                          .         $cr2crvhClause
                          .         $jb2crvhClause
                          . "       cr.cr_sid = crvh.crvh_sid                        "
                          .         $mandatoryCourierFilterClause . "             AND"
                          . "       crvh.vht_id = mt.mt_sort                      AND"
                          . "       mt.mt_type = 'vehicletype'                       "
                          . " ORDER BY cr.cr_availabletime";

              $result = $db2->query($sqlquery);
              if (DB::isError($result)) die ("$PHP_SELF 8: {$sqlquery} " . $result->getMessage());

              // Table with header      
              while ($row = $result->fetch_assoc()):
	               $crArray[] = array($row["cr_id"], $row["cr_sid"], $row["cr_eid"], $row["mt_value"], $row["name"], $row["cr_availabletime"], $row["crvh_filter"], $row["cr_filter"]);
              endwhile;
              $result->free();              
           endif;
           $retArray[4] = $crArray;
        endif;
     endif;

     // ****************************************
     // * Service by matrix of mediation areas *
     // ****************************************
     if ($mediationMode == "2") :

        // Get ID of the zipcode
        $srvp_id = getFieldValueFromId("serviceplz", "srvp_plz", $zipcode, "srvp_id");

        // Get ID of the mediationarea according to the current zipcode
        // $srvpa_id = getFieldValueFromId("serviceplzareamapping", "srvp_id", $srvp_id, "srvpa_id");
/*
        $srvpa_id = $db2->getOne("SELECT srvpam.srvpa_id FROM serviceplzarea AS srvpa, serviceplzareamapping AS srvpam" .
                                "  WHERE srvpam.srvp_id = '" . $srvp_id . "' AND srvpa.srvpa_id = srvpam.srvpa_id AND srvpa.hq_id = '" . $currentHqId . "'");
*/
        $srvpa_id = getOneStmt("SELECT srvpam.srvpa_id FROM serviceplzarea AS srvpa, serviceplzareamapping AS srvpam" .
                               "  WHERE srvpam.srvp_id = '" . $srvp_id . "' AND srvpa.srvpa_id = srvpam.srvpa_id AND srvpa.hq_id = '" . $currentHqId . "'", "srvpa_id");

        if ($srvpa_id != "" && substr($mode,3,1) == "1") :
           $whereClause .= "srvpam.srvpa_id = '" . $srvpa_id . "' AND";
           
           $sqlquery = "SELECT cr.cr_id, cr.cr_sid, cr.cr_eid, mt.mt_value, srvpa.srvpa_name AS name, cr.cr_availabletime, cr.cr_filter, crvh.crvh_filter"
	                     . " FROM courier AS cr, couriervehicle AS crvh, metatype AS mt, company AS cmp,"
	                     . "      serviceplz AS srvp, serviceplzareamapping AS srvpam, serviceplzarea AS srvpa"
                       . " WHERE cr.cr_sid != ''                         AND"
                       .         $blockedCouriersClause
                       .         $whereClauseHqId
                       . "       cr.cr_available = '1'                   AND"
                       .         $occupiedCourierClause
                       .         $cr2crvhClause
                       . "       cr.cr_sid = crvh.crvh_sid                  "
                       .         $mandatoryCourierFilterClause . "       AND"
                       . "       crvh.vht_id = mt.mt_sort                AND"
                       . "       mt.mt_type = 'vehicletype'              AND"
                       . "       cr.cmp_id = cmp.cmp_id                  AND"
                       . "       cmp.cmp_authenticated = '1'             AND"
                       . "       cr.vht_id >= '" . $jbVhtId . "'         AND"
                       . "       cr.cr_outlay >= '" . $jbOutlay . "'     AND"
                       .         $jb2crvhClause
                       . "       cr.cr_locationzipcode = srvp.srvp_plz   AND"
                       . "       srvp.srvp_id = srvpam.srvp_id           AND"
                       . "   " . $whereClause
                       . "       srvpam.srvpa_id = srvpa.srvpa_id           "
                       . " ORDER BY cr.cr_availabletime";

           $result = $db2->query($sqlquery);
           if (DB::isError($result)) die ("$PHP_SELF 9: {$sqlquery} " . $result->getMessage());

           $crArray = array();
           // Table with header      
           while ($row = $result->fetch_assoc()):
	            $crArray[] = array($row["cr_id"], $row["cr_sid"], $row["cr_eid"], $row["mt_value"], $row["name"], $row["cr_availabletime"], $row["crvh_filter"], $row["cr_filter"]);
           endwhile;
           $result->free();
           $retArray[3] = $crArray;
        endif;
        
        // If requested get all neighbours of the current area
        if ($srvpa_id != "" && (substr($mode,4,1) == "1" || substr($mode,5,1) == "1")) :

           // Get neighbours of the area(-IDs)
           $tmpSqlquery = "SELECT srvpan.srvpa2_id"
                          . " FROM serviceplzareaneighbour AS srvpan"
                          . " WHERE srvpan.srvpa_id = '" . $srvpa_id . "'"
                          . " ORDER BY srvpan.srvpan_sort";

           $result = $db2->query($tmpSqlquery);
           if (DB::isError($result)) die ("$PHP_SELF 1: {$tmpSqlquery} " . $result->getMessage());
           // Set new whereClause
           $tmpArray = array();
           $whereClause = "";           
           while ($row = $result->fetch_assoc()):
	            $tmpArray[] = "srvpam.srvpa_id = '" . $row["srvpa2_id"] . "'";
	            $retArray[5][] = $row["srvpa2_id"];
           endwhile;
           if (count($tmpArray) > 0) :
              $whereClause = "(";
              $whereClause .= implode(" || ",$tmpArray);
              $whereClause .= ") AND";
           endif;           

           $crArray = array();           
           if (substr($mode,4,1) == "1" && $whereClause != "") :

              $sqlquery = "SELECT cr.cr_id, cr.cr_sid, cr.cr_eid, mt.mt_value, srvpa.srvpa_name AS name, cr.cr_availabletime, cr.cr_filter, crvh.crvh_filter"
	                        . " FROM courier AS cr, couriervehicle AS crvh, metatype AS mt, company AS cmp,"
	                        . "      serviceplz AS srvp, serviceplzareamapping AS srvpam, serviceplzarea AS srvpa"
                          . " WHERE cr.cr_sid != ''                         AND"
                          .         $blockedCouriersClause
                          .         $whereClauseHqId
                          . "       cr.cr_available = '1'                   AND"
                          .         $occupiedCourierClause
                          .         $cr2crvhClause
                          . "       cr.cr_sid = crvh.crvh_sid                  "
                          .         $mandatoryCourierFilterClause . "       AND"
                          . "       crvh.vht_id = mt.mt_sort                AND"
                          . "       mt.mt_type = 'vehicletype'              AND"
                          . "       cr.cmp_id = cmp.cmp_id                  AND"
                          . "       cmp.cmp_authenticated = '1'             AND"
                          . "       cr.vht_id >= '" . $jbVhtId . "'         AND"
                          . "       cr.cr_outlay >= '" . $jbOutlay . "'     AND"
                          .         $jb2crvhClause
                          . "       cr.cr_locationzipcode = srvp.srvp_plz   AND"
                          . "       srvp.srvp_id = srvpam.srvp_id           AND"
                          . "   " . $whereClause
                          . "       srvpam.srvpa_id = srvpa.srvpa_id           "
                          . " ORDER BY cr.cr_availabletime";

              $result = $db2->query($sqlquery);
              if (DB::isError($result)) die ("$PHP_SELF 2: {$sqlquery} " . $result->getMessage());

              // Table with header      
              while ($row = $result->fetch_assoc()):
	               $crArray[] = array($row["cr_id"], $row["cr_sid"], $row["cr_eid"], $row["mt_value"], $row["name"], $row["cr_availabletime"], $row["crvh_filter"], $row["cr_filter"]);
              endwhile;
              $result->free();
           endif;
           $retArray[4] = $crArray;
        endif;
     endif;

     // ***************************************************************************************************************
     // * Combined mode: Service by matrix of mediation areas, where each zipcode as member has an own neighbour area *
     // ***************************************************************************************************************
     if ($mediationMode == "3") :

        // Get ID of the zipcode
        $srvp_id = getFieldValueFromId("serviceplz", "srvp_plz", $zipcode, "srvp_id");

        // Get ID of the mediation area according to the current zipcode
        // $srvpa_id = getFieldValueFromId("serviceplzareamapping", "srvp_id", $srvp_id, "srvpa_id");
/*        
        $srvpa_id = $db2->getOne("SELECT srvpam.srvpa_id FROM serviceplzarea AS srvpa, serviceplzareamapping AS srvpam" .
                                 " WHERE srvpam.srvp_id = '" . $srvp_id . "' AND srvpa.srvpa_id = srvpam.srvpa_id AND srvpa.hq_id = '" . $currentHqId . "'");
*/
        $srvpa_id = getOneStmt("SELECT srvpam.srvpa_id FROM serviceplzarea AS srvpa, serviceplzareamapping AS srvpam" .
                               " WHERE srvpam.srvp_id = '" . $srvp_id . "' AND srvpa.srvpa_id = srvpam.srvpa_id AND srvpa.hq_id = '" . $currentHqId . "'", "srvpa_id");

        if ($srvpa_id != "" && substr($mode,3,1) == "1") :
           $whereClause .= "srvpam.srvpa_id = '" . $srvpa_id . "' AND";
           
           $sqlquery = "SELECT cr.cr_id, cr.cr_sid, cr.cr_eid, mt.mt_value, srvpa.srvpa_name AS name, cr.cr_availabletime, cr.cr_filter, crvh.crvh_filter"
	                     . " FROM courier AS cr, couriervehicle AS crvh, metatype AS mt, company AS cmp,"
	                     . "      serviceplz AS srvp, serviceplzareamapping AS srvpam, serviceplzarea AS srvpa"
                       . " WHERE cr.cr_sid != ''                         AND"
                       .         $blockedCouriersClause
                       .         $whereClauseHqId
                       . "       cr.cr_available = '1'                   AND"
                       .         $occupiedCourierClause
                       .         $cr2crvhClause
                       . "       cr.cr_sid = crvh.crvh_sid                  "
                       .         $mandatoryCourierFilterClause . "       AND"
                       . "       crvh.vht_id = mt.mt_sort                AND"
                       . "       mt.mt_type = 'vehicletype'              AND"
                       . "       cr.cmp_id = cmp.cmp_id                  AND"
                       . "       cmp.cmp_authenticated = '1'             AND"
                       . "       cr.vht_id >= '" . $jbVhtId . "'         AND"
                       . "       cr.cr_outlay >= '" . $jbOutlay . "'     AND"
                       .         $jb2crvhClause
                       . "       cr.cr_locationzipcode = srvp.srvp_plz   AND"
                       . "       srvp.srvp_id = srvpam.srvp_id           AND"
                       . "   " . $whereClause
                       . "       srvpam.srvpa_id = srvpa.srvpa_id           "
                       . " ORDER BY cr.cr_availabletime";

           $result = $db2->query($sqlquery);
           if (DB::isError($result)) die ("$PHP_SELF 9: {$sqlquery} " . $result->getMessage());

           $crArray = array();
           // Table with header      
           while ($row = $result->fetch_assoc()):
	            $crArray[] = array($row["cr_id"], $row["cr_sid"], $row["cr_eid"], $row["mt_value"], $row["name"], $row["cr_availabletime"], $row["crvh_filter"], $row["cr_filter"]);
           endwhile;
           $result->free();           
           $retArray[3] = $crArray;
        endif;
        
        // If requested get all neighbour areas of the current zipcode
        if ($srvpa_id != "" && (substr($mode,4,1) == "1" || substr($mode,5,1) == "1")) :

           // Get specified(!) neighbour area of the current zipcode
           $whereClause = "";
           if ($neighbourLevel != "") :
              $whereClause = " AND srvpna.srvpna_sort = '" . $neighbourLevel . "'";
           endif;
           $tmpSqlquery = "SELECT srvpna.srvpa_id"
                          . " FROM serviceplzneighbourarea AS srvpna"
                          . " WHERE srvpna.srvp_id = '" . $srvp_id . "' AND"
                          . "       srvpna.hq_id = '" . $currentHqId . "'"
                          .         $whereClause
                          . " ORDER BY srvpna.srvpna_sort";

           $result = $db2->query($tmpSqlquery);
           if (DB::isError($result)) die ("$PHP_SELF 1: {$tmpSqlquery} " . $result->getMessage());
           // Set new whereClause
           $tmpArray = array();
           $whereClause = "";
           while ($row = $result->fetch_assoc()):
	           $tmpArray[] = "srvpam.srvpa_id = '" . $row["srvpa_id"] . "'";
	           $retArray[5][] = $row["srvpa_id"];
           endwhile;
           if (count($tmpArray) > 0) :
              $whereClause = "(";
              $whereClause .= implode(" || ",$tmpArray);
              $whereClause .= ") AND";
           endif;           

           $crArray = array();
           // Check mode AND $neighbourLevel
           // If $neighbourLevel is empty, ALL neighbours will be involved => OK
           // But if $neighbourLevel is set, the existence of at least one area of the specified zipcode is a must
           if (substr($mode,4,1) == "1" && ($neighbourLevel = "" || ($neighbourLevel != "" && count($tmpArray) > 0)) && $whereClause != "") :

              $sqlquery = "SELECT cr.cr_id, cr.cr_sid, cr.cr_eid, mt.mt_value, srvpa.srvpa_name AS name, cr.cr_availabletime, cr.cr_filter, crvh.crvh_filter"
	                        . " FROM courier AS cr, couriervehicle AS crvh, metatype AS mt, company AS cmp,"
	                        . "      serviceplz AS srvp, serviceplzareamapping AS srvpam, serviceplzarea AS srvpa"
                          . " WHERE cr.cr_sid != ''                         AND"
                          .         $blockedCouriersClause
                          .         $whereClauseHqId
                          . "       cr.cr_available = '1'                   AND"
                          .         $occupiedCourierClause
                          .         $cr2crvhClause
                          . "       cr.cr_sid = crvh.crvh_sid                  "
                          .         $mandatoryCourierFilterClause . "       AND"
                          . "       crvh.vht_id = mt.mt_sort                AND"
                          . "       mt.mt_type = 'vehicletype'              AND"
                          . "       cr.cmp_id = cmp.cmp_id                  AND"
                          . "       cmp.cmp_authenticated = '1'             AND"
                          . "       cr.vht_id >= '" . $jbVhtId . "'         AND"
                          . "       cr.cr_outlay >= '" . $jbOutlay . "'     AND"
                          .         $jb2crvhClause
                          . "       cr.cr_locationzipcode = srvp.srvp_plz   AND"
                          . "       srvp.srvp_id = srvpam.srvp_id           AND"
                          . "   " . $whereClause
                          . "       srvpam.srvpa_id = srvpa.srvpa_id           "
                          . " ORDER BY cr.cr_availabletime";

              $result = $db2->query($sqlquery);
              if (DB::isError($result)) die ("$PHP_SELF 2: {$sqlquery} " . $result->getMessage());
              
              // Table with header      
              while ($row = $result->fetch_assoc()):
	               $crArray[] = array($row["cr_id"], $row["cr_sid"], $row["cr_eid"], $row["mt_value"], $row["name"], $row["cr_availabletime"], $row["crvh_filter"], $row["cr_filter"]);
              endwhile;
              $result->free();
           endif;
           $retArray[4] = $crArray;
        endif;
     endif;

     // *********************************
     // * Service by longhaul mediation *
     // *********************************
     if ($mediationMode == "4") :

        // Explode special string with coordinates in "$zipcode" for longhaul jobs
        // [Components: 0 = Latitude start/target zipcode, 1 = Longitude start/target zipcode, 2 = Latitude desired/home zipcode, 3 = Longitude desired/home zipcode]
        $jbCoordArr = explode(",", $zipcode);

        if (substr($mode,3,1) == "1") :

           if ($radiusKm == 0) :
              $parRankingRadiusKm = getParameterValue("0", "RANKING_RADIUS_KM", $currentHqId);
              if ($parRankingRadiusKm == "") : $parRankingRadiusKm = getParameterValue("0", "RANKING_RADIUS_KM", "0"); endif;
              if ($parRankingRadiusKm == "" || !is_numeric($parRankingRadiusKm)) :
                 $parRankingRadiusKm = "50";
              endif;
              $radiusKm = $parRankingRadiusKm;
           endif;

           $coordClause = "SQRT(POW(ABS(cr.cr_gps_lat - " . $jbCoordArr[0] . "),2) + POW(ABS(cr.cr_gps_long - " . $jbCoordArr[1] . "),2))";
           if (mcArrIsSet($jbCoordArr, 2) != "" && mcArrIsSet($jbCoordArr, 3) != "") :
              // Acting as if the driver is at his desired zipcode
//              $coordClause = "SQRT(POW(ABS(" . $jbCoordArr[2] . " - " . $jbCoordArr[0] . "),2) + POW(ABS(" . $jbCoordArr[3] . " - " . $jbCoordArr[1] . "),2))";
              $coordClause = "SQRT(POW(ABS(cr.cr_gps_lat_home - " . $jbCoordArr[2] . "),2) + POW(ABS(cr.cr_gps_long_home - " . $jbCoordArr[3] . "),2))";
           endif;
           $kmClause = "(" . $coordClause . " * 111)";
           $fieldClause .= ", " . $kmClause . " AS nb";
           $whereClause .= $kmClause . " < " . $radiusKm . " AND ";
           // $orderByClause = "ORDER BY cr.cr_availabletime";
           $orderByClause = "";
           // $limitClause = "LIMIT 0,100";
           $limitClause = "";

           $sqlquery = "SELECT cr.cr_id, cr.cr_sid, cr.cr_eid, mt.mt_value, cr.cr_locationzipcode AS name, cr.cr_availabletime, cr.cr_filter, crvh.crvh_filter" . $fieldClause
	                     . " FROM courier AS cr, couriervehicle AS crvh, metatype AS mt, company AS cmp"
                       . " WHERE " . $whereClause . $blockedCouriersClause
                       . "       cr.cr_sid != ''                               AND"
                       . "       cr.cr_available = '1'                         AND"
                       .         $occupiedCourierClause
                       . "       cr.cmp_id = cmp.cmp_id                        AND"
                       . "       cmp.cmp_authenticated = '1'                   AND"
                       . "       cmp.cmp_no_longhaul = '0'                     AND"
                       . "       cr.vht_id >= '" . $jbVhtId . "'               AND"
                       . "       cr.cr_outlay >= '" . $jbOutlay . "'           AND"
                       .         $cr2crvhClause
                       .         $jb2crvhClause
                       . "       cr.cr_sid = crvh.crvh_sid                        "
                       .         $mandatoryCourierFilterClause . "             AND"
                       . "       crvh.vht_id = mt.mt_sort                      AND"
                       . "       mt.mt_type = 'vehicletype'                       "
                       . " " . $orderByClause . " " . $limitClause;
           $result = $db2->query($sqlquery);
           if (DB::isError($result)) die ("$PHP_SELF : {$sqlquery} " . $result->getMessage());
//echo($sqlquery);   
//if (mcArrIsSet($jbCoordArr, 2) != "" && mcArrIsSet($jbCoordArr, 3) != "") :
//  die();
//endif;
           $crArray = array();
           // Table with header      
           while ($row = $result->fetch_assoc()):
	            $crArray[] = array($row["cr_id"], $row["cr_sid"], $row["cr_eid"], $row["mt_value"], $row["name"], $row["cr_availabletime"], $row["crvh_filter"], $row["cr_filter"], $row["nb"]);
           endwhile;
           $result->free();
           $retArray[3] = $crArray;
        endif;
        
        // If requested get all neighbours of the current zipcode
        /*
        if (substr($mode,4,1) == "1" || substr($mode,5,1) == "1") :
           
           // Get ID of the zipcode
           $srvp_id = getFieldValueFromId("serviceplz", "srvp_plz", $zipcode, "srvp_id");
           
           // Get neighbours of the zipcode(-IDs)
           $tmpSqlquery = "SELECT srvp.srvp_plz"
                          . " FROM serviceplzneighbour AS srvpn, serviceplz AS srvp"
                          . " WHERE srvpn.srvp_id = '" . $srvp_id . "' AND"
                          . "       srvpn.srvp2_id = srvp.srvp_id      AND"
                          . "       srvpn.hq_id = '" . $currentHqId . "'"
                          . " ORDER BY srvpn.srvpn_sort";
     
           $result = $db2->query($tmpSqlquery);
     
           if (DB::isError($result)) die ("$PHP_SELF 7: {$tmpSqlquery} " . $result->getMessage());
           // Set new whereClause
           $tmpArray = array();
           $whereClause = "";
           while ($row = $result->fetch_assoc()):
	            $tmpArray[] = "cr.cr_locationzipcode = '" . $row["srvp_plz"] . "'";
	            $retArray[5][] = $row["srvp_plz"];
           endwhile;
           if (count($tmpArray) > 0) : 
              $whereClause = "(";
              $whereClause .= implode(" || ",$tmpArray);
              $whereClause .= ") AND";
           endif;                                 
     
           $crArray = array();
           if (substr($mode,4,1) == "1" && $whereClause != "") :
     
              $sqlquery = "SELECT cr.cr_id, cr.cr_sid, cr.cr_eid, mt.mt_value, cr.cr_locationzipcode AS name, cr.cr_availabletime, cr.cr_filter, crvh.crvh_filter"
	                        . " FROM courier AS cr, couriervehicle AS crvh, metatype AS mt, company AS cmp"
                          . " WHERE " . $whereClause . $blockedCouriersClause
                          .         $whereClauseHqId
                          . "       cr.cr_sid != ''                               AND"
                          . "       cr.cr_available = '1'                         AND"
                          .         $occupiedCourierClause
                          . "       cr.cmp_id = cmp.cmp_id                        AND"
                          . "       cmp.cmp_authenticated = '1'                   AND"
                          . "       cr.vht_id >= '" . $jbVhtId . "'               AND"
                          . "       cr.cr_outlay >= '" . $jbOutlay . "'           AND"
                          .         $cr2crvhClause
                          .         $jb2crvhClause
                          . "       cr.cr_sid = crvh.crvh_sid                        "
                          .         $mandatoryCourierFilterClause . "             AND"
                          . "       crvh.vht_id = mt.mt_sort                      AND"
                          . "       mt.mt_type = 'vehicletype'                       "
                          . " ORDER BY cr.cr_availabletime";
     
              $result = $db2->query($sqlquery);
              if (DB::isError($result)) die ("$PHP_SELF 8: {$sqlquery} " . $result->getMessage());
     
              // Table with header      
              while ($row = $result->fetch_assoc()):
	               $crArray[] = array($row["cr_id"], $row["cr_sid"], $row["cr_eid"], $row["mt_value"], $row["name"], $row["cr_availabletime"], $row["crvh_filter"], $row["cr_filter"]);
              endwhile;
              $result->free();              
           endif;
           $retArray[4] = $crArray;
        endif;
        */
     endif;

  endif;
  

  // ********************************************
  // * Get ALL couriers with or without blocked *
  // ********************************************
  if (substr($mode,0,1) == "1" || substr($mode,8,1) == "1") :
     
     $whereClauseHqId = " cr.hq_id = '" . $currentHqId . "' AND ";  // RESTRICTION because of ALL couriers
     if (substr($mode,8,1) == "1") :
        if ($f_hq_id == "" || count($f_hq_id) == 0) : $f_hq_id = array($hq_id); endif;
        $whereClauseHqId = " cr.hq_id IN " . getSQLMandatorArray($f_hq_id) . " AND ";                
     endif;
     
     // For the rest of the couriers (and vehicles) use switch to pay attention for vehicle restrictions
     $whereClauseCrvhRestriction = "";
     if ($jobId != "") :
        $parRankingUseCrvhRestriction = getParameterValue("0", "RANKING_USE_CRVH_RESTRICTION", $currentHqId);
        if ($parRankingUseCrvhRestriction == "1") :
           $whereClauseCrvhRestriction = $jb2crvhClause . " cr.vht_id >= '" . $jbVhtId . "' AND cr.cr_outlay >= '" . $jbOutlay . "' AND ";
        endif;
     endif;
     
     $sqlquery = "SELECT cr.cr_id, cr.cr_sid, cr.cr_eid, mt.mt_value, cr.cr_locationzipcode AS name, cr.cr_availabletime, cr.cr_occupied, cr.cr_filter, crvh.crvh_filter"
               . " FROM courier AS cr, couriervehicle AS crvh, metatype AS mt, company AS cmp"
               . " WHERE " . $blockedCouriersClause
               .         $whereClauseHqId
               . "       cr.cr_sid != ''                               AND"
               . "       cr.cr_available = '1'                         AND"
               . "       cr.cmp_id = cmp.cmp_id                        AND"
               . "       cmp.cmp_authenticated = '1'                   AND"
               .         $whereClauseCrvhRestriction
               .         $cr2crvhClause
               . "       cr.cr_sid = crvh.crvh_sid                        "
               .         $mandatoryCourierFilterClause . "             AND"
               . "       crvh.vht_id = mt.mt_sort                      AND"
               . "       mt.mt_type = 'vehicletype'                       "
               . " ORDER BY cr.cr_availabletime";

     $result = $db2->query($sqlquery);
     if (DB::isError($result)) die ("$PHP_SELF 3: {$sqlquery} " . $result->getMessage());

     // Table with header
     $crArray = array();
     while ($row = $result->fetch_assoc()):
	      $crArray[] = array($row["cr_id"], $row["cr_sid"], $row["cr_eid"], $row["mt_value"], $row["name"], $row["cr_availabletime"], $row["crvh_filter"], $row["cr_occupied"], $row["cr_filter"]);
     endwhile;
     $result->free();
     $retArray[0] = $crArray;
  endif;

  return $retArray;
}

// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// BEISPIEL UND BESCHREIBUNG
// 1. Komponente: Je nach Modus ex. Array (z.B. "101011" <=> $retArray[0], $retArray[2], $retArray[4], $retArray[5] existieren)
// 2. Komponente: Datensatz innerhalb
// 3. Komponente: Feld des Datensatzes (0=cr_id, 1=cr_sid, 2=cr_eid, 3=mt_value, 4=name, 5=cr_availabletime)
// Folgend Ausgabe nur der cr_id´s
/*
if ($argv[1] == "XXXX") :
   echo "\n[----]\n";
   $xxxx = getCourierByRanking("50.790913,9.593785","000100","21097271","3");
   print_r($xxxx[3]);
   echo "\n[----]\n";
endif;
*/
/*
$xxx = getCourierByRanking("28195","","5714");
echo "PLZ: 28195 <br><br>";
echo "0: " . $xxx[0][0][0] . " " . $xxx[0][1][0] . " " . $xxx[0][2][0] . " " . $xxx[0][3][0] . " " . $xxx[0][4][0] . " " . $xxx[0][5][0] . " " . $xxx[0][6][0] . " " . $xxx[0][7][0] . " " . $xxx[0][8][0] . " " . $xxx[0][9][0] . " " . $xxx[0][10][0] . "<br><br>";
echo "1: " . $xxx[1][0] . " " . $xxx[1][1] . " " . $xxx[1][2] . " " . $xxx[1][3] . " " . $xxx[1][4] . "<br><br>";
echo "2: " . $xxx[2][0] . " " . $xxx[2][1] . " " . $xxx[2][2] . " " . $xxx[2][3] . " " . $xxx[2][4] . "<br><br>";
echo "3: " . $xxx[3][0][0] . " " . $xxx[3][1][0] . " " . $xxx[3][2][0] . " " . $xxx[3][3][0] . " " . $xxx[3][4][0] . "<br><br>";
echo "4: " . $xxx[4][0][0] . " " . $xxx[4][1][0] . " " . $xxx[4][2][0] . " " . $xxx[4][3][0] . " " . $xxx[4][4][0] . "<br><br>";
echo "5: " . $xxx[5][0] . " " . $xxx[5][1] . " " . $xxx[5][2] . " " . $xxx[5][3] . " " . $xxx[5][4] . " " . $xxx[5][5] . " " . $xxx[5][6] . " " . $xxx[5][7] . " " . $xxx[5][8] . " " . $xxx[5][9] . " " . $xxx[5][10] . " " . $xxx[5][11] . " " . $xxx[5][12] . " " . $xxx[5][13] . " " . $xxx[5][14] . "<br><br>";
echo "6: " . $xxx[6][0] . " " . $xxx[6][1] . " " . $xxx[6][2] . " " . $xxx[6][3] . " " . $xxx[6][4] . "<br><br>";
echo "7: " . $xxx[7][0][0] . " " . $xxx[7][1][0] . " " . $xxx[7][2][0] . " " . $xxx[7][3][0] . " " . $xxx[7][4][0] . "<br><br>";
echo "8: " . $xxx[8][0][0] . " " . $xxx[8][1][0] . " " . $xxx[8][2][0] . " " . $xxx[8][3][0] . " " . $xxx[8][4][0] . "<br><br>";
*/
// 28207 28195
// echo $sqlquery . "<br><br>";



// Checks the couriers position 
// Returns: 0 = OUTSIDE OF ANY AREA
//          1 = MAIN ZIPCODE
//          2 = MAIN AREA AND NEIGHBOUR AREAS
function getLocationCourier($cr_id, $zipcode, $currentHqId = "", $crLocationZipcodeInit = "") {
   global $db, $PHP_SELF, $hq_id;

   if ($currentHqId == "") : $currentHqId = $hq_id; endif;

   $crLocation = "0";   // OUTSIDE OF ANY AREA

   // Get current zipcode of the courier out of the table "courier" (cr_locationzipcode) to compare with locating zipcode
   if ($crLocationZipcodeInit == "") :
      $crLocationZipcode = getFieldValueFromId("courier","cr_id",$cr_id,"cr_locationzipcode");
   else :
      $crLocationZipcode = $crLocationZipcodeInit;
   endif;

   // Check existence of the zipcode and check if it is real
   /*
   $zipcodeOK = false;
   if ($zipcode != "") :
      $srvpIdZipcode = getFieldValueFromId("serviceplz","srvp_plz",$zipcode,"srvp_id");
      if ($srvpIdZipcode != "") :
         $srvpIsRealZipcode = getFieldValueFromId("serviceplz","srvp_id",$srvpIdZipcode,"srvp_isreal");   
         if ($srvpIsRealZipcode == "1") :
            $zipcodeOK = true;
         endif;
      endif;
   endif;
   */

   if ($zipcode != "" && $crLocationZipcode != "") :

      // Check current zipcode with locating zipcode
      if ($zipcode == $crLocationZipcode) :

         $crLocation = "1";   // MAIN AREA
      else :
         // Check locating zipcode is in neighbourhood
         // If true then ok => do not update ranking time

         // Get the general mediation mode for the headquarter
         $mediationMode = getParameterValue("0", "MODE_INTERMEDIATION", $currentHqId);
         if ($mediationMode == "") :
            $mediationMode = getFieldValueFromId("headquarters", "hq_id", "$currentHqId", "hq_invmode");
         endif;

         // Get all neighbours for the current zipcode(area)
         if ($mediationMode == "1") :
            $zipcodeArray = getCourierByRanking($crLocationZipcode, "0000010000", "", "", $currentHqId);
            $zipcodeArray = $zipcodeArray[5];
         else :
            $areaIdArray = getCourierByRanking($crLocationZipcode, "0000010000", "", "", $currentHqId);
            $areaIdArray = $areaIdArray[5];
            
            // Add ID of the main mediation area
            $srvpIdZipcode = getFieldValueFromId("serviceplz","srvp_plz",$crLocationZipcode,"srvp_id");
            // $srvpaIdMain = getFieldValueFromId("serviceplzareamapping","srvp_id",$srvpIdZipcode,"srvpa_id");
/*
            $srvpaIdMain = $db->getOne("SELECT srvpam.srvpa_id FROM serviceplzarea AS srvpa, serviceplzareamapping AS srvpam" .
                                    "  WHERE srvpam.srvp_id = '" . $srvpIdZipcode . "' AND srvpa.srvpa_id = srvpam.srvpa_id AND srvpa.hq_id = '" . $currentHqId . "'");
*/
            $srvpaIdMain = getOneStmt("SELECT srvpam.srvpa_id FROM serviceplzarea AS srvpa, serviceplzareamapping AS srvpam" .
                                      "  WHERE srvpam.srvp_id = '" . $srvpIdZipcode . "' AND srvpa.srvpa_id = srvpam.srvpa_id AND srvpa.hq_id = '" . $currentHqId . "'", "srvpa_id");

            if ($areaIdArray == "") : $areaIdArray = array(); endif;
            array_push($areaIdArray, $srvpaIdMain);            
            
            $areaIdArrayLen = count($areaIdArray);

            $zipcodeArray = array();
            for ($i = 0; $i < $areaIdArrayLen; $i++) :

                $sqlquery = "SELECT srvp.srvp_plz"
                            . " FROM serviceplzareamapping AS srvpam, serviceplz AS srvp"
                            . " WHERE srvpam.srvp_id = srvp.srvp_id AND srvpam.srvpa_id = '" . $areaIdArray[$i] . "'";
                
                $result = $db->query($sqlquery);
                if (DB::isError($result)) die ("$PHP_SELF: " . $result->getMessage());
                
                while ($row = $result->fetch_assoc()):
                      $zipcodeArray[] = $row["srvp_plz"];
                endwhile;
                $result->free();
            endfor;
         endif;

         $zipcodeArrayLen = count($zipcodeArray);
         for ($i = 0; $i < $zipcodeArrayLen; $i++) :
             if ($zipcode == $zipcodeArray[$i]) :
                $crLocation = "2";   // NEIGHBOUR AREA
             endif;
         endfor;
      endif;
   endif;

   return $crLocation;
};


// Checks the couriers position regarding ranking
// If courier is in area or in neighbour area the ranking will be lost
// If courier is NOT in these areas, the ranking NOT will be lost
function looseRanking($cr_id, $zipcode, $currentHqId = "") {
   global $db, $PHP_SELF, $hq_id;

   if ($currentHqId == "") : $currentHqId = $hq_id; endif;

   $looseRankingPosition = "0";   // Loose ranking NO
   
   $crLocation = getLocationCourier($cr_id, $zipcode, $currentHqId, "");
   
   // Check for courier being in area or neighbour area
   if ($crLocation == "1" || $crLocation == "2") :
      $looseRankingPosition = "1";   // Loose ranking YES
   endif;

   return $looseRankingPosition;
};


// Checks the current status of the courier regarding to the last (successful) locating
function checkLocatingState ($cr_id) {
	global $db, $PHP_SELF;
	$initNewLocating = "1";
	$retArray = array($initNewLocating, "", "", "", "");
	if ($cr_id != "" && $cr_id != "0" && is_numeric($cr_id)) :
     $currentTime = getDateTime("0");

     $sqlquery = "SELECT cr.cr_gps_time, cr.cr_gps_type, cr.cr_gps_long, cr.cr_gps_lat, cr.cr_gps_acc,"
                  . "    (UNIX_TIMESTAMP('" . $currentTime . "')-UNIX_TIMESTAMP(cr.cr_gps_time)) AS intervalinseconds"
                  . " FROM phoenix.courier AS cr"
                  . " WHERE cr.cr_id = '" . $cr_id . "'";
     $result = $db->query($sqlquery);
     if (DB::isError($result)) die ("$PHP_SELF: " . $result->getMessage());
     while ($row = $result->fetch_assoc()):
           // Check for current GPS type (last locating by LBS = 1, GPS = 2, Network = 3, ...)
           // If type == 1 (LBS) or undefined (== 0) then execute a new locating indepentent from the time else look for GPS timestamp
           if (substr($row["cr_gps_long"],0,3) < "100" && substr($row["cr_gps_lat"],0,3) < "100") :   // Coordinates have to ok
//              if ($row["cr_gps_type"] != "" && $row["cr_gps_type"] >= "2") :
              // 05.04.2024 CA: cr_gps_type istderzeit auschließlich "0" und muss daher für die Kartendarstellung als "ok" betrachtet werden
              if (($row["cr_gps_type"] != "" && $row["cr_gps_type"] >= "2") || $row["cr_gps_type"] == "0") :
                 $initNewLocating = "0";
                 $parSeconds = getParameterValue("0", "LOCATING_SECONDS_NEEDED_FOR_LBS_LOCATING", "0");
                 if ($parSeconds == "") : $parSeconds = 900; endif;   // Default 15 minutes
                 if ($row["intervalinseconds"] > $parSeconds) :
                    $initNewLocating = "1";
                 endif;
              endif;
           else :
              $initNewLocating = "1";
           endif;
           $retArray = array($initNewLocating, $row["cr_gps_long"], $row["cr_gps_lat"], $row["cr_gps_type"], $row["cr_gps_time"], $row["cr_gps_acc"]);
     endwhile;
     $result->free();
	endif;
	return $retArray;
}


// Checks the current ranking position (zipcode) against the geo coordinates
function checkRanking ($cr_id, $longitude, $latitude, $gps_type, $gps_time, $gps_acc, $jobId, $currentHqId = "", $courierSid = "", $jobStartZipcode, $doLogAndUpdate = true) {
	global $db, $PHP_SELF, $hq_id;
	$retVal = "0";

	if ($currentHqId == "") : $currentHqId = $hq_id; endif;
  $constLocatingMode = getParameterValue("0", "LOCATING_MODE", $currentHqId);
  if ($constLocatingMode == "") : $constLocatingMode = "0"; endif;

  if ($constLocatingMode == "0") :
     $zipcode = findZipcodeArea($longitude, $latitude);
     if (trim($zipcode) == "") : $constLocatingMode = "1"; endif;
  endif;

  if ($constLocatingMode == "1") :
     // Get nearest coordinates
     $sqlquery = "SELECT srvp.srvp_id, srvp.srvp_plz, srvp.srvp_latitude, srvp.srvp_longitude, "
                 .      "SQRT(POW(ABS(srvp.srvp_latitude - $latitude),2) + POW(ABS(srvp.srvp_longitude - $longitude),2)) AS nb"
                 . " FROM serviceplz AS srvp"
                 . " ORDER BY nb"
                 . " LIMIT 0,1";
  
     $result = $db->query($sqlquery);
     if (DB::isError($result)) die ("$PHP_SELF: " . $result->getMessage());
     // all defined db-fields an titles shall become content of the following arrays
     while ($row = $result->fetch_assoc()):   
        $zipcode = $row["srvp_plz"];         // Zipcode to be displayed
     endwhile;
     $result->free();
  endif;

  // Per default the zipcode from coordinates (real zipcode) will be checked with the job start zipcode
  $comparisonZipcode = $jobStartZipcode;
  $logZipcodeText = "ZIP_JOB";
  $constModeLocationCheckOfZipcodes = getParameterValue("0", "LOCATING_ZIPCODE_COMPARISON_MODE", $currentHqId);
  if ($constModeLocationCheckOfZipcodes == "") : $constModeLocationCheckOfZipcodes = getParameterValue("0", "LOCATING_ZIPCODE_COMPARISON_MODE", "0"); endif;

  // Get zipcode of courier data if requested or job start zipcode is empty
  if ($constModeLocationCheckOfZipcodes == "1" || $comparisonZipcode == "") :
     $comparisonZipcode = getFieldValueFromId("courier","cr_id",$cr_id,"cr_locationzipcode");
     $logZipcodeText = "ZIP_FREE";
  endif;

  // Comparison call with zipcode from the GPS coordinates(!) and with the job start zipcode OR locating zipcode
  $crCurrentLocation = getLocationCourier($cr_id, $zipcode, $currentHqId, $comparisonZipcode);  
  if ($crCurrentLocation == "0") :
     if ($doLogAndUpdate):
        // Courier is outside
        $currentTime = getDateTime("0");
        if ($courierSid == "") : $courierSid = getFieldValueFromId("courier","cr_id",$cr_id,"cr_sid"); endif;

        if (locatingIsPlausible($cr_id, $longitude, $latitude, $gps_type, $gps_time, $gps_acc)):
          updateStmt("courier", "cr_id", $cr_id, array("cr_locationzipcode", $zipcode, "cr_availabletime", $currentTime));

          // Write logdata into log database
          writeToLogDB("28",$currentHqId,$jobId,"",$cr_id,$courierSid,"","LONG=".$longitude."|LAT=".$latitude."|ZIP_REAL=".$zipcode."|".$logZipcodeText."=".$comparisonZipcode."|LRANK=YES|LMODE=".$constLocatingMode."|AREA_STATE=".$crCurrentLocation);
        endif;
     endif;
     $retVal = "1";
  else :
     if ($doLogAndUpdate):
       // Write logdata into log database
       writeToLogDB("28",$currentHqId,$jobId,"",$cr_id,$courierSid,"","LONG=".$longitude."|LAT=".$latitude."|ZIP_REAL=".$zipcode."|".$logZipcodeText."=".$comparisonZipcode."|LRANK=NO|LMODE=".$constLocatingMode."|AREA_STATE=".$crCurrentLocation);
     endif;
  endif;
  return $retVal;
}

function locatingIsPlausible($cr_id, $longitude, $latitude, $loc_type, $loc_time, $loc_acc/*, $fileHandle*/) {
  global $db, $PHP_SELF;

  $fileHandle = @fopen("../log/implausible_locatings_" . date("Ym") . ".log", 'a');
  
//@fwrite($fileHandle, "$cr_id, $longitude, $latitude, $loc_type, $loc_time, $loc_acc\n");

  
  // Get accuracy and other parameters of the locating specified in $longitude, $latitude
  //   Unfortunately the entries in 'courier' do no necessarily have corresponding ones in 'locating', so we have to take the entry in 'courier';
  //   the disadvantage here ist the problem, that we do not have the accuracy of the locating, which can be large when of type 3 (network);
  //   currently, we have to live with this problem
//  $usr_id = $db->getOne("SELECT usr_id FROM courier WHERE cr_id = '" . $cr_id . "'");
//  $cr_gps_time = $db->getOne("SELECT cr_gps_time FROM courier WHERE cr_id = '" . $cr_id . "'");
//  $sqlquery = "SELECT loc_type, loc_acc, loc_time, loc_created FROM phoenix_log.locating WHERE usr_id = " . $usr_id . " AND ROUND(loc_long, 6) = ROUND(" . $longitude . ", 6) AND ROUND(loc_lat, 6) = ROUND(" . $latitude . ", 6) ORDER BY loc_created DESC LIMIT 0,1";

//  $sqlquery = "SELECT cr_gps_type AS loc_type, cr_gps_time AS loc_created, '0000-00-00 00:00:00' AS loc_time, usr_id FROM courier WHERE cr_id = " . $cr_id . " AND ROUND(cr_gps_long, 6) = ROUND(" . $longitude . ", 6) AND ROUND(cr_gps_lat, 6) = ROUND(" . $latitude . ", 6)";
//  $result = $db->query($sqlquery);
//  if (DB::isError($result)) die ("$PHP_SELF: " . $result->getMessage());
//  if ($row = $result->fetch_assoc()):   
//    $loc_type = $row["loc_type"];
    
    // if accuracy is 2 (GPS) then ok; if accuracy is 3 (Network) then check plausibility
    if ($loc_type == 2):
      @fclose($fileHandle);
      return true;
    elseif ($loc_type == 3):
//      $usr_id = $row["usr_id"];
//      $loc_acc = $row["loc_acc"];
//      $loc_time = $row["loc_time"];
//      $loc_created = $row["loc_created"];
      $loc_created = $loc_time;
      $usr_id = $db->getOne("SELECT usr_id FROM courier WHERE cr_id = '" . $cr_id . "'");

      // find the last previous locating with type 2 (GPS)
      $sqlquery = "SELECT loc_long, loc_lat, loc_acc, loc_time, loc_created FROM phoenix_log.locating WHERE usr_id = " . $usr_id . " AND loc_type = 2 AND loc_created < '" . $loc_created . "' ORDER BY loc_created DESC LIMIT 0,1";
      $result1 = $db->query($sqlquery);
      if (DB::isError($result1)) die ("$PHP_SELF: " . $result1->getMessage());
      if ($row1 = $result1->fetch_assoc()):   
        $loc_long_gps = $row1["loc_long"];
        $loc_lat_gps = $row1["loc_lat"];
        $loc_acc_gps = $row1["loc_acc"];
        $loc_time_gps = $row1["loc_time"];
        $loc_created_gps = $row1["loc_created"];
        if ($loc_time_gps == "0000-00-00 00:00:00")
          $loc_time_gps = $loc_created_gps;

        // calculate the velocity needed to get from the point of type "GPS" to the point of type "network"
        $hq_id = $db->getOne("SELECT hq_id FROM courier WHERE cr_id = '" . $cr_id . "'");
        $geo_earth_radius = getParameterValue("0", "GEO_EARTH_RADIUS", $hq_id);
        $distKm = acos(sin(deg2rad($latitude)) * sin(deg2rad($loc_lat_gps)) + cos(deg2rad($latitude)) * cos(deg2rad($loc_lat_gps)) * cos(deg2rad($loc_long_gps) - deg2rad($longitude))) * $geo_earth_radius;

	    if (!is_null ($loc_acc) && trim($loc_acc) != "")
          $distKm = $distKm - ($loc_acc / 1000) - ($loc_acc_gps / 1000);
//        else
//          @fwrite($fileHandle, "loc_acc is empty\n");
        $velocity = round(($distKm / (strtotime($loc_time) - strtotime($loc_time_gps))) * 3600);
        $velocity_threshold = getParameterValue("0", "LOCATING_PLAUSIBLE_VELOCITY", "0");
        if (abs($velocity) <= $velocity_threshold):
          // log for test only
          $log_text = "\n[" . date("Y-m-d H:i:s") . "] velocity under threshold: \$distKm = $distKm, difference in time: " . (strtotime($loc_time) - strtotime($loc_time_gps)) . " seconds, \$velocity = $velocity, \$velocity_threshold = $velocity_threshold\n";
          $log_text .= "this locating (\$loc_type = $loc_type) is plausible: \$latitude = $latitude, \$longitude = $longitude," .
            " \$loc_time = $loc_time, \$loc_acc = $loc_acc, \$cr_id = $cr_id, \$usr_id = $usr_id, \$hq_id = $hq_id\n";
          $log_text .= "in relation to the latest earlier locating of type GPS (\$loc_type = 2): \$loc_lat_gps = $loc_lat_gps, \$loc_long_gps = $loc_long_gps, \$loc_time_gps = $loc_time_gps, \$loc_acc_gps = $loc_acc_gps\n";
          @fwrite($fileHandle, $log_text);
          @fclose($fileHandle);
          return true;
        endif;
        // log it if a locating is considered implausible
        $log_text = "\n[" . date("Y-m-d H:i:s") . "] velocity over threshold: \$distKm = $distKm, difference in time: " . (strtotime($loc_time) - strtotime($loc_time_gps)) . " seconds, \$velocity = $velocity, \$velocity_threshold = $velocity_threshold\n";
        $log_text .= "this locating (\$loc_type = $loc_type) is implausible: \$latitude = $latitude, \$longitude = $longitude," .
          " \$loc_time = $loc_time, \$loc_acc = $loc_acc, \$cr_id = $cr_id, \$usr_id = $usr_id, \$hq_id = $hq_id\n";
        $log_text .= "in relation to the latest earlier locating of type GPS (\$loc_type = 2): \$loc_lat_gps = $loc_lat_gps, \$loc_long_gps = $loc_long_gps, \$loc_time_gps = $loc_time_gps, \$loc_acc_gps = $loc_acc_gps\n";
        @fwrite($fileHandle, $log_text);

      else:
        $log_text = "\n[" . date("Y-m-d H:i:s") . "] locating of type GPS not found: [" . $sqlquery .  "]\n";
        $log_text .= "\$latitude = $latitude, \$longitude = $longitude," .
          " \$loc_time = $loc_time, \$loc_type = $loc_type, \$cr_id = $cr_id, \$usr_id = $usr_id\n";
        @fwrite($fileHandle, $log_text);
      endif;
      $result1->free();
    else:  
      $log_text = "\n[" . date("Y-m-d H:i:s") . "] loc_type is neither 2 nor 3\n";
      $log_text .= "\$latitude = $latitude, \$longitude = $longitude," .
        " \$loc_time = $loc_time, \$loc_type = $loc_type, \$cr_id = $cr_id\n";
      @fwrite($fileHandle, $log_text);
      return true;      
    endif;
//    $result->free();
//  else:  
//    @fwrite($fileHandle, "[" . date("Y-m-d H:i:s") . "]\n entry in table 'courier' not found: [" . $sqlquery .  "]\n\n");
//  endif;

  @fclose($fileHandle);
  return false;
}
?>
