exercice php
- Application
- Consignes
- php class Tableau
- php Ajax Handler
- Réinitialiser
Objective
- Distribute a total amount randomly (within certain parameters) in a range of dates, excluding weekends.
- There should be a baseline that will define the minimum amount of the value assigned to a specific date.
- The returned result should be a unidimensional array with the following structure:
Array(
[YYYY-mm-dd]=>0.00, // The value should be a float value (with two decimal places) corresponding to the date used as key
[YYYY-mm-dd]=>0.00,
[YYYY-mm-dd]=>0.00,
...
)
Requirements
- The values should be distributed only on weekdays, therefore the weekends should be included in the array and have zero as value assigned.
- The total sum of the values assigned in the resulting array should be within 1% above or below the total value given.
- Example:
$total=75300;
$distributed=array_sum($result);
// $distributed value can only be a maximum of 76053 or a minimum of 74547 (1% above and below 75300)
$baseline=20;
$total=100;
$start_date='2016-12-19';
$start_date='2016-12-23';
// This set of parameters should guarantee that each day will have a minimum value of 4
// Example result
Array(
[2016-12-19]=>12,
[2016-12-20]=>4.22,
[2016-12-21]=>34.53,
[2016-12-22]=>19.47,
[2016-12-23]=>29.78
)
$baseline=100;
$total=100;
$start_date='2016-12-21';
$start_date='2016-12-27';
// This set of parameters should guarantee that each day will have a minimum value of 20
// Example result
Array(
[2016-12-21]=>20,
[2016-12-22]=>20,
[2016-12-23]=>20,
[2016-12-22]=>0, // Saturday
[2016-12-23]=>0, // Sunday
[2016-12-24]=>20,
[2016-12-25]=>20,
)
$baseline=50;
$total=100;
$start_date='2016-12-19';
$start_date='2016-12-24';
// This set of parameters should guarantee that each day will have a minimum value of 10
// Example result
Array(
[2016-12-19]=>21.05,
[2016-12-20]=>12.91,
[2016-12-21]=>10,
[2016-12-22]=>29.65,
[2016-12-23]=>26.39,
[2016-12-24]=>0 // Saturday
)
Optional
- A user interface and/or user friendly results display using any or all of the following: HTML, CSS, jQuery, Bootstrap
- Asyncronous requests (using AJAX and JSON)
- Input parsing to prevent code injection/execution
- Responsiveness for the UI
Input parameters
@param date $start_date
@param date $end_date
@param integer $total
@param integer $baseline
Output:
@return array
<?php
class Tableau{
// Propriétés
private $_baseline;
private $_total;
private $_startDate;
private $_endDate;
private $_rand_array;
private $_errors;
//constructeur
function __construct($baseline, $total, $start, $end){
$this->set_baseline($baseline);
$this->set_total($total);
$this->set_start($start);
$this->set_end($end);
if(empty($this->_errors)){
$this->_rand_array = $this->set_rand_tableau();
}
}
//gestion erreurs
public function errors(){
return $this->_errors;
}
//setter baseline
private function set_baseline($baseline){
if(!is_numeric($baseline) || $baseline < 0 || $baseline > 100){
$this->_errors['baseline'] = "Le baseline doit être un nombre entier entre 0 et 100.";
return;
}
$this->_baseline = $baseline;
}
//setter total
private function set_total($total){
if(!is_numeric($total)){
$this->_errors['total'] = "Le total doit être un nombre entier";
return;
}
if($total < $this->_baseline){
$this->_errors['total'] = "Le total doit être égal ou supérieur au baseline.";
return;
}
$this->_total = $total;
}
//setter start_date
private function set_start($start){
if(!$this->validateDate($start)){
$this->_errors['start_date'] = "La date d'entrée n'est pas une date valide.";
return;
}
$this->_startDate = $start;
}
//setter end_date
private function set_end($end){
if(!$this->validateDate($end)){
$this->_errors['end_date'] = "La date de sortie n'est pas une date valide.";
return;
}
if(!(strtotime($end) > strtotime($this->_startDate))){
$this->_errors['end_date'] = "La date de fin doit être supérieure à la date de début.";
return;
}
$this->_endDate = $end;
}
//retourne le nombre de jours total
private function total_range(){
$start = date_create($this->_startDate);
$end = date_create($this->_endDate)->modify('+1 day');
$total_range = $start->diff($end);
$total_range = $total_range->format('%a');
return $total_range;
}
//retourne le nombre de jour de semaine
private function range_weekdays(){
$range = 0;
foreach ($this->period() as $key => $value) {
if(!$this->isWeekend($value->format('Y-m-d'))){
$range++;
}
}
return $range;
}
//retourne la periode de date
private function period(){
$period = new DatePeriod(date_create($this->_startDate), new DateInterval('P1D'), date_create($this->_endDate)->modify('+1 day'));
return $period;
}
//retourne la valeur minimum par date
private function minimum_value(){
$min_value = (($this->_baseline/$this->_total) / $this->range_weekdays()) *100;
if ($min_value > $this->_baseline * ($this->_total / array_sum($this->_rand_array))) {
$min_value = $this->_baseline * ($this->_total / array_sum($this->_rand_array));
}
return $min_value;
}
//retourne le tableau de date avec valeurs aléatoires temporaires
private function set_rand_tableau(){
$date_array = [];
foreach ($this->period() as $value) {
if ($this->isWeekend($value->format('Y-m-d'))) {
$date_array[$value->format('Y-m-d')] = 0.00;
} else {
$date_array[$value->format('Y-m-d')] = (mt_rand($this->_baseline, $this->_total));
}
}
return $date_array;
}
//retourne le tableau de date avec valeurs aléatoires finales
private function set_date_value(){
$final_array = $this->_rand_array;
$ratio = $this->_total / array_sum($final_array);
foreach ($final_array as $key => $value) {
$final_array[$key] = round($value * $ratio, 2);
}
return $final_array;
}
//retourne un booléen vrai si la date est un jour de fin de semaine
private function isWeekend($date){
return (date('N', strtotime($date)) >= 6);
}
//retourne un booléen vrai si la date est véritable
private function validateDate($date, $format = 'Y-m-d'){
$d = DateTime::createFromFormat($format, $date);
return $d && $d->format($format) == $date;
}
//retourne les différentes informations au handler
public function output_tableau(){
$tableau = $this->set_date_value();
$data['Valeur minimale'] = round($this->minimum_value(),2);
$data['Somme du tableau'] = array_sum($tableau);
$data['Jours total'] = $this->total_range();
$data['Jours de semaine'] = $this->range_weekdays();
$data['tableau'] = $tableau;
return $data;
}
}//fin class Tableau
<?php
//si requete ajax
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
//si baseline soumise
if(isset($_POST['baseline'])){
ini_set('date.timezone', 'America/Montreal');
require_once 'tableau.php';
//récupérer input
$baseline = $_POST['baseline'];
$total = $_POST['total'];
$start_date = $_POST['start_date'];
$end_date = $_POST['end_date'];
//instancier objet tableau
$tableau = new tableau($baseline,$total,$start_date,$end_date);
///retour à ajax
header('Content-Type: application/json');
//si erreurs
if(!empty($tableau->errors())){
http_response_code(206);
echo json_encode($tableau->errors());
//si tableau ok
}else{
http_response_code(202);
echo json_encode($tableau->output_tableau());
}
//si baseline non soumise
}else{
header('Location:index.php');
}
//si requête non ajax
}else{
header('Location:index.php');
}