Difference between revisions of "Headband Helper"

From ESE205 Wiki
Jump to navigation Jump to search
m (Protected "Headband Helper" ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite)))
 
(141 intermediate revisions by 2 users not shown)
Line 1: Line 1:
 +
== Links ==
 +
[[Headband_Helper_Log]]
 +
 +
Presentation [https://docs.google.com/presentation/d/1va63ZxhfQByzYhv9sMv3vxhq-qosAvJl_7e99bX9yR8/edit#slide=id.g4f72464c2f_1_10]
 +
 +
GitHub Repository [https://github.com/ESE205/HeadbandHelper]
 +
 +
Accelerometer code [https://github.com/jenfoxbot/ImpactForceMonitor/blob/master/PythonProgram.py]
 +
 +
Final Poster [https://docs.google.com/presentation/d/1YqyF-MSyof1BxPqdG08AN3Ktq9phNsZCDhroIBUUU6o/edit#slide=id.p]
 +
 +
Accelerometer Tutorial [https://classes.engineering.wustl.edu/ese205/core/index.php?title=Accelerometer_%2B_Pi_Zero]
 +
 +
Web Interface [http://ec2-3-14-3-138.us-east-2.compute.amazonaws.com/]
 +
 
== Project Proposal ==
 
== Project Proposal ==
 
===Overview===
 
===Overview===
We hope to construct an accelerometer-based concussion monitoring system that is contained within a headband. In addition, we will create a web interface that allows users to track their impact history. These two pieces (software and hardware) will communicate using Bluetooth.  
+
We hope to construct an accelerometer-based concussion monitoring system using a Raspberry Pi OW that can be contained within a headband. In addition, we will create a web interface that allows users to track their impact history. These two pieces (software and hardware) will communicate using an ad hoc IP network run by another Raspberry Pi.
 +
 
 
=== Team Members ===
 
=== Team Members ===
 
*Jarrod Huther
 
*Jarrod Huther
Line 10: Line 26:
 
=== Objectives ===
 
=== Objectives ===
 
*Create an accelerometer-based concussion monitoring system that can be contained within a headband
 
*Create an accelerometer-based concussion monitoring system that can be contained within a headband
*Create a web interface that allows users to track their impact history which is stored in a database
+
*Create an ad hoc IP network using a master Raspberry Pi to collect data from the headbands
*Ensure that the device and web interface can successfully communicate
+
*Ensure that the master Pi and web interface can successfully communicate so the web interface can display collected data about collisions
  
 
=== Challenges ===
 
=== Challenges ===
 
*We both have limited experience with circuitry
 
*We both have limited experience with circuitry
 
*We both are comfortable working in Java but have never really used any languages beyond Java
 
*We both are comfortable working in Java but have never really used any languages beyond Java
*3
+
*No experience with sensor networks; creating a fully debugged network will be difficult
  
 
=== Budget ===
 
=== Budget ===
*Raspberry Pi 0 (free)
+
*2 accelerometers ($11.95 each, $23.90 total)[https://www.digikey.com/product-detail/en/sparkfun-electronics/SEN-14480/1568-1811-ND/8032538?WT.srch=1&gclid=EAIaIQobChMI066LuLWg4AIVqLSzCh1RlgNEEAQYAyABEgJXT_D_BwE]
*Accelerometer (price?)
+
**Shipping (~$8.00)
*Server/web host - AWS (free)
+
*1 Amp battery & charger (provided- free)
*3D box to contain tracking materials within headband?
+
*Raspberry Pi 0W- headband (provided- free)
 +
*Raspberry Pi- master (provided- free)
 +
*3D box to contain tracking materials within headband (free)
  
=== Materials ===
+
Total Budget: '''$31.90'''
*Raspberry Pi 0
 
*Accelerometer
 
  
 
=== Gantt Chart ===
 
=== Gantt Chart ===
 +
[[File: Gantt_fig.JPG|800px|Gantt Chart]]
 +
 +
== Design and Solutions ==
 +
=== Overview ===
 +
 +
Headband Helper is an accelerometer-based concussion monitoring system that communicates with a web interface that can be used by trainers, coaches, and athletes to assess the impacts a player sustains during a game. In our system, we connected a triple-axle accelerometer to a Raspberry Pi 0W to read acceleration data, then sent this data from the RPi0W to a Raspberry Pi 3 using an ad hoc IP network and HTTP POST requests. The data is then routed from the server on the RPi3 to a MySQL database, and this data is then displayed on a web page hosted on Amazon AWS. This process is outlined in the diagram below:
 +
 +
*[[File: PosterDiagram.png|500px]]
 +
 +
We set out to create our concussion monitoring system by dividing the process into a few different modules. The following are the modules we created, organized by relatedness of the task.
 +
 +
=== Module 1: Wiring Accelerometer to Pi 0 ===
 +
Module 1 of our project involves wiring the H3LIS331DL accelerometer to the Raspberry Pi 0, as well as implementing the code in python that executes the readings. This specific accelerometer is 3-axis, meaning it records data in the x, y, and z-planes, and can take readings up to +-400g's. We chose this board specifically because concussions occur at approximately 95g's, so we needed a sensor that was capable of sensing events of this magnitude and beyond. Once the sensor was wired to the pi, we had to code the pi to use the sensor, as well as transmit the data to the master pi, in order to read the data on another interface. We begin by following the tutorial linked above (which we created for the purposes of this project). The completed system is shown below.
 +
*[[File: Pi_with_acc.jpeg|300px]] [[File: wiring_pi_acc.jpeg|200px]]
 +
Once the system was functioning properly, we used OnShape to design a case that could contain the pi, acceleromter, and power supply, to give it some protection from the more physical impacts it will likely record.
 +
*[[File: PiCase.jpeg|300px]]
 +
Once the pi case was created and the system was placed inside, we could then fit it in a football helmet.
 +
 +
=== Module 2: Filtering the Data ===
 +
Module 2 of our project involves filtering the data being read by the RPi0.
 +
To do so, we first conducted testing to examine what collision data looks like compared to noise and other potential accelerations read by the RPi0. We performed three different rounds of tests: one measuring the acceleration generated when Jarrod performed athletic movements (running, cutting, changes of direction, etc.), one measuring the acceleration generated from dropping the helmet from approximately 1.5 meters off the ground, and one measuring the acceleration generated from hitting the helmet with a hammer (to mimic an impulse). Below are our results from these tests (each value is measured in G's):
 +
*Run/change direction:
 +
**15, 18, 17, 14, 15
 +
**12, 36, 40, 25, 26, 11, 5
 +
*Drop
 +
**14, 6, 16, 20
 +
**3, 17, 20, 7
 +
*Hit with hammer
 +
**3, 3, 114, 14, 4
 +
**2, 2, 2, 148, 46, 22, 9 (helmet rolled away after hit)
 +
*Additionally, we plotted the impact from throwing the helmet into a wall in the chart below, for the purposes of modeling an actual hit in the sport
 +
*[[File: Data_Dissemenation.png|300px]]
 +
From our testing results, we determined athletic movements generate accelerations far below the threshold for concussions, with the max value being 40G's, while dropping the helmet (with no additional mass) creates even smaller accelerations. However, hitting the empty (small mass) helmet with a hammer generated large spikes in the data which imitated an impulse function. We do not want to allow these low-G accelerations and impulses to register as collisions in our database, and we also wanted to ensure that each collision we reported was generated from a unique hit. As such, we determined that we should include three simple filtering functions: a peak detection algorithm, a minimum threshold for the peak point in the hit, and a minimum threshold for the average of the peak and the two adjacent data points on either side of the collision. We decided to use a peak detection algorithm to ensure each hit recorded in the database represented a unique collision rather than sending two (or more) hit events from the same collision. We included the minimum threshold for the peak point in the hit, which we set to 40G's, to avoid overcrowding the database with meaningless data, while we included the minimum threshold for the average to ensure the hit being recorded is not just noise/error read as impulses from the accelerometer.
 +
 +
To implement the simple peak detection algorithm, we created a simple algorithm that follows the logic the pseudocode below:
 +
<source>
 +
if(point > 40 && previouslyOverThreshold = false):
 +
  previousOverThreshold = true
 +
  belowFor = 0
 +
if(point < 40 && previouslyOverThreshold = true):
 +
  belowFor += 1
 +
  if (belowFor = 2):
 +
      previouslyOverThreshold = false
 +
      belowFor = 0
 +
      checkThresholds()
 +
</source>
 +
 +
Then, if checkThresholds() is called, we calculate the average of the two adjacent data points on either side of the collision (five points total). If the average is greater than 30G's and the maximum is greater than 40G's, these values are sent to the RPi3 via the ad hoc IP network (described in Module 3). We chose to report values far below the medically assigned threshold of 95G's because we determined it is better to over-report and provide an option to further filter on the webpage (see Module 4) than it is to under-report and potentially have collision of 85G's (or lower depending on an individual's physiology) that is concussive but not included in the reported results. Futhermore, recent research has increasingly been pointing to sub-concussive hits (around 60-70G's) as a significant contributor to CTE, so we wanted to provide the option to track those hits as well.
 +
 +
=== Module 3: Building a Communication Network And Storing Data===
 +
Module 3 of our project involves building a communication network to allow the data to be transmitted from the RPi0 to the RPi3 and from the RPi3 to the MySQL database. To transmit the filtered data between the RPi0 and the RPi3, we configured an ad hoc IP network on the RPi3 following a tutorial we found online, linked here [https://www.raspberrypi.org/documentation/configuration/wireless/access-point.md]. We then sent collision data from the RPi0 to the RPi3 using an HTTP POST request in the accelerometer code. These POST requests are processed by the RPi3 and the data is then inputted into the database using the following SQL Insert query:
 +
<source>
 +
async function sendToMySql(playerID, timestamp, avg, max) {
 +
let qString = 'INSERT INTO hits (player_id, marked_bad, timestamp, avg_force, max_force) values (?, false, ?, ?, ?)';
 +
await query(qString, [playerID, timestamp, avg, max]);
 +
};
 +
</source>
 +
From here, the data is now stored in the database and ready to be accessed when users interacting with the web interface request it. The database features three tables: one that stores hit/collision data, one that stores player data, and one that stores team data. The following image outlines the database schema:
 +
*[[File: database_schema_2.JPG|300px]]
 +
 +
=== Module 4: Displaying the Data ===
 +
Module 4 of our project involves designing a web page that displays our data in a clear manner so it can easily be analyzed by players, coaches, and trainers. The first step in this process was outlining a simple layout for our user interface so we knew what data we needed to access (which informed the routes we created on the server). This wireframe diagram is included below:
 +
 +
[[File: Hhmainpage.PNG|300px]]
 +
[[File: hhteampage.PNG|300px]]
 +
[[File: hhplayerpage.PNG|300px]]
 +
 +
To implement this design, we first wrote the HTML and CSS for the welcome/search page. Since each different "view" (welcome page, team results, and player results) are all written in the same HTML file, we had to figure out a way to hide and show certain elements depending on which "view" should be displayed. We accomplished this by containing each "view" within a div and then using CSS to tag that div's display attribute as either none or inline-block.
 +
 +
In addition to displaying all the collisions sustained by a player, we also wanted users to be able to filter the results by date and by minimum threshold. To do so, we allowed filter inputs when users are searching by player ID number. These filters then directed to an HTTP request specific for the type of filter (date or minimum G's). This means that rather than filtering the data/results obtained by the normal player ID search, we created a new MySQL query to obtain the filtered data/results.
 +
 +
Once we had implemented the UI, we needed to create our main.js file and link it to the HTML page. The purpose of this file is to provide the interactivity of the UI, meaning that when a user clicked a button to search this file would read the search parameters and execute the API call. We also had to build our API on our express server to provide the response to these requests. In our API, we wrote routes that accessed the data stored in our MySQL database using HTTP GET requests on our server which we called in our main.js file. Our completed data interface website can be found by following this link. [http://ec2-3-14-3-138.us-east-2.compute.amazonaws.com/]
 +
 +
When displaying the results, we decided to use two primary means to communicate our data: a table containing all of the hits, and a chart graphing the magnitude of the hits sustained across time. We chose these two means to display our results because the table provided a clear way to read all of the data about any particular hit, while the chart provided a means to easily visualize a player's hit history.
 +
 +
Below is a screenshot of the chart.
 +
*[[File: Data_Display.png|600px]]
 +
 +
== Results ==
 +
Overall our project was successful with respect to our original goals. We were able to create a system that could accurately detect the impact force sustained, and then forward that data to a server where it was then accessible via web page. All modules worked, from wiring accelerometer to the pi 0, all the way to data display. The only deviation from our original objective was the size of our system, which is currently too bulky to fit into a headband, and is a tight fit into a helmet. However, over half the size is due to the portable battery, so initial miniaturization going forward is not outside the realm of possibility. Our results were a very rough estimate, the critical factor being the way our data was aggregated and filtered. We used a very basic filtering system, which worked for the purposes of our demo and poster session, however if we were to go forward with the project we would implement something more sophisticated than taking an average of 5 "at-risk" data points. One major issue to address in regards to our project's privacy is how the collected data is secured. Since it is medical data, we would need to implement some form of password-encryption protection for the website, to prevent just any individual from accessing the information.
 +
 +
The physical component of our concussion-monitoring system is shown in the image below:
 +
 +
[[File: Complete_accelerometer_HH.jpeg|600px]]
 +
 +
The logic of our system is outlined in the flowchart below:
 +
 +
[[File: FlowchartKatyJarrod.jpeg|800px]]
 +
 +
== Next Steps ==
 +
*Miniaturization: Further development would allow us to miniaturize the system for easier implementation in headbands, helmets, and potentially other carriers.
 +
*Security: design credential-based login to prevent other teams from accessing information, for many different reasons. Primarily privacy, as technically this is medical data and should be restricted to the same securities provided to information such as physicals. Additionally, should have a way of preventing editing of information, to prevent unethical practices such as erasing positive concussion readings.
 +
*Refined Interface: Spend time improving aesthetic of displayed information, not only for obvious reason of looking nicer, but also to be more user-friendly and navigable. For example, some features that would be helpful include:
 +
**clicking on a player returned by the team search returns the player search for that player id
 +
**clicking on a hit expands it to provide the two points before and two points after
 +
**team search returns the most recent collisions sustained by players on that team
 +
  
== Links ==
 
[[Headband_Helper_Log]]
 
  
 
[[Category:Projects]]
 
[[Category:Projects]]
 
[[Category:Spring 2019 Projects]]
 
[[Category:Spring 2019 Projects]]

Latest revision as of 11:47, 2 May 2019

Links

Headband_Helper_Log

Presentation [1]

GitHub Repository [2]

Accelerometer code [3]

Final Poster [4]

Accelerometer Tutorial [5]

Web Interface [6]

Project Proposal

Overview

We hope to construct an accelerometer-based concussion monitoring system using a Raspberry Pi OW that can be contained within a headband. In addition, we will create a web interface that allows users to track their impact history. These two pieces (software and hardware) will communicate using an ad hoc IP network run by another Raspberry Pi.

Team Members

  • Jarrod Huther
  • Katy Mockett
  • TA: Ethan Shry
  • Professor: James Feher

Objectives

  • Create an accelerometer-based concussion monitoring system that can be contained within a headband
  • Create an ad hoc IP network using a master Raspberry Pi to collect data from the headbands
  • Ensure that the master Pi and web interface can successfully communicate so the web interface can display collected data about collisions

Challenges

  • We both have limited experience with circuitry
  • We both are comfortable working in Java but have never really used any languages beyond Java
  • No experience with sensor networks; creating a fully debugged network will be difficult

Budget

  • 2 accelerometers ($11.95 each, $23.90 total)[7]
    • Shipping (~$8.00)
  • 1 Amp battery & charger (provided- free)
  • Raspberry Pi 0W- headband (provided- free)
  • Raspberry Pi- master (provided- free)
  • 3D box to contain tracking materials within headband (free)

Total Budget: $31.90

Gantt Chart

Gantt Chart

Design and Solutions

Overview

Headband Helper is an accelerometer-based concussion monitoring system that communicates with a web interface that can be used by trainers, coaches, and athletes to assess the impacts a player sustains during a game. In our system, we connected a triple-axle accelerometer to a Raspberry Pi 0W to read acceleration data, then sent this data from the RPi0W to a Raspberry Pi 3 using an ad hoc IP network and HTTP POST requests. The data is then routed from the server on the RPi3 to a MySQL database, and this data is then displayed on a web page hosted on Amazon AWS. This process is outlined in the diagram below:

  • PosterDiagram.png

We set out to create our concussion monitoring system by dividing the process into a few different modules. The following are the modules we created, organized by relatedness of the task.

Module 1: Wiring Accelerometer to Pi 0

Module 1 of our project involves wiring the H3LIS331DL accelerometer to the Raspberry Pi 0, as well as implementing the code in python that executes the readings. This specific accelerometer is 3-axis, meaning it records data in the x, y, and z-planes, and can take readings up to +-400g's. We chose this board specifically because concussions occur at approximately 95g's, so we needed a sensor that was capable of sensing events of this magnitude and beyond. Once the sensor was wired to the pi, we had to code the pi to use the sensor, as well as transmit the data to the master pi, in order to read the data on another interface. We begin by following the tutorial linked above (which we created for the purposes of this project). The completed system is shown below.

  • Pi with acc.jpeg Wiring pi acc.jpeg

Once the system was functioning properly, we used OnShape to design a case that could contain the pi, acceleromter, and power supply, to give it some protection from the more physical impacts it will likely record.

  • PiCase.jpeg

Once the pi case was created and the system was placed inside, we could then fit it in a football helmet.

Module 2: Filtering the Data

Module 2 of our project involves filtering the data being read by the RPi0. To do so, we first conducted testing to examine what collision data looks like compared to noise and other potential accelerations read by the RPi0. We performed three different rounds of tests: one measuring the acceleration generated when Jarrod performed athletic movements (running, cutting, changes of direction, etc.), one measuring the acceleration generated from dropping the helmet from approximately 1.5 meters off the ground, and one measuring the acceleration generated from hitting the helmet with a hammer (to mimic an impulse). Below are our results from these tests (each value is measured in G's):

  • Run/change direction:
    • 15, 18, 17, 14, 15
    • 12, 36, 40, 25, 26, 11, 5
  • Drop
    • 14, 6, 16, 20
    • 3, 17, 20, 7
  • Hit with hammer
    • 3, 3, 114, 14, 4
    • 2, 2, 2, 148, 46, 22, 9 (helmet rolled away after hit)
  • Additionally, we plotted the impact from throwing the helmet into a wall in the chart below, for the purposes of modeling an actual hit in the sport
  • Data Dissemenation.png

From our testing results, we determined athletic movements generate accelerations far below the threshold for concussions, with the max value being 40G's, while dropping the helmet (with no additional mass) creates even smaller accelerations. However, hitting the empty (small mass) helmet with a hammer generated large spikes in the data which imitated an impulse function. We do not want to allow these low-G accelerations and impulses to register as collisions in our database, and we also wanted to ensure that each collision we reported was generated from a unique hit. As such, we determined that we should include three simple filtering functions: a peak detection algorithm, a minimum threshold for the peak point in the hit, and a minimum threshold for the average of the peak and the two adjacent data points on either side of the collision. We decided to use a peak detection algorithm to ensure each hit recorded in the database represented a unique collision rather than sending two (or more) hit events from the same collision. We included the minimum threshold for the peak point in the hit, which we set to 40G's, to avoid overcrowding the database with meaningless data, while we included the minimum threshold for the average to ensure the hit being recorded is not just noise/error read as impulses from the accelerometer.

To implement the simple peak detection algorithm, we created a simple algorithm that follows the logic the pseudocode below:

if(point > 40 && previouslyOverThreshold = false):
   previousOverThreshold = true
   belowFor = 0
if(point < 40 && previouslyOverThreshold = true):
   belowFor += 1
   if (belowFor = 2):
      previouslyOverThreshold = false
      belowFor = 0
      checkThresholds()

Then, if checkThresholds() is called, we calculate the average of the two adjacent data points on either side of the collision (five points total). If the average is greater than 30G's and the maximum is greater than 40G's, these values are sent to the RPi3 via the ad hoc IP network (described in Module 3). We chose to report values far below the medically assigned threshold of 95G's because we determined it is better to over-report and provide an option to further filter on the webpage (see Module 4) than it is to under-report and potentially have collision of 85G's (or lower depending on an individual's physiology) that is concussive but not included in the reported results. Futhermore, recent research has increasingly been pointing to sub-concussive hits (around 60-70G's) as a significant contributor to CTE, so we wanted to provide the option to track those hits as well.

Module 3: Building a Communication Network And Storing Data

Module 3 of our project involves building a communication network to allow the data to be transmitted from the RPi0 to the RPi3 and from the RPi3 to the MySQL database. To transmit the filtered data between the RPi0 and the RPi3, we configured an ad hoc IP network on the RPi3 following a tutorial we found online, linked here [8]. We then sent collision data from the RPi0 to the RPi3 using an HTTP POST request in the accelerometer code. These POST requests are processed by the RPi3 and the data is then inputted into the database using the following SQL Insert query:

async function sendToMySql(playerID, timestamp, avg, max) {
	let qString = 'INSERT INTO hits (player_id, marked_bad, timestamp, avg_force, max_force) values (?, false, ?, ?, ?)';
	await query(qString, [playerID, timestamp, avg, max]);
};

From here, the data is now stored in the database and ready to be accessed when users interacting with the web interface request it. The database features three tables: one that stores hit/collision data, one that stores player data, and one that stores team data. The following image outlines the database schema:

  • Database schema 2.JPG

Module 4: Displaying the Data

Module 4 of our project involves designing a web page that displays our data in a clear manner so it can easily be analyzed by players, coaches, and trainers. The first step in this process was outlining a simple layout for our user interface so we knew what data we needed to access (which informed the routes we created on the server). This wireframe diagram is included below:

Hhmainpage.PNG Hhteampage.PNG Hhplayerpage.PNG

To implement this design, we first wrote the HTML and CSS for the welcome/search page. Since each different "view" (welcome page, team results, and player results) are all written in the same HTML file, we had to figure out a way to hide and show certain elements depending on which "view" should be displayed. We accomplished this by containing each "view" within a div and then using CSS to tag that div's display attribute as either none or inline-block.

In addition to displaying all the collisions sustained by a player, we also wanted users to be able to filter the results by date and by minimum threshold. To do so, we allowed filter inputs when users are searching by player ID number. These filters then directed to an HTTP request specific for the type of filter (date or minimum G's). This means that rather than filtering the data/results obtained by the normal player ID search, we created a new MySQL query to obtain the filtered data/results.

Once we had implemented the UI, we needed to create our main.js file and link it to the HTML page. The purpose of this file is to provide the interactivity of the UI, meaning that when a user clicked a button to search this file would read the search parameters and execute the API call. We also had to build our API on our express server to provide the response to these requests. In our API, we wrote routes that accessed the data stored in our MySQL database using HTTP GET requests on our server which we called in our main.js file. Our completed data interface website can be found by following this link. [9]

When displaying the results, we decided to use two primary means to communicate our data: a table containing all of the hits, and a chart graphing the magnitude of the hits sustained across time. We chose these two means to display our results because the table provided a clear way to read all of the data about any particular hit, while the chart provided a means to easily visualize a player's hit history.

Below is a screenshot of the chart.

  • Data Display.png

Results

Overall our project was successful with respect to our original goals. We were able to create a system that could accurately detect the impact force sustained, and then forward that data to a server where it was then accessible via web page. All modules worked, from wiring accelerometer to the pi 0, all the way to data display. The only deviation from our original objective was the size of our system, which is currently too bulky to fit into a headband, and is a tight fit into a helmet. However, over half the size is due to the portable battery, so initial miniaturization going forward is not outside the realm of possibility. Our results were a very rough estimate, the critical factor being the way our data was aggregated and filtered. We used a very basic filtering system, which worked for the purposes of our demo and poster session, however if we were to go forward with the project we would implement something more sophisticated than taking an average of 5 "at-risk" data points. One major issue to address in regards to our project's privacy is how the collected data is secured. Since it is medical data, we would need to implement some form of password-encryption protection for the website, to prevent just any individual from accessing the information.

The physical component of our concussion-monitoring system is shown in the image below:

Complete accelerometer HH.jpeg

The logic of our system is outlined in the flowchart below:

FlowchartKatyJarrod.jpeg

Next Steps

  • Miniaturization: Further development would allow us to miniaturize the system for easier implementation in headbands, helmets, and potentially other carriers.
  • Security: design credential-based login to prevent other teams from accessing information, for many different reasons. Primarily privacy, as technically this is medical data and should be restricted to the same securities provided to information such as physicals. Additionally, should have a way of preventing editing of information, to prevent unethical practices such as erasing positive concussion readings.
  • Refined Interface: Spend time improving aesthetic of displayed information, not only for obvious reason of looking nicer, but also to be more user-friendly and navigable. For example, some features that would be helpful include:
    • clicking on a player returned by the team search returns the player search for that player id
    • clicking on a hit expands it to provide the two points before and two points after
    • team search returns the most recent collisions sustained by players on that team