Node version: 18.17.0
After cloning:
chmod +x setup.sh
./setup.sh
cd backend
npm start
(Use sudo at the beginning if you are running into permission issues)
Frontend-Open a new terminal window and run the following from the inside /EventualFinalRound:
npm start
Update-Fixed this -->(Minor Bug Alert) On the pricing page, you have to click the submit button 3 times before the stike line is visible, working on fixing this
When working on this I think I spent a couple hours in the evening of 7/17- I am on PST- Created all components, API endpoints, input validation and linking the front-end to the backend
Finished it the morning of 7/18- this was mainly fixing routing, session state, and documentation
I used react form validation to make sure inputs were valid, and then used bcrypt on the server side to hash the passwords before inserting them into the DB For Signup, I made the email as the identifier, so no two users can have the same email
This was the most tedious aspect of building this, as react-router-dom has a bunch of changes between v5 and v6 that I had to deal with
I used an AuthProvider object which leverages the useContext hook in react, this object uses localStorage to keep track of a users logged in state. Since we use persistent storage, even when the page is exited or refreshed, whatever state the user was in before(logged in or not) is kept the same.
Routing was done using the useHistory library from react-router, I also created a Routes page which acts as the entry point to the application and keeps track of which component each url should navigate to
I have separate components for the Login, Signup, Landing page, and the pricing tool page- Since the only stateful thing that we need to keep track of is whether or not the user is logged in, we can pass our AuthContext object to them to make sure that only logged in users can access the pricing page.
Each component has its own styling object, this just helped me with managing minor changes as I worked through it
Based on what scenario the user selected, I used the filestream library and csv-parser to pull in the correct sea level data. The csvs for this project are located in public/csvs/
These csvs are pulled in at the time of payout calculation, and the logic is all handled in the backend so only one request needs to be made from the frontend.
When the user is trying to input values, whether or not each of them are valid is updated as the value in the form field changes. This makes for a much more responsive UI. React has a handleChange method that can be called whenever a change is detected in an input field.
Once the payouts have been calculated, the frontend pulls in the data returned from the API. I used the useState hook to mount all the information before the component is rendered
The chart is generated using chart.js- and I used the data from the relevant csv to create the labels for the x-axis
The first blocker I faced was setting up babel so I could use ES6 features such as import statements.These are not automatically available within express.js APIs
Solution: Installing babel, creating a .babelrc file, and modifying package.json so the start script was correct
The second largest blocker that I faced was react routing, which took the majority of time
Solution: Literally just removing the React.StrictMode tags (This took a while to find the right github issue that had a fix, kind of hacky but got the job done)
- URL:
/register
- Method: POST
- Parameters:
firstName
(string, required): User's first namelastName
(string, required): User's last nameemail
(string, required): User's email addresspassword
(string, required): User's passwordorganization
(string, optional): User's organization
- Response Codes:
- 201: User registered successfully
- 400: User with this email already exists
- 500: Server error
- URL:
/login
- Method: POST
- Parameters:
email
(string, required): User's email addresspassword
(string, required): User's password
- Response Codes:
- 200: Login successful
- 401: Invalid credentials
- 404: User not found
- 500: Server error
- URL:
/getSeaLevels/:scenarioName
- Method: GET
- Parameters:
scenarioName
(string, required): Name of the sea level rise scenario
- Response Codes:
- 200: Returns JSON array of sea level data
- 500: Error reading CSV file
- URL:
/calculateExpectedTotalPayout
- Method: GET
- Query Parameters:
scenarioName
(string, required): Name of the sea level rise scenarionotional
(number, required): Notional amountoriginDate
(string, required): Origin date in format "MM/DD/YY"termLength
(number, required): Term length in yearsstrikePercentage
(number, required): Strike percentage
- Response Codes:
- 200: Returns JSON object with calculated premium, total payout, and scenario data
- 500: Error calculating expected total payout
The calculatePremium
function is used to compute the annual premium and total payout based on sea level rise scenarios.
- It filters the scenario data to include only the relevant period based on the start date and term length.
- For each month in the relevant period, it calculates a payout if the sea level exceeds the strike percentage using the maximum of 0 and the amount that sea level exceeds strike.
- The total payout is the sum of all monthly payouts, I used the map reduce function to aggregate these amounts.
- The annual premium is calculated by dividing the total payout by the term length and applying a 3% annual increase.
The function returns an object containing the annual premium, total payout, and the scenario data used in the calculation.