Skip to content

Commit b7deede

Browse files
authored
0.2.1 (#12)
* 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>
1 parent 0f66912 commit b7deede

File tree

8 files changed

+96
-9
lines changed

8 files changed

+96
-9
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ A selection sort search is a simple and efficient sorting algorithm that works b
6969

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

72+
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.
73+
74+
![example](https://raw.githubusercontent.com/soda480/ascii-animator/main/docs/images/example6.gif)
75+
7276
#### [Equalizer Bars Animation](https://github.com/soda480/ascii-animator/blob/main/examples/example2.py)
7377

7478
An animation for symmetrical equalizer bars.

build.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
authors = [Author('Emilio Reyes', 'soda480@gmail.com')]
1616
summary = 'A simple ASCII art animator'
1717
url = 'https://github.com/soda480/ascii-animator'
18-
version = '0.2.0'
18+
version = '0.2.1'
1919
default_task = [
2020
'clean',
2121
'analyze',

docs/images/example4.gif

2.42 KB
Loading

docs/images/example6.gif

301 KB
Loading

examples/example4.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,4 @@ def _update_grid(self, idxi, idxj, idxm, done=False):
6464

6565

6666
if __name__ == '__main__':
67-
Animator(animation=SelectionSort(), speed=Speed.FAST, max_loops=2)
67+
Animator(animation=SelectionSort(), speed=Speed.FAST, max_loops=1)

examples/example6.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import random
2+
from ascii_animator import Animator, Animation, Speed
3+
from colorama import Style, Fore
4+
5+
CHAR = chr(9475)
6+
7+
class SelectionSort(Animation):
8+
9+
def __init__(self):
10+
self.y_size = 32
11+
self.x_size = 120
12+
self.reset()
13+
14+
@property
15+
def grid(self):
16+
return self._grid
17+
18+
def cycle(self):
19+
length = len(self._numbers)
20+
for idxi in range(length):
21+
idxm = idxi
22+
for idxj in range(idxi + 1, length):
23+
if self._numbers[idxj] < self._numbers[idxm]:
24+
idxm = idxj
25+
# display numbers as they are being sorted
26+
yield self._update_grid(idxi, idxj, idxm)
27+
# swap numbers
28+
self._numbers[idxi], self._numbers[idxm] = self._numbers[idxm], self._numbers[idxi]
29+
# display numbers after they have been sorted
30+
yield self._update_grid(idxi, idxj, idxm, done=True)
31+
32+
def reset(self):
33+
self._grid = [['' for x in range(self.x_size)] for y in range(self.y_size)]
34+
# even numbers work better for this animation
35+
self._numbers = [random.randrange(2, 60, 2) for _ in range(90)]
36+
# track y position from where bars start - leave two lines for labels
37+
self._y_pos = self.y_size - 3
38+
self._show_bars()
39+
40+
def _update_grid(self, idxi, idxj, idxm, done=False):
41+
self._show_bars(idxi=idxi, idxm=idxm)
42+
self._show_labels(idxi, idxm, done=done)
43+
return done
44+
45+
def _get_label(self, items, done=False):
46+
line = [' ' for _ in range(len(self._numbers))]
47+
if not done:
48+
for index, label in items:
49+
line[index] = Style.BRIGHT + Fore.BLUE + label
50+
return line
51+
52+
def _show_labels(self, idxi, idxm, done=False):
53+
self._grid[self.y_size - 1] = self._get_label([(idxi, 'i'), (idxm, 'm')], done=done)
54+
self._grid[self.y_size - 2] = self._get_label([(idxi, u'\u25B2'), (idxm, u'\u25B2')], done=done)
55+
56+
def _get_line(self, y, heights, idxi=None, idxm=None):
57+
line = []
58+
for height in heights:
59+
if y <= self._y_pos - height:
60+
# height does not reach
61+
line.append(' ')
62+
else:
63+
line.append(CHAR)
64+
if idxi and idxi != len(heights) - 1:
65+
# end green highlight
66+
line[idxi] = Style.RESET_ALL + line[idxi]
67+
if idxm and idxm != len(heights) - 1:
68+
# highlight middle
69+
line[idxm] = Style.BRIGHT + Fore.YELLOW + line[idxm] + Style.RESET_ALL
70+
return Style.BRIGHT + Fore.GREEN + ''.join(line)
71+
72+
def _show_bars(self, idxi=None, idxm=None):
73+
# get heights of all numbers as they relate to the grid
74+
heights = [int(number / 2) for number in self._numbers]
75+
for y in range(self._y_pos + 1):
76+
self._grid[y] = self._get_line(y, heights, idxi=idxi, idxm=idxm)
77+
78+
if __name__ == '__main__':
79+
Animator(animation=SelectionSort(), speed=Speed.SLOW, max_loops=1)

src/main/python/ascii_animator/animator.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ def cycle(self):
8686

8787
class Animator:
8888

89-
def __init__(self, animation=None, speed=Speed.NORMAL, show_axis=False, max_loops=None):
89+
def __init__(self, animation=None, speed=Speed.NORMAL, show_axis=False, max_loops=None, first_cycle_sleep=True):
9090
""" initialize Animator
9191
"""
9292
logger.debug('executing Animator constructor')
@@ -98,6 +98,11 @@ def __init__(self, animation=None, speed=Speed.NORMAL, show_axis=False, max_loop
9898
self.animation = animation
9999
self.show_axis = show_axis
100100
self.max_loops = max_loops
101+
# control if animator should sleep after first loop
102+
# some animations first cycle is slow thus a sleep is not necessary
103+
# AsciiAnimation first cycle loads the image into memory
104+
# this process is inherently slow thus sleeping is not necessary
105+
self.first_cycle_sleep = first_cycle_sleep
101106
self.start()
102107

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

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

163166
except MaxLoopsProcessed:
164-
logger.debug('maximum loops processed %d - ending animation', self.loop - 1)
167+
logger.debug(f'maximum loops processed {self.loop - 1} - ending animation')

src/main/python/ascii_animator/cli.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ def main():
4141
animation=AsciiAnimation(args.file, columns=args.columns),
4242
speed=speed,
4343
show_axis=args.show_axis,
44-
max_loops=args.max_loops)
44+
max_loops=args.max_loops,
45+
first_cycle_sleep=False)
4546

4647
except argparse.ArgumentError:
4748
parser.print_help()

0 commit comments

Comments
 (0)