print("typical output")

"""
Explanation: Outputs you can update by name
This notebook demonstrates the new name-based display functionality in the notebook. Previously, notebooks could only attach output to the cell that was currently being executed:
End of explanation
"""


h1 = display('initial display', display_id='some_destination')

"""
Explanation: There was no simple way to make code in one cell to write output to another cell. Now there is!
This feature will only work on IPython &gt;= 5.4, so upgrade if you need to with pip install --upgrade ipython. Feel free to update with
pip install --upgrade ipython
then restart the kernel with Language -&gt; Restart Running Kernel. We'll wait here...
The fun stuff
You made it to the future! Pat yourself on the back and take a deep breath, the scariest part is over. The display function now has an optional display_id parameter. Let's give our next display the boring name and call it some_destination.
End of explanation
"""


h2 = display('spoiler alert: output updated in both', display_id='some_destination')			

"""
Explanation: Ok, so far, nothing earth shattering. But what happens if you call display with the same display_id again?
End of explanation
"""


h3 = display('no output here, update above', display_id='some_destination', update=True)			

"""
Explanation: Fantastic! We have a way of mirroring output in multiple places. But what if you only want update the previously named displays, without creating a new one? Just call display with update=True, like this:
End of explanation
"""


import os
from binascii import hexlify

class ProgressBar(object):
    def __init__(self, capacity):
        self._display_id = hexlify(os.urandom(8)).decode('ascii')
        self.capacity = capacity
        self.progress = 0
        
        
    def _repr_html_(self):
        return "<progress style='width:100%' max='{}' value='{}'></progress>".format(self.capacity, self.progress)
    
    def display(self):
        display(self, display_id=self._display_id)
    
    def update(self):
        display(self, display_id=self._display_id, update=True)

bar = ProgressBar(100)
bar.display()

"""
Explanation: Though we have been working with text so far, this also works for the all other output types. Let's make an HTML-based progress bar!
End of explanation
"""


bar.progress = 50
bar.update()

"""
Explanation: The progress bar is drawn and it starts off at 0. Fill it up half way and call its update method to get a redraw.
End of explanation
"""


bar.progress = 75
bar.update()

"""
Explanation: Now go half-way again
End of explanation
"""


bar.display()

"""
Explanation: Our original bar is kind of far away now, let's get another view of it below.
End of explanation
"""


class AutoupdatingProgressBar(ProgressBar):
    @property
    def progress(self):
        return self._progress
    
    @progress.setter
    def progress(self, value):
        self._progress = value
        self.update()

better_bar = AutoupdatingProgressBar(100)
better_bar.display()

better_bar.progress = 40

"""
Explanation: This is good, but it would be awesome to have a progress bar that would automatically update whenever its progress was modified - that would be truly progressive. We subclass ProgressBar and now we make progress into a Python property, which will allow us to set it and get it like an attribute, but do that using methods. In particular, whenever we assign a new value to progress, we also call update.
End of explanation
"""


import time
better_bar.progress = 0
for _ in range(10):
    time.sleep(.5)
    better_bar.progress += (better_bar.capacity - better_bar.progress) / 2

"""
Explanation: Much better. No more pesky update calls. Let's make a little animation that Zeno would be proud of:
End of explanation
"""


num_bars = 5
bars = [AutoupdatingProgressBar(100) for _ in range(num_bars)]
for b in bars:
    b.display()

import random 
for x in range(40):
    time.sleep(.1)
    idx = random.randrange(num_bars)
    bars[idx].progress +=  random.randint(-2, 10)

for b in bars:
    b.display()

"""
Explanation: You might have noticed that each ProgressBar autogenerates a random display_id which is handy if you want to have several of them.
End of explanation
"""


