2022-10-05 22:13:12 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
class Pota extends CI_Model {
|
|
|
|
|
|
2026-03-24 14:32:17 +00:00
|
|
|
public function split_refs($value) {
|
|
|
|
|
if ($value === null || $value === '') {
|
|
|
|
|
return [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$parts = preg_split('/\s*,\s*/', strtoupper(trim((string)$value)));
|
|
|
|
|
$parts = array_filter($parts, static function($part) {
|
|
|
|
|
return $part !== '';
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return array_values(array_unique($parts));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function collect_refs_from_rows($rows) {
|
|
|
|
|
$refs = [];
|
|
|
|
|
foreach ($rows as $row) {
|
|
|
|
|
foreach ($this->split_refs($row->COL_POTA_REF ?? '') as $ref) {
|
|
|
|
|
$refs[$ref] = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return array_keys($refs);
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-10 15:08:22 +00:00
|
|
|
// Existing method used by current simple table
|
2022-10-05 22:13:12 +02:00
|
|
|
function get_all() {
|
|
|
|
|
$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) {
|
2026-01-10 15:08:22 +00:00
|
|
|
return null;
|
|
|
|
|
}
|
2022-10-05 22:13:12 +02:00
|
|
|
|
|
|
|
|
$this->load->model('bands');
|
|
|
|
|
|
|
|
|
|
$bandslots = $this->bands->get_worked_bands('pota');
|
|
|
|
|
|
2023-06-29 13:50:55 +02:00
|
|
|
if(!$bandslots) return null;
|
|
|
|
|
|
2022-10-05 22:13:12 +02:00
|
|
|
$this->db->where_in("station_id", $logbooks_locations_array);
|
|
|
|
|
$this->db->where_in("col_band", $bandslots);
|
|
|
|
|
$this->db->order_by("COL_POTA_REF", "ASC");
|
|
|
|
|
$this->db->where('COL_POTA_REF !=', '');
|
|
|
|
|
|
|
|
|
|
return $this->db->get($this->config->item('table_name'));
|
|
|
|
|
}
|
2026-01-10 15:08:22 +00:00
|
|
|
|
|
|
|
|
// New: generic filtered fetch for HTMX table
|
|
|
|
|
function fetch_qsos($filters) {
|
|
|
|
|
$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 [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$this->db->from($this->config->item('table_name'));
|
|
|
|
|
$this->db->where_in('station_id', $logbooks_locations_array);
|
|
|
|
|
$this->db->where('COL_POTA_REF !=', '');
|
|
|
|
|
|
|
|
|
|
$this->apply_filters($filters);
|
|
|
|
|
|
|
|
|
|
$this->db->order_by('COL_TIME_ON', 'DESC');
|
|
|
|
|
$query = $this->db->get();
|
|
|
|
|
return $query->result();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// New: first and last QSO timestamps/refs within filters
|
|
|
|
|
function get_first_last($filters) {
|
|
|
|
|
$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 ['first'=>null,'last'=>null];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// first
|
|
|
|
|
$this->db->from($this->config->item('table_name'));
|
|
|
|
|
$this->db->where_in('station_id', $logbooks_locations_array);
|
|
|
|
|
$this->db->where('COL_POTA_REF !=', '');
|
|
|
|
|
$this->apply_filters($filters);
|
|
|
|
|
$this->db->order_by('COL_TIME_ON', 'ASC');
|
|
|
|
|
$this->db->limit(1);
|
|
|
|
|
$first = $this->db->get()->row();
|
|
|
|
|
|
|
|
|
|
// last
|
|
|
|
|
$this->db->from($this->config->item('table_name'));
|
|
|
|
|
$this->db->where_in('station_id', $logbooks_locations_array);
|
|
|
|
|
$this->db->where('COL_POTA_REF !=', '');
|
|
|
|
|
$this->apply_filters($filters);
|
|
|
|
|
$this->db->order_by('COL_TIME_ON', 'DESC');
|
|
|
|
|
$this->db->limit(1);
|
|
|
|
|
$last = $this->db->get()->row();
|
|
|
|
|
|
|
|
|
|
return ['first'=>$first, 'last'=>$last];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// New: unique parks and optionally by band/mode
|
|
|
|
|
function get_uniques($filters, $by = null) {
|
|
|
|
|
$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 [];
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-24 14:32:17 +00:00
|
|
|
$this->db->select('COL_POTA_REF, COL_BAND, COL_MODE, COL_SUBMODE');
|
2026-01-10 15:08:22 +00:00
|
|
|
$this->db->from($this->config->item('table_name'));
|
|
|
|
|
$this->db->where_in('station_id', $logbooks_locations_array);
|
|
|
|
|
$this->db->where('COL_POTA_REF !=', '');
|
|
|
|
|
$this->apply_filters($filters);
|
|
|
|
|
|
2026-03-24 14:32:17 +00:00
|
|
|
$rows = $this->db->get()->result();
|
2026-01-10 15:08:22 +00:00
|
|
|
|
|
|
|
|
if (!$by) {
|
2026-03-24 14:32:17 +00:00
|
|
|
return count($this->collect_refs_from_rows($rows));
|
2026-01-10 15:08:22 +00:00
|
|
|
}
|
2026-03-24 14:32:17 +00:00
|
|
|
|
2026-01-10 15:08:22 +00:00
|
|
|
$out = [];
|
2026-03-24 14:32:17 +00:00
|
|
|
foreach ($rows as $row) {
|
|
|
|
|
$key = $by === 'band'
|
|
|
|
|
? $row->COL_BAND
|
|
|
|
|
: (($row->COL_SUBMODE !== null && $row->COL_SUBMODE !== '') ? $row->COL_SUBMODE : $row->COL_MODE);
|
|
|
|
|
|
|
|
|
|
if (!isset($out[$key])) {
|
|
|
|
|
$out[$key] = [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach ($this->split_refs($row->COL_POTA_REF) as $ref) {
|
|
|
|
|
$out[$key][$ref] = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach ($out as $key => $refs) {
|
|
|
|
|
$out[$key] = count($refs);
|
2026-01-10 15:08:22 +00:00
|
|
|
}
|
2026-03-24 14:32:17 +00:00
|
|
|
|
2026-01-10 15:08:22 +00:00
|
|
|
return $out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// New: confirmation counts
|
|
|
|
|
function get_confirmations($filters) {
|
|
|
|
|
$filtersConfirmed = $filters;
|
|
|
|
|
$filtersConfirmed['confirmed'] = true;
|
|
|
|
|
return $this->get_uniques($filtersConfirmed);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// New: read assets/json/pota_parks.csv and map refs to metadata
|
|
|
|
|
function get_parks_meta($refs) {
|
|
|
|
|
$refs = array_values(array_unique(array_filter($refs)));
|
|
|
|
|
if (empty($refs)) return [];
|
|
|
|
|
|
|
|
|
|
// Read only the needed refs from CSV to keep memory low
|
|
|
|
|
$out = $this->load_parks_subset($refs);
|
|
|
|
|
|
|
|
|
|
// If still missing coords, we skip map markers quietly
|
|
|
|
|
return $out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function load_parks_subset($wantedRefs) {
|
|
|
|
|
$path = FCPATH . 'assets/json/pota_parks.csv';
|
|
|
|
|
if (!file_exists($path)) return [];
|
|
|
|
|
|
|
|
|
|
$wantedSet = array_fill_keys($wantedRefs, true);
|
|
|
|
|
$found = [];
|
|
|
|
|
|
|
|
|
|
$fh = fopen($path, 'r');
|
|
|
|
|
if ($fh === false) return [];
|
|
|
|
|
|
|
|
|
|
$header = fgetcsv($fh);
|
|
|
|
|
if ($header === false) { fclose($fh); return []; }
|
|
|
|
|
$idx = $this->map_header_indices($header);
|
|
|
|
|
|
|
|
|
|
while (($cols = fgetcsv($fh)) !== false) {
|
|
|
|
|
if (!isset($cols[$idx['ref']])) continue;
|
|
|
|
|
$ref = trim($cols[$idx['ref']]);
|
|
|
|
|
if ($ref === '' || !isset($wantedSet[$ref])) continue;
|
|
|
|
|
|
|
|
|
|
$found[$ref] = [
|
|
|
|
|
'name' => $idx['name'] !== null && isset($cols[$idx['name']]) ? $cols[$idx['name']] : null,
|
|
|
|
|
'entity' => $idx['entity'] !== null && isset($cols[$idx['entity']]) ? $cols[$idx['entity']] : null,
|
|
|
|
|
'country' => $idx['country'] !== null && isset($cols[$idx['country']]) ? $cols[$idx['country']] : null,
|
|
|
|
|
'lat' => $idx['lat'] !== null && isset($cols[$idx['lat']]) ? floatval($cols[$idx['lat']]) : null,
|
|
|
|
|
'lon' => $idx['lon'] !== null && isset($cols[$idx['lon']]) ? floatval($cols[$idx['lon']]) : null,
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
// Early exit if we got all requested refs
|
|
|
|
|
if (count($found) === count($wantedSet)) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fclose($fh);
|
|
|
|
|
return $found;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function map_header_indices($header) {
|
|
|
|
|
$find = function($candidates) use ($header) {
|
|
|
|
|
foreach ($header as $i => $h) {
|
|
|
|
|
$hn = strtolower(trim($h));
|
|
|
|
|
foreach ($candidates as $cand) {
|
|
|
|
|
if ($hn === $cand) return $i;
|
|
|
|
|
if (strpos($hn, $cand) !== false) return $i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
};
|
|
|
|
|
// Try to detect columns by common names
|
|
|
|
|
$refIdx = $find(['ref','reference','park id','park','entity id']);
|
|
|
|
|
if ($refIdx === null) $refIdx = 0; // fallback to first column
|
|
|
|
|
return [
|
|
|
|
|
'ref' => $refIdx,
|
|
|
|
|
'name' => $find(['name','park name','designation']),
|
|
|
|
|
'entity' => $find(['entity','state','province','region']),
|
|
|
|
|
'country' => $find(['country','country code']),
|
|
|
|
|
'lat' => $find(['lat','latitude']),
|
|
|
|
|
'lon' => $find(['lon','longitude','lng']),
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function apply_filters($filters) {
|
|
|
|
|
// Date range
|
|
|
|
|
if (!empty($filters['from'])) {
|
|
|
|
|
$this->db->where('COL_TIME_ON >=', $filters['from'] . ' 00:00:00');
|
|
|
|
|
}
|
|
|
|
|
if (!empty($filters['to'])) {
|
|
|
|
|
$this->db->where('COL_TIME_ON <=', $filters['to'] . ' 23:59:59');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Band / SAT
|
|
|
|
|
if (!empty($filters['band']) && $filters['band'] !== 'All') {
|
|
|
|
|
if ($filters['band'] === 'SAT') {
|
|
|
|
|
$this->db->where('COL_PROP_MODE', 'SAT');
|
|
|
|
|
} else {
|
|
|
|
|
$this->db->where('(COL_PROP_MODE IS NULL OR COL_PROP_MODE <> "SAT")', null, false);
|
|
|
|
|
$this->db->where('COL_BAND', $filters['band']);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Mode
|
|
|
|
|
if (!empty($filters['mode']) && $filters['mode'] !== 'All') {
|
|
|
|
|
$this->db->group_start();
|
|
|
|
|
$this->db->where('COL_MODE', $filters['mode']);
|
|
|
|
|
$this->db->or_where('COL_SUBMODE', $filters['mode']);
|
|
|
|
|
$this->db->group_end();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Confirmed only
|
|
|
|
|
if (!empty($filters['confirmed'])) {
|
|
|
|
|
$this->db->group_start();
|
|
|
|
|
$this->db->where('col_qsl_rcvd', 'Y');
|
|
|
|
|
$this->db->or_where('col_lotw_qsl_rcvd', 'Y');
|
|
|
|
|
$this->db->group_end();
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-10-05 22:13:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
?>
|