1. sendMessage Function (Frontend)

Purpose:

Handles user input by allowing users to send messages to the chatroom, dynamically updating the interface, and communicating with the backend.

How it meets PPR Requirements:

User Input Handling: Accepts user input from a text field and processes it.
List Usage: Manages chat messages dynamically as a list in the DOM.
Algorithm Implementation:

  • Sequencing: Sends a message, updates the UI, and calls the backend.
  • Selection: Validates if a message is empty before sending.
  • Iteration: Uses forEach when updating messages.
    Program Output: Visually updates the chat with a new message.

async function sendMessage() {
    const chatBox = document.getElementById('chatBox');
    const messageInput = document.getElementById('messageInput');
    const message = messageInput.value.trim();
    if (message) {
        const tempId = `temp-${Date.now()}`;
        const messageElement = document.createElement('div');
        messageElement.className = 'chat-message';
        messageElement.id = tempId;
        messageElement.innerHTML = `
            <div class="message-content">
                <p><strong>${message}</strong></p>
                <button class="edit-button" onclick="editMessage('${tempId}')">Edit</button>
                <button class="delete-button" onclick="deleteMessage('${tempId}')">Delete</button>
            </div>
        `;
        chatBox.appendChild(messageElement);
        messageInput.value = '';
        chatBox.scrollTop = chatBox.scrollHeight;

        const postData = { message: message, channel_id: selectedChannelId };
        try {
            const response = await fetch(`${pythonURI}/api/chat`, {
                ...fetchOptions,
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify(postData)
            });
            if (!response.ok) throw new Error('Failed to add post: ' + response.statusText);
            const result = await response.json();
            const postId = result.id;
            const tempElement = document.getElementById(tempId);
            tempElement.id = `post-${postId}`;
            tempElement.querySelector('.edit-button').setAttribute('onclick', `editMessage(${postId})`);
            tempElement.querySelector('.delete-button').setAttribute('onclick', `deleteMessage(${postId})`);
        } catch (error) {
            console.error('Error adding post:', error);
            document.getElementById(tempId).remove();
        }
    }
}

2. ChatAPI._CRUD.post (Backend)

Purpose:

Handles message creation by receiving data from the frontend, validating input, and storing it in the database.

How it meets PPR Requirements:

User Input Handling: Processes messages sent by users.
List Usage: Stores chat messages in a database table (Chat).
Student-Developed Procedure:

  • Defined Name & Return Type: post(self) returns a JSON response.
  • Uses Parameters: Extracts message and channel_id from the request.
    Algorithm Implementation:
  • Sequencing: Validates input, creates a new message, and saves it.
  • Selection: Checks if required fields are present.
  • Iteration: Not directly needed for creating a single message, but used when retrieving messages.
    Program Output: Returns a JSON response with the new chat message.
@token_required()
def post(self):
    """
    Create a new chat message.
    """
    current_user = g.current_user
    data = request.get_json()

    if not data or 'message' not in data or 'channel_id' not in data:
        return {'message': 'Message and Channel ID are required'}, 400

    chat = Chat(message=data['message'], user_id=current_user.id, channel_id=data['channel_id'])
    chat.create()
    return jsonify(chat.read())

3. fetchData(channelId) (Frontend)

Purpose:

Fetches and displays chat messages for a selected channel.

How it meets PPR Requirements:

User Input Handling: Fetches messages based on user-selected channels.
List Usage: Uses an array of chat messages retrieved from the backend.
Algorithm Implementation:

  • Sequencing: Retrieves messages and updates the UI.
  • Selection: Checks if the response is valid before displaying data.
  • Iteration: Loops through messages to display them.
    Program Output: Visually updates the chat window.
async function fetchData(channelId) {
    try {
        const userResponse = await fetch(`${pythonURI}/api/user`, fetchOptions);
        if (!userResponse.ok) throw new Error('Failed to fetch user data');
        const userData = await userResponse.json();
        const currentUserId = userData.id;

        const response = await fetch(`${pythonURI}/api/chat?id=${channelId}`, {
            ...fetchOptions,
            method: 'GET',
            headers: { 'Content-Type': 'application/json' }
        });
        if (!response.ok) throw new Error('Failed to fetch chats: ' + response.statusText);
        const chatData = await response.json();

        const chatBox = document.getElementById('chatBox');
        chatBox.innerHTML = '';
        chatData.forEach(chatItem => {
            const messageElement = document.createElement('div');
            messageElement.className = 'chat-message';
            messageElement.id = `chat-${chatItem.id}`;
            let buttonsHTML = "";
            if (chatItem.user_id === currentUserId || currentUserId === 1) {
                buttonsHTML = `
                    <button class="edit-button" onclick="editMessage(${chatItem.id})">Edit</button>
                    <button class="delete-button" onclick="deleteMessage(${chatItem.id})">Delete</button>
                `;
            }
            messageElement.innerHTML = `
                <div class="message-content">
                    <p><strong>${chatItem.message}</strong></p>
                    ${buttonsHTML}
                </div>
            `;
            chatBox.appendChild(messageElement);
        });
        chatBox.scrollTop = chatBox.scrollHeight;
    } catch (error) {
        console.error('Error fetching data:', error);
    }
}

4. Chat.update (Backend)

Purpose:

Allows users to edit existing messages.

How it meets PPR Requirements:

User Input Handling: Updates messages with new content provided by the user.
List Usage: Modifies existing chat messages in the database.
Student-Developed Procedure:

  • Defined Name & Return Type: update(self, data) returns the updated message.
  • Uses Parameters: Accepts data, which contains new message content.
    Algorithm Implementation:
  • Sequencing: Updates the message and commits changes.
  • Selection: Checks if message exists before updating.
  • Iteration: Not directly, but used for batch updates in future modifications.
    Program Output: Returns updated message data.
def update(self, data):
    """
    Updates the chat message object with new data.

    Args:
        data (dict): A dictionary containing the new data for the chat message.

    Returns:
        Chat: The updated chat message object, or None on error.
    """
    if 'message' in data:
        self._message = data['message']

    try:
        db.session.commit()
    except IntegrityError as e:
        db.session.rollback()
        logging.warning(f"IntegrityError: Could not update chat with ID '{self.id}' due to {str(e)}.")
        return None
    return self

Overall, these will be the 4 code snippets I submit as my PPR to College Board, so that I can use it while talking about my PPR on the FRQ portion of the exam.