Module polysphere_app.views

Expand source code
import os
import shutil
import time
from io import BytesIO
from PIL import Image
from django.db.backends import mysql
import mysql.connector
from django.http import JsonResponse
from django.shortcuts import render, redirect
from django.views.decorators.http import require_http_methods
from .kanoodle import Kanoodle
from .models import *
from .puzzle_pieces import PuzzlePieces
import re

# Sets the grid height and width
grid_width = 11
grid_height = 5

# Set global start_time
start_time = time.time()
end_time = 0


def landing(request):
    """
    Renders the landing page and handles the form submission.

    If the request method is POST, it retrieves the data from the landing form,
    stores it in the session, and redirects to the 'levels' view.
    If the request method is GET, it renders the landing.html template.

    Args:
        request (HttpRequest): The HTTP request object.

    Returns:
        HttpResponse: The HTTP response object.
    """
    if request.method == 'POST':
        data_from_landing = request.POST.get('data_from_landing', '')
        request.session['data_from_landing'] = data_from_landing
        return redirect('polysphere:levels')
    else:
        return render(request, 'polysphere_app/landing.html')


def levels(request):
    """
    Renders the 'levels.html' template and passes the 'data_from_landing' variable from the session to the template.

    Args:
        request (HttpRequest): The HTTP request object.

    Returns:
        HttpResponse: The rendered response.
    """
    data_from_landing = request.session.get('data_from_landing', '')
    return render(request, 'polysphere_app/levels.html', {'data_from_landing': data_from_landing})


@require_http_methods(["POST"])
def submit_kanoodle_problem(request):
    """
    Submits a Kanoodle problem to the server and returns the solution.

    Args:
        request: The HTTP request object.

    Returns:
        A JSON response containing the problem ID, solution, and time taken in milliseconds.
    """
    # Assume data is now coming from a predefined function or file
    piece_descriptions = get_pieces_data()
    grid_width = 3
    grid_height = 3

    # Create a KanoodleProblem instance and store in the database
    problem = KanoodleProblem.objects.create(
        piece_descriptions=json.dumps(piece_descriptions),
        grid_width=grid_width,
        grid_height=grid_height
    )

    # Solve the problem using Kanoodle logic
    start_time = time.time()
    solutions_str = Kanoodle.findAllSolutions(piece_descriptions, grid_width, grid_height)
    end_time = time.time()

    # Create a KanoodleSolution instance and store in the database
    KanoodleSolution.objects.create(problem=problem, solution_data=solutions_str)

    # Return the response
    return JsonResponse({
        'problem_id': problem.id,
        'solution': solutions_str,
        'time_taken_ms': (end_time - start_time) * 1000
    }, status=201)


@require_http_methods(["GET"])
def get_kanoodle_solution(request, problem_id):
    """
    Retrieve the Kanoodle problem and its solutions.

    Args:
        request (HttpRequest): The HTTP request object.
        problem_id (int): The ID of the Kanoodle problem.

    Returns:
        JsonResponse: The JSON response containing the problem ID and its solutions.

    Raises:
        KanoodleProblem.DoesNotExist: If the Kanoodle problem with the given ID does not exist.
    """
    try:
        # Retrieve the problem and its solutions
        problem = KanoodleProblem.objects.get(id=problem_id)
        solutions = problem.solutions.all()

        # Format the solutions for the response
        solutions_data = [sol.get_solution_data() for sol in solutions]
        return JsonResponse({
            'problem_id': problem_id,
            'solutions': solutions_data
        })
    except KanoodleProblem.DoesNotExist:
        return JsonResponse({'error': 'Problem not found.'}, status=404)


def get_pieces_data():
    """
    Retrieves the data of puzzle pieces.

    Returns:
        dict: A dictionary containing the data of puzzle pieces, including shape, grid, image path, and rotation.
    """
    puzzle_pieces_data = PuzzlePieces.pieces_data.copy()
    for piece in PuzzlePiece.objects.all():
        puzzle_pieces_data[piece.shape] = {
            'shape': piece.shape,
            'grid': piece.get_grid(),
            'image_path': piece.image_path,
            'rotation': piece.rotation
        }

    return puzzle_pieces_data


def generate_solution_image(solution_matrix, pieces_data, block_size=50):
    """
    Generate a solution image based on the solution matrix and pieces data.

    Args:
        solution_matrix (list): A 2D matrix representing the solution.
        pieces_data (dict): A dictionary mapping piece symbols to their corresponding image data.
        block_size (int, optional): The size of each block in pixels. Defaults to 50.

    Returns:
        BytesIO: An in-memory file containing the generated solution image.
    """
    solution_width = len(solution_matrix[0]) * block_size
    solution_height = len(solution_matrix) * block_size
    solution_image = Image.new('RGB', (solution_width, solution_height),
                               (128, 128, 128))  # Create grey background image

    for row_idx, row in enumerate(solution_matrix):
        for col_idx, piece_symbol in enumerate(row):
            if piece_symbol in pieces_data:  # Make sure the piece symbol exists in the data
                piece_symbol = pieces_data[piece_symbol]
                # Ensure the position is calculated correctly: (x, y) format
                position = (col_idx * block_size, row_idx * block_size)
                # print(f"Placeing {piece_symbol} at {position}, Image Size: {solution_image.size}")
                display_piece(piece_symbol, position, block_size, solution_image)

    # Instead of showing the image, save it to an in-memory file
    image_io = BytesIO()
    solution_image.save(image_io, 'WebP')
    image_io.seek(0)

    return image_io


# Django view that returns an image response
def get_list_of_solution_matrices():
    """
    Retrieves a list of solution matrices for the Kanoodle puzzle.

    Returns:
        list: A list of solution matrices.
    """
    kanoodle_solver = Kanoodle()

    # Directly use the pieces_data to get the list of grids
    list_of_grids = [value['grid'] for key, value in PuzzlePieces.pieces_data.items()]
    grid_strings = []
    for grid in list_of_grids:
        grid_strings.append("\n".join(grid))

    # Call the findAllSolutions method with the list of grids and the puzzle dimensions
    solutions = kanoodle_solver.findAllSolutions(grid_strings, grid_width, grid_height)

    global end_time
    end_time = time.time()
    solutions = solutions.split("\n\n")
    return solutions


def generate_solution_gallery(request):
    """
    Generates a solution gallery by looping through each solution,
    generating an image for it, and adding the path to the file.

    Args:
        request (HttpRequest): The HTTP request object.

    Returns:
        HttpResponse: The HTTP response object.
    """
    # solutions = get_list_of_solution_matrices()
    # solutions = [solution.split("\n") for solution in solutions]
    # time_taken = end_time - start_time
    # print(f"{len(solutions)} solutions found in {time_taken}")
    # pieces_data = get_pieces_data()

    # Create a temporary directory within MEDIA_ROOT
    # media_dir = os.path.join(settings.MEDIA_ROOT)
    # if not os.path.exists(media_dir):
    #     os.makedirs(media_dir)
    #
    # # Temporary storage for images
    # fs = FileSystemStorage(location=media_dir)

    # Clears the media folder of existing files before generating the new ones
    # clear_solutions(media_dir)

    # List to hold the paths of the generated images
    image_paths = []

    # Loop through each solution, generating an image for it and adding the path to the file
    for idx in range(0, 80444):
        # image_io = generate_solution_image(solution_matrix, pieces_data)
        # filename = f'media/solution_{idx}.webp'
        # image_path = fs.url(filename)
        image_path = f'media/solution_{idx}.webp'
        image_paths.append(image_path)

        data_from_landing = request.session.get('data_from_landing', '')
        return render(request, 'polysphere_app/kanoodle-solver.html', {'data_from_landing': data_from_landing})

    # return render(request, 'polysphere_app/kanoodle-solver.html')
    # return render(request, 'polysphere_app/dashboard.html', {'image_paths': image_paths})


def clear_solutions(directory):
    """
    Clears all the solution files and directories in the given directory.

    Args:
        directory (str): The path to the directory containing the solution files.

    Returns:
        None
    """
    for filename in os.listdir(directory):
        if filename.startswith("solution"):
            file_path = os.path.join(directory, filename)
            try:
                if os.path.isfile(file_path) or os.path.islink(file_path):
                    os.unlink(file_path)
                elif os.path.isdir(file_path):
                    shutil.rmtree(file_path)
            except Exception as e:
                print('Failed to delete %s. Reason: %s' % (file_path, e))


def display_piece(piece_data, position, block_size, solution_image):
    """
    Display a piece on the solution image at the specified position.

    Args:
        piece_data (dict): The data of the piece, including its image path and rotation.
        position (tuple): The position where the piece should be placed on the solution image.
        block_size (int): The size of each block in the solution image.
        solution_image (PIL.Image.Image): The solution image.

    Returns:
        None
    """
    image_path = piece_data['image_path']
    # Open the image file corresponding to the piece
    with Image.open(image_path) as piece_image:
        # Apply rotations to images
        if piece_data['rotation'] != 0:
            piece_image = piece_image.rotate(piece_data['rotation'], expand=True)

        # Resize the image if necessary
        piece_image = piece_image.resize((block_size, block_size))

        # Check if the piece fits within the solution image
        if position[0] + piece_image.width <= solution_image.width and position[
            1] + piece_image.height <= solution_image.height:
            # Paste the piece image onto the solution image at the calculated position
            solution_image.paste(piece_image, position, piece_image)


def generate_regex_pattern(partial_solution):
    """
    Generate a regular expression pattern based on a partial solution.

    Args:
        partial_solution (list): A 2D list representing a partial solution.

    Returns:
        str: The regular expression pattern generated from the partial solution.
    """
    pattern = ""
    for row in partial_solution:
        row_pattern = ""
        for cell in row:
            if cell == ' ':
                row_pattern += '.'  # Any character
            else:
                row_pattern += cell  # Specific character
        pattern += row_pattern + "\n"
    return pattern.rstrip("\n")


def find_partial_solutions(request):
    """
    Finds partial solutions based on the given request.

    Args:
        request (HttpRequest): The HTTP request object.

    Returns:
        JsonResponse: The JSON response containing the partial solutions or an error message.
    """
    # If a request sent from the webpage
    if request.method == 'POST':
        # Assigns a variable to the partial configuration and generates a regex pattern from it
        configuration = json.loads(request.body)
        regex_pattern = generate_regex_pattern(configuration)
        # Opens the solutions.txt file
        with open(
                r'polysphere_app/solutions/all_solutions.txt',
                'r') as file:
            solutions_text = file.read()
        # Split the text into individual solutions
        raw_solutions = solutions_text.strip().split('\n\n')
        # Format each solution with newline characters
        formatted_solutions = ['\n'.join(solution.split('\n')) for solution in raw_solutions]

        # Matches pattern to solutions
        matching_solutions = []
        for solution in formatted_solutions:
            if re.match(regex_pattern, solution, re.DOTALL):
                matching_solutions.append(solution)
        # Gets the matching solutions' image_paths from database
        return get_partial_solutions(matching_solutions)

    else:
        return JsonResponse({'error:': 'Invalid request'}, status=400)


def get_partial_solutions(matching_solutions):
    """
    Retrieves partial solutions from the database based on the given matching solutions.

    Args:
        matching_solutions (list): A list of matching solutions.

    Returns:
        dict: A JSON response containing the image paths of the matching patterns.
    """
    # Establish database connection
    conn = mysql.connector.connect(host='144.21.52.245', port='6969', user='asegroup6', passwd='ASEgroup6mysql@2023##',
                                   db='group_6_project')
    # conn = mysql.connector.connect(host='localhost', port='3306', user='root', passwd='',
    #                                db='group_6_project')
    cursor = conn.cursor()
    print(len(matching_solutions))
    # Gets matching patterns from the database
    img_paths = []
    for match in matching_solutions:
        print("Match found:", match)
        query = "SELECT img_path FROM kanoodle_solver WHERE mapping LIKE %s"
        match_with_wildcard = f"%{match}%"
        cursor.execute(query, (match_with_wildcard,))
        img_paths.extend([row[0] for row in cursor.fetchall()])
    cursor.close()
    conn.close()
    # Returns a Json response
    return JsonResponse({'img_paths': img_paths})

Functions

def clear_solutions(directory)

Clears all the solution files and directories in the given directory.

Args

directory : str
The path to the directory containing the solution files.

Returns

None

Expand source code
def clear_solutions(directory):
    """
    Clears all the solution files and directories in the given directory.

    Args:
        directory (str): The path to the directory containing the solution files.

    Returns:
        None
    """
    for filename in os.listdir(directory):
        if filename.startswith("solution"):
            file_path = os.path.join(directory, filename)
            try:
                if os.path.isfile(file_path) or os.path.islink(file_path):
                    os.unlink(file_path)
                elif os.path.isdir(file_path):
                    shutil.rmtree(file_path)
            except Exception as e:
                print('Failed to delete %s. Reason: %s' % (file_path, e))
def display_piece(piece_data, position, block_size, solution_image)

Display a piece on the solution image at the specified position.

Args

piece_data : dict
The data of the piece, including its image path and rotation.
position : tuple
The position where the piece should be placed on the solution image.
block_size : int
The size of each block in the solution image.
solution_image : PIL.Image.Image
The solution image.

Returns

None

Expand source code
def display_piece(piece_data, position, block_size, solution_image):
    """
    Display a piece on the solution image at the specified position.

    Args:
        piece_data (dict): The data of the piece, including its image path and rotation.
        position (tuple): The position where the piece should be placed on the solution image.
        block_size (int): The size of each block in the solution image.
        solution_image (PIL.Image.Image): The solution image.

    Returns:
        None
    """
    image_path = piece_data['image_path']
    # Open the image file corresponding to the piece
    with Image.open(image_path) as piece_image:
        # Apply rotations to images
        if piece_data['rotation'] != 0:
            piece_image = piece_image.rotate(piece_data['rotation'], expand=True)

        # Resize the image if necessary
        piece_image = piece_image.resize((block_size, block_size))

        # Check if the piece fits within the solution image
        if position[0] + piece_image.width <= solution_image.width and position[
            1] + piece_image.height <= solution_image.height:
            # Paste the piece image onto the solution image at the calculated position
            solution_image.paste(piece_image, position, piece_image)
def find_partial_solutions(request)

Finds partial solutions based on the given request.

Args

request : HttpRequest
The HTTP request object.

Returns

JsonResponse
The JSON response containing the partial solutions or an error message.
Expand source code
def find_partial_solutions(request):
    """
    Finds partial solutions based on the given request.

    Args:
        request (HttpRequest): The HTTP request object.

    Returns:
        JsonResponse: The JSON response containing the partial solutions or an error message.
    """
    # If a request sent from the webpage
    if request.method == 'POST':
        # Assigns a variable to the partial configuration and generates a regex pattern from it
        configuration = json.loads(request.body)
        regex_pattern = generate_regex_pattern(configuration)
        # Opens the solutions.txt file
        with open(
                r'polysphere_app/solutions/all_solutions.txt',
                'r') as file:
            solutions_text = file.read()
        # Split the text into individual solutions
        raw_solutions = solutions_text.strip().split('\n\n')
        # Format each solution with newline characters
        formatted_solutions = ['\n'.join(solution.split('\n')) for solution in raw_solutions]

        # Matches pattern to solutions
        matching_solutions = []
        for solution in formatted_solutions:
            if re.match(regex_pattern, solution, re.DOTALL):
                matching_solutions.append(solution)
        # Gets the matching solutions' image_paths from database
        return get_partial_solutions(matching_solutions)

    else:
        return JsonResponse({'error:': 'Invalid request'}, status=400)
def generate_regex_pattern(partial_solution)

Generate a regular expression pattern based on a partial solution.

Args

partial_solution : list
A 2D list representing a partial solution.

Returns

str
The regular expression pattern generated from the partial solution.
Expand source code
def generate_regex_pattern(partial_solution):
    """
    Generate a regular expression pattern based on a partial solution.

    Args:
        partial_solution (list): A 2D list representing a partial solution.

    Returns:
        str: The regular expression pattern generated from the partial solution.
    """
    pattern = ""
    for row in partial_solution:
        row_pattern = ""
        for cell in row:
            if cell == ' ':
                row_pattern += '.'  # Any character
            else:
                row_pattern += cell  # Specific character
        pattern += row_pattern + "\n"
    return pattern.rstrip("\n")

Generates a solution gallery by looping through each solution, generating an image for it, and adding the path to the file.

Args

request : HttpRequest
The HTTP request object.

Returns

HttpResponse
The HTTP response object.
Expand source code
def generate_solution_gallery(request):
    """
    Generates a solution gallery by looping through each solution,
    generating an image for it, and adding the path to the file.

    Args:
        request (HttpRequest): The HTTP request object.

    Returns:
        HttpResponse: The HTTP response object.
    """
    # solutions = get_list_of_solution_matrices()
    # solutions = [solution.split("\n") for solution in solutions]
    # time_taken = end_time - start_time
    # print(f"{len(solutions)} solutions found in {time_taken}")
    # pieces_data = get_pieces_data()

    # Create a temporary directory within MEDIA_ROOT
    # media_dir = os.path.join(settings.MEDIA_ROOT)
    # if not os.path.exists(media_dir):
    #     os.makedirs(media_dir)
    #
    # # Temporary storage for images
    # fs = FileSystemStorage(location=media_dir)

    # Clears the media folder of existing files before generating the new ones
    # clear_solutions(media_dir)

    # List to hold the paths of the generated images
    image_paths = []

    # Loop through each solution, generating an image for it and adding the path to the file
    for idx in range(0, 80444):
        # image_io = generate_solution_image(solution_matrix, pieces_data)
        # filename = f'media/solution_{idx}.webp'
        # image_path = fs.url(filename)
        image_path = f'media/solution_{idx}.webp'
        image_paths.append(image_path)

        data_from_landing = request.session.get('data_from_landing', '')
        return render(request, 'polysphere_app/kanoodle-solver.html', {'data_from_landing': data_from_landing})

    # return render(request, 'polysphere_app/kanoodle-solver.html')
    # return render(request, 'polysphere_app/dashboard.html', {'image_paths': image_paths})
def generate_solution_image(solution_matrix, pieces_data, block_size=50)

Generate a solution image based on the solution matrix and pieces data.

Args

solution_matrix : list
A 2D matrix representing the solution.
pieces_data : dict
A dictionary mapping piece symbols to their corresponding image data.
block_size : int, optional
The size of each block in pixels. Defaults to 50.

Returns

BytesIO
An in-memory file containing the generated solution image.
Expand source code
def generate_solution_image(solution_matrix, pieces_data, block_size=50):
    """
    Generate a solution image based on the solution matrix and pieces data.

    Args:
        solution_matrix (list): A 2D matrix representing the solution.
        pieces_data (dict): A dictionary mapping piece symbols to their corresponding image data.
        block_size (int, optional): The size of each block in pixels. Defaults to 50.

    Returns:
        BytesIO: An in-memory file containing the generated solution image.
    """
    solution_width = len(solution_matrix[0]) * block_size
    solution_height = len(solution_matrix) * block_size
    solution_image = Image.new('RGB', (solution_width, solution_height),
                               (128, 128, 128))  # Create grey background image

    for row_idx, row in enumerate(solution_matrix):
        for col_idx, piece_symbol in enumerate(row):
            if piece_symbol in pieces_data:  # Make sure the piece symbol exists in the data
                piece_symbol = pieces_data[piece_symbol]
                # Ensure the position is calculated correctly: (x, y) format
                position = (col_idx * block_size, row_idx * block_size)
                # print(f"Placeing {piece_symbol} at {position}, Image Size: {solution_image.size}")
                display_piece(piece_symbol, position, block_size, solution_image)

    # Instead of showing the image, save it to an in-memory file
    image_io = BytesIO()
    solution_image.save(image_io, 'WebP')
    image_io.seek(0)

    return image_io
def get_kanoodle_solution(request, problem_id)

Retrieve the Kanoodle problem and its solutions.

Args

request : HttpRequest
The HTTP request object.
problem_id : int
The ID of the Kanoodle problem.

Returns

JsonResponse
The JSON response containing the problem ID and its solutions.

Raises

KanoodleProblem.DoesNotExist
If the Kanoodle problem with the given ID does not exist.
Expand source code
@require_http_methods(["GET"])
def get_kanoodle_solution(request, problem_id):
    """
    Retrieve the Kanoodle problem and its solutions.

    Args:
        request (HttpRequest): The HTTP request object.
        problem_id (int): The ID of the Kanoodle problem.

    Returns:
        JsonResponse: The JSON response containing the problem ID and its solutions.

    Raises:
        KanoodleProblem.DoesNotExist: If the Kanoodle problem with the given ID does not exist.
    """
    try:
        # Retrieve the problem and its solutions
        problem = KanoodleProblem.objects.get(id=problem_id)
        solutions = problem.solutions.all()

        # Format the solutions for the response
        solutions_data = [sol.get_solution_data() for sol in solutions]
        return JsonResponse({
            'problem_id': problem_id,
            'solutions': solutions_data
        })
    except KanoodleProblem.DoesNotExist:
        return JsonResponse({'error': 'Problem not found.'}, status=404)
def get_list_of_solution_matrices()

Retrieves a list of solution matrices for the Kanoodle puzzle.

Returns

list
A list of solution matrices.
Expand source code
def get_list_of_solution_matrices():
    """
    Retrieves a list of solution matrices for the Kanoodle puzzle.

    Returns:
        list: A list of solution matrices.
    """
    kanoodle_solver = Kanoodle()

    # Directly use the pieces_data to get the list of grids
    list_of_grids = [value['grid'] for key, value in PuzzlePieces.pieces_data.items()]
    grid_strings = []
    for grid in list_of_grids:
        grid_strings.append("\n".join(grid))

    # Call the findAllSolutions method with the list of grids and the puzzle dimensions
    solutions = kanoodle_solver.findAllSolutions(grid_strings, grid_width, grid_height)

    global end_time
    end_time = time.time()
    solutions = solutions.split("\n\n")
    return solutions
def get_partial_solutions(matching_solutions)

Retrieves partial solutions from the database based on the given matching solutions.

Args

matching_solutions : list
A list of matching solutions.

Returns

dict
A JSON response containing the image paths of the matching patterns.
Expand source code
def get_partial_solutions(matching_solutions):
    """
    Retrieves partial solutions from the database based on the given matching solutions.

    Args:
        matching_solutions (list): A list of matching solutions.

    Returns:
        dict: A JSON response containing the image paths of the matching patterns.
    """
    # Establish database connection
    conn = mysql.connector.connect(host='144.21.52.245', port='6969', user='asegroup6', passwd='ASEgroup6mysql@2023##',
                                   db='group_6_project')
    # conn = mysql.connector.connect(host='localhost', port='3306', user='root', passwd='',
    #                                db='group_6_project')
    cursor = conn.cursor()
    print(len(matching_solutions))
    # Gets matching patterns from the database
    img_paths = []
    for match in matching_solutions:
        print("Match found:", match)
        query = "SELECT img_path FROM kanoodle_solver WHERE mapping LIKE %s"
        match_with_wildcard = f"%{match}%"
        cursor.execute(query, (match_with_wildcard,))
        img_paths.extend([row[0] for row in cursor.fetchall()])
    cursor.close()
    conn.close()
    # Returns a Json response
    return JsonResponse({'img_paths': img_paths})
def get_pieces_data()

Retrieves the data of puzzle pieces.

Returns

dict
A dictionary containing the data of puzzle pieces, including shape, grid, image path, and rotation.
Expand source code
def get_pieces_data():
    """
    Retrieves the data of puzzle pieces.

    Returns:
        dict: A dictionary containing the data of puzzle pieces, including shape, grid, image path, and rotation.
    """
    puzzle_pieces_data = PuzzlePieces.pieces_data.copy()
    for piece in PuzzlePiece.objects.all():
        puzzle_pieces_data[piece.shape] = {
            'shape': piece.shape,
            'grid': piece.get_grid(),
            'image_path': piece.image_path,
            'rotation': piece.rotation
        }

    return puzzle_pieces_data
def landing(request)

Renders the landing page and handles the form submission.

If the request method is POST, it retrieves the data from the landing form, stores it in the session, and redirects to the 'levels' view. If the request method is GET, it renders the landing.html template.

Args

request : HttpRequest
The HTTP request object.

Returns

HttpResponse
The HTTP response object.
Expand source code
def landing(request):
    """
    Renders the landing page and handles the form submission.

    If the request method is POST, it retrieves the data from the landing form,
    stores it in the session, and redirects to the 'levels' view.
    If the request method is GET, it renders the landing.html template.

    Args:
        request (HttpRequest): The HTTP request object.

    Returns:
        HttpResponse: The HTTP response object.
    """
    if request.method == 'POST':
        data_from_landing = request.POST.get('data_from_landing', '')
        request.session['data_from_landing'] = data_from_landing
        return redirect('polysphere:levels')
    else:
        return render(request, 'polysphere_app/landing.html')
def levels(request)

Renders the 'levels.html' template and passes the 'data_from_landing' variable from the session to the template.

Args

request : HttpRequest
The HTTP request object.

Returns

HttpResponse
The rendered response.
Expand source code
def levels(request):
    """
    Renders the 'levels.html' template and passes the 'data_from_landing' variable from the session to the template.

    Args:
        request (HttpRequest): The HTTP request object.

    Returns:
        HttpResponse: The rendered response.
    """
    data_from_landing = request.session.get('data_from_landing', '')
    return render(request, 'polysphere_app/levels.html', {'data_from_landing': data_from_landing})
def submit_kanoodle_problem(request)

Submits a Kanoodle problem to the server and returns the solution.

Args

request
The HTTP request object.

Returns

A JSON response containing the problem ID, solution, and time taken in milliseconds.

Expand source code
@require_http_methods(["POST"])
def submit_kanoodle_problem(request):
    """
    Submits a Kanoodle problem to the server and returns the solution.

    Args:
        request: The HTTP request object.

    Returns:
        A JSON response containing the problem ID, solution, and time taken in milliseconds.
    """
    # Assume data is now coming from a predefined function or file
    piece_descriptions = get_pieces_data()
    grid_width = 3
    grid_height = 3

    # Create a KanoodleProblem instance and store in the database
    problem = KanoodleProblem.objects.create(
        piece_descriptions=json.dumps(piece_descriptions),
        grid_width=grid_width,
        grid_height=grid_height
    )

    # Solve the problem using Kanoodle logic
    start_time = time.time()
    solutions_str = Kanoodle.findAllSolutions(piece_descriptions, grid_width, grid_height)
    end_time = time.time()

    # Create a KanoodleSolution instance and store in the database
    KanoodleSolution.objects.create(problem=problem, solution_data=solutions_str)

    # Return the response
    return JsonResponse({
        'problem_id': problem.id,
        'solution': solutions_str,
        'time_taken_ms': (end_time - start_time) * 1000
    }, status=201)