python-3.xjinja2pdfkittimetable

Horizontally merge and divide cells in an HTML Table for Timetable based on the Data in Python File


Please note this question is an extension of this previously asked question: How to make Images/PDF of Timetable using Python

I am working on a program that generates randomized Timetable based on an algorithm. For the Final Output of that program, I require a Timetable to be stored in a PDF File.

There are multiple sections and each section must have its own timetable/schedule. Each Section can have multiple Courses whose lectures will be allocated on different slots from Monday to Friday by the algorithm. For my timetable,

As an Example, I have created below a dictionary where key represents the Section and the items have a 2D Array of size 5x5. Each Index of that 2D array contains the course details for which the lecture will take place in that slot.

CS-3B :  [['', '', 'DS ', '', 'COaAL '], ['', 'COaAL ', '', 'DS ', 'OOP '], ['DS-L ', 'DS-L ', 'OOP-L ', 'OOP-L ', 'FoM '], ['COaAL-L ', 'COaAL-L ', 'OOP ', '', ''], ['', 'FoM ', 'DE ', '', 'DE ']]
SE-3A :  [['', 'OOP-L ', 'OOP-L ', '', 'SRE '], ['SRE ', 'OOP ', 'DS-L ', 'DS-L ', ''], ['', 'DS ', '', '', 'MM '], ['DS ', 'MM ', '', 'LA ', ''], ['OOP ', 'HCI ', '', 'LA ', 'HCI ']]

This, however, only contains "strings'. While, in actual data, there would be object of a course instead of that string. That object will contain different information regarding that course for which the lecture is going to take place on that specific slot of the day.

While generating the timetable, there are three major concerns that must be resolved,

  1. Lectures for "Labs" are held over two consecutive slots. So, for all the labs, those two cells in the table must be merged

  2. It is possible that at the same time, two or more than two different lectures are taking place for one section. In such a case, the cell of that slot must be horizontally divided into two or more cells

  3. It is also possible that at the same time, two lectures are being held at one slot and one of those two lectures can be of Lab. In such a case, two consecutive cells should be merged and also horizontally divided to accomadate both the lectures.

With help of previous post, I was able to transform this Data into PDF format using Jinja library. However, it was only doing it on strings, by differentiating between consecutive lectures with space character. Now, I have complete objects and I am unable to do the same with them.

I placed a list of objects on each index of 2D Array. That list may contain no object, one object or multiple objects (one object represents one course). Moreover, there is a single object for a Lab course (and that single object is added to the two consecutive indexes in which lab lecture is being held)

Following is the complete code (I have created sample data for only two sections)

from typing import List
import pdfkit
from pdfkit.api import configuration
from jinja2 import FileSystemLoader, Environment
wkhtml_path = pdfkit.configuration(wkhtmltopdf = "C:\\Program Files\\wkhtmltopdf\\bin\\wkhtmltopdf.exe")  #by using configuration you can add path value.

class section:
    def __init__(self, id, course, section, instructor, room):
        self.id = id
        self.course = course
        self.section = section
        self.instructor = instructor
        self.room = room

def generate_data():
    data = {}

    # For CS-1A
    data["CS-1A"] = [[[] for i in range(5)] for j in range(5)]
    data["CS-1A"][0][0].append(section(1, "Advance Programming", "CS-1A", "Mr. Ashas", "Room #2"))
    data["CS-1A"][0][0].append(section(2, "Programming Fundamentals", "CS-1A", "Bilal", "Room #1"))
    data["CS-1A"][0][1].append(section(3, "Applied Physics", "CS-1A", "Muhammad Bilal", "Room #5"))
    obj = section(4, "Programming Lab", "CS-1A", "Mr. Abid", "Lab #01")
    data["CS-1A"][0][1].append(obj)
    data["CS-1A"][0][2].append(obj)
    data["CS-1A"][0][4].append(section(5, "English Communication", "CS-1A1", "Ms. Ayeza", "Cal Lab"))
    data["CS-1A"][0][4].append(section(6, "English Communication", "CS-1A2", "Ms. Ayesha", "GP Lab"))
    data["CS-1A"][1][1].append(section(7, "Linear Algebra", "CS-1A", "Ms. Zain", "Romm #2"))
    obj = section(8, "English Lab", "CS-1A", "Ms. Abida", "Lab #04")
    data["CS-1A"][1][3].append(obj)
    data["CS-1A"][1][4].append(obj)
    data["CS-1A"][2][0].append(section(9, "Social Studies", "CS-1A", "Mr. Zain Iqbal", "Room #14"))
    data["CS-1A"][2][4].append(section(10, "Programming Fundamentals", "CS-1A", "Bilal", "Room #15"))
    # No lectures on Thursday i.e. 3rd index
    obj = section(11, "English Lab", "CS-1A", "Ms. Abida", "Lab #03")
    data["CS-1A"][4][1].append(obj)
    data["CS-1A"][4][2].append(obj)
    data["CS-1A"][4][2].append(section(12, "English Communication", "CS-1A1", "Ms. Ayeza", "Room #3"))
    data["CS-1A"][4][2].append(section(13, "English Communication", "CS-1A2", "Ms. Ayesha", "GP Lab"))



    # For CS-1B
    data["CS-1B"] = [[[] for i in range(5)] for j in range(5)]

    data["CS-1B"][0][1].append(section(14, "Advance Programming", "CS-1B", "Mr. Ali Hassan", "Room #2"))
    data["CS-1B"][0][2].append(section(15, "English Comprehension and Communication", "CS-1B", "Mr. Bilal", "Room #1"))
    obj = section(15, "Software for Mobile and Devices", "CS-1B", "Mr. Jacob", "Room #5")
    data["CS-1B"][1][1].append(obj)
    data["CS-1B"][1][2].append(obj)
    data["CS-1B"][1][3].append(section(17, "Calculus and Geometrical Analytics", "CS-1B", "Ms. Nomi Khan", "Room #06"))
    data["CS-1B"][2][3].append(section(18, "Introduction to Information and Communication Technology - Lab", "CS-1B1", "Ms. Sarah Niaz", "Lab #01"))
    data["CS-1B"][2][3].append(section(19, "Introduction to Information and Communication Technology - Lab", "CS-1B2", "Ms. Julia John", "Lab #06"))
    data["CS-1B"][2][4].append(section(20, "English Comprehenseion and Communication", "Cs-1B", "Mr. Lionel Boyle", "Room #02"))
    data["CS-1B"][3][3].append(section(21, "Programming Fundamentals", "CS-1B", "Mr. Alex Niles", "Room #3"))
    data["CS-1B"][4][2].append(section(22, "Linear Algebra", "CS-1B", "Ms. Ayesha", "GP Lab"))

    return data

def organise_input_data(elements: List[List[str]]) -> List[list]:
    """
    Organises the input data to find double courses for easier use in templates
    """
    new_elements = []
    for day in elements:
        last_course = None
        course_list = []
        index = 0
        for course in day:
            # check if long course (and not lunch time)
            if not course:
                course_list.append(("", "", "", 1))
            else:
                if course[0] == last_course and index != 3:
                    #for sub_course in course:
                    course_list.remove((course[0].course, course[0].section, course[0].instructor, 1))
                    course_list.append((course[0].course, course[0].section, course[0].instructor, 2))
                    course_list.append(("none", "none", "none", 0))
                    last_course = course[0]
                else:
                    #for sub_course in course:
                    course_list.append((course[0].course, course[0].section, course[0].instructor, 1))
                    last_course = course[0]
            index += 1
        #print(course_list)
        new_elements.append(course_list)

    return new_elements


def generate_html(template, name: str, elements: List[list]) -> str:

    new_elements = organise_input_data(elements=elements)

    rendered = template.render(
        name=name,
        monday=new_elements[0],
        tuesday=new_elements[1],
        wednesday=new_elements[2],
        thursday=new_elements[3],
        friday=new_elements[4]
    )

    with open(f"out_{name}.html", "w+") as file:
        file.write(rendered)

    return rendered


def run(input_data):
    # Init jinja
    file_loader = FileSystemLoader('.')
    env = Environment(loader=file_loader)
    template = env.get_template('template.html')

    full_text = ""
    for name, elements in input_data.items():
        full_text += generate_html(template=template, name=name, elements=elements)
    pdfkit.from_string(full_text, "out1.pdf", configuration = wkhtml_path)


if __name__ == '__main__':
    
    data = generate_data()
    run(data)

For now, it will only consider the first Course and will place it in the Timetable, while ignoring the rest of the courses allocated on that same slot.

A sample Final Output would be like this (but with only 5 slots, not 13 slots like here)

enter image description here

The template.html file for my code has this following code right now,

<!DOCTYPE html>
<html>
  <style>
.center
{
  text-align: center;

}
.left
{
    text-align: left;
    margin-left: 6px;
    /*margin-top: 10px;*/
}
.right
{
    text-align: right;  margin-right: 4px;
}
.teacher
{
    margin-left: 4px;
}
td{
  height:100px;
  width:150px;
}


  </style>
<body>
<!-- Heading -->
    <h1 class="center">{{name}}</h1>

<!-- Table -->
    <table border="5" cellspacing="5" align="center">

<!-- Day/Periods -->
        <tr>
            <td class="center" ><br>
                <b>Day/Period</b></br>
            </td>
            <td class="center" >
                <b>I</b>
            </td>
            <td class="center" >
                <b>II</b>
            </td>
            <td class="center">
                <b>III</b>
            </td>
            <td class="center">
                <b>1:15-1:45</b>
            </td>
            <td class="center" >
                <b>IV</b>
            </td>
            <td class="center" >
                <b>V</b>
            </td>

        </tr>
<!-- Monday -->
        <tr>
            <td class="center">
                <b>Monday</b></td>
            {% for course in monday %}
                {% if loop.index == 4 %}
                    <td rowspan="6" class="center">
                        <h2>L<br>U<br>N<br>C<br>H</h2>
                    </td>
                {% endif %}
                {% if course[3] != 0 %}
                    <td colspan={{course[3]}}>
                        <p class="left">{{course[0]}}</p>
                        <p class="right">{{course[1]}}</p>
                        <p class="teacher">{{course[2]}}</p>
                    </td>
                {% endif %}
            {% endfor %}

        </tr>
<!-- Tuesday -->
        <tr>
            <td class="center">
                <b>Tuesday</b>
            </td>
            {% for course in tuesday %}
                {% if course[3] != 0 %}
                    <td colspan={{course[3]}}>
                        <p class="left">{{course[0]}}</p>
                        <p class="right">{{course[1]}}</p>
                        <p class="teacher">{{course[2]}}</p>
                    </td>
                {% endif %}
            {% endfor %}
        </tr>
<!-- Wednesday -->
        <tr>
            <td class="center">
                <b>Wednesday</b>
            </td>
            {% for course in wednesday %}
                {% if course[3] != 0 %}
                    <td colspan={{course[3]}}>
                        <p class="left">{{course[0]}}</p>
                        <p class="right">{{course[1]}}</p>
                        <p class="teacher">{{course[2]}}</p></td>
                {% endif %}
            {% endfor %}
        </tr>
<!-- Thursday -->
        <tr>
            <td class="center">
                <b>Thursday</b>
            </td>
            {% for course in thursday %}
                {% if course[3] != 0 %}
                    <td colspan={{course[3]}}>
                    <p class="left">{{course[0]}}</p>
                        <p class="right">{{course[1]}}</p>
                        <p class="teacher">{{course[2]}}</p></td>
                {% endif %}
            {% endfor %}

        </tr>
<!-- Friday -->
        <tr>
            <td class="center">
                <b>Friday</b>
            </td>
            {% for course in friday %}
                {% if course[3] != 0 %}
                    <td colspan={{course[3]}}>
                        <p class="left">{{course[0]}}</p>
                        <p class="right">{{course[1]}}</p>
                        <p class="teacher">{{course[2]}}</p>
                    </td>
                {% endif %}
            {% endfor %}

        </tr>

    </table>
</body>

</html>

Solution

  • I am not much familiar with Jinja, so this answer might not be the most efficient one.

    By using basic hard coding in your Template.HTML file, I was able to achieve the results you are trying to. For this, I used the same code that was given by D-E-N in your previous question.

    I combined all the attributes of your object into a string

    Here's the updated code of yours with these changes,

    from typing import List
    import pdfkit
    from pdfkit.api import configuration
    from jinja2 import FileSystemLoader, Environment
    wkhtml_path = pdfkit.configuration(wkhtmltopdf = "C:\\Program Files\\wkhtmltopdf\\bin\\wkhtmltopdf.exe")  #by using configuration you can add path value.
    
    class section:
        def __init__(self, id, course, section, instructor, room):
            self.id = id
            self.course = course
            self.section = section
            self.instructor = instructor
            self.room = room
    
    def generate_data():
        data = {}
    
        # For CS-1A
        data["CS-1A"] = [["" for i in range(5)] for j in range(5)]
        data["CS-1A"][0][0] += "Advance_Programming@Mr.Ashas@Room_#2 "
        data["CS-1A"][0][0] += "Applied_Physics@Bilal@Room_#1 "
        data["CS-1A"][0][1] += "Programming_Fundamentals@Muhammad_Bilal@Room_#1 "
        data["CS-1A"][0][3] += "Programming_Fundamentals_Lab@Mr._Abid@Lab_#01 "
        data["CS-1A"][0][4] += "Programming_Fundamentals_Lab@Mr._Abid@Lab_#01 "
    
        # You may change all these for testing purposes. 
        # data["CS-1A"][0][0].append(section(2, "Programming Fundamentals", "CS-1A", "Bilal", "Room #1"))
        # data["CS-1A"][0][1].append(section(3, "Applied Physics", "CS-1A", "Muhammad Bilal", "Room #5"))
        # obj = section(4, "Programming Lab", "CS-1A", "Mr. Abid", "Lab #01")
        # data["CS-1A"][0][1].append(obj)
        # data["CS-1A"][0][2].append(obj)
        # data["CS-1A"][0][4].append(section(5, "English Communication", "CS-1A1", "Ms. Ayeza", "Cal Lab"))
        # data["CS-1A"][0][4].append(section(6, "English Communication", "CS-1A2", "Ms. Ayesha", "GP Lab"))
        # data["CS-1A"][1][1].append(section(7, "Linear Algebra", "CS-1A", "Ms. Zain", "Romm #2"))
        # obj = section(8, "English Lab", "CS-1A", "Ms. Abida", "Lab #04")
        # data["CS-1A"][1][3].append(obj)
        # data["CS-1A"][1][4].append(obj)
        # data["CS-1A"][2][0].append(section(9, "Social Studies", "CS-1A", "Mr. Zain Iqbal", "Room #14"))
        # data["CS-1A"][2][4].append(section(10, "Programming Fundamentals", "CS-1A", "Bilal", "Room #15"))
        # # No lectures on Thursday i.e. 3rd index
        # obj = section(11, "English Lab", "CS-1A", "Ms. Abida", "Lab #03")
        # data["CS-1A"][4][1].append(obj)
        # data["CS-1A"][4][2].append(obj)
        # data["CS-1A"][4][2].append(section(12, "English Communication", "CS-1A1", "Ms. Ayeza", "Room #3"))
        # data["CS-1A"][4][2].append(section(13, "English Communication", "CS-1A2", "Ms. Ayesha", "GP Lab"))
        #
        #
        #
        # # For CS-1B
        # data["CS-1B"] = [[[] for i in range(5)] for j in range(5)]
        #
        # data["CS-1B"][0][1].append(section(14, "Advance Programming", "CS-1B", "Mr. Ali Hassan", "Room #2"))
        # data["CS-1B"][0][2].append(section(15, "English Comprehension and Communication", "CS-1B", "Mr. Bilal", "Room #1"))
        # obj = section(15, "Software for Mobile and Devices", "CS-1B", "Mr. Jacob", "Room #5")
        # data["CS-1B"][1][1].append(obj)
        # data["CS-1B"][1][2].append(obj)
        # data["CS-1B"][1][3].append(section(17, "Calculus and Geometrical Analytics", "CS-1B", "Ms. Nomi Khan", "Room #06"))
        # data["CS-1B"][2][3].append(section(18, "Introduction to Information and Communication Technology - Lab", "CS-1B1", "Ms. Sarah Niaz", "Lab #01"))
        # data["CS-1B"][2][3].append(section(19, "Introduction to Information and Communication Technology - Lab", "CS-1B2", "Ms. Julia John", "Lab #06"))
        # data["CS-1B"][2][4].append(section(20, "English Comprehenseion and Communication", "Cs-1B", "Mr. Lionel Boyle", "Room #02"))
        # data["CS-1B"][3][3].append(section(21, "Programming Fundamentals", "CS-1B", "Mr. Alex Niles", "Room #3"))
        # data["CS-1B"][4][2].append(section(22, "Linear Algebra", "CS-1B", "Ms. Ayesha", "GP Lab"))
    
        return data
    
    def organise_input_data(elements: List[List[str]]) -> List[list]:
        """
        Organises the input data to find double courses for easier use in templates
        """
        new_elements = []
        for day in elements:
            last_course = None
            course_list = []
            index = 0
            for course in day:
                # cleanup data
                course = course.strip().replace(" ", "<hr>")
                # check if long course (and not lunch time)
                if course != "" and course == last_course and index != 3:
                    course_list.remove((course, 1))
                    course_list.append((course, 2))
                    course_list.append(("none", 0))
                else:
                    course_list.append((course.replace(" ", "<hr>"), 1))
                last_course = course
                index += 1
            new_elements.append(course_list)
    
        return new_elements
    
    
    def generate_html(template, name: str, elements: List[list]) -> str:
    
        new_elements = organise_input_data(elements=elements)
    
        rendered = template.render(
            name=name,
            monday=new_elements[0],
            tuesday=new_elements[1],
            wednesday=new_elements[2],
            thursday=new_elements[3],
            friday=new_elements[4]
        )
    
        with open(f"out_{name}.html", "w+") as file:
            file.write(rendered)
    
        return rendered
    
    
    def run(input_data):
        # Init jinja
        file_loader = FileSystemLoader('.')
        env = Environment(loader=file_loader)
        template = env.get_template('template.html')
    
        full_text = ""
        for name, elements in input_data.items():
            full_text += generate_html(template=template, name=name, elements=elements)
    
        pdfkit.from_string(full_text, "out.pdf", configuration = wkhtml_path)
    
    
    if __name__ == '__main__':
        data = generate_data()
        run(data)
    

    Major changes are done in the template.html file to achieve what you are trying to achieve. Here's the Code,

    <!DOCTYPE html>
    
    <html>
      <style>
    .center
    {
      text-align: center;
    
    }
    .left
    {
        text-align: left;
        margin-left: 6px;
        /*margin-top: 10px;*/
    }
    .right
    {
        text-align: right;  margin-right: 4px;
    }
    .teacher
    {
        margin-left: 4px;
    }
    td{
      height:175px;
      width:150px;
    }
    
    
      </style>
    <body>
    <!-- Heading -->
        <h1 class="center">{{name}}</h1>
    
    <!-- Table -->
        <table border="5" cellspacing="5" align="center">
    
    <!-- Day/Periods -->
            <tr>
                <td class="center" ><br>
                    <b>Day/Period</b></br>
                </td>
                <td class="center" >
                    <b>I</b>
                </td>
                <td class="center" >
                    <b>II</b>
                </td>
                <td class="center">
                    <b>III</b>
                </td>
                <td class="center">
                    <b>1:15-1:45</b>
                </td>
                <td class="center" >
                    <b>IV</b>
                </td>
                <td class="center" >
                    <b>V</b>
                </td>
    
            </tr>
    <!-- Monday -->
            <tr>
                <td class="center">
                    <b>Monday</b></td>
                {% for course in monday %}
                    {% if loop.index == 4 %}
                        <td rowspan="6" class="center">
                            <h2>L<br>U<br>N<br>C<br>H</h2>
                        </td>
                    {% endif %}
                    {% if course[1] != 0 %}
                        <td colspan={{course[1]}}>
                            {% set count = [] %}
                            {%- for y in range(0, 5) -%}
                                {%- if count|length < course[0]|length -%}
                                    <p class="left">
                                
                                        {%- for z in range(count|length, course[0]|length) -%}
                                            {%- if course[0][count|length] == '@' -%}
                                            {%- else -%}
                                                {% set __ = count.append(1) %}
                                                {%- if course[0][count|length-1] == '_' -%}
                                                    {{' '}}
                                                {%- else -%}
                                                    {{course[0][count|length-1]}}
                                                {%- endif -%}
                                            {%- endif -%}
                                        {%- endfor -%}
                                        </p>
                                        {% set __ = count.append(1) %}
                                        <p class = "right">
                                        {%- for z in range(count|length, course[0]|length) -%}
                                            {%- if course[0][count|length] == '@' -%}
                                            {%- else -%}
                                                {% set __ = count.append(1) %}
                                                {%- if course[0][count|length-1] == '_' -%}
                                                    {{' '}}
                                                {%- else -%}
                                                    {{course[0][count|length-1]}}
                                                {%- endif -%}
                                            {%- endif -%}
                                        {%- endfor -%}
    
                                    </p>
                                {% set __ = count.append(1) %}
                            <p class = "teacher">
                            {%- for z in range(count|length, course[0]|length) -%}
                                {%- if course[0][count|length] == '@' -%}
                                {%- else -%}
                                    {% set __ = count.append(1) %}
                                    {%- if course[0][count|length-1] == '_' -%}
                                        {{' '}}
                                    {%- else -%}
                                        {{course[0][count|length-1]}}
                                    {%- endif -%}
                                {%- endif -%}
                            {%- endfor -%}  
                            </p>
                            <!-- <p class="left">{{course[0]}}</p>
                            <p class="right">{{course[1]}}</p>
                            <p class="teacher">{{course[2]}}</p> -->
                           {%- endif -%}
                          {%- endfor -%}    
                        </td>
                    {% endif %}
                {% endfor %}
    
            </tr>
    <!-- Tuesday -->
            <tr>
                <td class="center">
                    <b>Tuesday</b>
                </td>
                {% for course in tuesday %}
                    {% if course[1] != 0 %}
                        <td colspan={{course[1]}}>
                            {% set count = [] %}
                            {%- for y in range(0, 5) -%}
                                {%- if count|length < course[0]|length -%}
                                    <p class="left">
                                
                                        {%- for z in range(count|length, course[0]|length) -%}
                                            {%- if course[0][count|length] == '@' -%}
                                            {%- else -%}
                                                {% set __ = count.append(1) %}
                                                {%- if course[0][count|length-1] == '_' -%}
                                                    {{' '}}
                                                {%- else -%}
                                                    {{course[0][count|length-1]}}
                                                {%- endif -%}
                                            {%- endif -%}
                                        {%- endfor -%}
                                        </p>
                                        {% set __ = count.append(1) %}
                                        <p class = "right">
                                        {%- for z in range(count|length, course[0]|length) -%}
                                            {%- if course[0][count|length] == '@' -%}
                                            {%- else -%}
                                                {% set __ = count.append(1) %}
                                                {%- if course[0][count|length-1] == '_' -%}
                                                    {{' '}}
                                                {%- else -%}
                                                    {{course[0][count|length-1]}}
                                                {%- endif -%}
                                            {%- endif -%}
                                        {%- endfor -%}
    
                                    </p>
                                {% set __ = count.append(1) %}
                            <p class = "teacher">
                            {%- for z in range(count|length, course[0]|length) -%}
                                {%- if course[0][count|length] == '@' -%}
                                {%- else -%}
                                    {% set __ = count.append(1) %}
                                    {%- if course[0][count|length-1] == '_' -%}
                                        {{' '}}
                                    {%- else -%}
                                        {{course[0][count|length-1]}}
                                    {%- endif -%}
                                {%- endif -%}
                            {%- endfor -%}  
                            </p>
                            <!-- <p class="left">{{course[0]}}</p>
                            <p class="right">{{course[1]}}</p>
                            <p class="teacher">{{course[2]}}</p> -->
                           {%- endif -%}
                          {%- endfor -%}    
                        </td>
                    {% endif %}
                {% endfor %}
            </tr>
    <!-- Wednesday -->
            <tr>
                <td class="center">
                    <b>Wednesday</b>
                </td>
                {% for course in wednesday %}
                    {% if course[1] != 0 %}
                        <td colspan={{course[1]}}>
                            {% set count = [] %}
                            {%- for y in range(0, 5) -%}
                                {%- if count|length < course[0]|length -%}
                                    <p class="left">
                                
                                        {%- for z in range(count|length, course[0]|length) -%}
                                            {%- if course[0][count|length] == '@' -%}
                                            {%- else -%}
                                                {% set __ = count.append(1) %}
                                                {%- if course[0][count|length-1] == '_' -%}
                                                    {{' '}}
                                                {%- else -%}
                                                    {{course[0][count|length-1]}}
                                                {%- endif -%}
                                            {%- endif -%}
                                        {%- endfor -%}
                                        </p>
                                        {% set __ = count.append(1) %}
                                        <p class = "right">
                                        {%- for z in range(count|length, course[0]|length) -%}
                                            {%- if course[0][count|length] == '@' -%}
                                            {%- else -%}
                                                {% set __ = count.append(1) %}
                                                {%- if course[0][count|length-1] == '_' -%}
                                                    {{' '}}
                                                {%- else -%}
                                                    {{course[0][count|length-1]}}
                                                {%- endif -%}
                                            {%- endif -%}
                                        {%- endfor -%}
    
                                    </p>
                                {% set __ = count.append(1) %}
                            <p class = "teacher">
                            {%- for z in range(count|length, course[0]|length) -%}
                                {%- if course[0][count|length] == '@' -%}
                                {%- else -%}
                                    {% set __ = count.append(1) %}
                                    {%- if course[0][count|length-1] == '_' -%}
                                        {{' '}}
                                    {%- else -%}
                                        {{course[0][count|length-1]}}
                                    {%- endif -%}
                                {%- endif -%}
                            {%- endfor -%}  
                            </p>
                            <!-- <p class="left">{{course[0]}}</p>
                            <p class="right">{{course[1]}}</p>
                            <p class="teacher">{{course[2]}}</p> -->
                           {%- endif -%}
                          {%- endfor -%}    
                        </td>
                    {% endif %}
                {% endfor %}
            </tr>
    <!-- Thursday -->
            <tr>
                <td class="center">
                    <b>Thursday</b>
                </td>
                {% for course in thursday %}
                    {% if course[1] != 0 %}
                        <td colspan={{course[1]}}>
                            {% set count = [] %}
                            {%- for y in range(0, 5) -%}
                                {%- if count|length < course[0]|length -%}
                                    <p class="left">
                                
                                        {%- for z in range(count|length, course[0]|length) -%}
                                            {%- if course[0][count|length] == '@' -%}
                                            {%- else -%}
                                                {% set __ = count.append(1) %}
                                                {%- if course[0][count|length-1] == '_' -%}
                                                    {{' '}}
                                                {%- else -%}
                                                    {{course[0][count|length-1]}}
                                                {%- endif -%}
                                            {%- endif -%}
                                        {%- endfor -%}
                                        </p>
                                        {% set __ = count.append(1) %}
                                        <p class = "right">
                                        {%- for z in range(count|length, course[0]|length) -%}
                                            {%- if course[0][count|length] == '@' -%}
                                            {%- else -%}
                                                {% set __ = count.append(1) %}
                                                {%- if course[0][count|length-1] == '_' -%}
                                                    {{' '}}
                                                {%- else -%}
                                                    {{course[0][count|length-1]}}
                                                {%- endif -%}
                                            {%- endif -%}
                                        {%- endfor -%}
    
                                    </p>
                                {% set __ = count.append(1) %}
                            <p class = "teacher">
                            {%- for z in range(count|length, course[0]|length) -%}
                                {%- if course[0][count|length] == '@' -%}
                                {%- else -%}
                                    {% set __ = count.append(1) %}
                                    {%- if course[0][count|length-1] == '_' -%}
                                        {{' '}}
                                    {%- else -%}
                                        {{course[0][count|length-1]}}
                                    {%- endif -%}
                                {%- endif -%}
                            {%- endfor -%}  
                            </p>
                            <!-- <p class="left">{{course[0]}}</p>
                            <p class="right">{{course[1]}}</p>
                            <p class="teacher">{{course[2]}}</p> -->
                           {%- endif -%}
                          {%- endfor -%}    
                        </td>
                    {% endif %}
                {% endfor %}
    
            </tr>
    <!-- Friday -->
            <tr>
                <td class="center">
                    <b>Friday</b>
                </td>
                {% for course in friday %}
                    {% if course[1] != 0 %}
                        <td colspan={{course[1]}}>
                            {% set count = [] %}
                            {%- for y in range(0, 5) -%}
                                {%- if count|length < course[0]|length -%}
                                    <p class="left">
                                
                                        {%- for z in range(count|length, course[0]|length) -%}
                                            {%- if course[0][count|length] == '@' -%}
                                            {%- else -%}
                                                {% set __ = count.append(1) %}
                                                {%- if course[0][count|length-1] == '_' -%}
                                                    {{' '}}
                                                {%- else -%}
                                                    {{course[0][count|length-1]}}
                                                {%- endif -%}
                                            {%- endif -%}
                                        {%- endfor -%}
                                        </p>
                                        {% set __ = count.append(1) %}
                                        <p class = "right">
                                        {%- for z in range(count|length, course[0]|length) -%}
                                            {%- if course[0][count|length] == '@' -%}
                                            {%- else -%}
                                                {% set __ = count.append(1) %}
                                                {%- if course[0][count|length-1] == '_' -%}
                                                    {{' '}}
                                                {%- else -%}
                                                    {{course[0][count|length-1]}}
                                                {%- endif -%}
                                            {%- endif -%}
                                        {%- endfor -%}
    
                                    </p>
                                {% set __ = count.append(1) %}
                            <p class = "teacher">
                            {%- for z in range(count|length, course[0]|length) -%}
                                {%- if course[0][count|length] == '@' -%}
                                {%- else -%}
                                    {% set __ = count.append(1) %}
                                    {%- if course[0][count|length-1] == '_' -%}
                                        {{' '}}
                                    {%- else -%}
                                        {{course[0][count|length-1]}}
                                    {%- endif -%}
                                {%- endif -%}
                            {%- endfor -%}  
                            </p>
                            <!-- <p class="left">{{course[0]}}</p>
                            <p class="right">{{course[1]}}</p>
                            <p class="teacher">{{course[2]}}</p> -->
                           {%- endif -%}
                          {%- endfor -%}    
                        </td>
                    {% endif %}
                {% endfor %}
    
            </tr>
    
        </table>
    </body>
    
    </html>
    

    This produces the following result,

    enter image description here