From 76f55f7f270e0a3f1761ab2b97f066da9c187e29 Mon Sep 17 00:00:00 2001 From: Peter Goodhall Date: Sat, 23 Aug 2025 21:11:36 +0100 Subject: [PATCH] Add Most Worked Callsigns feature Introduces a new 'Most Worked Callsigns' page, controller, model, and view to display callsigns worked multiple times from the active logbook. Adds language support for this feature in multiple languages and updates the navigation menu to include a link to the new page. Also includes DataTables integration and filter options for bands, modes, satellites, date range, and minimum QSOs. --- application/controllers/Mostworked.php | 58 +++++ application/language/bulgarian/menu_lang.php | 1 + .../language/bulgarian/most_worked_lang.php | 12 + .../language/chinese_simplified/menu_lang.php | 1 + .../chinese_simplified/most_worked_lang.php | 12 + application/language/czech/menu_lang.php | 1 + .../language/czech/most_worked_lang.php | 12 + application/language/dutch/menu_lang.php | 1 + .../language/dutch/most_worked_lang.php | 12 + application/language/english/menu_lang.php | 1 + .../language/english/most_worked_lang.php | 12 + application/language/finnish/menu_lang.php | 1 + .../language/finnish/most_worked_lang.php | 12 + application/language/french/menu_lang.php | 1 + .../language/french/most_worked_lang.php | 12 + application/language/german/menu_lang.php | 1 + .../language/german/most_worked_lang.php | 12 + application/language/greek/menu_lang.php | 1 + .../language/greek/most_worked_lang.php | 12 + application/language/italian/menu_lang.php | 1 + .../language/italian/most_worked_lang.php | 12 + application/language/polish/menu_lang.php | 1 + .../language/polish/most_worked_lang.php | 12 + application/language/portuguese/menu_lang.php | 1 + .../language/portuguese/most_worked_lang.php | 12 + application/language/russian/menu_lang.php | 1 + .../language/russian/most_worked_lang.php | 12 + application/language/spanish/menu_lang.php | 1 + .../language/spanish/most_worked_lang.php | 12 + application/language/swedish/menu_lang.php | 1 + .../language/swedish/most_worked_lang.php | 12 + application/language/turkish/menu_lang.php | 1 + .../language/turkish/most_worked_lang.php | 12 + application/models/Mostworked_model.php | 206 ++++++++++++++++++ application/views/interface_assets/footer.php | 25 +++ application/views/interface_assets/header.php | 2 + application/views/mostworked/index.php | 131 +++++++++++ 37 files changed, 630 insertions(+) create mode 100644 application/controllers/Mostworked.php create mode 100644 application/language/bulgarian/most_worked_lang.php create mode 100644 application/language/chinese_simplified/most_worked_lang.php create mode 100644 application/language/czech/most_worked_lang.php create mode 100644 application/language/dutch/most_worked_lang.php create mode 100644 application/language/english/most_worked_lang.php create mode 100644 application/language/finnish/most_worked_lang.php create mode 100644 application/language/french/most_worked_lang.php create mode 100644 application/language/german/most_worked_lang.php create mode 100644 application/language/greek/most_worked_lang.php create mode 100644 application/language/italian/most_worked_lang.php create mode 100644 application/language/polish/most_worked_lang.php create mode 100644 application/language/portuguese/most_worked_lang.php create mode 100644 application/language/russian/most_worked_lang.php create mode 100644 application/language/spanish/most_worked_lang.php create mode 100644 application/language/swedish/most_worked_lang.php create mode 100644 application/language/turkish/most_worked_lang.php create mode 100644 application/models/Mostworked_model.php create mode 100644 application/views/mostworked/index.php diff --git a/application/controllers/Mostworked.php b/application/controllers/Mostworked.php new file mode 100644 index 00000000..c3678ff0 --- /dev/null +++ b/application/controllers/Mostworked.php @@ -0,0 +1,58 @@ +load->model('user_model'); + if(!$this->user_model->authorize(2)) { $this->session->set_flashdata('notice', 'You\'re not allowed to do that!'); redirect('dashboard'); } + + // Load language files + $this->lang->load('most_worked'); + } + + public function index() + { + // Check if users logged in + if ($this->user_model->validate_session() == 0) { + // user is not logged in + redirect('user/login'); + } + + $this->load->model('mostworked_model'); + $this->load->model('logbooks_model'); + + // Get filter parameters + $filters = array( + 'band' => $this->input->post('band') ?: 'all', + 'mode' => $this->input->post('mode') ?: 'all', + 'satellite' => $this->input->post('satellite') ?: 'all', + 'fromdate' => $this->input->post('fromdate') ?: '', + 'todate' => $this->input->post('todate') ?: '', + 'min_qsos' => $this->input->post('min_qsos') ?: 5 + ); + + // Get active station logbook + $logbooks_locations_array = $this->logbooks_model->list_logbook_relationships($this->session->userdata('active_station_logbook')); + + if (!$logbooks_locations_array) { + $data['mostworked_callsigns'] = array(); + } else { + $data['mostworked_callsigns'] = $this->mostworked_model->get_most_worked_callsigns($filters); + } + + // Get filter dropdown data + $data['bands'] = $this->mostworked_model->get_bands(); + $data['modes'] = $this->mostworked_model->get_modes(); + $data['satellites'] = $this->mostworked_model->get_satellites(); + $data['filters'] = $filters; + + $data['page_title'] = "Most Worked Callsigns"; + + $this->load->view('interface_assets/header', $data); + $this->load->view('mostworked/index', $data); + $this->load->view('interface_assets/footer'); + } +} \ No newline at end of file diff --git a/application/language/bulgarian/menu_lang.php b/application/language/bulgarian/menu_lang.php index 04b1f384..57761bf4 100644 --- a/application/language/bulgarian/menu_lang.php +++ b/application/language/bulgarian/menu_lang.php @@ -32,6 +32,7 @@ $lang['menu_days_with_qsos'] = 'Days with QSOs'; $lang['menu_timeline'] = 'Timeline'; $lang['menu_accumulated_statistics'] = 'Accumulated Statistics'; $lang['menu_timeplotter'] = 'Timeplotter'; +$lang['menu_most_worked'] = 'Най-Работени'; $lang['menu_custom_maps'] = 'Custom Maps'; $lang['menu_continents'] = 'Continents'; diff --git a/application/language/bulgarian/most_worked_lang.php b/application/language/bulgarian/most_worked_lang.php new file mode 100644 index 00000000..1a99f23a --- /dev/null +++ b/application/language/bulgarian/most_worked_lang.php @@ -0,0 +1,12 @@ +load->model('logbooks_model'); + $logbooks_locations_array = $CI->logbooks_model->list_logbook_relationships($this->session->userdata('active_station_logbook')); + + if (!$logbooks_locations_array) { + return array(); + } + + $location_list = "'" . implode("','", $logbooks_locations_array) . "'"; + + // Set defaults + $min_qsos = isset($filters['min_qsos']) ? intval($filters['min_qsos']) : 5; + $band = isset($filters['band']) ? $filters['band'] : 'all'; + $mode = isset($filters['mode']) ? $filters['mode'] : 'all'; + $satellite = isset($filters['satellite']) ? $filters['satellite'] : 'all'; + $fromdate = isset($filters['fromdate']) ? $filters['fromdate'] : ''; + $todate = isset($filters['todate']) ? $filters['todate'] : ''; + + $sql = "SELECT + col_call as callsign, + COUNT(*) as contact_count, + MIN(col_time_on) as first_qso, + MAX(col_time_on) as last_qso, + GROUP_CONCAT(DISTINCT col_band ORDER BY col_band) as bands, + GROUP_CONCAT(DISTINCT COALESCE(col_submode, col_mode) ORDER BY col_mode) as modes + FROM " . $this->config->item('table_name') . " + WHERE station_id IN (" . $location_list . ") + AND col_call IS NOT NULL + AND col_call != ''"; + + // Apply filters + if ($band != 'all') { + if ($band == 'SAT') { + $sql .= " AND col_prop_mode = 'SAT'"; + } else { + $sql .= " AND col_band = '" . $this->db->escape_str($band) . "'"; + $sql .= " AND (col_prop_mode != 'SAT' OR col_prop_mode IS NULL)"; + } + } + + if ($mode != 'all') { + $sql .= " AND (col_mode = '" . $this->db->escape_str($mode) . "' OR col_submode = '" . $this->db->escape_str($mode) . "')"; + } + + if ($satellite != 'all') { + $sql .= " AND col_sat_name = '" . $this->db->escape_str($satellite) . "'"; + } + + if (!empty($fromdate)) { + $sql .= " AND DATE(col_time_on) >= '" . $this->db->escape_str($fromdate) . "'"; + } + + if (!empty($todate)) { + $sql .= " AND DATE(col_time_on) <= '" . $this->db->escape_str($todate) . "'"; + } + + $sql .= " GROUP BY col_call + HAVING contact_count >= " . $min_qsos . " + ORDER BY contact_count DESC, col_call ASC"; + + $query = $this->db->query($sql); + + return $query->result(); + } + + /* + * Get list of modes from the active logbook + */ + function get_modes() + { + $CI =& get_instance(); + $CI->load->model('logbooks_model'); + $logbooks_locations_array = $CI->logbooks_model->list_logbook_relationships($this->session->userdata('active_station_logbook')); + + if (!$logbooks_locations_array) { + return array(); + } + + $location_list = "'" . implode("','", $logbooks_locations_array) . "'"; + + $sql = "SELECT DISTINCT COALESCE(col_submode, col_mode) as mode + FROM " . $this->config->item('table_name') . " + WHERE station_id IN (" . $location_list . ") + AND COALESCE(col_submode, col_mode) IS NOT NULL + AND COALESCE(col_submode, col_mode) != '' + ORDER BY mode"; + + $query = $this->db->query($sql); + + return $query->result(); + } + + /* + * Get list of satellites from the active logbook + */ + function get_satellites() + { + $CI =& get_instance(); + $CI->load->model('logbooks_model'); + $logbooks_locations_array = $CI->logbooks_model->list_logbook_relationships($this->session->userdata('active_station_logbook')); + + if (!$logbooks_locations_array) { + return array(); + } + + $location_list = "'" . implode("','", $logbooks_locations_array) . "'"; + + $sql = "SELECT DISTINCT col_sat_name as satellite + FROM " . $this->config->item('table_name') . " + WHERE station_id IN (" . $location_list . ") + AND col_sat_name IS NOT NULL + AND col_sat_name != '' + ORDER BY col_sat_name"; + + $query = $this->db->query($sql); + + return $query->result(); + } + + /* + * Get list of bands from the active logbook + */ + function get_bands() + { + $CI =& get_instance(); + $CI->load->model('logbooks_model'); + $logbooks_locations_array = $CI->logbooks_model->list_logbook_relationships($this->session->userdata('active_station_logbook')); + + if (!$logbooks_locations_array) { + return array(); + } + + $location_list = "'" . implode("','", $logbooks_locations_array) . "'"; + + $sql = "SELECT DISTINCT col_band as band + FROM " . $this->config->item('table_name') . " + WHERE station_id IN (" . $location_list . ") + AND col_band IS NOT NULL + AND col_band != '' + AND (col_prop_mode != 'SAT' OR col_prop_mode IS NULL) + ORDER BY + CASE col_band + WHEN '160m' THEN 1 + WHEN '80m' THEN 2 + WHEN '60m' THEN 3 + WHEN '40m' THEN 4 + WHEN '30m' THEN 5 + WHEN '20m' THEN 6 + WHEN '17m' THEN 7 + WHEN '15m' THEN 8 + WHEN '12m' THEN 9 + WHEN '10m' THEN 10 + WHEN '6m' THEN 11 + WHEN '4m' THEN 12 + WHEN '2m' THEN 13 + WHEN '1.25m' THEN 14 + WHEN '70cm' THEN 15 + ELSE 999 + END, col_band"; + + $query = $this->db->query($sql); + + $results = array(); + foreach($query->result() as $row) { + $results[] = $row->band; + } + + return $results; + } + + /* + * Get detailed contact information for a specific callsign + */ + function get_callsign_details($callsign) + { + $CI =& get_instance(); + $CI->load->model('logbooks_model'); + $logbooks_locations_array = $CI->logbooks_model->list_logbook_relationships($this->session->userdata('active_station_logbook')); + + if (!$logbooks_locations_array) { + return array(); + } + + $location_list = "'" . implode("','", $logbooks_locations_array) . "'"; + + $this->db->select('col_time_on, col_band, col_mode, col_submode, col_rst_sent, col_rst_rcvd, col_country, col_qsl_sent, col_qsl_rcvd'); + $this->db->from($this->config->item('table_name')); + $this->db->where('station_id IN (' . $location_list . ')', NULL, FALSE); + $this->db->where('col_call', $callsign); + $this->db->order_by('col_time_on', 'DESC'); + + $query = $this->db->get(); + + return $query->result(); + } +} diff --git a/application/views/interface_assets/footer.php b/application/views/interface_assets/footer.php index c23b6011..8b12f6da 100644 --- a/application/views/interface_assets/footer.php +++ b/application/views/interface_assets/footer.php @@ -158,6 +158,31 @@ if ($this->session->userdata('user_id') != null) { +uri->segment(1) == "mostworked") { ?> + + + uri->segment(1) == "station") { ?> diff --git a/application/views/interface_assets/header.php b/application/views/interface_assets/header.php index 319d79a2..b93b1ec5 100644 --- a/application/views/interface_assets/header.php +++ b/application/views/interface_assets/header.php @@ -133,6 +133,8 @@ + + diff --git a/application/views/mostworked/index.php b/application/views/mostworked/index.php new file mode 100644 index 00000000..63bed396 --- /dev/null +++ b/application/views/mostworked/index.php @@ -0,0 +1,131 @@ +
+
+
+
+
+

Most Worked Callsigns

+

Callsigns worked multiple times from your active logbook, showing contact frequency and other details.

+
+
+ +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ + +
+
+
+ + + + + +
+ + + + + + + + + + + + + session->userdata('user_date_format')) { + // If Logged in and session exists + $custom_date_format = $this->session->userdata('user_date_format'); + } else { + // Get Default date format from /config/cloudlog.php + $custom_date_format = $this->config->item('qso_date_format'); + } + + foreach ($mostworked_callsigns as $row) { ?> + + + + + + + + + +
RankCallsignContactsFirst QSOLast QSO
+ callsign)); ?> + + contact_count; ?> + + first_qso); + echo date($custom_date_format, $timestamp); + ?> + + last_qso); + echo date($custom_date_format, $timestamp); + ?> +
+
+ +
+
+
+
+