Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Eineki cracked the algorithm. The part missing from my attempts was having the start <strong>and</strong> the stop time available in each multiplier range. I value the density of data in my original rateTable, so I used the guts of Eineki's convert() routine to take the table stored in config and add the stop times in. My code already auto-created (or filled in) a minimal rate table, guaranteeing that the rest of the code won't choke or throw warning/errors, so I included that. I also condensed bill() and map_shift() together since in my mind the two don't have any useful purpose without each other.</p> <pre><code>&lt;?php //----------------------------------------------------------------------- function CompactSliceData($start, $stop, $multiplier) // Used by the VerifyRateTable() to change the format of the multiplier table. { return compact('start', 'stop','multiplier'); } //----------------------------------------------------------------------- function VerifyAndConvertRateTable($configRateTable) // The rate table must contain keyed elements for all 7 days of the week. // Each subarray must contain at LEAST a single entry for '00:00:00' =&gt; // 1 and '23:59:59' =&gt; 1. If the first entry does not start at midnight, // a new element will be added to the array to represent this. If given // an empty array, this function will auto-vivicate a "default" rate // table where all time is billed at 1.0x. { $weekDays = array('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday',); // Not very i18n friendly? $newTable = array(); foreach($weekDays as $day) { if( !array_key_exists($day, $configRateTable) || !is_array($configRateTable[$day]) || !array_key_exists('00:00:00', $configRateTable[$day]) ) { $configRateTable[$day]['00:00:00'] = 1; } if( !array_key_exists($day, $configRateTable) || !is_array($configRateTable[$day]) || !array_key_exists('23:59:59', $configRateTable[$day]) ) { $configRateTable[$day]['23:59:59'] = 1; } // Convert the provided table format to something we can work with internally. // Ref: http://stackoverflow.com/questions/2792048/slicing-a-time-range-into-parts $newTable[$day] = array_slice( array_map( 'CompactSliceData', array_keys($configRateTable[$day]), array_keys(array_slice($configRateTable[$day],1)), $configRateTable[$day]), 0,-1); } return $newTable; } //----------------------------------------------------------------------- function SliceTimeEntry($dayTable, $start, $stop) // Iterate through a day's table of rate slices and split the $start/$stop // into parts along the boundaries. // Ref: http://stackoverflow.com/questions/2792048/slicing-a-time-range-into-parts { $report = array(); foreach($dayTable as $slice) { if ($start &lt; $slice['stop'] &amp;&amp; $stop &gt; $slice['start']) { $report[] = array( 'start'=&gt; max($start, $slice['start']), 'stop' =&gt; min($stop, $slice['stop']), 'multiplier' =&gt; $slice['multiplier'] ); } } return $report; } /* examples */ $rateTable = array( 'Monday' =&gt; array('00:00:00' =&gt; 1.5, '08:00:00' =&gt; 1, '17:00:00' =&gt; 1.5), 'Tuesday' =&gt; array('00:00:00' =&gt; 1.5, '08:00:00' =&gt; 1, '17:00:00' =&gt; 1.5), 'Wednesday' =&gt; array('00:00:00' =&gt; 1.5, '08:00:00' =&gt; 1, '17:00:00' =&gt; 1.5), 'Thursday' =&gt; array('00:00:00' =&gt; 1.5, '08:00:00' =&gt; 1, '17:00:00' =&gt; 1.5), 'Friday' =&gt; array('00:00:00' =&gt; 1.5, '08:00:00' =&gt; 1, '17:00:00' =&gt; 1.5), 'Saturday' =&gt; array('00:00:00' =&gt; 1.5, '15:00:00' =&gt; 2), 'Sunday' =&gt; array('00:00:00' =&gt; 1.5, '15:00:00' =&gt; 2), ); $rateTable = VerifyAndConvertRateTable($rateTable); print_r(SliceTimeEntry($rateTable['Monday'],'08:05:00','18:05:00')); print_r(SliceTimeEntry($rateTable['Monday'],'08:05:00','12:00:00')); print_r(SliceTimeEntry($rateTable['Tuesday'],'07:15:00','19:30:00')); print_r(SliceTimeEntry($rateTable['Tuesday'],'07:15:00','17:00:00')); ?&gt; </code></pre> <p>Thanks everyone, especially Eineki.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload