LUXROBO/pymodi

View on GitHub
modi/util/tutorial_util.py

Summary

Maintainability
B
5 hrs
Test Coverage
import os
import time

from textwrap import fill
from textwrap import dedent


class Tutor:
    """
    Tutor teaches overall usage of PyMODI
    """

    row_len = 79

    def __init__(self):
        self.bundle = None
        self.led = None
        self.button = None

    @staticmethod
    def clear():
        clear_cmd = 'cls' if os.name == 'nt' else 'clear'
        os.system(clear_cmd)

    def print_wrap(self, msg):
        message = fill(dedent(msg), self.row_len).lstrip()
        print(message)

    def print_lesson(self, lesson, title):
        print('-' * self.row_len)
        topic = f"Lesson {lesson}: {title}"
        print(f"{topic:^{self.row_len}}")
        print('-' * self.row_len)

    @staticmethod
    def check_user_input(answer, give_answer=True, guide=">>> "):
        response = input(guide)
        nb_wrong = 1
        while response != answer:
            if give_answer:
                print(f"Write below code precisely.\n>>> {answer}\n")
            elif nb_wrong > 2:
                print(f"The answer is {answer}. Type it below.")
            else:
                print("Try again!")
            response = input(guide)
            nb_wrong += 1
        return response

    def run_introduction(self):
        self.clear()
        print("=" * self.row_len)
        print(f"= {'Welcome to the PyMODI Tutor':^{self.row_len - 4}} =")
        print("=" * self.row_len)

        self.print_wrap(
            """
            PyMODI is a very powerful tool that can control the MODI modules
            using python scripts. As long as you learn how to use built-in
            functions of PyMODI, you can easily control MODI modules. This
            interactive CUI tutorial will guide you through the world of
            PyMODI.
            """
        )

        selection = dedent(
            """
            Tutorial includes:
            1. Making MODI
            2. Accessing Modules
            3. Controlling Modules
            4. Your First PyMODI Project
            """
        )
        print(selection)

        lesson_nb = int(input("Enter the lesson number and press ENTER: "))
        self.clear()

        if not (0 < lesson_nb < 5):
            print("ERROR: lesson_nb must be one of 1, 2, 3 or 4")
            os._exit(0)

        # Skip lesson 1
        if lesson_nb > 1:
            print("=" * self.row_len)
            print(f"= {'Preparing the modi object...':^{self.row_len - 4}} =")
            print("=" * self.row_len)
            import modi
            self.print_wrap(
                """
                In order to skip the first lesson, we need to set-up the
                prerequisites. Thus, connect button and led module to your
                device.
                """
            )
            input("\nif the modules are ready, press ENTER to continue: ")
            print()

            self.bundle = modi.MODI()

        # Skip lesson 2
        if lesson_nb > 2:
            self.button = self.bundle.buttons[0]
            self.led = self.bundle.leds[0]

        run_selected_lesson = {
            1: self.run_lesson1,
            2: self.run_lesson2,
            3: self.run_lesson3,
            4: self.run_lesson4,
        }.get(lesson_nb)
        run_selected_lesson()

    def run_lesson1(self):
        self.print_lesson(1, "Making MODI")
        self.print_wrap('First, you should import modi. Type "import modi"')

        self.check_user_input('import modi')
        import modi
        print("\nGreat! Now you can use all the features of MODI!\n")

        self.print_wrap(
            """
            To control the modules, make a MODI object that contains all the
            connected modules. Once you create it, it will automatically find
            all the modules connected to the network module.
            """
        )
        input("\nPress ENTER")
        self.clear()

        self.print_wrap(
            """
            Now, prepare real MODI modules. Connect a network module to your
            computing device. Then, connect a Button module and an Led module.
            Make a MODI bundle object by typing bundle = modi.MODI()
            """
        )
        self.check_user_input('bundle = modi.MODI()')
        bundle = modi.MODI()

        self.print_wrap(
            """
            Great! The "bundle" is your MODI object. With it, you can control
            all the modules connected to your device.
            """
        )
        input("\nYou have completed this lesson. Press ENTER to continue.")
        self.bundle = bundle
        self.run_lesson2()

    def run_lesson2(self):
        self.clear()
        self.print_lesson(2, "Accessing modules")
        self.print_wrap(
            """
            In the previous lesson, you created a MODI object. Let's figure out
            how we can access modules connected to it.
            """
        )
        print()
        self.print_wrap(
            """
            "bundle.modules" is a method to get all the modules connected to
            the device.
            """
        )
        print("\nType: bundle.modules")
        self.check_user_input("bundle.modules")
        print(self.bundle.modules)
        print()

        self.print_wrap(
            """
            You can see two modules connected (excluding the network module) to
            the machine. You can access each module by the same method we use
            with an array.
            """
        )
        self.print_wrap(
            """
            You can also access modules by types.
            """
        )
        print("\nType: bundle.leds")

        self.check_user_input("bundle.leds")
        print(self.bundle.leds)
        print()
        self.print_wrap(
            """
            If you have followed previous instructions correctly, there must be
            one led module connected to the network module. Now, make an led
            variable by accessing the first led module.
            """
        )
        print("\nType: led = bundle.leds[0]")

        self.check_user_input("led = bundle.leds[0]")
        led = self.bundle.leds[0]
        self.led = led
        print()
        self.print_wrap(
            """
            Super! You can now do whatever you want with these modules. If you
            have different modules connected, you can access the modules in a
            same way, just typing bundle.<module_name>s"
            """
        )

        input("\nYou have completed this lesson. Press ENTER to continue: ")
        self.run_lesson3()

    def run_lesson3(self):
        led = self.led
        led.rgb = 0, 0, 0
        self.clear()
        self.print_lesson(3, "Controlling modules")
        self.print_wrap(
            """
            Now you know how to access individual modules.

            Let's make an object named "button" as well for your button module.
            You know how to do it (You have the modi object, "bundle").
            """
        )

        self.check_user_input("button = bundle.buttons[0]", False)
        button = self.bundle.buttons[0]
        self.button = button
        print()

        self.print_wrap(
            """
            Perfect. With your button module and led module, we can either get
            data from the module or send command to the module.
            """
        )

        print()
        self.print_wrap(
            """
            "pressed" is a property method of a button module which returns
            whether the button is pressed or not (i.e. press state).
            """
        )
        print("Check the press state of the button by typing button.pressed")

        self.check_user_input("button.pressed")
        print(button.pressed)
        print()

        self.print_wrap(
            """
            Now, see if the same command returns True when pressing the button.
            """
        )

        self.check_user_input("button.pressed")
        print(button.pressed)
        print()

        self.print_wrap(
            """
            Good. Now let's send a command to the led module. Led's rgb is a
            property or setter method of an led module.
            """
        )
        print("Let there be light by typing led.rgb = 0, 0, 255")

        response = self.check_user_input("led.rgb = 0, 0, 255")
        exec(response)
        print()

        self.print_wrap(
            """
            Perfect! You will see the blue light from the led module.
            """
        )

        input("\nYou have completed this lesson. Press ENTER to continue.")
        self.run_lesson4()

    def run_lesson4(self):
        button = self.button
        led = self.led

        self.clear()
        self.print_lesson(4, "Your First PyMODI Project(i.e. Creation)")

        self.print_wrap(
            """
            Let's make a PyMODI project that blinks led when button is pressed.
            """
        )
        self.print_wrap(
            """
            In an infinite loop, we want our led to light up when button is
            pressed, and turn off when not pressed. Complete the following code
            based on the description.
            """
        )

        input("\nPress ENTER when you're ready! ")
        self.clear()

        print(">>> while True:")
        print("...     # Check if button is pressed")
        self.check_user_input(
            "button.pressed:", give_answer=False, guide="...     if "
        )
        print("...         # Set Led color to green")
        self.check_user_input(
            "led.rgb = 0, 255, 0", give_answer=False, guide="...         "
        )
        print("...     elif button.double_clicked:")
        print("...         break")
        print("...     else:")
        print("...         # Turn off the led. (i.e. set color to (0, 0, 0))")
        self.check_user_input(
            "led.rgb = 0, 0, 0", give_answer=False, guide="...         "
        )
        print()

        self.print_wrap(
            """
            Congrats!! Now let's see if the code works as we want.
            Press the button to light up the led. Double click the button to
            break out of the loop.
            """
        )

        while True:
            if button.pressed:
                led.rgb = 0, 255, 0
            elif button.double_clicked:
                break
            else:
                led.rgb = 0, 0, 0
            time.sleep(0.01)
        print()
        self.print_wrap(
            """
            It looks great! Now you know how to use PyMODI to control modules.
            """
        )
        print(
            'You can check more functions at "pymodi.readthedocs.io/en/latest"'
        )

        input("You have completed the tutorial. Press ENTER to exit: ")
        os._exit(0)