Рубрики
Без рубрики

Рисование блоков на командной строке с Python

Эй, ребята! Я только что присоединился к сообществу здесь, и я думал, что поделюсь интересным маленьким кроликом Hol … Теги с Python, FirstPost, Учебник.

Эй, ребята! Я только что присоединился к сообществу здесь, и я думал, что поделюсь интересной маленькой кроликой, я недавно упал.

Цель

Пару недель назад я выпустил прогрессировать ; Пакет Python для рисования стержней прогресса на командной строке:

apple harvest   █▎                     1 /   9 •  11%
banana harvest  ██                     9 /  99 •   9%
caramel harvest ███████████████████▉ 100 / 100 • 100%

Пакет делает пару классных вещей, но я собираюсь сосредоточиться на моем подходе к рисованию бара.

Первый выстрел

Мой первоначальный план для бара был просто для расчета количества доступных пространств, затем заполните правильный процент от него с помощью Unicode «Полный блок» ( ) символ.

Так, например, батончик длины 10 и процент 0,50.0 быть 0% и 1.0 быть на 100%) будет выглядеть так:

[█████     ]

Вот какой-то код, который соответствует этому правилу:

from decimal import Decimal

EMPTY = " "

def make_bar(length: int, pc: Decimal) -> str:
    """
    Returns a string describing a bar "length" characters long
    and filled to "pc" percent (0.0 to 1.0).
    """
    render = list(EMPTY * length)
    # Percentage of the length that each element represents:
    element_pc = Decimal(1) / length

    for index in range(length):
        # Take a slice of the percentage for this element:
        block_pc = (pc - (index * element_pc)).min(element_pc)
        # Calculate how full this block needs to be:
        block_fill_pc = (1 / element_pc) * block_pc
        # Add an appropriate character to the render:
        render[index] = make_char(block_fill_pc)

    return "".join(render)


def make_char(pc: Decimal) -> str:
    """
    Gets a character that represents "pc" percent (0.0 - 1.0).
    """
    FULL_BLOCK = 0x2588
    return EMPTY if pc < Decimal(0.5) else chr(FULL_BLOCK)

Итак, скажем, я хочу нарисовать батончик длиной 3 и процент 0,7 Отказ Внутри make_bar. () :

  1. оказывать устанавливается в список из 3 пробелов.
  2. element_pc установлен на 0,33 , поскольку каждый элемент в списке представляет 33% барной зоны.
  3. В итерации индекс :

    1. block_pc Установлено на количество полоса, которая будет описана первым блоком. Расчет для этого (В процентах полного бара - процент, уже отображаемый предыдущими индексами) .min (максимальный процент, который может представлять каждый блок) . Что .min.min (...) мешает нам отказаться от большего количества, чем мы можем жевать; Каждый блок может описать только столько, сколько его максимум, и любые остатки должны быть описаны последующими блоками. Итак, block_pc установлен на (0,7 - (0 * 0,33)). Мин (0,33) или 0,33 Отказ
    2. block_fill_pc устанавливается на процент полной нессы этого блока. Каждый блок представляет 0,33 площади и block_pc это 0,33 Так что этот блок должен быть 1.0 (100%) полный.
    3. Мы передаем это 1.0 к make_char () и – поскольку 1,0> 0,5 – Мы получаем полный блок Unicode.
  4. В итерации индекс :

    1. block_pc Установлено на сумму полоса, который будет описан вторым блоком: (0,7 - (1 * 0,33)). Мин (0,33) или 0,33 Отказ
    2. block_fill_pc устанавливается на процент полной нессы этого блока. Каждый блок представляет 0,33 площади и block_pc это 0,33 Так что этот блок должен быть 1.0 полный.
    3. Мы передаем это 1.0 к make_char () и – поскольку 1,0> 0,5 – Мы получаем полный блок Unicode.
  5. В итерации индекс :

    1. block_pc Установлено на количество полоса, которая будет описана третьим блоком: (0,7 - (2 * 0,33)). Min (0,33) или 0,04 Отказ
    2. block_fill_pc устанавливается на процент полной нессы этого блока. Каждый блок представляет 0,33 площади и block_pc это 0,04 Так что этот блок должен быть 0,12 полный.
    3. Мы передаем это 0,12 к make_char () и – поскольку 0,12 <0,5 – Мы получаем пустое пространство назад.
  6. Наконец, мы присоединяемся к оказывать Вместе, чтобы получить бар в виде строки, содержащей два полных блока Unicode и пустой строки.

Мы можем запустить это для ряда рядов постоянно растущих процентов с таким кодом:

if __name__ == "__main__":
    """
    Print a series of rows with ever-increasing percentages.
    """
    ROW_COUNT = 11
    iteration_pc = (Decimal(1) / (ROW_COUNT - 1))
    for index in range(ROW_COUNT):
        pc = iteration_pc * index
        bar = make_bar(length=6, pc=pc)
        print(f"{pc:0.2f}: [{bar}]")

И вот наш красивый вывод!

0.00: [      ]
0.10: [█     ]
0.20: [█     ]
0.30: [██    ]
0.40: [██    ]
0.50: [███   ]
0.60: [████  ]
0.70: [████  ]
0.80: [█████ ]
0.90: [█████ ]
1.00: [██████]

Ну, не так красивая

Это Хорошо , но это не Красивая Отказ Согласно этим барам, 0,10 и 0.20 такие же, как есть 0,30 и 0,40 , 0,60 и 0,70 и 0,80 и 0,90 Отказ

Не было бы неплохо добавить еще немного гранулярности?

Не было бы неплохо, если бы мы могли нарисовать блоки, которые были меньше, чем ширина полного персонажа?

Ну, мы можем!

В то время как персонаж Unicode 0x2588 Представляет полный блок, есть также серия символов Unicode, которые описывают восьмые блока:

0x2588. Левый 8/8 (полный блок)
0x2589. Оставил 7/8
0x258a. Оставил 6/8
0x258b. Оставил 5/8
0x258c. Оставил 4/8
0x258d. Оставил 3/8
0x258e. Оставил 2/8
0x258f. Оставил 1/8

Сделай это красивым!

Итак, давайте обновим make_char () Чтобы вернуть один из этих символов вместо двоичного «ON или OFF» для каждого блока:

from math import ceil

def make_char(pc: Decimal) -> str:
    """
    Gets a character that represents "pc" percent (0.0 - 1.0).
    """
    eighths = ceil(pc * 8)
    return chr(0x2590 - eighths) if eighths > 0 else EMPTY

По сути, мы можем рассчитать, сколько восьмых процентов состоит в том, чтобы умножить его на 8:

  • 0,000 ( 0.000 * 8 ) это 0 восьмые.
  • 0,125 ( 0.125 * 8 ) IS 1 восьмой.
  • 0.250 ( 0,250 * 8 ) Это 2 восьмые.
  • 0,375 ( 0,375 * 8 ) это 3 восьмые.
  • 0.500 ( 0.500 * 8 ) это 4 восьмые.
  • 0.625 ( 0,625 * 8 ) это 5 восьмые.
  • 0.750 ( 0,750 * 8 ) это 6 восьмые.
  • 0.875 ( 0,875 * 8 ) это 7 восьмые.
  • 1.000 ( 1.000 * 8 ) это 8 восьмые.

Когда мы знаем, сколько восьмых процентов, мы можем вычесть, что компенсировать от 0x2590 Чтобы получить правильный символ:

  • 0x2590 - (1/8)
  • 0x2590 - (2/8)
  • 0x2590 - (3/8)
  • 0x2590 - (4/8)
  • 0x2590 - (5/8)
  • 0x2590 - (6/8)
  • 0x2590 - (7/8)
  • 0x2590 - (8/8)

Теперь, если мы запустим код с обновленным make_char () Функция:

0.00: [      ]
0.10: [▋     ]
0.20: [█▎    ]
0.30: [█▉    ]
0.40: [██▌   ]
0.50: [███   ]
0.60: [███▋  ]
0.70: [████▎ ]
0.80: [████▉ ]
0.90: [█████▌]
1.00: [██████]

Та-да! Каждая ряд теперь имеет Многое Более точный бар!

Фактически, с одним быстрым изменением скрипта мы можем создать строку для каждого возможного частичного блока:

if __name__ == "__main__":
    """
    Print a series of rows with ever-increasing percentages.
    """
    LENGTH = 2
    ROW_COUNT = (8 * LENGTH) + 1
    iteration_pc = (Decimal(1) / (ROW_COUNT - 1))
    for index in range(ROW_COUNT):
        pc = iteration_pc * index
        bar = make_bar(length=LENGTH, pc=pc)
        print(f"{pc:0.2f}: [{bar}]")
0.00: [  ]
0.06: [▏ ]
0.12: [▎ ]
0.19: [▍ ]
0.25: [▌ ]
0.31: [▋ ]
0.38: [▊ ]
0.44: [▉ ]
0.50: [█ ]
0.56: [█▏]
0.62: [█▎]
0.69: [█▍]
0.75: [█▌]
0.81: [█▋]
0.88: [█▊]
0.94: [█▉]
1.00: [██]

Теперь, кто сказал, что инструменты командной строки не могут быть красивыми?

Рекомендуемая Фото Уэсли Тинги. на Бессмысленно .

Оригинал: “https://dev.to/cariad/drawing-blocks-on-the-command-line-with-python-3pn7”