vivianknee / tri2miniProject

Apache License 2.0
0 stars 0 forks source link

Final Crossover Review Ticket - Vivian Aliya Kevin #4

Open vivianknee opened 10 months ago

vivianknee commented 10 months ago

Grading

Team: Crossover Score Runtime Writeup GitHub Commits
0.83
  1. Sorting
  2. Fibonacci
    See Below for writeup
    1. Backend
    2. Frontend
      1. Backend
      2. Frontend

        Individuals:

        Name Crossover Score Key Commits Analytics Video Individual Ticket
        Vivian Ni 0.885 + 0.83 = 1.865
        1. Added time methods to sorting class
        2. Finishing Art and Sorting APIS, setup @Override annotation for sorting algorithtim files
        3. added sortingsteps to Sorting class
        4. GET request on fronted, JS art piece display formatting
        5. POST request on frontend for likes and sorting methods
        6. Sorting animations
        profile Video Link
        Kevin Du 0.88 + 1 = 1.86
        1. Binet Fibonacci Algorithim
        2. JS for Fibonacci art generator
        3. Decorated Home page
        4. Matrix Exponentation
        5. Iterative Fibonacci
        profile Video [Link]()
        Aliya Tang 0.845 + 0.83 = 1.825
        1. Merge sort
        2. bubble sort
        3. insertion sort
        4. selection sort
        5. Created popup for sort animation
        6. Nav bar styling and gallery styling
        profile Video Link

        Project

        Our project utilizes sorting and Fibonacci to create an art gallery that can be sorted by popularity. Users visiting the site can interact with the art pieces, choose their favorite, and like it. They can then sort the arts by likes and see a visualization of the sort, the number of steps it takes to sort, and the total time in NS. The Fibonacci portion of the project allows the user to input a number (nth term) and a piece of art is created based on it. This is the link to our initial plan which has been adapted since

        Issues

        We ran into a lot of issues.

        Kevin: 1) Fibonacci connection backend issue. I attempted to connect some Java versions of the Fibonacci sequence, but failed to connect. I did manage to get a better understanding of how the backend works, unlike last year, I still didn't know how backend worked. The only thing I was struggling on was connecting it to frontend.

        Vivian:

        1. Animation js issue: JavaScript is single-threaded, meaning only one function can be running at any given time in the thread. Initially, I used a nested loop which accumulated the code for every step of the animation and was returned at the very end. However, I wasn't able to see the animation because Canvas draws all the commands including the clear canvas at the end so the final result was just blank. So instead, I used setInterval to run the function once, wait 500 ms, add to variable i(represents the number of steps), and then run again. This way, it shows the steps of the animation. Here is the new code:

          function animate(array) {
              const canvas = document.getElementById("animation");
              const ctx = canvas.getContext("2d");
              ctx.fillStyle = 'blue';
              var barContainerWidth = 500/array[0].length;
              var barWidth = 2/3 * barContainerWidth;
              var i = 0;
              var intervalInvalid = setInterval(function() {
                  ctx.clearRect(0,0,500,350);
                  var max = Math.max(...array[i]);
                  console.log(max);
                  for (let j = 0; j < array[i].length; j++) {
                      var likes = array[i][j]
                      if (likes == 0) {
                          likes = 0.1
                      }
                      var x = barContainerWidth * j;
                      var y = (max - likes)/max * 350;
                      var w = barWidth;
                      var h = likes/max * 350
                      ctx.fillRect(x, y, w, h);
                  }
                  i++;
                  if (i >= array.length) {
                      clearInterval(intervalInvalid);
                  }
              }, 500);
          }
        2. Another issue I ran into was returning sorting steps to the front end so that I could animate and create a sorting visual for the algorithms. For the LONGEST time, the return for sorting steps was Null which made me realize that the method on the backend to get the sorting results was not being called. How I had it coded was each sort on the drop-down menu on the frontend is assigned a value which is then used in the POST request URL to the backend. However, if the backend method was not being called, it meant the value being used was incorrect. I ended up using this Java syntax to fix the error contains("bubble") Now, as long as the value contains the name of the sort, the method will be called. I don't think this is the best way to fix the problem but it's a temporary solution I found. Now sorting steps return an array of lists:

          Screenshot 2023-12-10 at 2 55 19 PM

        Aliya: An issue I ran into was that when the art pieces were sorted there would be duplicates of pieces if the like count changed between sorting. I thought it was a problem with all the sort methods but then I realized there was an error with my bubble sort method. Initially, the swapping based on likes was making duplicates by setting both positions to the same value of the pieces instead of actually swapping and replacing it:

        temp = unsortedArts.get(j);
        unsortedArts.set(j, unsortedArts.get(j));
        unsortedArts.set(j + 1, temp);

        Initially, the swapping based on likes was making duplicates by setting both positions to the same value of the pieces instead of actually swapping and replacing it. After fixing it:

        temp = unsortedArts.get(j);
        unsortedArts.set(j, unsortedArts.get(j + 1));
        unsortedArts.set(j + 1, temp);

        The bubble sort works and doesn't create duplicates.

        Improvements

        1. While I did get the animation to work for insertion, selection, and bubble, merge was a little more tricky as it is a recursive algorithm. Going into the future, that is something I want to figure out.
        2. I also want to make it so that the art can be disliked and be sorted by dislikes. Creating an option to sort by ascending and descending order would be a cool addition.
        3. Have Fibonacci be more interactive. Users can type in the nth number

        Reflection

        We followed our Agile Manifesto as we progressed through this project.

        Screenshot 2023-12-10 at 3 09 31 PM

        Our collaboration improved a lot from each of our experiences from the last trimester. We called and met up in person outside of school to work on the project. Vivian and Aliya's collaboration was on point because their features were more intertwined, but it was hard to collaborate between Aliya/Vivian, and Kevin because his role with Fibonacci in the project a different feature. Because of the time crunch, we decided to take a divide-and-conquer approach, which hindered our collaboration. Next time, we should avoid this approach.

        Overall, we learned a lot from the analysis portion of this project. Initially, we never realized the difference in times and procedures for each sort. But after seeing the animation, time, and number of swaps, It's made us understand the differences between each sort that the computer itself can't show. Specifically, Bubble sort is very slow and has way more swaps than selection sort which is much faster.

        Sorting - Algorithms, Inheritance, Abstraction

        Vivian and Aliya primarily worked on the Sorting on the backend. Vivian constructed the API and Aliya wrote the sorting methods for each.

        Inheritance and Abstraction

        Since we are using 4 different methods of sorting, those being merge, insertion, bubble, and selection, we created a parent class called Sorting. In this class is the method for each sort which was then customized to the specific type of sort using the annotation @Override. In order to show the user the animation, time, and steps taken per sort, we created another method SortingResult to return those variables.

        package com.nighthawk.spring_portfolio.mvc.sorting;
        
        //import java.util.ArrayList;
        import java.util.List;
        
        import com.nighthawk.spring_portfolio.mvc.art.Art;
        
        public class Sorting {
        
            //override to create specific sort
            protected SortingResult sortArt(List<Art> unsortedArts) {
                return new SortingResult();
            }
        
            public SortingResult getSortingResult(List<Art> unsortedArts) {
                long startTime = System.nanoTime();
                SortingResult result = sortArt(unsortedArts);
                long endTime = System.nanoTime();
                long finalTime = endTime - startTime;
                result.sortTime = finalTime;
                //result.steps.add(unsortedArts);
                return result;
            }
        }

        Algorithms

        Here is a link to the algorithms that Aliya wrote. Vivian did crossover checks with Aliya to ensure the sorts were all in descending order.

        Sort Type Link
        Bubble Link
        Insertion Link
        Merge Link
        Selection Link

        Backend

        Besides sorting algorithms, Vivian created an Art API as well as Create and Read functionalities to display the art on the frontend and allow users to interact with it.

        This first code is the Art class which contains the data for the SQLite table

        public class Art {
            @Id
            @GeneratedValue(strategy = GenerationType.AUTO)
            private Long id;
        
            @Column(unique=true)
            private String artName;
        
            private int like;
        
            public static String[] init() {
                final String[] artArray = {
                    *art names go here*
                };
                return artArray;
            }
        }

        This code segment shows the ArtApiController which has GET, POST (for likes), and another POST method to call the sorting algorithms on the backend

        public class ArtApiController {
            // Autowired enables Control to connect URI request and POJO Object to easily for Database CRUD operations
            @Autowired
            private ArtJpaRepository repository;
        
            /* GET List of Jokes
             * @GetMapping annotation is used for mapping HTTP GET requests onto specific handler methods.
             */
            @GetMapping("/")
            public ResponseEntity<List<Art>> getArts() {
                // ResponseEntity returns List of Jokes provide by JPA findAll()
                return new ResponseEntity<>( repository.findAll(), HttpStatus.OK);
            }
        
            //Update Like 
            @PostMapping("/like/{id}")
            public ResponseEntity<Art> setLike(@PathVariable long id) {
        
                Optional<Art> optional = repository.findById(id);
                if (optional.isPresent()) {  // Good ID
                    Art art = optional.get();  // value from findByID
                    art.setLike(art.getLike()+1); // increment value
                    repository.save(art);  // save entity
                    return new ResponseEntity<>(art, HttpStatus.OK);  // OK HTTP response: status code, headers, and body
                }
                // Bad ID
                return new ResponseEntity<>(HttpStatus.BAD_REQUEST);  // Failed HTTP response: status code, headers, and body
            }
        
            @PostMapping("/sorted/{method}")
            public ResponseEntity<SortingResult> getSortedArts(@PathVariable String method) throws Exception {
                // ResponseEntity returns List of Jokes provide by JPA findAll()
                List<Art> arts = repository.findAll();
        
                Sorting sorter = new Bubble();
                if (method.contains("bubble")) {
                    sorter = new Bubble();
                }
                else if (method.contains("insertion")) {
                    sorter = new Insertion();
                }
                else if (method.contains("merge")) {
                    sorter = new Merge();
                }
                else if (method.contains("selection")) {
                    sorter = new Selection();
                }
                else {
                    throw new Exception(method);
                }
        
                // use your sorting class here to sort the list
                SortingResult sortResult = sorter.getSortingResult(arts);
        
                return new ResponseEntity<>(sortResult, HttpStatus.OK);
            }
        }

        Frontend

        GET request

        function getArtWorks() {
                fetch(deployURL + '/api/art/')
                    .then(response => response.json())
                    .then(data => {
                        formatArt(data);  
                        showPopup();
                    })
                    .catch(err => {
                        console.log(err);
                    });
            }

        POST Request

        function setupSort() {
                var sort_button = document.getElementById("sort_button");
                console.log(sort_button);
                sort_button.addEventListener("click", function(){
                            var sortingMethod = document.getElementById('sorts').value
                            fetch(deployURL + `/api/art/sorted/${sortingMethod}`, {
                                method: 'POST',
                                headers: {
                                    'Content-Type': 'application/json',
                                },
                            })
                            .then((response) => response.json())
                            .then((sortResult) => { 
                                console.log(sortResult);
                                formatArt(sortResult.sortedArts); 
                                const sort_time = document.getElementById("sort_time");
                                sort_time.innerHTML = "Sort Time: " + sortResult.sortTime + " ns";
                            });
                        });
            }

        The beautiful design Aliya made

        Screenshot 2023-12-10 at 2 27 49 PM

        Fibonacci

        Frontend

        image

        const canvas = document.getElementById('fibCanvas');
        const ctx = canvas.getContext('2d');
        function fibonacciBinet(n) {
            const phi = (1 + Math.sqrt(5)) / 2; // Golden ratio
            const sqrt5 = Math.sqrt(5);
            const fibN = Math.round((Math.pow(phi, n) - Math.pow(1 - phi, n)) / sqrt5);
            return fibN;
        }
        function generateArt() {
            const startTime = performance.now();
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            const method = Math.random(); // Randomly choose a method
            let generationTime;
            if (method < 0.25) {
                displayFibMethod('recursive');
                generateRecursiveArt();
            } else if (method < 0.5) {
                displayFibMethod('Binet formula');
                generateRecursiveArtWithBinet(20);
            } else if (method < 0.75) {
                displayFibMethod('iterative');
                generateIterativeArt();
                generationTime = performance.now() - startTime;
            } else {
                displayFibMethod('matrix');
                generateMatrixArt();
                generationTime = performance.now() - startTime;
            }
            if (!generationTime) {
                generationTime = performance.now() - startTime;
            }
            displayGenerationTime(generationTime);
        }
        function generateRecursiveArtWithBinet(maxIterations) {
            const centerX = canvas.width / 2;
            const centerY = canvas.height / 1;
            recursiveDrawWithBinet(centerX, centerY - 350, 0.5, maxIterations, 0);
        }
        function fibonacciBinet(n) {
            return Math.round(
                (1 / Math.sqrt(5)) *
                (Math.pow((1 + Math.sqrt(5)) / 2, n) - Math.pow((1 - Math.sqrt(5)) / 2, n))
            );
        }
        function recursiveDrawWithBinet(x, y, size, remainingIterations, angle) {
            if (remainingIterations > 0) {
                ctx.beginPath();
                ctx.arc(x, y, size * 3.2, 0, Math.PI * 2);
                ctx.fillStyle = `hsl(${Math.random() * 360}, 70%, 50%)`;// Adjust color based on size and iteration
                ctx.fill();
                const newSize = fibonacciBinet(remainingIterations); // Use Binet formula for size
                const nextX = x + size * 0.05 * Math.cos(angle); // Adjust x-position based on angle
                const nextY = y + size * 0.05 * Math.sin(angle); // Adjust y-position based on angle
                const newAngle = angle + Math.PI / 3; // Increment angle for each iteration
                recursiveDrawWithBinet(nextX, nextY, newSize * 0.3, remainingIterations - 1, newAngle);
            }
        }

        Backend

        Created Fibonacci API with two methods: golden ratio and binet recursive method

        Analysis - Calculations and Measurements

        Vivian:

        F1nnC commented 10 months ago

        Individual Review "FInn" grading "Aliya"

        Individuals Video, Issue(s), Commits(s)

        TheoH32 commented 10 months ago

        Individual Review "Theo Huntalas" grading "Vivian Ni"

        Individuals Video, Issue(s), Commits(s)

        .885/.9 Theo's Notes:

        You had almost everything perfect. Coding wise, you made an amazing project with a art gallery theme that I actually really like. You combined a fundamental lesson of algorithms with a form of creative expression. Even if you didn't make the idea up, the way you executed it was very well done. I like how you combined the backend functionality of likes, pictures, and algorithms. But review wise, you need to brag more. You wrote a lot of good code so brag about it in your video, issues, and review. Very good overall.

        Jyustin commented 10 months ago

        Individual Review Justin Nguyen grading Kevin Du

        Individuals Video, Issue(s), Commits(s)

        F1nnC commented 10 months ago

        Team Review "JTF" grading "ABK"

        Team Review ticket containing key Team and individual contributions