2025-11-14 16:39:56 +00:00
< ? php if ( ! defined ( 'BASEPATH' )) exit ( 'No direct script access allowed' );
/*
Controller for generating monthly reports of amateur radio activity
*/
class Monthlyreport extends CI_Controller {
function __construct ()
{
parent :: __construct ();
$this -> load -> helper ( array ( 'form' , 'url' ));
$this -> load -> model ( 'user_model' );
if ( ! $this -> user_model -> authorize ( 2 )) {
$this -> session -> set_flashdata ( 'notice' , 'You\'re not allowed to do that!' );
redirect ( 'dashboard' );
}
}
/**
* Index page - display report selection form
*/
public function index ()
{
$this -> load -> model ( 'logbooks_model' );
$data [ 'logbooks' ] = $this -> logbooks_model -> show_all ();
$data [ 'page_title' ] = " Monthly Report " ;
$this -> load -> view ( 'interface_assets/header' , $data );
$this -> load -> view ( 'monthlyreport/index' );
$this -> load -> view ( 'interface_assets/footer' );
}
/**
* Generate report for selected logbook and month
*/
public function generate ()
{
$this -> load -> model ( 'monthlyreport_model' );
$this -> load -> model ( 'logbooks_model' );
// Get parameters from POST
$logbook_id = $this -> input -> post ( 'logbook_id' );
$year = $this -> input -> post ( 'year' );
$month = $this -> input -> post ( 'month' );
// Validate inputs
if ( empty ( $logbook_id ) || empty ( $year ) || empty ( $month )) {
$this -> session -> set_flashdata ( 'notice' , 'Please select a logbook and month' );
redirect ( 'monthlyreport' );
}
// Get logbook relationships (station locations)
$logbooks_locations_array = $this -> logbooks_model -> list_logbook_relationships ( $logbook_id );
if ( ! $logbooks_locations_array ) {
$this -> session -> set_flashdata ( 'notice' , 'No station locations found for this logbook' );
redirect ( 'monthlyreport' );
}
// Generate report data
$data [ 'report' ] = $this -> monthlyreport_model -> generate_report ( $logbooks_locations_array , $year , $month );
$data [ 'logbook_name' ] = $this -> logbooks_model -> find_name ( $logbook_id );
$data [ 'year' ] = $year ;
$data [ 'month' ] = $month ;
$data [ 'month_name' ] = date ( 'F' , mktime ( 0 , 0 , 0 , $month , 1 ));
$data [ 'page_title' ] = " Monthly Report - " . $data [ 'month_name' ] . " " . $year ;
$this -> load -> view ( 'interface_assets/header' , $data );
$this -> load -> view ( 'monthlyreport/report' );
$this -> load -> view ( 'interface_assets/footer' );
}
/**
* Export report in AI - friendly format ( JSON )
*/
public function export_json ()
{
$this -> load -> model ( 'monthlyreport_model' );
$this -> load -> model ( 'logbooks_model' );
// Get parameters from POST
$logbook_id = $this -> input -> post ( 'logbook_id' );
$year = $this -> input -> post ( 'year' );
$month = $this -> input -> post ( 'month' );
// Get logbook relationships
$logbooks_locations_array = $this -> logbooks_model -> list_logbook_relationships ( $logbook_id );
// Generate report data
$report = $this -> monthlyreport_model -> generate_report ( $logbooks_locations_array , $year , $month );
$logbook_name = $this -> logbooks_model -> find_name ( $logbook_id );
$month_name = date ( 'F' , mktime ( 0 , 0 , 0 , $month , 1 ));
// Create AI-friendly export
$export = array (
'metadata' => array (
'logbook' => $logbook_name ,
'period' => $month_name . ' ' . $year ,
'generated_at' => date ( 'Y-m-d H:i:s' ),
'report_type' => 'monthly_amateur_radio_activity'
),
'summary' => array (
'total_qsos' => $report [ 'total_qsos' ],
'new_dxcc_entities' => count ( $report [ 'new_dxcc' ]),
'new_dxcc_by_band_count' => count ( $report [ 'new_dxcc_by_band' ]),
'new_dxcc_satellite' => count ( $report [ 'new_dxcc_satellite' ]),
'new_dxcc_eme' => count ( $report [ 'new_dxcc_eme' ]),
'new_gridsquares' => count ( $report [ 'new_grids' ]),
'new_gridsquares_hf' => count ( $report [ 'new_grids_hf' ]),
'new_gridsquares_satellite' => count ( $report [ 'new_grids_satellite' ]),
'new_gridsquares_eme' => count ( $report [ 'new_grids_eme' ]),
'unique_callsigns' => $report [ 'unique_callsigns' ],
'countries_worked' => count ( $report [ 'countries_worked' ])
),
'details' => array (
'new_countries' => $report [ 'new_dxcc' ],
'new_countries_by_band' => $report [ 'new_dxcc_by_band' ],
'new_countries_satellite' => $report [ 'new_dxcc_satellite' ],
'new_countries_eme' => $report [ 'new_dxcc_eme' ],
'new_gridsquares' => $report [ 'new_grids' ],
2025-11-14 17:49:25 +00:00
'new_gridsquares_by_band' => $report [ 'new_grids_by_band' ],
2025-11-14 16:39:56 +00:00
'new_gridsquares_hf' => $report [ 'new_grids_hf' ],
'new_gridsquares_satellite' => $report [ 'new_grids_satellite' ],
'new_gridsquares_eme' => $report [ 'new_grids_eme' ],
'callsigns_worked' => $report [ 'callsign_list' ],
'modes_used' => $report [ 'modes' ],
'bands_used' => $report [ 'bands' ],
'continents_worked' => $report [ 'continents' ],
'satellite_qsos' => $report [ 'satellite_qsos' ],
2025-11-14 17:49:25 +00:00
'eme_qsos' => $report [ 'eme_qsos' ],
'satellite_breakdown' => $report [ 'satellite_breakdown' ]
2025-11-14 16:39:56 +00:00
),
'statistics' => array (
'qsos_per_day' => round ( $report [ 'total_qsos' ] / date ( 't' , strtotime ( " $year - $month -01 " )), 2 ),
'most_active_band' => $report [ 'top_band' ],
'most_used_mode' => $report [ 'top_mode' ]
),
'ai_prompt_suggestion' => " Write an engaging amateur radio blog post about my " . $month_name . " " . $year . " operating activity. I made " . $report [ 'total_qsos' ] . " contacts " .
( count ( $report [ 'new_dxcc' ]) > 0 ? " , worked " . count ( $report [ 'new_dxcc' ]) . " new countries " : " " ) .
( count ( $report [ 'new_grids' ]) > 0 ? " , and confirmed " . count ( $report [ 'new_grids' ]) . " new gridsquares " : " " ) .
" . Focus on the highlights and make it sound exciting for fellow radio enthusiasts. "
);
// Set headers for JSON download
2025-11-14 17:11:18 +00:00
$filename = " monthly_report_ { $year } _ { $month } .json " ;
2025-11-14 16:39:56 +00:00
$this -> output
-> set_content_type ( 'application/json' )
2025-11-14 17:11:18 +00:00
-> set_header ( 'Content-Disposition: attachment; filename="' . $filename . '"' )
2025-11-14 16:39:56 +00:00
-> set_output ( json_encode ( $export , JSON_PRETTY_PRINT ));
}
/**
* Export report as plain text for AI consumption
*/
public function export_text ()
{
$this -> load -> model ( 'monthlyreport_model' );
$this -> load -> model ( 'logbooks_model' );
// Get parameters from POST
$logbook_id = $this -> input -> post ( 'logbook_id' );
$year = $this -> input -> post ( 'year' );
$month = $this -> input -> post ( 'month' );
// Get logbook relationships
$logbooks_locations_array = $this -> logbooks_model -> list_logbook_relationships ( $logbook_id );
// Generate report data
$report = $this -> monthlyreport_model -> generate_report ( $logbooks_locations_array , $year , $month );
$logbook_name = $this -> logbooks_model -> find_name ( $logbook_id );
$month_name = date ( 'F' , mktime ( 0 , 0 , 0 , $month , 1 ));
// Create plain text report
$text = " AMATEUR RADIO MONTHLY ACTIVITY REPORT \n " ;
$text .= " ======================================== \n \n " ;
$text .= " Logbook: { $logbook_name } \n " ;
$text .= " Period: { $month_name } { $year } \n " ;
$text .= " Generated: " . date ( 'Y-m-d H:i:s' ) . " \n \n " ;
$text .= " SUMMARY \n " ;
$text .= " ------- \n " ;
$text .= " Total QSOs: { $report [ 'total_qsos' ] } \n " ;
$text .= " Unique Callsigns Worked: { $report [ 'unique_callsigns' ] } \n " ;
$text .= " New DXCC Entities: " . count ( $report [ 'new_dxcc' ]) . " \n " ;
$text .= " New Gridsquares: " . count ( $report [ 'new_grids' ]) . " \n " ;
$text .= " Countries Worked: " . count ( $report [ 'countries_worked' ]) . " \n \n " ;
if ( count ( $report [ 'new_dxcc' ]) > 0 ) {
$text .= " NEW COUNTRIES THIS MONTH - OVERALL \n " ;
$text .= " ---------------------------------- \n " ;
foreach ( $report [ 'new_dxcc' ] as $dxcc ) {
$text .= " - { $dxcc [ 'name' ] } \n " ;
}
$text .= " \n " ;
}
if ( ! empty ( $report [ 'new_dxcc_by_band' ])) {
$text .= " NEW COUNTRIES BY BAND \n " ;
$text .= " --------------------- \n " ;
// Bands already sorted in model
foreach ( $report [ 'new_dxcc_by_band' ] as $band => $dxcc_list ) {
$text .= " \n { $band } ( " . count ( $dxcc_list ) . " new): \n " ;
foreach ( $dxcc_list as $dxcc ) {
2025-11-14 17:49:25 +00:00
$text .= " - { $dxcc [ 'name' ] } " ;
if ( ! empty ( $dxcc [ 'callsign' ])) {
$text .= " (worked { $dxcc [ 'callsign' ] } " ;
if ( ! empty ( $dxcc [ 'mode' ])) {
$text .= " on { $dxcc [ 'mode' ] } " ;
}
$text .= " ) " ;
}
$text .= " \n " ;
2025-11-14 16:39:56 +00:00
}
}
$text .= " \n " ;
}
if ( count ( $report [ 'new_dxcc_satellite' ]) > 0 ) {
$text .= " NEW COUNTRIES VIA SATELLITE \n " ;
$text .= " --------------------------- \n " ;
foreach ( $report [ 'new_dxcc_satellite' ] as $dxcc ) {
2025-11-14 17:49:25 +00:00
$text .= " - { $dxcc [ 'name' ] } " ;
if ( ! empty ( $dxcc [ 'callsign' ])) {
$text .= " (worked { $dxcc [ 'callsign' ] } " ;
if ( ! empty ( $dxcc [ 'mode' ])) {
$text .= " on { $dxcc [ 'mode' ] } " ;
}
$text .= " ) " ;
}
$text .= " \n " ;
2025-11-14 16:39:56 +00:00
}
$text .= " \n " ;
}
if ( count ( $report [ 'new_dxcc_eme' ]) > 0 ) {
$text .= " NEW COUNTRIES VIA EME (MOONBOUNCE) \n " ;
$text .= " ---------------------------------- \n " ;
foreach ( $report [ 'new_dxcc_eme' ] as $dxcc ) {
2025-11-14 17:49:25 +00:00
$text .= " - { $dxcc [ 'name' ] } " ;
if ( ! empty ( $dxcc [ 'callsign' ])) {
$text .= " (worked { $dxcc [ 'callsign' ] } " ;
if ( ! empty ( $dxcc [ 'mode' ])) {
$text .= " on { $dxcc [ 'mode' ] } " ;
}
$text .= " ) " ;
}
$text .= " \n " ;
2025-11-14 16:39:56 +00:00
}
$text .= " \n " ;
}
if ( count ( $report [ 'new_grids' ]) > 0 ) {
$text .= " NEW GRIDSQUARES THIS MONTH \n " ;
$text .= " -------------------------- \n " ;
2025-11-14 17:49:25 +00:00
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 " ;
}
2025-11-14 16:39:56 +00:00
}
}
2025-11-14 17:49:25 +00:00
$text .= " \n " ;
} $text .= " MODES USED \n " ;
2025-11-14 16:39:56 +00:00
$text .= " ---------- \n " ;
foreach ( $report [ 'modes' ] as $mode => $count ) {
$text .= sprintf ( " %-10s %d QSOs \n " , $mode , $count );
}
$text .= " \n " ;
$text .= " BANDS USED \n " ;
$text .= " ---------- \n " ;
foreach ( $report [ 'bands' ] as $band => $count ) {
$text .= sprintf ( " %-10s %d QSOs \n " , $band , $count );
}
$text .= " \n " ;
if ( ! empty ( $report [ 'continents' ])) {
$text .= " CONTINENTAL DISTRIBUTION \n " ;
$text .= " ------------------------ \n " ;
foreach ( $report [ 'continents' ] as $continent => $count ) {
$text .= sprintf ( " %-15s %d QSOs \n " , $continent , $count );
}
$text .= " \n " ;
}
if ( ! empty ( $report [ 'callsign_list' ])) {
$text .= " UNIQUE CALLSIGNS WORKED ( " . count ( $report [ 'callsign_list' ]) . " ) \n " ;
$text .= " ---------------------------- \n " ;
foreach ( $report [ 'callsign_list' ] as $callsign ) {
$text .= sprintf ( " %-15s %d QSO%s \n " , $callsign [ 'callsign' ], $callsign [ 'qso_count' ], $callsign [ 'qso_count' ] > 1 ? 's' : '' );
}
$text .= " \n " ;
}
if ( $report [ 'satellite_qsos' ] > 0 ) {
$text .= " SATELLITE ACTIVITY \n " ;
$text .= " ------------------ \n " ;
2025-11-14 17:49:25 +00:00
$text .= " Total Satellite QSOs: { $report [ 'satellite_qsos' ] } \n " ;
if ( ! empty ( $report [ 'satellite_breakdown' ])) {
$text .= " \n QSOs 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 " ;
2025-11-14 16:39:56 +00:00
}
if ( $report [ 'eme_qsos' ] > 0 ) {
$text .= " EME (MOONBOUNCE) ACTIVITY \n " ;
$text .= " ------------------------- \n " ;
$text .= " Total EME QSOs: { $report [ 'eme_qsos' ] } \n \n " ;
}
$text .= " STATISTICS \n " ;
$text .= " ---------- \n " ;
$days_in_month = date ( 't' , strtotime ( " $year - $month -01 " ));
$text .= " Average QSOs per day: " . round ( $report [ 'total_qsos' ] / $days_in_month , 2 ) . " \n " ;
$text .= " Most active band: { $report [ 'top_band' ] } \n " ;
$text .= " Most used mode: { $report [ 'top_mode' ] } \n \n " ;
$text .= " --- \n " ;
$text .= " This report can be used to generate an article about your amateur radio activity. \n " ;
$text .= " Consider using an AI tool like ChatGPT or Claude to create an engaging blog post from this data. \n " ;
// Set headers for text download
$filename = " monthly_report_ { $year } _ { $month } .txt " ;
$this -> output
-> set_content_type ( 'text/plain' )
-> set_header ( 'Content-Disposition: attachment; filename="' . $filename . '"' )
-> set_output ( $text );
}
}