Tableau de bord
  • 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)

  • Implementation of object programming is preferred in this exercise
  • The basepne parameter should control the amount of randomness in the distribution of values throughout the given dates and it should be given as an integer from 0 to 100. It should also guarantee a minimum value per date. The baseline indicates the amount of randomness allowed in the distribution. This method can have several approaches depending on the algorithm used, so the actual value resulting of the baseline is open to interpretation. In the following examples we use it as the percentage of the total, divided amongst the total of days that have non-zero values (weekdays).
  • Example 1:
  • $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

    )

  • Example 2:
  • $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,

    )

  • Example 3:
  • $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

    )

  • All dates within the range should be included in the array.

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 || $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 $ratio2);
        }
        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');
}