Comp 110 BYOB: Build Your Own Bracket

In this problem set you'll use data from the 2017 NCAA season to build your own computationally generated bracket! It is divided into three parts. First, you'll write your own implementations of the filter, map, and reduce functions, then you'll use those functions to find some statistics about the dataset, and last you'll implement a function that uses the data and your own creativity to predict what team would win in a game, which you'll use to generate your own bracket for the 2017 NCAA basketball season.

Learning Objectives

After completing this problem set, you should:

1. Be able to use the higher-order function filter to narrow a collection of data down based on some predicate criteria

2. Be able to use the higher-order function map to process a collection of data by applying a transform function to each element

3. Be able to use the higher-order function reduce to compute a value by processing a collection and accumulating a result (i.e., with a list of numbers, find the sum or maximum)

4. Have practice writing function literals in conjunction with higher-order functions. This will be required for part three of the problem set. 

This problem set specifies the required functions you must write and export, however, you are free to arrive at computing the results any way you would like. We strongly encourage you to make as much use applying filter/map/reduce as possible and to reuse the early functions you write wherever possible to avoid redundancy in your code.

Part 0. Starting the Dev Environment

As with in lecture, begin by opening up VSCode, ensuring your project is still open, and then running the following two commands in the VSCode Integrated Terminal:

  1. npm run pull
  2. npm start

The first command "pulls" the latest files needed for COMP110 into your repo, if any. The second command starts the development environment and will open your web browser to the local server. 

The scaffolding of this problem set is already setup for you in the ps05-byob folder. You will be working in the ps05-byob/stats-app.ts file.

Begin by filling in your name and ONYEN in the respective fields of the honor code portion of the file.

0.1 Imports

We have already imported the functions you'll need for this project, but it's worth thinking through what is imported for you. 

We have also already included the Player class and the three functional interfaces needed for filter/map/reduce. Make sure to read over this to understand the included code. 

0.2 Data

The data for this project is every men's basketball team player's stat lines from each game the 2017 season. The file our data resides in is the data/NCAA-data.csv file - select this file when you run your app.

Each player has the following properties:

  1. team - Basketball team of specific player
  2. season - Year of season (all will be 2017)
  3. conference - Conference the player's team is in (ex. ACC, SEC, etc.)
  4. winPercent - Percentage of wins for that player's team from the specific season
  5. avgPoints Average points per game of the player's team of that specific season. 
  6. player - Name of the player
  7. gamesPlayed - Number of games player played of that specific season 
  8. gamesStarted - Number of games player started the game in of that specific season
  9. avgMinutesPerGame - Average number of minutes the player had per game of that specific season
  10. fieldGoalPercent - Percentage of total shots made (not including free throws)
  11. twoPointPercent - Percentage of 2 point shots made
  12. threePointPercent - Percentage of 3 point shots made
  13. freeThrowPercent - Percentage of free throw shots made
  14. averageReboundsPerGame - Average number of rebounds the player had per game of that specific season
  15. averageAssistsPerGame - Average number of assists the player had per game of that specific season
  16. averageStealsPerGame- Average number of blocks the player had per game of that specific season
  17. averageBlocksPerGame - Average number of blocks the player had per game of that specific season
  18. avgTurnoversPerGame - Average number of turnovers the player had per game of that specific season 
  19. avgPointsPerGame- Average number of points the player had per game of that specific season. 
  20. coach - Name of coach of the team of the player of that specific season.

Part 1. Creating Filter/Map/Reduce

Be sure to export all of your functions!

1.1 Filter

You have already written filter recursively in class. Now, we want you to write it iteratively with a for-loop or while-loop. This filter function, takes in a generic array and a generic predicate and returns a generic array. Make sure to test this well because you will be using it throughout the problem set!

1.2 Map

As with filter, you have written map recursively too. Now, write map with a for-loop or while loop. This map function takes in a generic array and a generic transformer and returns a generic array. Remember that the generic array returned is a different type than the generic array used as a parameter. Make sure to test this well because you will be using it throughout the problem set! 

1.3 Reduce 

The last function for this section is reduce. As with the other two functions, we are asking you to implement this function with a for-loop or a while loop. This reduce function should take in a generic array, a reducer, and a generic memo and return the type of the generic memo.

For the rest of the problem set, you will use these three functions on the dataset. Use these that you implemented, not the built in ones.

Part 2. Build a Statistics Report

2.0 The Goal Report

The end goal for this section is to generate a report that should look similar to the one below. To do this you'll first have to implement the functions below, use them with filter, map, and reduce, and print the results.

1. Season MVP:
<player properties>
2. Average number of points scored by all players: ##
3. Total number of players who scored above the average number of points: ##

Note that the #'s will be replaced with the actual computed numbers. 

Also note, when the autograder is posted it will test using a different data set than this season's to ensure your computations work for any dataset.

Be sure to export all of your functions!

2.1 reduceByMaxPoints

This is a reducer function that takes in two player objects and returns the player with the higher avgPointsPerGame property

2.2 getSeasonMVP

Given an array of Player objects, return the player who scored the most points per game (Player property avgPointsPerGame). Do not worry about ties. (Hint: use your reduceByMaxPoints function.)

Print the result - Finally, call the getSeasonMVP function in main and print the result (this will be a table with the player's properties).

2.3 mapToPoints

This transform function takes in a player object and returns that player's avgPointsPerGame property.

2.4 sum

This reducer function takes in two numbers and returns the sum of those numbers

2.5 avgTotalPoints

Given an array of Player objects, return the average points scored in a single game from all of the players in the data set (Player property avgPointsPerGame). (Hint: use mapToPoints and sum along with map and reduce. Remember that average is sum / count)

Print the result - call the avgTotalPoints function in main and print the result.

2.6 aboveAvgPoints

This predicate function should return true if the player's avgPointsPerGame property is greater than the average for the whole dataset, and false otherwise. It's fine to hard-code in the literal number value that you found when you printed it in 2.5.

(Hacker edition challenge once you have submitted for full credit: think about how you could do this without hard-coding the average value)

2.7 numAboveAvgPoints

Given an array of Player objects, return the total number of players who scored above the average total points. 

Print the result - call the numAboveAvgPoints function in main and print the result.

2.8 Print Report

Make sure the report you've generated by printing these stats looks similar to the example report above. 

Be sure to export all of your functions!

Part 3. Creating Your Bracket

Be sure to export all of your functions!

3.1 playerScorer 

Given a single player object, return a point value that corresponds to that player. This point value is created by you. You can use whatever player properties you want to determine how many points each player should get. Be creative and don't hard-code a return value (your function should return different scores for different players).

3.2 winner

Given two team names and an array of Player objects (our full dataset), return the team predicted to win. Calculate the team predicted to win by summing the player scores (as calculated by playerScorer) for each player on the team, and returning the team name with the greater player score sum. The team names are strings, and each Player object has a "team" property. If there is a tie, the winner should be the first team used as an argument. Solutions that hard-code north-carolina-chapel-hill to always win will be acccepted :) (This is a joke, do not hard-code)

Winner requires the use of inline functions to filter the data. Please see below for an example of an inline function. 

You must declare the type in your anonymous function (as in the example below).

let fruitBasket = ["banana", "apple", "banana", "orange"];
let onlyBananas = filter(fruitBasket, (fruit: string)  => fruit === "banana");

3.3 Generate your bracket!

In main, call the imported makeBracket function, passing in your winner function and the data from the csv, to see what bracket your playerScorer and winner functions generate! (You don't have to print the result, just call the function)

Be sure to export all of your functions!