'''
Created on 07-Feb-2021

@author: bthakur
'''
import random
import inspect
import traceback

from sympy import (latex, Rational)

from xv.km.util._latex import latex_fraction
        
from ..helper import BaseHelper
from xv.km.managers import BaseManager
from xv.km.kelements import KProblemTemplate
from sympy.core.expr import UnevaluatedExpr
from sympy.simplify.simplify import nsimplify
        
class AdvancedPowerManager(BaseManager):
    '''
    Power or Exponent
    Example:
        ke = AdvancedPowerManager()
        ke.printProblemTypes()
        
        ke.getRandomProblem()
        ke.getRandomProblem(problem_type = 0)
        ke.getRandomProblem(problem_type = 1)
        ...
        ke.printProblem()
        ke.printAnswer()
        ke.printSolution()

        ke.initProblem(10, 24)
        ke.initProblem(15, 25, 30)

    '''    
    def __new__(cls, *args, **kwargs):
        instance = super(AdvancedPowerManager, cls).__new__(cls, *args, **kwargs)
        for base_class in AdvancedPowerManager.__bases__:
            base_class.__init__(instance, *args, **kwargs)
        return instance
    
    def __init__(self, *args, **kwargs):
        self.base_helper = BaseHelper(**kwargs)
        pass


    
    def _init_problem_types(self, *args, **kwargs):
        self._append_problem_types([
            '_problem_evaluate_plus_expr',
            '_problem_evaluate_mul_expr',
            '_problem_evaluate_mul_expr_reversed',
            '_problem_express_as_power',
            '_problem_sum_of_pair_of_sum_series',
            '_problem_sum_of_pair_of_mul_series',
            '_problem_sum_of_pair_of_mul_series_reversed',
            '_problem_sum_large_series',
            '_problem_mul_large_series',
            '_problem_multiple_of_a_sum_series',
            '_problem_power_of_a_sum_series',
            '_problem_division_of_sum_series',
            '_problem_division_of_mul_series',
            '_problem_fraction_of_sum_series',
            '_problem_fraction_of_sum_series_reversed',
            '_problem_fraction_of_mul_series',
            '_problem_fraction_of_mul_series_reversed',
            '_problem_distribute_power_of_product',
            '_problem_simplify_as_expr_of_exponents',
            '_problem_difficult_problems',
         ])
        pass
    
    def _problem_evaluate_plus_expr(self, *args, **kwargs):
        pw = self.base_helper.get_arithmetic_helper().get_power_helper()
        result = pw.get_sum_series()

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

        problem_s = f"""Find value of 
        $\\displaystyle {result['expr_sum']}$
        """
        problemTemplate.add_problem(problem_s.strip(), 'text/html')
        
        soln_s = f"""
        $\\displaystyle {result['expr_sum']}$
        
        $\\displaystyle = {result['expr_mul_latex']}$
        
        $\\displaystyle = {result['expr_value']}$
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')
        
        answer_s = f"""
        $\\displaystyle {result['expr_value']}$
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        return problemTemplate
        pass

    def _problem_evaluate_mul_expr(self, *args, **kwargs):
        pw = self.base_helper.get_arithmetic_helper().get_power_helper()
        
        a = random.randint(0, 5)
        b = random.randint(2, 4)
        result = pw.get_mul_series(a = a, b = b)

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

        problem_s = f"""Find value of 
        $\\displaystyle {result['expr_mul']}$
        """
        problemTemplate.add_problem(problem_s.strip(), 'text/html')
        
        soln_s = f"""
        $\\displaystyle {result['expr_mul']}$
        
        $\\displaystyle = {latex(result['expr_power'])}$
        
        $\\displaystyle = {result['expr_value']}$
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')
        
        answer_s = f"""
        $\\displaystyle {result['expr_value']}$
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        return problemTemplate
        pass

    def _problem_evaluate_mul_expr_reversed(self, *args, **kwargs):
        pw = self.base_helper.get_arithmetic_helper().get_power_helper()
        
        a = random.randint(0, 5)
        b = random.randint(2, 4)
        result = pw.get_mul_series(a = a, b = b)

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

        problem_s = f"""Find value of 

        $\\displaystyle {latex(result['expr_power'])}$
        """
        problemTemplate.add_problem(problem_s.strip(), 'text/html')
        
        soln_s = f"""
        $\\displaystyle {latex(result['expr_power'])}$
        
        $\\displaystyle = {result['expr_mul']}$
        
        $\\displaystyle = {result['expr_value']}$
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')
        
        answer_s = f"""
        $\\displaystyle {result['expr_value']}$
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        return problemTemplate
        pass



    def _problem_express_as_power(self, *args, **kwargs):
        pw = self.base_helper.get_arithmetic_helper().get_power_helper()
        result = pw.get_mul_series()

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

        problem_s = f"""
        Express as power of {result['a']}:
        $\\displaystyle {result['expr_mul']}$
        """
        problemTemplate.add_problem(problem_s.strip(), 'text/html')
        
        soln_s = f"""
        $\\displaystyle {result['expr_mul']}$
        
        $\\displaystyle = {latex(result['expr_power'])}$
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')
        
        answer_s = f"""
        $\\displaystyle {latex(result['expr_power'])}$
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        return problemTemplate
        pass


    def _problem_sum_of_pair_of_sum_series(self, *args, **kwargs):
        pw = self.base_helper.get_arithmetic_helper().get_power_helper()
        
        a = random.randint(2, 10)
        result1 = pw.get_sum_series(a = a)
        result2 = pw.get_sum_series(a = a)
        
        b = result1['b'] + result2['b']
        result = pw.get_sum_series(a = a, b = b)

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

        problem_s = f"""Find value of 
        $\\displaystyle 
        \\left({result1['expr_sum']}\\right) + 
        \\left({result2['expr_sum']}\\right)
        $
        """
        problemTemplate.add_problem(problem_s.strip(), 'text/html')
        
        soln_s = f"""
        $\\displaystyle 
        \\left({result1['expr_sum']}\\right) + 
        \\left({result2['expr_sum']}\\right)
        $
        
        $\\displaystyle = {result1['expr_mul_latex']} + {result2['expr_mul_latex']}$
        
        $\\displaystyle = \\left( {result1['b']} + {result2['b']} \\right)
        * {result1['a']} 
        $

        $\\displaystyle = {result['expr_mul_latex']}$
        
        $\\displaystyle = {result['expr_value']}$
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')
        
        answer_s = f"""
        $\\displaystyle {result['expr_value']}$
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        return problemTemplate
        pass

    def _problem_sum_of_pair_of_mul_series(self, *args, **kwargs):
        pw = self.base_helper.get_arithmetic_helper().get_power_helper()
        
        a = random.randint(0, 5)
        b1 = random.randint(1, 4)
        b2 = random.randint(2, 4)
        result1 = pw.get_mul_series(a = a, b = b1)
        result2 = pw.get_mul_series(a = a, b = b2)
        
        b = result1['b'] + result2['b']
        
        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        problem_s = f"""Find value of 
        $\\displaystyle 
        \\left({result1['expr_mul']}\\right) + 
        \\left({result2['expr_mul']}\\right)
        $
        """
        problemTemplate.add_problem(problem_s.strip(), 'text/html')
        
        soln_s = f"""
        $\\displaystyle 
        \\left({result1['expr_mul']}\\right) + 
        \\left({result2['expr_mul']}\\right)
        $
        
        $\\displaystyle = {latex(result1['expr_power'])}
         + {latex(result2['expr_power'])}$

        $\\displaystyle = {latex(result1['expr_value'])}
         + {latex(result2['expr_value'])}$

        $\\displaystyle = {latex(result1['expr_value'] + result2['expr_value'])}
        $

        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')
        
        answer_s = f"""
        $\\displaystyle {latex(result1['expr_value'] + result2['expr_value'])}
        $
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        return problemTemplate
        pass

    def _problem_sum_of_pair_of_mul_series_reversed(self, *args, **kwargs):
        pw = self.base_helper.get_arithmetic_helper().get_power_helper()
        
        a = random.randint(0, 5)
        b1 = random.randint(1, 4)
        b2 = random.randint(2, 4)
        result1 = pw.get_mul_series(a = a, b = b1)
        result2 = pw.get_mul_series(a = a, b = b2)
        
        b = result1['b'] + result2['b']

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

        problem_s = f"""Find value of 
        $\\displaystyle {result1['expr_mul']} + {result2['expr_mul']}$
        """
        problemTemplate.add_problem(problem_s.strip(), 'text/html')
        
        soln_s = f"""
        $\\displaystyle {result1['expr_mul']} + {result2['expr_mul']}$
        
        $\\displaystyle = {latex(result1['expr_power'])}
         + {latex(result2['expr_power'])}$

        $\\displaystyle = {latex(result1['expr_value'])}
         + {latex(result2['expr_value'])}$

        $\\displaystyle = {latex(result1['expr_value'] + result2['expr_value'])}
        $

        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')
        
        answer_s = f"""
        $\\displaystyle {latex(result1['expr_value'] + result2['expr_value'])}
        $
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        return problemTemplate
        pass

    def _problem_sum_large_series(self, *args, **kwargs):
        pw = self.base_helper.get_arithmetic_helper().get_power_helper()

        b = random.choice([
            random.randint(-10, -1),
            0,
            random.randint(1, 10),
            ])
        result = pw.get_sum_series(b = b)

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

        problem_s = f"""
        Write expression to add {result['a']} with itself {result['b']} times.
        """
        problemTemplate.add_problem(problem_s.strip(), 'text/html')
        
        soln_s = f"""
        Result of adding {result['a']} with itself {result['b']} times
        
        $\\displaystyle = {result['large_series']}$
        
        $\\displaystyle = {result['expr_mul_latex']}$
        
        $\\displaystyle = {result['expr_value']}$
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')
        
        answer_s = f"""
        $\\displaystyle {result['expr_value']}$
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        return problemTemplate
        pass


    def _problem_mul_large_series(self, *args, **kwargs):
        pw = self.base_helper.get_arithmetic_helper().get_power_helper()

        b = random.choice([
            random.randint(-10, -1),
            0,
            random.randint(1, 10),
            ])
        result = pw.get_mul_series(b = b)

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

        problem_s = f"""
        Write exponential form when {result['a']} is multiplied with itself {result['b']} times.
        """
        problemTemplate.add_problem(problem_s.strip(), 'text/html')
        
        soln_s = f"""
        Result of multiplying {result['a']} with itself {result['b']} times
        
        $\\displaystyle = {result['large_series']}$
        
        $\\displaystyle = {latex(result['expr_power'])}$
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')
        
        answer_s = f"""
        $\\displaystyle {latex(result['expr_power'])}$
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        return problemTemplate
        pass

    
    def _problem_multiple_of_a_sum_series(self, *args, **kwargs):
        pw = self.base_helper.get_arithmetic_helper().get_power_helper()
        
        result = pw.express_multiple_of_a_sum_series()

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

        problem_s = f"""Express as multiples of {result['a']} 
        
        $\\displaystyle {result['exprs_sum']} $
        """
        problemTemplate.add_problem(problem_s.strip(), 'text/html')
        
        soln_s = f"""
        $\\displaystyle {result['exprs_sum']} $
        
        $\\displaystyle = {result['exprs_mul_latex']}$
        
        $\\displaystyle = {result['expr_mul']}$

        $\\displaystyle = {result['expr_value']}$
        
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')
        
        answer_s = f"""
        $\\displaystyle {result['expr_value']}$
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        return problemTemplate
        pass

    def _problem_power_of_a_sum_series(self, *args, **kwargs):
        pw = self.base_helper.get_arithmetic_helper().get_power_helper()
        
        a = random.randint(2, 5)
        b = random.randint(2, 5)
        c = random.randint(2, 5)
        
        result = pw.express_power_of_a_sum_series(a = a,
                                                  b = b,
                                                  c = c)

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

        problem_s = f"""Simplify the expression 
        
        $\\displaystyle {result['exprs_mul']} $
        """
        problemTemplate.add_problem(problem_s.strip(), 'text/html')
        
        
        soln_s = f"""
        $\\displaystyle {result['exprs_mul']} $
        
        $\\displaystyle = {result['exprs_power_latex']}$
        
        $\\displaystyle = {result['expr_power']}$
        
        $\\displaystyle = {result['expr_dist_power']}$
        
        $\\displaystyle = {result['expr_dist_value']}$
        
        $\\displaystyle = {result['expr_value']}$
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')
        
        answer_s = f"""
        $\\displaystyle {result['expr_value']}$
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        return problemTemplate
        pass



    def _problem_division_of_sum_series(self, *args, **kwargs):
        pw = self.base_helper.get_arithmetic_helper().get_power_helper()
        
        a = random.randint(2, 10)
        result1 = pw.get_sum_series(a = a)
        result2 = pw.get_sum_series(a = a)
        
        b1 = result1['b']
        b2 = result2['b']
        
        expr_sum_fraction = latex_fraction(f"{result1['expr_sum']}",
                                       f"{result2['expr_sum']}")
        
        expr_mul_fraction = latex_fraction(f"{result1['expr_mul_latex']}",
                                       f"{result2['expr_mul_latex']}")

        b = Rational(b1, b2)
        b_fraction = latex_fraction(b1, b2)
        result = pw.get_sum_series(a = a, b = b)

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

        problem_s = f"""Simplify
        
        $\\displaystyle {expr_sum_fraction}$
        """
        problemTemplate.add_problem(problem_s.strip(), 'text/html')
        
        soln_s = f"""
        $\\displaystyle {expr_sum_fraction}$
        
        $\\displaystyle = {expr_mul_fraction}$

        $\\displaystyle = {b_fraction} $ \t\t After canceling {a} 
        
        $\\displaystyle = {latex(b)}$
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')
        
        answer_s = f"""
        $\\displaystyle {latex(b)}$
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        return problemTemplate
        pass

    
    def _problem_fraction_of_sum_series(self, *args, **kwargs):
        pw = self.base_helper.get_arithmetic_helper().get_power_helper()
        
        a = random.randint(2, 10)
        result1 = pw.get_sum_series(a = a)
        result2 = pw.get_sum_series(a = a)
        result3 = pw.get_sum_series(a = a)
        
        b1 = result1['b']
        b2 = result2['b']
        
        expr_sum_fraction = latex_fraction(f"{result1['expr_sum']}",
                                       f"{result2['expr_sum']}")
        
        expr_sum_fraction = f"{expr_sum_fraction} + {result3['expr_sum']}"
        
        expr_mul_fraction = latex_fraction(f"{result1['expr_mul_latex']}",
                                       f"{result2['expr_mul_latex']}")

        expr_mul_fraction = f"{expr_mul_fraction} + {result3['expr_mul_latex']}"
        
        b1_b2_fraction = latex_fraction(b1, b2)
        b = Rational(b1, b2)
        
        expr_value = b + result3['expr_value']

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

        problem_s = f"""Simplify
        
        $\\displaystyle {expr_sum_fraction}$
        """
        problemTemplate.add_problem(problem_s.strip(), 'text/html')
        
        soln_s = f"""
        $\\displaystyle {expr_sum_fraction}$
        
        $\\displaystyle = {expr_mul_fraction}$

        $\\displaystyle = {b1_b2_fraction} +  {result3['expr_value']}$
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        if b.p != b1:
            soln_s = f"""
            $\\displaystyle = {latex(b)} +  {result3['expr_value']}$
            """
            problemTemplate.add_solution(soln_s.strip(), 'text/html')
            pass
        
        soln_s = f"""
        $\\displaystyle = {latex(expr_value)}$
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')
        
        answer_s = f"""
        $\\displaystyle {latex(expr_value)}$
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        return problemTemplate
        pass
    
    def _problem_fraction_of_sum_series_reversed(self, *args, **kwargs):
        pw = self.base_helper.get_arithmetic_helper().get_power_helper()
        
        a = random.randint(2, 10)
        result1 = pw.get_sum_series(a = a)
        result2 = pw.get_sum_series(a = a)
        result3 = pw.get_sum_series(a = a)
        
        b1 = result1['b']
        b2 = result2['b']
        
        expr_sum_fraction = latex_fraction(f"{result1['expr_sum']}",
                                       f"{result2['expr_sum']}")
        
        expr_sum_fraction = f"{result3['expr_sum']} + {expr_sum_fraction}"
        
        expr_mul_fraction = latex_fraction(f"{result1['expr_mul_latex']}",
                                       f"{result2['expr_mul_latex']}")

        expr_mul_fraction = f"{result3['expr_mul_latex']} + {expr_mul_fraction}"
        
        b1_b2_fraction = latex_fraction(b1, b2)
        b = Rational(b1, b2)
        
        expr_value = b + result3['expr_value']

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

        problem_s = f"""Simplify
        
        $\\displaystyle {expr_sum_fraction}$
        """
        problemTemplate.add_problem(problem_s.strip(), 'text/html')
        
        soln_s = f"""
        $\\displaystyle {expr_sum_fraction}$
        
        $\\displaystyle = {expr_mul_fraction}$

        $\\displaystyle = {result3['expr_value']} + {b1_b2_fraction}$
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        if b.p != b1:
            soln_s = f"""
            $\\displaystyle = {result3['expr_value']} + {latex(b)}$
            """
            problemTemplate.add_solution(soln_s.strip(), 'text/html')
            pass
        
        soln_s = f"""
        $\\displaystyle = {latex(expr_value)}$
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')
        
        answer_s = f"""
        $\\displaystyle {latex(expr_value)}$
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        return problemTemplate
        pass

    def _problem_division_of_mul_series(self, *args, **kwargs):
        pw = self.base_helper.get_arithmetic_helper().get_power_helper()
        
        a = random.randint(2, 10)
        result1 = pw.get_mul_series(a = a)
        result2 = pw.get_mul_series(a = a)
        
        b1 = result1['b']
        b2 = result2['b']
        
        expr_mul_fraction = latex_fraction(f"{result1['expr_mul']}",
                                           f"{result2['expr_mul']}")
        
        expr_power_fraction = latex_fraction(f"{latex(result1['expr_power'])}",
                                             f"{latex(result2['expr_power'])}")

        b = b1 - b2
        expr_power_gross = f"{a}^{{{b1} - {b2}}}"
        expr_power = f"{a}^{{{b}}}"

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

        problem_s = f"""Simplify
        
        $\\displaystyle {expr_mul_fraction}$
        """
        problemTemplate.add_problem(problem_s.strip(), 'text/html')
        
        soln_s = f"""
        $\\displaystyle {expr_mul_fraction}$
        
        $\\displaystyle = {expr_power_fraction}$

        $\\displaystyle = {expr_power_gross}$

        $\\displaystyle = {expr_power}$
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')
        
        answer_s = f"""
        $\\displaystyle {expr_power}$
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        return problemTemplate
        pass


    def _problem_fraction_of_mul_series(self, *args, **kwargs):
        pw = self.base_helper.get_arithmetic_helper().get_power_helper()
        
        a = random.randint(2, 10)
        result1 = pw.get_mul_series(a = a)
        result2 = pw.get_mul_series(a = a)
        result3 = pw.get_mul_series(a = a)
        
        b1 = result1['b']
        b2 = result2['b']
        
        expr_mul_fraction = latex_fraction(f"{result1['expr_mul']}",
                                           f"{result2['expr_mul']}")
        
        
        expr_mul_fraction = f"{expr_mul_fraction} + {result3['expr_mul']}"
        
        expr_power_fraction_gross = latex_fraction(f"{latex(result1['expr_power'])}",
                                             f"{latex(result2['expr_power'])}")


        expr_power_fraction_gross = f"{expr_power_fraction_gross} + {latex(result3['expr_power'])}"

        b = b1 - b2
        expr_power_b1_b2 = f"{a}^{{{b}}}"
        expr_power_fraction = f"{expr_power_b1_b2} + {latex(result3['expr_power'])}"
        
        expr_value = nsimplify(a**b) + result3['expr_value']

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

        problem_s = f"""Simplify
        
        $\\displaystyle {expr_mul_fraction}$
        """
        problemTemplate.add_problem(problem_s.strip(), 'text/html')
        
        soln_s = f"""
        $\\displaystyle {expr_mul_fraction}$
        
        $\\displaystyle = {expr_power_fraction_gross}$

        $\\displaystyle = {expr_power_fraction}$

        $\\displaystyle = {latex(nsimplify(a**b))} 
        + {latex(result3['expr_value'])}$

        $\\displaystyle = {latex(expr_value)}$
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        answer_s = f"""
        $\\displaystyle {latex(expr_value)}$
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        return problemTemplate
        pass
    
    def _problem_fraction_of_mul_series_reversed(self, *args, **kwargs):
        pw = self.base_helper.get_arithmetic_helper().get_power_helper()
        
        a = random.randint(2, 10)
        result1 = pw.get_mul_series(a = a)
        result2 = pw.get_mul_series(a = a)
        result3 = pw.get_mul_series(a = a)
        
        b1 = result1['b']
        b2 = result2['b']
        
        expr_mul_fraction = latex_fraction(f"{result1['expr_mul']}",
                                           f"{result2['expr_mul']}")
        
        
        expr_mul_fraction = f"{result3['expr_mul']} + {expr_mul_fraction}"
        
        expr_power_fraction_gross = latex_fraction(f"{latex(result1['expr_power'])}",
                                             f"{latex(result2['expr_power'])}")


        expr_power_fraction_gross = f"{latex(result3['expr_power'])} + {expr_power_fraction_gross}"

        b = b1 - b2
        expr_power_b1_b2 = f"{a}^{{{b}}}"
        expr_power_fraction = f"{latex(result3['expr_power'])} + {expr_power_b1_b2}"
        
        expr_value = nsimplify(a**b) + result3['expr_value']

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

        problem_s = f"""Simplify
        
        $\\displaystyle {expr_mul_fraction}$
        """
        problemTemplate.add_problem(problem_s.strip(), 'text/html')
        
        soln_s = f"""
        $\\displaystyle {expr_mul_fraction}$
        
        $\\displaystyle = {expr_power_fraction_gross}$

        $\\displaystyle = {expr_power_fraction}$

        $\\displaystyle = {latex(result3['expr_value'])}
        + {latex(nsimplify(a**b))} 
        $

        $\\displaystyle = {latex(expr_value)}$
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        answer_s = f"""
        $\\displaystyle {latex(expr_value)}$
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        return problemTemplate
        pass
    
    
    def _problem_distribute_power_of_product(self, *args, **kwargs):
        pw = self.base_helper.get_arithmetic_helper().get_power_helper()
        
        e = random.choice([
            0,
            random.randint(1, 10),
            random.randint(-10, -1),
            Rational(random.randint(1, 10), random.randint(2, 10))
            ])
        
        print(f"e = {e}")
        
        result = pw.distribute_power_of_product_expr(e = e)

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

        problem_s = f"""Distribute power:
        
        $\\displaystyle {latex(result['expr_power'])} $
        """
        problemTemplate.add_problem(problem_s.strip(), 'text/html')
        
        soln_s = f"""
        $\\displaystyle {latex(result['expr_power'])} $
        
        $\\displaystyle = {latex(result['expr_dist_power'])}$
        
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')
        
        answer_s = f"""
        $\\displaystyle {latex(result['expr_dist_power'])}$
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        return problemTemplate
        pass
    

    def _problem_simplify_as_expr_of_exponents(self, *args, **kwargs):
        
        ap_helper = self.base_helper.get_arithmetic_helper().get_advanced_power_helper()
        
        result = ap_helper.get_problem_simplify_as_expr_of_exponents(**kwargs)
        
        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        prob_s = f"""
        {result['prob_s']}
        """
        problemTemplate.add_problem(prob_s.strip(), 'text/html')
        
        soln_s = f"""
        {result['soln_s']}
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')
        
        answer_s = f"""
        {result['answer_s']}
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        return problemTemplate

        pass
    
    
    def _problem_difficult_problems(self, *args, **kwargs):
        ap_helper = self.base_helper.get_arithmetic_helper().get_advanced_power_helper()
        
        result = ap_helper.get_problem_difficult_problems(**kwargs)
        
        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        prob_s = f"""
        {result['prob_s']}
        """
        problemTemplate.add_problem(prob_s.strip(), 'text/html')
        
        soln_s = f"""
        {result['soln_s']}
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')
        
        answer_s = f"""
        {result['answer_s']}
        """
        problemTemplate.add_answer(answer_s.strip(), '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

