Blog Layout

Full stack application build out and other learning from week 17 of Hack Reactor.

Alexander Clemens • Jun 12, 2023

Share

This week marks the completion of our group’s Module 3 full-stack web applications. I’m grateful to have been on a five-person team where members were focused on achieving our Minimal viable product delivered on the due date, and everyone played a part in the project’s design, building, and debugging. I now only have two weeks left of the program, which consists of a final exam on Monday, career service activities, applying for roles, and continual prepping and building upon interview strategies.

Module 3 Project Finalized and Summary on our application


https://gitlab.com/XanderRubio/clueless


For the module 3 final project, I worked with my team to develop a web application for clothing organization and planning. We began by identifying our users, developing high-level functionality, and identifying the APIs needed to bring our project to life. We then created a logo and wireframe and finalized our ideas with a project consultant. Throughout the project, we worked on developing our FastAPI, MongoDB database, and React frontend, focusing on tasks such as creating CRUD functionality for our bins, closet, and clothes models, implementing authentication, and integrating the Open Weather API for displaying weather data. We also spent time improving our CSS and designing our pages based on our wireframes. Throughout the project, we encountered challenges with various aspects of our application, including getting data to display correctly on the front end, but we worked collaboratively to overcome these obstacles. Overall, I contributed to various aspects of the project, including developing the frontend, building the MongoDB database, and working on the FastAPI.

Full stack application built with the following tech stack: Python, FastAPI, Mongo DB, React, Docker, and deployed using Cirrus by Galvanize. Group project completed during module 3 of the Hack Reactor Coding Bootcamp. Users can create an account, upload clothing images, view their images, see a five-day calendar displaying the weather, and select outfit combinations from the planner/calendar page based on the weather for each day.

Our Clueless application can be viewed at https://xanderrubio.gitlab.io/clueless/

The team (corporate-espionage👀) behind this project is:

Clueless — Quickly create outfits based on the weather forecast.

Clueless — Clothing organizer categorized by hat, top, bottoms, and shoes.

Clueless — Stay stylish and organized, all in one place.

Design

can be viewed in detail on our teams repository for this application at: https://gitlab.com/XanderRubio/clueless/-/tree/main/docs



Intended Users


This application is perfect for individuals interested in fashion, organization, and saving time. Specifically, fashionistas who want to store images of their clothes, create outfits, and get weather forecasts for their area; organizers who need a visual way to organize their clothes and easily find the perfect outfit for any occasion; and time-savers who want to quickly create outfits by using the weather forecast to guide them. If you fall into any of these categories, this app is the ideal solution for you!

Functionality


  • Create an account: Users can create an account by providing their email address, password, username, and zip code.
  • Upload clothing images: Users can upload images of their clothes by clicking on the “Upload” button and selecting the images from their computer.
  • See images: Users can see the images they have uploaded by clicking on the “Images” tab.
  • View a five-day calendar: Users can view a five-day calendar to see the weather for their location based on their zip code. The calendar will display the date, temperature, and a weather description with the icon of the weather.
  • Select different outfit combinations: Users can select different outfit combinations from the planner/calendar page to take into consideration their outfit combination based on the weather for that day. To do this, users can click on the “Planner” tab and then select the outfit combinations they want to wear for each day.

Project Initialization

To fully enjoy this application on your local machine, please make sure to follow these steps:


  1. Clone the repository down to your local machine
  2. CD into the new project directory
  3. Run  docker volume create clueless-db
  4. Run  docker compose build
  5. Run  docker compose up

Enjoy your new wardrobe with I Wear Whatevr!

What is Agile in software engineering?

In my experience working with my team during the Module 3 project, Agile is a way to develop flexible software focused on making customers happy. Agile teams work together to create solutions that evolve over time. The Agile Manifesto is a set of values and principles that guide this approach. These include making customers happy, being open to change, delivering working software often, and prioritizing communication and teamwork.

How I describe the bubble sort

The bubble sort method is one of the first sorting methods taught to individuals when they are initially learning various ways to sort data. This is because it is easy to understand how the technique works. However, it is not a practical method for sorting large sets of data. The bubble sort is mainly used to teach and introduce engineers/developers to how sorting works in algorithms.


To implement the bubble sort method, we need an array with a list of numbers. In the function, we will use variables to access the elements in the array. We will compare two elements at a time from the array, so we need to iterate over the array until all elements have been reached. Since we will use a simple iteration of a for loop, we don’t need to have a recursive call because the data is not big enough to warrant breaking down the problem into smaller problems. Typically, developers represent these index variables with i for the outer loop and j for the inner loop, following best practices and industry standards.

The goal of the bubble sort is to compare two adjacent elements and determine which one is greater (or less) than the other, depending on the direction you need to sort the data. If the first element is greater (or less) than the second element, they are swapped to create the ordered sort. This process continues until the last two elements in the array are reached and sorted.

The name “bubble sort” comes from the sorting feature that moves or “bubbles” up the largest or smallest value to the end of the array. Think of a soda can and how liquid and bubbles are in the can. When you pour the soda into a glass (which represents looping over the array and comparing elements), the bubbles rise to the top of the liquid in the glass. In this case, the bubbles represent the largest or smallest elements needing sorting.

How I describe the Radix Sort (bucket sort)

Radix sort, also known as bucket sort, confidently sorts the individual digits of a number without the need for comparisons. This non-comparative sorting algorithm begins by grouping the digits of the numbers into buckets, each corresponding to a specific digit and sorted from least to most significant digit. For instance, if sorting a list of three-digit numbers, ten buckets representing the digits 0–9 would be created for each digit place value.


The algorithm then iterates through each digit place value of each number in the list (from right to left), placing the number into the corresponding bucket based on the digit at that value. Once all numbers are inducted into the buckets, the algorithm concatenates them to form the sorted list. This sorting process is repeated for each digit place value, starting from the least significant digit and iterating to the most significant digit. After sorting all the digits, the list is fully sorted.

Radix sort’s O(n) time complexity makes it a linear time sorting algorithm. Nonetheless, it requires extra space to create and maintain the buckets, which may not be practical for large datasets. To summarize, radix sort is an efficient non-comparative sorting algorithm that confidently sorts the digits of a number and groups them into buckets. It sorts each digit place value of each number in the list, starting from the least significant digit and iterating to the most significant digit. Radix sort has a time complexity of O(n) and requires additional space for bucket creation and maintenance.


How I describe the Selection Sort

Selection Sort is a basic algorithm for sorting an array. It works by repeatedly finding the smallest element from the unsorted part of the array and moving it to the beginning of the sorted part. This is done using two loops. The outer loop selects the leftmost unsorted element, while the inner loop finds the minimum element in the unsorted part of the array. Once the minimum element is found, it is swapped with the leftmost unsorted element. This process is repeated until the entire array is sorted.


Selection Sort differs from other sorting algorithms because it does not use recursive calls. Instead, it uses three variables to keep track of its state and perform the necessary comparisons and swaps. These variables are an index variable to keep track of the leftmost unsorted element, a minimum variable to keep track of the current minimum element, and a temporary variable for swapping elements.

In my mind the selection sort is a simple and efficient algorithm for sorting an array. It works by finding and moving the smallest element to the beginning of the sorted part of the array. It uses three variables to keep track of its state and does not use recursive calls.

How I describe the Quick Sort

Quick Sort is a sorting algorithm that divides an array into smaller sub-arrays based on a “pivot” element. The pivot element is chosen from the array, and all other elements are compared to it. Elements that are smaller than the pivot are moved to the left of it, while larger elements are transferred to the right of it. The pivot element is now in its final sorted position.


The algorithm is then applied recursively to the pivot’s sub-arrays on the left and right until the entire array is sorted. This process is repeated until there are no more sub-arrays to sort.

The recursive calls in Quick Sort are necessary for sorting the sub-arrays. The algorithm chooses a pivot element and partitions the array into two sub-arrays based on the pivot. The left sub-array contains all elements less than or equal to the pivot, while the right sub-array contains all elements greater than the pivot. The algorithm then applies itself recursively to both sub-arrays until the entire array is sorted.

Variables are used in Quick Sort to keep track of the pivot element, the left and right indices of the sub-arrays, and a temporary variable used for swapping elements. These variables serve to keep track of the algorithm’s state and perform the necessary comparisons and swaps.

This sorting algorithm chooses a pivot element and partitions the array into two sub-arrays based on the pivot. The algorithm then sorts the sub-arrays recursively until the entire array is sorted. Recursive calls are necessary to sort the sub-arrays, and variables are used to keep track of the algorithm’s state.

How I describe Binary Search

Binary Search is an algorithm used to find a specific value within a sorted array. It works by repeatedly dividing the array in half until the value is found or it is determined that the value is not in the array.


To start the algorithm, we need a sorted array and a target value to search for. We set two pointers, one at the beginning of the array and one at the end of the array. We then calculate the middle index of the array by taking the average of the two pointers. We compare the value at the middle index with the target value. If the central element is equal to the target value, we return the index of the middle element.

If the middle element is greater than the target value, we discard the right half of the array and repeat the algorithm on the left half of the array. If the middle element is less than the target value, we discard the left half of the array and repeat the algorithm on the right half of the array. We continue this process of dividing the array in half until we find the target value or determine that it is not in the array.

Binary Search is a recursive algorithm that calls itself repeatedly until the target value is found or it is determined that the value is not in the array. The recursive calls are necessary because the algorithm needs to search the left or right half of the array depending on whether the middle element is greater than or less than the target value.

Several variables are used in Binary Search, including pointers for the beginning and end of the array, a middle index variable, and a target value variable. These variables are used to keep track of the algorithm’s state and perform the necessary comparisons and calculations.

How I describe Looping Binary Search

Looping Binary Search is a search algorithm for a specific value within a sorted array. It works by repeatedly dividing the array in half until the value is found or it is determined that the value is not in the array. To start the algorithm, we need a sorted array and a target value to search for. We set two pointers, one at the beginning of the array and one at the end of the array. We then calculate the middle index of the array by taking the average of the two pointers. We compare the value at the middle index with the target value. If the middle element is equal to the target value, we return the index of the middle element. If the middle element exceeds the target value, we move the right pointer to the middle index and recalculate the middle index. If the middle element is less than the target value, we carry the left pointer to the middle index and recalculate the middle index. We continue this process of dividing the array in half and comparing the middle element with the target value until we find the target value or determine that it is not in the array. Looping Binary Search uses a loop to accomplish this task. The loop iterates through the array and recalculates the middle index on each iteration. The variables used include pointers to the beginning and end of the array, a middle index variable, and a target value variable. The purpose of these variables is to keep track of the algorithm’s state and perform the necessary comparisons and calculations. In summary, Looping Binary Search is a search algorithm to find a specific value within a sorted array. It works by dividing the array in half and comparing the middle element with the target value. Suppose the middle element is greater than or less than the target value. In that case, the algorithm continues the search in the appropriate half of the array by adjusting the pointers and recalculating the middle index. Looping Binary Search uses a loop to iterate through the array and has variables to keep track of the algorithm’s state.


How I describe Recursive Binary Search

Recursive Binary Search

Recursive Binary Search is an algorithm that finds a specific value within a sorted array. It does this by dividing the array in half and comparing the middle element with the target value. If the middle element is equal to the target value, the algorithm returns the index of the middle element. If the middle element is greater than the target value, the algorithm applies itself recursively to the left half of the array; otherwise, it applies itself recursively to the right half of the array.


The algorithm uses a pivot element to partition the array into two sub-arrays. The left sub-array contains all elements less than or equal to the pivot, while the right sub-array contains all elements greater than the pivot. The algorithm applies itself recursively to both sub-arrays until the entire array is sorted.

Recursive Binary Search uses variables to keep track of the algorithm’s state, including the pivot element, the left and right indices of the sub-arrays, and a temporary variable used for swapping elements. This helps the algorithm to perform necessary comparisons and swaps.

This search algorithm finds a specific value within a sorted array by dividing the array in half and comparing the middle element with the target value. Depending on the middle element’s value, it applies itself recursively to the left or right half of the array. It uses variables to keep track of its state and to perform necessary comparisons and swaps.

How I describe the merge sort

Sorting algorithms offer different methods to choose from, each with its pros and cons. One popular method is the merge sort algorithm, known for its efficiency and scalability. The merge sort algorithm follows the divide-and-conquer approach to problem-solving. It breaks down the problem into smaller, more manageable pieces, then recursively solved. To sort an array of elements, the merge sort algorithm divides the array into smaller arrays, each sorted recursively. The sorted sub-arrays are then merged to form the final sorted array. The merge step is where the real magic happens in the merge sort algorithm. This step allows the algorithm to be efficient and scalable. Two arrays are combined into a single sorted array using an auxiliary data structure, such as an accumulator list. The merge step compares the first element of each input array, selects the smaller element, and appends it to the accumulator list. The pointer of the smaller value is then incremented to the next element in the array. This process is repeated until one of the input arrays is empty. The remaining elements of the other input array are then appended to the accumulator list. The merge sort algorithm has an overall time complexity of O(n log n) and space complexity of O(n). The divide-and-conquer approach allows the algorithm to sort the array in a logarithmic time. The auxiliary data structure, such as an accumulator list, stores the sorted elements during the merge step, resulting in space complexity. The merge sort algorithm is a powerful and efficient sorting algorithm that follows the divide-and-conquer approach. It uses the merge step to combine sorted sub-arrays into a single sorted array. This step is what makes the algorithm efficient and scalable. The merge sort algorithm has an overall time complexity of O(n log n) and space complexity of O(n), making it a great choice for sorting large datasets.


How I describe the Big-O class and what it means for an algorithm to have O(log n) worst-case complexity.

O(log n) represents how long (the time) an algorithm will need to complete the function is determined logarithmically. In this case, it will be represented by the sizes of the data or inputs and growing more complex in time-solving described in the l measurement of og of n. To data scientists and algorithm experts, O(log n) represents how long (the time) an algorithm will need to complete the function is determined logarithmically. In this case, it will be represented by the sizes of the data or inputs and growing more complex in time-solving described in the l measurement of og of n. To data scientists and algorithm experts, this is considered a more efficient alternative than having a time complexity that grows in the complexity of (O(n)). It is called a quadratic growth of (O(n²)), which, quite frankly, I can’t wrap my head around the immense iterations that would need to be performed in an algorithm with a time complexity of quadratic growth.


For example, performing a sort algorithm that continually splits or divides an array in half until the value that has been set is found, also known as a binary search, would be an example of a time complexity of O(log n). In this case, the n would represent the time it takes to run the iteration or search through the list size. Therefore O(log n) is good because time grows slowly for running this function as more data or input is added. This is considered a more efficient alternative than having a time complexity that grows in the complexity of (O(n)). I believe it is called a quadratic growth of (O(n²)), which, quite frankly, I can’t wrap my head around the immense iterations that would need to be performed in an algorithm with a time complexity of quadratic growth. For example, performing a sort algorithm that continually splits or divides an array in half until the value that has been set is found, also known as a binary search, would be an example of a time complexity of O(log n). In this case, the n would represent the time it takes to run the iteration or search through the list size. Therefore O(log n) is good because time grows slowly for running this function as more data or input is added.

SQL Syntax

  • SELECT: used to retrieve data from one or more tables in a database
  • FROM: used to specify the table(s) the data is being retrieved from in a SELECT statement
  • WHERE: used to filter data based on a specific condition(s)
  • GROUP BY: used to group data based on one or more columns
  • HAVING: used to filter data based on a specific condition(s) after data has been grouped using GROUP BY
  • ORDER BY: used to sort data based on one or more columns
  • JOIN: used to combine rows from two or more tables based on a related column between them
  • UNION: used to combine the results of two or more SELECT statements into a single result set
  • INNER JOIN: returns only the rows that have matching values in both tables being joined
  • LEFT JOIN: returns all the rows from the left table and the matching rows from the right table being joined
  • RIGHT JOIN: returns all the rows from the right table and the matching rows from the left table being joined
  • FULL OUTER JOIN: returns all the rows from both tables being joined, including the ones that don’t have matching rows in the other table
  • CREATE: used to create a new table, view, or other database objects
  • ALTER: used to modify an existing table, view, or other database objects
  • DROP: used to delete an existing table, view, or other database objects
  • INSERT INTO: used to insert new rows into a table
  • UPDATE: used to update existing rows in a table
  • DELETE: used to delete existing rows from a table
  • COMMIT: used to save changes made to the database
  • ROLLBACK: used to undo changes made to the database since the last COMMIT
  • INDEX: used to speed up data retrieval by creating an index on one or more columns in a table
  • VIEW: a virtual table that is based on the result of a SELECT statement, used to simplify complex queries or restrict access to sensitive data
  • PROCEDURE: a stored program that can be called by other programs or scripts to perform a specific task
  • FUNCTION: a stored program that returns a value based on input parameters
  • TRIGGER: a special type of stored program that is automatically executed in response to specific events, such as INSERT, UPDATE, or DELETE statements
  • CONSTRAINT: used to enforce specific rules or conditions on the data in a table
  • PRIMARY KEY: a column or group of columns that uniquely identifies each row in a table
  • FOREIGN KEY: a column or group of columns that refers to the primary key of another table, used to establish a relationship between two tables
  • UNIQUE: a column or group of columns that must contain unique values across all rows in a table
  • NOT NULL: a column constraint that specifies the column cannot contain NULL values
  • CHECK: a column constraint that specifies a condition that must be true for all rows in a table

Different types of joins.

In SQL, you can join two tables in different ways. We discussed two ways: inner join and left/right join. An inner join returns only the rows that have matching values in both tables, while a left or right join returns all the rows from one table and only matching rows from the other table.


When using the INNER JOIN, this will find the math meaning that it will return rows that only have the values that match the two tables that are being joined. With the LEFT/RIGHT JOIN, this will look for all the tables from the left/right table and then return a matching value from the right/left table depending on which join you use, left or right. In addition, when using left/right join, it will return a NULL if no match is found.

Example INNER JOIN: Let’s say you want to retrieve a chef’s name for the name of one of their recipes. You can select both tables of recipes. title and chefs. name and then use the INNER JOIN to combine the data from those two tables and display the chef and his recipe.

Example LEFT/RIGHT JOIN: Let’s say you need to retrieve all the chefs from the chef’s table. Then I could use the SQL query of SELECT chefs. name then FROM chefs, and LEFT JOIN recipes ON chef.id, and this will return all the chefs and their names even if they still need to register a recipe in the database.

Depth-first search

During a depth-first search of a tree data structure, we use a data structure to keep track of which nodes we’re currently searching. This data structure is a stack.


In software engineering, a stack is a data structure that stores a collection of elements and operates based on the last-in-first-out (LIFO) principle. Elements are pushed onto the stack and popped off the stack in reverse order. This data structure is commonly used in programming languages to manage function calls, as well as in other applications such as undo/redo functionality.

What are tree data structure

Trees are a type of graph that do not have cycles. A tree data structure is a specific type of graph that does not contain cycles. It consists of nodes with child nodes and a parent node (except for the root node). Trees are frequently used to model hierarchical structures, such as file directories, organizational charts, and family trees. In programming, trees are frequently used to implement search algorithms and other operations that involve organizing and retrieving data in a specific order.


What describes components of a graph that is the object that stores data?

This is a Node. In software engineering, a node is a fundamental component of many data structures, including trees and graphs. In a tree structure, a node represents a single element or object, such as a file in a file directory or a record in a database. In a graph, a node typically represents a point or object, and may be connected to other nodes via edges or links. Nodes can store data and metadata relevant to the structure they are a part of, and may also have associated functions or methods to manipulate the data or interact with other nodes in the structure.

LinkedIn Learning Courses completed for this week

LinkedIn's AI Academy Learning Path | LinkedIn Learning, formerly Lynda.com

AI is very important but seldom fully understood. It's changing the way we think about business, but it's changing so…

www.linkedin.com


Digital marketing meets generative AI - Generative AI for Digital Marketers Video Tutorial |…

From the course: Generative AI for Digital Marketers - It's taken more than 60 years for artificial intelligence to…

www.linkedin.com


Immediate benefits of arguing like a lawyer - Tips to Win Arguments and Influence Like a Lawyer…

From the course: Tips to Win Arguments and Influence Like a Lawyer - When was your last argument? Not that fun, right…

www.linkedin.com


Acing your MAANG interview - Landing a MAANG Job: Behavioral Interview Questions Video Tutorial |…

From the course: Landing a MAANG Job: Behavioral Interview Questions - Welcome. If you're here, you're probably hoping…

www.linkedin.com


https://www.linkedin.com/learning/introducing-s

emantic-kernel-building-ai-based-apps/introducing-semantic-kernel

DevOps foundations: CD/CI - DevOps Foundations: Continuous Delivery/Continuous Integration Video…

From the course: DevOps Foundations: Continuous Delivery/Continuous Integration - Are you troubled by strange ways that…

www.linkedin.com


Understanding techniques - Software Testing Foundations: Test Techniques Video Tutorial | LinkedIn…

The moment you enter testing, you have to consider the arsenal of tools available to ensure a quality product will be…

www.linkedin.com


Why you need to know about artificial intelligence — Build new artificial intelligence skills with free courses Video Tutorial | LinkedIn Learning, formerly Lynda.com

Going into Week 18

As I progress through the last two weeks of the Hack Reactor Bootcamp, I’m excited to soon move onto the phase of job searching, interviews, and reviewing offers. The program provides a six-month service for graduates to use the job-searching software called Huntr (https://huntr.co/).

Huntr - Job Application Tracker & CRM

No more messy job search spreadsheets. Huntr keeps track of every detail about your job opportunities regardless of…

huntr.co


Like most people in this space, I see the industry for individuals who work in it as needing to consistently learn and grind to stay on top of the tech stack or industry trends that change at the speed of light. The apparent trend is AI, which poses massive changes for humanity because of its constant operation. It doesn’t require rest, sleep, food, a comfortable workspace, a professional and productive team to work with, or professional communication. This rapid technological development can make it so that humans must continually reinvent themselves at a pace that has never existed. This became even more evident when I watched a recent talk that the well-known historian and philosopher, Yuval Noah Harari, gave at a live interview in Lisbon, Portugal (https://www.youtube.com/watch?v=4hIlDiVDww4).


Anyways, I continue to learn as much as possible in my limited time while also prioritizing my mental health, physical movement, and relationships with my girlfriend and family. Moving onto week 18! Nos vemos en el próximo artículo.


Ready to work with Xander Clemens?

I'd be happy to discuss your project and how we can work together to create unique, fun and engaging content.

Go ahead and click here to be taken to my business service page and see what I can do for you. Book a call with me now. Looking forward to chatting soon!

Book A Call
Share by: