'''
Created on 16-Apr-2021

@author: bthakur
'''
import os
import numpy as np
import random
import inspect
import traceback

from xv.km.ui import SvgHelper


from sympy import ( symbols, diff, Symbol, Mul, Matrix,
                    factorial, sympify, Rational,
                    Derivative, factor,
                    exp, sin, cos, cosh, sinh, pi)

from sympy.core.numbers import One, Integer


from builtins import enumerate


from ..helper import BaseHelper
from xv.km.managers import BaseManager
from xv.km.kelements import KProblemTemplate, KPrintElement

# _basic_plotting_manager
# BasicPlottingManager

class BasicPlottingManager(BaseManager):
    '''
    Basic Plotting
    Example:
        ke = BasicPlottingManager()
        ke

        ke.printProblemTypes()

        ke.getRandomProblem()
        ke.getRandomProblem(problem_type = 0)
        ke.getRandomProblem(problem_type = 1)
        ...

        ke.printProblem()
        ke.printAnswer()
        ke.printSolution()


    '''
    def __new__(cls, *args, **kwargs):
        instance = super(BasicPlottingManager, cls).__new__(cls, *args, **kwargs)
        for base_class in BasicPlottingManager.__bases__:
            base_class.__init__(instance, *args, **kwargs)
        return instance

    def __init__(self, *args, **kwargs):
        self.base_helper = BaseHelper(**kwargs)
        self._colors = ['indigo', 'blue', 'green', 'red', 'cyan', 'magenta', 'violet', 'black', 'orange']
        self._markers = ['o', 'v', '^', '<', '>', '1', '2', '3', '4',
                         '8', 's', 'p', 'P', '*', 'h', 'H', 'X', 'D', 'd', ]
        pass

    def _get_annotation_code(self,
                             x = None, y = None,
                             xVar = 'x', yVar = 'y',
                             annotate_flag = True):
        if not annotate_flag:
            return ""
        if not (x is None or y is None):
            return f"plt.gca().annotate(f'({x}, {y})',xy=({x + 0.3}, {y + 0.3}), xycoords='data')"
            pass

        return f"plt.gca().annotate(f'({{{xVar}}}, {{{yVar}}})',xy=({xVar} + 0.3, {yVar} + 0.3), xycoords='data')"
        pass

    def _get_annotation_code_for_points(self, points,
                             xVar = 'x', yVar = 'y',
                             annotate_flag = True):
        annotation_codes = ""
        for point in points:
            s = self._get_annotation_code(
                                      x = point[0],
                                      y = point[1],
                                      xVar = xVar,
                                      yVar = yVar,
                                      annotate_flag = annotate_flag)

            if s:
                annotation_codes = f"""{annotation_codes}
{s}"""
            pass
        return annotation_codes
        pass

    def _adjust_minmax(self, minmax, adj_factor = 0.1):
        xRange = (minmax[1] - minmax[0]) * adj_factor
        yRange = (minmax[3] - minmax[2]) * adj_factor

        minmax = [
                int(minmax[0] - xRange) - 1,
                int(minmax[1] + xRange) + 1,
                int(minmax[2] - yRange) - 1,
                int(minmax[3] + yRange) + 1,
            ]
        return minmax
        pass

    def _set_minmax(self, x, y, minmax = None):
        if minmax is None:
            minmax = [-1, 1, -1, 1]

        minmax = [
                min(minmax[0], x),
                max(minmax[1], x),
                min(minmax[2], y),
                max(minmax[3], y)
            ]

        return minmax
        pass

    def _init_movement_data(self, annotate_flag = False):
        x0 = random.randint(0, 10) * random.choice([-1, 1])
        y0 = random.randint(0, 10) * random.choice([-1, 1])

        minmax = self._set_minmax(x0, y0, minmax = None)

        m_count = random.randint(2, 5)
        movements = []
        posX = x0
        posY = y0
        while m_count > 0:
            x = random.randint(1, 10) * random.choice([-1, 0, 1])
            y = random.randint(1, 10) * random.choice([-1, 0, 1])
            if x == 0 and y == 0:
                continue
            posX = posX + x
            posY = posY + y

            minmax = self._set_minmax(posX, posY, minmax = minmax)

            m_str = "Go "

            if x != 0:
                if x < 0:
                    m_str = f"{m_str} left by {abs(x)}"
                else:
                    m_str = f"{m_str} right by {abs(x)}"
                pass

            if x != 0 and y != 0:
                m_str =f"{m_str} and"

            if y != 0:
                if y < 0:
                    m_str = f"{m_str} down by {abs(y)}"
                else:
                    m_str = f"{m_str} up by {abs(y)}"
                pass

            movements.append((m_str, (x, y)))

            m_count = m_count - 1
            pass #while m_count > 0:

        minmax = self._adjust_minmax(minmax)
        return x0, y0, movements, minmax
        pass



    def _get_movement_lines(self, annotate_flag = False):
        x0, y0, movements, minmax = self._init_movement_data(annotate_flag)

        markersize = 10
        custom_code = f"""
x = {x0}
y = {y0}
plt.plot(x, y, marker = 'o', color = '{self._colors[0]}', markersize = {markersize})
"""
        if annotate_flag:
            custom_code = f"""{custom_code}
plt.gca().annotate(f'Start({{x}}, {{y}})',
    xy=(x + 0.3, y + 0.3), xycoords='data')
"""
        for idx, movement in enumerate(movements):
            custom_code = f"""{custom_code}
xstart = x
ystart = y
x = xstart + {movement[1][0]}
y = ystart + {movement[1][1]}
plt.plot(x, y, marker = 'o', color = '{self._colors[idx + 1]}', markersize = {markersize})
plt.plot((xstart, x), (ystart, y), color = '{self._colors[idx + 1]}')
"""
            if annotate_flag:
                custom_code = f"""{custom_code}
plt.gca().annotate(f'({{x}}, {{y}})',
    xy=(x + 0.3, y + 0.3), xycoords='data')
"""
                pass

            pass

        custom_code = f"""{custom_code}

#optional code
plt.xlim({minmax[0]}, {minmax[1]})
plt.ylim({minmax[2]}, {minmax[3]})
"""

        return x0, y0, movements, custom_code
        pass



    def _get_random_annotation_flag(self):
        annotate_flag = random.choice([True, False])
        if annotate_flag:
            annotate_str = " with annotation"
        else:
            annotate_str = ""
        return annotate_flag, annotate_str
        pass


    def _init_problem_types(self, *args, **kwargs):
        self._append_problem_types([
                '_problem_canvas_area',
                '_problem_plot_a_point',
                '_problem_plot_a_point_annotated',
                '_problem_plot_two_points',
                '_problem_plot_a_line',
                '_problem_plot_locus',
                '_problem_plot_movement',
                '_problem_plot_square',
                '_problem_plot_polar_points',
                '_problem_plot_four_polar_point',
                '_problem_plot_a_circle',
                '_problem_plot_arcs',
                '_problem_plot_multiple_concentric_circles',
                '_problem_plot_multiple_circles',
             ])
        pass

    def _problem_canvas_area(self, *args, **kwargs):
        size = (2, 2)
        signs = np.random.choice([1, -1], size)
        xs, ys = np.random.randint(1, 10, size) * signs

        statement = f"Set plot axes as follows:"
        expr_s = f"x-axis = ({xs[0]}, {xs[1]}), y-axis = ({ys[0]}, {ys[1]})"
        expr = KPrintElement(expr_s, 'text/html')

        custom_code = f"""
plt.xlim({min(*xs)}, {max(*xs)})
plt.ylim({min(*ys)}, {max(*ys)})
"""

        svgHelper = SvgHelper()
        svg_str, plot_code = svgHelper.get_svg_data(custom_code)
        answer = KPrintElement(svg_str, 'text/svg')

        solution = []
        solution.append(plot_code)
        solution.append(answer)

        problemTemplate = KProblemTemplate(
                problem_type = '_problem_canvas_area',
                problem = [statement, expr],
                answer = answer,
                solution = solution)

        return problemTemplate
        pass


    def _problem_plot_a_point(self, *args, **kwargs):
        annotate_flag = False
        annotate_str = ""
        return self._problem_plot_a_point_init(annotate_flag, annotate_str, *args, **kwargs)
        pass

    def _problem_plot_a_point_annotated(self, *args, **kwargs):
        annotate_flag = True
        annotate_str = " with annotation"
        return self._problem_plot_a_point_init(annotate_flag, annotate_str, *args, **kwargs)
        pass


    def _problem_plot_a_point_init(self, annotate_flag, annotate_str, *args, **kwargs):
        x0 = 0
        y0 = 0
        x = random.randint(0, 10) * random.choice([-1, 1])
        y = random.randint(0, 10) * random.choice([-1, 1])
        color = random.sample(self._colors, 2)
        marker = random.sample(self._markers, 2)
        sizeFactor = random.randint(2, 5)
        markersize = sizeFactor * 5

        statement = f"""Plot a point at ({x}, {y}){annotate_str}"""
        expr = ""

        annotation_code = self._get_annotation_code(
            x = x, y = y, annotate_flag = annotate_flag)

        custom_code = f"""
plt.plot({x}, {y}, marker = '{marker[1]}', color = '{color[1]}', markersize = {markersize})
{annotation_code.strip()}

#optional code
xyMin = min({x0}, {x}, {y0}, {y}) - 1
xyMax = max({x0}, {x}, {y0}, {y}) + 1
plt.xlim(xyMin, xyMax)
plt.ylim(xyMin, xyMax)
"""

        svgHelper = SvgHelper()
        svg_str, plot_code = svgHelper.get_svg_data(custom_code)
        answer = KPrintElement(svg_str, 'text/svg')

        solution = []
        solution.append(plot_code)
        solution.append(answer)

        problemTemplate = KProblemTemplate(
                problem_type = '_problem_plot_a_point',
                problem = [statement, expr],
                answer = answer,
                solution = solution)

        return problemTemplate
        pass

    def _problem_plot_two_points(self, *args, **kwargs):
        annotate_flag, annotate_str = self._get_random_annotation_flag()

        x0 = random.randint(0, 10) * random.choice([-1, 1])
        y0 = random.randint(0, 10) * random.choice([-1, 1])
        x = random.randint(0, 10) * random.choice([-1, 1])
        y = random.randint(0, 10) * random.choice([-1, 1])
        color = random.sample(self._colors, 2)
        marker = random.sample(self._markers, 2)
        sizeFactor = random.randint(2, 5)
        markersize = sizeFactor * 5

        statement = f"""Plot two points at ({x0}, {y0}) and ({x}, {y}){annotate_str}"""
        expr = ""

        annotation_codes = self._get_annotation_code_for_points([(x0, y0), (x, y)],
                                        annotate_flag = annotate_flag)

        custom_code = f"""
plt.plot({x0}, {y0}, marker = '{marker[0]}', color = '{color[0]}', markersize = {markersize})
plt.plot({x}, {y}, marker = '{marker[1]}', color = '{color[1]}', markersize = {markersize})

{annotation_codes}

#optional code
xyMin = min({x0}, {x}, {y0}, {y}) - 1
xyMax = max({x0}, {x}, {y0}, {y}) + 1
plt.xlim(xyMin, xyMax)
plt.ylim(xyMin, xyMax)
"""

        svgHelper = SvgHelper()
        svg_str, plot_code = svgHelper.get_svg_data(custom_code)

        answer = KPrintElement(svg_str, 'text/svg')

        solution = []
        solution.append(plot_code)
        solution.append(answer)

        problemTemplate = KProblemTemplate(
                problem_type = '_problem_plot_two_points',
                problem = [statement, expr],
                answer = answer,
                solution = solution)

        return problemTemplate
        pass

    def _problem_plot_a_line(self, *args, **kwargs):
        annotate_flag, annotate_str = self._get_random_annotation_flag()
        x0 = random.randint(0, 10) * random.choice([-1, 1])
        y0 = random.randint(0, 10) * random.choice([-1, 1])
        x = random.randint(0, 10) * random.choice([-1, 1])
        y = random.randint(0, 10) * random.choice([-1, 1])
        color = random.sample(self._colors, 2)
        sizeFactor = random.randint(2, 5)
        markersize = sizeFactor * 5


        statement = f"""Plot the points ({x0}, {y0}) and ({x}, {y}) and a line joining them{annotate_str}"""
        expr = ""

        annotation_codes = self._get_annotation_code_for_points([(x0, y0), (x, y)],
                                        annotate_flag = annotate_flag)


        custom_code = f"""
plt.plot({x0}, {y0}, marker = 'o', color = '{color[0]}', markersize = {markersize})
plt.plot({x}, {y}, marker = 'o', color = '{color[0]}', markersize = {markersize})
plt.plot(({x0}, {x}), ({y0}, {y}), color = '{color[1]}')

{annotation_codes}

#optional code
xyMin = min({x0}, {x}, {y0}, {y}) - 1
xyMax = max({x0}, {x}, {y0}, {y}) + 1
plt.xlim(xyMin, xyMax)
plt.ylim(xyMin, xyMax)
"""

        svgHelper = SvgHelper()
        svg_str, plot_code = svgHelper.get_svg_data(custom_code)

        answer = KPrintElement(svg_str, 'text/svg')

        solution = []
        solution.append(plot_code)
        solution.append(answer)

        problemTemplate = KProblemTemplate(
                problem_type = '_problem_plot_two_points',
                problem = [statement, expr],
                answer = answer,
                solution = solution)

        return problemTemplate
        pass

    def _problem_plot_locus(self, *args, **kwargs):
        annotate_flag, annotate_str = self._get_random_annotation_flag()

        points_count = np.random.randint(3, 6)
        size = (points_count, 2)
        signs = np.random.choice([1, -1], size)
        points = np.random.randint(1, 10, size) * signs

        markersize = 10

        statement = f"""Plot the points{annotate_str} and lines through them"""

        points_str = [f"({point[0]}, {point[1]})" for point in points]
        expr = KPrintElement("\n".join(points_str), 'text/html')

        custom_code = ""
        xs = []
        ys = []
        for i, point in enumerate(points):
            xs.append(point[0])
            ys.append(point[1])
            s_code  =f"plt.plot({point[0]}, {point[1]}, marker = 'o', color = '{self._colors[i]}', markersize = {markersize})"

            custom_code = f"""{custom_code}
{s_code}
            """
            pass

        locus_code  =f"plt.plot({xs}, {ys})"

        annotation_codes = self._get_annotation_code_for_points(points,
                                        annotate_flag = annotate_flag)

        xMin = min(xs) - 1
        xMax = max(xs) + 1
        yMin = min(ys) - 1
        yMax = max(ys) + 1

        custom_code = f"""{custom_code}
{locus_code}
{annotation_codes}

#optional code
plt.xlim({xMin}, {xMax})
plt.ylim({yMin}, {yMax})
"""

        svgHelper = SvgHelper()
        svg_str, plot_code = svgHelper.get_svg_data(custom_code)

        answer = KPrintElement(svg_str, 'text/svg')

        solution = []
        solution.append(plot_code)
        solution.append(answer)

        problemTemplate = KProblemTemplate(
                problem_type = '_problem_plot_locus',
                problem = [statement, expr],
                answer = answer,
                solution = solution)

        return problemTemplate


    def _problem_plot_movement(self, *args, **kwargs):
        annotate_flag, annotate_str = self._get_random_annotation_flag()

        x0, y0, movements, custom_code = self._get_movement_lines(annotate_flag = annotate_flag)

        statement = f"""Start from ({x0}, {y0}) and plot the moves as follows{annotate_str}:"""
        expr_s = "\n".join([f"{item_idx[0] + 1}. {item_idx[1][0]}"
                          for item_idx in enumerate(movements)])

        expr = KPrintElement(expr_s, 'text/html')

        svgHelper = SvgHelper()
        svg_str, plot_code = svgHelper.get_svg_data(custom_code)

        answer = KPrintElement(svg_str, 'text/svg')

        solution = []
        solution.append(plot_code)
        solution.append(answer)

        problemTemplate = KProblemTemplate(
                problem_type = '_problem_plot_two_points',
                problem = [statement, expr],
                answer = answer,
                solution = solution)

        return problemTemplate
        pass




    def _problem_plot_square(self, *args, **kwargs):
        annotate_flag, annotate_str = self._get_random_annotation_flag()
        x0 = 0
        y0 = 0
        color = random.sample(self._colors, 2)
        marker = random.sample(self._markers, 2)
        sizeFactor = random.randint(2, 5)
        markersize = sizeFactor * 5
        sl = random.randint(5, 10)
        origin_pos = ['top-left', 'bottom-left', 'bottom-right', 'top-right', 'center']
        idx = random.randint(0, len(origin_pos) - 1)
        slh =sl/2
        xy = [
            [(0, 0, sl, sl, 0), (0, -sl, -sl, 0, 0)],
            [(0, sl, sl, 0, 0), (0, 0, sl, sl, 0)],
            [(0, 0, -sl, -sl, 0), (0, sl, sl, 0, 0)],
            [(0, -sl, -sl, 0, 0), (0, 0, -sl, -sl, 0)],
            [(slh, -slh, -slh, slh, slh), (slh, slh, -slh, -slh, slh)]
            ]

        statement = f"""Draw a square{annotate_str} with side length of {sl} and origin at {origin_pos[idx]} of the square."""
        expr = ""

        custom_code = f"""
plt.plot({x0}, {y0}, marker = '{marker[0]}', color = '{color[0]}', markersize = {markersize})
plt.plot({xy[idx][0]}, {xy[idx][1]}, color = '{color[1]}')
"""

        for i in range(len(xy[idx][0])):
            annotation_code = self._get_annotation_code(
                    x = xy[idx][0][i],
                    y = xy[idx][1][i],
                    annotate_flag = annotate_flag)

            custom_code = f"""{custom_code}
{annotation_code}
            """

        svgHelper = SvgHelper()
        svg_str, plot_code = svgHelper.get_svg_data(custom_code)
        answer = KPrintElement(svg_str, 'text/svg')

        solution = []
        solution.append(plot_code)
        solution.append(answer)

        problemTemplate = KProblemTemplate(
                problem_type = '_problem_plot_make_visible',
                problem = [statement, expr],
                answer = answer,
                solution = solution)

        return problemTemplate
        pass



    def _problem_plot_polar_points(self, *args, **kwargs):
        annotate_flag, annotate_str = self._get_random_annotation_flag()
        r = random.randint(1, 10)
        theta = pi / random.randint(1, 9)
        x0 = 0
        y0 = 0
        color = random.sample(self._colors, 2)
        marker = random.sample(self._markers, 2)
        sizeFactor = random.randint(2, 5)
        markersize = sizeFactor * 5

        statement = f"""Draw origin and another point at a distance {r} from origin and making an angle {theta} with the horizontal."""
        if annotate_flag:
            expr = "Draw annotation also."
        else:
            expr = ""

        annotation_code_0 = self._get_annotation_code(
            x = x0, y = y0, annotate_flag = annotate_flag)

        annotation_code = self._get_annotation_code(
            x = round(r * cos(theta), 1),
            y = round(r * sin(theta), 1),
            annotate_flag = annotate_flag)

        custom_code = f"""
from numpy import pi, cos,sin

#set distance
r = {r}

#set angle
theta = {theta}

#draw origin
plt.plot({x0}, {y0}, marker = 'o')
{annotation_code_0}

#draw the other point
plt.plot(r * cos(theta), r * sin(theta), marker = '{marker[0]}', color = '{color[0]}', markersize = {markersize})
{annotation_code}

#set x-axis limits
plt.xlim(-{r}-1, {r}+1)

#set y-axis limits
plt.ylim(-{r}-1, {r}+1)

#set uniform units for x and y axes
plt.gca().set_aspect('equal', adjustable='box')

# note:
# x = r * cos(theta) = {r} * cos({theta}) = {round(float(r * cos(theta)), 2)}
# y = r * sin(theta) = {r} * sin({theta}) = {round(float(r * sin(theta)), 2)}
"""

        svgHelper = SvgHelper()
        svg_str, plot_code = svgHelper.get_svg_data(custom_code)
        answer = KPrintElement(svg_str, 'text/svg')

        solution = []
        solution.append(plot_code)
        solution.append(answer)

        problemTemplate = KProblemTemplate(
                problem_type = '_problem_plot_polar_points',
                problem = [statement, expr],
                answer = answer,
                solution = solution)

        return problemTemplate
        pass


    def _problem_plot_four_polar_point(self, *args, **kwargs):
        annotate_flag, annotate_str = self._get_random_annotation_flag()
        r = random.randint(1, 10)
        x0 = 0
        y0 = 0
        color = random.sample(self._colors, 4)
        marker = ['>', '^', '<', 'v']
        sizeFactor = random.randint(2, 5)
        markersize = sizeFactor * 5

        statement = f"""Draw origin and four points at {r} distance from origin, right, top, left and down."""
        if annotate_flag:
            expr = "Draw annotation also."
        else:
            expr = ""

        annotation_codes = self._get_annotation_code_for_points(
            [(0, r), (r, 0), (0, -r), (-r, 0)],
            annotate_flag = annotate_flag)


        custom_code = f"""
from numpy import pi, cos,sin

#set distance
r = {r}


#draw origin
plt.plot({x0}, {y0}, marker = 'o')

#draw right point
theta = 0 * pi / 2
plt.plot(r * cos(theta), r * sin(theta), marker = '{marker[0]}', color = '{color[0]}', markersize = {markersize})

#draw top point
theta = 1 * pi / 2
plt.plot(r * cos(theta), r * sin(theta), marker = '{marker[1]}', color = '{color[1]}', markersize = {markersize})

#draw left point
theta = 2 * pi / 2
plt.plot(r * cos(theta), r * sin(theta), marker = '{marker[2]}', color = '{color[2]}', markersize = {markersize})

#draw bottom point
theta = 3 * pi / 2
plt.plot(r * cos(theta), r * sin(theta), marker = '{marker[3]}', color = '{color[3]}', markersize = {markersize})

#annotation
{annotation_codes}

#set x-axis limits
plt.xlim(-{r}-1, {r}+1)

#set y-axis limits
plt.ylim(-{r}-1, {r}+1)

#set uniform units for x and y axes
plt.gca().set_aspect('equal', adjustable='box')

"""

        svgHelper = SvgHelper()
        svg_str, plot_code = svgHelper.get_svg_data(custom_code)
        answer = KPrintElement(svg_str, 'text/svg')

        solution = []
        solution.append(plot_code)
        solution.append(answer)

        problemTemplate = KProblemTemplate(
                problem_type = '_problem_plot_four_polar_point',
                problem = [statement, expr],
                answer = answer,
                solution = solution)

        return problemTemplate
        pass


    def _problem_plot_a_circle(self, *args, **kwargs):
        r = random.randint(1, 10)
        theta = pi / random.randint(1, 9)
        x0 = random.choice([0, random.randint(-5, 5)])
        y0 = random.choice([0, random.randint(-5, 5)])

        color = random.sample(self._colors, 2)
        marker = random.sample(self._markers, 2)
        sizeFactor = random.randint(2, 5)
        markersize = sizeFactor * 5

        statement = f"""Draw a circle of radius {r} with center at ({x0}, {y0})."""
        expr = ""

        if x0 == 0 and y0 == 0:
            circle_points = 'r * cos(angles), r * sin(angles)'
        else:
            circle_points = f'{x0} + r * cos(angles), {y0} + r * sin(angles)'

        max_xy = max( abs(x0) + r, abs(y0) + r )

        custom_code = f"""
from numpy import pi, cos,sin, linspace

#Create angles
angles = linspace(0, 2*pi, 100)

#set radius
r = {r}

#plot center
plt.plot({x0}, {y0}, marker = 'o')

#plot circle points
plt.plot({circle_points}, color = '{color[0]}')

#set x-axis limits
plt.xlim(-{max_xy} -1, {max_xy}+1)

#set y-axis limits
plt.ylim(-{max_xy}-1, {max_xy}+1)

#set uniform units for x and y axes
plt.gca().set_aspect('equal', adjustable='box')

"""

        svgHelper = SvgHelper()
        svg_str, plot_code = svgHelper.get_svg_data(custom_code)
        answer = KPrintElement(svg_str, 'text/svg')

        solution = []
        solution.append(plot_code)
        solution.append(answer)

        problemTemplate = KProblemTemplate(
                problem_type = '_problem_plot_a_circle',
                problem = [statement, expr],
                answer = answer,
                solution = solution)

        return problemTemplate
        pass


    def _problem_plot_arcs(self, *args, **kwargs):
        arc_types = [
            ('top half circle', "0 * pi", "1 * pi"),
            ('bottom half circle', "1 * pi"," 2 * pi"),
            ('right half circle', "3 * pi/2", "5 * pi/2"),
            ('left half circle', "1 * pi/2", "3 * pi/2"),
            ('top right quardant arc', "0 * pi/2", "1 * pi/2"),
            ('top left quardant arc', "1 * pi/2", "2 * pi/2"),
            ('bottom left quardant arc', "2 * pi/2", "3 * pi/2"),
            ('bottom right quardant arc', "3 * pi/2", "4 * pi/2"),
            ]
        idx = random.randint(1, len(arc_types) - 1)

        arc_type, theta1, theta2 = arc_types[idx]

        r = random.randint(1, 10)
        x0 = 0
        y0 = 0
        color = random.sample(self._colors, 2)
        marker = random.sample(self._markers, 2)
        sizeFactor = random.randint(2, 5)
        markersize = sizeFactor * 5

        statement = f"""Draw a {arc_type} of radius {r} with center at origin."""
        expr = ""

        custom_code = f"""
from numpy import pi, cos,sin, linspace

#Create angles
theta1 = {theta1}
theta2 = {theta2}
angles = linspace(theta1, theta2, 100)

#set radius
r = {r}

#plot center
plt.plot({x0}, {y0}, marker = 'o')

#plot circle points
plt.plot(r * cos(angles), r * sin(angles), color = '{color[0]}')

#set x-axis limits
plt.xlim(-{r}-1, {r}+1)

#set y-axis limits
plt.ylim(-{r}-1, {r}+1)

#set uniform units for x and y axes
plt.gca().set_aspect('equal', adjustable='box')

"""

        svgHelper = SvgHelper()
        svg_str, plot_code = svgHelper.get_svg_data(custom_code)
        answer = KPrintElement(svg_str, 'text/svg')

        solution = []
        solution.append(plot_code)
        solution.append(answer)

        problemTemplate = KProblemTemplate(
                problem_type = '_problem_plot_arcs',
                problem = [statement, expr],
                answer = answer,
                solution = solution)

        return problemTemplate
        pass



    def _problem_plot_multiple_concentric_circles(self, *args, **kwargs):
        circleCount = random.randint(2, 5)
        radii = np.random.randint(1, 10, circleCount)

        r = max(radii)
        x0 = 0
        y0 = 0
        color = random.sample(self._colors, circleCount)
        marker = random.sample(self._markers, 2)
        sizeFactor = random.randint(2, 5)
        markersize = sizeFactor * 5

        statement = f"""Draw circles with the following radii with centers at origin."""
        expr = ", ".join([str(r) for r in radii])

        custom_code = f"""
from numpy import pi, cos,sin, linspace

#Create angles
angles = linspace(0, 2*pi, 100)

#set radii
radii = {[r for r in radii]}
color = {color}

#plot center
plt.plot({x0}, {y0}, marker = 'o')


for idx, r in enumerate(radii):
    #plot circle with radius r
    space(4)plt.plot(r * cos(angles), r * sin(angles), color = color[idx] )

max_radius = max(radii)
#set x-axis limits
plt.xlim(-max_radius-1, max_radius+1)

#set y-axis limits
plt.ylim(-max_radius-1, max_radius+1)

#set uniform units for x and y axes
plt.gca().set_aspect('equal', adjustable='box')

"""

        svgHelper = SvgHelper()
        svg_str, plot_code = svgHelper.get_svg_data(custom_code)
        answer = KPrintElement(svg_str, 'text/svg')

        solution = []
        solution.append(plot_code)
        solution.append(answer)

        problemTemplate = KProblemTemplate(
                problem_type = '_problem_plot_multiple_concentric_circles',
                problem = [statement, expr],
                answer = answer,
                solution = solution)

        return problemTemplate
        pass


    def _problem_plot_multiple_circles(self, *args, **kwargs):
        circleCount = random.randint(1, 4)
        radii = np.random.randint(1, 10, circleCount)
        centers = np.random.randint(1, 10, (circleCount, 2))


        r = max(radii)
        x0 = 0
        y0 = 0
        color = random.sample(self._colors, circleCount)
        marker = random.sample(self._markers, 2)
        sizeFactor = random.randint(2, 5)
        markersize = sizeFactor * 5

        statement = f"""Draw the following circles:"""
        expr_s = ""
        for i, raduis in enumerate(radii):
            x, y = centers[i]
            expr_s = f"{expr_s} \nRadius = {raduis}, Center = ({x}, {y})"
            pass
        expr = KPrintElement(expr_s, 'text/html')


        custom_code = f"""
import numpy as np
from numpy import pi, cos,sin, linspace

#Create angles
angles = linspace(0, 2*pi, 100)

#set radii
radii = {[r for r in radii]}
centers = {[(center[0], center[1]) for center in centers]}
color = {color}

for idx, r in enumerate(radii):
    space(4)center = centers[idx]

    space(4)#plot center
    space(4)plt.plot(center[0], center[1], marker = 'o', color = color[idx])

    space(4)#plot circle
    space(4)centerX = center[0] + r * cos(angles)
    space(4)centerY = center[1] + r * sin(angles)
    space(4)plt.plot(centerX, centerY, color = color[idx] )


#set uniform units for x and y axes
plt.gca().set_aspect('equal', adjustable='box')

"""

        svgHelper = SvgHelper()
        svg_str, plot_code = svgHelper.get_svg_data(custom_code)
        answer = KPrintElement(svg_str, 'text/svg')

        solution = []
        solution.append(plot_code)
        solution.append(answer)

        problemTemplate = KProblemTemplate(
                problem_type = '_problem_plot_multiple_circles',
                problem = [statement, expr],
                answer = answer,
                solution = solution)

        return problemTemplate
        pass