Skip to content

Commit

Permalink
0.2.1 (#12)
Browse files Browse the repository at this point in the history
* docs: add another selection sort example
* feat: add first cycle sleep attribute
* fix: use fstrings
* docs: update example images
---------
Signed-off-by: Emilio Reyes <soda480@gmail.com>
  • Loading branch information
soda480 authored Sep 2, 2024
1 parent 0f66912 commit b7deede
Show file tree
Hide file tree
Showing 8 changed files with 96 additions and 9 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ A selection sort search is a simple and efficient sorting algorithm that works b

![example](https://raw.githubusercontent.com/soda480/ascii-animator/main/docs/images/example4.gif)

Here is another [example](https://github.com/soda480/ascii-animator/blob/main/examples/example6.py) of a selection sort animation this time using vertical bars.

![example](https://raw.githubusercontent.com/soda480/ascii-animator/main/docs/images/example6.gif)

#### [Equalizer Bars Animation](https://github.com/soda480/ascii-animator/blob/main/examples/example2.py)

An animation for symmetrical equalizer bars.
Expand Down
2 changes: 1 addition & 1 deletion build.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
authors = [Author('Emilio Reyes', 'soda480@gmail.com')]
summary = 'A simple ASCII art animator'
url = 'https://github.com/soda480/ascii-animator'
version = '0.2.0'
version = '0.2.1'
default_task = [
'clean',
'analyze',
Expand Down
Binary file modified docs/images/example4.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/example6.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion examples/example4.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,4 @@ def _update_grid(self, idxi, idxj, idxm, done=False):


if __name__ == '__main__':
Animator(animation=SelectionSort(), speed=Speed.FAST, max_loops=2)
Animator(animation=SelectionSort(), speed=Speed.FAST, max_loops=1)
79 changes: 79 additions & 0 deletions examples/example6.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import random
from ascii_animator import Animator, Animation, Speed
from colorama import Style, Fore

CHAR = chr(9475)

class SelectionSort(Animation):

def __init__(self):
self.y_size = 32
self.x_size = 120
self.reset()

@property
def grid(self):
return self._grid

def cycle(self):
length = len(self._numbers)
for idxi in range(length):
idxm = idxi
for idxj in range(idxi + 1, length):
if self._numbers[idxj] < self._numbers[idxm]:
idxm = idxj
# display numbers as they are being sorted
yield self._update_grid(idxi, idxj, idxm)
# swap numbers
self._numbers[idxi], self._numbers[idxm] = self._numbers[idxm], self._numbers[idxi]
# display numbers after they have been sorted
yield self._update_grid(idxi, idxj, idxm, done=True)

def reset(self):
self._grid = [['' for x in range(self.x_size)] for y in range(self.y_size)]
# even numbers work better for this animation
self._numbers = [random.randrange(2, 60, 2) for _ in range(90)]
# track y position from where bars start - leave two lines for labels
self._y_pos = self.y_size - 3
self._show_bars()

def _update_grid(self, idxi, idxj, idxm, done=False):
self._show_bars(idxi=idxi, idxm=idxm)
self._show_labels(idxi, idxm, done=done)
return done

def _get_label(self, items, done=False):
line = [' ' for _ in range(len(self._numbers))]
if not done:
for index, label in items:
line[index] = Style.BRIGHT + Fore.BLUE + label
return line

def _show_labels(self, idxi, idxm, done=False):
self._grid[self.y_size - 1] = self._get_label([(idxi, 'i'), (idxm, 'm')], done=done)
self._grid[self.y_size - 2] = self._get_label([(idxi, u'\u25B2'), (idxm, u'\u25B2')], done=done)

def _get_line(self, y, heights, idxi=None, idxm=None):
line = []
for height in heights:
if y <= self._y_pos - height:
# height does not reach
line.append(' ')
else:
line.append(CHAR)
if idxi and idxi != len(heights) - 1:
# end green highlight
line[idxi] = Style.RESET_ALL + line[idxi]
if idxm and idxm != len(heights) - 1:
# highlight middle
line[idxm] = Style.BRIGHT + Fore.YELLOW + line[idxm] + Style.RESET_ALL
return Style.BRIGHT + Fore.GREEN + ''.join(line)

def _show_bars(self, idxi=None, idxm=None):
# get heights of all numbers as they relate to the grid
heights = [int(number / 2) for number in self._numbers]
for y in range(self._y_pos + 1):
self._grid[y] = self._get_line(y, heights, idxi=idxi, idxm=idxm)

if __name__ == '__main__':
Animator(animation=SelectionSort(), speed=Speed.SLOW, max_loops=1)
15 changes: 9 additions & 6 deletions src/main/python/ascii_animator/animator.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def cycle(self):

class Animator:

def __init__(self, animation=None, speed=Speed.NORMAL, show_axis=False, max_loops=None):
def __init__(self, animation=None, speed=Speed.NORMAL, show_axis=False, max_loops=None, first_cycle_sleep=True):
""" initialize Animator
"""
logger.debug('executing Animator constructor')
Expand All @@ -98,6 +98,11 @@ def __init__(self, animation=None, speed=Speed.NORMAL, show_axis=False, max_loop
self.animation = animation
self.show_axis = show_axis
self.max_loops = max_loops
# control if animator should sleep after first loop
# some animations first cycle is slow thus a sleep is not necessary
# AsciiAnimation first cycle loads the image into memory
# this process is inherently slow thus sleeping is not necessary
self.first_cycle_sleep = first_cycle_sleep
self.start()

def _check_loops(self, cycle_complete):
Expand All @@ -112,9 +117,7 @@ def _check_loops(self, cycle_complete):
def _sleep(self):
""" determine if execution should sleep
"""
if self.loop == 1 and isinstance(self.animation, AsciiAnimation):
# AsciiAnimation first cycle loads the image into memory
# this process is inherently slow thus sleeping is not necessary
if self.loop == 1 and not self.first_cycle_sleep:
return
sleep(self.speed.value)

Expand Down Expand Up @@ -143,7 +146,7 @@ def start(self):
"""
logger.debug('starting ascii art animation')
try:
logger.debug('there are %d lines in the animation to display', len(self.animation.grid))
logger.debug(f'there are {len(self.animation.grid)} lines in the animation to display')
with Lines(self.animation.grid, show_index=self.show_axis, show_x_axis=self.show_axis, max_chars=self._get_max_chars()) as lines:
self.loop = 1
while True:
Expand All @@ -161,4 +164,4 @@ def start(self):
logger.debug('encountered a keyboard interrupt - ending animation')

except MaxLoopsProcessed:
logger.debug('maximum loops processed %d - ending animation', self.loop - 1)
logger.debug(f'maximum loops processed {self.loop - 1} - ending animation')
3 changes: 2 additions & 1 deletion src/main/python/ascii_animator/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ def main():
animation=AsciiAnimation(args.file, columns=args.columns),
speed=speed,
show_axis=args.show_axis,
max_loops=args.max_loops)
max_loops=args.max_loops,
first_cycle_sleep=False)

except argparse.ArgumentError:
parser.print_help()
Expand Down

0 comments on commit b7deede

Please sign in to comment.