load->model('report_model'); } public function chart() { ini_set('memory_limit', '256M'); $params = $this->input->get(); $data = []; $errors = []; $chartData1 = []; $chartData2 = []; $data['transport_providers_dropdown'] = [ ['id' => 1, 'name' => 'Uber', 'color' => 'rgb(45, 230, 92)'], ['id' => 2, 'name' => 'Lyft', 'color' => 'rgb(255, 0, 255)'], ['id' => 3, 'name' => 'Grab' , 'color' => 'rgb(54, 162, 235)'], ['id' => 4, 'name' => 'ComfortDelGro', 'color' => 'rgb(0, 255, 255)'], ['id' => 5, 'name' => 'GOJEK', 'color' => 'rgb(255, 191, 0)'], ]; if (!empty($params)) { // get data for period of time 1 $period1_input = [ 'start_date' => $params['start_date_1'] ?? '', 'end_date' => $params['end_date_1'] ?? '', 'transport_providers' => $params['transport_providers'] ?? '', ]; // get data for period of time 2 $period2_input = [ 'start_date' => $params['start_date_2'] ?? '', 'end_date' => $params['end_date_2'] ?? '', 'transport_providers' => $params['transport_providers'] ?? '', ]; // chart1 and chart2 are same data (just different how to plot chart) => load first to have good performance $loadDataFromDatabase1 = $response = $this->report_model->getPriceComparisonTrend($period1_input); // for period of time 1 $loadDataFromDatabase2 = $response = $this->report_model->getPriceComparisonTrend($period2_input); // for period of time 2 $chartDataResponse1 = $this->getChartData1($loadDataFromDatabase1, $loadDataFromDatabase2, $data['transport_providers_dropdown']); $chartDataResponse2 = $this->getChartData2($loadDataFromDatabase1, $loadDataFromDatabase2, $data['transport_providers_dropdown']); if (!$chartDataResponse1['success'] || !$chartDataResponse2['success']) { if (!empty($chartDataResponse1['message'])) { $errors[] = $chartDataResponse1['message']; } if (!empty($chartDataResponse2['message'])) { $errors[] = $chartDataResponse2['message']; } } else { $chartData1 = $chartDataResponse1['data']; $chartData2 = $chartDataResponse2['data']; } } $data['chartData1'] = json_encode($chartData1); $data['chartData2'] = json_encode($chartData2); $data['filterData'] = $params; $data['errors'] = $errors; $this->renderAdminPage('report/view_price_comparison_trend', $data); } public function getChartData2(array $loadDataFromDatabase1, array $loadDataFromDatabase2, array $transport_providers_map) { $errors = []; $datasets = []; $general_index_date_map = []; $datasets_1 = $this->generateChartDataset( $loadDataFromDatabase1, $transport_providers_map, $general_index_date_map, 'Period1' ); $datasets_2 = $this->generateChartDataset( $loadDataFromDatabase2, $transport_providers_map, $general_index_date_map, 'Period2' ); if (!$datasets_1['success'] || !$datasets_2['success']) { if (!empty($datasets_1['message'])) { $errors[] = $datasets_1['message']; } if (!empty($datasets_2['message'])) { $errors[] = $datasets_2['message']; } } else { $datasets = array_merge($datasets_1['data'], $datasets_2['data']); } if (!empty($errors)) { return [ 'success' => false, 'message' => $errors[0] ]; } $chartData = [ 'datasets' => $datasets, 'general_index_date_map' => $general_index_date_map ?? [], ]; return [ 'success' => true, 'data' => $chartData ]; } public function getChartData1(array $loadDataFromDatabase1, array $loadDataFromDatabase2, array $transport_providers_map) { $errors = []; $datasets = []; $index_date_map_1 = []; $index_date_map_2 = []; $datasets_1 = $this->generateChartDataset( $loadDataFromDatabase1, $transport_providers_map, $index_date_map_1, 'Period1', true ); $datasets_2 = $this->generateChartDataset( $loadDataFromDatabase2, $transport_providers_map, $index_date_map_2, 'Period2', true ); if (!$datasets_1['success'] || !$datasets_2['success']) { if (!empty($datasets_1['message'])) { $errors[] = $datasets_1['message']; } if (!empty($datasets_2['message'])) { $errors[] = $datasets_2['message']; } } else { $datasets = array_merge($datasets_1['data'], $datasets_2['data']); } if (!empty($errors)) { return [ 'success' => false, 'message' => $errors[0] ]; } $chartData = [ 'datasets' => $datasets, 'index_date_map_1' => $index_date_map_1 ?? [], 'index_date_map_2' => $index_date_map_2 ?? [], ]; return [ 'success' => true, 'data' => $chartData ]; } protected function generateChartDataset( array $loadDataFromDatabase, array $transport_providers_map, array &$index_date_map, string $period_name, bool $is_mutiple_x_axis = false) : array { if (!$loadDataFromDatabase['success']) { return [ 'success' => false, 'message' => $loadDataFromDatabase['message'] ]; } $datasets = []; $dataset = []; $i = count($index_date_map); foreach ($loadDataFromDatabase['data'] as $key => $item) { if (!array_key_exists($item['travel_date'], $index_date_map)) { $index_date_map[$item['travel_date']] = $i; $i++; } $dataset[$item['transport_provider_id']][] = [ 'x' => $index_date_map[$item['travel_date']], 'count' => (int) $item['count'], 'y' => $item['cost'] ]; } foreach ($dataset as $transport_provider_id => $chart_data ) { $found_key = array_search($transport_provider_id, array_column($transport_providers_map, 'id')); if ($found_key === FALSE) { continue; } $label = $transport_providers_map[$found_key]['name']; $color = $transport_providers_map[$found_key]['color']; // add scatter (data point) $dataset_item = [ 'type' => 'scatter', 'showLine' => false, 'label' => $label . " (${period_name})", // only get [x, y] points to plot chart 'data' => array_map(function($el) { return ['x' => $el['x'], 'y' => $el['y']]; }, $chart_data), 'backgroundColor' => $color ]; // add trend line based on scatter $trendLineData = $this->calculateTrendLine($chart_data); $trend_line_dataset = [ 'type' => 'line', 'showLine'=> true, 'fill' => false, 'pointRadius' => 0, 'cubicInterpolationMode' => 'monotone', 'label' => $label . " - Trend line (${period_name})", 'data' => $trendLineData, 'backgroundColor' => $color, 'borderColor'=> $color, ]; if ($is_mutiple_x_axis) { $dataset_item['xAxisID'] = 'x-' . $period_name; $trend_line_dataset['xAxisID'] = 'x-' . $period_name; } $datasets[] = $dataset_item; $datasets[] = $trend_line_dataset; } return [ 'success' => true, 'data' => $datasets ]; } protected function calculateTrendLine(array $data) { // e.g. // $samples = [[73676, 1996], [77006, 1998], [10565, 2000], [146088, 1995]]; // $targets = [2000, 2750, 15500, 960]; $samples = array_map(function($el) { return [$el['x'], $el['count']]; }, $data); $targets = array_map(function($el) { return $el['y']; }, $data); $regression = new LeastSquares(); $regression->train($samples, $targets); $coefficients = $regression->getCoefficients(); $intercept = $regression->getIntercept(); $result = []; foreach ($samples as $el) { $y = $intercept + $el[0] * $coefficients[0] + 1 * $coefficients[1]; $result[] = ['x' => $el[0], 'y' => $y]; } return $result; } public function surgePricingVaraition() { global $savvyext; $this->load->helper('surge_pricing_varaition'); $regression1 = new LeastSquares(); $t = 3; $date1 = "2020-01-01"; $date2 = "2020-05-10"; $area1 = 14; $area2 = 11; $areas = [ 10 => 'Central - Tanglin', 11 => 'Central - Newton', 17 => 'Far East - Changi', 14 => 'Central East - Eunos' ]; $t = isset($_GET['t'])?((int)$_GET['t']):$t; $date1 = isset($_GET['date1'])?date("Y-m-d",strtotime($_GET['date1'])):$date1; $date2 = isset($_GET['date2'])?date("Y-m-d",strtotime($_GET['date2'])):$date2; $area1 = isset($_GET['area1'])?((int)$_GET['area1']):$area1; $area2 = isset($_GET['area2'])?((int)$_GET['area2']):$area2; if (3 > $t || $t > 5) $t = 3; if (!array_key_exists($area1,$areas)) $area1 = 14; if (!array_key_exists($area2,$areas)) $area2 = 11; $providers = [3 => "Grab", 5 => "Gojek", 4 => "ComfortDelGro"]; $c = '#ff5555'; list($data1,$label1,$poly1) = $this->report_model->area_to_area($area1, $area2, $date1, $date2, $t, $c); $res1 = $this->surgePricingTrendLine($regression1, $data1); $pub1 = $res1[0]; $c = '#5555ff'; list($data2,$label2,$poly2) = $this->report_model->area_to_area($area2, $area1, $date1, $date2, $t, $c); $res2 = $this->surgePricingTrendLine($regression1, $data2); $pub2 = $res2[0]; $data = array_merge($data1, $data2); $data = [ 't' => $t, 'date1' => $date1, 'date2' => $date2, 'area1' => $area1, 'area2' => $area2, 'areas' => $areas, 'providers' => $providers, 'data' => $data, 'data1' => $data1, 'data2' => $data2, 'label1' => $label1, 'label2' => $label2, 'poly1' => $poly1, 'poly2' => $poly2, 'res1' => $res1, 'res2' => $res2, 'pub1' => $pub1, 'pub2' => $pub2, 'google_api_key' => $savvyext->cfgReadChar( 'google.api_key' ) ]; $this->renderAdminPage('report/view_surge_pricing_varaition', $data); } /*** * Email & Bank Connection Log */ public function emailAndBankConnectionReport() { $this->load->model('combo_model'); $data_report = $this->report_model->getEmailAndBankConnectionReportSummary(); $data = [ 'page_title' => 'Email & Bank Connection Report', 'data_report' => $data_report, 'country_filter' => $this->combo_model->getCountriesHasAccount('country_filter', ''), ]; $this->renderAdminPage('report/view_email_and_bank_connection_report', $data); } public function emailAndBankConnectionReportDatatables() { $data = $this->report_model->getEmailBankConnectionReportDatatables($this->input->post(), 'search'); header('Content-Type: application/json'); echo json_encode($data); } public function emailAndBankConnectionReportCSV() { $this->load->library('session'); $postData = $this->session->userdata("EBCRR_PARAM"); if ($postData) { $this->report_model->getEmailBankConnectionReportDatatables($postData, 'export_csv'); } else { echo 'Please try again!'; die(); } } public function getBankAccountDetailJson() { $member_id = $this->input->get('member_id'); $data = $this->report_model->getBankAccountDetail($member_id); header('Content-Type: application/json'); echo json_encode($data); } public function surgePricingTrendLine($regression1, $data) { $i = 0; $pub1 = array(); $xs1 = []; $ys1 = []; $ys2 = []; foreach ($data as $f) { $t = $f['time']; $pub1[$t] = array($t,$f['cost']); $xs1[] = [$t]; $ys1[] = $f['cost']; $i++; } if ($i>0) { $regression1->train($xs1,$ys1); } foreach ($pub1 as $key=>$f) { $y = $regression1->predict( [$f[0]] ); $f[2] = $y; $pub1[$key] = $f; } return [$pub1,$xs1,$ys2]; } protected function renderAdminPage($page_name, $data) { $this->load->view('admin/view_admin_header', $data); $this->load->view($page_name, $data); $this->load->view('admin/view_admin_footer', $data); } }