. */ require_once("./IRundaily.php"); require_once("../include/g_meal.php"); class StatisticsRundaily implements IRundaily { private $messages; public function __construct() { $this->messages = array(); } public function run() { $accepted = $this->getCountPerStatus(); if( $accepted['total'] >= 50 ) { // Require at least 50 applications to make statistics $period = $this->getPeriods($accepted); $this->deleteOldStatistics(); $this->createAcceptedStatus($accepted); /// All applications /// // Applications per day $this->createApplicationsPerDay($accepted['total']); // Quorum $this->createQuorum($period); // Rest goes in batch (limited amount of options) $this->createStatsLimitedOptions($period); // Batch (unlimited amount of options) $this->createStatsUnlimitedOptions($period); }else { $this->addMessage("Too few applications to generate statistics."); } } public function isEnabled() { global $setup; return $setup['EventDateAppStart'] != "" && get_sql_date($setup['EventDateAppStart']) <= date("Y-m-d", strtotime("+2 days")); } public function getTitle() { return "Creating statistics"; } public function getMessages() { return $this->messages; } private function addMessage($message) { $this->messages[] = $message; } private function getCountPerStatus() { $accepted = array(); $accepted['-'] = 0; $accepted['yes'] = 0; $accepted['pending'] = 0; $accepted['confirmed'] = 0; $accepted['arrived'] = 0; $accepted['no'] = 0; $accepted['cancel'] = 0; $accepted['total'] = 0; $queryBuilder = new QueryBuilder($GLOBALS['DB'], "applications"); $queryBuilder->addField("accepted"); $queryBuilder->addField(new DBMethodCount("accepted"), "amount"); $queryBuilder->addGroup("accepted"); if( $GLOBALS['DB']->select($queryBuilder->toQuery()) > 0 ) { while( $row = $GLOBALS['DB']->fetchAssoc() ) { $accepted[ $row['accepted'] ] = $row['amount']; $accepted['total'] += $row['amount']; } } return $accepted; } private function getPeriods($accepted) { global $setup; $period = array(); $period[0]['name'] = "all"; $period[0]['queryWhere'] = NULL; $period[0]['sum'] = $accepted['total']; if( $accepted['yes'] + $accepted['pending'] + $accepted['confirmed'] + $accepted['arrived'] >= 50 && $setup['ShowParticipantList'] ) { $period[1]['name'] = "accepted"; $period[1]['queryWhere'] = array("yes", "pending", "confirmed"); $period[1]['sum'] = $accepted['yes'] + $accepted['pending'] + $accepted['confirmed']; if( $accepted['arrived'] >= 50 ) { $period[2]['name'] = "arrived"; $period[2]['queryWhere'] = array("arrived"); $period[2]['sum'] = $accepted['arrived']; } } return $period; } private function deleteOldStatistics() { if( $GLOBALS['DB']->delete("statistics") ) { $this->addMessage("Old statistics deleted"); }else { $this->addMessage("Failed deleting old statistics"); } } private function createAcceptedStatus($acceptedWithTotal) { global $setup; if( $setup['ShowParticipantList'] ) { $html = ""; $json = array(); $json['generated'] = date("Y-m-d H:i:s"); $json['total'] = $acceptedWithTotal['total']; $json['data'] = array(); $row = 0; $accepted = $acceptedWithTotal; unset($accepted['total']); foreach( $accepted as $name => $count ) { $html .= ""; $html .= ""; $html .= ""; $html .= ""; $html .= ""; $json['data'][$row]['name'] = $name; $json['data'][$row]['count'] = $count; $json['data'][$row]['percentage'] = number_format($count / $acceptedWithTotal['total'] * 100, 1) . "%"; $row++; } $html .= "
StatusAmount
" . $name . "" . $count . "" . number_format($count / $acceptedWithTotal['total'] * 100, 1) . "%
"; $chart = new Chart("Accepted status", $accepted, 10, FULL_PATH . "tmp/"); $data = array(); $data['selection'] = "all"; $data['title'] = "Accepted status"; $data['date'] = date("Y-m-d H:i:s"); $data['html'] = $html; $data['json'] = json_encode($json); $data['image'] = $chart->pie(300); $data['image_height'] = $chart->get_height("pie"); $data['image_width'] = $chart->get_width("pie"); if( $GLOBALS['DB']->insert("statistics", $data) ) { $this->addMessage("Created 'accepted status'"); }else { $this->addMessage("Failed creating 'accepted status'"); } } } private function createApplicationsPerDay($total) { global $setup; $queryBuilder = new QueryBuilder($GLOBALS['DB'], "applications"); $queryBuilder->addField(new DBMethodMin(new DBMethodLeft("created", 10)), "first"); $queryBuilder->addField(new DBMethodMax(new DBMethodLeft("created", 10)), "last"); if( $GLOBALS['DB']->select($queryBuilder->toQuery()) == 1 ) { $startEnd =$GLOBALS['DB']->fetchAssoc(); } $queryBuilder = new QueryBuilder($GLOBALS['DB'], "applications"); $queryBuilder->addField(new DBMethodLeft("created", 10), "applicationday"); $queryBuilder->addField(new DBMethodCount("id"), "number"); $queryBuilder->addGroup(new DBMethodLeft("created", 10)); $queryBuilder->addOrderAsc("applicationday"); if( $GLOBALS['DB']->select($queryBuilder->toQuery()) > 0 ) { $html_applperday = ""; $html_appl = "
DateAmount
"; $data_applperday = array(); $data_appl = array(); $jsonDataApplPerDay = array(); $jsonDataAppl = array(); $weekend = array(); $deadline = array($setup['EventDateAppEnd']); for( $i=strtotime($startEnd['first']); $i<=strtotime($startEnd['last']); $i+=24*3600 ) { $data_applperday[ date("d.m.Y", $i) ] = 0; $data_appl[ date("d.m.Y", $i) ] = 0; if( date("w", $i) == 0 || date("w", $i) == 6 ) $weekend[] = date("d.m.Y", $i); } $i = 0; $count = 0; while( $row = $GLOBALS['DB']->fetchAssoc() ) { $i++; $count += $row['number']; $data_applperday[ get_date($row['applicationday']) ] = $row['number']; $data_appl[ get_date($row['applicationday']) ] = $count; $jsonDataApplPerDay[ get_date($row['applicationday']) ] = $row['number']; $jsonDataAppl[ get_date($row['applicationday']) ] = $count; $html_applperday .= ""; $html_applperday .= ""; $html_applperday .= ""; $html_applperday .= ""; $html_applperday .= ""; $html_appl .= ""; $html_appl .= ""; $html_appl .= ""; $html_appl .= ""; } // Correct for days without applications for( $i=strtotime($startEnd['first'])+24*3600; $i<=strtotime($startEnd['last']); $i+=24*3600 ) { $yesterday = date("d.m.Y", $i-24*3600); $today = date("d.m.Y", $i); if( $data_appl[$yesterday] > $data_appl[$today] ) $data_appl[$today] = $data_appl[$yesterday]; } $html_applperday .= "
DateAmount
" . get_date($row['applicationday']) . "" . $row['number'] . "" . number_format($row['number'] / $total * 100, 1) . "%
" . get_date($row['applicationday']) . "" . $count . "
"; $html_appl .= ""; $jsonPerDay = array(); $jsonPerDay['generated'] = date("Y-m-d H:i:s"); $jsonPerDay['total'] = $total; $jsonPerDay['data'] = $jsonDataApplPerDay; $chart = new Chart("Applications per day", $data_applperday, 10, FULL_PATH . "tmp/"); $data = array(); $data['selection'] = "all"; $data['title'] = "Applications per day"; $data['date'] = date("Y-m-d H:i:s"); $data['html'] = $html_applperday; $data['json'] = json_encode($jsonPerDay); $data['image'] = $chart->bar(600, 500, -1, -1, -1, -1, $deadline, array(), $weekend, array()); $data['image_height'] = $chart->get_height("bar"); $data['image_width'] = $chart->get_width("bar"); if( $GLOBALS['DB']->insert("statistics", $data) ) { $this->addMessage("Created 'applications per day'"); }else { $this->addMessage("Failed creating 'applications per day'"); } $json = array(); $json['generated'] = date("Y-m-d H:i:s"); $json['total'] = $total; $json['data'] = $jsonDataAppl; $chart = new Chart("Applications", $data_appl, 10, FULL_PATH . "tmp/"); $data = array(); $data['selection'] = "all"; $data['title'] = "Applications"; $data['date'] = date("Y-m-d H:i:s"); $data['html'] = $html_appl; $data['json'] = json_encode($json); $data['image'] = $chart->line(600, 500, -1, -1, -1, -1, $deadline, array(), $weekend, array()); $data['image_height'] = $chart->get_height("line"); $data['image_width'] = $chart->get_width("line"); if( $GLOBALS['DB']->insert("statistics", $data) ) { $this->addMessage("Created 'applications'"); }else { $this->addMessage("Failed creating 'applications'"); } } } private function createQuorum($period) { global $setup; for( $p=0; $p=get_sql_date($setup['EventDateStart'])?2:1) ) { $queryBuilder = new QueryBuilder($GLOBALS['DB'], "ab_bodies"); $queryBuilder->addField(new DBMethodCount("bodycode"), "total"); $queryBuilder->addWhereEquals("bodystatus", "A"); if( $GLOBALS['DB']->select($queryBuilder->toQuery()) == 1 ) { $row = $GLOBALS['DB']->fetchAssoc(); $total = $row['total']; $queryBuilder = new QueryBuilder($GLOBALS['DB'], "applications"); $queryBuilder->addField(new DBMethodCount("ab_bodies.bodycode"), "count"); $queryBuilder->addInnerJoin("ab_bodies", "bodycode", "applications.bodycode"); $queryBuilder->addWhereEquals("ab_bodies.bodystatus", "A"); if( $period[$p]['queryWhere'] != NULL ) { $queryBuilder->addWhereIn("accepted", $period[$p]['queryWhere']); } $queryBuilder->addGroup("ab_bodies.bodycode"); if( $GLOBALS['DB']->select($queryBuilder->toQuery()) > 0 ) { $present = $GLOBALS['DB']->numRows(); $html = ""; $html .= ""; $html .= ""; $html .= "
StatusAmount
Present".$present."".number_format($present/$total*100, 1)."%
Not present".($total-$present)."".number_format(($total-$present)/$total*100, 1)."%
"; $html .= "

The quorum is the percentage of present bodies with voting rights (Antenna & AEGEE-WG). For a statutory meeting with decision power, this should be at least 50% + 1. Please note that the values shown here are calculated from the participants that applied. This chart only shows an estimate, the official number depends on the number of bodies that registers with AEGEE-Europe.

"; $json = array(); $json['generated'] = date("Y-m-d H:i:s"); $json['total'] = $total; $json['data']['present'] = $present; $json['data']['notPresent'] = $total - $present; $data = array("Present" => $present, "Not present" => $total - $present); $chart = new Chart("Quorum", $data, 10, FULL_PATH . "tmp/"); $data = array(); $data['selection'] = $period[$p]['name']; $data['title'] = "Quorum"; $data['date'] = date("Y-m-d H:i:s"); $data['html'] = $html; $data['json'] = json_encode($json); $data['image'] = $chart->pie(300); $data['image_height'] = $chart->get_height("pie"); $data['image_width'] = $chart->get_width("pie"); if( $GLOBALS['DB']->insert("statistics", $data) ) { $this->addMessage("Created 'quorum (" . $period[$p]['name'] . ")'"); }else { $this->addMessage("Failed creating 'quorum (" . $period[$p]['name'] . ")'"); } }else { $this->addMessage("Failed selecting present bodies for quorum"); } }else { $this->addMessage("Failed selecting total bodies for quorum"); } } } private function createStatsLimitedOptions($period) { global $setup; global $Meals; for( $p=0; $p < count($period); $p += (date("Y-m-d") >= get_sql_date($setup['EventDateStart']) ? 2 : 1) ) { $stats = array(); $stats['Meals'] = $this->createQueryStats("meals", $period[$p]["queryWhere"]); ##$stats['Board confirmed'] = $this->createQueryStats("boardconfirmed", $period[$p]["queryWhere"]); $stats['Participant type'] = $this->createQueryStats("participanttype", $period[$p]["queryWhere"]); $stats['Gender'] = $this->createQueryStats("sex", $period[$p]["queryWhere"]); ##$stats['Visa invitation needed'] = $this->createQueryStats("visa", $period[$p]["queryWhere"]); $stats['Type of member'] = $this->createQueryStats("membertype", $period[$p]["queryWhere"]); $stats['Number of Agora visited'] = $this->createQueryStats("agoravisited", $period[$p]["queryWhere"]); foreach( $stats as $name => $query ) { if( $GLOBALS['DB']->select($query) > 0 ) { $html = ""; $data = array(); while( $row = $GLOBALS['DB']->fetchAssoc() ) { if( $name == "Number of Agora visited" && $row['key'] == "10" ) $row['key'] = "10+"; if( $name == "Meals" ) $row['key'] = $Meals[ $row['key'] ]; $html .= ""; $html .= ""; $html .= ""; $html .= ""; $html .= ""; $data[ $row['key'] ] = $row['amount']; } $html .= "
" . $name . "Amount
" . $row['key'] . "" . $row['amount'] . "" . number_format($row['amount'] / $period[$p]['sum'] * 100, 1) . "%
"; $json = array(); $json['generated'] = date("Y-m-d H:i:s"); $json['total'] = $period[$p]['sum']; $json['data'] = $data; $chart = new Chart($name, $data, 10, FULL_PATH . "tmp/"); $data = array(); $data['selection'] = $period[$p]['name']; $data['title'] = $name; $data['date'] = date("Y-m-d H:i:s"); $data['html'] = $html; $data['json'] = json_encode($json); $data['image'] = $chart->pie(300); $data['image_height'] = $chart->get_height("pie"); $data['image_width'] = $chart->get_width("pie"); if( $GLOBALS['DB']->insert("statistics", $data) ) { $this->addMessage("Created '" . $name . " (" . $period[$p]['name'] . ")'"); }else { $this->addMessage("Failed creating '" . $name . " (" . $period[$p]['name'] . ")'"); } } } } } private function createStatsUnlimitedOptions($period) { global $setup; for( $p=0; $p < count($period); $p += (date("Y-m-d") >= get_sql_date($setup['EventDateStart']) ? 2 : 1) ) { $stats = array(); $stats['Year of birth'] = $this->createQueryStatsYearOfBirth($period[$p]["queryWhere"]); $stats['Body'] = $this->createQueryStatsBody($period[$p]["queryWhere"]); $stats['Country'] = $this->createQueryStatsCountry($period[$p]["queryWhere"]); foreach( $stats as $name => $query ) { if( $GLOBALS['DB']->select($query) > 0 ) { $html = ""; $data = array(); $jsonData = array(); $other = 0; while( $row = $GLOBALS['DB']->fetchAssoc() ) { if( $name == "Country" ) $row['key'] = ucwords(strtolower($row['key'])); if( count($data)>10 ) { $other += $row['amount']; }else { $data[ $row['key'] ] = $row['amount']; } $jsonData[ $row['key'] ] = $row['amount']; } ksort($data); ksort($jsonData); $data['(Other)'] = $other; $row = 0; foreach( $data as $key => $value ) { $html .= ""; $html .= ""; $html .= ""; $html .= ""; $html .= ""; $row++; } $html .= "
" . $name . "Amount
" . $key . "" . $value . "" . number_format($value / $period[$p]['sum'] * 100, 1) . "%
"; if( $name == "Country" ) { $html .= "

Most European bodies (Commissions, Working Groups, Projects) are registered in Belgium. The country shown is the country of the body for which a person applied.

"; } $json = array(); $json['generated'] = date("Y-m-d H:i:s"); $json['total'] = $period[$p]['sum']; if( $name == "Body" || $name == "Country" ) { $json['data'] = $jsonData; }else { $json['data'] = $data; } $chart = new Chart($name, $data, 10, FULL_PATH . "tmp/"); $data = array(); $data['selection'] = $period[$p]['name']; $data['title'] = $name; $data['date'] = date("Y-m-d H:i:s"); $data['html'] = $html; $data['json'] = json_encode($json); $data['image'] = $chart->pie(300); $data['image_height'] = $chart->get_height("pie"); $data['image_width'] = $chart->get_width("pie"); if( $GLOBALS['DB']->insert("statistics", $data) ) { $this->addMessage("Created '" . $name . " (" . $period[$p]['name'] . ")'"); }else { $this->addMessage("Failed creating '" . $name . " (" . $period[$p]['name'] . ")'"); } } } } } private function createQueryStats($field, $accepted) { $queryBuilder = $this->createQueryStatsQueryBuilder($accepted); $queryBuilder->addField($field, "key"); return $queryBuilder->toQuery(); } private function createQueryStatsYearOfBirth($accepted) { $queryBuilder = $this->createQueryStatsQueryBuilder($accepted); $queryBuilder->addField(new DBMethodLeft("datebirth", 4), "key"); $queryBuilder->addOrderDesc("amount"); return $queryBuilder->toQuery(); } private function createQueryStatsBody($accepted) { $queryBuilder = $this->createQueryStatsQueryBuilder($accepted); $queryBuilder->addField("ab_bodies.bodyname", "key"); $queryBuilder->addInnerJoin("ab_bodies", "bodycode", "applications.bodycode"); $queryBuilder->addOrderDesc("amount"); return $queryBuilder->toQuery(); } private function createQueryStatsCountry($accepted) { $queryBuilder = $this->createQueryStatsQueryBuilder($accepted); $queryBuilder->addField("countrycodes.name", "key"); $queryBuilder->addInnerJoin("ab_bodies", "bodycode", "applications.bodycode"); $queryBuilder->addInnerJoin("countrycodes", "postal", "ab_bodies.countrycode"); $queryBuilder->addOrderDesc("amount"); return $queryBuilder->toQuery(); } private function createQueryStatsQueryBuilder($accepted) { $queryBuilder = new QueryBuilder($GLOBALS['DB'], "applications"); $queryBuilder->addField(new DBMethodCount("applications.id"), "amount"); if( $accepted != NULL ) { $queryBuilder->addWhereIn("accepted", $accepted); } $queryBuilder->addGroup("key"); return $queryBuilder; } } ?>