Skip to content

ShawnBoyle7/Programmatic

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Programmatic

Logo

Introduction

Programmatic is a developer's curriculum platform. We set out to help those who struggle to solidify an understanding of abstract computer science and programming concepts, by breaking them down with thorough but succinct courses, lessons, and visualizations. Visit our Visualizations page for animations and diagrams of Data Structures & Algorithms to assist your learning. You can personalize your own learning path to set clear goals for your aspirations as a developer. In your path, you can add a course or a specific lesson that you plan to complete, which you can check as complete when you're done!

Table of Contents

  1. Introduction
  2. Technologies
  3. Documentation
  4. Development
  5. How To Use
  6. Code Highlights
  7. Future Plans

Technologies

  • JavaScript
  • Python
  • HTML
  • CSS
  • React
  • Redux
  • Flask-SQLAlchemy
  • Node.js
  • AWS S3
  • Docker
  • Heroku

Documentation

Development

  1. Clone the repository at https://github.com/ShawnBoyle7/Programmatic
  2. Install depdencies
pipenv install --dev -r dev-requirements.txt && pipenv install -r requirements.txt 
  1. Set up your postgreSQL user and database.

  2. Create the .env file. You can use my env example as a reference, ensure your settings match your local database from last step.

  3. Enter your virtual environment, migrate and seed your database, then run the backend application.
pipenv shell
flask db upgrade
flask seed all
flask run
  1. Enter react-app and install your dependencies, then run the frontend application.
npm install
npm start

How To Use

Splash

When you first load up the website, you'll encounter this splash page where you can sign up, log in.

Splash

You will need to be signed in to view a lesson, comment, or access the profile and learning path feature. If you'd like to try out those features feel free to use the Demo!

Visualizations

Once you navigate to the visualizations section, you'll encounter this page showing a list of our visualizations. You can click one to visualize the algorithm.

Visualizations

Visualization Modal

After clicking on an algorithm, this modal will appear with a graph of nodes. You can click visualize to play the traversal animation and shortest path, faster for 2x speed, slower for 0.5x speed, or reset to reset the graph.

Visualization Modal

Home

When you are logged in, you'll see this page rather than the splash, which displays our highest rated lessons from user votes descending.

Home

Courses

When on the courses page, you'll see a list of clickable courses which contain lessons. If logged in, you can add them to your learning path if any lessons in them aren't in your learning path already.

Courses

Lessons

When on the lessons page, you'll see a list of clickable lessons that take you to the individual lesson page. You will need to be logged in to access this, so go ahead and click the demo button if you haven't already! If logged in, you can also add these to your learning path if they aren't in your learning path already.

Lessons

Lesson

When on the lesson page, you'll be met with a title and description of the lesson, proceeded by a diagram or representational image, and the course content text below it.

Lesson

Feedback

If logged in while on the lesson page, you can comment below the lesson or vote below the comment section to share your feedback!

Feedback

Profile

Now on your profile page, you can view the courses and lessons you've added to your learning path. If you want to move it to completed, or remove it, you can hover over the circles to display buttons to do so.

Profile

Edit Account

While on your profile, you can edit your account details by hovering over your profile image and clicking the pencil. It will display a modal to edit your details.

Edit Account

Code Highlights

This is Dijkstra's shortest path being used to animate the traversal process of the algorithm through a graph. The shortest path is also rendered after the traversal.

const graphNodes = require('../../data/dijkstra_graph_data.json')

function DijkstraVisualization() {

    const checkIfNode = (key) => {
        const node = graphNodes[key]
        return node ? true : false
    }

    const createGrid = () => {
        const gridCells = []
        for (let row = 0; row < 20; row++) {
            for (let column = 0; column < 30; column++) {
                gridCells.push(<GridCell key={`r${row}c${column}`} row={row} column={column} isNode={checkIfNode(`r${row}c${column}`)} />)

            }
        }
        return gridCells;
    };

    const dijkstraAlgorithm = (startNode, targetNode) => {
        const traversalOrder = [];
        const nodesToVisit = [];
        const visitedNodeCoordinates = new Set();

        nodesToVisit.push({
            coord: startNode.coord,
            path: [startNode.coord],
            edgeToNode: null,
            totalWeight: 0
        })

        while (nodesToVisit.length) {
            const currentNode = nodesToVisit.shift()
            traversalOrder.push(currentNode.coord)
            visitedNodeCoordinates.add(currentNode.coord)

            if (currentNode.coord === targetNode.coord) {
                const dijkstraPath = currentNode.path
                return [dijkstraPath, traversalOrder]
            }

            graphNodes[currentNode.coord].neighbors.forEach(neighbor => {
                traversalOrder.push(neighbor.edge)
                if (visitedNodeCoordinates.has(neighbor.coord)) return;

                const plannedToVisit = nodesToVisit.find(node => node.coord === neighbor.coord)
                if (!plannedToVisit) {
                    nodesToVisit.push({
                        coord: neighbor.coord,
                        path: [...currentNode.path, neighbor.edge, neighbor.coord],
                        edgeToNode: neighbor.edge,
                        totalWeight: currentNode.totalWeight + neighbor.weight
                    })
                } else {
                    if (plannedToVisit.totalWeight > currentNode.totalWeight + neighbor.weight) {
                        const index = nodesToVisit.indexOf(plannedToVisit);
                        nodesToVisit[index].path = [...currentNode.path, neighbor.edge, neighbor.coord]
                        nodesToVisit[index].edgeToNode = neighbor.edge
                        nodesToVisit[index].totalWeight = currentNode.totalWeight + neighbor.weight
                    }

                }
            })

            nodesToVisit.sort((a, b) => a.totalWeight - b.totalWeight)
        }
    }

    const [dijkstraPath, traversalOrder] = dijkstraAlgorithm(graphNodes.r1c1, graphNodes.r18c28)

    const playVisualization = (e) => {
        resetGraph();
        const traversalOrderCopy = traversalOrder.slice();
        const dijkstraPathCopy = dijkstraPath.slice();
        window.animateTraversalInterval = setInterval(() => {
            animateTraversal(traversalOrderCopy, dijkstraPathCopy);
            if (!traversalOrderCopy.length) {
                clearInterval(window.animateTraversalInterval);
            }
        }, e.target.value)

    }

    const animateTraversal = (traversalOrderCopy, dijkstraPathCopy) => {
        if (traversalOrderCopy.length) {
            const coordinate = traversalOrderCopy.shift()
            document.querySelector(`.${coordinate}`)?.classList.add("traversed");
        }

        if (!traversalOrderCopy.length) {
            window.animatePathInterval = setInterval(() => {
                animatePath(dijkstraPathCopy);
                if (!dijkstraPathCopy.length) {
                    clearInterval(window.animatePathInterval);
                }
            }, 100)
        }
    }

    const animatePath = (dijkstraPathCopy) => {
        if (dijkstraPathCopy.length) {
            const coordinate = dijkstraPathCopy.shift()
            document.querySelector(`.${coordinate}`)?.classList.add("path");
        }
    }

    const resetGraph = () => {
        clearInterval(window.animateTraversalInterval);
        clearInterval(window.animatePathInterval);
        traversalOrder.forEach(coordinate => {
            document.querySelector(`.${coordinate}`)?.classList.remove("traversed");
        })
        dijkstraPath.forEach(coordinate => {
            document.querySelector(`.${coordinate}`)?.classList.remove("path");
        })
    }

Future Plans

  • In the future, we're planning to keep adding traversal & sorting algorithms to the application until we have a highly diverse of rendered visualizations for different needs.

  • We plan to write out the lessons manually and implement diagrams for users to learn more about data structures & algorithms conceptually.

Developers

About

Programmers visualize algorithms and data for programmers.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •  

Languages