[Awards] WPX added

This commit is contained in:
Andreas Kristiansen
2025-09-27 12:09:09 +02:00
parent d1df67af20
commit 27d3e79af5
7 changed files with 951 additions and 9 deletions

View File

@@ -2209,4 +2209,113 @@ class Awards extends CI_Controller {
$this->load->view('awards/73on73/index');
$this->load->view('interface_assets/footer');
}
public function wpx () {
$footerData = [];
$footerData['scripts'] = [
'assets/js/sections/wpx.js?' . filemtime(realpath(__DIR__ . "/../../assets/js/sections/wpx.js")),
];
$this->load->model('wpx');
$this->load->model('modes');
$this->load->model('bands');
$data['orbits'] = $this->bands->get_worked_orbits();
$data['sats_available'] = $this->bands->get_worked_sats();
$data['user_default_band'] = $this->session->userdata('user_default_band');
$data['worked_bands'] = $this->bands->get_worked_bands('dxcc'); // Used in the view for band select
$data['modes'] = $this->modes->active(); // Used in the view for mode select
if ($this->input->post('band') != NULL) { // Band is not set when page first loads.
if ($this->input->post('band') == 'All') { // Did the user specify a band? If not, use all bands
$bands = $data['worked_bands'];
} else {
$bands[] = $this->security->xss_clean($this->input->post('band'));
}
} else {
$bands = $data['worked_bands'];
}
$data['bands'] = $bands; // Used for displaying selected band(s) in the table in the view
if($this->input->method() === 'post') {
$postdata['qsl'] = ($this->input->post('qsl',true) ?? 0) == 0 ? NULL: 1;
$postdata['lotw'] = ($this->input->post('lotw',true) ?? 0) == 0 ? NULL: 1;
$postdata['eqsl'] = ($this->input->post('eqsl',true) ?? 0) == 0 ? NULL: 1;
$postdata['qrz'] = ($this->input->post('qrz',true) ?? 0) == 0 ? NULL: 1;
$postdata['clublog'] = ($this->input->post('clublog',true) ?? 0) == 0 ? NULL: 1;
$postdata['Africa'] = ($this->input->post('Africa',true) ?? 0) == 0 ? NULL: 1;
$postdata['Asia'] = ($this->input->post('Asia',true) ?? 0) == 0 ? NULL: 1;
$postdata['Europe'] = ($this->input->post('Europe',true) ?? 0) == 0 ? NULL: 1;
$postdata['NorthAmerica'] = ($this->input->post('NorthAmerica',true) ?? 0) == 0 ? NULL: 1;
$postdata['SouthAmerica'] = ($this->input->post('SouthAmerica',true) ?? 0) == 0 ? NULL: 1;
$postdata['Oceania'] = ($this->input->post('Oceania',true) ?? 0) == 0 ? NULL: 1;
$postdata['Antarctica'] = ($this->input->post('Antarctica',true) ?? 0) == 0 ? NULL: 1;
$postdata['band'] = $this->security->xss_clean($this->input->post('band'));
$postdata['mode'] = $this->security->xss_clean($this->input->post('mode'));
$postdata['sat'] = $this->security->xss_clean($this->input->post('sats'));
$postdata['orbit'] = $this->security->xss_clean($this->input->post('orbits'));
} else { // Setting default values at first load of page
$postdata['qsl'] = 1;
$postdata['lotw'] = 1;
$postdata['eqsl'] = NULL;
$postdata['qrz'] = NULL;
$postdata['clublog'] = NULL;
$postdata['Africa'] = 1;
$postdata['Asia'] = 1;
$postdata['Europe'] = 1;
$postdata['NorthAmerica'] = 1;
$postdata['SouthAmerica'] = 1;
$postdata['Oceania'] = 1;
$postdata['Antarctica'] = 1;
$postdata['band'] = 'All';
$postdata['mode'] = 'All';
$postdata['sat'] = 'All';
$postdata['orbit'] = 'All';
}
$data['wpx_array'] = $this->wpx->get_wpx_array($bands, $postdata);
// Render Page
$data['page_title'] = sprintf(__("Awards - %s"), __("WPX"));
$data['posted_band']=$postdata['band'];
$this->load->view('interface_assets/header', $data);
$this->load->view('awards/wpx/index');
$this->load->view('interface_assets/footer', $footerData);
}
public function wpx_details()
{
$postdata['band'] = $this->input->post('band', true);
$postdata['status'] = $this->input->post('status', true);
$postdata['sat'] = $this->security->xss_clean($this->input->post('sats'));
$postdata['orbit'] = $this->security->xss_clean($this->input->post('orbits'));
$postdata['mode'] = $this->input->post('mode');
$postdata['qsl'] = ($this->input->post('qsl', true) ?? 0) == 0 ? NULL: 1;
$postdata['lotw'] = ($this->input->post('lotw', true) ?? 0) == 0 ? NULL: 1;
$postdata['eqsl'] = ($this->input->post('eqsl', true) ?? 0) == 0 ? NULL: 1;
$postdata['qrz'] = ($this->input->post('qrz', true) ?? 0) == 0 ? NULL: 1;
$postdata['clublog'] = ($this->input->post('clublog', true) ?? 0) == 0 ? NULL: 1;
$postdata['Africa'] = ($this->input->post('Africa', true) ?? 0) == 0 ? NULL: 1;
$postdata['Asia'] = ($this->input->post('Asia', true) ?? 0) == 0 ? NULL: 1;
$postdata['Europe'] = ($this->input->post('Europe', true) ?? 0) == 0 ? NULL: 1;
$postdata['NorthAmerica'] = ($this->input->post('NorthAmerica', true) ?? 0) == 0 ? NULL: 1;
$postdata['SouthAmerica'] = ($this->input->post('SouthAmerica', true) ?? 0) == 0 ? NULL: 1;
$postdata['Oceania'] = ($this->input->post('Oceania', true) ?? 0) == 0 ? NULL: 1;
$postdata['Antarctica'] = ($this->input->post('Antarctica', true) ?? 0) == 0 ? NULL: 1;
$this->load->model('wpx');
$this->load->model('modes');
$this->load->model('bands');
$results = $this->wpx->getWpxBandDetails($postdata);
$data['band'] = $postdata['band'];
$data['status'] = $postdata['status'];
$data['results'] = $results;
$this->load->view('awards/wpx/wpx_details', $data);
}
}

470
application/models/Wpx.php Normal file
View File

@@ -0,0 +1,470 @@
<?php
class WPX extends CI_Model {
function __construct() {
if(!$this->load->is_loaded('Genfunctions')) {
$this->load->library('Genfunctions');
}
}
function get_wpx_array($bands, $postdata) {
$this->load->model('logbooks_model');
$logbooks_locations_array = $this->logbooks_model->list_logbook_relationships($this->session->userdata('active_station_logbook'));
if (!$logbooks_locations_array) {
return null;
}
$this->load->model('bands');
$location_list = "'".implode("','",$logbooks_locations_array)."'";
foreach ($bands as $band) { // Looping through bands and entities to generate the array needed for display
//'<div class="bg-danger awardsBgDanger" ><a href=\'javascript:displayContacts("'.$wdxcc->dxcc.'","'. $band . '","'. $postdata['sat'] . '","' . $postdata['orbit'] . '","'. $postdata['mode'] . '","DXCC2", "")\'>W</a></div>';
$worked = $this->getWpxForBand($band, $location_list, $postdata);
$confirmed = $this->getWpxForBandConfirmed($band, $location_list, $postdata);
$wpxSummary['worked'][$band] = $worked[0]->wpxcount;
$wpxSummary['confirmed'][$band] = $confirmed[0]->wpxcount;
}
$workedTotal = $this->getWpxForBand($postdata['band'], $location_list, $postdata);
$confirmedTotal = $this->getWpxForBandConfirmed($postdata['band'], $location_list, $postdata);
$wpxSummary['worked']['Total'] = $workedTotal[0]->wpxcount;
$wpxSummary['confirmed']['Total'] = $confirmedTotal[0]->wpxcount;
if (isset($wpxSummary)) {
return $wpxSummary;
} else {
return 0;
}
}
function getWpxForBand($band, $location_list, $postdata) {
$bindings = [];
$sql = "select count(distinct wpx_prefix) wpxcount from (
SELECT
col_call,
CASE
/* case 1: /digit suffix → handle multi-digit prefixes correctly */
WHEN col_call REGEXP '/[0-9]$' THEN
CASE
/* If prefix has multiple digits, replace the last digit */
WHEN SUBSTRING_INDEX(col_call, '/', 1) REGEXP '^[0-9]?[A-Z]{1,3}[0-9]{2,}' THEN
CONCAT(
REGEXP_REPLACE(
SUBSTRING_INDEX(col_call, '/', 1),
'^([0-9]?[A-Z]{1,3}[0-9]*)[0-9].*$',
'\\\\1'
),
SUBSTRING_INDEX(col_call, '/', -1)
)
/* If prefix has single digit, replace it */
ELSE
CONCAT(
REGEXP_REPLACE(
SUBSTRING_INDEX(col_call, '/', 1),
'^([0-9]?[A-Z]{1,3})[0-9].*$',
'\\\\1'
),
SUBSTRING_INDEX(col_call, '/', -1)
)
END
/* case 2: no digit at all → append 0 */
WHEN call_core NOT REGEXP '[A-Z][0-9]' THEN CONCAT(call_core, '0')
/* case 3: normal/anniversary calls → keep prefix+digits */
ELSE
REGEXP_REPLACE(call_core, '^([0-9]?[A-Z]{1,3}[0-9]{1,4}).*$', '\\\\1')
END AS wpx_prefix
FROM (
SELECT
col_call,
CASE
WHEN num_slashes >= 2 THEN left_part
WHEN num_slashes = 1 AND NOT (call_raw REGEXP '/[0-9]$') THEN
CASE
WHEN (left_has_digit + left_short) > (right_has_digit + right_short) THEN left_part
WHEN (left_has_digit + left_short) < (right_has_digit + right_short) THEN right_part
ELSE left_part
END
ELSE call_raw
END AS call_core
FROM (
SELECT
col_call,
UPPER(TRIM(col_call)) AS call_raw,
(LENGTH(UPPER(TRIM(col_call))) - LENGTH(REPLACE(UPPER(TRIM(col_call)), '/', ''))) AS num_slashes,
SUBSTRING_INDEX(UPPER(TRIM(col_call)), '/', 1) AS left_part,
SUBSTRING_INDEX(UPPER(TRIM(col_call)), '/', -1) AS right_part,
(SUBSTRING_INDEX(UPPER(TRIM(col_call)), '/', 1) REGEXP '[0-9]') AS left_has_digit,
(SUBSTRING_INDEX(UPPER(TRIM(col_call)), '/', -1) REGEXP '[0-9]') AS right_has_digit,
(LENGTH(SUBSTRING_INDEX(UPPER(TRIM(col_call)), '/', 1)) <= 3) AS left_short,
(LENGTH(SUBSTRING_INDEX(UPPER(TRIM(col_call)), '/', -1)) <= 3) AS right_short
FROM ".$this->config->item('table_name')." thcv
left join satellite on thcv.COL_SAT_NAME = satellite.name
WHERE station_id in (" . $location_list . ") ";
if ($postdata['mode'] != 'All') {
$sql .= " and (col_mode = ? or col_submode = ?)";
$bindings[] = $postdata['mode'];
$bindings[] = $postdata['mode'];
}
$sql .= $this->genfunctions->addBandToQuery($band, $bindings);
$sql .= $this->addContinentsToQuery($postdata);
$sql .= $this->addOrbitToQuery($postdata, $bindings);
$sql .= " ) AS s
) AS t
) as x";
if (!empty($bindings)) {
$query = $this->db->query($sql, $bindings);
} else {
$query = $this->db->query($sql);
}
return $query->result();
}
function getWpxForBandConfirmed($band, $location_list, $postdata) {
$bindings=[];
$sql = "select count(distinct wpx_prefix) wpxcount from (
SELECT
col_call,
CASE
/* case 1: /digit suffix → handle multi-digit prefixes correctly */
WHEN col_call REGEXP '/[0-9]$' THEN
CASE
/* If prefix has multiple digits, replace the last digit */
WHEN SUBSTRING_INDEX(col_call, '/', 1) REGEXP '^[0-9]?[A-Z]{1,3}[0-9]{2,}' THEN
CONCAT(
REGEXP_REPLACE(
SUBSTRING_INDEX(col_call, '/', 1),
'^([0-9]?[A-Z]{1,3}[0-9]*)[0-9].*$',
'\\\\1'
),
SUBSTRING_INDEX(col_call, '/', -1)
)
/* If prefix has single digit, replace it */
ELSE
CONCAT(
REGEXP_REPLACE(
SUBSTRING_INDEX(col_call, '/', 1),
'^([0-9]?[A-Z]{1,3})[0-9].*$',
'\\\\1'
),
SUBSTRING_INDEX(col_call, '/', -1)
)
END
/* case 2: no digit at all → append 0 */
WHEN call_core NOT REGEXP '[A-Z][0-9]' THEN CONCAT(call_core, '0')
/* case 3: normal/anniversary calls → keep prefix+digits */
ELSE
REGEXP_REPLACE(call_core, '^([0-9]?[A-Z]{1,3}[0-9]{1,4}).*$', '\\\\1')
END AS wpx_prefix
FROM (
SELECT
col_call,
CASE
WHEN num_slashes >= 2 THEN left_part
WHEN num_slashes = 1 AND NOT (call_raw REGEXP '/[0-9]$') THEN
CASE
WHEN (left_has_digit + left_short) > (right_has_digit + right_short) THEN left_part
WHEN (left_has_digit + left_short) < (right_has_digit + right_short) THEN right_part
ELSE left_part
END
ELSE call_raw
END AS call_core
FROM (
SELECT
col_call,
UPPER(TRIM(col_call)) AS call_raw,
(LENGTH(UPPER(TRIM(col_call))) - LENGTH(REPLACE(UPPER(TRIM(col_call)), '/', ''))) AS num_slashes,
SUBSTRING_INDEX(UPPER(TRIM(col_call)), '/', 1) AS left_part,
SUBSTRING_INDEX(UPPER(TRIM(col_call)), '/', -1) AS right_part,
(SUBSTRING_INDEX(UPPER(TRIM(col_call)), '/', 1) REGEXP '[0-9]') AS left_has_digit,
(SUBSTRING_INDEX(UPPER(TRIM(col_call)), '/', -1) REGEXP '[0-9]') AS right_has_digit,
(LENGTH(SUBSTRING_INDEX(UPPER(TRIM(col_call)), '/', 1)) <= 3) AS left_short,
(LENGTH(SUBSTRING_INDEX(UPPER(TRIM(col_call)), '/', -1)) <= 3) AS right_short
FROM ".$this->config->item('table_name')." thcv
left join satellite on thcv.COL_SAT_NAME = satellite.name
WHERE station_id in (" . $location_list . ") ";
$sql .= $this->genfunctions->addQslToQuery($postdata);
$sql .= $this->genfunctions->addBandToQuery($band, $bindings);
$sql .= $this->addContinentsToQuery($postdata);
if ($postdata['mode'] != 'All') {
$sql .= " and (col_mode = ? or col_submode = ?)";
$bindings[]=$postdata['mode'];
$bindings[]=$postdata['mode'];
}
$sql .= $this->addContinentsToQuery($postdata);
$sql .= $this->addOrbitToQuery($postdata,$bindings);
$sql .= " ) AS s
) AS t
) as x";
if (!empty($bindings)) {
$query = $this->db->query($sql, $bindings);
} else {
$query = $this->db->query($sql);
}
return $query->result();
}
// Made function instead of repeating this several times
function addContinentsToQuery($postdata) {
$sql = '';
if ($postdata['Africa'] == NULL) {
$sql .= " and col_cont <> 'AF'";
}
if ($postdata['Europe'] == NULL) {
$sql .= " and col_cont <> 'EU'";
}
if ($postdata['Asia'] == NULL) {
$sql .= " and col_cont <> 'AS'";
}
if ($postdata['SouthAmerica'] == NULL) {
$sql .= " and col_cont <> 'SA'";
}
if ($postdata['NorthAmerica'] == NULL) {
$sql .= " and col_cont <> 'NA'";
}
if ($postdata['Oceania'] == NULL) {
$sql .= " and col_cont <> 'OC'";
}
if ($postdata['Antarctica'] == NULL) {
$sql .= " and col_cont <> 'AN'";
}
if (strlen($sql) > 0) {
$sql .= " and col_cont <> '' and col_cont IS NOT NULL";
}
return $sql;
}
// Adds orbit type to query
function addOrbitToQuery($postdata,&$binding) {
$sql = '';
if ($postdata['orbit'] != 'All') {
$sql .= ' AND satellite.orbit = ?';
$binding[]=$postdata['orbit'];
}
return $sql;
}
public function get_band_details($band, $status)
{
$this->db->select('col_call, col_time_on, col_mode, col_qsl_rcvd, col_lotw_qsl_rcvd, col_eqsl_qsl_rcvd');
$this->db->from($this->config->item('table_name') . ' thcv');
$station_id = $this->session->userdata('active_station_logbook');
if (is_array($station_id)) {
$this->db->where_in('station_id', $station_id);
} else {
$this->db->where('station_id', $station_id);
}
// filter by band (skip if "Total")
if ($band !== 'Total') {
$this->db->where('col_band', $band);
}
// filter by status
if ($status === 'confirmed') {
$this->db->where("(col_qsl_rcvd = 'Y' OR col_lotw_qsl_rcvd = 'Y' OR col_eqsl_qsl_rcvd = 'Y')", null, false);
}
$this->db->order_by('col_time_on', 'DESC');
$query = $this->db->get();
return $query->result();
}
function getWpxBandDetails($postdata) {
$this->load->model('logbooks_model');
$logbooks_locations_array = $this->logbooks_model->list_logbook_relationships($this->session->userdata('active_station_logbook'));
if (!$logbooks_locations_array) {
return null;
}
$location_list = "'".implode("','",$logbooks_locations_array)."'";
$bindings = [];
$sql = "select wpx_prefix, col_call, col_time_on, col_band, col_mode, col_submode,
col_lotw_qsl_rcvd, col_qsl_rcvd, col_eqsl_qsl_rcvd, COL_QRZCOM_QSO_DOWNLOAD_STATUS, COL_CLUBLOG_QSO_DOWNLOAD_STATUS
from (
select wpx_prefix, col_call, col_time_on, col_band, col_mode, col_submode,
col_lotw_qsl_rcvd, col_qsl_rcvd, col_eqsl_qsl_rcvd, COL_QRZCOM_QSO_DOWNLOAD_STATUS, COL_CLUBLOG_QSO_DOWNLOAD_STATUS,
ROW_NUMBER() OVER (
PARTITION BY wpx_prefix
ORDER BY
/* Prioritize confirmed contacts first */
CASE
WHEN col_lotw_qsl_rcvd = 'Y' OR
col_qsl_rcvd = 'Y' OR
col_eqsl_qsl_rcvd = 'Y' OR
COL_QRZCOM_QSO_DOWNLOAD_STATUS = 'Y' OR
COL_CLUBLOG_QSO_DOWNLOAD_STATUS = 'Y'
THEN 0
ELSE 1
END,
/* Then by time */
col_time_on ASC
) as rn from (
SELECT col_call, col_time_on, col_band, col_mode, col_submode,
col_lotw_qsl_rcvd, col_qsl_rcvd, col_eqsl_qsl_rcvd, COL_QRZCOM_QSO_DOWNLOAD_STATUS, COL_CLUBLOG_QSO_DOWNLOAD_STATUS,
CASE
/* case 1: /digit suffix → handle multi-digit prefixes correctly */
WHEN col_call REGEXP '/[0-9]$' THEN
CASE
/* If prefix has multiple digits, replace the last digit */
WHEN SUBSTRING_INDEX(col_call, '/', 1) REGEXP '^[0-9]?[A-Z]{1,3}[0-9]{2,}' THEN
CONCAT(
REGEXP_REPLACE(
SUBSTRING_INDEX(col_call, '/', 1),
'^([0-9]?[A-Z]{1,3}[0-9]*)[0-9].*$',
'\\\\1'
),
SUBSTRING_INDEX(col_call, '/', -1)
)
/* If prefix has single digit, replace it */
ELSE
CONCAT(
REGEXP_REPLACE(
SUBSTRING_INDEX(col_call, '/', 1),
'^([0-9]?[A-Z]{1,3})[0-9].*$',
'\\\\1'
),
SUBSTRING_INDEX(col_call, '/', -1)
)
END
/* case 2: no digit at all → append 0 */
WHEN call_core NOT REGEXP '[A-Z][0-9]' THEN CONCAT(call_core, '0')
/* case 3: normal/anniversary calls → keep prefix+digits */
ELSE
REGEXP_REPLACE(call_core, '^([0-9]?[A-Z]{1,3}[0-9]{1,4}).*$', '\\\\1')
END AS wpx_prefix
FROM (
SELECT
col_call, col_time_on, col_band, col_mode, col_submode,
col_lotw_qsl_rcvd, col_qsl_rcvd, col_eqsl_qsl_rcvd, COL_QRZCOM_QSO_DOWNLOAD_STATUS, COL_CLUBLOG_QSO_DOWNLOAD_STATUS,
CASE
WHEN num_slashes >= 2 THEN left_part
WHEN num_slashes = 1 AND NOT (call_raw REGEXP '/[0-9]$') THEN
CASE
WHEN (left_has_digit + left_short) > (right_has_digit + right_short) THEN left_part
WHEN (left_has_digit + left_short) < (right_has_digit + right_short) THEN right_part
ELSE left_part
END
ELSE call_raw
END AS call_core
FROM (
SELECT
col_call, col_time_on, col_band, col_mode, col_submode, col_lotw_qsl_rcvd, col_qsl_rcvd, col_eqsl_qsl_rcvd, COL_QRZCOM_QSO_DOWNLOAD_STATUS, COL_CLUBLOG_QSO_DOWNLOAD_STATUS,
UPPER(TRIM(col_call)) AS call_raw,
(LENGTH(UPPER(TRIM(col_call))) - LENGTH(REPLACE(UPPER(TRIM(col_call)), '/', ''))) AS num_slashes,
SUBSTRING_INDEX(UPPER(TRIM(col_call)), '/', 1) AS left_part,
SUBSTRING_INDEX(UPPER(TRIM(col_call)), '/', -1) AS right_part,
(SUBSTRING_INDEX(UPPER(TRIM(col_call)), '/', 1) REGEXP '[0-9]') AS left_has_digit,
(SUBSTRING_INDEX(UPPER(TRIM(col_call)), '/', -1) REGEXP '[0-9]') AS right_has_digit,
(LENGTH(SUBSTRING_INDEX(UPPER(TRIM(col_call)), '/', 1)) <= 3) AS left_short,
(LENGTH(SUBSTRING_INDEX(UPPER(TRIM(col_call)), '/', -1)) <= 3) AS right_short
FROM ".$this->config->item('table_name')." thcv
LEFT JOIN satellite on thcv.COL_SAT_NAME = satellite.name
WHERE station_id in (" . $location_list . ") ";
if ($postdata['mode'] != 'All') {
$sql .= " and (col_mode = ? or col_submode = ?)";
$bindings[] = $postdata['mode'];
$bindings[] = $postdata['mode'];
}
// filter by band (skip if "Total")
if ($postdata['band'] !== 'Total') {
$sql .= $this->genfunctions->addBandToQuery($postdata['band'], $bindings);
}
if ($postdata['status'] === 'confirmed') {
$sql .= $this->addQslToQuery($postdata);
}
$sql .= $this->addContinentsToQuery($postdata);
$sql .= " ) AS s
) AS t
) as x
) as ranked
WHERE rn = 1
ORDER BY wpx_prefix";
if (!empty($bindings)) {
$query = $this->db->query($sql, $bindings);
} else {
$query = $this->db->query($sql);
}
return $query->result();
}
function addQslToQuery($postdata) {
$sql = '';
$qsl = array();
if ( (($postdata['clublog'] ?? '') != '') ||
(($postdata['qrz'] ?? '') != '') ||
(($postdata['lotw'] ?? '') != '') ||
(($postdata['qsl'] ?? '') != '') ||
(($postdata['dcl'] ?? '') != '') ||
(($postdata['eqsl'] ?? '') != '') ) {
$sql .= ' and (';
if (($postdata['qsl'] ?? '') != '') {
array_push($qsl, "col_qsl_rcvd = 'Y'");
}
if (($postdata['lotw'] ?? '') != '') {
array_push($qsl, "col_lotw_qsl_rcvd = 'Y'");
}
if (($postdata['eqsl'] ?? '') != '') {
array_push($qsl, "col_eqsl_qsl_rcvd = 'Y'");
}
if (($postdata['qrz'] ?? '') != '') {
array_push($qsl, "COL_QRZCOM_QSO_DOWNLOAD_STATUS = 'Y'");
}
if (($postdata['clublog'] ?? '') != '') {
array_push($qsl, "COL_CLUBLOG_QSO_DOWNLOAD_STATUS = 'Y'");
}
if (($postdata['dcl'] ?? '') != '') {
array_push($qsl, "COL_DCL_QSL_RCVD = 'Y'");
}
if (count($qsl) > 0) {
$sql .= implode(' or ', $qsl);
} else {
$sql .= '1=0';
}
$sql .= ')';
} else {
$sql.=' and 1=0';
}
return $sql;
}
}
?>

View File

@@ -0,0 +1,233 @@
<div class="container">
<!-- Award Info Box -->
<br>
<div id="awardInfoButton">
<h2><?php echo $page_title; ?></h2>
</div>
<!-- End of Award Info Box -->
<form method="post" enctype="multipart/form-data">
<div class="mb-4 text-center">
<div class="dropdown" data-bs-auto-close="outside">
<button id="button1id" type="submit" name="button1id" class="btn btn-sm btn-primary"><?= __("Show"); ?></button>
<button class="btn btn-sm btn-primary dropdown-toggle" type="button" id="filterDropdown" data-bs-toggle="dropdown" aria-expanded="false"><?= __("Filters") ?></button>
<!-- Dropdown Menu with Filter Content -->
<div class="dropdown-menu start-50 translate-middle-x p-3 mt-5" aria-labelledby="filterDropdown" style="min-width: 250px;">
<div class="card-body filterbody">
<div class="row">
<div class="col-md-6">
<!-- QSL Types Card -->
<div class="card mb-3">
<div class="card-header"><?= __("Show QSO with QSL Type") ?></div>
<div class="card-body">
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" name="qsl" value="1" id="qsl" <?php if ($this->input->post('qsl') || $this->input->method() !== 'post') echo ' checked="checked"'; ?> >
<label class="form-check-label" for="qsl"><?= __("QSL"); ?></label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" name="lotw" value="1" id="lotw" <?php if ($this->input->post('lotw') || $this->input->method() !== 'post') echo ' checked="checked"'; ?> >
<label class="form-check-label" for="lotw"><?= __("LoTW"); ?></label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" name="eqsl" value="1" id="eqsl" <?php if ($this->input->post('eqsl')) echo ' checked="checked"'; ?> >
<label class="form-check-label" for="eqsl"><?= __("eQSL"); ?></label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" name="qrz" value="1" id="qrz" <?php if ($this->input->post('qrz')) echo ' checked="checked"'; ?> >
<label class="form-check-label" for="qrz"><?= __("QRZ.com"); ?></label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" name="clublog" value="1" id="clublog" <?php if ($this->input->post('clublog')) echo ' checked="checked"'; ?> >
<label class="form-check-label" for="clublog"><?= __("Clublog"); ?></label>
</div>
</div>
</div>
<!-- Continents Card -->
<div class="card mb-3">
<div class="card-header"><?= __("Continents") ?></div>
<div class="card-body">
<?php
$continents = [
"Antarctica" => __("Antarctica"),
"Africa" => __("Africa"),
"Asia" => __("Asia"),
"Europe" => __("Europe"),
"NorthAmerica" => __("North America"),
"SouthAmerica" => __("South America"),
"Oceania" => __("Oceania"),
];
foreach ($continents as $key => $label) { ?>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" name="<?= $key ?>" id="<?= $key ?>" value="1" <?php if ($this->input->post($key) || $this->input->method() !== 'post') echo ' checked="checked"'; ?> >
<label class="form-check-label" for="<?= $key ?>"><?= $label ?></label>
</div>
<?php } ?>
</div>
</div>
</div>
<div class="col-md-6">
<!-- Band/Satellite/Orbit Card -->
<div class="card mb-3">
<div class="card-header"><?= __("Band / Satellite / Orbit") ?></div>
<div class="card-body">
<div class="mb-3">
<label class="form-label" for="band2"><?= __("Band"); ?></label>
<select id="band2" name="band" class="form-select form-select-sm">
<option value="All" <?php if ($this->input->post('band') == "All" || $this->input->method() !== 'post') echo ' selected'; ?> ><?= __("Every band (w/o SAT)"); ?></option>
<?php foreach($worked_bands as $band) {
echo '<option value="' . $band . '"';
if ($this->input->post('band') == $band) echo ' selected';
echo '>' . $band . '</option>'."\n";
} ?>
</select>
</div>
<div id="satrow" class="mb-3" <?php if ($this->input->post('band') != 'SAT' && $this->input->post('band') != 'All') echo "style=\"display: none\""; ?>>
<?php if (count($sats_available) != 0) { ?>
<label class="form-label" id="satslabel" for="sats"><?= __("Satellite"); ?></label>
<select class="form-select form-select-sm" id="sats" name="sats">
<option value="All" <?php if ($this->input->post('sats') == "All" || $this->input->method() !== 'post') echo ' selected'; ?>><?= __("All")?></option>
<?php foreach($sats_available as $sat) {
echo '<option value="' . $sat . '"';
if ($this->input->post('sats') == $sat) echo ' selected';
echo '>' . $sat . '</option>'."\n";
} ?>
</select>
<?php } else { ?>
<input id="sats" type="hidden" value="All"></input>
<?php } ?>
</div>
<div id="orbitrow" class="mb-3" <?php if ($this->input->post('band') != 'SAT' && $this->input->post('band') != 'All') echo "style=\"display: none\""; ?>>
<label class="form-label" id="orbitslabel" for="orbits"><?= __("Orbit"); ?></label>
<select class="form-select form-select-sm" id="orbits" name="orbits">
<option value="All" <?php if ($this->input->post('orbits') == "All" || $this->input->method() !== 'post') echo ' selected'; ?>><?= __("All")?></option>
<?php
foreach($orbits as $orbit){
echo '<option value="' . $orbit . '"';
if ($this->input->post('orbits') == $orbit) echo ' selected';
echo '>' . strtoupper($orbit) . '</option>'."\n";
}
?>
</select>
</div>
</div>
</div>
<!-- Mode Card -->
<div class="card mb-3">
<div class="card-header"><?= __("Mode") ?></div>
<div class="card-body">
<label class="form-label" for="mode"><?= __("Mode"); ?></label>
<select id="mode" name="mode" class="form-select form-select-sm">
<option value="All" <?php if ($this->input->post('mode') == "All" || $this->input->method() !== 'mode') echo ' selected'; ?>><?= __("All"); ?></option>
<?php
foreach($modes->result() as $mode){
if ($mode->submode == null) {
echo '<option value="' . $mode->mode . '"';
if ($this->input->post('mode') == $mode->mode) echo ' selected';
echo '>'. $mode->mode . '</option>'."\n";
} else {
echo '<option value="' . $mode->submode . '"';
if ($this->input->post('mode') == $mode->submode) echo ' selected';
echo '>' . $mode->submode . '</option>'."\n";
}
}
?>
</select>
</div>
</div>
</div>
</div>
</div>
<div class="mb-4 text-center">
<button id="button2id" type="reset" name="button2id" class="btn btn-sm btn-warning"><?= __("Reset"); ?></button>
</div>
</div>
</div>
</div>
</form>
<!-- End Filtering Parent Card -->
<?php
if ($wpx_array) {
echo '<h2>' . __("Summary") . '</h2>
<table class="table-sm tablesummary table table-bordered table-hover table-striped table-condensed text-center">
<thead>
<tr><td></td>';
$addsat = '';
foreach ($bands as $band) {
if ($band != 'SAT') {
echo '<td>' . $band . '</td>';
} else {
$addsat = '<td>' . $band . '</td>';
}
}
echo '<td><b>' . __("Total") . '</b></td>';
if (count($bands) > 1) {
echo '<td class="spacingcell"></td>';
}
echo $addsat;
echo '
</tr>
</thead>
<tbody>';
// ---- Worked row ----
echo '<tr><td>' . __("Total worked") . '</td>';
$addsat = '';
foreach ($wpx_array['worked'] as $band => $value) {
if ($band != 'SAT') {
echo '<td style="text-align: center">';
echo '<a href=\'javascript:wpxLoadDetails("worked", "' . $band . '")\'>' . $value . '</a>';
echo '</td>';
} else {
$addsat = '<td style="text-align: center">' . $value . '</td>';
}
}
if (count($bands) > 1) {
echo '<td class="spacingcell"></td>';
}
if ($addsat != '' && count($wpx_array['worked']) > 1) {
echo $addsat;
}
echo '</tr>';
// ---- Confirmed row ----
echo '<tr><td>' . __("Total confirmed") . '</td>';
$addsat = '';
foreach ($wpx_array['confirmed'] as $band => $value) {
if ($band != 'SAT') {
echo '<td style="text-align: center">';
echo '<a href=\'javascript:wpxLoadDetails("confirmed", "' . $band . '")\'>' . $value . '</a>';
echo '</td>';
} else {
$addsat = '<td style="text-align: center">' . $value . '</td>';
}
}
if (count($bands) > 1) {
echo '<td class="spacingcell"></td>';
}
if ($addsat != '' && count($wpx_array['confirmed']) > 1) {
echo $addsat;
}
echo '</tr>';
echo '</table>';
echo '<div class="showWpxResults mt-3"></div>';
} else {
echo '<div class="alert alert-danger" role="alert">' . __("Nothing found!") . '</div>';
}
?>
</div>

View File

@@ -0,0 +1,60 @@
<h3><?php echo sprintf("%s %s", ucfirst($status), $band); ?></h3>
<?php
if ($this->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/wavelog.php
$custom_date_format = $this->config->item('qso_date_format');
}
$i = 1;
if (!empty($results)): ?>
<table class="table wpxdetails table-sm table-bordered table-striped text-center">
<thead>
<tr>
<th>#</th>
<th><?= __("WPX"); ?></th>
<th><?= __("Callsign"); ?></th>
<th><?= __("QSO Date"); ?></th>
<th><?= __("Band"); ?></th>
<th><?= __("Mode"); ?></th>
<td><?= __("Confirmed"); ?></td>
</tr>
</thead>
<tbody>
<?php foreach ($results as $qso):
$qsotimestamp = strtotime($qso->col_time_on);
?>
<tr>
<td><?php echo $i++; ?></td>
<td><?php echo $qso->wpx_prefix; ?></td>
<td><?php echo $qso->col_call; ?></td>
<td><?php echo date($custom_date_format, $qsotimestamp) . ' ' . date('H:i', $qsotimestamp); ?></td>
<td><?php echo $qso->col_band; ?></td>
<td><?php echo $qso->col_submode ?? $qso->col_mode; ?></td>
<td><?php echo cf_type($qso->col_qsl_rcvd, $qso->col_lotw_qsl_rcvd, $qso->col_eqsl_qsl_rcvd, $qso->COL_QRZCOM_QSO_DOWNLOAD_STATUS, $qso->COL_CLUBLOG_QSO_DOWNLOAD_STATUS); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php else: ?>
<div class="alert alert-warning">No QSOs found for <?php echo $band; ?>.</div>
<?php endif;
function cf_type($qsl, $lotw, $eqsl, $qrz, $clublog) {
$string = '';
if ((($qsl ?? 'N') == 'Y')) { $string.= 'Q'; }
if ((($lotw ?? 'N') == 'Y')) { $string.= 'L'; }
if ((($eqsl ?? 'N') == 'Y')) { $string.= 'E'; }
if ((($qrz ?? 'N') == 'Y')) { $string.= 'Z'; }
if ((($clublog ?? 'N') == 'Y')) { $string.= 'C'; }
if ($string == '') { return '<div class="bg-danger awardsBgDanger">-</div>'; }
return '<div class="bg-success awardsBgSuccess">' . $string . '</div>';
}
?>

View File

@@ -1867,7 +1867,7 @@ $(document).ready(function(){
<script src="<?php echo base_url(); ?>assets/js/sections/webadif.js"></script>
<?php } ?>
<?php if ($this->uri->segment(2) == "dxcc" || $this->uri->segment(2) == "wae") { ?>
<?php if ($this->uri->segment(2) == "dxcc" || $this->uri->segment(2) == "wae" || $this->uri->segment(2) == "wpx") { ?>
<script>
$('.tabledxcc').DataTable({
"pageLength": 25,
@@ -1884,7 +1884,7 @@ $(document).ready(function(){
buttons: [
{
extend: 'csv',
className: 'mb-1 btn btn-primary', // Bootstrap classes
className: 'mb-1 btn btn-sm btn-primary', // Bootstrap classes
init: function(api, node, config) {
$(node).removeClass('dt-button').addClass('btn btn-primary'); // Ensure Bootstrap class applies
},
@@ -1907,7 +1907,7 @@ $(document).ready(function(){
buttons: [
{
extend: 'csv',
className: 'mb-1 btn btn-primary', // Bootstrap classes
className: 'mb-1 btn btn-sm btn-primary', // Bootstrap classes
init: function(api, node, config) {
$(node).removeClass('dt-button').addClass('btn btn-primary'); // Ensure Bootstrap class applies
},
@@ -1921,7 +1921,7 @@ $(document).ready(function(){
}
</script>
<?php } ?>
<?php if ($this->uri->segment(2) == "wae") { ?>
<?php if ($this->uri->segment(2) == "wae" || $this->uri->segment(2) == "wpx") { ?>
<script>
$('#band2').change(function(){
var band = $("#band2 option:selected").text();
@@ -1985,7 +1985,7 @@ $('#sats').change(function(){
buttons: [
{
extend: 'csv',
className: 'mb-1 btn btn-primary', // Bootstrap classes
className: 'mb-1 btn-sm btn btn-primary', // Bootstrap classes
init: function(api, node, config) {
$(node).removeClass('dt-button').addClass('btn btn-primary'); // Ensure Bootstrap class applies
},
@@ -2017,7 +2017,7 @@ $('#sats').change(function(){
buttons: [
{
extend: 'csv',
className: 'mb-1 btn btn-primary', // Bootstrap classes
className: 'mb-1 btn btn-sm btn-primary', // Bootstrap classes
init: function(api, node, config) {
$(node).removeClass('dt-button').addClass('btn btn-primary'); // Ensure Bootstrap class applies
},
@@ -2040,7 +2040,7 @@ $('#sats').change(function(){
buttons: [
{
extend: 'csv',
className: 'mb-1 btn btn-primary', // Bootstrap classes
className: 'mb-1 btn btn-sm btn-primary', // Bootstrap classes
init: function(api, node, config) {
$(node).removeClass('dt-button').addClass('btn btn-primary'); // Ensure Bootstrap class applies
},
@@ -2072,7 +2072,7 @@ $('#sats').change(function(){
buttons: [
{
extend: 'csv',
className: 'mb-1 btn btn-primary', // Bootstrap classes
className: 'mb-1 btn btn-sm btn-primary', // Bootstrap classes
init: function(api, node, config) {
$(node).removeClass('dt-button').addClass('btn btn-primary'); // Ensure Bootstrap class applies
},
@@ -2095,7 +2095,7 @@ $('#sats').change(function(){
buttons: [
{
extend: 'csv',
className: 'mb-1 btn btn-primary', // Bootstrap classes
className: 'mb-1 btn btn-sm btn-primary', // Bootstrap classes
init: function(api, node, config) {
$(node).removeClass('dt-button').addClass('btn btn-primary'); // Ensure Bootstrap class applies
},

View File

@@ -189,6 +189,8 @@
<div class="dropdown-divider"></div>
<li><a class="dropdown-item" href="<?php echo site_url('awards/wac'); ?>"><i class="fas fa-trophy"></i> <?= __("Worked All Continents (WAC)"); ?></a></li>
<div class="dropdown-divider"></div>
<li><a class="dropdown-item" href="<?php echo site_url('awards/wpx'); ?>"><i class="fas fa-trophy"></i> <?= __("Worked All Prefixes (WPX)"); ?></a></li>
<div class="dropdown-divider"></div>
<li><a class="dropdown-item" href="<?php echo site_url('awards/wwff'); ?>"><i class="fas fa-trophy"></i> <?= __("WWFF"); ?></a></li>
</ul>
</li>

68
assets/js/sections/wpx.js Normal file
View File

@@ -0,0 +1,68 @@
document.addEventListener("DOMContentLoaded", function() {
document.querySelectorAll('.dropdown').forEach(dd => {
dd.addEventListener('hide.bs.dropdown', function (e) {
if (e.clickEvent && e.clickEvent.target.closest('.dropdown-menu')) {
e.preventDefault(); // stop Bootstrap from closing
}
});
});
});
function wpxLoadDetails(status, band) {
$('.showWpxResults').empty();
$.ajax({
url: site_url + '/awards/wpx_details',
type: 'post',
data: {
band: band,
mode: $('#mode').val(),
status: status,
sats: $('#sats').is(':checked') ? 1 : 0,
orbit: $('#orbit').is(':checked') ? 1 : 0,
Asia: $('#Asia').is(':checked') ? 1 : 0,
Africa: $('#Africa').is(':checked') ? 1 : 0,
NorthAmerica: $('#NorthAmerica').is(':checked') ? 1 : 0,
SouthAmerica: $('#SouthAmerica').is(':checked') ? 1 : 0,
Antarctica: $('#Antarctica').is(':checked') ? 1 : 0,
Europe: $('#Europe').is(':checked') ? 1 : 0,
Oceania: $('#Oceania').is(':checked') ? 1 : 0,
qsl: $('#qsl').is(':checked') ? 1 : 0,
lotw: $('#lotw').is(':checked') ? 1 : 0,
eqsl: $('#eqsl').is(':checked') ? 1 : 0,
qrz: $('#qrz').is(':checked') ? 1 : 0,
clublog: $('#clublog').is(':checked') ? 1 : 0,
},
type: 'post',
success: function (html) {
$('.showWpxResults').html(html);
$('.wpxdetails').DataTable({
"pageLength": 25,
responsive: false,
ordering: false,
"scrollY": "400px",
"scrollCollapse": true,
"paging": false,
"scrollX": true,
"language": {
url: getDataTablesLanguageUrl(),
},
dom: 'Bfrtip',
buttons: [
{
extend: 'csv',
className: 'mb-1 btn btn-sm btn-primary', // Bootstrap classes
init: function(api, node, config) {
$(node).removeClass('dt-button').addClass('btn btn-primary'); // Ensure Bootstrap class applies
},
}
]
});
// change color of csv-button if dark mode is chosen
if (isDarkModeTheme()) {
$(".buttons-csv").css("color", "white");
}
},
error: function (data) {
},
});
}