den1008/progress-status

计算进度

2.0.1 2021-06-10 11:41 UTC

This package is auto-updated.

Last update: 2024-09-10 19:06:50 UTC


README

ProgressStatus 是一个用于计算多模块程序总体执行进度的简单易用的组件,适用于 PHP

安装

$ composer require den1008/progress-status

使用

主要元素是 StatusProcessor,它实现了计算进度的功能,需要传递处理程序,具体取决于需要将进度信息输出到何处。目前有两个处理程序:StdOutStatusFileStatus,但您可以编写自己的类似处理程序。

StatusProcessor

为了通知用户进度变化,有两种方法:say()sayStage()

$status->say();      //Вывод сообщений об изменении прогресса
$status->sayStage(); //Вывод сообщений об изменении этапа выполнения

注意!所有处理程序都必须实现接口 IStatusHandler(方法 sayStageConcrete()sayConcrete(),而不是方法 sayStage()say())。这是为了能够筛选处理程序的消息。示例

$processor = new StatusProcessor([new SomeStatusHandler()]);
$processor->setTotal(100)
       ->setStepProcessingProgress(25); //Теперь все хэндлеры будут получать сообщения с шагом 25%
for ($i = 0; $i < 100; $i++){
    $processor->increaseProgress()->say('processing');
}

输出 SomeStatusHandler

[I completed 25%] processing
[I completed 50%] processing
[I completed 75%] processing
[I completed 100%] processing

使用 wrapSubProgram(Closure $func, $endProgress) 方法在嵌套子程序中计算统计数据,其中 $func 是要执行的子程序,而 $endProgress 是子程序完成时要达到的进度。示例使用

$processor = new StatusProcessor([new SomeStatusHandler()]);
//Необходимо обязательно задавать общее количество, иначе будет выброшено исключение.
//$processor->getNested() == 1 глубина вложенности
$processor->setTotal(1000);
  //{%total%} = 1000
  for ($i = 0; $i <= 20; $i += 10) {
     $processor->setProgress($i * 10);
     //$i=0  -->  {%percent%} = 0%,  {%progress%} = 0,   {%commonPercent%} = 0%
     //$i=10 -->  {%percent%} = 10%, {%progress%} = 100, {%commonPercent%} = 10%
     //$i=20 -->  {%percent%} = 20%, {%progress%} = 200, {%commonPercent%} = 20%

     $processor->say('Процесс 1 {%percent%}% элементов ({%progress%} из {%total%})');
  }
  //Запуск подпрограммы
  $processor->wrapSubProgram(function (StatusProcessor $processor){
     //$processor->getNested() == 2 глубина вложенности
     //Подпрограмма ничего не знает о родительском статусе выполнения, поэтому ведет собственный расчет от 0 до {%total%}
     //Если не указать общее количество, процент выполнения будет равен 100%.
     $processor->setTotal(50);
     //{%total%} = 50

     for ($i = 0; $i < 5; $i++) {
         $processor->increaseProgress(10);
         //$i=0  -->  {%percent%} = 20%,  {%progress%} = 10, {%commonPercent%} = 28%
         //$i=1  -->  {%percent%} = 40%,  {%progress%} = 20, {%commonPercent%} = 36%
         //$i=2  -->  {%percent%} = 60%,  {%progress%} = 30, {%commonPercent%} = 44%
         //$i=3  -->  {%percent%} = 80%,  {%progress%} = 40, {%commonPercent%} = 52%
         //$i=4  -->  {%percent%} = 100%, {%progress%} = 50, {%commonPercent%} = 60%

         //Здесь параметры {%progress%} из {%total%} будут для текущего контекста, но {%commonPercent%}% - для общего
         $processor->say('Процесс 2 {%commonPercent%}% элементов ({%progress%} из {%total%})');
     }
  }, 600); //Здесь 600 - прогресс который будет достигнут после выполнения подпрограммы
  //$processor->getNested() == 1 глубина вложенности
  //{%commonPercent%} == {%percent%} == 60%, т.к. ни одна подпрограмма не была обернута
  //{%progress%} = 600
  //{%total%} = 1000

  for ($i = 60; $i <= 100; $i += 10) {
     $processor->setProgress($i * 10);
     //$i=60  -->  {%percent%} = 60%  {%progress%} = 600,  {%commonPercent%} = 60%
     //$i=70  -->  {%percent%} = 70%  {%progress%} = 700,  {%commonPercent%} = 70%
     //$i=80  -->  {%percent%} = 80%  {%progress%} = 800,  {%commonPercent%} = 80%
     //$i=90  -->  {%percent%} = 90%  {%progress%} = 900,  {%commonPercent%} = 90%
     //$i=100 -->  {%percent%} = 100% {%progress%} = 1000, {%commonPercent%} = 100%

     $processor->say('Процесс 1 {%percent%}% элементов ({%progress%} из {%total%})');
  }

StdOutStatusHandler

该组件将进度信息输出到 std。简单的使用示例如下

use den1008\ProgressStatus\handlers\StdOutStatusHandler;

// define status
$processor = new StatusProcessor([new StdOutStatusHandler()]);
$processor->setTotal(100);
for ($i = 0; $i < 100; $i++){
    $processor->increaseProgress()->say('processing');
}

执行脚本时,在控制台将输出以下行

[2019-04-16 19:36:51][  1.0%][    0.00] processing
[2019-04-16 19:36:51][  2.0%][    0.00] processing
...
[2019-04-16 19:36:51][100.0%][    0.00] processing

为了不在每次都打印新行,而是更新同一行,需要这样做

$handler = new StdOutStatusHandler(0); // изменение глубины вывода вложенных прогрессов

默认情况下,隐藏的嵌套进度深度为 1,即调用 say()sayStage() 方法时,深度 1 的每条消息都会在新行中输出。对于深度 2 的消息,进度将输出在同一行上。一般情况:如果隐藏消息的深度设置为 N,则深度 <= N 的所有消息都会在新行中输出,而深度 > N 的消息将输出在同一行上。

要更改输出消息的模板,需要更改以下公共字段

/** @var string Формат вывода */
 public $mainFormat = "[{%date%} {%time%}][{%commonPercent%}%][{%totalTime%}] {%msg%}";
 /** @var string Формат вывода скрытых однострочных статусов */
 public $hideFormat = "[{%date%} {%time%}][{%commonPercent%}%][{%totalTime%}] └ {%msg%}";
用于格式化消息的是 FormatMessageTrait。可用的输出参数
  • {%date%} - 当前日期
  • {%time%} - 当前时间
  • {%progress%} - 当前进度
  • {%total%} - 最大进度
  • {%time%} - 当前时间
  • {%percent%} - 当前执行百分比
  • {%commonPercent%} - 总执行百分比
  • {%totalTime%} - 每一步的总时间(从开始工作的时间点)
  • {%stepTime%} - 每一步的耗时(从最后一步的时间点)
  • {%msg%} - 消息

FileStatusHandler

该组件将进度信息输出到文件。简单的使用示例如下

use den1008\ProgressStatus\handlers\FileStatusHandler;

// define status
$processor = new StatusProcessor([new FileStatusHandler('path/to/file')]);
$processor->setTotal(100);
for ($i = 0; $i < 100; $i++){
    $processor->increaseProgress()->say('processing');
}

执行脚本时,在文件中将记录以下行

[2019-04-16 19:36:51][  1.0%] processing
[2019-04-16 19:36:51][  2.0%] processing
...
[2019-04-16 19:36:51][100.0%] processing

要更改输出消息的模板,需要更改以下类的字段

/** @var string Формат вывода */
public $format = "[{%date%} {%time%}][{%commonPercent%}] {%msg%}";

StdOutStatusHandler 类似,用于格式化消息也使用 FormatMessageTrait(参见上面的描述)。

测试

用于测试的是 PhpUnit

./vendor/bin/phpunit tests/