From 45528ee293cdcf7a8524af0cefea8c7014367bde Mon Sep 17 00:00:00 2001 From: Peter Goodhall Date: Fri, 14 Nov 2025 17:49:25 +0000 Subject: [PATCH] Add new gridsquares by band to monthly report Introduces per-band breakdown of new gridsquares in the monthly report, including model, controller, and view changes. The report now displays new gridsquares grouped by band, as well as improved details for new DXCCs and satellite activity breakdowns. --- application/controllers/Monthlyreport.php | 92 ++++++++----- application/models/Monthlyreport_model.php | 147 +++++++++++++++++++++ application/views/monthlyreport/report.php | 142 +++++++++++--------- 3 files changed, 287 insertions(+), 94 deletions(-) diff --git a/application/controllers/Monthlyreport.php b/application/controllers/Monthlyreport.php index ce78fde4f..34423c0c4 100644 --- a/application/controllers/Monthlyreport.php +++ b/application/controllers/Monthlyreport.php @@ -121,6 +121,7 @@ class Monthlyreport extends CI_Controller { 'new_countries_satellite' => $report['new_dxcc_satellite'], 'new_countries_eme' => $report['new_dxcc_eme'], 'new_gridsquares' => $report['new_grids'], + 'new_gridsquares_by_band' => $report['new_grids_by_band'], 'new_gridsquares_hf' => $report['new_grids_hf'], 'new_gridsquares_satellite' => $report['new_grids_satellite'], 'new_gridsquares_eme' => $report['new_grids_eme'], @@ -129,7 +130,8 @@ class Monthlyreport extends CI_Controller { 'bands_used' => $report['bands'], 'continents_worked' => $report['continents'], 'satellite_qsos' => $report['satellite_qsos'], - 'eme_qsos' => $report['eme_qsos'] + 'eme_qsos' => $report['eme_qsos'], + 'satellite_breakdown' => $report['satellite_breakdown'] ), 'statistics' => array( 'qsos_per_day' => round($report['total_qsos'] / date('t', strtotime("$year-$month-01")), 2), @@ -202,7 +204,15 @@ class Monthlyreport extends CI_Controller { foreach ($report['new_dxcc_by_band'] as $band => $dxcc_list) { $text .= "\n{$band} (" . count($dxcc_list) . " new):\n"; foreach ($dxcc_list as $dxcc) { - $text .= " - {$dxcc['name']}\n"; + $text .= " - {$dxcc['name']}"; + if (!empty($dxcc['callsign'])) { + $text .= " (worked {$dxcc['callsign']}"; + if (!empty($dxcc['mode'])) { + $text .= " on {$dxcc['mode']}"; + } + $text .= ")"; + } + $text .= "\n"; } } $text .= "\n"; @@ -212,7 +222,15 @@ class Monthlyreport extends CI_Controller { $text .= "NEW COUNTRIES VIA SATELLITE\n"; $text .= "---------------------------\n"; foreach ($report['new_dxcc_satellite'] as $dxcc) { - $text .= "- {$dxcc['name']}\n"; + $text .= "- {$dxcc['name']}"; + if (!empty($dxcc['callsign'])) { + $text .= " (worked {$dxcc['callsign']}"; + if (!empty($dxcc['mode'])) { + $text .= " on {$dxcc['mode']}"; + } + $text .= ")"; + } + $text .= "\n"; } $text .= "\n"; } @@ -221,7 +239,15 @@ class Monthlyreport extends CI_Controller { $text .= "NEW COUNTRIES VIA EME (MOONBOUNCE)\n"; $text .= "----------------------------------\n"; foreach ($report['new_dxcc_eme'] as $dxcc) { - $text .= "- {$dxcc['name']}\n"; + $text .= "- {$dxcc['name']}"; + if (!empty($dxcc['callsign'])) { + $text .= " (worked {$dxcc['callsign']}"; + if (!empty($dxcc['mode'])) { + $text .= " on {$dxcc['mode']}"; + } + $text .= ")"; + } + $text .= "\n"; } $text .= "\n"; } @@ -230,37 +256,27 @@ class Monthlyreport extends CI_Controller { $text .= "NEW GRIDSQUARES THIS MONTH\n"; $text .= "--------------------------\n"; - if (count($report['new_grids_hf']) > 0) { - $text .= "HF/VHF Terrestrial (" . count($report['new_grids_hf']) . "):\n"; - $grids_per_line = 10; - $grid_list = array_column($report['new_grids_hf'], 'grid'); - for ($i = 0; $i < count($grid_list); $i += $grids_per_line) { - $text .= implode(', ', array_slice($grid_list, $i, $grids_per_line)) . "\n"; - } - $text .= "\n"; - } - - if (count($report['new_grids_satellite']) > 0) { - $text .= "Satellite (" . count($report['new_grids_satellite']) . "):\n"; - $grids_per_line = 10; - $grid_list = array_column($report['new_grids_satellite'], 'grid'); - for ($i = 0; $i < count($grid_list); $i += $grids_per_line) { - $text .= implode(', ', array_slice($grid_list, $i, $grids_per_line)) . "\n"; - } - $text .= "\n"; - } - - if (count($report['new_grids_eme']) > 0) { - $text .= "EME (Moonbounce) (" . count($report['new_grids_eme']) . "):\n"; - $grids_per_line = 10; - $grid_list = array_column($report['new_grids_eme'], 'grid'); - for ($i = 0; $i < count($grid_list); $i += $grids_per_line) { - $text .= implode(', ', array_slice($grid_list, $i, $grids_per_line)) . "\n"; + if (!empty($report['new_grids_by_band'])) { + foreach ($report['new_grids_by_band'] as $band => $grids_list) { + $text .= "\n{$band} (" . count($grids_list) . " new):\n"; + foreach ($grids_list as $grid) { + $text .= " {$grid['grid']}"; + if (!empty($grid['callsign'])) { + $text .= " ({$grid['callsign']}"; + if (!empty($grid['satellite'])) { + $text .= " via {$grid['satellite']}"; + } + if (!empty($grid['mode'])) { + $text .= " - {$grid['mode']}"; + } + $text .= ")"; + } + $text .= "\n"; + } } } - } - - $text .= "MODES USED\n"; + $text .= "\n"; + } $text .= "MODES USED\n"; $text .= "----------\n"; foreach ($report['modes'] as $mode => $count) { $text .= sprintf("%-10s %d QSOs\n", $mode, $count); @@ -295,7 +311,15 @@ class Monthlyreport extends CI_Controller { if ($report['satellite_qsos'] > 0) { $text .= "SATELLITE ACTIVITY\n"; $text .= "------------------\n"; - $text .= "Total Satellite QSOs: {$report['satellite_qsos']}\n\n"; + $text .= "Total Satellite QSOs: {$report['satellite_qsos']}\n"; + + if (!empty($report['satellite_breakdown'])) { + $text .= "\nQSOs per Satellite:\n"; + foreach ($report['satellite_breakdown'] as $sat) { + $text .= sprintf(" %-20s %3d QSOs (%s%%)\n", $sat['satellite'], $sat['qso_count'], $sat['percentage']); + } + } + $text .= "\n"; } if ($report['eme_qsos'] > 0) { diff --git a/application/models/Monthlyreport_model.php b/application/models/Monthlyreport_model.php index afba7741e..f4094e26f 100644 --- a/application/models/Monthlyreport_model.php +++ b/application/models/Monthlyreport_model.php @@ -32,6 +32,7 @@ class Monthlyreport_model extends CI_Model { 'new_dxcc_satellite' => $this->get_new_dxcc_by_prop($logbooks_locations_array, $start_date, $end_date, $prev_month_end, 'SAT'), 'new_dxcc_eme' => $this->get_new_dxcc_by_prop($logbooks_locations_array, $start_date, $end_date, $prev_month_end, 'EME'), 'new_grids' => $this->get_new_gridsquares($logbooks_locations_array, $start_date, $end_date, $prev_month_end), + 'new_grids_by_band' => $this->get_new_gridsquares_by_band($logbooks_locations_array, $start_date, $end_date, $prev_month_end), 'new_grids_satellite' => $this->get_new_gridsquares_by_prop($logbooks_locations_array, $start_date, $end_date, $prev_month_end, 'SAT'), 'new_grids_eme' => $this->get_new_gridsquares_by_prop($logbooks_locations_array, $start_date, $end_date, $prev_month_end, 'EME'), 'new_grids_hf' => $this->get_new_gridsquares_hf($logbooks_locations_array, $start_date, $end_date, $prev_month_end), @@ -432,6 +433,152 @@ class Monthlyreport_model extends CI_Model { return $new_dxcc; } + /** + * Get new gridsquares by band + */ + private function get_new_gridsquares_by_band($locations, $start_date, $end_date, $prev_month_end) { + $new_grids_by_band = array(); + + // Get all bands worked this month, plus propagation mode to separate SAT/EME + $this->db->distinct(); + $this->db->select('COL_BAND, COL_PROP_MODE'); + $this->db->from($this->config->item('table_name')); + $this->db->where_in('station_id', $locations); + $this->db->where('COL_TIME_ON >=', $start_date); + $this->db->where('COL_TIME_ON <=', $end_date); + $this->db->where('COL_BAND IS NOT NULL'); + $this->db->where('COL_BAND !=', ''); + $bands_query = $this->db->get(); + + foreach ($bands_query->result() as $band_row) { + $band = $band_row->COL_BAND; + $prop_mode = $band_row->COL_PROP_MODE; + + // Group SAT and EME separately, not by frequency band + if ($prop_mode == 'SAT') { + $band_key = 'Satellite'; + } elseif ($prop_mode == 'EME') { + $band_key = 'EME'; + } else { + $band_key = $band; + } + + if (!isset($new_grids_by_band[$band_key])) { + $new_grids_by_band[$band_key] = array(); + } + + // Get all gridsquares worked on this band/prop this month + $this->db->select('COL_CALL, COL_GRIDSQUARE, COL_VUCC_GRIDS, COL_TIME_ON, COL_MODE, COL_SUBMODE, COL_SAT_NAME'); + $this->db->from($this->config->item('table_name')); + $this->db->where_in('station_id', $locations); + $this->db->where('COL_TIME_ON >=', $start_date); + $this->db->where('COL_TIME_ON <=', $end_date); + $this->db->where('COL_BAND', $band); + + // Filter by propagation mode + if ($prop_mode) { + $this->db->where('COL_PROP_MODE', $prop_mode); + } else { + // For terrestrial, exclude SAT and EME + $this->db->where('(COL_PROP_MODE IS NULL OR (COL_PROP_MODE != "SAT" AND COL_PROP_MODE != "EME"))', NULL, FALSE); + } + + $this->db->order_by('COL_TIME_ON', 'ASC'); + + $query = $this->db->get(); + $grid_data = array(); + + foreach ($query->result() as $row) { + $mode = !empty($row->COL_SUBMODE) ? $row->COL_SUBMODE : $row->COL_MODE; + + // Process main gridsquare (first 4 characters only) + if (!empty($row->COL_GRIDSQUARE) && strlen($row->COL_GRIDSQUARE) >= 4) { + $grid_4char = strtoupper(substr($row->COL_GRIDSQUARE, 0, 4)); + if (!isset($grid_data[$grid_4char])) { + $grid_data[$grid_4char] = array( + 'callsign' => $row->COL_CALL, + 'satellite' => !empty($row->COL_SAT_NAME) ? $row->COL_SAT_NAME : '', + 'mode' => $mode, + 'time' => $row->COL_TIME_ON + ); + } + } + + // Process VUCC grids (first 4 characters only) + if (!empty($row->COL_VUCC_GRIDS)) { + $vucc_grids = explode(',', $row->COL_VUCC_GRIDS); + foreach ($vucc_grids as $grid) { + $grid = trim($grid); + if (strlen($grid) >= 4) { + $grid_4char = strtoupper(substr($grid, 0, 4)); + if (!isset($grid_data[$grid_4char])) { + $grid_data[$grid_4char] = array( + 'callsign' => $row->COL_CALL, + 'satellite' => !empty($row->COL_SAT_NAME) ? $row->COL_SAT_NAME : '', + 'mode' => $mode, + 'time' => $row->COL_TIME_ON + ); + } + } + } + } + } + + // Check each grid to see if it was worked before on this band/prop + foreach ($grid_data as $grid => $data) { + // Check if this grid was worked before this month on this band/prop + $this->db->select('COUNT(*) as count'); + $this->db->from($this->config->item('table_name')); + $this->db->where_in('station_id', $locations); + $this->db->where('COL_BAND', $band); + if ($prop_mode) { + $this->db->where('COL_PROP_MODE', $prop_mode); + } else { + $this->db->where('(COL_PROP_MODE IS NULL OR (COL_PROP_MODE != "SAT" AND COL_PROP_MODE != "EME"))', NULL, FALSE); + } + $this->db->where('COL_TIME_ON <', $start_date); + $this->db->group_start(); + $this->db->where('UPPER(SUBSTR(COL_GRIDSQUARE, 1, 4)) =', $grid); + $this->db->or_like('COL_VUCC_GRIDS', $grid); + $this->db->group_end(); + + $prev_query = $this->db->get(); + $prev_row = $prev_query->row(); + + // If not worked before on this band/prop, it's new + if ($prev_row->count == 0) { + // Avoid duplicates in the same band_key + $already_added = false; + foreach ($new_grids_by_band[$band_key] as $existing) { + if ($existing['grid'] == $grid) { + $already_added = true; + break; + } + } + + if (!$already_added) { + $new_grids_by_band[$band_key][] = array( + 'grid' => $grid, + 'callsign' => $data['callsign'], + 'satellite' => $data['satellite'], + 'mode' => $data['mode'] + ); + } + } + } + } + + // Remove bands with no new grids + $new_grids_by_band = array_filter($new_grids_by_band, function($arr) { + return !empty($arr); + }); + + // Sort bands in proper amateur radio order + $new_grids_by_band = $this->sort_bands_array($new_grids_by_band); + + return $new_grids_by_band; + } + /** * Get new gridsquares worked this month (first time ever) - All modes */ diff --git a/application/views/monthlyreport/report.php b/application/views/monthlyreport/report.php index bc08476a0..ad61ee959 100644 --- a/application/views/monthlyreport/report.php +++ b/application/views/monthlyreport/report.php @@ -213,77 +213,99 @@ - - 0) { ?> + + $grids_list) { + if ($band != 'Satellite' && $band != 'EME') { + $terrestrial_grids[$band] = $grids_list; + } + } + } + + if (!empty($terrestrial_grids)) { + ?>
-
New Gridsquares This Month
+
New Gridsquares by Band
- - 0) { ?> -
-
HF/VHF Terrestrial ()
-
- -
-
- - - - - + $grids_list) { + $icon = ''; + ?> +
+
( new)
+
+ +
+
+ + + + + +
-
- + +
-
- - 0) { ?> -
-
Satellite ()
-
- -
-
- - - - - - -
-
- -
-
- - - 0) { ?> -
-
EME (Moonbounce) ()
-
- -
-
- - - - - -
-
- -
-
- -
- + + 0) { ?> +
+
+
New Gridsquares via Satellite ()
+
+
+
+ +
+
+ + + + + + +
+
+ +
+
+
+ + + + 0) { ?> +
+
+
New Gridsquares via EME (Moonbounce) ()
+
+
+
+ +
+
+ + + + + +
+
+ +
+
+
+