@ 2014-02-03T12:02:41Z <?php
class Cache
{
public static function has( $name ){
return false;
}
public static function get( $name ){
return null;
}
public static function put( $name, $value, $time = 1440 ){
return true;
}
}
class Collivery
{
protected $token;
protected $client;
protected $config;
protected $errors = array();
protected $check_cache = 2;
protected $default_address_id;
protected $client_id;
protected $user_id;
/**
* Setup class with basic Config
*
* @param Array $config Configuration Array
*/
function __construct( array $config = array() )
{
$this->config = (object) array(
'app_name' => 'Default App Name', // Application Name
'app_version' => '0.0.1', // Application Version
'app_host' => '', // Framework/CMS name and version, eg 'Wordpress 3.8.1 WooCommerce 2.0.20' / 'Joomla! 2.5.17 VirtueMart 2.0.26d'
'app_url' => '', // URL your site is hosted on
'user_email' => 'demo@collivery.co.za',
'user_password' => 'demo',
'demo' => false,
);
foreach ( $config as $key => $value ) {
$this->config->$key = $value;
}
if ( $this->config->demo ){
$this->config->user_email = 'demo@collivery.co.za';
$this->config->user_password = 'demo';
}
$this->authenticate();
}
/**
* Setup the Soap Object
*
* @return SoapClient MDS Collivery Soap Client
*/
protected function init ()
{
if ( ! $this->client ){
try {
$this->client = new SoapClient( // Setup the soap client
'http://www.collivery.co.za/wsdl/v2', // URL to WSDL File
array( 'cache_wsdl' => WSDL_CACHE_NONE ) // Don't cache the WSDL file
);
} catch (SoapFault $e) {
$this->catchSoapFault( $e );
return false;
}
}
return true;
}
/**
* Checks if the Soap Client has been set, and returns it.
*
* @return SoapClient Webserver Soap Client
*/
protected function client()
{
if ( ! $this->client ) {
$this->init();
}
if ( ! $this->token ) {
$this->authenticate();
}
return $this->client;
}
/**
* Authenticate and set the token
*
* @return string
*/
protected function authenticate()
{
if ( ( $this->check_cache == 2 ) && Cache::has('collivery.auth') ) {
$authenticate = Cache::get('collivery.auth');
$this->default_address_id = $authenticate['default_address_id'];
$this->client_id = $authenticate['client_id'];
$this->user_id = $authenticate['user_id'];
$this->token = $authenticate['token'];
return true;
} else {
if ( ! $this->init() ) return false;
$user_email = $this->config->user_email;
$user_password = $this->config->user_password;
try {
$authenticate = $this->client->authenticate($user_email, $user_password, $this->token,
array(
'name' => $this->config->app_name . ' mds/collivery/class',
'version' => $this->config->app_version,
'host' => $this->config->app_host,
'url' => $this->config->app_url,
'lang' => 'PHP '. phpversion(),
));
} catch (SoapFault $e) {
$this->catchSoapFault( $e );
return false;
}
if ( is_array( $authenticate ) && isset( $authenticate['token'] ) ){
if ( $this->check_cache != 0 ) Cache::put( 'collivery.auth', $authenticate, 50 );
$this->default_address_id = $authenticate['default_address_id'];
$this->client_id = $authenticate['client_id'];
$this->user_id = $authenticate['user_id'];
$this->token = $authenticate['token'];
return true;
} else {
if ( isset( $result['error_id'] ) )
$this->setError( $result['error_id'], $result['error'] );
else
$this->setError( 'result_unexpected', 'No address_id returned.' );
return false;
}
}
}
/**
* Returns a list of avaibale parcel images for a given Waybill Number.
*
* @param int $collivery_id Collivery waybill number
* @return array
*/
public function getParcelImageList( $collivery_id )
{
if ( ( $this->check_cache == 2 ) && Cache::has( 'collivery.parcel_image_list.'. $this->client_id .'.'. $collivery_id ) ) {
return Cache::get( 'collivery.parcel_image_list.'. $this->client_id .'.'. $collivery_id );
} else {
try {
$result = $this->client()->get_parcel_image_list( $collivery_id, $this->token );
} catch (SoapFault $e) {
$this->catchSoapFault( $e );
return false;
}
if ( isset( $result['images'] ) ) {
if ( isset( $result['error_id'] ) )
$this->setError( $result['error_id'], $result['error'] );
else
if ( $this->check_cache != 0 ) Cache::put( 'collivery.parcel_image_list.'. $this->client_id .'.'. $collivery_id, $result['images'], 60*12 );
return $result['images'];
} else {
if ( isset( $result['error_id'] ) )
$this->setError( $result['error_id'], $result['error'] );
else
$this->setError( 'result_unexpected', 'No address_id returned.' );
return false;
}
}
}
/**
* Returns the image of a given parcel-id of a waybill.
* If the Waybill number is 54321 and there are 3 parcels, they would
* be referenced by id's 54321-1, 54321-2 and 54321-3.
*
* @param string $parcel_id Parcel ID
* @return array Array containing all the information
* about the image including the image
* itself in base64
*/
public function getParcelImage( $parcel_id )
{
if ( ( $this->check_cache == 2 ) && Cache::has( 'collivery.parcel_image.'. $this->client_id .'.'. $parcel_id ) ) {
return Cache::get( 'collivery.parcel_image.'. $this->client_id .'.'. $parcel_id );
} else {
try {
$result = $this->client()->get_parcel_image( $parcel_id, $this->token );
} catch (SoapFault $e) {
$this->catchSoapFault( $e );
return false;
}
if ( isset( $result['image'] ) ) {
if ( isset( $result['error_id'] ) )
$this->setError( $result['error_id'], $result['error'] );
else
if ( $this->check_cache != 0 ) Cache::put( 'collivery.parcel_image.'. $this->client_id .'.'. $parcel_id, $result['image'], 60*24 );
return $result['image'];
} else {
if ( isset( $result['error_id'] ) )
$this->setError( $result['error_id'], $result['error'] );
else
$this->setError( 'result_unexpected', 'No address_id returned.' );
return false;
}
}
}
/**
* Returns the status tracking detail of a given Waybill number.
* If the collivery is still active, the estimated time of delivery
* will be provided. If delivered, the time and receivers name (if availble)
* with returned.
*
* @param int $collivery_id Collivery ID
* @return array Collivery Status Information
*/
public function getStatus( $collivery_id )
{
if ( ( $this->check_cache == 2 ) && Cache::has( 'collivery.status.'. $this->client_id .'.'. $collivery_id ) ) {
return Cache::get( 'collivery.status.'. $this->client_id .'.'. $collivery_id );
} else {
try {
$result = $this->client()->get_collivery_status( $collivery_id, $this->token );
} catch (SoapFault $e) {
$this->catchSoapFault( $e );
return false;
}
if ( isset( $result['status_id'] ) ) {
if ( isset( $result['error_id'] ) )
$this->setError( $result['error_id'], $result['error'] );
else
if ( $this->check_cache != 0 ) Cache::put( 'collivery.status.'. $this->client_id .'.'. $collivery_id, $result, 60*12 );
return $result;
} else {
if ( isset( $result['error_id'] ) )
$this->setError( $result['error_id'], $result['error'] );
else
$this->setError( 'result_unexpected', 'No address_id returned.' );
return false;
}
}
}
/**
* Create a new Address and Contact
*
* @param array $data Address and Contact Information
* @return array Address ID and Contact ID
*/
public function addAddress( array $data )
{
if ( ! isset( $data['location_type'] ) )
$this->setError( 'missing_data', 'location_type not set.' );
elseif ( ! isset( $this->getLocationTypes()[ $data['location_type'] ] ) )
$this->setError( 'invalid_data', 'Invalid location_type.' );
if ( ! isset( $data['town_id'] ) )
$this->setError( 'missing_data', 'town_id not set.' );
elseif ( ! isset( $this->getTowns()[ $data['town_id'] ] ) )
$this->setError( 'invalid_data', 'Invalid town_id.' );
if ( ! isset( $data['suburb_id'] ) )
$this->setError( 'missing_data', 'suburb_id not set.' );
elseif ( ! isset( $this->getSuburbs( $data['town_id'] )[ $data['suburb_id'] ] ) )
$this->setError( 'invalid_data', 'Invalid suburb_id.' );
if ( ! isset( $data['street'] ) )
$this->setError( 'missing_data', 'street not set.' );
if ( ! isset( $data['full_name'] ) )
$this->setError( 'missing_data', 'full_name not set.' );
if ( isset( $data['phone'] ) || isset( $data['cellphone'] ) )
$this->setError( 'missing_data', 'Please supply ether a phone or cellphone number...' );
if ( ! $this->hasErrors() ) {
try {
$result = $this->client()->add_address( $data, $this->token );
Cache::forget( 'collivery.addresses.'. $this->client_id );
} catch (SoapFault $e) {
$this->catchSoapFault( $e );
return false;
}
if ( isset( $result['address_id'] ) ) {
return $result;
} else {
if ( isset( $result['error_id'] ) )
$this->setError( $result['error_id'], $result['error'] );
else
$this->setError( 'result_unexpected', 'No address_id returned.' );
return false;
}
}
}
/**
* Add's a contact person for a given Address ID
*
* @param array $data New Contact Data
* @return int New Contact ID
*/
public function addContact( array $data )
{
if ( ! isset( $data['address_id'] ) )
$this->setError( 'missing_data', 'address_id not set.' );
elseif ( ! is_array( $this->getAddress( $data['address_id'] ) ) )
$this->setError( 'invalid_data', 'Invalid address_id.' );
if ( ! isset( $data['street'] ) )
$this->setError( 'missing_data', 'street not set.' );
if ( ! isset( $data['full_name'] ) )
$this->setError( 'missing_data', 'full_name not set.' );
if ( isset( $data['phone'] ) || isset( $data['cellphone'] ) )
$this->setError( 'missing_data', 'Please supply ether a phone or cellphone number...' );
if ( ! $this->hasErrors() ) {
try {
$result = $this->client()->add_address( $data, $this->token );
Cache::forget( 'collivery.addresses.'. $this->client_id );
} catch (SoapFault $e) {
$this->catchSoapFault( $e );
return false;
}
if ( isset( $result['address_id'] ) ) {
return $result;
} else {
if ( isset( $result['error_id'] ) )
$this->setError( $result['error_id'], $result['error'] );
else
$this->setError( 'result_unexpected', 'No address_id returned.' );
return false;
}
}
}
/**
* Returns the price based on the data provided.
*
* @param array $data Your Collivery Details
* @return array Pricing for details supplied
*/
public function getPrice( array $data )
{
if ( ! isset( $data['collivery_from'] ) && ! isset( $data['from_town_id'] ) )
$this->setError( 'missing_data', 'collivery_from/from_town_id not set.' );
elseif ( isset( $data['collivery_from'] ) && ! is_array( $this->getAddress( $data['collivery_from'] ) ) )
$this->setError( 'invalid_data', 'Invalid Address ID for: collivery_from.' );
elseif ( isset( $data['from_town_id'] ) && ! isset( $this->getTowns()[ $data['from_town_id'] ] ) )
$this->setError( 'invalid_data', 'Invalid Town ID for: from_town_id.' );
if ( ! isset( $data['collivery_to'] ) && ! isset( $data['to_town_id'] ) )
$this->setError( 'missing_data', 'collivery_to/to_town_id not set.' );
elseif ( isset( $data['collivery_to'] ) && ! is_array( $this->getAddress( $data['collivery_to'] ) ) )
$this->setError( 'invalid_data', 'Invalid Address ID for: collivery_to.' );
elseif ( isset( $data['to_town_id'] ) && ! isset( $this->getTowns()[ $data['to_town_id'] ] ) )
$this->setError( 'invalid_data', 'Invalid Town ID for: to_town_id.' );
if ( ! isset( $data['service'] ) )
$this->setError( 'missing_data', 'service not set.' );
if ( ! $this->hasErrors() ) {
try {
$result = $this->client()->get_price( $data, $this->token );
} catch (SoapFault $e) {
$this->catchSoapFault( $e );
return false;
}
if ( is_array( $result ) ) {
if ( isset( $result['error_id'] ) )
$this->setError( $result['error_id'], $result['error'] );
return $result;
} else {
if ( isset( $result['error_id'] ) )
$this->setError( $result['error_id'], $result['error'] );
else
$this->setError( 'result_unexpected', 'No address_id returned.' );
return false;
}
}
}
/**
* Validate Collivery
*
* Returns the validated data array of all details pertaining to a collivery.
* This process validates the information based on services, time frames and parcel information.
* Dates and times may be altered during this process based on the collection and delivery towns service parameters.
* Certain towns are only serviced on specific days and between certain times.
* This function automatically alters the values.
* The parcels volumetric calculations are also done at this time.
* It is important that the data is first validated before a collivery can be added.
*
* @param array $data Properties of the new Collivery
* @return array The validated data
*/
public function validate( array $data )
{
if ( ! isset( $data['collivery_from'] ) )
$this->setError( 'missing_data', 'collivery_from not set.' );
elseif ( ! is_array( $this->getAddress( $data['collivery_from'] ) ) )
$this->setError( 'invalid_data', 'Invalid Address ID for: collivery_from.' );
if ( ! isset( $data['contact_from'] ) )
$this->setError( 'missing_data', 'contact_from not set.' );
elseif ( ! isset( $this->getContacts( $data['collivery_from'] )[ $data['contact_from'] ] ) )
$this->setError( 'invalid_data', 'Invalid Contact ID for: contact_from.' );
if ( ! isset( $data['collivery_to'] ) )
$this->setError( 'missing_data', 'collivery_to not set.' );
elseif ( ! is_array( $this->getAddress( $data['collivery_to'] ) ) )
$this->setError( 'invalid_data', 'Invalid Address ID for: collivery_to.' );
if ( ! isset( $data['contact_to'] ) )
$this->setError( 'missing_data', 'contact_to not set.' );
elseif ( ! isset( $this->getContacts( $data['collivery_from'] )[ $data['contact_to'] ] ) )
$this->setError( 'invalid_data', 'Invalid Contact ID for: contact_to.' );
if ( ! isset( $data['collivery_type'] ) )
$this->setError( 'missing_data', 'collivery_type not set.' );
elseif ( ! isset( $this->getParcelTypes()[ $data['collivery_type'] ] ) )
$this->setError( 'invalid_data', 'Invalid collivery_type.' );
if ( ! isset( $data['service'] ) )
$this->setError( 'missing_data', 'service not set.' );
elseif ( ! isset( $this->getServices()[ $data['service'] ] ) )
$this->setError( 'invalid_data', 'Invalid service.' );
if ( ! $this->hasErrors() ) {
try {
$result = $this->client()->validate_collivery( $data, $this->token );
} catch (SoapFault $e) {
$this->catchSoapFault( $e );
return false;
}
if ( is_array( $result ) ) {
if ( isset( $result['error_id'] ) )
$this->setError( $result['error_id'], $result['error'] );
return $result;
} else {
if ( isset( $result['error_id'] ) )
$this->setError( $result['error_id'], $result['error'] );
else
$this->setError( 'result_unexpected', 'No address_id returned.' );
return false;
}
}
}
/**
* Creates a new Collivery based on the data array provided.
* The array should first be validated before passing to this function.
* The Waybill No is return apon successful creation of the collivery.
*
* @param array $data Properties of the new Collivery
* @return int New Collivery ID
*/
public function addCollivery( array $data )
{
if ( ! isset( $data['collivery_from'] ) )
$this->setError( 'missing_data', 'collivery_from not set.' );
elseif ( ! is_array( $this->getAddress( $data['collivery_from'] ) ) )
$this->setError( 'invalid_data', 'Invalid Address ID for: collivery_from.' );
if ( ! isset( $data['contact_from'] ) )
$this->setError( 'missing_data', 'contact_from not set.' );
elseif ( ! isset( $this->getContacts( $data['collivery_from'] )[ $data['contact_from'] ] ) )
$this->setError( 'invalid_data', 'Invalid Contact ID for: contact_from.' );
if ( ! isset( $data['collivery_to'] ) )
$this->setError( 'missing_data', 'collivery_to not set.' );
elseif ( ! is_array( $this->getAddress( $data['collivery_to'] ) ) )
$this->setError( 'invalid_data', 'Invalid Address ID for: collivery_to.' );
if ( ! isset( $data['contact_to'] ) )
$this->setError( 'missing_data', 'contact_to not set.' );
elseif ( ! isset( $this->getContacts( $data['collivery_from'] )[ $data['contact_to'] ] ) )
$this->setError( 'invalid_data', 'Invalid Contact ID for: contact_to.' );
if ( ! isset( $data['collivery_type'] ) )
$this->setError( 'missing_data', 'collivery_type not set.' );
elseif ( ! isset( $this->getParcelTypes()[ $data['collivery_type'] ] ) )
$this->setError( 'invalid_data', 'Invalid collivery_type.' );
if ( ! isset( $data['service'] ) )
$this->setError( 'missing_data', 'service not set.' );
elseif ( ! isset( $this->getServices()[ $data['service'] ] ) )
$this->setError( 'invalid_data', 'Invalid service.' );
if ( ! $this->hasErrors() ) {
try {
$result = $this->client()->add_collivery( $data, $this->token );
} catch (SoapFault $e) {
$this->catchSoapFault( $e );
return false;
}
if ( isset( $result['collivery_id'] ) ) {
if ( isset( $result['error_id'] ) )
$this->setError( $result['error_id'], $result['error'] );
return $result['collivery_id'];
} else {
if ( isset( $result['error_id'] ) )
$this->setError( $result['error_id'], $result['error'] );
else
$this->setError( 'result_unexpected', 'No address_id returned.' );
return false;
}
}
}
/**
* Accepts the newly created Collivery, moving it from Waiting Client Acceptance
* to Accepted so that it can be processed.
*
* @param int $collivery_id ID of the Collivery you wish to accept
* @return boolean Has the Collivery been accepted
*/
public function acceptCollivery( $collivery_id )
{
try {
$result = $this->client()->accept_collivery( $collivery_id, $this->token );
} catch (SoapFault $e) {
$this->catchSoapFault( $e );
return false;
}
if ( isset( $result['result'] ) ) {
if ( isset( $result['error_id'] ) )
$this->setError( $result['error_id'], $result['error'] );
return $result['result'] == 'Accepted';
} else {
if ( isset( $result['error_id'] ) )
$this->setError( $result['error_id'], $result['error'] );
else
$this->setError( 'result_unexpected', 'No address_id returned.' );
return false;
}
}
/**
* Handle error messages in SoapFault
*
* @param SoapFault $e SoapFault Object
*/
protected function catchSoapFault( $e )
{
$this->setError( $e->faultcode, $e->faultstring );
}
/**
* Add a new error
*
* @param string $id Error ID
* @param string $text Error text
*/
protected function setError( $id, $text )
{
$this->errors[ $id ] = $text;
}
/**
* Retrieve errors
*/
public function getErrors()
{
return $this->errors;
}
/**
* Check if this instance has an error
*/
public function hasErrors()
{
return !empty($this->errors);
}
/**
* Clears all the Errors
*/
public function clearErrors()
{
$this->errors = array();
}
/**
* Disable Cached completely and retrieve data directly from the webservice
*/
public function disableCache()
{
$this->check_cache = 0;
}
/**
* Ignore Cached data and retrieve data directly from the webservice
* Save returned data to Cache
*/
public function ignoreCache()
{
$this->check_cache = 1;
}
/**
* Check if cache exists before querying the webservice
* If webservice was queried, save returned data to Cache
*/
public function enableCache()
{
$this->check_cache = 2;
}
}
Enable javascript to submit You have javascript disabled. You will not be able to edit any code.
Here you find the average performance (time & memory) of each version. A grayed out version indicates it didn't complete successfully (based on exit-code).
Version System time (s) User time (s) Memory (MiB) 7.4.0 0.011 0.011 15.17 7.3.12 0.006 0.009 14.74 7.3.11 0.016 0.006 14.69 7.3.10 0.006 0.009 14.86 7.3.9 0.000 0.013 15.08 7.3.8 0.007 0.003 14.86 7.3.7 0.004 0.011 14.64 7.3.6 0.007 0.007 14.91 7.3.5 0.004 0.011 14.84 7.3.4 0.010 0.000 14.90 7.3.3 0.003 0.012 14.93 7.3.2 0.003 0.010 16.61 7.3.1 0.004 0.012 16.46 7.3.0 0.007 0.007 16.51 7.2.25 0.010 0.013 14.79 7.2.24 0.008 0.008 15.01 7.2.23 0.011 0.003 14.93 7.2.22 0.013 0.003 15.17 7.2.21 0.012 0.006 15.01 7.2.20 0.007 0.007 14.99 7.2.19 0.009 0.009 14.95 7.2.18 0.004 0.011 15.00 7.2.17 0.007 0.010 14.73 7.2.0 0.008 0.005 18.92 7.1.33 0.010 0.003 15.23 7.1.32 0.010 0.007 15.39 7.1.31 0.003 0.007 15.61 7.1.30 0.008 0.003 15.41 7.1.29 0.003 0.010 15.66 7.1.28 0.003 0.009 15.30 7.1.27 0.010 0.003 15.61 7.1.26 0.006 0.009 15.38 7.1.10 0.009 0.000 18.00 7.1.7 0.005 0.005 17.05 7.1.6 0.013 0.013 19.43 7.1.5 0.023 0.013 34.45 7.1.0 0.000 0.070 22.32 7.0.20 0.007 0.004 16.37 7.0.14 0.007 0.070 22.01 7.0.10 0.003 0.073 20.20 7.0.9 0.007 0.080 20.20 7.0.8 0.010 0.077 20.09 7.0.7 0.010 0.077 20.18 7.0.6 0.003 0.093 20.23 7.0.5 0.020 0.070 20.48 7.0.4 0.007 0.090 20.14 7.0.3 0.013 0.077 20.13 7.0.2 0.013 0.080 20.13 7.0.1 0.007 0.087 20.12 7.0.0 0.013 0.077 20.13 5.6.28 0.010 0.070 20.91 5.6.25 0.007 0.077 20.95 5.6.24 0.007 0.047 20.71 5.6.23 0.013 0.067 20.64 5.6.22 0.013 0.040 20.78 5.6.21 0.003 0.087 20.76 5.6.20 0.017 0.077 21.16 5.6.19 0.007 0.083 21.30 5.6.18 0.010 0.073 21.25 5.6.17 0.010 0.063 21.08 5.6.16 0.007 0.087 21.17 5.6.15 0.010 0.047 21.25 5.6.14 0.017 0.073 21.16 5.6.13 0.007 0.050 21.15 5.6.12 0.010 0.040 21.15 5.6.11 0.013 0.077 21.16 5.6.10 0.003 0.087 21.21 5.6.9 0.003 0.053 21.14 5.6.8 0.003 0.053 20.52 5.6.7 0.010 0.073 20.62 5.6.6 0.010 0.077 20.53 5.6.5 0.007 0.083 20.63 5.6.4 0.000 0.060 20.52 5.6.3 0.010 0.077 20.57 5.6.2 0.010 0.070 20.49 5.6.1 0.007 0.083 20.46 5.6.0 0.010 0.073 20.49 5.5.38 0.007 0.080 20.70 5.5.37 0.010 0.070 20.58 5.5.36 0.007 0.083 20.43 5.5.35 0.010 0.097 20.59 5.5.34 0.013 0.080 20.83 5.5.33 0.010 0.080 21.00 5.5.32 0.007 0.087 20.97 5.5.31 0.013 0.043 21.00 5.5.30 0.020 0.070 20.99 5.5.29 0.007 0.090 20.93 5.5.28 0.007 0.070 20.90 5.5.27 0.007 0.050 21.01 5.5.26 0.013 0.080 20.99 5.5.25 0.003 0.060 20.85 5.5.24 0.003 0.083 20.32 5.5.23 0.007 0.053 20.24 5.5.22 0.010 0.057 20.31 5.5.21 0.010 0.080 20.31 5.5.20 0.013 0.043 20.39 5.5.19 0.007 0.073 20.41 5.5.18 0.010 0.047 20.13 5.5.16 0.013 0.073 20.30 5.5.15 0.013 0.073 20.41 5.5.14 0.007 0.083 20.40 5.5.13 0.017 0.067 20.28 5.5.12 0.003 0.067 20.11 5.5.11 0.003 0.077 20.39 5.5.10 0.013 0.073 20.21 5.5.9 0.017 0.073 20.18 5.5.8 0.007 0.083 20.24 5.5.7 0.007 0.083 20.20 5.5.6 0.007 0.050 20.20 5.5.5 0.007 0.047 20.29 5.5.4 0.013 0.073 20.28 5.5.3 0.023 0.063 20.18 5.5.2 0.010 0.077 20.19 5.5.1 0.000 0.083 20.23 5.5.0 0.010 0.080 20.16 5.4.45 0.013 0.077 19.41 5.4.44 0.007 0.080 19.49 5.4.43 0.003 0.087 19.29 5.4.42 0.010 0.077 19.42 5.4.41 0.000 0.087 19.16 5.4.40 0.013 0.053 19.13 5.4.39 0.007 0.070 18.96 5.4.38 0.003 0.083 19.23 5.4.37 0.003 0.077 19.06 5.4.36 0.003 0.053 19.12 5.4.35 0.013 0.067 18.93 5.4.34 0.007 0.083 19.09 5.4.32 0.007 0.073 19.13 5.4.31 0.007 0.077 19.10 5.4.30 0.010 0.070 19.28 5.4.29 0.010 0.073 19.18 5.4.28 0.007 0.070 19.12 5.4.27 0.007 0.080 19.10 5.4.26 0.020 0.070 19.15 5.4.25 0.003 0.043 19.18 5.4.24 0.017 0.067 19.17 5.4.23 0.010 0.077 18.91 5.4.22 0.007 0.080 19.09 5.4.21 0.003 0.050 19.17 5.4.20 0.003 0.087 18.96 5.4.19 0.010 0.080 19.01 5.4.18 0.013 0.070 18.91 5.4.17 0.003 0.077 19.09 5.4.16 0.023 0.043 19.08 5.4.15 0.010 0.070 19.16 5.4.14 0.010 0.067 16.53 5.4.13 0.003 0.060 16.31 5.4.12 0.000 0.077 16.42 5.4.11 0.007 0.073 16.48 5.4.10 0.007 0.080 16.49 5.4.9 0.007 0.070 16.59 5.4.8 0.003 0.050 16.48 5.4.7 0.003 0.073 16.43 5.4.6 0.010 0.070 16.45 5.4.5 0.010 0.060 16.36 5.4.4 0.007 0.077 16.36 5.4.3 0.003 0.077 16.51 5.4.2 0.010 0.067 16.45 5.4.1 0.010 0.063 16.41 5.4.0 0.003 0.077 16.01 5.3.29 0.007 0.060 14.80 5.3.28 0.007 0.080 14.81 5.3.27 0.010 0.073 14.75 5.3.26 0.010 0.077 14.80 5.3.25 0.010 0.067 14.66 5.3.24 0.010 0.073 14.63 5.3.23 0.007 0.073 14.81 5.3.22 0.007 0.073 14.62 5.3.21 0.017 0.073 14.65 5.3.20 0.003 0.073 14.64 5.3.19 0.003 0.057 14.79 5.3.18 0.003 0.080 14.63 5.3.17 0.003 0.077 14.57 5.3.16 0.003 0.080 14.78 5.3.15 0.010 0.073 14.57 5.3.14 0.010 0.063 14.69 5.3.13 0.000 0.050 14.56 5.3.12 0.013 0.073 14.69 5.3.11 0.017 0.070 14.56 5.3.10 0.010 0.070 14.09 5.3.9 0.003 0.073 14.18 5.3.8 0.017 0.063 14.13 5.3.7 0.000 0.083 14.21 5.3.6 0.000 0.043 14.19 5.3.5 0.020 0.060 14.14 5.3.4 0.007 0.060 13.91 5.3.3 0.000 0.040 14.05 5.3.2 0.007 0.060 13.76 5.3.1 0.003 0.073 13.78 5.3.0 0.003 0.053 13.73
preferences:dark mode live preview
59.32 ms | 400 KiB | 5 Q