'''
Created on 01-Apr-2021
@author: bthakur
'''
from xv.km.ui import SvgHelper

import numpy as np
import random
import inspect
import traceback
import sympy
from sympy import (simplify, sympify, log, symbols, Eq, Matrix, latex,
                   srepr, solve, Rational, diag)


from xv.km.util import (latex_fraction)

from xv.util import toIntOrFloat
from ._exp_expression import ExpExpression

from ._bivariate_expressions import BivariateExpressions

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

class ArithmeticInequalityManager(BaseManager):
    '''
    ArithmeticInequalityManager
    Example:
        ke = ArithmeticInequalityManager()
        ke.getRandomProblem()
        ke.getRandomProblem(problem_type = 0)
        ke.getRandomProblem(problem_type = 1)
        ...
        ke.printProblem()
        ke.printAnswer()
        ke.printSolution()

        ke.printProblemTypes()
    '''

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

    def __init__(self, *args, **kwargs):
        self.base_helper = BaseHelper(**kwargs)
        self._equation = None
        pass



    def _splitArrPosNeg(self, arr):
        arrPos = [item for item in arr if item > 0]
        arrNeg = [item for item in arr if item < 0]
        return arrPos, arrNeg
        pass


    def _getProdExpr(self, arr, showPlus = None):
        if showPlus is None:
            showPlus = random.choice([True, False])

        s = ""
        for idx, item in enumerate(arr):

            if item < 0:
                s_item = f" (-{0 - item})"
                pass
            else:
                if showPlus:
                    s_item = f" (+{item})"
                else:
                    s_item = f" {item}"
                pass

            s = f"{s} * {s_item}"

            pass

        s = s.strip()
        if s[0] == "*":
            s = s[1:]

        return s.strip()
        pass

    def _make_decimal_strs_similar(self, dcm1, dcm2):
        sign1 = dcm1
        sign2 = dcm2

        dcm1 = f"{abs(dcm1)}"
        dcm2 = f"{abs(dcm2)}"

        if not '.' in dcm1:
            dcm1 = dcm1 + "."
        if not '.' in dcm2:
            dcm2 = dcm2 + "."

        parts1 = dcm1.split('.')
        parts2 = dcm2.split('.')

        int_digits = max(len(parts1[0]), len(parts2[0]))
        parts1[0] = parts1[0].zfill(int_digits)
        parts2[0] = parts2[0].zfill(int_digits)

        len1 = len(parts1[1])
        len2 = len(parts2[1])
        if len1 >= len2:
            parts2[1] = parts2[1] + "0" * (len1 - len2)
        else:
            parts1[1] = parts1[1] + "0" * (len2 - len1)
            pass

        dcm1_m = '.'.join(parts1)
        dcm2_m = '.'.join(parts2)

        decimal_digits =  max(len1, len2)

        if sign1 < 0:
            dcm1_m = f"- {dcm1_m}"

        if sign2 < 0:
            dcm2_m = f"- {dcm2_m}"

        return dcm1_m, dcm2_m, decimal_digits
        pass

    def _get_bar_chart(self, nums, nums_expr = None, addl_code = ""):

        nums_s = [n for n in nums]
        if not nums_expr is None:
            nums_expr = [n for n in nums_expr]
        else:
            nums_expr = [repr(n) for n in nums]

        custom_code = f"""
{addl_code}
labels = {repr(nums_expr)}
values = {repr(nums_s)}
plt.bar(labels, values, color = 'lightgreen')

# optionally, add bar values
for i, v in enumerate(values):
    v_float = round(float(v), 10)
    plt.text(x = i-.3, y = v/2, s=f"{{labels[i]}} = {{v_float}}",
             fontdict = dict(fontsize = 15), color = "red")

# plot x-axis line
plt.gca().axhline(y = 0)

# optionally, hide right and top boarders
plt.gca().spines['right'].set_visible(False)
plt.gca().spines['top'].set_visible(False)
            """
        svgHelper = SvgHelper()
        svg_str, plot_code = svgHelper.get_svg_data(custom_code,
                                                    strip_lines = False)

        return svg_str, plot_code
        pass


    def _init_problem_types(self, *args, **kwargs):
        self._append_problem_types([
            '_problem_expr_fraction',
            '_problem_expr_common_denominator',
            '_problem_expr_decimal',
            '_problem_expr_relation_minus',
            '_problem_expr_relation_plus_minus_multiply',
            '_problem_expr_relation_divide',
            '_problem_expr_relation_exp',
            '_problem_expr_relation_exp_2',
            '_problem_expr_relation_exp_3',
            '_problem_plot_division_function',
            '_problem_plot_exp_function',
            '_problem_plot_log_function',
            '_problem_expr_relation_log',
            '_problem_expr_relation_log_advanced',
            '_problem_random_inequality_n1_n2',
            ])
        pass

    def _problem_expr_fraction(self, *args, **kwargs):
        implies = symbols(u'\U000021D2')
        m1, m2 = random.sample(range(2, 10), 2)
        n1 = Rational(1, m1)
        n2 = Rational(1, m2)

        n1_expr = latex_fraction(1, m1)
        n2_expr = latex_fraction(1, m2)

        if n1 == n2:
            op = "="
        elif n1 > n2:
            op = ">"
        else:
            op = "<"

        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        statement = f"""
        $\\displaystyle {n1_expr} \\quad \\text{{ ? }} \\quad {n2_expr}$ \t\tWrite <, = or >
        """
        problemTemplate.add_problem(statement, "text/html")

        soln_s = f"""
        $\\displaystyle {n1_expr} \\quad \\text{{ ? }} \\quad {n2_expr}$

        $\\displaystyle {n1_expr} \\quad {op} \\quad {n2_expr} $
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')


        custom_code = f"""
            from matplotlib import pyplot as plt
            import numpy as np

            fig, (ax1, ax2) = plt.subplots(1,2)

            labels1 = ['{n1}', ' ']
            labels2 = ['{n2}', ' ']

            vals1 = [{n1}, 1-{n1}]
            vals2 = [{n2}, 1-{n2}]

            ax1.pie(vals1, labels = labels1, textprops={{'fontsize': 20}})
            ax2.pie(vals2, labels = labels2, textprops={{'fontsize': 20}})

            ax1.set_alpha(0.5)
            ax2.set_alpha(0.5)

            #optional code
            plt.gca().set_aspect('equal')
            plt.axis('off')
            """

        svgHelper = SvgHelper()
        svg_str, plot_code = svgHelper.get_svg_data(custom_code, strip_lines = True)
        problemTemplate.add_solution(svg_str, 'text/svg')

        problemTemplate.add_solution("<b>Code to draw pi chart</b>", 'text/html')
        problemTemplate.add_solution(plot_code, 'text/html')


        answer_s = f"""$\\displaystyle {n1_expr} \\quad {op} \\quad {n2_expr} $"""
        problemTemplate.add_answer(f"{answer_s}", 'text/html')
        problemTemplate.add_answer(svg_str, 'text/svg')

        return problemTemplate

    def _problem_expr_common_denominator(self, *args, **kwargs):
        implies = symbols(u'\U000021D2')
        m1, m2, dn = random.sample(range(2, 10), 3)
        n1 = Rational(m1, dn)
        n2 = Rational(m2, dn)

        n1_expr = latex_fraction(m1, dn)
        n2_expr = latex_fraction(m2, dn)

        if n1 == n2:
            op = "="
        elif n1 > n2:
            op = ">"
        else:
            op = "<"

        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        statement = f"""
        $\\displaystyle {n1_expr} \\quad \\text{{ ? }} \\quad {n2_expr}$ \t\tWrite <, = or >
        """
        problemTemplate.add_problem(statement, "text/html")

        soln_s = f"""
        $\\displaystyle {n1_expr} \\quad \\text{{ ? }} \\quad {n2_expr}$

        $\\displaystyle {n1_expr} \\quad {op} \\quad {n2_expr} $
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')


        custom_code = f"""
        from matplotlib import pyplot as plt
        import numpy as np

        fig, (ax1) = plt.subplots(1,1)

        labels1 = ['{m1}/{dn}' if i == 0 else '' for i in range({dn})]
        labels2 = ['{m2}/{dn}' if i == 0 else '' for i in range({dn})]

        vals1 = np.array([1 for i in range({dn})])
        vals2 = np.array([1 for i in range({dn})])

        if {m1} > {m2}:
            space(4)r1 = 1
            space(4)r2 = {m2} / {m1}
        else:
            space(4)r2 = 1
            space(4)r1 = {m1} / {m2}


        if {m1} > {m2}:
            space(4)ax1.pie(vals1, labels = labels1, radius = r1, textprops={{'fontsize': 14}}, wedgeprops={{'alpha':0.3}}, labeldistance=0.9)
            space(4)ax1.pie(vals2, labels = labels2, radius = r2, textprops={{'fontsize': 10}}, wedgeprops={{'alpha':0.5}}, labeldistance=0.2)
        else:
            space(4)ax1.pie(vals2, labels = labels2, radius = r2, textprops={{'fontsize': 14}}, wedgeprops={{'alpha':0.3}}, labeldistance=0.9)
            space(4)ax1.pie(vals1, labels = labels1, radius = r1, textprops={{'fontsize': 10}}, wedgeprops={{'alpha':0.5}}, labeldistance=0.2)

        #ax1.set_alpha(0.1)

        #optional code
        plt.gca().set_aspect('equal')
        plt.axis('off')
        """



        svgHelper = SvgHelper()
        svg_str, plot_code = svgHelper.get_svg_data(custom_code, strip_lines = True)
        problemTemplate.add_solution(svg_str, 'text/svg')

        problemTemplate.add_solution("<b>Code to draw pi chart</b>", 'text/html')
        problemTemplate.add_solution(plot_code, 'text/html')


        answer_s = f"""$\\displaystyle {n1_expr} \\quad {op} \\quad {n2_expr} $"""
        problemTemplate.add_answer(f"{answer_s}", 'text/html')

        return problemTemplate

    def _problem_expr_decimal(self, *args, **kwargs):
        implies = symbols(u'\U000021D2')
        m1, m2 = random.sample(range(1, 10), 2)

        numebrs = [
                Rational(m1, m2),
                Rational(m2, m1),
                toIntOrFloat(m1/m2),
                toIntOrFloat(m2/m1),
                toIntOrFloat(m1/m2 * 10 ** random.choice([-1, 1])),
                toIntOrFloat(m2/m1 * 10 ** random.choice([-1, 1])),
            ]

        n1, n2 = random.sample(numebrs, 2)
        n1 = n1 * random.choice([-1, 1])
        n2 = n2 * random.choice([-1, 1])

        n1_float = toIntOrFloat(float(n1), 4)
        n2_float = toIntOrFloat(float(n2), 4)

        dcm1_m, dcm2_m, decimal_digits = self._make_decimal_strs_similar(
                            n1_float, n2_float)
        if n1 == n2:
            op = "="
        elif n1 > n2:
            op = ">"
        else:
            op = "<"

        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        statement = f"""
        $\\displaystyle {n1} \\quad \\text{{ ? }} \\quad {n2}$ \t\tWrite <, = or >
        """
        problemTemplate.add_problem(statement, "text/html")

        soln_s = f"""
        $\\displaystyle {n1} \\quad \\text{{ ? }} \\quad {n2}$
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        if n1 >= 0 and n2 < 0:
            comment = f"Positive Number > Negative Number"
        elif n1 < 0 and n2 >= 0:
            comment = f"Negative Number < Positive Number"
        elif n1 >= 1 and n2 < 1:
            comment = f"Larger or equal to one > Less than one"
        elif n1 < 1 and n2 >= 1:
            comment = f"Less than one < Larger or equal to one"
        else:
            soln_s = f"""
            $\\displaystyle {implies} {n1_float} \\quad \\text{{ ? }} \\quad {n2_float}$

            $\\displaystyle {implies} {dcm1_m} \\quad \\text{{ ? }} \\quad {dcm2_m}$

            $\\displaystyle {implies} {dcm1_m.replace('.', '')} \\quad \\text{{ ? }} \\quad {dcm2_m.replace('.', '')}$
            """
            problemTemplate.add_solution(soln_s.strip(), 'text/html')

            if n1 < 0 and n2 < 0:
                comment = "A negative number with smaller absolute value is bigger"
            else:
                comment = ""

        soln_s = f"""
        $\\displaystyle {implies} {n1} \\quad {op} \\quad {n2}$  \t {comment}
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        svg_str, plot_code = self._get_bar_chart([n1, n2])
        problemTemplate.add_solution(svg_str, 'text/svg')

        problemTemplate.add_solution("<b>Code to draw chart</b>", 'text/html')
        problemTemplate.add_solution(plot_code, 'text/html')


        answer_s = f"""$\\displaystyle {n1} \\quad {op} \\quad {n2} $"""
        problemTemplate.add_answer(f"{answer_s}", 'text/html')

        return problemTemplate

    def _problem_expr_relation_minus(self, *args, **kwargs):
        implies = symbols(u'\U000021D2')
        n1, n2 = random.sample(range(0, 10), 2)
        n3 = 0 - n1
        n4 = 0 - n2
        nums = [n1, n2, n3, n4]
        n1, n2 = random.sample(nums, 2)

        if n1 == n2:
            op = "="
        elif n1 > n2:
            op = ">"
        else:
            op = "<"


        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        statement = f"""
        $\\displaystyle {n1} \\quad \\text{{ ? }} \\quad {n2}$ \t\tWrite <, = or >
        """
        problemTemplate.add_problem(statement, "text/html")

        soln_s = f"""
        $\\displaystyle {n1} \\quad \\text{{ ? }} \\quad {n2}$
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        n1_comp = n1
        n2_comp = n2
        if n1 < 0 and n2 < 0:
            max_n = max(abs(n1), abs(n2))
            n1_comp = n1 + max_n
            n2_comp = n2 + max_n
            soln_s = f"""
            $\\displaystyle {implies} {n1} + {max_n} \\quad \\text{{ ? }} \\quad {n2} + {max_n} $ \t Add {max_n} to both sides

            $\\displaystyle {implies} {n1_comp} \\quad \\text{{ ? }} \\quad {n2_comp} $

            $\\displaystyle {implies} {n1_comp} \\quad {op} \\quad {n2_comp} $
            """
            problemTemplate.add_solution(soln_s.strip(), 'text/html')

        if n1 >= 0 and n2 < 0:
            comment = f"Positive Number > Negative Number"
        elif n1 < 0 and n2 >= 0:
            comment = f"Negative Number < Positive Number"
        else:
            comment = ""

        soln_s = f"""
        $\\displaystyle {implies} {n1} \\quad {op} \\quad {n2}$  \t {comment}
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        svg_str, plot_code = self._get_bar_chart([n1, n2])
        problemTemplate.add_solution(svg_str, 'text/svg')

        problemTemplate.add_solution("<b>Code to draw chart</b>", 'text/html')
        problemTemplate.add_solution(plot_code, 'text/html')


        answer_s = f"""$\\displaystyle {n1} \\quad {op} \\quad {n2} $"""
        problemTemplate.add_answer(f"{answer_s}", 'text/html')

        return problemTemplate

    def _problem_expr_relation_plus_minus_multiply(self, *args, **kwargs):
        implies = symbols(u'\U000021D2')
        n1 = random.randint(0, 10)
        n2 = random.randint(0, 10)
        n3 = 0 - n1
        n4 = 0 - n2
        nums = [n1, n2, n3, n4]
        random.shuffle(nums)

        operation = random.choice(['+', '*'])
        if operation == "+":
            lhs_expr = f"{nums[0]} + {nums[1]}"
            rhs_expr = f"{nums[2]} + {nums[3]}"
            lhs = nums[0] + nums[1]
            rhs = nums[2] + nums[3]

        elif operation == "*":
            lhs_expr = f"{nums[0]} * {nums[1]}"
            rhs_expr = f"{nums[2]} * {nums[3]}"
            lhs = nums[0] * nums[1]
            rhs = nums[2] * nums[3]

        elif operation == "/":
            lhs_expr = latex_fraction(nums[0], nums[1])
            rhs_expr = latex_fraction(nums[2], nums[3])
            lhs = toIntOrFloat(nums[0] / nums[1], roundoff = 4)
            rhs = toIntOrFloat(nums[2] / nums[3], roundoff = 4)

        elif operation == "**":
            lhs_expr = f"{nums[0]} ^ {{{nums[1]}}}"
            rhs_expr = f"{nums[2]} ^ {{{nums[3]}}}"
            lhs = nums[0] ** nums[1]
            rhs = nums[2] ** nums[3]

        if lhs == rhs:
            op = "="
        elif lhs > rhs:
            op = ">"
        else:
            op = "<"


        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        statement = f"""
        Write relation between the expression given below ( <, =, or > ):

        $\\displaystyle {lhs_expr} \\quad \\text{{ ? }} \\quad {rhs_expr}$
        """
        problemTemplate.add_problem(statement, "text/html")

        soln_s = f"""
        $\\displaystyle {lhs_expr} \\quad \\text{{ ? }} \\quad {rhs_expr}$

        $\\displaystyle {implies} {lhs} \\quad \\text{{ ? }} \\quad {rhs}$
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')


        soln_s = f"""
        $\\displaystyle {implies} {lhs} \\quad {op} \\quad {rhs}$

        $\\displaystyle {implies} {lhs_expr} \\quad {op} \\quad {rhs_expr}$
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        svg_str, plot_code = self._get_bar_chart([lhs, rhs],
                                                 [lhs_expr, rhs_expr])
        problemTemplate.add_solution(svg_str, 'text/svg')

        problemTemplate.add_solution("<b>Code to draw chart</b>", 'text/html')
        problemTemplate.add_solution(plot_code, 'text/html')

        answer_s = f"""$\\displaystyle {lhs_expr} \\quad {op} \\quad {rhs_expr} $"""
        problemTemplate.add_answer(f"{answer_s}", 'text/html')

        return problemTemplate

    def _problem_expr_relation_divide(self, *args, **kwargs):
        implies = symbols(u'\U000021D2')
        #n1 = random.randint(1, 10)
        #n2 = random.randint(1, 10)
        nums = [0, 0, 0, 0]
        while nums[1] == 0 or nums[3] == 0:
            n1, n2 = random.sample(range(0, 10), 2)
            n3 = 0 - n1
            n4 = 0 - n2
            nums = [n1, n2, n3, n4]
            random.shuffle(nums)
            pass


        operation = "/"
        lhs_expr = latex_fraction(nums[0], nums[1])
        rhs_expr = latex_fraction(nums[2], nums[3])
        lhs = toIntOrFloat(nums[0] / nums[1], roundoff = 4)
        rhs = toIntOrFloat(nums[2] / nums[3], roundoff = 4)

        if lhs == rhs:
            op = "="
        elif lhs > rhs:
            op = ">"
        else:
            op = "<"


        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        statement = f"""
        Write relation between the expression given below ( <, =, or > ):

        $\\displaystyle  {lhs_expr} \\quad \\text{{ ? }} \\quad {rhs_expr}$
        """
        problemTemplate.add_problem(statement, "text/html")

        soln_s = f"""
        $\\displaystyle  {lhs_expr} \\quad \\text{{ ? }} \\quad {rhs_expr}$
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        if nums[1] != nums[3]:
            lhs_computed_expr1 = latex_fraction(
                f"{nums[0]}*{nums[3]}",
                f"{nums[1]}*{nums[3]}")

            rhs_computed_expr1 = latex_fraction(
                f"{nums[2]}*{nums[1]}",
                f"{nums[3]}*{nums[1]}")

            lhs_computed_expr2 = latex_fraction(
                f"{nums[0] * nums[3]}",
                f"{nums[1] * nums[3]}")

            rhs_computed_expr2 = latex_fraction(
                f"{nums[2] * nums[1]}",
                f"{nums[3] * nums[1]}")


            soln_s = f"""
            Make denominators common.
            Multiply left side numerator and denominator by {nums[3]}
            Multiply right side numerator and denominator by {nums[1]}

            $\\displaystyle  {implies} {lhs_computed_expr1} \\quad \\text{{ ? }} \\quad {rhs_computed_expr1}$

            $\\displaystyle  {implies} {lhs_computed_expr2} \\quad \\text{{ ? }} \\quad {rhs_computed_expr2}$

            $\\displaystyle {implies} {lhs_computed_expr2} \\quad {op} \\quad {rhs_computed_expr2}$
            """
            problemTemplate.add_solution(soln_s.strip(), 'text/html')
        else:
            soln_s = f"""
            $\\displaystyle {implies} {lhs} \\quad \\text{{ ? }} \\quad {rhs}$

            $\\displaystyle {implies} {lhs} \\quad {op} \\quad {rhs}$
            """
            problemTemplate.add_solution(soln_s.strip(), 'text/html')

        soln_s = f"""
        $\\displaystyle {implies} {lhs_expr} \\quad {op} \\quad {rhs_expr}$
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        svg_str, plot_code = self._get_bar_chart([lhs, rhs],
                                [f"${lhs_expr}$", f"${rhs_expr}$"])
        problemTemplate.add_solution(svg_str, 'text/svg')

        problemTemplate.add_solution("<b>Code to draw chart</b>", 'text/html')
        problemTemplate.add_solution(plot_code, 'text/html')


        answer_s = f"""$\\displaystyle {lhs_expr} \\quad {op} \\quad {rhs_expr} $"""
        problemTemplate.add_answer(f"{answer_s}", 'text/html')

        return problemTemplate

    def _problem_expr_relation_exp(self, *args, **kwargs):
        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        implies = symbols(u'\U000021D2')


        max_tries = 10
        while max_tries > 0:
            max_tries = max_tries - 1
            try:
                n1, n2 = random.sample(range(0, 10), 2)
                n3 = 0 - n1
                n4 = 0 - n2
                nums = [n1, n2, n3, n4]
                random.shuffle(nums)
                e1 = ExpExpression(nums[0], nums[1])
                e2 = ExpExpression(nums[2], nums[3])
                break
            except Exception as e:
                if self.verbose:
                    print(f"Error: {e}")
                n1 = None
                pass

        if n1 is None:
            problemTemplate.add_problem(f"""
            Failed to get problem
            """.strip(), "text/html")



        operation = "**"
        lhs = e1.toIntOrFloat(roundoff = 8)
        rhs = e2.toIntOrFloat(roundoff = 8)

        lhs_expr = e1.get_latex_expr()
        rhs_expr = e2.get_latex_expr()

        op = e1.getRelationExpression(e2)

        statement = f"""
        Write relation between the expression given below ( <, =, or > ):

        $\\displaystyle {lhs_expr} \\quad \\text{{ ? }} \\quad {rhs_expr}$
        """
        problemTemplate.add_problem(statement, "text/html")

        soln_s = f"""
        $\\displaystyle {lhs_expr} \\quad \\text{{ ? }} \\quad {rhs_expr}$
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        c_lhs_expr = lhs_expr
        c_rhs_expr = rhs_expr

        if e1.has_inverse_format() or e2.has_inverse_format():
            c_lhs_expr = e1.get_latex_expr(inverse_format = True)
            c_rhs_expr = e2.get_latex_expr(inverse_format = True)

            soln_s = f"""
            $\\displaystyle {implies} {c_lhs_expr} \\quad \\text{{ ? }} \\quad {c_rhs_expr}$
            """
            problemTemplate.add_solution(soln_s.strip(), 'text/html')
            pass

        if e1.has_net_sign_format() or e2.has_net_sign_format():
            c_lhs_expr = e1.get_latex_expr(_net_sign_format_with_inverse = True)
            c_rhs_expr = e2.get_latex_expr(_net_sign_format_with_inverse = True)
            #lhs_comment =  e1.get_net_sign_comment()
            #rhs_comment =  e1.get_net_sign_comment()

            soln_s = f"""
            $\\displaystyle {implies} {c_lhs_expr} \\quad \\text{{ ? }} \\quad {c_rhs_expr}$
            """
            problemTemplate.add_solution(soln_s.strip(), 'text/html')
            pass

        if (e1.n1 == 0 or
            e1.n2 == 0 or
            e2.n1 == 0 or
            e2.n2 == 0):

            if e1.n1 == 0 or e1.n2 == 0:
                c_lhs_expr = f"{e1.value()}"
            if e2.n1 == 0 or e2.n2 == 0:
                c_rhs_expr = f"{e2.value()}"

            comment = []
            if e1.n2 == 0 or e2.n2 == 0:
                comment.append("$n^0 = 1$")

            if ((e1.n1 == 0 and e1.n2 != 0) or
                (e2.n1 == 0 and e2.n2 != 0)) :
                comment.append("$0^m = 0$ if m is not zero")

            comment = "As\t" + ",\t".join(comment)

            soln_s = f"""
            $\\displaystyle {implies} {c_lhs_expr} \\quad \\text{{ ? }} \\quad {c_rhs_expr}$ \t{comment}
            """
            problemTemplate.add_solution(soln_s.strip(), 'text/html')
            pass

        soln_s = e1.getInequalityStatement(e2, c_lhs_expr, c_rhs_expr)
        if not soln_s is None:
            problemTemplate.add_solution(f"\n{soln_s}", 'text/html')


        soln_s = f"""
        $\\displaystyle {implies} {lhs_expr} \\quad {op} \\quad {rhs_expr}$
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        svg_str, plot_code = self._get_bar_chart([lhs, rhs],
                                [f"${lhs_expr}$", f"${rhs_expr}$"])
        problemTemplate.add_solution(svg_str, 'text/svg')

        problemTemplate.add_solution("<b>Code to draw chart</b>", 'text/html')
        problemTemplate.add_solution(plot_code, 'text/html')


        answer_s = f"""$\\displaystyle {lhs_expr} \\quad {op} \\quad {rhs_expr} $"""
        problemTemplate.add_answer(f"{answer_s}", 'text/html')

        return problemTemplate

    def _problem_expr_relation_exp_2(self, *args, **kwargs):
        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        implies = symbols(u'\U000021D2')

        max_tries = 10
        while max_tries > 0:
            max_tries = max_tries - 1
            try:
                n1 = random.randint(2, 9)
                n2 = Rational(1, n1)
                n3 = Rational(-n1)
                n4 = Rational(-1, n1)

                nums = random.sample([n1, n2, n3, n4], 2)
                e1 = ExpExpression(nums[0], nums[1])
                e2 = ExpExpression(nums[1], nums[0])
                break
            except Exception as e:
                if self.verbose:
                    print(f"Error: {e}")
                n1 = None
                pass
            pass

        if n1 is None:
            problemTemplate.add_problem(f"""
            Failed to get problem
            """.strip(), "text/html")



        operation = "**"
        lhs = e1.toIntOrFloat()
        rhs = e2.toIntOrFloat()

        lhs_expr = e1.get_latex_expr()
        rhs_expr = e2.get_latex_expr()

        op = e1.getRelationExpression(e2)

        statement = f"""
        Write relation between the expression given below ( <, =, or > ):

        $\\displaystyle {lhs_expr} \\quad \\text{{ ? }} \\quad {rhs_expr}$
        """
        problemTemplate.add_problem(statement, "text/html")

        soln_s = f"""
        $\\displaystyle {lhs_expr} \\quad \\text{{ ? }} \\quad {rhs_expr}$
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        c_lhs_expr = lhs_expr
        c_rhs_expr = rhs_expr

        if e1.has_inverse_format() or e2.has_inverse_format():
            c_lhs_expr = e1.get_latex_expr(inverse_format = True)
            c_rhs_expr = e2.get_latex_expr(inverse_format = True)

            soln_s = f"""
            $\\displaystyle {implies} {c_lhs_expr} \\quad \\text{{ ? }} \\quad {c_rhs_expr}$
            """
            problemTemplate.add_solution(soln_s.strip(), 'text/html')
            pass

        if e1.has_net_sign_format() or e2.has_net_sign_format():
            c_lhs_expr = e1.get_latex_expr(_net_sign_format_with_inverse = True)
            c_rhs_expr = e2.get_latex_expr(_net_sign_format_with_inverse = True)
            #lhs_comment =  e1.get_net_sign_comment()
            #rhs_comment =  e1.get_net_sign_comment()

            soln_s = f"""
            $\\displaystyle {implies} {c_lhs_expr} \\quad \\text{{ ? }} \\quad {c_rhs_expr}$
            """
            problemTemplate.add_solution(soln_s.strip(), 'text/html')
            pass

        if (e1.n1 == 0 or
            e1.n2 == 0 or
            e2.n1 == 0 or
            e2.n2 == 0):

            if e1.n1 == 0 or e1.n2 == 0:
                c_lhs_expr = f"{e1.value()}"
            if e2.n1 == 0 or e2.n2 == 0:
                c_rhs_expr = f"{e2.value()}"

            comment = []
            if e1.n2 == 0 or e2.n2 == 0:
                comment.append("$n^0 = 1$")

            if ((e1.n1 == 0 and e1.n2 != 0) or
                (e2.n1 == 0 and e2.n2 != 0)) :
                comment.append("$0^m = 0$ if m is not zero")

            comment = "As\t" + ",\t".join(comment)

            soln_s = f"""
            $\\displaystyle {implies} {c_lhs_expr} \\quad \\text{{ ? }} \\quad {c_rhs_expr}$ \t{comment}
            """
            problemTemplate.add_solution(soln_s.strip(), 'text/html')
            pass

        soln_s = e1.getInequalityStatement(e2, c_lhs_expr, c_rhs_expr)
        if not soln_s is None:
            problemTemplate.add_solution(f"\n{soln_s}", 'text/html')


        soln_s = f"""
        $\\displaystyle {implies} {lhs_expr} \\quad {op} \\quad {rhs_expr}$
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        svg_str, plot_code = self._get_bar_chart([lhs, rhs],
                                [f"${lhs_expr}$", f"${rhs_expr}$"])
        problemTemplate.add_solution(svg_str, 'text/svg')

        problemTemplate.add_solution("<b>Code to draw chart</b>", 'text/html')
        problemTemplate.add_solution(plot_code, 'text/html')


        answer_s = f"""$\\displaystyle {lhs_expr} \\quad {op} \\quad {rhs_expr} $"""
        problemTemplate.add_answer(f"{answer_s}", 'text/html')

        return problemTemplate

    def _problem_expr_relation_exp_3(self, *args, **kwargs):
        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        implies = symbols(u'\U000021D2')

        max_tries = 10
        while max_tries > 0:
            max_tries = max_tries - 1
            try:
                n1 = random.randint(2, 9)
                n2 = Rational(1, n1)
                n3 = Rational(-n1)
                n4 = Rational(-1, n1)

                nums = random.sample([n1, n2, n3, n4], 2)
                random.shuffle(nums)
                nums.append(random.choice([1, 0]))
                nums.append(random.choice([1, 0]))

                e1 = ExpExpression(nums[0], nums[1])
                e2 = ExpExpression(nums[2], nums[3])
                break
            except Exception as e:
                if self.verbose:
                    print(f"Error: {e}")
                n1 = None
                pass
            pass


        if n1 is None:
            problemTemplate.add_problem(f"""
            Failed to get problem
            """.strip(), "text/html")



        operation = "**"
        lhs = e1.toIntOrFloat()
        rhs = e2.toIntOrFloat()

        lhs_expr = e1.get_latex_expr()
        rhs_expr = e2.get_latex_expr()

        op = e1.getRelationExpression(e2)

        statement = f"""
        Write relation between the expression given below ( <, =, or > ):

        $\\displaystyle {lhs_expr} \\quad \\text{{ ? }} \\quad {rhs_expr}$
        """
        problemTemplate.add_problem(statement, "text/html")

        soln_s = f"""
        $\\displaystyle {lhs_expr} \\quad \\text{{ ? }} \\quad {rhs_expr}$
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        c_lhs_expr = lhs_expr
        c_rhs_expr = rhs_expr

        if e1.has_inverse_format() or e2.has_inverse_format():
            c_lhs_expr = e1.get_latex_expr(inverse_format = True)
            c_rhs_expr = e2.get_latex_expr(inverse_format = True)

            soln_s = f"""
            $\\displaystyle {implies} {c_lhs_expr} \\quad \\text{{ ? }} \\quad {c_rhs_expr}$
            """
            problemTemplate.add_solution(soln_s.strip(), 'text/html')
            pass

        if e1.has_net_sign_format() or e2.has_net_sign_format():
            c_lhs_expr = e1.get_latex_expr(_net_sign_format_with_inverse = True)
            c_rhs_expr = e2.get_latex_expr(_net_sign_format_with_inverse = True)
            #lhs_comment =  e1.get_net_sign_comment()
            #rhs_comment =  e1.get_net_sign_comment()

            soln_s = f"""
            $\\displaystyle {implies} {c_lhs_expr} \\quad \\text{{ ? }} \\quad {c_rhs_expr}$
            """
            problemTemplate.add_solution(soln_s.strip(), 'text/html')
            pass

        if (e1.n1 == 0 or
            e1.n2 == 0 or
            e2.n1 == 0 or
            e2.n2 == 0):

            if e1.n1 == 0 or e1.n2 == 0:
                c_lhs_expr = f"{e1.value()}"
            if e2.n1 == 0 or e2.n2 == 0:
                c_rhs_expr = f"{e2.value()}"

            comment = []
            if e1.n2 == 0 or e2.n2 == 0:
                comment.append("$n^0 = 1$")

            if ((e1.n1 == 0 and e1.n2 != 0) or
                (e2.n1 == 0 and e2.n2 != 0)) :
                comment.append("$0^m = 0$ if m is not zero")

            comment = "As\t" + ",\t".join(comment)

            soln_s = f"""
            $\\displaystyle {implies} {c_lhs_expr} \\quad \\text{{ ? }} \\quad {c_rhs_expr}$ \t{comment}
            """
            problemTemplate.add_solution(soln_s.strip(), 'text/html')
            pass

        soln_s = e1.getInequalityStatement(e2, c_lhs_expr, c_rhs_expr)
        if not soln_s is None:
            problemTemplate.add_solution(f"\n{soln_s}", 'text/html')


        soln_s = f"""
        $\\displaystyle {implies} {lhs_expr} \\quad {op} \\quad {rhs_expr}$
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        svg_str, plot_code = self._get_bar_chart([lhs, rhs],
                                [f"${lhs_expr}$", f"${rhs_expr}$"])
        problemTemplate.add_solution(svg_str, 'text/svg')

        problemTemplate.add_solution("<b>Code to draw chart</b>", 'text/html')
        problemTemplate.add_solution(plot_code, 'text/html')


        answer_s = f"""$\\displaystyle {lhs_expr} \\quad {op} \\quad {rhs_expr} $"""
        problemTemplate.add_answer(f"{answer_s}", 'text/html')

        return problemTemplate

    def _problem_plot_division_function(self, *args, **kwargs):
        implies = symbols(u'\U000021D2')
        infinity = symbols(u'\U0000221E')
        base = random.randint(2, 10)
        x = symbols('x')

        random_xs = [0.25, 0.50, 0.75, 1, 1.5, 2, 3]
        random_delta = random.choice([-0.2, -0.1, 0, 0.1, 0.2])
        random_x = random.choice(random_xs) + random_delta
        options = [toIntOrFloat(base/(i + random_delta))
                   for i in random_xs]

        n1_expr = f"{{{base}}}/{{{x}}}"
        n1_random_x_expr = latex_fraction(base,
                                          toIntOrFloat(random_x))
        # f"{{{base}}}/{{{toIntOrFloat(random_x)}}}"
        n1_answer = toIntOrFloat(base / random_x)

        options_expr = ",\t".join([str(option) for option in options])

        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        statement = f"""
        The value of <b>$\\;\\;{n1_random_x_expr}\\;\\;$</b> is:\t {options_expr}
        """
        problemTemplate.add_problem(statement, "text/html")

        problemTemplate.add_solution(f"${n1_random_x_expr} = {n1_answer}$", "text/html")

        exp_1 = f"${{{base}}}/{{{base}}} = 1$"
        exp_base = f"${{{base}}}/{{1}} = {base}$"
        exp_2_base = f"${{{base}}}/{{0.5}} = {2*base}$"
        exp_4_base = f"${{{base}}}/{{0.25}} = {4*base}$"
        exp_less_1 = f"${{{base}}}/{{{2 * base}}} = 0.5$"

        custom_code = f"""
            from matplotlib import pyplot as plt
            import numpy as np

            xs = np.linspace(0.0001, 3 * {base}, 100)
            ys = [{base}/item for item in xs]

            plt.plot(xs, ys)

            plt.plot({base}, 1, marker = 'o', color = 'red', markersize = 10)
            plt.gca().annotate('{exp_1}', xy=({base} - 0.2, 1 + {base}/5 ), xycoords='data')

            plt.plot(1, {base}, marker = 'o', color = 'red', markersize = 10)
            plt.gca().annotate('{exp_base}', xy=(1 + 0.2, {base} + {base}/5 ), xycoords='data')

            plt.plot(0.5, 2*{base}, marker = 'o', color = 'red', markersize = 10)
            plt.gca().annotate('{exp_2_base}', xy=(0.5 + 0.2, 2*{base} + {base}/5 ), xycoords='data')

            plt.plot(0.25, 4*{base}, marker = 'o', color = 'red', markersize = 10)
            plt.gca().annotate('{exp_4_base}', xy=(0.25 + 0.2, 4*{base} + {base}/5 ), xycoords='data')

            plt.plot({2 * base}, 0.5, marker = 'o', color = 'red', markersize = 10)
            plt.gca().annotate('{exp_less_1}', xy=({2 * base} - 0.3, 0.5 + {base}/5 ), xycoords='data')

            plt.gca().spines['right'].set_visible(False)
            plt.gca().spines['top'].set_visible(False)

            plt.xlim(0, 2.3 * {base})
            plt.ylim(0, 5.3 * {base})
            """
        svgHelper = SvgHelper()
        svg_str, plot_code = svgHelper.get_svg_data(custom_code, strip_lines = True)
        problemTemplate.add_solution(svg_str, 'text/svg')

        problemTemplate.add_solution(plot_code)


        problemTemplate.add_problem(svg_str, 'text/svg')
        problemTemplate.add_answer(n1_answer)

        return problemTemplate


    def _problem_plot_exp_function(self, *args, **kwargs):
        infinity = symbols(u'\U0000221E')
        base = random.randint(2, 10)

        random_delta = random.choice(list(np.linspace(-2, 0, 21)))

        random_xs = [toIntOrFloat(x + random_delta)
                     for x in list(np.linspace(-2, 2, 5))]

        options = [toIntOrFloat(base ** x)
                   for x in random_xs]

        random_x = random.choice(random_xs)
        n1_random_x_expr = f"{{{base}}}^{{{toIntOrFloat(random_x)}}}"
        n1_answer = toIntOrFloat(base ** random_x)

        options_expr = ",\t".join([str(option) for option in options])

        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        statement = f"""
        The value of <b>$\\;\\;{n1_random_x_expr}\\;\\;$</b> is:\t {options_expr}
        """
        problemTemplate.add_problem(statement, "text/html")

        problemTemplate.add_solution(f"${n1_random_x_expr} = {n1_answer}$", "text/html")

        exp_0_1 = f"${{{base}}}^0 = 1$"
        exp_1_base = f"${{{base}}}^1 = {base}$"
        exp_inf_0 = f"${{{base}}}^{{{-infinity}}} = 0$"
        exp_neg = f"${{{base}}}^{{-ve}} < {base}$"
        exp_1_plus = f"${{{base}}}^{{1+}} > {base}$"

        custom_code = f"""
            from matplotlib import pyplot as plt
            import numpy as np

            xs = np.linspace(-2, 2, 100)
            ys = [{base}**item for item in xs]

            plt.plot(xs, ys)

            plt.plot(0, 1, marker = 'o', color = 'red', markersize = 10)
            plt.gca().annotate('{exp_0_1}', xy=(0 - 0.2, 1 + {base}/10 ), xycoords='data')


            plt.plot(1, {base}, marker = 'o', color = 'red', markersize = 10)
            plt.gca().annotate('{exp_1_base}', xy=(1 + 0.2, {base} - {base}/5 ), xycoords='data')

            plt.gca().annotate('{exp_inf_0}', xy=(-2, 0 - {base}/5), xycoords='data')

            plt.gca().annotate('{exp_neg}', xy=(-1, 0 - {base}/7), xycoords='data')
            plt.gca().annotate('{exp_1_plus}', xy=(1.3, 0 + {base} ** 1.2), xycoords='data')

            plt.gca().spines['right'].set_visible(False)
            plt.gca().spines['top'].set_visible(False)

            plt.xlim(-2.1, 2.5)
            plt.ylim(-2.1 * {base}, 2.3 * {base})
            """
        svgHelper = SvgHelper()
        svg_str, plot_code = svgHelper.get_svg_data(custom_code, strip_lines = True)
        problemTemplate.add_solution(svg_str, 'text/svg')

        problemTemplate.add_solution(plot_code)

        problemTemplate.add_problem(svg_str, 'text/svg')
        problemTemplate.add_answer(n1_answer)

        return problemTemplate



    def _problem_plot_log_function(self, *args, **kwargs):
        implies = symbols(u'\U000021D2')
        base = random.randint(2, 10)
        x = symbols('x')

        random_delta = random.choice([-0.2, -0.1, 0.1, 0.2])
        random_xs = [0.5, 1, base, base**2, base**3]
        random_x = random.choice(random_xs) + random_delta

        options = [toIntOrFloat(
                    np.log(i + random_delta)/np.log(base))
                   for i in random_xs]

        n1_expr = f"\log_{{{base}}}{{{x}}}"

        n1_random_x_expr = f"\log_{{{base}}}{{{random_x}}}"

        #f"{{{base}}}^{{{toIntOrFloat(random_x)}}}"

        n1_answer = toIntOrFloat(np.log(random_x)/np.log(base))

        options_expr = ",\t".join([str(option) for option in options])

        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        statement = f"""
        The value of <b>$\\;\\;{n1_random_x_expr}\\;\\;$</b> is:\t {options_expr}
        """
        problemTemplate.add_problem(statement, "text/html")

        problemTemplate.add_solution(f"${n1_random_x_expr} = {n1_answer}$", "text/html")

        log_1_0 = f"$\log_{{{base}}}1 = 0$"
        log_base_base = f"$\log_{{{base}}}{{{base}}} = 1$"
        log_negative = f"$\log_{{{base}}}{{(<1)}} < 0 $"
        log_more_1 = f"$\log_{{{base}}}{{(>{base})}} > 1 $"

        custom_code = f"""
            from matplotlib import pyplot as plt
            import numpy as np

            xs = np.linspace(0.000001, {base} * 2, 100)
            ys = [np.log(item)/np.log({base}) for item in xs]

            plt.plot({base}, 1, marker = 'o', color = 'green', markersize = 10)
            plt.plot(1, 0, marker = 'o', color = 'red', markersize = 10)
            plt.gca().annotate('{log_1_0}', xy=(1-0.20, 0-1), xycoords='data')
            plt.gca().annotate('{log_base_base}', xy=({base}-0.20, 1+0.5), xycoords='data')
            plt.gca().annotate('{log_negative}', xy=(0+0.50, -4+0.3), xycoords='data')
            plt.gca().annotate('{log_more_1}', xy=(1.6 * {base}+0.50, 1-0.3), xycoords='data')

            plt.gca().spines['right'].set_visible(False)
            plt.gca().spines['top'].set_visible(False)

            plt.plot(xs, ys)

            """
        svgHelper = SvgHelper()
        svg_str, plot_code = svgHelper.get_svg_data(custom_code, strip_lines = True)
        problemTemplate.add_solution(svg_str, 'text/svg')

        problemTemplate.add_solution(plot_code)

        problemTemplate.add_answer(n1_answer)
        problemTemplate.add_answer(svg_str, 'text/svg')


        return problemTemplate



    def _problem_expr_relation_log(self, *args, **kwargs):
        implies = symbols(u'\U000021D2')
        if random.choice([True, False]):
            base1, m1, m2 = random.sample(range(2, 10), 3)
            base2 = base1
        else:
            base1, base2, m1 = random.sample(range(2, 10), 3)
            m2 = m1

        n1 = log(m1, base1)
        n2 = log(m2, base2)

        n1_expr = f"\log_{{{base1}}}{{{m1}}}"
        n2_expr = f"\log_{{{base2}}}{{{m2}}}"

        if n1 == n2:
            op = "="
        elif n1 > n2:
            op = ">"
        else:
            op = "<"

        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        statement = f"""
        $\\displaystyle {n1_expr} \\quad \\text{{ ? }} \\quad {n2_expr}$ \t\tWrite <, = or >
        """
        problemTemplate.add_problem(statement, "text/html")

        comment = ""
        if m1 == m2:
            comment = "If numbers are same, the log of lower base is bigger."
        if base1 == base2:
            comment = "If bases are same, the log of bigger number is bigger."

        soln_s = f"""
        $\\displaystyle {n1_expr} \\quad \\text{{ ? }} \\quad {n2_expr}$

        $\\displaystyle {n1_expr} \\quad {op} \\quad {n2_expr} $ \t {comment}
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        svg_str, plot_code = self._get_bar_chart(
                                [n1, n2],
                                [f"${n1_expr}$", f"${n2_expr}$"],
                                addl_code = "from sympy import *")
        problemTemplate.add_solution(svg_str, 'text/svg')

        problemTemplate.add_solution("<b>Code to draw chart</b>", 'text/html')
        problemTemplate.add_solution(plot_code, 'text/html')



        answer_s = f"""$\\displaystyle {n1_expr} \\quad {op} \\quad {n2_expr} $"""
        problemTemplate.add_answer(f"{answer_s}", 'text/html')

        return problemTemplate

    def _problem_expr_relation_log_advanced(self, *args, **kwargs):
        implies = symbols(u'\U000021D2')
        base1, base2, m1, m2 = random.sample(range(1, 10), 4)

        nums = [base1, m1, base2, m2]
        random.shuffle(nums)
        e1 = ExpExpression(nums[0], nums[1])
        e2 = ExpExpression(nums[2], nums[3])

        log1_expr = f"\log_{{{base1}}}{{{m1}}}"
        log2_expr = f"\log_{{{base2}}}{{{m2}}}"

        log1_computed = log1_expr
        log2_computed = log2_expr

        if log(m1, base1) == log(m2, base2):
            op = "="
        elif log(m1, base1) > log(m2, base2):
            op = ">"
        else:
            op = "<"


        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        statement = f"""
        Write relation between the expression given below ( <, =, or > ):

        $\\displaystyle {log1_expr} \\quad \\text{{ ? }} \\quad {log2_expr}$
        """
        problemTemplate.add_problem(statement, "text/html")

        soln_s = f"""
        $\\displaystyle {log1_expr} \\quad \\text{{ ? }} \\quad {log2_expr}$
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        if m1 == 1 and m2 != 1:
            log1_computed = 0

            soln_s = f"""
            $\\displaystyle {log1_computed} \\quad \\text{{ ? }} \\quad {log2_computed}$
            """
            problemTemplate.add_solution(soln_s.strip(), 'text/html')

            if m2 > 1:
                log2_computed = f"\\text{{ A positive number }}"
            else:
                log2_computed = f"\\text{{ A negative number }}"
                pass

            soln_s = f"""
            $\\displaystyle {log1_computed} \\quad {op} \\quad {log2_computed} $
            """
            problemTemplate.add_solution(soln_s.strip(), 'text/html')

        elif m2 == 1 and m1 != 1:
            log2_computed = 0

            soln_s = f"""
            $\\displaystyle {log1_computed} \\quad \\text{{ ? }} \\quad {log2_computed}$
            """
            problemTemplate.add_solution(soln_s.strip(), 'text/html')

            if m1 > 1:
                log1_computed = f"\\text{{ A positive number }}"
            else:
                log1_computed = f"\\text{{ A negative number }}"
                pass

            soln_s = f"""
            $\\displaystyle {log1_computed} \\quad {op} \\quad {log2_computed}$
            """
            problemTemplate.add_solution(soln_s.strip(), 'text/html')
        else:
            log2_expanded_expr = f"""
            \log_{{{base2}}}{{{base1}}} *
            \log_{{{base1}}}{{{m1}}} *
            \log_{{{m1}}}{{{m2}}}
            """
            log1_computed = 1
            log2_computed = f"""
            \log_{{{base2}}}{{{base1}}} *
            \log_{{{m1}}}{{{m2}}}
            """

            soln_s = f"""
            $\\displaystyle {log1_expr} \\quad \\text{{ ? }} \\quad {log2_expanded_expr}$

            $\\displaystyle {log1_computed} \\quad \\text{{ ? }} \\quad {log2_computed}$ \t Divide both sides by ${log1_expr}$
            """
            problemTemplate.add_solution(soln_s.strip(), 'text/html')

            if base2 > base1 and m1 > m2:
                log2_computed = "\\text {{ (less than 1) * (less than 1) = Less than one }}"
                soln_s = f"""
                $\\displaystyle {log1_computed} \\quad \\text{{ ? }} \\quad {log2_computed}$
                """
                problemTemplate.add_solution(soln_s.strip(), 'text/html')

            if base2 < base1 and m1 < m2:
                log2_computed = "\\text {{ (greater than 1) * (greater than 1) = greater than one }}"
                soln_s = f"""
                $\\displaystyle {log1_computed} \\quad \\text{{ ? }} \\quad {log2_computed}$
                """
                problemTemplate.add_solution(soln_s.strip(), 'text/html')



        soln_s = f"""
        $\\displaystyle {implies} {log1_expr} \\quad {op} \\quad {log2_expr}$
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        n1 = log(m1, base1)
        n2 = log(m2, base2)

        svg_str, plot_code = self._get_bar_chart(
                                [n1, n2],
                                [f"${log1_expr}$", f"${log2_expr}$"],
                                addl_code = "from sympy import *")
        problemTemplate.add_solution(svg_str, 'text/svg')

        problemTemplate.add_solution("<b>Code to draw chart</b>", 'text/html')
        problemTemplate.add_solution(plot_code, 'text/html')



        answer_s = f"""$\\displaystyle {log1_expr} \\quad {op} \\quad {log2_expr} $"""
        problemTemplate.add_answer(f"{answer_s}", 'text/html')

        return problemTemplate




    def _problem_random_inequality_n1_n2(self, *args, **kwargs):
        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        implies = symbols(u'\U000021D2')
        m1 = random.randint(1, 10)
        m2 = random.choice([m1, random.randint(1, 10)])

        max_tries = 10
        while max_tries > 0:
            max_tries = max_tries - 1
            try:
                bve = BivariateExpressions(m1, m2)
                expr1, expr2 = random.sample(bve.expr_tuples, 2)

                n1 = expr1['result']
                n2 = expr2['result']
                n1_expr = expr1['expr']
                n2_expr = expr2['expr']

                n1_label = expr1['result_label']
                n2_label = expr2['result_label']

                if n1 == n2:
                    op = "="
                elif n1 > n2:
                    op = ">"
                else:
                    op = "<"
                    pass

                break
            except Exception as e:
                if self.verbose:
                    print(f"Error: {e}")
                n1 = None
                pass

        if n1 is None:
            problemTemplate.add_problem(f"""
            Failed to get problem
            """.strip(), "text/html")


        statement = f"""
        $\\displaystyle {n1_expr} \\quad \\text{{ ? }} \\quad {n2_expr}$ \t\tWrite <, = or >
        """
        problemTemplate.add_problem(statement, "text/html")

        soln_s = f"""
        $\\displaystyle {n1_expr} \\quad \\text{{ ? }} \\quad {n2_expr}$

        $\\displaystyle {n1_label} \\quad \\text{{ ? }} \\quad {n2_label}$

        $\\displaystyle {n1_label} \\quad {op} \\quad {n2_label} $

        $\\displaystyle {n1_expr} \\quad {op} \\quad {n2_expr} $
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        answer_s = f"""$\\displaystyle {n1_expr} \\quad {op} \\quad {n2_expr} $"""
        problemTemplate.add_answer(f"{answer_s}", 'text/html')

        svg_str, plot_code = self._get_bar_chart(
                                [n1, n2],
                                [f"${n1_expr}$", f"${n2_expr}$"],
                                addl_code = "from sympy import *")
        problemTemplate.add_solution(svg_str, 'text/svg')

        problemTemplate.add_solution("<b>Code to draw chart</b>", 'text/html')
        problemTemplate.add_solution(plot_code, 'text/html')

        return problemTemplate


    def _sample(self, *args, **kwargs):
        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        problem_s = f"""
        """
        problemTemplate.add_problem(problem_s.strip(), 'text/html')

        soln_s = f"""
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        answer_s = f"""
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')

        return problemTemplate

