CompSci Blogs

August 2023 to June 2024

View the Project on GitHub sfremy/csablog

17 April 2024

Data Structures Writeup

by

Collections

(Blog Python Model code and SQLite Database.)

From VSCode using SQLite3 Editor, show your unique collection/table in database, display rows and columns in the table of the SQLite database.

From VSCode model, show your unique code that was created to initialize table and create test data.

from __init__ import app, db #Ignore error, file absent
from sqlalchemy.exc import IntegrityError

#Colleges SQLAlchemy model
class College(db.Model):
    __tablename__ = 'colleges'

    # Define the Colleges schema with "vars" from object
    _name = db.Column(db.String(255), unique=False, nullable=True)
    _link = db.Column(db.String(255), nullable=False, primary_key=True)
    _image = db.Column(db.String(255), unique=False, nullable=True)
    
    
#... (setters, read, update, other needed model functionality)

# Builds model test data
def initColleges():
    with app.app_context():
        db.create_all()
        
        #Properties of each college element
        c1 = College(name='Stanford University',link='https://admission.stanford.edu/apply/',img='https://identity.stanford.edu/wp-content/uploads/sites/3/2020/07/block-s-right.png')
        c2 = College(name='Harvard University',link='https://college.harvard.edu/admissions/apply',img='https://1000logos.net/wp-content/uploads/2017/02/Harvard-Logo.png')
        c3 = College(name='MIT',link='https://apply.mitadmissions.org/portal/apply',img='https://upload.wikimedia.org/wikipedia/commons/thumb/0/0c/MIT_logo.svg/2560px-MIT_logo.svg.png')
        c4 = College(name='Georgia Tech',link='https://admission.gatech.edu/apply/',img='https://brand.gatech.edu/sites/default/files/inline-images/GTVertical_RGB.png')
        c5 = College(name='Duke University',link='https://admissions.duke.edu/apply/',img='https://upload.wikimedia.org/wikipedia/commons/thumb/0/04/Duke_Blue_Devils_logo.svg/909px-Duke_Blue_Devils_logo.svg.png')
        c6 = College(name='Yale University',link='https://www.yale.edu/admissions',img='https://upload.wikimedia.org/wikipedia/commons/thumb/6/6e/Yale_University_logo.svg/2560px-Yale_University_logo.svg.png')
        c7 = College(name='Princeton University',link='https://admission.princeton.edu/apply',img='https://upload.wikimedia.org/wikipedia/commons/thumb/d/d0/Princeton_seal.svg/1200px-Princeton_seal.svg.png')
        c8 = College(name='Columbia University',link='https://undergrad.admissions.columbia.edu/apply',img='https://admissions.ucr.edu/sites/default/files/styles/form_preview/public/2020-07/ucr-education-logo-columbia-university.png?itok=-0FD6Ma2')
        c9 = College(name='University of Chicago',link='https://collegeadmissions.uchicago.edu/apply',img='https://upload.wikimedia.org/wikipedia/commons/c/cd/University_of_Chicago_Coat_of_arms.png')
        c10 = College(name='UC Berkeley',link='https://admissions.berkeley.edu/apply-to-berkeley/',img='https://upload.wikimedia.org/wikipedia/commons/thumb/a/a1/Seal_of_University_of_California%2C_Berkeley.svg/1200px-Seal_of_University_of_California%2C_Berkeley.svg.png')
        c11 = College(name='UCLA',link='https://admission.ucla.edu/apply',img='https://upload.wikimedia.org/wikipedia/commons/thumb/d/d1/UCLA_Bruins_primary_logo.svg/1200px-UCLA_Bruins_primary_logo.svg.png')
        #Add new data to this line
        
        colleges = [c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11]

        #Iterate through list of elements to initialize and add to SQLite database
        for college in colleges:
            try:
                college.create()
                
            #Catch errors
            except IntegrityError:
                db.session.remove()
                print(f"Records exist, duplicate email, or error: {college.name}")

Lists & Dictionaries

(Blog Python API code and use of List and Dictionaries.)

In VSCode using Debugger, show a list as extracted from database as Python objects.

Note that college_list is a Python list object which contains data returned from the Users SQLite table.

In VSCode use Debugger and list, show two distinct example examples of dictionaries, show Keys/Values using debugger.

Note here that the body read and the indices of colleges_data are dictionary elements.

APIs and JSON

(Blog Python API code and use of Postman to request and respond with JSON.)

In VSCode, show Python API code definition for request and response using GET, POST, UPDATE methods. Discuss algorithmic condition used to direct request to appropriate Python method based on request method.

from flask import jsonify
from flask_restful import Resource, request
from model.users import User
import ast
import json

class _Edit(Resource):
    # POST method to add new colleges to a user's list
        def post(self):
            # Extract data from the request's JSON body
            body = request.get_json()
            
            # Retrieve the user's ID
            username = body.get('name')
            
            if username is None:
                return {'message': 'Invalid request'}, 400
            
            # Query the database for the user's record using the user ID
            user = User.query.filter_by(_uid=username).first()
            
            if user is None:
                return {'message': "User ID not found"}, 404
            
            # Decode the JSON string of the user's college list into a Python list
            namelist = ast.literal_eval(user.read()['college_list'])
            
            # Query the database for colleges that match the names in the user's list
            matching_colleges = College.query.filter(College._name.in_(namelist)).all()
            
            # Convert the query results to a JSON-serializable format
            colleges_data = [college.read() for college in matching_colleges]
            print(colleges_data)
            json_data = jsonify(colleges_data)
            
            return json_data  # Return the JSON data of the colleges

        # GET method to retrieve a list of all colleges from the database
        def get(self):
            # Query the database for all college records
            all_colleges = College.query.all()
            # Convert each college record to a JSON-serializable format
            colleges_data = [college.read() for college in all_colleges]
            json_data = jsonify(colleges_data)
            
            return json_data  # Return the JSON data of all colleges

        # PUT method to update the college list associated with a user
        def put(self):
            # Extract data from the request's JSON body
            body = request.get_json()
            
            # Retrieve the user's ID
            username = body.get('name')
            
            # Query the database for the user's record
            user = User.query.filter_by(_uid=username).first()
            
            if user is None:
                return {'message': "User ID not found"}, 404
            
            # Decode the JSON string of the user's current college list into a Python list
            namelist = ast.literal_eval(user.read()['college_list'])
            
            
            # Get the list of college names from the request data
            selected_names = body.get('names', [])
            
            # Update the user's college list by adding new names, avoiding duplicates
            namelist += [elem for elem in selected_names if elem not in namelist]
            
            # Update the user's record in the database with the new college list
            user.update(college_list=json.dumps(namelist))
            
            return {'message': "User list updated"}

In VSCode, show algorithmic conditions used to validate data on a POST condition.

from model.users import User
from flask import request

def post(self):
    # Extract data from the request's JSON body
    body = request.get_json()
        
    #CHECK if body contains the right information
    #400 if body doesn't exist
    if body is None:
        return {'message': 'Invalid request'}, 400
    
    # Retrieve the user's ID
    username = body.get('name')
    
    # Query the database for the user's record using the user ID
    user = User.query.filter_by(_uid=username).first()
    
    #404 if body isn't searchable in User
    if user is None:
        return {'message': "User ID not found"}, 404
    
#...

In Postman, show URL request and Body requirements for GET, POST, and UPDATE methods.

In Postman, show the JSON response data for 200 success conditions on GET, POST, and UPDATE methods.

GET returns the whole Colleges database with no input.

POST returns the lines of the Colleges database whose names match entries in the user's instance of college_list, given their username.

PUT takes a list of college names obtained through the frontend and adds novel ones to user's college_list.

In Postman, show the JSON response for error for 400 when missing body on a POST request.

In Postman, show the JSON response for error for 404 when providing an unknown user ID to a UPDATE request.

Frontend

(Blog JavaScript API fetch code and formatting code to display JSON.)

In Chrome inspect, show response of JSON objects from fetch of GET, POST, and UPDATE methods.

In the Chrome browser, show a demo (GET) of obtaining an Array of JSON objects that are formatted into the browsers screen.

In JavaScript code, describe fetch and method that obtained the Array of JSON objects.

In JavaScript code, show code that performs iteration and formatting of data into HTML.

import { uri, options } from '/csablog/assets/js/api/config.js';
const apiURL = uri + '/api/users/edit';
console.log(apiURL)

function getFullList() {
  // Make a GET request to the backend API endpoint
  fetch(apiURL)
    .then(response => response.json()) // Parse the JSON response - this contains the array of JSON objects
    .then(data => {
      data.forEach(item => { //Iterate to create a list of corresponding <li> elements
        // Create an <li> element
        var listItem = document.createElement('li');

        // Create an <img> element with the image URL
        var image = document.createElement('image');
        image.src = item.image; // Access 'img' property from JSON

        // Create a text node with the 'name' property as content
        var textNode = document.createTextNode(item.name); // Access 'name' property from JSON

        // Append the image and text to the <li> element
        listItem.appendChild(image);
        listItem.appendChild(textNode);

        // Append the <li> element to the <ul> section
        document.getElementById('appList').appendChild(listItem);
      });
    })
    .catch(error => console.error('Error:', error)); // Handle any errors that occur during the request
}

//Generate this list when the page loads
document.addEventListener('DOMContentLoaded',getFullList)

In the Chrome browser, show a demo (POST or UPDATE) gathering and sending input and receiving a response that show update. Repeat this demo showing both success and failure.

In JavaScript code, show and describe code that handles success. Describe how code shows success to the user in the Chrome Browser screen.

In JavaScript code, show and describe code that handles failure. Describe how the code shows failure to the user in the Chrome Browser screen.

//Make appList selectable
document.addEventListener('DOMContentLoaded', () => {
    // Add event listener to each list item
    document.querySelectorAll('#appList > li').forEach(item => {
      item.addEventListener('click', () => {
        // Toggle the 'selected' class when clicked
        item.classList.toggle('selected');
      });
    });
  });
  
  // Function to retrieve selected items
  function getSelectedItems() {
    return document.querySelectorAll('#appList > li.selected');
  }
  
  function addUserColleges() {
    // Get all selected items
    var selectedItems = getSelectedItems();
    
    // Extract names from selected items
    var selectedNames = [];
    selectedItems.forEach(item => {
        // Find the text node within the list item
        var textNode = item.childNodes[1]; // Assuming the text node is the second child
        selectedNames.push(textNode.textContent);
    });
  
    // Make a PUT request to the backend API endpoint
    fetch(apiURL, {
        method: 'PUT',
        headers: {
            'Content-Type': 'application/json'
        },
        //Body contains selections & username
        body: JSON.stringify({
          name: document.getElementById("name").value, 
          names: selectedNames
          })
      })
      .then(response => response.json())
      .then(data => {
        updateUserList(); //Success - once the information is written to backend, call updateUserList to add new colleges to frontend
      })
      .catch(error => {
        // Failure - display error in a popup window
        window.alert('Error: ' + error);
      });// Handle any errors that occur during the request
  }

(Success in updating the user's list is followed by a regeneration of the user list column, which will be noticeable if any new colleges were added.)

(A popup window appears if failed, as shown in the above code. Note that the success condition relies on the function updateUserList, which is the POST method.)

function updateUserList() {
    fetch(apiURL, {
      method: 'POST', // Specify the POST method
      headers: {
        'Content-Type': 'application/json' // Set the content type header if sending JSON data
      },
      body: JSON.stringify(name: document.getElementById("name").value)
    }).then(response => response.json())
    .then(data => {

      //Find the <ul> block with the id 'appList'
      const ul = document.getElementById('applist'); 
      data.forEach(item => {
        //For each item in the response JSON, make a <li> block
        const li = document.createElement('li');

        //Add the image at the url 'img' to the <li>
        const img = document.createElement('img');
        img.src = item.img;
        img.alt = item.name;

        //Add the string 'link' as a link to the <li>
        const a = document.createElement('a');
        a.href = item.link; 
        a.textContent = item.name;
        li.appendChild(img);
        li.appendChild(a);

        //Apppend the list element to the working <ul> element
        ul.appendChild(li);
      });
    })
    .catch(error => console.error('Error:', error));
  }

Optional/Extra, Algorithm Analysis

In the ML projects, there is a great deal of algorithm analysis. Think about preparing data and predictions.

Show algorithms and preparation of data for analysis. This includes cleaning, encoding, and one-hot encoding.

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_absolute_error
from sklearn.linear_model import LinearRegression
from joblib import dump

#Use pandas read_csv module to convert csv file contents to pandas dataframes
df_happiness = pd.read_csv('world-happiness-report.csv')
df_loc = pd.read_csv('world-happiness-report-2021.csv')

#Restrict to needed columns
df_final = df_happiness[["Country name", "year", "Log GDP per capita", "Social support","Healthy life expectancy at birth", "Freedom to make life choices"]]

#Create dictionaries matching names to scores and location of all countries
add_scores = dict(zip(df_loc['Country name'], df_loc['Ladder score']))
add_locs = dict(zip(df_loc['Country name'], df_loc['Regional indicator']))

#Match names to add new columns
df_final['score'] = df_final['Country name'].map(add_scores)
df_final['location'] = df_final['Country name'].map(add_locs)

#Dictionary of name - key correspondences
mapping = {'Southeast Asia': 0, 'South Asia': 1, 'Western Europe': 2, 'North America and ANZ': 3, 'East Asia': 4,
           'Middle East and North Africa': 5, 'Central and Eastern Europe': 6, 'Latin America and Caribbean': 7,
           'Commonwealth of Independent States': 8, 'Sub-Saharan Africa': 9}

#Add new encoded location column
df_final['loc_encoded'] = df_final['location'].map(mapping)

#Make sure there are no NaN entries
df_final = df_final.fillna(0)

#Drop unneeded columns from x
x = df_final.drop(['Country name','location','score'],axis=1)

#Take score column as y
y = df_final['score']

#Split into testing and training datasets
X_train, X_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=42)

# -- ANALYSIS --

#Train a linear regression model
model = LinearRegression()
model.fit(X_train, y_train)

#Save file using joblib
dump(model, 'happiness_model.joblib') 

Show algorithms and preparation for predictions.

# Importing necessary libraries for data manipulation and Flask RESTful API creation
import pandas as pd
import numpy as np
from flask_restful import Api, Resource
from flask import Blueprint, request
from joblib import load

# A model save file using joblib needs no additional preparation in order for use.
model = load('./api/happiness_model.joblib')

def post(self):
    # Retrieve JSON data sent from the frontend
    body = request.get_json()
    
    # Check if any data is received
    if body is not None:
        # Convert the received JSON data into a pandas DataFrame
        # and rename the columns to match the model's expected input
        data = pd.DataFrame([body])
        data = data.rename(columns={
            "freedom": "Freedom to make life choices",
            "lifespan": "Healthy life expectancy at birth",
            "money": "Log GDP per capita",
            "social": "Social support",
            "location": "loc_encoded"
        })

        # Use the loaded model to predict the happiness score based on the input data
        # model.predict returns a numpy array, so we get the first element ([0]) as the score
        score = model.predict(data)[0]
        # Return the predicted score and a 200 OK status to the client
        return {'score': score}, 200
    else:
        # If no data was provided in the request, return an error message and a 400 Bad Request status
        return {'message': 'No data provided'}, 400

Discuss concepts and understanding of Linear Regression algorithms.

A linear regression algorithm takes two sets of data corresponding to a predictive and target variable and uses them to generate a best-fit linear relation between the two variables. The resulting linear function is then used to predict the values of the target variable given that of the predictive at some unknown point.

A least-squares linear regression is the linear relation where the sum of the squares of the distances of all points from the corresponding point at the same x-value on the relation is the smallest.

Discuss concepts and understanding of Decision Tree analysis algorithms.

A decision tree algorithm attempts to predict the class or value of a target variable using binary decision rules (nodes) learned from training data. The training data associates values of the target with various conditions of several predictive variables. At each node of the tree, it assesses the value of a predictive variable and moves on to the nodes the value grants access too (like a flowchart).

Unlike a linear regression model, decision tree algorithms can be used to infer the value of a categorical target variable.

tags: