From 7d005bc4e1b602e4db9a9de082f9a457fe2eb3bb Mon Sep 17 00:00:00 2001 From: Andreas Kristiansen <6977712+AndreasK79@users.noreply.github.com> Date: Fri, 6 Mar 2026 09:48:21 +0100 Subject: [PATCH 1/8] [VUCC Award] Main query rewrite --- application/models/Vucc.php | 350 +++++++++++++++++++++++++----------- 1 file changed, 243 insertions(+), 107 deletions(-) diff --git a/application/models/Vucc.php b/application/models/Vucc.php index 4163de860..51bd406da 100644 --- a/application/models/Vucc.php +++ b/application/models/Vucc.php @@ -27,69 +27,81 @@ class VUCC extends CI_Model * Builds the array to display worked/confirmed vucc on award page */ function fetchVucc($data) { - $totalGridConfirmed = array(); - $totalGridWorked = array(); + // Use associative arrays for O(1) lookups instead of O(n) in_array() + $totalGridWorked = []; + $totalGridConfirmed = []; + $workedZones = []; // [band][grid] = true + $confirmedZones = []; // [band][grid] = true - foreach($data['worked_bands'] as $band) { + // Create a lookup array for valid bands + $validBands = array_flip($data['worked_bands']); - // Getting all the worked grids - $col_gridsquare_worked = $this->get_vucc_summary($band, 'none'); + // Get combined data (2 queries instead of 4 per band) + $combinedData = $this->get_vucc_combined_data_all_bands(); - $workedGridArray = array(); - foreach ($col_gridsquare_worked as $workedgrid) { - array_push($workedGridArray, $workedgrid['gridsquare']); - if(!in_array($workedgrid['gridsquare'], $totalGridWorked)){ - array_push($totalGridWorked, $workedgrid['gridsquare']); + // Process col_gridsquare data + if (!empty($combinedData['gridsquare'])) { + foreach ($combinedData['gridsquare'] as $row) { + $grid = $row['gridsquare']; + $band = $row['col_band']; + + // Skip if this band is not in our requested bands list + if (!isset($validBands[$band])) { + continue; } - } - $col_vucc_grids_worked = $this->get_vucc_summary_col_vucc($band, 'none'); + // Always add to worked + $totalGridWorked[$grid] = true; + if (!isset($workedZones[$band][$grid])) { + $workedZones[$band][$grid] = true; + } - foreach ($col_vucc_grids_worked as $gridSplit) { - $grids = explode(",", $gridSplit['col_vucc_grids']); - foreach($grids as $key) { - $grid_four = strtoupper(substr(trim($key),0,4)); - - if(!in_array($grid_four, $workedGridArray)){ - array_push($workedGridArray, $grid_four); - } - - if(!in_array($grid_four, $totalGridWorked)){ - array_push($totalGridWorked, $grid_four); + // Add to confirmed if flagged + if ($row['confirmed']) { + $totalGridConfirmed[$grid] = true; + if (!isset($confirmedZones[$band][$grid])) { + $confirmedZones[$band][$grid] = true; } } } + } - // Getting all the confirmed grids - $col_gridsquare_confirmed = $this->get_vucc_summary($band, 'both'); + // Process col_vucc_grids data + if (!empty($combinedData['vucc_grids'])) { + foreach ($combinedData['vucc_grids'] as $row) { + $grids = explode(",", $row['col_vucc_grids']); + $band = $row['col_band']; - $confirmedGridArray = array(); - foreach ($col_gridsquare_confirmed as $confirmedgrid) { - array_push($confirmedGridArray, $confirmedgrid['gridsquare']); - if(!in_array($confirmedgrid['gridsquare'], $totalGridConfirmed)){ - array_push($totalGridConfirmed, $confirmedgrid['gridsquare']); + // Skip if this band is not in our requested bands list + if (!isset($validBands[$band])) { + continue; } - } - $col_vucc_grids_confirmed = $this->get_vucc_summary_col_vucc($band, 'both'); + foreach ($grids as $key) { + $grid_four = strtoupper(substr(trim($key), 0, 4)); - foreach ($col_vucc_grids_confirmed as $gridSplit) { - $grids = explode(",", $gridSplit['col_vucc_grids']); - foreach($grids as $key) { - $grid_four = strtoupper(substr(trim($key),0,4)); - - if(!in_array($grid_four, $confirmedGridArray)){ - array_push($confirmedGridArray, $grid_four); + // Always add to worked + $totalGridWorked[$grid_four] = true; + if (!isset($workedZones[$band][$grid_four])) { + $workedZones[$band][$grid_four] = true; } - if(!in_array($grid_four, $totalGridConfirmed)){ - array_push($totalGridConfirmed, $grid_four); + // Add to confirmed if flagged + if ($row['confirmed']) { + $totalGridConfirmed[$grid_four] = true; + if (!isset($confirmedZones[$band][$grid_four])) { + $confirmedZones[$band][$grid_four] = true; + } } } } + } - $vuccArray[$band]['worked'] = count($workedGridArray); - $vuccArray[$band]['confirmed'] = count($confirmedGridArray); + // Build the result array with counts per band + $vuccArray = []; + foreach ($data['worked_bands'] as $band) { + $vuccArray[$band]['worked'] = isset($workedZones[$band]) ? count($workedZones[$band]) : 0; + $vuccArray[$band]['confirmed'] = isset($confirmedZones[$band]) ? count($confirmedZones[$band]) : 0; } $vuccArray['All']['worked'] = count($totalGridWorked); @@ -157,14 +169,9 @@ class VUCC extends CI_Model $sql = "select distinct upper(substring(log.col_gridsquare, 1, 4)) gridsquare from " . $this->config->item('table_name') . " log". - " inner join bands b on (b.band = log.col_band) ". " where log.station_id in (" . $location_list . ")" . " and log.col_gridsquare <> ''"; - if (($band == 'SAT') || ($band == 'All')) { - $sql.=" and b.bandgroup in ('vhf','uhf','shf','sat')"; - } - if ($confirmationMethod == 'both') { $sql .= " and (log.col_qsl_rcvd='Y' or log.col_lotw_qsl_rcvd='Y')"; } else if ($confirmationMethod == 'qsl') { @@ -192,16 +199,77 @@ class VUCC extends CI_Model * Makes a list of all gridsquares on chosen band with info about lotw and qsl */ function vucc_details($band, $type) { + // Get combined data for the specific band + $bandData = $this->get_vucc_band_data($band); - if ($type == 'worked') { - $workedGridArray = $this->getWorkedGridsList($band, 'none'); - $vuccBand = $this->removeConfirmedGrids($band, $workedGridArray); - } else if ($type == 'confirmed') { - $workedGridArray = $this->getWorkedGridsList($band, 'both'); - $vuccBand = $this->markConfirmedGrids($band, $workedGridArray); - } else { - $workedGridArray = $this->getWorkedGridsList($band, 'none'); - $vuccBand = $this->markConfirmedGrids($band, $workedGridArray); + if (empty($bandData['gridsquare']) && empty($bandData['vucc_grids'])) { + return 0; + } + + $vuccBand = []; + + // Process col_gridsquare data + foreach ($bandData['gridsquare'] as $row) { + $grid = $row['gridsquare']; + $qsl = $row['qsl_confirmed'] ? 'Y' : ''; + $lotw = $row['lotw_confirmed'] ? 'Y' : ''; + $confirmed = $row['confirmed']; + + // Filter based on type + if ($type == 'worked' && $confirmed) { + continue; // Skip confirmed grids when showing only worked + } + if ($type == 'confirmed' && !$confirmed) { + continue; // Skip worked grids when showing only confirmed + } + + if (!isset($vuccBand[$grid])) { + $vuccBand[$grid]['qsl'] = $qsl; + $vuccBand[$grid]['lotw'] = $lotw; + } else { + // Update confirmation status if already exists + if ($qsl) $vuccBand[$grid]['qsl'] = $qsl; + if ($lotw) $vuccBand[$grid]['lotw'] = $lotw; + } + } + + // Process col_vucc_grids data + foreach ($bandData['vucc_grids'] as $row) { + $grids = explode(",", $row['col_vucc_grids']); + $qsl = $row['qsl_confirmed'] ? 'Y' : ''; + $lotw = $row['lotw_confirmed'] ? 'Y' : ''; + $confirmed = $row['confirmed']; + + foreach ($grids as $key) { + $grid_four = strtoupper(substr(trim($key), 0, 4)); + + // Filter based on type + if ($type == 'worked' && $confirmed) { + continue; // Skip confirmed grids when showing only worked + } + if ($type == 'confirmed' && !$confirmed) { + continue; // Skip worked grids when showing only confirmed + } + + if (!isset($vuccBand[$grid_four])) { + $vuccBand[$grid_four]['qsl'] = $qsl; + $vuccBand[$grid_four]['lotw'] = $lotw; + } else { + // Update confirmation status if already exists + if ($qsl) $vuccBand[$grid_four]['qsl'] = $qsl; + if ($lotw) $vuccBand[$grid_four]['lotw'] = $lotw; + } + } + } + + // Add callsign details for each grid + foreach ($vuccBand as $grid => $data) { + $result = $this->grid_detail($grid, $band); + $callsignlist = ''; + foreach($result->result() as $call) { + $callsignlist .= $call->COL_CALL . '
'; + } + $vuccBand[$grid]['call'] = $callsignlist; } if (!isset($vuccBand)) { @@ -212,60 +280,76 @@ class VUCC extends CI_Model } } - function removeConfirmedGrids($band, $workedGridArray) { - $vuccDataQsl = $this->get_vucc_summary($band, 'qsl'); - - foreach ($vuccDataQsl as $grid) { - if (($key = array_search($grid['gridsquare'], $workedGridArray)) !== false) { - unset($workedGridArray[$key]); - } + /* + * Fetches VUCC data for a specific band with QSL/LoTW confirmation details + * Returns data in a single query per band + */ + private function get_vucc_band_data($band) { + if (!$this->logbooks_locations_array) { + return ['gridsquare' => [], 'vucc_grids' => []]; } - $vuccDataLotw = $this->get_vucc_summary($band, 'lotw'); + $results = ['gridsquare' => [], 'vucc_grids' => []]; + $inPlaceholders = str_repeat('?,', count($this->logbooks_locations_array) - 1) . '?'; - foreach ($vuccDataLotw as $grid) { - if (($key = array_search($grid['gridsquare'], $workedGridArray)) !== false) { - unset($workedGridArray[$key]); - } - } + // Query 1: Get col_gridsquare data for the band + $bindings1 = array_merge($this->logbooks_locations_array); - $col_vucc_grids_confirmed_qsl = $this->get_vucc_summary_col_vucc($band, 'lotw'); - - foreach ($col_vucc_grids_confirmed_qsl as $gridSplit) { - $grids = explode(",", $gridSplit['col_vucc_grids']); - foreach($grids as $key) { - $grid_four = strtoupper(substr(trim($key),0,4)); - if (($key = array_search($grid_four, $workedGridArray)) !== false) { - unset($workedGridArray[$key]); - } - } - } - - $col_vucc_grids_confirmed_lotw = $this->get_vucc_summary_col_vucc($band, 'qsl'); - - foreach ($col_vucc_grids_confirmed_lotw as $gridSplit) { - $grids = explode(",", $gridSplit['col_vucc_grids']); - foreach($grids as $key) { - $grid_four = strtoupper(substr(trim($key),0,4)); - if (($key = array_search($grid_four, $workedGridArray)) !== false) { - unset($workedGridArray[$key]); - } - } - } - foreach ($workedGridArray as $grid) { - $result = $this->grid_detail($grid, $band); - $callsignlist = ''; - foreach($result->result() as $call) { - $callsignlist .= $call->COL_CALL . '
'; - } - $vuccBand[$grid]['call'] = $callsignlist; - } - - if (isset($vuccBand)) { - return $vuccBand; + if ($band == 'SAT') { + $bandCondition1 = " and log.col_prop_mode = ?"; + $bindings1[] = $band; } else { - return null; + $bandCondition1 = " and log.col_prop_mode != ? and log.col_band = ?"; + $bindings1[] = 'SAT'; + $bindings1[] = $band; } + + $sql1 = "SELECT + DISTINCT UPPER(SUBSTRING(col_gridsquare, 1, 4)) as gridsquare, + MAX(CASE WHEN col_qsl_rcvd='Y' THEN 1 ELSE 0 END) as qsl_confirmed, + MAX(CASE WHEN col_lotw_qsl_rcvd='Y' THEN 1 ELSE 0 END) as lotw_confirmed, + MAX(CASE WHEN (col_qsl_rcvd='Y' OR col_lotw_qsl_rcvd='Y') THEN 1 ELSE 0 END) as confirmed + FROM " . $this->config->item('table_name') . " log + INNER JOIN bands b ON (b.band = log.col_band) + WHERE log.station_id IN (" . $inPlaceholders . ") + AND log.col_gridsquare <> ''" + . $bandCondition1 . " + GROUP BY UPPER(SUBSTRING(col_gridsquare, 1, 4))"; + + $query1 = $this->db->query($sql1, $bindings1); + if ($query1->num_rows() > 0) { + $results['gridsquare'] = $query1->result_array(); + } + + // Query 2: Get col_vucc_grids data for the band + $bindings2 = array_merge($this->logbooks_locations_array); + + if ($band == 'SAT') { + $bandCondition2 = " and col_prop_mode = ?"; + $bindings2[] = $band; + } else { + $bandCondition2 = " and col_prop_mode != ? and col_band = ?"; + $bindings2[] = 'SAT'; + $bindings2[] = $band; + } + + $sql2 = "SELECT + DISTINCT col_vucc_grids, + MAX(CASE WHEN col_qsl_rcvd='Y' THEN 1 ELSE 0 END) as qsl_confirmed, + MAX(CASE WHEN col_lotw_qsl_rcvd='Y' THEN 1 ELSE 0 END) as lotw_confirmed, + MAX(CASE WHEN (col_qsl_rcvd='Y' OR col_lotw_qsl_rcvd='Y') THEN 1 ELSE 0 END) as confirmed + FROM " . $this->config->item('table_name') . " + WHERE station_id IN (" . $inPlaceholders . ") + AND col_vucc_grids <> ''" + . $bandCondition2 . " + GROUP BY col_vucc_grids"; + + $query2 = $this->db->query($sql2, $bindings2); + if ($query2->num_rows() > 0) { + $results['vucc_grids'] = $query2->result_array(); + } + + return $results; } function grid_detail($gridsquare, $band) { @@ -386,8 +470,7 @@ class VUCC extends CI_Model FROM " . $this->config->item('table_name') . " log INNER JOIN bands b ON (b.band = log.col_band) WHERE log.station_id IN (" . $inPlaceholders . ") - AND log.col_gridsquare <> '' - AND b.bandgroup IN ('vhf','uhf','shf','sat')" + AND log.col_gridsquare <> ''" . $bandCondition1 . " GROUP BY UPPER(SUBSTRING(col_gridsquare, 1, 4))"; @@ -430,6 +513,59 @@ class VUCC extends CI_Model return $results; } + /* + * Fetches VUCC data for ALL bands in 2 queries (optimized) + * Similar approach to CQ model's getCqZoneData() + * Returns data with band information included for processing + */ + private function get_vucc_combined_data_all_bands() { + if (!$this->logbooks_locations_array) { + return ['gridsquare' => [], 'vucc_grids' => []]; + } + + $results = ['gridsquare' => [], 'vucc_grids' => []]; + $inPlaceholders = str_repeat('?,', count($this->logbooks_locations_array) - 1) . '?'; + + // Query 1: Get col_gridsquare data for ALL bands with worked/confirmed status + // GROUP BY both gridsquare and band to get per-band statistics + $bindings1 = array_merge($this->logbooks_locations_array); + + $sql1 = "SELECT + DISTINCT UPPER(SUBSTRING(col_gridsquare, 1, 4)) as gridsquare, + col_band, + MAX(CASE WHEN (col_qsl_rcvd='Y' OR col_lotw_qsl_rcvd='Y') THEN 1 ELSE 0 END) as confirmed + FROM " . $this->config->item('table_name') . " log + WHERE log.station_id IN (" . $inPlaceholders . ") + AND log.col_gridsquare <> '' + AND log.col_prop_mode != 'SAT' + GROUP BY UPPER(SUBSTRING(col_gridsquare, 1, 4)), col_band"; + + $query1 = $this->db->query($sql1, $bindings1); + if ($query1->num_rows() > 0) { + $results['gridsquare'] = $query1->result_array(); + } + + // Query 2: Get col_vucc_grids data for ALL bands with worked/confirmed status + $bindings2 = array_merge($this->logbooks_locations_array); + + $sql2 = "SELECT + DISTINCT col_vucc_grids, + col_band, + MAX(CASE WHEN (col_qsl_rcvd='Y' OR col_lotw_qsl_rcvd='Y') THEN 1 ELSE 0 END) as confirmed + FROM " . $this->config->item('table_name') . " + WHERE station_id IN (" . $inPlaceholders . ") + AND col_vucc_grids <> '' + AND col_prop_mode != 'SAT' + GROUP BY col_vucc_grids, col_band"; + + $query2 = $this->db->query($sql2, $bindings2); + if ($query2->num_rows() > 0) { + $results['vucc_grids'] = $query2->result_array(); + } + + return $results; + } + /* * Builds the array to display worked/confirmed vucc on dashboard page */ From dc6099dbe10c3b5bc5ed199d764af174eff5d35e Mon Sep 17 00:00:00 2001 From: Andreas Kristiansen <6977712+AndreasK79@users.noreply.github.com> Date: Fri, 6 Mar 2026 10:28:46 +0100 Subject: [PATCH 2/8] Optimize fetching information about gridsquares --- application/models/Vucc.php | 88 ++++++++++++++++++++++++++++++++++--- 1 file changed, 82 insertions(+), 6 deletions(-) diff --git a/application/models/Vucc.php b/application/models/Vucc.php index 51bd406da..508b7ae24 100644 --- a/application/models/Vucc.php +++ b/application/models/Vucc.php @@ -197,6 +197,7 @@ class VUCC extends CI_Model /* * Makes a list of all gridsquares on chosen band with info about lotw and qsl + * Optimized to fetch all callsigns in a single query instead of one per grid */ function vucc_details($band, $type) { // Get combined data for the specific band @@ -262,12 +263,16 @@ class VUCC extends CI_Model } } - // Add callsign details for each grid + // Get all callsigns for all grids in a SINGLE query + $gridCallsigns = $this->get_grid_callsigns_batch(array_keys($vuccBand), $band); + + // Add callsign details for each grid from the batched result foreach ($vuccBand as $grid => $data) { - $result = $this->grid_detail($grid, $band); $callsignlist = ''; - foreach($result->result() as $call) { - $callsignlist .= $call->COL_CALL . '
'; + if (isset($gridCallsigns[$grid])) { + foreach ($gridCallsigns[$grid] as $call) { + $callsignlist .= $call . '
'; + } } $vuccBand[$grid]['call'] = $callsignlist; } @@ -280,6 +285,79 @@ class VUCC extends CI_Model } } + /* + * Fetches callsigns for multiple grids in a single query + * Returns array indexed by 4-character grid with list of callsigns + */ + private function get_grid_callsigns_batch($grids, $band) { + if (empty($grids) || !$this->logbooks_locations_array) { + return []; + } + + $inPlaceholders = str_repeat('?,', count($this->logbooks_locations_array) - 1) . '?'; + $bindings = array_merge($this->logbooks_locations_array); + + // Build band condition + if ($band == 'SAT') { + $bandCondition = " and col_prop_mode = ?"; + $bindings[] = $band; + } else { + $bandCondition = " and col_prop_mode != ? and col_band = ?"; + $bindings[] = 'SAT'; + $bindings[] = $band; + } + + // Fetch all QSOs for this band - we'll filter by grids in PHP + // This is much more efficient than one query per grid + $sql = "SELECT COL_CALL, col_gridsquare, col_vucc_grids + FROM " . $this->config->item('table_name') . " + WHERE station_id IN (" . $inPlaceholders . ") + AND (col_gridsquare <> '' OR col_vucc_grids <> '')" + . $bandCondition; + + $query = $this->db->query($sql, $bindings); + $result = $query->result_array(); + + // Group callsigns by grid in PHP + $gridCallsigns = []; + $gridsLookup = array_flip($grids); // For O(1) lookups + + foreach ($result as $row) { + // Process col_gridsquare + if (!empty($row['col_gridsquare'])) { + $grid_four = strtoupper(substr($row['col_gridsquare'], 0, 4)); + if (isset($gridsLookup[$grid_four])) { + if (!isset($gridCallsigns[$grid_four])) { + $gridCallsigns[$grid_four] = []; + } + // Avoid duplicate callsigns for the same grid + if (!in_array($row['COL_CALL'], $gridCallsigns[$grid_four])) { + $gridCallsigns[$grid_four][] = $row['COL_CALL']; + } + } + } + + // Process col_vucc_grids (comma-separated list) + if (!empty($row['col_vucc_grids'])) { + $vuccGrids = explode(",", $row['col_vucc_grids']); + foreach ($vuccGrids as $vuccGrid) { + $grid_four = strtoupper(substr(trim($vuccGrid), 0, 4)); + if (isset($gridsLookup[$grid_four])) { + if (!isset($gridCallsigns[$grid_four])) { + $gridCallsigns[$grid_four] = []; + } + // Avoid duplicate callsigns for the same grid + if (!in_array($row['COL_CALL'], $gridCallsigns[$grid_four])) { + $gridCallsigns[$grid_four][] = $row['COL_CALL']; + } + } + } + } + } + + return $gridCallsigns; + } + /* * Fetches VUCC data for a specific band with QSL/LoTW confirmation details * Returns data in a single query per band @@ -310,7 +388,6 @@ class VUCC extends CI_Model MAX(CASE WHEN col_lotw_qsl_rcvd='Y' THEN 1 ELSE 0 END) as lotw_confirmed, MAX(CASE WHEN (col_qsl_rcvd='Y' OR col_lotw_qsl_rcvd='Y') THEN 1 ELSE 0 END) as confirmed FROM " . $this->config->item('table_name') . " log - INNER JOIN bands b ON (b.band = log.col_band) WHERE log.station_id IN (" . $inPlaceholders . ") AND log.col_gridsquare <> ''" . $bandCondition1 . " @@ -468,7 +545,6 @@ class VUCC extends CI_Model DISTINCT UPPER(SUBSTRING(col_gridsquare, 1, 4)) as gridsquare, MAX(CASE WHEN (col_qsl_rcvd='Y' OR col_lotw_qsl_rcvd='Y') THEN 1 ELSE 0 END) as confirmed FROM " . $this->config->item('table_name') . " log - INNER JOIN bands b ON (b.band = log.col_band) WHERE log.station_id IN (" . $inPlaceholders . ") AND log.col_gridsquare <> ''" . $bandCondition1 . " From b34c963c1310de88491f8f5f6d65e53c199d8695 Mon Sep 17 00:00:00 2001 From: Andreas Kristiansen <6977712+AndreasK79@users.noreply.github.com> Date: Mon, 9 Mar 2026 09:38:34 +0100 Subject: [PATCH 3/8] Clean up code a bit --- application/models/Vucc.php | 90 +++++-------------------------------- 1 file changed, 12 insertions(+), 78 deletions(-) diff --git a/application/models/Vucc.php b/application/models/Vucc.php index 508b7ae24..d1be43b1b 100644 --- a/application/models/Vucc.php +++ b/application/models/Vucc.php @@ -30,8 +30,8 @@ class VUCC extends CI_Model // Use associative arrays for O(1) lookups instead of O(n) in_array() $totalGridWorked = []; $totalGridConfirmed = []; - $workedZones = []; // [band][grid] = true - $confirmedZones = []; // [band][grid] = true + $workedGrids = []; + $confirmedGrids = []; // Create a lookup array for valid bands $validBands = array_flip($data['worked_bands']); @@ -52,15 +52,15 @@ class VUCC extends CI_Model // Always add to worked $totalGridWorked[$grid] = true; - if (!isset($workedZones[$band][$grid])) { - $workedZones[$band][$grid] = true; + if (!isset($workedGrids[$band][$grid])) { + $workedGrids[$band][$grid] = true; } // Add to confirmed if flagged if ($row['confirmed']) { $totalGridConfirmed[$grid] = true; - if (!isset($confirmedZones[$band][$grid])) { - $confirmedZones[$band][$grid] = true; + if (!isset($confirmedGrids[$band][$grid])) { + $confirmedGrids[$band][$grid] = true; } } } @@ -82,15 +82,15 @@ class VUCC extends CI_Model // Always add to worked $totalGridWorked[$grid_four] = true; - if (!isset($workedZones[$band][$grid_four])) { - $workedZones[$band][$grid_four] = true; + if (!isset($workedGrids[$band][$grid_four])) { + $workedGrids[$band][$grid_four] = true; } // Add to confirmed if flagged if ($row['confirmed']) { $totalGridConfirmed[$grid_four] = true; - if (!isset($confirmedZones[$band][$grid_four])) { - $confirmedZones[$band][$grid_four] = true; + if (!isset($confirmedGrids[$band][$grid_four])) { + $confirmedGrids[$band][$grid_four] = true; } } } @@ -100,8 +100,8 @@ class VUCC extends CI_Model // Build the result array with counts per band $vuccArray = []; foreach ($data['worked_bands'] as $band) { - $vuccArray[$band]['worked'] = isset($workedZones[$band]) ? count($workedZones[$band]) : 0; - $vuccArray[$band]['confirmed'] = isset($confirmedZones[$band]) ? count($confirmedZones[$band]) : 0; + $vuccArray[$band]['worked'] = isset($workedGrids[$band]) ? count($workedGrids[$band]) : 0; + $vuccArray[$band]['confirmed'] = isset($confirmedGrids[$band]) ? count($confirmedGrids[$band]) : 0; } $vuccArray['All']['worked'] = count($totalGridWorked); @@ -448,72 +448,6 @@ class VUCC extends CI_Model return $this->db->query($sql); } - function markConfirmedGrids($band, $workedGridArray) { - foreach ($workedGridArray as $grid) { - $vuccBand[$grid]['qsl'] = ''; - $vuccBand[$grid]['lotw'] = ''; - } - - $vuccDataQsl = $this->get_vucc_summary($band, 'qsl'); - - foreach ($vuccDataQsl as $grid) { - $vuccBand[$grid['gridsquare']]['qsl'] = 'Y'; - } - - $vuccDataLotw = $this->get_vucc_summary($band, 'lotw'); - - foreach ($vuccDataLotw as $grid) { - $vuccBand[$grid['gridsquare']]['lotw'] = 'Y'; - } - - $col_vucc_grids_confirmed_qsl = $this->get_vucc_summary_col_vucc($band, 'lotw'); - - foreach ($col_vucc_grids_confirmed_qsl as $gridSplit) { - $grids = explode(",", $gridSplit['col_vucc_grids']); - foreach($grids as $key) { - $grid_four = strtoupper(substr(trim($key),0,4)); - $vuccBand[$grid_four]['lotw'] = 'Y'; - } - } - - $col_vucc_grids_confirmed_lotw = $this->get_vucc_summary_col_vucc($band, 'qsl'); - - foreach ($col_vucc_grids_confirmed_lotw as $gridSplit) { - $grids = explode(",", $gridSplit['col_vucc_grids']); - foreach($grids as $key) { - $grid_four = strtoupper(substr(trim($key),0,4)); - $vuccBand[$grid_four]['qsl'] = 'Y'; - } - } - - return $vuccBand; - } - - function getWorkedGridsList($band, $confirmationMethod) { - - $col_gridsquare_worked = $this->get_vucc_summary($band, $confirmationMethod); - - $workedGridArray = array(); - foreach ($col_gridsquare_worked as $workedgrid) { - array_push($workedGridArray, $workedgrid['gridsquare']); - } - - $col_vucc_grids_worked = $this->get_vucc_summary_col_vucc($band, $confirmationMethod); - - foreach ($col_vucc_grids_worked as $gridSplit) { - $grids = explode(",", $gridSplit['col_vucc_grids']); - foreach($grids as $key) { - $grid_four = strtoupper(substr(trim($key),0,4)); - - if(!in_array($grid_four, $workedGridArray)){ - array_push($workedGridArray, $grid_four); - } - } - } - - return $workedGridArray; - } - private function get_vucc_combined_data($band = 'All') { if (!$this->logbooks_locations_array) { return ['gridsquare' => [], 'vucc_grids' => []]; From 0f5875884f7df9456ef26c2559a7896105586270 Mon Sep 17 00:00:00 2001 From: Andreas Kristiansen <6977712+AndreasK79@users.noreply.github.com> Date: Mon, 9 Mar 2026 13:10:28 +0100 Subject: [PATCH 4/8] Remove unused functions --- application/models/Vucc.php | 129 +----------------------------------- 1 file changed, 1 insertion(+), 128 deletions(-) diff --git a/application/models/Vucc.php b/application/models/Vucc.php index d1be43b1b..abdd10c15 100644 --- a/application/models/Vucc.php +++ b/application/models/Vucc.php @@ -114,88 +114,7 @@ class VUCC extends CI_Model return $vuccArray; } - /* - * Gets the grid from col_vucc_grids - * $band = the band chosen - * $confirmationMethod - qsl, lotw or both, use anything else to skip confirmed - */ - function get_vucc_summary_col_vucc($band, $confirmationMethod) { - - if (!$this->logbooks_locations_array) { - return null; - } - - $location_list = "'".implode("','",$this->logbooks_locations_array)."'"; - - $sql = "select distinct col_vucc_grids - from " . $this->config->item('table_name') . - " where station_id in (" . $location_list . ")" . - " and col_vucc_grids <> '' "; - - if ($confirmationMethod == 'both') { - $sql .= " and (col_qsl_rcvd='Y' or col_lotw_qsl_rcvd='Y')"; - } - else if ($confirmationMethod == 'qsl') { - $sql .= " and col_qsl_rcvd='Y'"; - } - else if ($confirmationMethod == 'lotw') { - $sql .= " and col_lotw_qsl_rcvd='Y'"; - } - - if ($band != 'All') { - if ($band == 'SAT') { - $sql .= " and col_prop_mode ='" . $band . "'"; - } else { - $sql .= " and col_prop_mode !='SAT'"; - $sql .= " and col_band ='" . $band . "'"; - } - } - - $query = $this->db->query($sql); - return $query->result_array(); - } - - /* - * Gets the grid from col_gridsquare - * $band = the band chosen - * $confirmationMethod - qsl, lotw or both, use anything else to skip confirmed - */ - function get_vucc_summary($band, $confirmationMethod) { - if (!$this->logbooks_locations_array) { - return null; - } - - $location_list = "'".implode("','",$this->logbooks_locations_array)."'"; - - $sql = "select distinct upper(substring(log.col_gridsquare, 1, 4)) gridsquare - from " . $this->config->item('table_name') . " log". - " where log.station_id in (" . $location_list . ")" . - " and log.col_gridsquare <> ''"; - - if ($confirmationMethod == 'both') { - $sql .= " and (log.col_qsl_rcvd='Y' or log.col_lotw_qsl_rcvd='Y')"; - } else if ($confirmationMethod == 'qsl') { - $sql .= " and log.col_qsl_rcvd='Y'"; - } else if ($confirmationMethod == 'lotw') { - $sql .= " and log.col_lotw_qsl_rcvd='Y'"; - } - - if ($band != 'All') { - if ($band == 'SAT') { - $sql .= " and log.col_prop_mode ='" . $band . "'"; - } else { - $sql .= " and log.col_prop_mode !='SAT'"; - $sql .= " and log.col_band ='" . $band . "'"; - } - } else { - $sql .= " and log.col_prop_mode !='SAT'"; - } - $query = $this->db->query($sql); - - return $query->result_array(); - } - - /* + /* * Makes a list of all gridsquares on chosen band with info about lotw and qsl * Optimized to fetch all callsigns in a single query instead of one per grid */ @@ -575,51 +494,5 @@ class VUCC extends CI_Model return $results; } - - /* - * Builds the array to display worked/confirmed vucc on dashboard page - */ - function fetchVuccSummary($band = 'All') { - // Use associative arrays for O(1) lookups instead of O(n) in_array() - $totalGridWorked = []; - $totalGridConfirmed = []; - - // Get combined data (2 queries instead of 4) - $data = $this->get_vucc_combined_data($band); - - // Process col_gridsquare data - if (!empty($data['gridsquare'])) { - foreach ($data['gridsquare'] as $row) { - $grid = $row['gridsquare']; - // Always add to worked - $totalGridWorked[$grid] = true; - // Add to confirmed if flagged - if ($row['confirmed']) { - $totalGridConfirmed[$grid] = true; - } - } - } - - // Process col_vucc_grids data - if (!empty($data['vucc_grids'])) { - foreach ($data['vucc_grids'] as $row) { - $grids = explode(",", $row['col_vucc_grids']); - foreach ($grids as $key) { - $grid_four = strtoupper(substr(trim($key), 0, 4)); - // Always add to worked - $totalGridWorked[$grid_four] = true; - // Add to confirmed if flagged - if ($row['confirmed']) { - $totalGridConfirmed[$grid_four] = true; - } - } - } - } - - $vuccArray[$band]['worked'] = count($totalGridWorked); - $vuccArray[$band]['confirmed'] = count($totalGridConfirmed); - - return $vuccArray; - } } ?> From 205bef33b289dcc844562a5d73b4e628de3dd7d3 Mon Sep 17 00:00:00 2001 From: Andreas Kristiansen <6977712+AndreasK79@users.noreply.github.com> Date: Mon, 9 Mar 2026 13:27:29 +0100 Subject: [PATCH 5/8] Code adjustments --- application/models/Vucc.php | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/application/models/Vucc.php b/application/models/Vucc.php index abdd10c15..749540c58 100644 --- a/application/models/Vucc.php +++ b/application/models/Vucc.php @@ -213,13 +213,11 @@ class VUCC extends CI_Model return []; } - $inPlaceholders = str_repeat('?,', count($this->logbooks_locations_array) - 1) . '?'; - $bindings = array_merge($this->logbooks_locations_array); + $location_list = "'" . implode("','", $this->logbooks_locations_array) . "'"; // Build band condition if ($band == 'SAT') { $bandCondition = " and col_prop_mode = ?"; - $bindings[] = $band; } else { $bandCondition = " and col_prop_mode != ? and col_band = ?"; $bindings[] = 'SAT'; @@ -230,7 +228,7 @@ class VUCC extends CI_Model // This is much more efficient than one query per grid $sql = "SELECT COL_CALL, col_gridsquare, col_vucc_grids FROM " . $this->config->item('table_name') . " - WHERE station_id IN (" . $inPlaceholders . ") + WHERE station_id IN (" . $location_list . ") AND (col_gridsquare <> '' OR col_vucc_grids <> '')" . $bandCondition; @@ -287,14 +285,11 @@ class VUCC extends CI_Model } $results = ['gridsquare' => [], 'vucc_grids' => []]; - $inPlaceholders = str_repeat('?,', count($this->logbooks_locations_array) - 1) . '?'; - // Query 1: Get col_gridsquare data for the band - $bindings1 = array_merge($this->logbooks_locations_array); + $location_list = "'" . implode("','", $this->logbooks_locations_array) . "'"; if ($band == 'SAT') { $bandCondition1 = " and log.col_prop_mode = ?"; - $bindings1[] = $band; } else { $bandCondition1 = " and log.col_prop_mode != ? and log.col_band = ?"; $bindings1[] = 'SAT'; @@ -307,7 +302,7 @@ class VUCC extends CI_Model MAX(CASE WHEN col_lotw_qsl_rcvd='Y' THEN 1 ELSE 0 END) as lotw_confirmed, MAX(CASE WHEN (col_qsl_rcvd='Y' OR col_lotw_qsl_rcvd='Y') THEN 1 ELSE 0 END) as confirmed FROM " . $this->config->item('table_name') . " log - WHERE log.station_id IN (" . $inPlaceholders . ") + WHERE log.station_id IN (" . $location_list . ") AND log.col_gridsquare <> ''" . $bandCondition1 . " GROUP BY UPPER(SUBSTRING(col_gridsquare, 1, 4))"; @@ -317,9 +312,6 @@ class VUCC extends CI_Model $results['gridsquare'] = $query1->result_array(); } - // Query 2: Get col_vucc_grids data for the band - $bindings2 = array_merge($this->logbooks_locations_array); - if ($band == 'SAT') { $bandCondition2 = " and col_prop_mode = ?"; $bindings2[] = $band; @@ -335,7 +327,7 @@ class VUCC extends CI_Model MAX(CASE WHEN col_lotw_qsl_rcvd='Y' THEN 1 ELSE 0 END) as lotw_confirmed, MAX(CASE WHEN (col_qsl_rcvd='Y' OR col_lotw_qsl_rcvd='Y') THEN 1 ELSE 0 END) as confirmed FROM " . $this->config->item('table_name') . " - WHERE station_id IN (" . $inPlaceholders . ") + WHERE station_id IN (" . $location_list . ") AND col_vucc_grids <> ''" . $bandCondition2 . " GROUP BY col_vucc_grids"; From ad54adab4cb427c59d2f5d91eda99d1fc77b3390 Mon Sep 17 00:00:00 2001 From: Andreas Kristiansen <6977712+AndreasK79@users.noreply.github.com> Date: Mon, 9 Mar 2026 14:37:54 +0100 Subject: [PATCH 6/8] Fixed SAT --- application/models/Vucc.php | 211 +++++++++++++++++++++--------------- 1 file changed, 123 insertions(+), 88 deletions(-) diff --git a/application/models/Vucc.php b/application/models/Vucc.php index 749540c58..ef07590ef 100644 --- a/application/models/Vucc.php +++ b/application/models/Vucc.php @@ -38,6 +38,7 @@ class VUCC extends CI_Model // Get combined data (2 queries instead of 4 per band) $combinedData = $this->get_vucc_combined_data_all_bands(); + $combinedData2 = $this->get_vucc_combined_data_sat(); // Process col_gridsquare data if (!empty($combinedData['gridsquare'])) { @@ -97,6 +98,65 @@ class VUCC extends CI_Model } } + // Process col_gridsquare data + if (!empty($combinedData2['gridsquare'])) { + foreach ($combinedData2['gridsquare'] as $row) { + $grid = $row['gridsquare']; + $band = $row['col_band']; + + // Skip if this band is not in our requested bands list + if (!isset($validBands[$band])) { + continue; + } + + // Always add to worked + $totalGridWorked[$grid] = true; + if (!isset($workedGrids[$band][$grid])) { + $workedGrids[$band][$grid] = true; + } + + // Add to confirmed if flagged + if ($row['confirmed']) { + $totalGridConfirmed[$grid] = true; + if (!isset($confirmedGrids[$band][$grid])) { + $confirmedGrids[$band][$grid] = true; + } + } + } + } + + // Process col_vucc_grids data + if (!empty($combinedData2['vucc_grids'])) { + foreach ($combinedData2['vucc_grids'] as $row) { + $grids = explode(",", $row['col_vucc_grids']); + $band = $row['col_band']; + + // Skip if this band is not in our requested bands list + if (!isset($validBands[$band])) { + continue; + } + + foreach ($grids as $key) { + $grid_four = strtoupper(substr(trim($key), 0, 4)); + + // Always add to worked + $totalGridWorked[$grid_four] = true; + if (!isset($workedGrids[$band][$grid_four])) { + $workedGrids[$band][$grid_four] = true; + } + + // Add to confirmed if flagged + if ($row['confirmed']) { + $totalGridConfirmed[$grid_four] = true; + if (!isset($confirmedGrids[$band][$grid_four])) { + $confirmedGrids[$band][$grid_four] = true; + } + } + } + } + } + + // Build the result array with counts per band $vuccArray = []; foreach ($data['worked_bands'] as $band) { @@ -214,13 +274,13 @@ class VUCC extends CI_Model } $location_list = "'" . implode("','", $this->logbooks_locations_array) . "'"; + $bindings = array(); // Build band condition if ($band == 'SAT') { - $bandCondition = " and col_prop_mode = ?"; + $bandCondition = " and col_prop_mode = 'SAT'"; } else { - $bandCondition = " and col_prop_mode != ? and col_band = ?"; - $bindings[] = 'SAT'; + $bandCondition = " and col_prop_mode != 'SAT' and col_band = ?"; $bindings[] = $band; } @@ -288,11 +348,12 @@ class VUCC extends CI_Model $location_list = "'" . implode("','", $this->logbooks_locations_array) . "'"; + $bindings1 = array(); + if ($band == 'SAT') { - $bandCondition1 = " and log.col_prop_mode = ?"; + $bandCondition1 = " and log.col_prop_mode = 'SAT'"; } else { - $bandCondition1 = " and log.col_prop_mode != ? and log.col_band = ?"; - $bindings1[] = 'SAT'; + $bandCondition1 = " and log.col_prop_mode != 'SAT' and log.col_band = ?"; $bindings1[] = $band; } @@ -359,81 +420,6 @@ class VUCC extends CI_Model return $this->db->query($sql); } - private function get_vucc_combined_data($band = 'All') { - if (!$this->logbooks_locations_array) { - return ['gridsquare' => [], 'vucc_grids' => []]; - } - - $results = ['gridsquare' => [], 'vucc_grids' => []]; - - $inPlaceholders = str_repeat('?,', count($this->logbooks_locations_array) - 1) . '?'; - - // Query 1: Get col_gridsquare data with worked/confirmed status - $bindings1 = array_merge($this->logbooks_locations_array); - $bandCondition1 = ''; - - if ($band != 'All') { - if ($band == 'SAT') { - $bandCondition1 = " and log.col_prop_mode = ?"; - $bindings1[] = $band; - } else { - $bandCondition1 = " and log.col_prop_mode != ? and log.col_band = ?"; - $bindings1[] = 'SAT'; - $bindings1[] = $band; - } - } else { - $bandCondition1 = " and log.col_prop_mode != ?"; - $bindings1[] = 'SAT'; - } - - $sql1 = "SELECT - DISTINCT UPPER(SUBSTRING(col_gridsquare, 1, 4)) as gridsquare, - MAX(CASE WHEN (col_qsl_rcvd='Y' OR col_lotw_qsl_rcvd='Y') THEN 1 ELSE 0 END) as confirmed - FROM " . $this->config->item('table_name') . " log - WHERE log.station_id IN (" . $inPlaceholders . ") - AND log.col_gridsquare <> ''" - . $bandCondition1 . " - GROUP BY UPPER(SUBSTRING(col_gridsquare, 1, 4))"; - - $query1 = $this->db->query($sql1, $bindings1); - if ($query1->num_rows() > 0) { - $results['gridsquare'] = $query1->result_array(); - } - - // Query 2: Get col_vucc_grids data with worked/confirmed status - // Note: col_vucc_grids has NO band filter when band='All' (includes SAT) - $bindings2 = array_merge($this->logbooks_locations_array); - $bandCondition2 = ''; - - if ($band != 'All') { - if ($band == 'SAT') { - $bandCondition2 = " and col_prop_mode = ?"; - $bindings2[] = $band; - } else { - $bandCondition2 = " and col_prop_mode != ? and col_band = ?"; - $bindings2[] = 'SAT'; - $bindings2[] = $band; - } - } - // When band='All', NO band filter is added (includes all prop_mode including SAT) - - $sql2 = "SELECT - DISTINCT col_vucc_grids, - MAX(CASE WHEN (col_qsl_rcvd='Y' OR col_lotw_qsl_rcvd='Y') THEN 1 ELSE 0 END) as confirmed - FROM " . $this->config->item('table_name') . " - WHERE station_id IN (" . $inPlaceholders . ") - AND col_vucc_grids <> ''" - . $bandCondition2 . " - GROUP BY col_vucc_grids"; - - $query2 = $this->db->query($sql2, $bindings2); - if ($query2->num_rows() > 0) { - $results['vucc_grids'] = $query2->result_array(); - } - - return $results; - } - /* * Fetches VUCC data for ALL bands in 2 queries (optimized) * Similar approach to CQ model's getCqZoneData() @@ -445,41 +431,90 @@ class VUCC extends CI_Model } $results = ['gridsquare' => [], 'vucc_grids' => []]; - $inPlaceholders = str_repeat('?,', count($this->logbooks_locations_array) - 1) . '?'; // Query 1: Get col_gridsquare data for ALL bands with worked/confirmed status // GROUP BY both gridsquare and band to get per-band statistics - $bindings1 = array_merge($this->logbooks_locations_array); + $location_list = "'" . implode("','", $this->logbooks_locations_array) . "'"; $sql1 = "SELECT DISTINCT UPPER(SUBSTRING(col_gridsquare, 1, 4)) as gridsquare, col_band, MAX(CASE WHEN (col_qsl_rcvd='Y' OR col_lotw_qsl_rcvd='Y') THEN 1 ELSE 0 END) as confirmed FROM " . $this->config->item('table_name') . " log - WHERE log.station_id IN (" . $inPlaceholders . ") + WHERE log.station_id IN (" . $location_list . ") AND log.col_gridsquare <> '' AND log.col_prop_mode != 'SAT' GROUP BY UPPER(SUBSTRING(col_gridsquare, 1, 4)), col_band"; - $query1 = $this->db->query($sql1, $bindings1); + $query1 = $this->db->query($sql1); if ($query1->num_rows() > 0) { $results['gridsquare'] = $query1->result_array(); } // Query 2: Get col_vucc_grids data for ALL bands with worked/confirmed status - $bindings2 = array_merge($this->logbooks_locations_array); $sql2 = "SELECT DISTINCT col_vucc_grids, col_band, MAX(CASE WHEN (col_qsl_rcvd='Y' OR col_lotw_qsl_rcvd='Y') THEN 1 ELSE 0 END) as confirmed FROM " . $this->config->item('table_name') . " - WHERE station_id IN (" . $inPlaceholders . ") + WHERE station_id IN (" . $location_list . ") AND col_vucc_grids <> '' AND col_prop_mode != 'SAT' GROUP BY col_vucc_grids, col_band"; - $query2 = $this->db->query($sql2, $bindings2); + $query2 = $this->db->query($sql2); + if ($query2->num_rows() > 0) { + $results['vucc_grids'] = $query2->result_array(); + } + + return $results; + } + + /* + * Fetches VUCC data for ALL bands in 2 queries (optimized) + * Similar approach to CQ model's getCqZoneData() + * Returns data with band information included for processing + */ + private function get_vucc_combined_data_sat() { + if (!$this->logbooks_locations_array) { + return ['gridsquare' => [], 'vucc_grids' => []]; + } + + $results = ['gridsquare' => [], 'vucc_grids' => []]; + + // Query 1: Get col_gridsquare data for ALL bands with worked/confirmed status + // GROUP BY both gridsquare and band to get per-band statistics + $location_list = "'" . implode("','", $this->logbooks_locations_array) . "'"; + + $sql1 = "SELECT + DISTINCT UPPER(SUBSTRING(col_gridsquare, 1, 4)) as gridsquare, + col_prop_mode as col_band, + MAX(CASE WHEN (col_qsl_rcvd='Y' OR col_lotw_qsl_rcvd='Y') THEN 1 ELSE 0 END) as confirmed + FROM " . $this->config->item('table_name') . " log + WHERE log.station_id IN (" . $location_list . ") + AND log.col_gridsquare <> '' + AND log.col_prop_mode = 'SAT' + GROUP BY UPPER(SUBSTRING(col_gridsquare, 1, 4)), col_prop_mode"; + + $query1 = $this->db->query($sql1); + if ($query1->num_rows() > 0) { + $results['gridsquare'] = $query1->result_array(); + } + + // Query 2: Get col_vucc_grids data for ALL bands with worked/confirmed status + + $sql2 = "SELECT + DISTINCT col_vucc_grids, + col_prop_mode as col_band, + MAX(CASE WHEN (col_qsl_rcvd='Y' OR col_lotw_qsl_rcvd='Y') THEN 1 ELSE 0 END) as confirmed + FROM " . $this->config->item('table_name') . " + WHERE station_id IN (" . $location_list . ") + AND col_vucc_grids <> '' + AND col_prop_mode = 'SAT' + GROUP BY col_vucc_grids, col_prop_mode"; + + $query2 = $this->db->query($sql2); if ($query2->num_rows() > 0) { $results['vucc_grids'] = $query2->result_array(); } From 355d8654b093f67c562c9ac51e5ed843d691dd98 Mon Sep 17 00:00:00 2001 From: Andreas Kristiansen <6977712+AndreasK79@users.noreply.github.com> Date: Mon, 9 Mar 2026 14:45:02 +0100 Subject: [PATCH 7/8] Re-added used functions --- application/models/Vucc.php | 122 ++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) diff --git a/application/models/Vucc.php b/application/models/Vucc.php index ef07590ef..49e9a43d2 100644 --- a/application/models/Vucc.php +++ b/application/models/Vucc.php @@ -521,5 +521,127 @@ class VUCC extends CI_Model return $results; } + + /* + * Builds the array to display worked/confirmed vucc on dashboard page + */ + function fetchVuccSummary($band = 'All') { + // Use associative arrays for O(1) lookups instead of O(n) in_array() + $totalGridWorked = []; + $totalGridConfirmed = []; + + // Get combined data (2 queries instead of 4) + $data = $this->get_vucc_combined_data($band); + + // Process col_gridsquare data + if (!empty($data['gridsquare'])) { + foreach ($data['gridsquare'] as $row) { + $grid = $row['gridsquare']; + // Always add to worked + $totalGridWorked[$grid] = true; + // Add to confirmed if flagged + if ($row['confirmed']) { + $totalGridConfirmed[$grid] = true; + } + } + } + + // Process col_vucc_grids data + if (!empty($data['vucc_grids'])) { + foreach ($data['vucc_grids'] as $row) { + $grids = explode(",", $row['col_vucc_grids']); + foreach ($grids as $key) { + $grid_four = strtoupper(substr(trim($key), 0, 4)); + // Always add to worked + $totalGridWorked[$grid_four] = true; + // Add to confirmed if flagged + if ($row['confirmed']) { + $totalGridConfirmed[$grid_four] = true; + } + } + } + } + + $vuccArray[$band]['worked'] = count($totalGridWorked); + $vuccArray[$band]['confirmed'] = count($totalGridConfirmed); + + return $vuccArray; + } + + private function get_vucc_combined_data($band = 'All') { + if (!$this->logbooks_locations_array) { + return ['gridsquare' => [], 'vucc_grids' => []]; + } + + $results = ['gridsquare' => [], 'vucc_grids' => []]; + + $location_list = "'" . implode("','", $this->logbooks_locations_array) . "'"; + + // Query 1: Get col_gridsquare data with worked/confirmed status + $bandCondition1 = ''; + + if ($band != 'All') { + if ($band == 'SAT') { + $bandCondition1 = " and log.col_prop_mode = ?"; + $bindings1[] = $band; + } else { + $bandCondition1 = " and log.col_prop_mode != ? and log.col_band = ?"; + $bindings1[] = 'SAT'; + $bindings1[] = $band; + } + } else { + $bandCondition1 = " and log.col_prop_mode != ?"; + $bindings1[] = 'SAT'; + } + + $sql1 = "SELECT + DISTINCT UPPER(SUBSTRING(col_gridsquare, 1, 4)) as gridsquare, + MAX(CASE WHEN (col_qsl_rcvd='Y' OR col_lotw_qsl_rcvd='Y') THEN 1 ELSE 0 END) as confirmed + FROM " . $this->config->item('table_name') . " log + INNER JOIN bands b ON (b.band = log.col_band) + WHERE log.station_id IN (" . $location_list . ") + AND log.col_gridsquare <> '' + AND b.bandgroup IN ('vhf','uhf','shf','sat')" + . $bandCondition1 . " + GROUP BY UPPER(SUBSTRING(col_gridsquare, 1, 4))"; + + $query1 = $this->db->query($sql1, $bindings1); + if ($query1->num_rows() > 0) { + $results['gridsquare'] = $query1->result_array(); + } + + // Query 2: Get col_vucc_grids data with worked/confirmed status + // Note: col_vucc_grids has NO band filter when band='All' (includes SAT) + $bandCondition2 = ''; + + if ($band != 'All') { + if ($band == 'SAT') { + $bandCondition2 = " and col_prop_mode = ?"; + $bindings2[] = $band; + } else { + $bandCondition2 = " and col_prop_mode != ? and col_band = ?"; + $bindings2[] = 'SAT'; + $bindings2[] = $band; + } + } + // When band='All', NO band filter is added (includes all prop_mode including SAT) + + $sql2 = "SELECT + DISTINCT col_vucc_grids, + MAX(CASE WHEN (col_qsl_rcvd='Y' OR col_lotw_qsl_rcvd='Y') THEN 1 ELSE 0 END) as confirmed + FROM " . $this->config->item('table_name') . " + WHERE station_id IN (" . $location_list . ") + AND col_vucc_grids <> ''" + . $bandCondition2 . " + GROUP BY col_vucc_grids"; + + $query2 = $this->db->query($sql2, $bindings2); + if ($query2->num_rows() > 0) { + $results['vucc_grids'] = $query2->result_array(); + } + + return $results; + } + } ?> From fb80d0b5da4701753506543379cf9ea8dda3a82d Mon Sep 17 00:00:00 2001 From: Andreas Kristiansen <6977712+AndreasK79@users.noreply.github.com> Date: Mon, 9 Mar 2026 14:50:07 +0100 Subject: [PATCH 8/8] Fixed a variable error --- application/models/Vucc.php | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/application/models/Vucc.php b/application/models/Vucc.php index 49e9a43d2..e31c3b532 100644 --- a/application/models/Vucc.php +++ b/application/models/Vucc.php @@ -568,7 +568,7 @@ class VUCC extends CI_Model return $vuccArray; } - private function get_vucc_combined_data($band = 'All') { + private function get_vucc_combined_data($band = 'All') { if (!$this->logbooks_locations_array) { return ['gridsquare' => [], 'vucc_grids' => []]; } @@ -579,19 +579,17 @@ class VUCC extends CI_Model // Query 1: Get col_gridsquare data with worked/confirmed status $bandCondition1 = ''; + $bindings1 = array(); if ($band != 'All') { if ($band == 'SAT') { - $bandCondition1 = " and log.col_prop_mode = ?"; - $bindings1[] = $band; + $bandCondition1 = " and log.col_prop_mode = 'SAT'"; } else { - $bandCondition1 = " and log.col_prop_mode != ? and log.col_band = ?"; - $bindings1[] = 'SAT'; + $bandCondition1 = " and log.col_prop_mode != 'SAT' and log.col_band = ?"; $bindings1[] = $band; } } else { - $bandCondition1 = " and log.col_prop_mode != ?"; - $bindings1[] = 'SAT'; + $bandCondition1 = " and log.col_prop_mode != 'SAT'"; } $sql1 = "SELECT @@ -614,13 +612,13 @@ class VUCC extends CI_Model // Note: col_vucc_grids has NO band filter when band='All' (includes SAT) $bandCondition2 = ''; + $bindings2 = array(); + if ($band != 'All') { if ($band == 'SAT') { - $bandCondition2 = " and col_prop_mode = ?"; - $bindings2[] = $band; + $bandCondition2 = " and col_prop_mode = 'SAT'"; } else { - $bandCondition2 = " and col_prop_mode != ? and col_band = ?"; - $bindings2[] = 'SAT'; + $bandCondition2 = " and col_prop_mode != 'SAT' and col_band = ?"; $bindings2[] = $band; } }