diff --git a/css/styles.css b/css/styles.css
new file mode 100644
index 0000000..1530824
--- /dev/null
+++ b/css/styles.css
@@ -0,0 +1,351 @@
+* {
+ box-sizing: border-box;
+}
+
+html, body {
+ margin: 0;
+ font-family: Poppins, sans-serif;
+ color: #1f1f1f;
+}
+
+.header {
+ display: grid;
+ grid-template-columns: auto 1fr auto;
+ align-items: center;
+ background-color: #1f1f1f;
+}
+
+.header-left img {
+ padding: 1rem;
+ width: 5rem;
+ height: auto;
+}
+
+.header-middle {
+ display: flex;
+ gap: 1rem;
+ align-items: center;
+}
+
+#athlete-position select,
+#name-input,
+#status-input,
+#number-input {
+ font-size: 2.5rem;
+ font-weight: 100;
+ color: white;
+ border: none;
+ background-color: transparent;
+ height: 3rem;
+ line-height: 3rem;
+ display: flex;
+ align-items: center;
+}
+
+#athlete-position select {
+ border: none;
+}
+
+#athlete-position select:hover,
+#name-input:hover,
+#status-input:hover,
+#number-input:hover {
+ color: #980000;
+}
+
+.header-right {
+ display: flex;
+ align-items: center;
+ gap: 1rem;
+}
+
+#load-athletes,
+#download-pdf {
+ background-color: transparent;
+ color: white;
+ border: none;
+ border-radius: 4px;
+ padding: 0.5rem 1rem;
+ font-size: 1rem;
+ font-weight: 400;
+ cursor: pointer;
+ transition: background-color 0.2s ease;
+}
+
+#load-athletes:hover,
+#download-pdf:hover {
+ color: #980000;
+}
+
+#save-athlete,
+#clear-all {
+ padding: 0.5rem 1rem;
+ font-family: Poppins, sans-serif;
+ font-size: 0.75rem;
+ font-weight: 400;
+ color: white;
+ background-color: #011f5b;
+ border: none;
+ border-radius: 0.5rem;
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
+ cursor: pointer;
+}
+
+#save-athlete:hover,
+#clear-all:hover {
+ background-color: #023b87;
+ box-shadow: 0 6px 8px rgba(0, 0, 0, 0.15);
+}
+
+#save-athlete:active,
+#clear-all:active {
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
+ background-color: #001940;
+}
+
+
+/* Dropdown Menu */
+#dropdown-container {
+ position: relative;
+}
+
+.dropdown-menu {
+ position: absolute;
+ top: 100%;
+ left: 0;
+ background-color: #fff;
+ border: 1px solid #ccc;
+ border-radius: 4px;
+ list-style: none;
+ margin: 0;
+ padding: 0.5rem 0;
+ min-width: 200px;
+ max-height: 300px;
+ overflow-y: auto;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+ z-index: 1000;
+ display: none;
+}
+
+.dropdown-menu li {
+ padding: 0.5rem 1rem;
+ cursor: pointer;
+ transition: background-color 0.2s ease;
+}
+
+.dropdown-menu li:hover {
+ background-color: #f0f0f0;
+}
+
+.hidden {
+ display: none;
+}
+
+.visible {
+ display: block;
+}
+
+fieldset > * {
+ margin-bottom: 0.5rem;
+}
+
+.benchmark-page {
+ padding: 1rem;
+ display: grid;
+ grid-template-columns: repeat(6, 1fr);
+}
+
+
+fieldset {
+ border-color: transparent;
+}
+
+ul {
+ font-family: Lato, sans-serif;
+ list-style-type: none;
+ padding-left: 0;
+ font-weight: 300;
+ font-size: 0.9rem;
+}
+
+li {
+ display: flex;
+ margin-bottom: 0.5rem;
+ justify-content: space-between;
+}
+
+label {
+ display: flex;
+ flex-direction: row;
+}
+
+.benchmark-menu input {
+ font-family: Lato, sans-serif;
+ border-color: transparent;
+ width: 1rem;
+ font-size: 0.9rem;
+ background-color: #f8f8f8;
+ border-radius: 0.35em;
+ font-weight: 200;
+ color: #4d4d57;
+}
+
+#coach-notes {
+ width: 15vw;
+ display: block;
+ text-align: left;
+ padding: 0.5rem;
+ overflow-wrap: break-word;
+ word-wrap: break-word;
+ overflow-y: auto;
+ resize: vertical;
+ border-color: rgb(160, 159, 159, 0.3);
+ color: gray;
+ border-width: 1px;
+ border-radius: 0.35em;
+}
+
+.input-wrapper {
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-end;
+ width: 40%;
+}
+
+input[type="number"] {
+ width: 40%;
+ appearance: textfield;
+ text-align: center;
+}
+
+.unit {
+ font-family: Lato, sans-serif;
+ pointer-events: none;
+ align-content: center;
+ opacity: 0.5;
+ padding-left: 0.25rem;
+ color: #a2a2a2;
+}
+
+.benchmark-chart-area {
+ display: grid;
+ grid-column: 2 / 7;
+ grid-template-columns: repeat(3, 1fr);
+ grid-template-rows: repeat(2, 1fr);
+ gap: 2rem;
+ height: 80vh;
+}
+
+.pct-chart {
+ display: flex;
+ flex-direction: column;
+ background-color: white;
+ border-radius: 1rem;
+ box-shadow: 0 0 1rem rgba(7, 9, 173, 0.1);
+
+}
+
+.stat-category-label, label[for="coach-notes"] {
+ font-size: 0.75rem;
+ font-weight: 600;
+ margin-top: 1em;
+ text-transform: uppercase;
+}
+
+input[type="number"]:invalid {
+ color: salmon;
+}
+
+input[type="text"] {
+ border-color: transparent;
+}
+
+.header input[type="text"] {
+ border-color: transparent;
+ box-sizing: content-box;
+ width: auto;
+}
+
+/* Billboard Charts */
+
+.bb text.bb-title {
+ font-size: 0.75rem;
+ font-family: Poppins, sans-serif;
+ font-weight: 600;
+ margin-top: 1em;
+ text-transform: uppercase;
+}
+
+.bb-text {
+ font-family: Poppins, sans-serif;
+ font-size: 1rem;
+ font-weight: 300;
+}
+
+.bb tspan {
+ font-family: Lato, sans-serif;
+ fill: #011f5b;
+ font-weight: 500;
+ font-size: 0.75rem;
+}
+
+.bb-axis.bb-axis-x path.domain {
+ opacity: 0;
+}
+
+div#radar-chart .bb-level > text:nth-child(2),
+div#radar-chart .bb-text{
+ font-size: 0.75rem;
+ font-weight: 100;
+}
+
+div#radar-chart .bb-axis-0 > text:nth-child(2),
+div#radar-chart .bb-axis-1 > text:nth-child(2),
+div#radar-chart .bb-axis-2 > text:nth-child(2),
+div#radar-chart .bb-axis-3 > text:nth-child(2) {
+ font-size: 0.75rem;
+ font-family: Poppins, sans-serif;
+ font-weight: 600;
+ text-transform: uppercase;
+}
+
+
+/* Billboard.js Tooltip Styling */
+.bb-tooltip {
+ padding: 10px;
+ font-family: Poppins, sans-serif;
+ font-size: 14px;
+ color: #011f5b;
+ background: #fff;
+ border: 1px solid #ccc;
+ border-radius: 8px;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+
+.bb-tooltip .tooltip-title {
+ font-size: 0.75rem;
+ font-weight: 600;
+ margin-bottom: 0.5rem;
+ text-align: center;
+ text-transform: uppercase;
+}
+
+.bb-tooltip .tooltip-row {
+ display: flex;
+ justify-content: left;
+ margin-bottom: 4px;
+}
+
+.bb-tooltip .tooltip-row:last-child {
+ margin-bottom: 0;
+}
+
+.bb-tooltip .tooltip-label {
+ font-family: Lato, sans-serif;
+ font-weight: 400;
+}
+
+.bb-tooltip .tooltip-value {
+ font-family: Lato, sans-serif;
+ text-align: right;
+}
diff --git a/data/bulk uploads/jr_day_2025.json b/data/bulk uploads/jr_day_2025.json
new file mode 100644
index 0000000..6c27980
--- /dev/null
+++ b/data/bulk uploads/jr_day_2025.json
@@ -0,0 +1,8 @@
+{
+ "Name": ["cole aquino", "steven armbruster", "jake blum", "collier book", "chase calarco", "quincy capogna", "nathan cichy", "joey cleaver", "quinn connors", "benjamin coryea", "rocco costello", "arthur cutler", "joseph devane jr", "jimmy dewire", "george duggins", "austin engroff", "kai erwin", "johnny garcia", "mason geyer", "anthony giorgi", "william gorman", "drew hardwick", "cooper harris", "philip hatfield", "connor hepperlen", "evan honberger", "kyle lucas", "flynn malgieri", "preston mcdaniel", "jaden mcduffie", "mikey mcmahon", "kellen murray", "xavier myers", "jake namnun", "keegan parker", "matthew plumb", "aidan reid", "jaden richberg", "brennan ringer", "michael sclafani", "henry shoemaker", "owen stecker", "noah sur", "trey tallmadge", "jack thomas", "nasir thompson", "finley torrico", "nahmir tucker", "adam vessel", "sam waldman", "caden ward", "bryce werner", "fode wilks", "bo wolford", "joseph zamot"],
+ "Height": [67, 70, 72, 76, 70, 74, 72, 72, 76, 67, 72, 72, 71, 73, 74, 71, 74, 68, 74, 75, 74, 76, 73, 78, 75, 67, 75, 73, 72, 73, 75, 68, 74, 72, 78, 75, 76, 71, 74, 72, 76, 71, "NA", 71, 74, 77, 74, 67, 73, 72, 74, 72, 73, 72, 67],
+ "Weight": [179, 188, 192, 261, 202, 194, 182, 231, 226, 177, "NA", 241, 229, 283, 197, 201, 236, 196, 280, 213, 233, 224, 297, 310, 222, 137, 264, 330, 212, 154, 295, 180, 191, 285, 242, 232, 228, 241, 219, 186, 194, 196, 178, 200, 177, 254, 261, 215, 162, 207, 219, 188, 160, 312, 222],
+ "Wingspan": [71, 72.5, 72, 79, 76, 72.5, 74.5, 75.5, 77, 71, 75.5, 77.5, 75, 76, 76, 71, 73, 69, 74.5, 73.5, 78, 78, 75.5, 72.5, 74, 67.5, 77, 78, 76, 76, 75, 68, 77, 77, 81.5, 74, 74, 73, 74.5, 76, 75, 73, 72, 72, 70, 75, 77.5, 76, 68, 74.5, 77, 76, 73.5, 73, 75],
+ "Position": ["DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB", "DB"],
+ "Status": ["HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS", "HS"]
+}
diff --git a/data/bulk uploads/latest_tests_2020_2024.json b/data/bulk uploads/latest_tests_2020_2024.json
new file mode 100644
index 0000000..aabeca1
--- /dev/null
+++ b/data/bulk uploads/latest_tests_2020_2024.json
@@ -0,0 +1,23 @@
+{
+ "Name": ["joe basiura", "jc dobis", "travis spreen", "declan vargas", "isaiah malcome", "shane sweitzer", "lewis gibson", "owen goldsberry", "preston norwood", "khalil weathers", "mohammed diakite", "jason mccleod", "malcolm strickland", "prince emili", "matthew mcelroy", "tanner long", "daniel karrash", "chris rankins", "jake gonzalez", "grant ristoff", "henry iloanya", "jake heimlicher", "adam conyer", "ethan zemla", "garrett morris", "jack meehan", "luke hoggard", "ben hoitink", "chase bahr", "devin spencer", "trevor mayberry", "trevor radosevich", "ben gerber", "hugh brady", "trey flowers", "tysen comizio", "ben krimm", "john bergeron", "mike hoffler", "ryan mannelly", "travis wang", "rory starkey", "callum abernethy", "anthony bell", "kobe comizio", "graham gotlieb", "malone howley", "jack iuliano", "griffin jackstadt", "isaiah jordan", "mitzseen joseph", "liam kearney", "jaden key", "jack kosick", "jake ligos", "maurcus mcdaniel", "chandler mcgruder", "shiloh means", "jonathan melvin", "micah morris", "charlie mossy", "jonathan mulatu", "aidan nash", "lawson nash", "logan nash", "jordan niles", "clay petry", "jack plank", "jack purcell", "will seiler", "isaac shabay", "joey slackman", "bennett smith", "kendren smith", "walter soefker", "sterling stokes", "cameron wilson", "gabe wright", "ryan zanelli", "aaron jones", "aaron kruse", "aidan sayin", "albert jang", "alec wills", "alex haight", "bisi owens", "bo sprague", "brady ioannidis", "bryce hall", "bryce myers", "cameron polemeni-hegarty", "carter janki", "christian carter", "christian de villiers", "cj tremble", "cole olsztyn", "cole shannon", "dante barone", "darius beauvoir", "david okechukwu", "david rolands", "davis ellis", "davis greene", "devin malloy", "devin page", "dj brown", "emmanuel deng", "francesco barone", "grant parker", "hunter lay", "jack fairman", "jacob cisneros", "jake bingham", "jake davis", "jake peterson", "jamal bing jr", "james quinnelly", "john quinnelly", "jared richardson", "jayden drayton", "joey holliday", "john lista", "john ruvo iv", "josh narcisse", "joshua casilli", "julian talley", "julien stokes", "justin cayenne", "kadari machen", "kayleb ervin", "liam o'brien", "luke sacchetti", "malachi hosley", "matthew leyes", "max matolcsy", "maxwell freeman", "mike fernicola", "michael zack", "mike fraraccio", "netinho olivieri", "nicholas ostlund", "nick fryhoff", "patrick hawkins", "paul jennings", "raashed hall", "ryan o'connell", "sage webb", "sam carlson", "sam smith", "santiago sturla", "scott dochat", "sean williams jr", "sulayman adeoye", "travis mcfarling", "william bergin", "zach darche", "cadin olsen", "cole spencer"],
+ "Position": ["OL", "OL", "OL", "OL", "RB", "TE", "WR", "WR", "WR", "WR", "DB", "DB", "DB", "DL", "DL", "LB", "SP", "DB", "DB", "DL", "DL", "DL", "LB", "LB", "LB", "LB", "LB", "OL", "OL", "OL", "OL", "OL", "QB", "QB", "RB", "RB", "SP", "SP", "TE", "TE", "TE", "WR", "OL", "DB", "WR", "SP", "WR", "DL", "OL", "LB", "DL", "OL", "DB", "DB", "OL", "WR", "RB", "DB", "LB", "DL", "DL", "RB", "LB", "DB", "DB", "RB", "WR", "DL", "OL", "DL", "RB", "DL", "TE", "DB", "DB", "WR", "OL", "DB", "QB", "RB", "OL", "QB", "SP", "DB", "WR", "WR", "OL", "DL", "DL", "TE", "OL", "DL", "DB", "SP", "DB", "LB", "WR", "TE", "DB", "DB", "OL", "WR", "DL", "DB", "QB", "LB", "DB", "DB", "DB", "DL", "LB", "RB", "OL", "LB", "LB", "RB", "DL", "DL", "WR", "WR", "LB", "LB", "WR", "DB", "WR", "DB", "WR", "TE", "LB", "DB", "QB", "OL", "RB", "SP", "LB", "OL", "OL", "OL", "TE", "OL", "DL", "DL", "TE", "DL", "DL", "LB", "WR", "DL", "SP", "SP", "DL", "RB", "DL", "DL", "OL", "LB", "QB", "QB"],
+ "Number": [66, 61, 64, 68, 33, 12, 9, 11, 18, 6, 6, 17, 16, 78, 48, 13, 94, 2, 26, 90, 52, 15, 10, 54, 7, 27, 35, 69, 75, 71, 61, 58, 5, 3, 8, 40, 99, 45, 82, 92, 42, 7, 56, 21, 82, 93, 19, 48, 63, 36, 47, 59, 1, 22, 50, 14, 32, 25, 3, 98, 91, 21, 38, 2, 5, 24, 80, 19, 73, 17, 26, 97, 49, 4, 33, 17, 66, 37, 10, 16, 51, 9, 80, 6, 11, 7, 55, 94, 40, 15, 77, 90, 27, 97, 8, 33, 25, 85, 21, 28, 65, 3, 96, 4, 6, 36, 30, 29, 9, 92, 23, 20, 62, 43, 14, 22, 95, 6, 17, 12, 24, 44, 19, 16, 87, 7, 13, 84, 2, 32, 2, 75, 1, 45, 15, 67, 58, 54, 44, 74, 50, 18, 86, 10, 93, 41, 4, 42, 91, 95, 76, 5, 88, 99, 72, 53, 8, 10],
+ "Height": [75, 74.5, 75.5, 77, 65, 73.5, 72, 73.5, 74, 71, 73, 71.3, 70, 74, 75, 73, 74, 71.5, 73.6, 75, 74, 76.7, 70.5, 75.3, 71.7, 73, 71.2, 76.5, 74.5, 73.6, 74.1, 75, 73, 73.7, 69, 69, 73.4, 70.7, 74.6, 74.5, 71.5, 72.2, 76.5, 74, 69.5, 71, 75.5, 75, 75.5, 70, 75, 74, 73.5, 74, "NA", 71, "NA", 71, 72, "NA", 76, "NA", 73.5, 69, 69.25, 67, 74.5, 75, 76, 75.5, 67, 76, 77, "NA", 69, 75.5, 75.25, 69.5, 73, 69.7, 76, 74, 74.5, 70, 73.73, 75.5, 75.5, 75.25, 75.75, 75, 74.4, 77, 70, 76, 70.25, 72, 71.7, 74.2, 73, 74, 74.2, 72.25, 75.4, 71, 76, 71, 72.87, 71.6, 71, 73.5, 73.3, 68, 74, 75.75, 74.5, 67.25, 76, 76, 74.1, 68.7, 73.5, 73, 69, 71, 71.7, 68.4, 66.3, 76, 72, 69.6, 72, 75, 69.5, 72.2, 72, 75.25, 75.3, 75.3, 74.75, 76.6, 74.5, 77.25, 77, 76.3, 73.3, 73.5, 71.5, 75.5, 69.2, 75, 75, 69.1, 75.5, 76, 74.5, 72.87, 78, 70.2],
+ "Wingspan": [75, 75, 73, 77, 63, 72, 73, 71, 74, 72, 77, 72, 72, 81, 75, 72, 79, 75.5, 72.8, 77.8, 80.5, 78.5, 72.8, 76.3, 73.1, 73.3, 74.3, 80, 76.3, 73.8, 77.5, 78.1, 74.3, 74.3, 70.5, 71.3, 77.3, 70.3, 80.8, 77.5, 75, 77, "NA", 78, 72.25, 71, 77, 78.75, 77.5, 73, 79, 75.75, 77, 73, "NA", 74, "NA", 77, 73, 73.5, 76, "NA", 72, 72.75, 72.5, 70.5, 76.5, 78, 80.5, 77, 70, 79, 77, "NA", 71.5, 76, 77, 73, 72, 69, 76.75, 75, 77, 75.5, 75, 78, "NA", 77.5, 77.5, 75.5, 71, 77, 71.5, 76, 76, 75, 73, 79, 73, 76, 79, 72.5, 77, 72, 75.5, 74.5, 76.5, 72, 72.5, 76, 71.5, 70.5, 77, 77, 76, 71, "NA", "NA", 80, "NA", 79.5, 73, 70, 75, 72.5, 69.5, 69, 78.5, 74.5, 72, 74, 77.25, 73.5, 73, 75.5, 76, 75, 75, 75, 79.5, 73.5, 78, 77, 79.5, 76.5, 74, 71, 75, 70, 76.5, 78, 73, 81.5, "NA", 77.5, 74, 79.5, 72],
+ "Weight": [295, 280, 270, 289, 174, 225, 181, 191, 196, 184, 193, 185, 182, 271, 241, 230, 191, 203.4, 184.6, 257.2, 252, 239.8, 202.2, 230.2, 223, 200.4, 213.2, 290.4, 295.6, 277, 297, 296.8, 205, 184, 222.2, 184.4, 198.6, 219.6, 242, 235, 217.2, 214, 253, 193, 176, 162, 195, 258.4, 267.8, 218.6, 233.7, 286.6, 189.4, 164.4, "NA", 189.6, 201, 197.2, 239, "NA", 239, "NA", 212.6, 192, 178, 187.2, 202.6, 227.2, 300, 283.8, 195.4, 291.2, 232, "NA", 190, 207.6, 283, 184.8, 195, 213, 295, 212, 201, 179, 191, 217, 263, 237.6, 279, 226, 296, 278, 178.2, 204, 180, 213, 195, 243, 195, 193, 285, 191, 265, 187, 202, 240, 179, 193, 190, 242, 224, 205, 282, 222, 225, 190, 270, 270, 214.3, 170, 200, 215, 179, 189, 185, 179, 179, 240, 212, 186, 196, 301.2, 196, 202, 225, 300.6, 265, "NA", 237, 300, 278.5, 271, 238, 263, 229, 219.3, 190, 262, 185, 195, "NA", 196, 249, "NA", 288, 226, 228.6, 185],
+ "225lb Bench": [22, 14, 20, 3, 17, 7, 9, 7, 4, 9, 1, 8, 8, 21, 14, 15, 4, 8, "NA", 22, 15, 22, 14, 12, 15, 11, 18, 30, "NA", 10, 24, 26, 8, 0, 15, 7, 8, 1, 11, 14, 16, 10, "NA", 10, "NA", 4, 8, 22, 12, 19, 14, 15, "NA", 2, "NA", 6, "NA", 14, 21, "NA", 9, "NA", 19, 13, 7, 19, 4, 16, 16, 16, 14, "NA", 7, "NA", 12, 3, 15, 6, 1, 23, 15, 5, 11, 6, 14, 12, 15, 16, "NA", 7, 28, 25, 5, 1, 10, 9, 6, 7, 8, 2, 15, 9, 15, 9, 2, 19, "NA", 16, 6, 7, 21, 18, 35, 16, 12, 10, "NA", "NA", 19, 15, 5, 15, 7, 3, 8, 15, "NA", 14, 15, 9, 15, 32, 14, 1, 22, 17, 14, 15, 15, 18, 20, 17, "NA", 23, 16, 21, 1, 17, 1, 1, 15, 12, 5, 15, 27, 12, "NA", 3],
+ "Bench": [365, 305, 345, 255, 350, 275, 290, 265, 260, 295, 245, 260, 275, 355, 315, 320, 245, 245, 255, 345, 305, 365, 330, 295, 315, 285, 315, 425, "NA", 310, 395, 405, 280, 205, 335, 270, 285, 235, 295, 305, 315, 295, "NA", 285, 220, 240, 270, 390, 305, 360, 315, 325, "NA", 235, "NA", 260, 255, 310, 385, "NA", 275, "NA", 355, 305, 285, 340, 190, 340, 315, 315, 310, "NA", 260, "NA", 300, 245, 315, 265, 225, 355, 305, 260, 295, 265, 335, 300, "NA", 355, "NA", 275, 395, 345, "NA", 225, 285, 275, 275, 275, 265, 285, 335, 280, 325, 300, 235, 345, 230, 325, 275, 275, 315, 320, 415, 325, 300, 305, 265, 265, 315, 320, 265, "NA", 265, 235, 295, 315, "NA", 275, 325, 285, "NA", 395, 315, 235, 345, 335, 300, "NA", 275, 355, 345, 345, 305, 295, 238, 355, 230, 355, 245, 240, "NA", 285, 265, "NA", 365, 295, "NA", "NA"],
+ "Squat": [625, 365, 405, 365, "NA", 510, 385, 365, "NA", 435, 385, 410, 335, 620, 435, 475, 315, 445, 245, 475, 500, 525, 455, 395, 455, 390, 455, "NA", 515, 365, 515, 515, 425, 250, 475, 405, 365, 315, 360, 445, 415, 385, "NA", 500, 405, 315, 440, 545, 335, 565, 450, 415, "NA", "NA", "NA", 415, 395, 465, 585, 585, 405, "NA", 455, 465, 445, 455, 405, 525, 425, 500, 520, "NA", 365, "NA", 420, 365, "NA", 415, 395, 605, 505, 355, 385, 405, 405, 495, "NA", 455, 595, 455, 525, 465, 445, 335, 415, 435, 405, 405, 405, 375, 475, 375, 415, 445, 355, 475, 335, 425, 405, 345, "NA", 495, 615, 455, 475, 430, 385, 385, 475, "NA", 385, "NA", 365, 405, 455, 485, "NA", "NA", 495, 405, "NA", 545, 475, 325, 500, 545, 505, "NA", "NA", 510, 585, 425, "NA", 455, 425, 500, 440, 455, 395, 335, "NA", 425, 505, "NA", 515, 425, "NA", "NA"],
+ "Vertical Jump": [25.9, 21.1, 17.4, 18, "NA", 29.6, 29.9, 36.3, 29, 33.9, 31.4, 32.8, 34, 38, 29.5, 28.8, 30.2, 31.1, "NA", 27.8, 27.5, 33.1, 32, 30.5, 35, 32.4, 30.9, 30.9, 26.4, "NA", 29.8, 27, 27.1, 27, 33.3, 32.9, 28.9, 21, 27.4, 34.9, "NA", 34, 23, 40, 32.8, 34.9, 38.5, 33.9, 24.2, 35.6, 32.8, 26, 38.6, "NA", 24.2, 33.5, "NA", 37.9, 32.8, 33.6, 30.6, 31.2, 35.9, 33.1, 34.7, 32.7, 30.1, 34.5, 24.1, 31, 38.6, 26.5, 28.1, 36.1, 33.5, 32, 22.5, 34.8, 28, 42.7, 20.5, 25.2, "NA", 35.7, 36.4, 38.7, "NA", 32.2, 28.3, 30.1, "NA", 28.9, 34.5, 26.3, 30.4, 27.3, 31.1, 25.8, 31.6, 27.3, 23.2, 34.7, 23.8, 29.7, 29.3, 29.3, 31.8, 37.1, 31.6, 29.9, "NA", 34.7, 22, 36.3, 31.7, 35.4, 20.3, 20.3, 34.6, "NA", 31.7, "NA", 30.6, 33.5, 31.5, 34.1, 35, "NA", 31.3, 31.1, "NA", 23.8, 35, 26.3, 32.1, 24.6, "NA", "NA", 25.4, 24.4, 27.6, 24.4, 29.3, 35.2, 36.5, 35, 28, "NA", 26.3, 29.4, "NA", 29.6, 29.6, "NA", 29, 27.6, 25.2, 27.5],
+ "Broad Jump": [87.5, 87.5, 77, 96.5, "NA", 112, 121, 105, 114.5, 121.5, 105, 110.5, 120.5, 116, 99, 114.5, 88.5, 109, "NA", 116, 109, 108, 99, 108, 105, 97, 94, 105, 109, "NA", 102, 100, 112, 103, 117, 106, 116, 98, 112, 109, "NA", 104, "NA", 123.5, 107.25, 109.5, 122, 111.5, 92.5, 109, 106, 95, "NA", "NA", "NA", 112.25, 105, 122, 109.5, 105, 106, "NA", 110, 114, 110, 111.5, "NA", "NA", 96.25, 109, 112.5, "NA", 114.25, "NA", 105, 105.25, "NA", 109, 96.5, 118, 114, 125.5, 115, 118.5, 116, 111.5, "NA", 121, 109.5, 118.5, "NA", 109.5, 111, "NA", 119, 118, 113.5, 109, 113.5, 111, 119, "NA", "NA", 130, 105, "NA", 119, 125.5, 117, 110, "NA", 107, 99, 117, 114, 112.5, 111, 111, 113, "NA", 107, "NA", 112.5, 95, 105.5, 105.5, "NA", "NA", 107, 99.5, "NA", 109, 97, 107, 115, 112, 110.5, "NA", 124, "NA", 101, 114, "NA", 110, 123, "NA", 111, 105, 103, 105, "NA", 107, 112.5, "NA", 103, 118.5, 100.5, 102],
+ "10Y Sprint": [1.74, 1.7, 1.91, 1.93, "NA", 1.64, 1.64, 1.62, "NA", 1.55, 1.65, 1.57, "NA", 1.52, 1.58, 1.7, 1.65, 1.7, "NA", 1.81, 1.85, 1.79, 1.6, 1.82, 1.54, 1.56, 1.77, 1.86, 2.01, "NA", 1.75, 1.71, 1.59, 1.81, 1.6, 1.53, 1.78, 1.91, 1.65, 1.62, "NA", 1.68, 1.6, 1.49, 1.57, 1.58, 1.48, 1.59, 1.67, 1.55, 1.55, 1.78, 1.45, "NA", 1.65, 1.52, 1.61, 1.51, 1.6, 1.72, 1.61, 1.56, 1.44, 1.53, 1.53, 1.74, 1.57, 1.9, 1.78, 1.62, 1.58, 1.66, 1.7, 1.65, 1.6, 1.57, 1.91, 1.54, 1.63, 1.64, 1.8, 1.68, 1.64, 1.49, 1.68, 1.71, "NA", 1.68, 1.74, 1.66, "NA", 1.77, 1.64, 1.71, 1.74, 1.71, 1.68, 1.76, 1.66, 1.69, 1.74, 1.57, 1.84, 1.76, 1.62, 1.85, 1.7, 1.77, 1.63, 1.75, "NA", 1.7, 1.76, 1.64, 1.6, 1.68, 1.87, 1.87, 1.66, "NA", 1.64, "NA", 1.59, 1.64, 1.76, 1.56, 1.7, "NA", 1.66, 1.66, "NA", 1.85, 1.59, 1.78, 1.6, 1.97, 1.86, "NA", 1.68, 1.83, 1.78, 1.75, "NA", 1.63, 1.74, 1.6, 1.63, 1.73, 1.72, 1.82, "NA", 1.6, 1.64, "NA", 1.77, 1.72, 1.7, 1.66],
+ "Hang Clean": ["NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", 300, 245, 185, 255, 295, 225, 245, 245, 225, "NA", "NA", "NA", 225, "NA", 300, 275, "NA", 280, "NA", 265, 245, 265, 235, 225, 265, 255, 335, 245, "NA", 245, "NA", 300, 245, "NA", 255, 215, "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA"],
+ "L Drill": ["NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", 7.16, 7.53, 7.12, 6.87, 7.16, 7.96, 7.47, 7.69, 8.28, "NA", "NA", "NA", 7.34, 7.68, 7.1, 7.38, 7.97, 7.32, "NA", 7.29, 7.25, 7.47, 7.03, "NA", "NA", 8.12, 7.65, 7.84, "NA", 7.38, "NA", 7, 7, "NA", 7.4, 7.5, 7.18, 7.98, 6.92, 7.35, 7.04, 6.95, 6.79, "NA", 7.48, 7.39, 7.3, "NA", 7.36, 7.27, 7.64, 7.15, "NA", 7.57, 8.14, 7.25, 7.08, 7.78, 6.92, 7.13, 7.02, 7.27, 7.39, 7.06, 7.54, 6.87, 7.51, "NA", 7.34, 7.59, 7.17, 7.01, 7.49, 7.5, 7.5, 7.1, "NA", "NA", "NA", 6.97, 6.84, 6.98, 7.09, 7.21, "NA", 7.16, 7.16, "NA", 7.61, 7.41, 7.71, 7.43, 8.07, 7.97, "NA", 7.33, "NA", 7.51, 7.77, 7.15, 7.32, 7.49, 7.33, 6.91, 7.37, 7.44, 7.27, "NA", 7.01, 7.22, "NA", 8.16, 7.4, 7.35, 7.01],
+ "Pro Agility": ["NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", 4.5, 4.39, 4.55, 4.25, 4.28, 5.22, 4.55, 4.63, 5.19, "NA", "NA", "NA", 4.31, 4.49, 4.03, 4.58, 4.95, 4.63, "NA", 4.48, 4.59, 4.49, 4.25, "NA", "NA", 4.82, 4.79, 4.25, "NA", 4.64, "NA", 4.5, 4.49, "NA", 4.71, 4.87, 4.39, 5.03, 4.55, 4.46, 4.55, 4.38, 4.42, "NA", 4.66, 4.93, 4.76, "NA", 4.7, 4.6, 5.01, 4.6, 4.55, 4.78, 5.1, 4.72, 4.67, 4.99, 4.43, 4.84, "NA", 4.7, 4.82, 4.53, 4.63, 4.54, 4.87, 4.63, 4.86, 4.82, 4.85, 4.54, 4.53, 4.97, 4.97, 4.29, "NA", 4.76, "NA", 4.66, 4.5, 4.53, 4.74, 4.65, "NA", 4.56, 4.58, "NA", 5.05, 4.8, 4.77, 4.49, 4.84, 5.06, "NA", 4.79, "NA", 4.83, 5.13, 4.68, 4.67, 4.66, 4.77, 4.46, "NA", 4.79, 4.67, "NA", 4.66, 4.76, "NA", 4.8, 4.63, 4.83, 4.55],
+ "Power Clean": ["NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", 315, 255, 225, 270, 255, 275, 295, "NA", 305, "NA", 275, 295, 295, 265, 225, 235, 225, 275, 275, 225, 255, 245, 255, 325, 265, 225, 300, 205, 305, 225, 260, "NA", 295, 280, 265, 285, 275, "NA", "NA", 315, "NA", 255, "NA", 225, 235, 275, 285, "NA", "NA", 275, 245, "NA", 315, 275, 215, 315, 305, 285, "NA", "NA", 245, 285, 275, 265, 305, 275, 305, 235, 305, 195, 240, "NA", 235, 285, "NA", 305, 265, "NA", "NA"],
+ "Flying 10": ["NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", 1.02, 1.19, 1.06, 1.07, 1.04, 1, 1.02, "NA", 1.1, 1.09, 1.06, "NA", 1.04, 1.03, 1.1, 1.04, 1, 1.05, 1.07, 1, 1.09, 1.19, 1.03, 1.21, 1, 1.03, 1.06, 1.08, 1.03, 1.02, 1.09, "NA", 1.04, 1.13, 1.03, 1, 1.03, 1.2, 1.2, 0.98, "NA", 1.03, "NA", 0.95, 1, 1.08, 1.01, 0.97, "NA", 1.05, 1.1, "NA", 1.27, 1.01, 1.15, 1, 1.25, 1.21, "NA", 1.1, 1.16, 1.13, 1.16, "NA", 1.04, 1.08, 1.03, 1.05, 1.15, 1.08, 1.05, "NA", 1, 1.05, "NA", 1.19, 1.1, 1.07, 1.04],
+ "60Y Shuttle": ["NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", 12.5, 13.62, 12.72, 12.66, 12.22, 12.12, 11.81, "NA", 12.62, 13.09, 12.94, "NA", 13.06, 12.56, 14.44, 12.59, 12.63, 13.47, 13.38, 12.72, 12.69, 14.03, 12.27, 13.41, 12.09, 12.6, 12.81, 12.43, 12.6, 12.04, 13.25, 12.87, 13.25, 13.21, 11.87, 12.25, 12.7, 13.79, 13.79, 12.53, "NA", 12.97, "NA", 12.6, 12.44, 12.09, 12, 12.38, "NA", 12.35, 12.31, "NA", 14.47, 12.6, 13.5, 12.97, 13.38, 13.9, "NA", 13.34, "NA", 13.82, 13.79, 12.75, 12.47, 13.09, 12.85, 12.09, "NA", 12.97, 13.19, "NA", 12.88, 13.06, "NA", 12.97, 12.4, 13.9, 12.56],
+ "Test Year": [2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024],
+ "Grad Year": [2021, 2022, 2021, 2022, 2021, 2021, 2021, 2021, 2021, 2022, 2021, 2021, 2021, 2021, 2021, 2021, 2021, 2022, 2022, 2022, 2023, 2021, 2021, 2022, 2021, 2022, 2022, 2022, 2022, 2024, 2024, 2021, 2022, 2023, 2021, 2022, 2022, 2023, 2022, 2022, 2021, 2021, 2023, 2023, 2024, 2023, 2022, 2022, 2023, 2023, 2022, 2023, 2022, 2024, 2022, 2023, 2023, 2024, 2022, 2022, 2023, 2022, 2023, 2023, 2023, 2023, 2024, 2023, 2022, 2022, 2025, 2023, 2023, 2022, 2023, 2023, 2025, 2023, 2023, 2024, 2026, 2024, 2024, 2025, 2025, 2025, 2024, 2025, 2024, 2024, 2023, 2025, 2026, 2026, 2024, 2026, 2026, 2026, 2026, 2025, 2026, 2024, 2026, 2026, 2026, 2024, 2026, 2025, 2024, 2026, 2024, 2024, 2025, 2025, 2024, 2026, 2025, 2021, 2025, 2026, 2026, 2025, 2025, 2026, 2024, 2024, 2024, 2024, 2025, 2026, 2025, 2026, 2026, 2025, 2024, 2025, 2026, 2026, 2024, 2025, 2024, 2024, 2025, 2024, 2026, 2025, 2025, 2024, 2025, 2025, 2024, 2026, 2024, 2024, 2024, 2026, 2026, 2024],
+ "Status": ["JR", "SO", "JR", "SO", "JR", "JR", "JR", "JR", "JR", "SO", "JR", "JR", "JR", "JR", "JR", "JR", "JR", "SE", "SE", "SE", "JR", "SE", "SE", "SE", "SE", "SE", "SE", "SE", "SE", "SO", "SO", "SE", "SE", "JR", "SE", "SE", "SE", "JR", "SE", "SE", "SE", "SE", "SE", "SE", "JR", "SE", "SE", "SE", "SE", "SE", "SE", "SE", "SE", "JR", "SE", "SE", "SE", "JR", "SE", "SE", "SE", "SE", "SE", "SE", "SE", "SE", "JR", "SE", "SE", "SE", "SO", "SE", "SE", "SE", "SE", "SE", "SO", "SE", "SE", "SE", "SO", "SE", "SE", "JR", "JR", "JR", "SE", "JR", "SE", "SE", "SE", "JR", "SO", "SO", "SE", "SO", "SO", "SO", "SO", "JR", "SO", "SE", "SO", "SO", "SO", "SE", "SO", "JR", "SE", "SO", "SE", "SE", "JR", "JR", "SE", "SO", "JR", "SE", "JR", "SO", "SO", "JR", "JR", "SO", "SE", "SE", "SE", "SE", "JR", "SO", "JR", "SO", "SO", "JR", "SE", "JR", "SO", "SO", "SE", "JR", "SE", "SE", "JR", "SE", "SO", "JR", "JR", "SE", "JR", "JR", "SE", "SO", "SE", "SE", "SE", "SO", "SO", "SE"]
+}
diff --git a/data/stats_2020_2024.json b/data/stats_2020_2024.json
new file mode 100644
index 0000000..26a4927
--- /dev/null
+++ b/data/stats_2020_2024.json
@@ -0,0 +1,182 @@
+{
+ "OL": [
+ {
+ "Height": [76, 75, 76, 74.5, 76, 76.5, 78.5, 76, 77, 75.5, 75.5, 77, 76.5, 76.2, 74.4, 74.5, 73.6, 75.1, 76, 74, 74, 74.1, 75, 74, 76.5, 74.5, 74, 75.25, 75.5, 74, 75.875, 76.5, 74.5, 76, 74.25, 75, 75.5, 75.25, 75.375, 76, 75.5, 74.4, 74.2, 74, 75, 75.25, 75.3, 75.3, 76.6, 74.5],
+ "Wingspan": [75, 75, 75, 75, 75, 78, 81, 75, 78, 73, 73, 77, 80, 78.5, 78.3, 76.3, 73.8, 76.8, 80.5, 78.3, 75.9, 77.5, 78.1, 77, 77.5, 77.5, 76.5, 77.5, 75.75, 76.125, 79, 78.5, 80.5, 78.125, 77, 77, 77, 74.875, 76.75, 71, 79, 77, 77.25, 76, 75, 75, 79.5, 77.5],
+ "Weight": [285, 295, 287, 280, 290, 280, 262, 286, 279, 300, 270, 289, 290.4, 272, 286.4, 295.6, 277, 287.6, 287, 281.4, 263.8, 297, 296.8, 289, 253, 304.2, 275.4, 291.8, 267.8, 286.6, 289.2, 283.6, 299, 300, 271, 303.6, 269.6, 283, 289.8, 295, 263, 296, 285, 282, 301.2, 300.6, 265, 300, 288],
+ "225lb Bench": [17, 22, 16, 14, 23, 20, 16, 11, 11, 24, 20, 3, 30, 13, 23, 10, 14, 16, 14, 13, 24, 26, 22, 25, 31, 15, 12, 15, 12, 16, 16, 14, 30, 16, 15, 12, 15, 15, 28, 15, 35, 32, 17, 14, 15, 18, 27],
+ "Bench": [315, 365, 315, 305, 405, 365, 315, 310, 275, 385, 345, 255, 425, 305, 375, 310, 340, 300, 315, 300, 395, 405, 360, 395, 425, 315, 305, 325, 325, 315, 330, 315, 305, 395, 335, 415, 395, 335, 300, 355, 365],
+ "Squat": [415, 625, 415, 365, 555, 450, 455, 385, 550, 405, 365, 310, 485, 515, 365, 445, 385, 500, 385, 515, 515, 500, 565, 605, 565, 335, 415, 510, 545, 425, 545, 505, 525, 475, 615, 545, 545, 505, 510, 515],
+ "Vertical Jump": [23.6, 25.9, 25.1, 21.1, 26.8, 28.4, 26.3, 23, 23.5, 17.4, 18, 30.9, 24.8, 26.1, 26.4, 22.4, 23.4, 26.1, 24.4, 29.8, 27, 30.8, 23, 30.3, 27.8, 30, 24.2, 26, 22.4, 24.2, 26.5, 25.4, 24.1, 26, 32.4, 30.8, 22.5, 30, 20.5, 23.2, 22, 23.8, 24.6, 24.4, 29],
+ "Broad Jump": [88.5, 87.5, 93.5, 87.5, 96.5, 103.5, 97.5, 95, 88, 77, 96.5, 105, 108, 105, 109, 105, 84, 102, 108, 102, 100, 110, 97.5, 98, 105, 92.5, 95, 90.25, 98, 96.25, 108, 114, 119, 99, 109, 112, 110.5, 103],
+ "10Y Sprint": [1.8, 1.74, 1.65, 1.7, 1.85, 1.63, 1.83, 1.83, 1.81, 1.91, 1.93, 1.86, 1.92, 1.92, 2.01, 2.03, 1.99, 1.78, 1.81, 1.75, 1.71, 1.83, 1.6, 1.68, 1.6, 1.68, 1.67, 1.78, 2.01, 1.65, 1.66, 1.69, 1.78, 1.92, 2.01, 1.62, 1.91, 1.8, 1.74, 1.76, 1.85, 1.97, 1.86, 1.83, 1.77],
+ "Year": [2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024],
+ "Hang Clean": [295, 265, 265, 225, 225, 255, 305, 255, 265],
+ "L Drill": [7.75, 7.91, 8.25, 7.96, 8.28, 7.9, 7.91, 8.12, 7.81, 7.98, 7.78, 7.59, 7.61, 8.07, 7.97, 8.16],
+ "Pro Agility": [4.7, 4.65, 5.04, 5.22, 5.19, 4.78, 5, 4.82, 4.67, 5.03, 4.99, 4.82, 5.05, 4.84, 5.06, 4.8],
+ "Power Clean": [255, 295, 245, 280, 315, 305, 285, 245, 305],
+ "Flying 10": [1.19, 1.19, 1.13, 1.27, 1.25, 1.21, 1.16, 1.19],
+ "60Y Shuttle": [13.62, 14.03, 13.21, 14.47, 13.38, 13.9, 12.97]
+ }
+ ],
+ "QB": [
+ {
+ "Height": [74, 73, 75.5, 76, 73.7, 73, 73.7, 72, 72.5, 72, 77.25, 76, 74, 73, 74, 76, 72, 78, 70.2],
+ "Wingspan": [74, 76, 77, 74, 74.8, 74.3, 74.3, 72.8, 71.5, 73, 79, 76.875, 75, 72, 75, 75.5, 74, 79.5, 72],
+ "Weight": [205, 209, 195, 201, 204.6, 205, 184, 187.4, 194.8, 204.6, 221, 192.6, 201.8, 195, 212, 202, 196, 228.6, 185],
+ "225lb Bench": [6, 12, 0, 4, 2, 8, 0, 7, 6, 3, 3, 1, 5, 2, 15, 3],
+ "Bench": [280, 300, 215, 240, 255, 280, 205, 260, 205, 265, 245, 225, 260, 235],
+ "Squat": [455, 415, 315, 350, 315, 425, 250, 425, 340, 425, 355, 395, 355, 355],
+ "Vertical Jump": [28, 35, 26.5, 27.1, 29, 27.1, 27, 31.5, 26.1, 32.3, 24.3, 35.2, 27, 28, 25.2, 29.3, 25.2, 27.5],
+ "Broad Jump": [114, 99, 102, 103, 113, 112, 103, 116, 110, 108, 104, 96.5, 125.5, 105, 100.5, 102],
+ "10Y Sprint": [1.59, 1.63, 1.78, 1.67, 1.73, 1.59, 1.81, 1.56, 1.81, 1.59, 1.9, 1.68, 1.57, 1.63, 1.68, 1.62, 1.7, 1.66],
+ "Year": [2020, 2020, 2020, 2020, 2022, 2022, 2022, 2022, 2022, 2023, 2023, 2023, 2023, 2023, 2024, 2024, 2024, 2024, 2024],
+ "Hang Clean": [285, 210, 215],
+ "L Drill": [7.09, 7.31, 7.5, 6.92, 7.27, 7.35, 7.01],
+ "Pro Agility": [4.51, 4.53, 4.87, 4.55, 4.7, 4.83, 4.55],
+ "Power Clean": [225, 225],
+ "Flying 10": [1.06, 1.03, 1.07, 1.04],
+ "60Y Shuttle": [12.72, 12.6, 13.9, 12.56]
+ }
+ ],
+ "RB": [
+ {
+ "Height": [70, 70, 65, 72, 71, 68.1, 68, 68.5, 71.3, 67.3, 69, 69, 67.125, 70, 69.125, 69, 67, 67, 69, 69.7, 68, 67.25, 69.5, 69.1],
+ "Wingspan": [68, 69, 63, 72, 67, 68.3, 71.3, 71.8, 73, 71.3, 70.5, 71.3, 70.5, 72.25, 72.625, 69.75, 70.5, 70, 72.5, 69, 70.5, 71, 73.5, 73],
+ "Weight": [185, 215, 174, 205, 197, 212.8, 198.2, 189.8, 207.4, 186.6, 222.2, 184.4, 180.2, 195, 189.6, 208.4, 201, 187.2, 195.4, 186.6, 213, 205, 190, 196, 196],
+ "225lb Bench": [6, 11, 17, 12, 2, 16, 15, 17, 15, 7, 6, 15, 9, 19, 19, 14, 8, 23, 18, 10, 14, 12],
+ "Bench": [255, 315, 350, 300, 245, 345, 315, 340, 335, 270, 310, 340, 255, 340, 310, 355, 320, 305, 315, 285],
+ "Squat": [405, 500, 405, 375, 565, 485, 445, 475, 405, 455, 605, 395, 455, 520, 605, 495, 430, 475, 425],
+ "Vertical Jump": [28.5, 29, 27.9, 29.2, 32.9, 30.9, 29.9, 33.3, 32.9, 35.1, 29, 35.3, 36, 31.2, 32.7, 38.6, 30, 42.7, 34.7, 35.4, 35, 29.6],
+ "Broad Jump": [104, 107, 104, 111, 105, 109, 103, 117, 106, 103.5, 105, 111.5, 112.5, 118, 107, 112.5, 97, 107],
+ "10Y Sprint": [1.53, 1.61, 1.54, 1.59, 1.55, 1.6, 1.57, 1.6, 1.53, 1.47, 1.57, 1.43, 1.61, 1.56, 1.74, 1.58, 1.6, 1.64, 1.7, 1.68, 1.59, 1.6],
+ "Year": [2020, 2020, 2020, 2020, 2020, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2024, 2024, 2024, 2024, 2024],
+ "Hang Clean": [275, 225, 235, 245],
+ "L Drill": [6.25, 7.68, 7.03, 7.84, 7.18, 7.34, 7.49, 7.41, 7.01],
+ "Pro Agility": [4.63, 4.49, 4.25, 4.25, 4.39, 4.86, 4.53, 4.8, 4.66],
+ "Power Clean": [315, 295, 275, 275, 235],
+ "Flying 10": [1.02, 1.04, 1.03, 1.01, 1],
+ "60Y Shuttle": [12.5, 13.25, 12.7, 12.6, 12.88]
+ }
+ ],
+ "TE": [
+ {
+ "Height": [76.5, 75.5, 76, 78, 73.5, 72, 75.3, 76.4, 75.1, 74.4, 75, 74.1, 74.6, 74.5, 75, 71.5, 74, 75, 74.75, 77, 74.7, 77, 75, 74.2, 76, 74.75, 77],
+ "Wingspan": [76, 79, 75, 77, 72, 73, 76, 75.8, 77.1, 75.5, 78.8, 75.3, 80.8, 77.5, 76.3, 75, 78.875, 78.5, 75.5, 78, 76, 77, 75.5, 79, 78.5, 75, 77],
+ "Weight": [235, 235, 241, 225, 228, 226, 224.6, 242.8, 222, 236.8, 241.2, 242, 235, 239, 217.2, 248.6, 249.2, 235.6, 227, 218.8, 232, 226, 243, 240, 237, 238],
+ "225lb Bench": [6, 5, 13, 7, 15, 12, 7, 11, 6, 11, 10, 11, 14, 15, 16, 6, 13, 7, 7, 7, 7, 14, 15],
+ "Bench": [285, 265, 270, 335, 275, 315, 305, 260, 320, 255, 280, 305, 295, 305, 325, 315, 285, 315, 290, 265, 260, 275, 275, 275, 275, 305],
+ "Squat": [375, 315, 385, 405, 510, 425, 405, 345, 455, 405, 385, 360, 445, 425, 415, 385, 425, 365, 455, 405],
+ "Vertical Jump": [27.2, 29.3, 28.6, 29.6, 29.3, 29.1, 28.4, 30.4, 24.8, 25.3, 27.4, 34.9, 30.9, 25.4, 31, 27.6, 30.5, 28.1, 30.1, 25.8, 25.4, 29.3],
+ "Broad Jump": [110, 100, 112, 112, 115.5, 113.5, 100, 122, 102, 110, 112, 109, 116, 99, 108.25, 114.25, 118.5, 109, 124],
+ "10Y Sprint": [1.67, 1.59, 1.76, 1.64, 1.73, 1.61, 1.72, 1.7, 1.68, 1.72, 1.65, 1.62, 1.68, 1.87, 1.51, 1.58, 1.7, 1.66, 1.76, 1.68],
+ "Year": [2020, 2020, 2020, 2020, 2020, 2020, 2020, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2023, 2023, 2023, 2023, 2023, 2023, 2024, 2024, 2024, 2024, 2024],
+ "Hang Clean": [255, 225, 225, 245],
+ "L Drill": [7.62, 7.22, 7.38, 7.3, 8.14, 7.33, 7.15],
+ "Pro Agility": [4.74, 4.72, 4.64, 4.76, 5.1, 4.79, 4.68],
+ "Power Clean": [275, 275, 265],
+ "Flying 10": [1.06, 1.07, 1.1],
+ "60Y Shuttle": [12.94, 13.38, 13.34, 12.75]
+ }
+ ],
+ "WR": [
+ {
+ "Height": [72.5, 72, 73.5, 76, 75, 70, 74, 73, 73, 71, 74.2, 69.3, 72, 71, 66, 74.7, 72.2, 75, 69.5, 68.75, 72.25, 73, 75.5, 71, 75.5, 74.5, 74, 69, 71.875, 75.5, 71.5, 73.73, 75.5, 71.7, 72.25, 74.1, 68.7, 69, 71.7, 66.3, 71.5],
+ "Wingspan": [72, 73, 71, 73, 75, 68, 74, 72, 74, 72, 76, 70.5, 72.8, 72.5, 69.8, 74.5, 77, 74, 72.25, 70.875, 73, 75, 77, 74, 79.5, 76.5, 80.5, 70.125, 73, 76, 71, 75, 78, 73, 72.5, 80, 70, 72.5, 69, 71],
+ "Weight": [196, 181, 191, 198, 187, 194, 196, 186, 208, 184, 202.4, 187, 182, 185.8, 176.4, 195.6, 214, 199, 176, 164, 192.2, 191.8, 195, 189.6, 207.8, 202.6, 215.6, 169.8, 189, 207.6, 179.2, 191, 217, 195, 191, 214.3, 170, 179, 185, 179, 190],
+ "225lb Bench": [7, 9, 7, 10, 0, 10, 4, 8, 5, 9, 0, 6, 5, 10, 3, 11, 10, 16, 8, 6, 6, 4, 12, 7, 3, 3, 14, 12, 6, 9, 19, 15, 7, 8, 1],
+ "Bench": [265, 290, 265, 275, 220, 300, 260, 265, 265, 295, 195, 225, 260, 295, 245, 295, 235, 220, 275, 325, 270, 260, 265, 190, 285, 245, 225, 335, 300, 275, 280, 315, 320, 265, 295, 230],
+ "Squat": [405, 385, 365, 345, 375, 405, 355, 365, 435, 375, 405, 340, 435, 370, 385, 385, 405, 375, 405, 440, 415, 405, 500, 365, 405, 405, 495, 405, 375, 475, 365, 455, 440],
+ "Vertical Jump": [35.7, 29.9, 36.3, 29.3, 37.7, 32.4, 29, 33.2, 33.2, 33.9, 31.2, 29, 32, 37.1, 34, 30, 30, 32.8, 38, 36.7, 40.5, 38.5, 33.5, 40, 30.1, 36.4, 29, 31.4, 32, 34, 36.4, 38.7, 31.1, 34.7, 34.6, 30.6, 31.5, 35, 28],
+ "Broad Jump": [111, 121, 105, 97.5, 110, 118, 114.5, 111, 102, 121.5, 108, 115, 108, 104, 104, 91, 107.25, 112.5, 125.75, 122, 112.25, 125, 105.25, 108, 116, 111.5, 113.5, 113, 112.5, 105.5, 111],
+ "10Y Sprint": [1.57, 1.64, 1.62, 1.61, 1.46, 1.67, 1.63, 1.6, 1.55, 1.65, 1.5, 1.68, 1.62, 1.65, 1.57, 1.5, 1.48, 1.5, 1.48, 1.52, 1.52, 1.57, 1.46, 1.57, 1.56, 1.68, 1.71, 1.68, 1.57, 1.66, 1.59, 1.76, 1.7, 1.63],
+ "Year": [2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024],
+ "Hang Clean": [245, 215, 255, 255, 225, 225, 295, 245, 215],
+ "L Drill": [7.53, 7.15, 6.96, 6.87, 7.34, 6.94, 7, 7.25, 6.95, 6.79, 7.57, 6.92, 7.1, 6.97, 6.98, 7.21, 6.91],
+ "Pro Agility": [4.39, 4.51, 4.33, 4.25, 4.31, 4.36, 4.49, 4.4, 4.38, 4.42, 4.78, 4.43, 4.29, 4.66, 4.53, 4.65, 4.46],
+ "Power Clean": [275, 295, 275, 255, 315, 225, 275, 235],
+ "Flying 10": [1, 1.02, 1.05, 1.03, 0.98, 0.95, 1.08, 0.97, 1.05],
+ "60Y Shuttle": [12.12, 11.81, 13.47, 12.27, 12.53, 12.6, 12.09, 12.38, 12.09]
+ }
+ ],
+ "DB": [
+ {
+ "Height": [73, 75, 74.5, 71.3, 74, 71, 72, 73, 70, 71, 73.1, 71.5, 69, 69, 70.4, 74, 73.2, 73.6, 67.5, 73.4, 68.2, 68.7, 71.1, 69, 71.5, 73, 74, 70, 72.875, 69.625, 73.5, 74, 70.125, 71, 71, 69, 69.25, 73.5, 71, 69, 68.25, 70.25, 70, 69.5, 70, 70, 70.25, 73, 74, 71, 72.87, 71.6, 71, 71, 68.4, 69.6],
+ "Wingspan": [77, 73, 75, 72, 69, 68, 74, 76, 72, 69, 79.5, 75.5, 75, 71.9, 74.8, 73.5, 77.3, 72.8, 70.3, 77.3, 71.8, 71.3, 76.3, 70.5, 73.5, 73, 78, 71.875, 76, 72, 77, 73, 70, 77, 73.625, 72.75, 72.5, 76, 74, 71.5, 71, 76, 75.5, 73, 75.5, 71.5, 76, 73, 76, 72, 76.5, 72, 72.5, 75, 69.5, 72],
+ "Weight": [193, 192, 192, 185, 188, 177, 206, 191, 182, 169, 196.6, 203.4, 178.2, 183, 195.8, 176.4, 177.8, 184.6, 179.4, 202.8, 191.4, 179, 192.8, 190.8, 194.3, 191, 193, 170.4, 168.2, 170.4, 189.4, 164.4, 178.2, 197.2, 179.8, 192, 178, 193, 191.2, 190, 179.4, 177, 173, 184.8, 179, 178.2, 180, 195, 193, 187, 179, 193, 190, 189, 179, 186],
+ "225lb Bench": [1, 4, 4, 8, 3, 8, 3, 10, 8, 3, 8, 8, 7, 3, 8, 6, 15, 16, 11, 4, 12, 14, 7, 10, 6, 2, 8, 14, 2, 13, 7, 6, 6, 12, 14, 7, 6, 6, 5, 10, 8, 2, 9, 16, 6, 3, 15, 9],
+ "Bench": [245, 260, 265, 260, 245, 275, 275, 280, 275, 250, 275, 245, 275, 255, 255, 255, 340, 330, 305, 265, 300, 305, 325, 285, 235, 310, 305, 285, 285, 245, 300, 325, 275, 255, 265, 265, 285, 265, 285, 300, 230, 325, 275, 235, 315, 285],
+ "Squat": [385, 340, 365, 410, 325, 425, 415, 455, 335, 395, 475, 445, 375, 400, 375, 245, 500, 500, 465, 445, 395, 435, 415, 500, 465, 465, 445, 375, 385, 420, 500, 395, 375, 415, 405, 445, 415, 405, 375, 445, 335, 425, 405, 405, 485, 405],
+ "Vertical Jump": [31.4, 27.4, 37, 32.8, 29.1, 30.9, 29.5, 33.9, 34, 34.4, 37.6, 31.1, 29.8, 31.2, 31, 34.3, 33.9, 31.4, 34.2, 38, 33, 34.3, 34.6, 40, 33, 35, 31.8, 38.6, 31.7, 37.9, 33.4, 33.1, 34.7, 35, 32, 36.1, 33.5, 36.1, 31.8, 37.9, 34.8, 35.7, 34.5, 30.4, 31.6, 27.3, 29.7, 31.8, 37.1, 31.6, 33.5, 34.1, 31.1],
+ "Broad Jump": [105, 110.5, 106, 110.5, 114, 106, 111.5, 107, 120.5, 121, 125, 109, 110, 109, 110, 109, 108, 108, 102, 120, 105, 118, 123.5, 122, 114, 110, 114.5, 111, 105, 114.5, 114, 117.5, 109, 118.5, 111, 119, 113.5, 111, 130, 119, 125.5, 117, 95, 105.5, 99.5],
+ "10Y Sprint": [1.65, 1.6, 1.55, 1.57, 1.62, 1.59, 1.6, 1.5, 1.56, 1.67, 1.7, 1.59, 1.54, 1.62, 1.55, 1.75, 1.5, 1.58, 1.45, 1.6, 1.58, 1.49, 1.45, 1.51, 1.53, 1.53, 1.58, 1.59, 1.65, 1.6, 1.53, 1.6, 1.47, 1.54, 1.49, 1.64, 1.74, 1.66, 1.69, 1.76, 1.7, 1.77, 1.63, 1.64, 1.56, 1.66],
+ "Year": [2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024],
+ "Hang Clean": [285, 300, 300, 245, 265, 205, 195, 300, 265, 205, 205, 255],
+ "L Drill": [7.5, 7.16, 7.1, 7.25, 7.47, 7.19, 7.19, 7, 7.53, 7.41, 7.03, 7.4, 7.04, 7.27, 7.15, 7.25, 7.08, 7.02, 7.06, 7.54, 6.87, 6.84, 7.09, 7.16],
+ "Pro Agility": [4.71, 4.5, 4.03, 4.59, 4.49, 4.45, 4.55, 4.5, 4.53, 4.49, 4.06, 4.71, 4.55, 4.6, 4.6, 4.72, 4.67, 4.53, 4.63, 4.54, 4.5, 4.74, 4.58],
+ "Power Clean": [255, 265, 235, 225, 255, 265, 205, 305, 225, 235, 285, 245],
+ "Flying 10": [1.04, 1.03, 1.04, 1, 1.09, 1, 1.08, 1.03, 1.02, 1, 1.01, 1.1],
+ "60Y Shuttle": [12.22, 12.56, 12.59, 12.72, 12.69, 12.09, 12.43, 12.6, 12.04, 12.44, 12, 12.31]
+ }
+ ],
+ "DL": [
+ {
+ "Height": [74, 74, 76, 76, 74, 74.3, 75, 74, 74, 75.3, 77, 73, 76.5, 74, 75.4, 75, 74, 74.7, 76.2, 76.7, 75.4, 73.1, 74.8, 76.7, 73.5, 75.7, 74.6, 75.5, 75.4, 75, 75.5, 74.375, 77.25, 74.875, 75, 73, 75.25, 75, 77, 76.25, 75, 73.75, 76, 76, 74.5, 75, 75, 75.5, 76, 75.25, 75.75, 77, 75.4, 73.5, 76, 74.5, 77.25, 76.3, 73.3, 75.5, 75, 75.5, 76],
+ "Wingspan": [75, 81, 77, 76, 75, 76, 75, 73, 75, 78, 76, 72, 76, 77.8, 76, 77.8, 80.5, 78.5, 77.8, 78.5, 79.3, 73.5, 77, 78.3, 73.8, 80.5, 80.8, 78.5, 73.3, 80.5, 78, 74.25, 78.5, 75.5, 78.5, 75.25, 77.75, 78.75, 78, 80.5, 79, 75.125, 79, 73.5, 76, 74, 78, 75.125, 77, 79, 77.5, 77.5, 77, 77, 76, 73.5, 78, 79.5, 76.5, 75, 78, 81.5],
+ "Weight": [261, 271, 230, 243, 203, 275, 241, 260, 241, 270, 230, 272, 274, 249.4, 238.2, 257.2, 252, 251, 230.2, 239.8, 292.4, 278.6, 225, 238.4, 252.8, 260, 235.8, 285.6, 276, 230, 250, 242.8, 239, 245.4, 252.6, 228.8, 231.8, 258.4, 247.2, 250, 233.7, 225.6, 276, 239, 262.4, 227.2, 281.8, 283.8, 291.2, 237.6, 279, 278, 265, 242, 270, 278.5, 271, 263, 229, 262, 249],
+ "225lb Bench": [4, 21, 16, 22, 6, 12, 14, 8, 19, 17, 14, 19, 10, 14, 8, 22, 15, 22, 15, 22, 9, 15, 15, 20, 3, 22, 19, 3, 17, 8, 13, 15, 16, 15, 15, 22, 17, 20, 14, 4, 21, 9, 16, 16, 10, 16, 16, 25, 15, 7, 20, 17, 23, 16, 17, 15, 5, 15],
+ "Bench": [285, 355, 330, 330, 285, 285, 315, 275, 340, 350, 300, 365, 285, 330, 280, 345, 305, 365, 335, 365, 295, 340, 305, 250, 345, 335, 235, 335, 315, 340, 325, 390, 320, 335, 315, 345, 275, 320, 340, 315, 355, 345, 325, 275, 265, 345, 345, 295, 238, 355, 265],
+ "Squat": [395, 620, 500, 530, 405, 450, 435, 500, 475, 455, 440, 415, 455, 505, 405, 475, 500, 540, 505, 525, 515, 520, 505, 385, 500, 475, 405, 475, 475, 460, 485, 405, 585, 405, 545, 425, 495, 450, 495, 585, 405, 515, 525, 500, 455, 595, 465, 415, 345, 385, 585, 425, 455, 425, 455, 505],
+ "Vertical Jump": [27.9, 38, 36.9, 34.9, 30.4, 28.5, 29.5, 25.9, 30.6, 23.4, 27.4, 22.4, 29, 36.9, 29.6, 27.8, 27.5, 32.8, 26.5, 33.1, 28.1, 25.2, 26.5, 36, 27, 25, 32, 30.6, 31, 23.1, 26.8, 26.8, 31.9, 33, 32.7, 33.9, 30.9, 37.3, 32.8, 30.1, 25.8, 33.6, 30.6, 29.4, 34.5, 22.4, 31, 26.5, 32.2, 28.3, 28.9, 23.8, 29.9, 20.3, 27.6, 24.4, 35.2, 36.5, 29.6],
+ "Broad Jump": [111, 116, 97.5, 103, 96, 108.5, 99, 101, 93.5, 104, 107.25, 103.5, 104.5, 108, 109, 116, 109, 115, 115, 108, 107, 102, 104, 97, 85, 92, 99, 108, 108, 102, 109.5, 116, 111.5, 110, 123, 106, 112, 105, 106, 105, 109, 121, 109.5, 109.5, 110, 111, 101, 114, 110, 123, 105, 112.5],
+ "10Y Sprint": [1.6, 1.52, 1.6, 1.64, 1.57, 1.78, 1.58, 1.74, 1.56, 1.75, 1.7, 1.72, 1.63, 1.62, 1.7, 1.81, 1.85, 1.79, 1.75, 1.79, 1.85, 1.83, 1.65, 1.73, 1.79, 1.82, 1.59, 1.67, 1.62, 1.59, 1.69, 1.59, 1.59, 1.6, 1.55, 1.65, 1.72, 1.61, 1.63, 1.9, 1.62, 1.66, 1.68, 1.74, 1.77, 1.84, 1.75, 1.87, 1.78, 1.75, 1.63, 1.74, 1.73, 1.64],
+ "Year": [2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024],
+ "Hang Clean": [225, 275, 245, 295, 265, 295, 285, 315, 245, 355, 280, 255, 265, 335],
+ "L Drill": [7.53, 7.22, 7.5, 7.34, 7.31, 7.16, 7.38, 7.69, 7.56, 7.97, 7.32, 7.68, 7.65, 7.48, 7.39, 7.36, 7.13, 7.51, 7.5, 7.51, 7.77, 7.32, 7.49, 7.37, 7.22],
+ "Pro Agility": [4.69, 4.5, 4.78, 4.72, 4.4, 4.28, 4.57, 4.63, 4.72, 4.95, 4.63, 4.74, 4.79, 4.66, 4.93, 4.7, 4.84, 4.87, 4.97, 4.83, 5.13, 4.67, 4.66, 4.76],
+ "Power Clean": [305, 295, 325, 260, 285, 275, 305, 275, 305, 285],
+ "Flying 10": [1.1, 1.09, 1.04, 1.21, 1.09, 1.2, 1.13, 1.16, 1.04, 1.08, 1.15, 1.05],
+ "60Y Shuttle": [12.62, 13.09, 13.06, 13.41, 13.25, 13.79, 13.82, 13.79, 12.47, 13.09, 13.06]
+ }
+ ],
+ "LB": [
+ {
+ "Height": [72, 73.3, 71.5, 72, 73, 73.5, 73, 73, 74, 72, 75.5, 70.5, 72.2, 75.3, 71.7, 69.5, 72.4, 73, 74, 71.7, 71.2, 71.5, 71.125, 72.875, 75, 73, 73.375, 70, 73, 72, 72, 72, 73.5, 73.5, 72, 74.5, 72, 71, 73.3, 75.75, 74.5, 73.5, 73, 72, 72, 73.5, 72.87],
+ "Wingspan": [69, 75, 74, 69, 72, 72, 73, 72, 72, 72, 74, 73, 72.8, 72.5, 76.3, 73.1, 72.5, 72.5, 73.3, 76.9, 72.8, 74.3, 75.8, 73.875, 73.5, 77, 71, 79, 73, 75, 76, 73, 72, 74, 74, 76.5, 75, 74.5, 71.5, 77, 76, 79.5, 73, 74.5, 75.5, 74, 74],
+ "Weight": [208, 220, 215, 212, 230, 211, 222, 208, 235, 202, 235, 236, 202.2, 202.8, 230.2, 223, 215.4, 220, 200.4, 223.4, 229.2, 213.2, 227, 239.2, 215.8, 218, 223.3, 193.6, 218.6, 203, 211, 221, 239, 212.6, 217.4, 213.2, 224, 213, 240, 224, 222, 225, 200, 215, 212, 225, 219.3, 226],
+ "225lb Bench": [16, 15, 10, 15, 13, 16, 9, 21, 10, 11, 8, 14, 16, 12, 15, 19, 17, 11, 5, 19, 18, 14, 14, 8, 12, 21, 19, 13, 17, 20, 21, 19, 18, 6, 9, 9, 19, 21, 16, 12, 5, 15, 15, 22, 21, 12],
+ "Bench": [350, 245, 300, 310, 320, 325, 340, 285, 365, 285, 295, 265, 330, 335, 295, 315, 355, 335, 285, 265, 350, 315, 325, 295, 335, 360, 315, 325, 345, 385, 355, 325, 295, 275, 345, 315, 325, 300, 265, 325, 345, 355, 295],
+ "Squat": [455, 460, 445, 365, 475, 450, 500, 435, 485, 435, 400, 375, 455, 440, 395, 455, 520, 415, 390, 395, 570, 455, 475, 445, 425, 565, 515, 495, 515, 585, 455, 465, 475, 435, 475, 455, 475, 385, 495, 500, 500, 425],
+ "Vertical Jump": [35.7, 24.6, 30.8, 27.1, 28.8, 32.8, 33.2, 34.1, 33.6, 29.6, 29.4, 28.7, 32, 33, 30.5, 35, 33, 30.4, 32.4, 29.4, 32, 30.9, 29.9, 33.4, 31.9, 35.7, 30.6, 28.6, 35.6, 35.3, 32, 32.3, 32.8, 35.9, 33.7, 28.4, 31.9, 27.3, 29.3, 36.3, 31.7, 31.7, 31.3, 32.1, 35, 27.6],
+ "Broad Jump": [106, 99.5, 113, 112, 114.5, 110.5, 101.5, 104, 104.5, 102.5, 103, 102.5, 99, 88, 108, 105, 87, 97, 97, 94, 112, 94, 105, 111, 109, 109, 115.5, 113, 103.75, 109.5, 110, 106, 111, 118, 117, 114, 107, 107, 115, 118.5],
+ "10Y Sprint": [1.67, 1.61, 1.6, 1.68, 1.7, 1.6, 1.63, 1.57, 1.55, 1.67, 1.62, 1.7, 1.6, 1.57, 1.82, 1.54, 1.51, 1.59, 1.56, 1.66, 1.74, 1.77, 1.64, 1.8, 1.58, 1.64, 1.51, 1.55, 1.63, 1.57, 1.65, 1.6, 1.44, 1.47, 1.62, 1.71, 1.85, 1.64, 1.6, 1.64, 1.66, 1.6, 1.6, 1.72],
+ "Year": [2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024],
+ "Hang Clean": [245, 295, 245, 225, 275, 275, 265, 285, 235],
+ "L Drill": [7.28, 7.16, 7.47, 7.31, 7.46, 7.34, 7.38, 7.29, 7.53, 7.44, 7.39, 7.17, 7.01, 7.16, 7.43, 7.33, 7.4],
+ "Pro Agility": [4.5, 4.25, 4.55, 4.65, 4.3, 4.61, 4.58, 4.48, 4.71, 4.48, 4.55, 4.82, 4.63, 4.85, 4.54, 4.76, 4.56, 4.49, 4.77, 4.63],
+ "Power Clean": [225, 300, 265, 285, 255, 275, 315, 305, 265],
+ "Flying 10": [1, 1.06, 1.03, 1, 1.03, 1.05, 1, 1.03, 1.1],
+ "60Y Shuttle": [12.63, 12.81, 12.87, 11.87, 12.25, 12.97, 12.35, 12.97, 12.85, 12.4]
+ }
+ ],
+ "SP": [
+ {
+ "Height": [75, 74, 74, 72.8, 73.5, 73.4, 70.4, 70.7, 71, 74.5, 72.5, 69.5, 75, 74.5, 76, 72.2, 69.2, 75],
+ "Wingspan": [74, 79, 74, 72, 73, 77.3, 69.8, 70.3, 71, 77.25, 73, 70, 76.5, 77, 76, 73, 70, 76.5],
+ "Weight": [197, 191, 197, 214, 189, 198.6, 158.6, 219.6, 162, 199.4, 189.2, 184.6, 204.6, 201, 204, 202, 185, 195],
+ "225lb Bench": [1, 4, 1, 21, 4, 8, 1, 1, 4, 7, 1, 1, 1, 11, 1, 1, 1, 1],
+ "Bench": [230, 245, 225, 345, 260, 285, 225, 235, 240, 265, 220, 220, 225, 295, 225, 235, 245, 240],
+ "Squat": [315, 315, 335, 305, 365, 305, 315, 315, 365, 315, 365, 335, 385, 335, 325, 395, 335],
+ "Vertical Jump": [29, 30.2, 28, 29.8, 28.9, 30.5, 21, 27.6, 34.9, 33.3, 28.1, 27.7, 31, 26.3, 26.3, 26.3, 29.4],
+ "Broad Jump": [106.5, 88.5, 87.5, 87.5, 116, 101, 98, 109.5, 110, 97.5, 96.5, 115, 107, 103, 105],
+ "10Y Sprint": [1.62, 1.65, 1.64, 1.59, 1.78, 1.57, 1.91, 1.58, 1.53, 1.64, 1.62, 1.64, 1.71, 1.78, 1.72, 1.82],
+ "Year": [2020, 2020, 2020, 2020, 2020, 2022, 2022, 2022, 2023, 2023, 2023, 2023, 2023, 2023, 2024, 2024, 2024, 2024, 2024],
+ "Hang Clean": [185, 225, 205, 185, 205],
+ "L Drill": [7.12, 7.41, 7.75, 7.53, 7.1, 7.35, 7.64, 7.71, 7.44, 7.27],
+ "Pro Agility": [4.55, 4.56, 4.65, 4.85, 4.75, 4.46, 5.01, 4.77, 4.79, 4.67],
+ "Power Clean": [270, 225, 215, 195, 240],
+ "Flying 10": [1.07, 1.1, 1.15, 1.08, 1.05],
+ "60Y Shuttle": [12.66, 14.44, 13.5, 12.97, 13.19]
+ }
+ ]
+}
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..ee962fc
--- /dev/null
+++ b/index.html
@@ -0,0 +1,104 @@
+
+
+
+
+
+ Penn Football Strength Benchmarking
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/js/.Rhistory b/js/.Rhistory
new file mode 100644
index 0000000..e69de29
diff --git a/js/athlete_report.js b/js/athlete_report.js
new file mode 100644
index 0000000..675119a
--- /dev/null
+++ b/js/athlete_report.js
@@ -0,0 +1,109 @@
+import { getAthleteReports } from './firebase.js';
+
+function collectAthleteData() {
+ const data = {};
+
+ data.Name = document.getElementById('name-input').value.trim();
+ data.Position = document.querySelector('#athlete-position select').value.trim();
+ data.Status = document.getElementById('status-input').value.trim();
+ data.Number = document.getElementById('number-input').value.trim();
+ data.Notes = document.getElementById('coach-notes').value.trim();
+
+ document.querySelectorAll('[id^="athlete-stat-"]').forEach((input) => {
+ data[input.name] = input.value ? parseFloat(input.value) : null;
+ });
+
+ return data;
+}
+
+async function loadAthleteDropdown() {
+ const dropdownMenu = document.getElementById('athlete-list');
+ toggleDropdownVisibility(dropdownMenu);
+
+ if (dropdownMenu.classList.contains('visible')) {
+ dropdownMenu.innerHTML = '';
+ const athletes = await getAthleteReports();
+
+ athletes.forEach((athlete) => {
+ const listItem = document.createElement('li');
+ listItem.textContent = `${athlete.Name} (${athlete.Position}) - ${athlete.Status}`;
+ listItem.dataset.athlete = JSON.stringify(athlete);
+ listItem.classList.add('athlete-item');
+ dropdownMenu.appendChild(listItem);
+ });
+ }
+}
+
+function toggleDropdownVisibility(dropdownMenu) {
+ dropdownMenu.classList.toggle('hidden');
+ dropdownMenu.classList.toggle('visible');
+}
+
+function populateAthleteFields(athleteData) {
+ // Populate demographic fields
+ document.getElementById('name-input').value = athleteData.Name || '';
+ document.getElementById('number-input').value = athleteData.Number || '';
+ document.getElementById('status-input').value = athleteData.Status || '';
+ document.getElementById('coach-notes').value = athleteData.Notes || '';
+
+ // Update position dropdown
+ const positionDropdown = document.querySelector('#athlete-position select');
+ if (positionDropdown) {
+ positionDropdown.value = athleteData.Position || 'DB';
+ positionDropdown.dispatchEvent(new Event('change'));
+ }
+
+ // Populate stat fields
+ document.querySelectorAll('[id^="athlete-stat-"]').forEach((input) => {
+ const statName = input.name;
+ if (athleteData[statName] !== undefined) {
+ input.value = athleteData[statName] !== null ? athleteData[statName] : '';
+ input.dispatchEvent(new Event('input'));
+ }
+ });
+
+ // Resize demographic inputs
+ const inputsToResize = ['#name-input', '#number-input', '#status-input'];
+ inputsToResize.forEach((selector) => {
+ const input = document.querySelector(selector);
+ if (input) {
+ const canvas = document.createElement('canvas');
+ const context = canvas.getContext('2d');
+ const font = window.getComputedStyle(input).font;
+ context.font = font;
+ const textWidth = context.measureText(input.value || '').width;
+ const padding = 15;
+ const minWidth = 50;
+ input.style.width = `${Math.max(textWidth + padding, minWidth)}px`;
+ }
+ });
+}
+
+function setupAthleteSelectionListener() {
+ const dropdownMenu = document.getElementById('athlete-list');
+
+ // Close dropdown
+ document.addEventListener('click', (event) => {
+ const dropdownContainer = document.getElementById('dropdown-container');
+
+ if (!dropdownContainer.contains(event.target)) {
+ dropdownMenu.classList.add('hidden');
+ dropdownMenu.classList.remove('visible');
+ }
+ });
+
+ // Populate input fields
+ dropdownMenu.addEventListener('click', (event) => {
+ const target = event.target;
+ if (target.classList.contains('athlete-item')) {
+ const athleteData = JSON.parse(target.dataset.athlete);
+
+ populateAthleteFields(athleteData);
+
+ dropdownMenu.classList.add('hidden');
+ dropdownMenu.classList.remove('visible');
+ }
+ });
+}
+
+export { collectAthleteData, loadAthleteDropdown, setupAthleteSelectionListener, populateAthleteFields };
diff --git a/js/barchart.js b/js/barchart.js
new file mode 100644
index 0000000..3117c3c
--- /dev/null
+++ b/js/barchart.js
@@ -0,0 +1,153 @@
+const barInstances = {};
+
+function initBar(barEl, positionMedians, statNames, playerStats, playerPercentiles) {
+ const statCategories = {
+ anthropometrics: ['Weight', 'Height', 'Wingspan'],
+ strength: ['Squat', 'Bench', '225lb Bench'],
+ power: ['Vertical Jump', 'Broad Jump', 'Hang Clean', 'Power Clean'],
+ speed: ['10Y Sprint', 'Flying 10'],
+ agility: ['Pro Agility', 'L Drill', '60Y Shuttle'],
+ };
+
+ const category = barEl.id.replace('-chart', '').toLowerCase();
+ const metrics = statCategories[category];
+ const filteredStatNames = [];
+ const filteredPositionMedians = [];
+ const filteredPlayerStats = [];
+ const filteredPlayerPercentiles = [];
+
+ statNames.forEach((statName, index) => {
+ if (metrics.includes(statName)) {
+ filteredStatNames.push(statName);
+ filteredPositionMedians.push(positionMedians[index]);
+ filteredPlayerStats.push(playerStats[index]);
+ filteredPlayerPercentiles.push(playerPercentiles[index]);
+ }
+ });
+
+ const columns = [
+ ['x', ...filteredStatNames],
+ ['Percentile', ...filteredPlayerPercentiles],
+ ];
+
+ if (barInstances[barEl.id]) {
+ barInstances[barEl.id].destroy();
+ }
+
+ const colors = getColor(filteredPlayerPercentiles);
+
+ // eslint-disable-next-line no-undef
+ barInstances[barEl.id] = bb.generate({
+ title: {
+ text: category.charAt(0).toUpperCase() + category.slice(1),
+ },
+ data: {
+ x: 'x',
+ columns: columns,
+ labels: true,
+ type: 'bar',
+ color: function(color, d) {
+ if (d && d.index !== undefined) {
+ return colors[d.index];
+ }
+ return color;
+ },
+ },
+ bar: {
+ padding: 1,
+ radius: {
+ ratio: 0.2,
+ },
+ width: {
+ max: 60,
+ },
+ },
+ axis: {
+ rotated: false,
+ x: {
+ show: true,
+ type: 'category',
+ categories: filteredStatNames,
+ },
+ y: {
+ show: false,
+ max: 110,
+ padding: {
+ top: 0,
+ bottom: 0,
+ },
+ },
+ },
+ legend: {
+ show: false,
+ },
+ tooltip: {
+ show: true,
+ contents: function(data) {
+ const d = data[0];
+ const statIndex = d.index;
+ const statName = filteredStatNames[statIndex];
+ const unit = getUnit(statName);
+ const median = filteredPositionMedians[statIndex] !== undefined
+ ? `${Number(filteredPositionMedians[statIndex]).toFixed(1)} ${unit}`
+ : 'N/A';
+ const value = filteredPlayerStats[statIndex] !== undefined
+ ? `${Number(filteredPlayerStats[statIndex]).toFixed(1)} ${unit}`
+ : 'N/A';
+ const percentile = Number(d.value).toFixed(1);
+
+ return `
+
+ `;
+ },
+ },
+
+ bindto: barEl,
+ });
+
+ function getColor(percentiles) {
+ return percentiles.map((percentile) => {
+ if (percentile >= 80) {
+ return 'rgba(0, 139, 139, 0.7)';
+ } else if (percentile >= 60) {
+ return 'rgba(255, 215, 0, 0.7)';
+ } else if (percentile >= 40) {
+ return 'rgba(250, 128, 114, 0.7)';
+ } else {
+ return 'rgba(211, 211, 211, 0.7)';
+ }
+ });
+ }
+
+ function getUnit(stat) {
+ const unitMapping = {
+ lbs: ['Bench', 'Squat', 'Power Clean', 'Hang Clean', 'Weight'],
+ reps: ['225lb Bench'],
+ in: ['Vertical Jump', 'Broad Jump', 'Height', 'Wingspan'],
+ s: ['10Y Sprint', '60Y Shuttle', 'L Drill', 'Pro Agility', 'Flying 10'],
+ };
+
+ for (const [unit, stats] of Object.entries(unitMapping)) {
+ if (stats.includes(stat)) {
+ return unit;
+ }
+ }
+ return '';
+ }
+}
+
+export { initBar };
diff --git a/js/chart_data.js b/js/chart_data.js
new file mode 100644
index 0000000..7467dc0
--- /dev/null
+++ b/js/chart_data.js
@@ -0,0 +1,152 @@
+
+function calculateChartData(indivStats, events) {
+ let playerPosition = 'DB';
+ const playerStats = [];
+ const playerStatsValues = [];
+ let positionStatsValues = [];
+ let positionMedians = [];
+ let playerPercentiles = [];
+ let categoryPercentiles = [];
+
+ // Stats that are better when lower
+ const inversePercentileStats = [
+ 'Flying 10', '10Y Sprint', '60Y Shuttle', 'L Drill', 'Pro Agility',
+ ];
+
+ // Stat categories
+ const statCategories = {
+ speed: ['10Y Sprint', 'Flying 10'],
+ agility: ['Pro Agility', 'L Drill', '60Y Shuttle'],
+ power: ['Vertical Jump', 'Broad Jump', 'Hang Clean', 'Power Clean'],
+ strength: ['Squat', 'Bench', '225lb Bench'],
+ };
+
+ // Calculate mean player percentile within each stat category
+ function getCategoryPercentiles() {
+ categoryPercentiles = [];
+ for (const category in statCategories) {
+ if (statCategories) {
+ const statNames = statCategories[category];
+ const statIndexes = statNames.map((name) => playerStats.indexOf(name));
+ const percentiles = statIndexes
+ .map((index) => playerPercentiles[index])
+ .filter((value) => value !== undefined);
+
+ const mean = percentiles.reduce((a, b) => a + b, 0) / percentiles.length;
+ const categoryPercentile = Math.round(mean);
+ if (!isNaN(categoryPercentile)) {
+ categoryPercentiles.push(categoryPercentile);
+ } else {
+ categoryPercentiles.push(0);
+ }
+ }
+ }
+ return categoryPercentiles;
+ }
+
+ // Calculate player percentiles within position group
+ function getPercentiles() {
+ playerPercentiles = [];
+
+ playerStats.forEach((statName, index) => {
+ const playerValue = playerStatsValues[index];
+ const statValues = positionStatsValues[index];
+ const sortedStatValues = statValues.slice().sort((a, b) => a - b);
+ const countBelow = sortedStatValues.filter((value) => value <= playerValue).length;
+
+ let percentile = (countBelow / sortedStatValues.length);
+ percentile = Math.round(percentile * 100);
+
+ if (inversePercentileStats.includes(statName)) {
+ percentile = 100 - percentile;
+ }
+
+ playerPercentiles.push(percentile);
+ });
+
+ return playerPercentiles;
+ }
+
+ // Calculate position group medians (2020-2024)
+ function getMedians() {
+ positionMedians = [];
+
+ positionStatsValues.forEach((statValues) => {
+ const sortedValues = statValues.slice().sort((a, b) => a - b);
+ const mid = Math.floor(sortedValues.length / 2);
+
+ let median;
+ if (sortedValues.length % 2 === 0) {
+ median = (sortedValues[mid - 1] + sortedValues[mid]) / 2;
+ } else {
+ median = sortedValues[mid];
+ }
+ positionMedians.push(median);
+ });
+
+ return positionMedians;
+ }
+
+ // Handle stat changes
+ function updatePositionStatsValues() {
+ positionStatsValues = playerStats.map((statName) => {
+ return indivStats[playerPosition].map((item) => item[statName]);
+ });
+
+ positionStatsValues = positionStatsValues.map((statArray) => statArray.flat(1));
+ getMedians();
+ getPercentiles();
+ getCategoryPercentiles();
+ }
+
+ events.addEventListener('positionSelected', (evt) => {
+ const { position } = evt.detail;
+ playerPosition = position;
+ updatePositionStatsValues();
+ });
+
+ events.addEventListener('statFilled', (evt) => {
+ const { statName, filled, statValue } = evt.detail;
+
+ if (filled) {
+ const index = playerStats.indexOf(statName);
+
+ if (index !== -1) {
+ playerStatsValues[index] = statValue;
+ positionStatsValues[index] = indivStats[playerPosition].map((item) => item[statName]);
+ } else {
+ playerStats.push(statName);
+ playerStatsValues.push(statValue);
+ positionStatsValues.push(indivStats[playerPosition].map((item) => item[statName]));
+ }
+ } else {
+ const index = playerStats.indexOf(statName);
+ if (index !== -1) {
+ playerStats.splice(index, 1);
+ playerStatsValues.splice(index, 1);
+ positionStatsValues.splice(index, 1);
+ }
+ }
+ positionStatsValues = positionStatsValues.map((statArray) => statArray.flat(1));
+ getMedians();
+ getPercentiles();
+ getCategoryPercentiles();
+ });
+
+ // Return calculated data for bar and radar chart render
+ function getCalculatedData() {
+ return {
+ positionMedians,
+ playerPercentiles,
+ playerStats,
+ playerStatsValues,
+ categoryPercentiles,
+ };
+ }
+
+ return {
+ getCalculatedData,
+ };
+}
+
+export { calculateChartData };
diff --git a/js/firebase.js b/js/firebase.js
new file mode 100644
index 0000000..5dadb41
--- /dev/null
+++ b/js/firebase.js
@@ -0,0 +1,100 @@
+import { initializeApp } from 'https://www.gstatic.com/firebasejs/11.0.2/firebase-app.js';
+//import { getAnalytics } from 'https://www.gstatic.com/firebasejs/11.0.2/firebase-analytics.js';
+import { getFirestore, collection, doc, setDoc, addDoc, getDocs } from 'https://www.gstatic.com/firebasejs/11.0.2/firebase-firestore.js';
+
+// Firebase setup
+const firebaseConfig = {
+ apiKey: "AIzaSyAPujgD3xoa9zRjqve5nat6m4Q5Aa6MjDM",
+ authDomain: "penn-football-benchmarking.firebaseapp.com",
+ projectId: "penn-football-benchmarking",
+ storageBucket: "penn-football-benchmarking.firebasestorage.app",
+ messagingSenderId: "144027601930",
+ appId: "1:144027601930:web:a4ea4a588776b2341d63f3",
+ // measurementId: "G-834Q3624G1"
+
+};
+
+const app = initializeApp(firebaseConfig);
+//const analytics = getAnalytics(app);
+const db = getFirestore(app);
+
+
+
+window.db = db;
+window.collection = collection;
+window.addDoc = addDoc;
+window.getDocs = getDocs;
+
+// Add an athlete to Firestore
+async function addAthleteReport(data) {
+ console.log(data)
+ if (!data || data.Name == 'Athlete Name' || !data.Status || !data.Position) {
+ Toastify({
+ text: 'Save failed: Missing required information (Name, Status, Position).',
+ duration: 5000,
+ gravity: 'top',
+ position: 'center',
+ backgroundColor: 'salmon',
+ }).showToast();
+ return;
+ }
+
+
+
+ const athleteID = `${data.Name}-${data.Status}-${data.Position}`
+ .replace(/\s+/g, '')
+ .toLowerCase();
+
+ try {
+ await setDoc(doc(db, 'athlete-reports', athleteID), {
+ 'Timestamp': new Date(),
+ 'Name': data.Name,
+ 'Position': data.Position,
+ 'Status': data.Status,
+ 'Number': data.Number,
+ 'Notes': data.Notes,
+ 'Weight': data.Weight,
+ 'Height': data.Height,
+ 'Wingspan': data.Wingspan,
+ 'Bench': data.Bench,
+ 'Squat': data.Squat,
+ '225lb Bench': data['225lb Bench'],
+ 'Vertical Jump': data['Vertical Jump'],
+ 'Broad Jump': data['Broad Jump'],
+ 'Hang Clean': data['Hang Clean'],
+ 'Power Clean': data['Power Clean'],
+ '10Y Sprint': data['10Y Sprint'],
+ 'Flying 10': data['Flying 10'],
+ 'Pro Agility': data['Pro Agility'],
+ 'L Drill': data['L Drill'],
+ '60Y Shuttle': data['60Y Shuttle'],
+ });
+ Toastify({
+ text: `Athlete report for ${data.Name} saved successfully.`,
+ duration: 5000,
+ gravity: 'top',
+ position: 'center',
+ backgroundColor: '#4CAF50',
+ }).showToast();
+ } catch (error) {
+ Toastify({
+ text: `Save failed: ${error.message}`,
+ duration: 5000,
+ gravity: 'top',
+ position: 'center',
+ backgroundColor: 'salmon',
+ }).showToast();
+ }
+}
+
+// Access athlete reports from firestore
+async function getAthleteReports() {
+ const querySnapshot = await getDocs(collection(db, 'athlete-reports'));
+ const reports = [];
+ querySnapshot.forEach((doc) => {
+ reports.push(doc.data());
+ });
+ return reports;
+}
+
+export { app, db, addAthleteReport, getAthleteReports };
diff --git a/js/main.js b/js/main.js
new file mode 100644
index 0000000..7339db6
--- /dev/null
+++ b/js/main.js
@@ -0,0 +1,104 @@
+import { addAthleteReport } from './firebase.js';
+import { initBar } from './barchart.js';
+import { initStatEntry } from './stat_entry.js';
+import { calculateChartData } from './chart_data.js';
+import { initRadar } from './radar.js';
+import {
+ collectAthleteData,
+ loadAthleteDropdown,
+ setupAthleteSelectionListener,
+} from './athlete_report.js';
+
+// Fetch individual stats data
+const indivStatsResponse = await fetch('data/stats_2020_2024.json');
+const indivStats = await indivStatsResponse.json();
+
+// Event target for custom events
+const events = new EventTarget();
+
+// Set up references to DOM elements
+const statListEl = document.querySelector('#athlete-stats');
+const positionDropdownEl = document.querySelector('#header');
+
+// Extract positions and stat names
+const positions = Object.keys(indivStats);
+const statNames = Object.keys(Object.values(indivStats)[0][0]);
+
+// Initialize stat entry
+initStatEntry(statListEl, positionDropdownEl, statNames, positions, events);
+
+// Calculate chart data
+const chartData = calculateChartData(indivStats, events);
+
+// Get chart elements
+const chartElements = {
+ strength: document.querySelector('#strength-chart'),
+ power: document.querySelector('#power-chart'),
+ speed: document.querySelector('#speed-chart'),
+ agility: document.querySelector('#agility-chart'),
+ anthro: document.querySelector('#anthropometrics-chart'),
+ radar: document.querySelector('#radar-chart'),
+};
+
+// Render charts
+function renderCharts() {
+ const { positionMedians, playerPercentiles, playerStats, playerStatsValues, categoryPercentiles } =
+ chartData.getCalculatedData();
+
+ Object.values(chartElements).forEach((chartEl, index) => {
+ if (index < 5) {
+ initBar(chartEl, positionMedians, playerStats, playerStatsValues, playerPercentiles);
+ } else {
+ initRadar(chartElements.radar, categoryPercentiles);
+ }
+ });
+}
+
+// Initial render
+renderCharts();
+
+// Update charts on custom events
+events.addEventListener('statFilled', renderCharts);
+events.addEventListener('positionSelected', renderCharts);
+
+// Save athlete report
+document.getElementById('save-athlete').addEventListener('click', () => {
+ const data = collectAthleteData();
+ addAthleteReport(data);
+});
+
+// Load athletes
+document.getElementById('load-athletes').addEventListener('click', loadAthleteDropdown);
+
+// Enable athlete selection from dropdown
+setupAthleteSelectionListener();
+
+// Bulk athlete upload
+/* const finalStatsResponse = await fetch('data/bulk uploads/jr_day_2025.json');
+const finalStats = await finalStatsResponse.json();
+
+finalStats.Name.forEach((Name, index) => {
+ const athlete = {}
+ athlete.Name = finalStats.Name[index]
+ athlete.Position = "DB"
+ athlete.Status = "HS"
+ athlete.Number = "#"
+ athlete.Height = finalStats.Height[index]
+ athlete.Weight = finalStats.Weight[index]
+ athlete.Wingspan = finalStats.Wingspan[index]
+ athlete.Bench = "NA"
+ athlete.Squat = "NA"
+ athlete['225lb Bench'] = "NA"
+ athlete['Vertical Jump'] = "NA"
+ athlete['Broad Jump'] = "NA"
+ athlete['Hang Clean'] = "NA"
+ athlete['Power Clean'] = "NA"
+ athlete['10Y Sprint'] = "NA"
+ athlete['Flying 10'] = "NA"
+ athlete['Pro Agility'] = "NA"
+ athlete['L Drill'] = "NA"
+ athlete['60Y Shuttle'] = "NA"
+ athlete['Notes'] = "NA"
+
+ addAthleteReport(athlete)
+}); */
\ No newline at end of file
diff --git a/js/radar.js b/js/radar.js
new file mode 100644
index 0000000..43c58e2
--- /dev/null
+++ b/js/radar.js
@@ -0,0 +1,48 @@
+const radarInstances = {};
+
+function initRadar(radarEl, categoryPercentiles) {
+ console.log('Category Percentiles', categoryPercentiles);
+
+ let columns;
+
+ if (categoryPercentiles.length < 4) {
+ columns = [
+ ['x', '💨SPEED', '🐆AGILITY', '⚡POWER', '💪STRENGTH'],
+ ['Position Median', 50, 50, 50, 50],
+ ];
+ } else {
+ columns = [
+ ['x', '💨SPEED', '🐆AGILITY', '⚡POWER', '💪STRENGTH'],
+ ['Position Median', 50, 50, 50, 50],
+ ['Athlete', ...categoryPercentiles],
+ ];
+ }
+
+ if (radarInstances[radarEl.id]) {
+ radarInstances[radarEl.id].destroy();
+ }
+
+ radarInstances[radarEl.id] = bb.generate({
+ data: {
+ x: 'x',
+ columns: columns,
+ type: 'radar',
+ labels: true,
+ colors: {
+ 'Position Median': 'gray',
+ 'Athlete': 'darkcyan',
+ },
+ },
+ radar: {
+ axis: {
+ max: 100,
+ },
+ level: {
+ depth: 1,
+ },
+ },
+ bindto: '#radar-chart',
+ });
+}
+
+export { initRadar };
diff --git a/js/stat_entry.js b/js/stat_entry.js
new file mode 100644
index 0000000..9812ea3
--- /dev/null
+++ b/js/stat_entry.js
@@ -0,0 +1,252 @@
+function initStatEntry(statListEl, positionDropdownEl, stats, positions, events) {
+ const listEl = statListEl.querySelector(`ul`);
+ const positionEl = positionDropdownEl.querySelector(`div#athlete-position`);
+ const statListItems = {};
+ const positionPositionItems = {};
+
+ // Default notes for each position
+ const positionNotes = {
+ OL: `QUICKNESS / TWITCH\nFEET QUICKNESS\nANKLE & KNEE BEND\nBALANCE - BODY CONTROL\nHIP ROLL / EXPLOSION\nLATERAL MOVEMENT\nCHANGE OF DIRECTION\nATHLETIC ABILITY`,
+ RB: `INITIAL QUICKNESS\nBALANCE / BODY CONTROL\nINSIDE RUNNER\nPOWER / BREAK TACKLE\nAVOIDABILITY - ELUSIVENESS\nOUTSIDE RUNNER\nACCELERATION - BURST\nHANDS\nPASS PRO VS BLITZ\nRUN BLOCK (ISO - LEAD)`,
+ TE: `RUN BLOCKING\nINITIAL QUICKNESS\nSUSTAIN - FINISH\nCHANGE OF DIRECTION\nTOUGHNESS\nBALANCE - BODY CONTROL\nFLEXIBILITY\nDEEP THREAT - SPEED\nADJUST TO BALL\nROUTE RUNNING\nINSTINCTS / AWARENESS`,
+ WR: `TOUGHNESS\nHANDS\nABILITY TO ADJUST / ADAPT\nCHANGE OF DIRECTION\nACCELERATION / BURST\nRUN AFTER CATCH / BALL SKILLS\nBLOCKING\nINSTINCTS\nINITIAL QUICKNESS\nRELEASES (L.O.S)`,
+ QB: `TOUGHNESS\nACCURACY\nARM WHIP\nQUICK FEET\nATHLETIC\nQUICK TWITCH (GETS IT OUT)\nTHROWS ARE ON TIME\nMOXIE / DEMEANOR`,
+ DL: `INITIAL QUICKNESS\nREACT / RECOGNITION\nLATERAL QUICKNESS\nBALANCE / BODY CONTROL\nBURST / CLOSING SPEED\nHAND USE /SHED\nDOUBLE TEAM / ANCHOR\nTACKLING\nPASS RUSH ABILITY\nTOUGHNESS\nMOTOR`,
+ LB: `READ / REACT\nC.O.D. / MOTOR\nCLOSING SPEED\nSTRENGTH / POINT OF ATTACK\nBALANCE / ANKLE FLEXIBILITY\nBURST / ACCELERATION\nEXPLOSION / STRENGTH\nLATERAL QUICKNESS\nTACKLING\nBLITZ / RUSH ABILITY\nCOVERAGE / RANGE\nTOUGHNESS / EXPLOSIVE\nBALL SKILLS`,
+ DB: `BALL JUDGEMENT\nPLANT AND DRIVE\nBURST TO CLOSE\nABILITY TO PLAY MAN TO MAN\nTACKLING\nUNDERSTAND ZONES\nREACTION\nRUN SUPPORT\nBALANCE / BODY CONTROL\nSPECIAL TEAMS VALUE\nSHORT SPACE QUICKNESS`,
+ SP: ` `,
+ };
+
+ // Sort positions alphabetically
+ positions = positions.sort((a, b) => a.localeCompare(b));
+
+ const inputEl = document.querySelectorAll(`#athlete-position, #name-input, #status-input, #number-input, #coach-notes`);
+
+ inputEl.forEach((input) => {
+ input.style.boxSizing = `content-box`;
+
+ if (input.id !== `coach-notes`) {
+ resetDefaultValue.call(input);
+ resizeInput.call(input);
+ input.addEventListener(`input`, resizeInput);
+ input.addEventListener(`blur`, applyDefaultValue);
+ }
+
+ if (input.id === `name-input` || input.id === `number-input`) {
+ input.addEventListener(`focus`, clearPlaceholder);
+ }
+
+ if (input.id === `coach-notes`) {
+ input.addEventListener(`focus`, clearNotesPlaceholder);
+ input.addEventListener(`blur`, restoreNotesPlaceholder);
+ }
+ });
+
+ /* Utility Functions */
+ function clearPlaceholder() {
+ if (this.id === `name-input` && this.value === `Athlete Name`) this.value = ``;
+ if (this.id === `number-input` && this.value === `#`) this.value = ``;
+ }
+
+ function clearNotesPlaceholder() {
+ const coachNotesField = this;
+ const positionDropdown = document.querySelector(`#athlete-position select`);
+ const currentPosition = positionDropdown.value || `DB`;
+
+ if (coachNotesField.value === positionNotes[currentPosition]) {
+ coachNotesField.value = ``;
+ }
+ }
+
+ function restoreNotesPlaceholder() {
+ const positionDropdown = document.querySelector(`#athlete-position select`);
+ const currentPosition = positionDropdown.value || `DB`;
+ const coachNotesField = document.querySelector(`#coach-notes`);
+
+ if (coachNotesField.value.trim() === `` && positionNotes[currentPosition]) {
+ coachNotesField.value = positionNotes[currentPosition];
+ }
+ }
+
+ function resizeInput() {
+ if (this.tagName !== `INPUT` && this.tagName !== `SELECT`) return;
+ const canvas = document.createElement(`canvas`);
+ const context = canvas.getContext(`2d`);
+ context.font = window.getComputedStyle(this).font;
+ const textWidth = context.measureText(this.value || ``).width;
+ this.style.width = `${Math.max(textWidth + 15, 50)}px`;
+ }
+
+ function resetDefaultValue() {
+ if (this.id === `athlete-position`) this.value = `DB`;
+ if (this.id === `name-input`) this.value = `Athlete Name`;
+ if (this.id === `number-input`) this.value = `#`;
+ }
+
+ function applyDefaultValue() {
+ if (!this.value) resetDefaultValue.call(this);
+ resizeInput.call(this);
+ }
+
+ function getUnit(stat) {
+ const unitMapping = {
+ lbs: [`Bench`, `Squat`, `Power Clean`, `Hang Clean`, `Weight`],
+ reps: [`225lb Bench`],
+ in: [`Vertical Jump`, `Broad Jump`, `Height`, `Wingspan`],
+ s: [`10Y Sprint`, `60Y Shuttle`, `L Drill`, `Pro Agility`, `Flying 10`],
+ };
+
+ for (const [unit, stats] of Object.entries(unitMapping)) {
+ if (stats.includes(stat)) {
+ return unit;
+ }
+ }
+ return ``;
+ }
+
+ /* Initialize Stat List Items */
+ function initListItems() {
+ const orderedStats = [
+ `Weight`, `Height`, `Wingspan`,
+ `Bench`, `Squat`, `225lb Bench`,
+ `Vertical Jump`, `Broad Jump`, `Hang Clean`, `Power Clean`,
+ `10Y Sprint`, `Flying 10`,
+ `Pro Agility`, `L Drill`, `60Y Shuttle`,
+ ];
+
+ for (const stat of orderedStats) {
+ if (stats.includes(stat)) {
+ const unit = getUnit(stat);
+ const item = document.createElement(`li`);
+ item.innerHTML = `
+
+
+
+ ${unit}
+
`;
+ statListItems[stat] = item;
+ }
+ }
+ }
+
+ /* Initialize Position Items */
+ function initPositionItems() {
+ const selectEl = document.createElement(`select`);
+ selectEl.name = `position`;
+ positions.forEach((position) => {
+ const option = document.createElement(`option`);
+ option.value = position;
+ option.textContent = position;
+ selectEl.appendChild(option);
+ });
+ return selectEl;
+ }
+
+ /* Populate Position */
+ function populatePosition() {
+ positionEl.innerHTML = ``;
+ const position = initPositionItems();
+ positionEl.appendChild(position);
+ position.addEventListener(`change`, handlePositionChange);
+ }
+
+ /* Populate Stat List */
+ function populateList(stats) {
+ const statCategories = {
+ anthropometrics: [`Weight`, `Height`, `Wingspan`],
+ strength: [`Bench`, `Squat`, `225lb Bench`],
+ power: [`Vertical Jump`, `Broad Jump`, `Hang Clean`, `Power Clean`],
+ speed: [`10Y Sprint`, `Flying 10`],
+ agility: [`Pro Agility`, `L Drill`, `60Y Shuttle`],
+ };
+
+ const orderedStats = [
+ `Weight`, `Height`, `Wingspan`,
+ `Bench`, `Squat`, `225lb Bench`,
+ `Vertical Jump`, `Broad Jump`, `Hang Clean`, `Power Clean`,
+ `10Y Sprint`, `Flying 10`,
+ `Pro Agility`, `L Drill`, `60Y Shuttle`,
+ ];
+
+ listEl.innerHTML = ``;
+ const categoryAdded = new Set();
+
+ for (const stat of orderedStats) {
+ // Skip stats that are not in the provided stats list
+ if (!stats.includes(stat)) continue;
+
+ // Add category labels if not already added
+ for (const [category, categoryStats] of Object.entries(statCategories)) {
+ if (categoryStats.includes(stat) && !categoryAdded.has(category)) {
+ const labelEl = document.createElement(`li`);
+ labelEl.className = `stat-category-label`;
+ labelEl.textContent = category.charAt(0).toUpperCase() + category.slice(1);
+ listEl.appendChild(labelEl);
+ categoryAdded.add(category);
+ }
+ }
+
+ // Append the stat item
+ if (statListItems[stat]) {
+ listEl.appendChild(statListItems[stat]);
+ }
+ }
+ }
+
+ /* Event Handlers */
+ function handlePositionChange(evt) {
+ const selectedPosition = evt.target.value;
+ const coachNotesField = document.querySelector(`#coach-notes`);
+ if (positionNotes[selectedPosition]) {
+ coachNotesField.value = positionNotes[selectedPosition];
+ }
+ events.dispatchEvent(new CustomEvent(`positionSelected`, { detail: { position: selectedPosition } }));
+ }
+
+ function handleNumEntry(evt) {
+ const numInput = evt.target;
+ const statName = numInput.name;
+ const filled = numInput.value.trim() !== `` && parseFloat(numInput.value) > 0;
+ const statValue = filled ? parseFloat(numInput.value) : null;
+
+ numInput.setCustomValidity(``);
+ if (!numInput.checkValidity() || parseFloat(numInput.value) <= 0) {
+ numInput.setCustomValidity(`Please enter a valid number`);
+ numInput.reportValidity();
+ return;
+ }
+
+ events.dispatchEvent(new CustomEvent(`statFilled`, { detail: { statName, filled, statValue } }));
+ }
+
+ function clearAllStats() {
+ Object.values(statListItems).forEach((item) => {
+ const input = item.querySelector(`input`);
+ input.value = ``;
+ input.dispatchEvent(new Event(`input`));
+ });
+ }
+
+ /* Initialization */
+ const clearAllButton = document.getElementById(`clear-all`);
+ if (clearAllButton) {
+ clearAllButton.addEventListener(`click`, clearAllStats);
+ }
+
+ initPositionItems();
+ initListItems();
+ populatePosition();
+ populateList(stats);
+
+ Object.values(statListItems).forEach((item) => {
+ item.querySelector(`input`).addEventListener(`input`, handleNumEntry);
+ });
+
+ Object.values(positionPositionItems).forEach((item) => {
+ item.querySelector(`input`).addEventListener(`change`, handlePositionChange);
+ });
+}
+
+export { initStatEntry };
diff --git a/package-lock.json b/package-lock.json
index 9f99c26..6e29259 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,6 +8,9 @@
"name": "dashboard-project",
"version": "1.0.0",
"license": "ISC",
+ "dependencies": {
+ "firebase": "^11.0.2"
+ },
"devDependencies": {
"eslint": "^8.48.0",
"eslint-config-google": "^0.14.0",
@@ -183,6 +186,643 @@
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
+ "node_modules/@firebase/analytics": {
+ "version": "0.10.10",
+ "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.10.tgz",
+ "integrity": "sha512-Psdo7c9g2SLAYh6u1XRA+RZ7ab2JfBVuAt/kLzXkhKZL/gS2cQUCMsOW5p0RIlDPRKqpdNSmvujd2TeRWLKOkQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.11",
+ "@firebase/installations": "0.6.11",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/analytics-compat": {
+ "version": "0.2.16",
+ "resolved": "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.16.tgz",
+ "integrity": "sha512-Q/s+u/TEMSb2EDJFQMGsOzpSosybBl8HuoSEMyGZ99+0Pu7SIR9MPDGUjc8PKiCFQWDJ3QXxgqh1d/rujyAMbA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/analytics": "0.10.10",
+ "@firebase/analytics-types": "0.8.3",
+ "@firebase/component": "0.6.11",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/analytics-types": {
+ "version": "0.8.3",
+ "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.8.3.tgz",
+ "integrity": "sha512-VrIp/d8iq2g501qO46uGz3hjbDb8xzYMrbu8Tp0ovzIzrvJZ2fvmj649gTjge/b7cCCcjT0H37g1gVtlNhnkbg==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@firebase/app": {
+ "version": "0.10.16",
+ "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.10.16.tgz",
+ "integrity": "sha512-SUati2qH48gvVGnSsqMkZr1Iq7No52a3tJQ4itboSTM89Erezmw3v1RsfVymrDze9+KiOLmBpvLNKSvheITFjg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.11",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.10.2",
+ "idb": "7.1.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@firebase/app-check": {
+ "version": "0.8.10",
+ "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.8.10.tgz",
+ "integrity": "sha512-DWFfxxif/t+Ow4MmRUevDX+A3hVxm1rUf6y5ZP4sIomfnVCO1NNahqtsv9rb1/tKGkTeoVT40weiTS/WjQG1mA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.11",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/app-check-compat": {
+ "version": "0.3.17",
+ "resolved": "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.3.17.tgz",
+ "integrity": "sha512-a/eadrGsY0MVCBPhrNbKUhoYpms4UKTYLKO7nswwSFVsm3Rw6NslQQCNLfvljcDqP4E7alQDRGJXjkxd/5gJ+Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/app-check": "0.8.10",
+ "@firebase/app-check-types": "0.5.3",
+ "@firebase/component": "0.6.11",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/app-check-interop-types": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.3.tgz",
+ "integrity": "sha512-gAlxfPLT2j8bTI/qfe3ahl2I2YcBQ8cFIBdhAQA4I2f3TndcO+22YizyGYuttLHPQEpWkhmpFW60VCFEPg4g5A==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@firebase/app-check-types": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.5.3.tgz",
+ "integrity": "sha512-hyl5rKSj0QmwPdsAxrI5x1otDlByQ7bvNvVt8G/XPO2CSwE++rmSVf3VEhaeOR4J8ZFaF0Z0NDSmLejPweZ3ng==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@firebase/app-compat": {
+ "version": "0.2.46",
+ "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.46.tgz",
+ "integrity": "sha512-9hSHWE5LMqtKIm13CnH5OZeMPbkVV3y5vgNZ5EMFHcG2ceRrncyNjG9No5XfWQw8JponZdGs4HlE4aMD/jxcFA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/app": "0.10.16",
+ "@firebase/component": "0.6.11",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@firebase/app-types": {
+ "version": "0.9.3",
+ "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.3.tgz",
+ "integrity": "sha512-kRVpIl4vVGJ4baogMDINbyrIOtOxqhkZQg4jTq3l8Lw6WSk0xfpEYzezFu+Kl4ve4fbPl79dvwRtaFqAC/ucCw==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@firebase/auth": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.8.1.tgz",
+ "integrity": "sha512-LX9N/Cf5Z35r5yqm2+5M3+2bRRe/+RFaa/+u4HDni7TA27C/Xm4XHLKcWcLg1BzjrS4zngSaBEOSODvp6RFOqQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.11",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x",
+ "@react-native-async-storage/async-storage": "^1.18.1"
+ },
+ "peerDependenciesMeta": {
+ "@react-native-async-storage/async-storage": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@firebase/auth-compat": {
+ "version": "0.5.16",
+ "resolved": "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.5.16.tgz",
+ "integrity": "sha512-YlYwJMBqAyv0ESy3jDUyshMhZlbUiwAm6B6+uUmigNDHU+uq7j4SFiDJEZlFFIz397yBzKn06SUdqutdQzGnCA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/auth": "1.8.1",
+ "@firebase/auth-types": "0.12.3",
+ "@firebase/component": "0.6.11",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/auth-interop-types": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.4.tgz",
+ "integrity": "sha512-JPgcXKCuO+CWqGDnigBtvo09HeBs5u/Ktc2GaFj2m01hLarbxthLNm7Fk8iOP1aqAtXV+fnnGj7U28xmk7IwVA==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@firebase/auth-types": {
+ "version": "0.12.3",
+ "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.12.3.tgz",
+ "integrity": "sha512-Zq9zI0o5hqXDtKg6yDkSnvMCMuLU6qAVS51PANQx+ZZX5xnzyNLEBO3GZgBUPsV5qIMFhjhqmLDxUqCbnAYy2A==",
+ "license": "Apache-2.0",
+ "peerDependencies": {
+ "@firebase/app-types": "0.x",
+ "@firebase/util": "1.x"
+ }
+ },
+ "node_modules/@firebase/component": {
+ "version": "0.6.11",
+ "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.11.tgz",
+ "integrity": "sha512-eQbeCgPukLgsKD0Kw5wQgsMDX5LeoI1MIrziNDjmc6XDq5ZQnuUymANQgAb2wp1tSF9zDSXyxJmIUXaKgN58Ug==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@firebase/data-connect": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/@firebase/data-connect/-/data-connect-0.1.2.tgz",
+ "integrity": "sha512-Bcf29mntFCt5V7aceMe36wnkHrG7cwbMlUVbDHOlh2foQKx9VtSXEONw9r6FtL1sFobHVYOM5L6umX35f59m5g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/auth-interop-types": "0.2.4",
+ "@firebase/component": "0.6.11",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/database": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.0.10.tgz",
+ "integrity": "sha512-sWp2g92u7xT4BojGbTXZ80iaSIaL6GAL0pwvM0CO/hb0nHSnABAqsH7AhnWGsGvXuEvbPr7blZylPaR9J+GSuQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/app-check-interop-types": "0.3.3",
+ "@firebase/auth-interop-types": "0.2.4",
+ "@firebase/component": "0.6.11",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.10.2",
+ "faye-websocket": "0.11.4",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@firebase/database-compat": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-2.0.1.tgz",
+ "integrity": "sha512-IsFivOjdE1GrjTeKoBU/ZMenESKDXidFDzZzHBPQ/4P20ptGdrl3oLlWrV/QJqJ9lND4IidE3z4Xr5JyfUW1vg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.11",
+ "@firebase/database": "1.0.10",
+ "@firebase/database-types": "1.0.7",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@firebase/database-types": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.7.tgz",
+ "integrity": "sha512-I7zcLfJXrM0WM+ksFmFdAMdlq/DFmpeMNa+/GNsLyFo5u/lX5zzkPzGe3srVWqaBQBY5KprylDGxOsP6ETfL0A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/app-types": "0.9.3",
+ "@firebase/util": "1.10.2"
+ }
+ },
+ "node_modules/@firebase/firestore": {
+ "version": "4.7.5",
+ "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.7.5.tgz",
+ "integrity": "sha512-OO3rHvjC07jL2ITN255xH/UzCVSvh6xG8oTzQdFScQvFbcm1fjCL1hgAdpDZcx3vVcKMV+6ktr8wbllkB8r+FQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.11",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.10.2",
+ "@firebase/webchannel-wrapper": "1.0.3",
+ "@grpc/grpc-js": "~1.9.0",
+ "@grpc/proto-loader": "^0.7.8",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/firestore-compat": {
+ "version": "0.3.40",
+ "resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.3.40.tgz",
+ "integrity": "sha512-18HopMN811KYBc9Ptpr1Rewwio0XF09FF3jc5wtV6rGyAs815SlFFw5vW7ZeLd43zv9tlEc2FzM0H+5Vr9ZRxw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.11",
+ "@firebase/firestore": "4.7.5",
+ "@firebase/firestore-types": "3.0.3",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/firestore-types": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-3.0.3.tgz",
+ "integrity": "sha512-hD2jGdiWRxB/eZWF89xcK9gF8wvENDJkzpVFb4aGkzfEaKxVRD1kjz1t1Wj8VZEp2LCB53Yx1zD8mrhQu87R6Q==",
+ "license": "Apache-2.0",
+ "peerDependencies": {
+ "@firebase/app-types": "0.x",
+ "@firebase/util": "1.x"
+ }
+ },
+ "node_modules/@firebase/functions": {
+ "version": "0.11.10",
+ "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.11.10.tgz",
+ "integrity": "sha512-TP+Dzebazhw6+GduBdWn1kOJRFH84G2z+BW3pNVfkpFRkc//+uT1Uw2+dLpMGSSBRG7FrcDG91vcPnOFCzr15w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/app-check-interop-types": "0.3.3",
+ "@firebase/auth-interop-types": "0.2.4",
+ "@firebase/component": "0.6.11",
+ "@firebase/messaging-interop-types": "0.2.3",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/functions-compat": {
+ "version": "0.3.16",
+ "resolved": "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.3.16.tgz",
+ "integrity": "sha512-FL7EXehiiBisNIR7mlb0i+moyWKLVfcEJgh/Wq6ZV6BdrCObpCTz7w5EvuRIEFX5e9cNL2oWInKg8S5X4HtINg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.11",
+ "@firebase/functions": "0.11.10",
+ "@firebase/functions-types": "0.6.3",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/functions-types": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.6.3.tgz",
+ "integrity": "sha512-EZoDKQLUHFKNx6VLipQwrSMh01A1SaL3Wg6Hpi//x6/fJ6Ee4hrAeswK99I5Ht8roiniKHw4iO0B1Oxj5I4plg==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@firebase/installations": {
+ "version": "0.6.11",
+ "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.11.tgz",
+ "integrity": "sha512-w8fY8mw6fxJzsZM2ufmTtomopXl1+bn/syYon+Gpn+0p0nO1cIUEVEFrFazTLaaL9q1CaVhc3HmseRTsI3igAA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.11",
+ "@firebase/util": "1.10.2",
+ "idb": "7.1.1",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/installations-compat": {
+ "version": "0.2.11",
+ "resolved": "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.11.tgz",
+ "integrity": "sha512-SHRgw5LTa6v8LubmJZxcOCwEd1MfWQPUtKdiuCx2VMWnapX54skZd1PkQg0K4l3k+4ujbI2cn7FE6Li9hbChBw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.11",
+ "@firebase/installations": "0.6.11",
+ "@firebase/installations-types": "0.5.3",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/installations-types": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.5.3.tgz",
+ "integrity": "sha512-2FJI7gkLqIE0iYsNQ1P751lO3hER+Umykel+TkLwHj6plzWVxqvfclPUZhcKFVQObqloEBTmpi2Ozn7EkCABAA==",
+ "license": "Apache-2.0",
+ "peerDependencies": {
+ "@firebase/app-types": "0.x"
+ }
+ },
+ "node_modules/@firebase/logger": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.4.tgz",
+ "integrity": "sha512-mH0PEh1zoXGnaR8gD1DeGeNZtWFKbnz9hDO91dIml3iou1gpOnLqXQ2dJfB71dj6dpmUjcQ6phY3ZZJbjErr9g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@firebase/messaging": {
+ "version": "0.12.14",
+ "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.14.tgz",
+ "integrity": "sha512-cSGP34jJswFvME8tdMDkvJvW6T1jEekyMSyq84AMBZ0KEpJbDWuC9n4wKT2lxUm1jaL651iZnn6g51yCl77ICg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.11",
+ "@firebase/installations": "0.6.11",
+ "@firebase/messaging-interop-types": "0.2.3",
+ "@firebase/util": "1.10.2",
+ "idb": "7.1.1",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/messaging-compat": {
+ "version": "0.2.14",
+ "resolved": "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.14.tgz",
+ "integrity": "sha512-r9weK8jTEA2aGiwy0IbMQPnzuJ0DHkOQaMxGJOlU2QZ1a7fh6RHpNtaoM+LKnn6u1NQgmAOWYNr9vezVQEm9zw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.11",
+ "@firebase/messaging": "0.12.14",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/messaging-interop-types": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.3.tgz",
+ "integrity": "sha512-xfzFaJpzcmtDjycpDeCUj0Ge10ATFi/VHVIvEEjDNc3hodVBQADZ7BWQU7CuFpjSHE+eLuBI13z5F/9xOoGX8Q==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@firebase/performance": {
+ "version": "0.6.11",
+ "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.6.11.tgz",
+ "integrity": "sha512-FlkJFeqLlIeh5T4Am3uE38HVzggliDIEFy/fErEc1faINOUFCb6vQBEoNZGaXvRnTR8lh3X/hP7tv37C7BsK9g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.11",
+ "@firebase/installations": "0.6.11",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/performance-compat": {
+ "version": "0.2.11",
+ "resolved": "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.11.tgz",
+ "integrity": "sha512-DqeNBy51W2xzlklyC7Ht9JQ94HhTA08PCcM4MDeyG/ol3fqum/+YgtHWQ2IQuduqH9afETthZqLwCZiSgY7hiA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.11",
+ "@firebase/logger": "0.4.4",
+ "@firebase/performance": "0.6.11",
+ "@firebase/performance-types": "0.2.3",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/performance-types": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.2.3.tgz",
+ "integrity": "sha512-IgkyTz6QZVPAq8GSkLYJvwSLr3LS9+V6vNPQr0x4YozZJiLF5jYixj0amDtATf1X0EtYHqoPO48a9ija8GocxQ==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@firebase/remote-config": {
+ "version": "0.4.11",
+ "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.4.11.tgz",
+ "integrity": "sha512-9z0rgKuws2nj+7cdiqF+NY1QR4na6KnuOvP+jQvgilDOhGtKOcCMq5XHiu66i73A9kFhyU6QQ2pHXxcmaq1pBw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.11",
+ "@firebase/installations": "0.6.11",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/remote-config-compat": {
+ "version": "0.2.11",
+ "resolved": "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.11.tgz",
+ "integrity": "sha512-zfIjpwPrGuIOZDmduukN086qjhZ1LnbJi/iYzgua+2qeTlO0XdlE1v66gJPwygGB3TOhT0yb9EiUZ3nBNttMqg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.11",
+ "@firebase/logger": "0.4.4",
+ "@firebase/remote-config": "0.4.11",
+ "@firebase/remote-config-types": "0.3.3",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/remote-config-types": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.3.3.tgz",
+ "integrity": "sha512-YlRI9CHxrk3lpQuFup9N1eohpwdWayKZUNZ/YeQ0PZoncJ66P32UsKUKqVXOaieTjJIOh7yH8JEzRdht5s+d6g==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@firebase/storage": {
+ "version": "0.13.4",
+ "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.13.4.tgz",
+ "integrity": "sha512-b1KaTTRiMupFurIhpGIbReaWev0k5O3ouTHkAPcEssT+FvU3q/1JwzvkX4+ZdB60Fc43Mbp8qQ1gWfT0Z2FP9Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.11",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/storage-compat": {
+ "version": "0.3.14",
+ "resolved": "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.3.14.tgz",
+ "integrity": "sha512-Ok5FmXJiapaNAOQ8W8qppnfwgP8540jw2B8M0c4TFZqF4BD+CoKBxW0dRtOuLNGadLhzqqkDZZZtkexxrveQqA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.11",
+ "@firebase/storage": "0.13.4",
+ "@firebase/storage-types": "0.8.3",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/storage-types": {
+ "version": "0.8.3",
+ "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.8.3.tgz",
+ "integrity": "sha512-+Muk7g9uwngTpd8xn9OdF/D48uiQ7I1Fae7ULsWPuKoCH3HU7bfFPhxtJYzyhjdniowhuDpQcfPmuNRAqZEfvg==",
+ "license": "Apache-2.0",
+ "peerDependencies": {
+ "@firebase/app-types": "0.x",
+ "@firebase/util": "1.x"
+ }
+ },
+ "node_modules/@firebase/util": {
+ "version": "1.10.2",
+ "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.2.tgz",
+ "integrity": "sha512-qnSHIoE9FK+HYnNhTI8q14evyqbc/vHRivfB4TgCIUOl4tosmKSQlp7ltymOlMP4xVIJTg5wrkfcZ60X4nUf7Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@firebase/vertexai": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@firebase/vertexai/-/vertexai-1.0.1.tgz",
+ "integrity": "sha512-f48MGSofhaS05ebpN7zMIv4tBqYf19pXr5/4njKtNZVLbjxUswDma0SuFDoO+IwgbdkhFxgtNctM+C1zfI/O1Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/app-check-interop-types": "0.3.3",
+ "@firebase/component": "0.6.11",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x",
+ "@firebase/app-types": "0.x"
+ }
+ },
+ "node_modules/@firebase/webchannel-wrapper": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.3.tgz",
+ "integrity": "sha512-2xCRM9q9FlzGZCdgDMJwc0gyUkWFtkosy7Xxr6sFgQwn+wMNIWd7xIvYNauU1r64B5L5rsGKy/n9TKJ0aAFeqQ==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@grpc/grpc-js": {
+ "version": "1.9.15",
+ "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.15.tgz",
+ "integrity": "sha512-nqE7Hc0AzI+euzUwDAy0aY5hCp10r734gMGRdU+qOPX0XSceI2ULrcXB5U2xSc5VkWwalCj4M7GzCAygZl2KoQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@grpc/proto-loader": "^0.7.8",
+ "@types/node": ">=12.12.47"
+ },
+ "engines": {
+ "node": "^8.13.0 || >=10.10.0"
+ }
+ },
+ "node_modules/@grpc/proto-loader": {
+ "version": "0.7.13",
+ "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz",
+ "integrity": "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "lodash.camelcase": "^4.3.0",
+ "long": "^5.0.0",
+ "protobufjs": "^7.2.5",
+ "yargs": "^17.7.2"
+ },
+ "bin": {
+ "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/@humanwhocodes/config-array": {
"version": "0.13.0",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz",
@@ -253,12 +893,85 @@
"node": ">= 8"
}
},
+ "node_modules/@protobufjs/aspromise": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
+ "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/base64": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
+ "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/codegen": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz",
+ "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/eventemitter": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz",
+ "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/fetch": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz",
+ "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.1",
+ "@protobufjs/inquire": "^1.1.0"
+ }
+ },
+ "node_modules/@protobufjs/float": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
+ "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/inquire": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz",
+ "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/path": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
+ "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/pool": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
+ "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/utf8": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
+ "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==",
+ "license": "BSD-3-Clause"
+ },
"node_modules/@types/minimist": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==",
"dev": true
},
+ "node_modules/@types/node": {
+ "version": "22.9.0",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.0.tgz",
+ "integrity": "sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==",
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~6.19.8"
+ }
+ },
"node_modules/@types/normalize-package-data": {
"version": "2.4.4",
"resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz",
@@ -312,7 +1025,6 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
"engines": {
"node": ">=8"
}
@@ -321,7 +1033,6 @@
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dev": true,
"dependencies": {
"color-convert": "^2.0.1"
},
@@ -460,11 +1171,24 @@
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
+ "node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "dev": true,
"dependencies": {
"color-name": "~1.1.4"
},
@@ -475,8 +1199,7 @@
"node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "dev": true
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"node_modules/colord": {
"version": "2.9.3",
@@ -660,8 +1383,7 @@
"node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "dev": true
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
"node_modules/error-ex": {
"version": "1.3.2",
@@ -672,6 +1394,15 @@
"is-arrayish": "^0.2.1"
}
},
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
@@ -909,6 +1640,18 @@
"reusify": "^1.0.4"
}
},
+ "node_modules/faye-websocket": {
+ "version": "0.11.4",
+ "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz",
+ "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "websocket-driver": ">=0.5.1"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
"node_modules/file-entry-cache": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
@@ -949,6 +1692,42 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/firebase": {
+ "version": "11.0.2",
+ "resolved": "https://registry.npmjs.org/firebase/-/firebase-11.0.2.tgz",
+ "integrity": "sha512-w4T8BSJpzdZA25QRch5ahLsgB6uRvg1LEic4BaC5rTD1YygroI1AXp+W+rbMnr8d8EjfAv6t4k8doULIjc1P8Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/analytics": "0.10.10",
+ "@firebase/analytics-compat": "0.2.16",
+ "@firebase/app": "0.10.16",
+ "@firebase/app-check": "0.8.10",
+ "@firebase/app-check-compat": "0.3.17",
+ "@firebase/app-compat": "0.2.46",
+ "@firebase/app-types": "0.9.3",
+ "@firebase/auth": "1.8.1",
+ "@firebase/auth-compat": "0.5.16",
+ "@firebase/data-connect": "0.1.2",
+ "@firebase/database": "1.0.10",
+ "@firebase/database-compat": "2.0.1",
+ "@firebase/firestore": "4.7.5",
+ "@firebase/firestore-compat": "0.3.40",
+ "@firebase/functions": "0.11.10",
+ "@firebase/functions-compat": "0.3.16",
+ "@firebase/installations": "0.6.11",
+ "@firebase/installations-compat": "0.2.11",
+ "@firebase/messaging": "0.12.14",
+ "@firebase/messaging-compat": "0.2.14",
+ "@firebase/performance": "0.6.11",
+ "@firebase/performance-compat": "0.2.11",
+ "@firebase/remote-config": "0.4.11",
+ "@firebase/remote-config-compat": "0.2.11",
+ "@firebase/storage": "0.13.4",
+ "@firebase/storage-compat": "0.3.14",
+ "@firebase/util": "1.10.2",
+ "@firebase/vertexai": "1.0.1"
+ }
+ },
"node_modules/flat-cache": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
@@ -984,6 +1763,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "license": "ISC",
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
"node_modules/glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
@@ -1156,6 +1944,18 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/http-parser-js": {
+ "version": "0.5.8",
+ "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz",
+ "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==",
+ "license": "MIT"
+ },
+ "node_modules/idb": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz",
+ "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==",
+ "license": "ISC"
+ },
"node_modules/ignore": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
@@ -1268,7 +2068,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "dev": true,
"engines": {
"node": ">=8"
}
@@ -1427,6 +2226,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/lodash.camelcase": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
+ "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==",
+ "license": "MIT"
+ },
"node_modules/lodash.merge": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
@@ -1439,6 +2244,12 @@
"integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==",
"dev": true
},
+ "node_modules/long": {
+ "version": "5.2.3",
+ "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz",
+ "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==",
+ "license": "Apache-2.0"
+ },
"node_modules/lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
@@ -1846,6 +2657,30 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/protobufjs": {
+ "version": "7.4.0",
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz",
+ "integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==",
+ "hasInstallScript": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.2",
+ "@protobufjs/base64": "^1.1.2",
+ "@protobufjs/codegen": "^2.0.4",
+ "@protobufjs/eventemitter": "^1.1.0",
+ "@protobufjs/fetch": "^1.1.0",
+ "@protobufjs/float": "^1.0.2",
+ "@protobufjs/inquire": "^1.1.0",
+ "@protobufjs/path": "^1.1.2",
+ "@protobufjs/pool": "^1.1.0",
+ "@protobufjs/utf8": "^1.1.0",
+ "@types/node": ">=13.7.0",
+ "long": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
"node_modules/punycode": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
@@ -1962,6 +2797,15 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/require-from-string": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
@@ -2029,6 +2873,26 @@
"queue-microtask": "^1.2.2"
}
},
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
"node_modules/semver": {
"version": "7.6.3",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
@@ -2145,7 +3009,6 @@
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "dev": true,
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
@@ -2159,7 +3022,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
"dependencies": {
"ansi-regex": "^5.0.1"
},
@@ -2414,6 +3276,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
+ "license": "0BSD"
+ },
"node_modules/type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
@@ -2438,6 +3306,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/undici-types": {
+ "version": "6.19.8",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
+ "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
+ "license": "MIT"
+ },
"node_modules/uri-js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
@@ -2463,6 +3337,29 @@
"spdx-expression-parse": "^3.0.0"
}
},
+ "node_modules/websocket-driver": {
+ "version": "0.7.4",
+ "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz",
+ "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "http-parser-js": ">=0.5.1",
+ "safe-buffer": ">=5.1.0",
+ "websocket-extensions": ">=0.1.1"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/websocket-extensions": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz",
+ "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@@ -2487,6 +3384,23 @@
"node": ">=0.10.0"
}
},
+ "node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
@@ -2506,12 +3420,39 @@
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
+ "node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
},
+ "node_modules/yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "license": "MIT",
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/yargs-parser": {
"version": "20.2.9",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
@@ -2521,6 +3462,15 @@
"node": ">=10"
}
},
+ "node_modules/yargs/node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/yocto-queue": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
@@ -2617,6 +3567,450 @@
"integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==",
"dev": true
},
+ "@firebase/analytics": {
+ "version": "0.10.10",
+ "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.10.tgz",
+ "integrity": "sha512-Psdo7c9g2SLAYh6u1XRA+RZ7ab2JfBVuAt/kLzXkhKZL/gS2cQUCMsOW5p0RIlDPRKqpdNSmvujd2TeRWLKOkQ==",
+ "requires": {
+ "@firebase/component": "0.6.11",
+ "@firebase/installations": "0.6.11",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/analytics-compat": {
+ "version": "0.2.16",
+ "resolved": "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.16.tgz",
+ "integrity": "sha512-Q/s+u/TEMSb2EDJFQMGsOzpSosybBl8HuoSEMyGZ99+0Pu7SIR9MPDGUjc8PKiCFQWDJ3QXxgqh1d/rujyAMbA==",
+ "requires": {
+ "@firebase/analytics": "0.10.10",
+ "@firebase/analytics-types": "0.8.3",
+ "@firebase/component": "0.6.11",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/analytics-types": {
+ "version": "0.8.3",
+ "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.8.3.tgz",
+ "integrity": "sha512-VrIp/d8iq2g501qO46uGz3hjbDb8xzYMrbu8Tp0ovzIzrvJZ2fvmj649gTjge/b7cCCcjT0H37g1gVtlNhnkbg=="
+ },
+ "@firebase/app": {
+ "version": "0.10.16",
+ "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.10.16.tgz",
+ "integrity": "sha512-SUati2qH48gvVGnSsqMkZr1Iq7No52a3tJQ4itboSTM89Erezmw3v1RsfVymrDze9+KiOLmBpvLNKSvheITFjg==",
+ "requires": {
+ "@firebase/component": "0.6.11",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.10.2",
+ "idb": "7.1.1",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/app-check": {
+ "version": "0.8.10",
+ "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.8.10.tgz",
+ "integrity": "sha512-DWFfxxif/t+Ow4MmRUevDX+A3hVxm1rUf6y5ZP4sIomfnVCO1NNahqtsv9rb1/tKGkTeoVT40weiTS/WjQG1mA==",
+ "requires": {
+ "@firebase/component": "0.6.11",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/app-check-compat": {
+ "version": "0.3.17",
+ "resolved": "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.3.17.tgz",
+ "integrity": "sha512-a/eadrGsY0MVCBPhrNbKUhoYpms4UKTYLKO7nswwSFVsm3Rw6NslQQCNLfvljcDqP4E7alQDRGJXjkxd/5gJ+Q==",
+ "requires": {
+ "@firebase/app-check": "0.8.10",
+ "@firebase/app-check-types": "0.5.3",
+ "@firebase/component": "0.6.11",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/app-check-interop-types": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.3.tgz",
+ "integrity": "sha512-gAlxfPLT2j8bTI/qfe3ahl2I2YcBQ8cFIBdhAQA4I2f3TndcO+22YizyGYuttLHPQEpWkhmpFW60VCFEPg4g5A=="
+ },
+ "@firebase/app-check-types": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.5.3.tgz",
+ "integrity": "sha512-hyl5rKSj0QmwPdsAxrI5x1otDlByQ7bvNvVt8G/XPO2CSwE++rmSVf3VEhaeOR4J8ZFaF0Z0NDSmLejPweZ3ng=="
+ },
+ "@firebase/app-compat": {
+ "version": "0.2.46",
+ "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.46.tgz",
+ "integrity": "sha512-9hSHWE5LMqtKIm13CnH5OZeMPbkVV3y5vgNZ5EMFHcG2ceRrncyNjG9No5XfWQw8JponZdGs4HlE4aMD/jxcFA==",
+ "requires": {
+ "@firebase/app": "0.10.16",
+ "@firebase/component": "0.6.11",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/app-types": {
+ "version": "0.9.3",
+ "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.3.tgz",
+ "integrity": "sha512-kRVpIl4vVGJ4baogMDINbyrIOtOxqhkZQg4jTq3l8Lw6WSk0xfpEYzezFu+Kl4ve4fbPl79dvwRtaFqAC/ucCw=="
+ },
+ "@firebase/auth": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.8.1.tgz",
+ "integrity": "sha512-LX9N/Cf5Z35r5yqm2+5M3+2bRRe/+RFaa/+u4HDni7TA27C/Xm4XHLKcWcLg1BzjrS4zngSaBEOSODvp6RFOqQ==",
+ "requires": {
+ "@firebase/component": "0.6.11",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/auth-compat": {
+ "version": "0.5.16",
+ "resolved": "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.5.16.tgz",
+ "integrity": "sha512-YlYwJMBqAyv0ESy3jDUyshMhZlbUiwAm6B6+uUmigNDHU+uq7j4SFiDJEZlFFIz397yBzKn06SUdqutdQzGnCA==",
+ "requires": {
+ "@firebase/auth": "1.8.1",
+ "@firebase/auth-types": "0.12.3",
+ "@firebase/component": "0.6.11",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/auth-interop-types": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.4.tgz",
+ "integrity": "sha512-JPgcXKCuO+CWqGDnigBtvo09HeBs5u/Ktc2GaFj2m01hLarbxthLNm7Fk8iOP1aqAtXV+fnnGj7U28xmk7IwVA=="
+ },
+ "@firebase/auth-types": {
+ "version": "0.12.3",
+ "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.12.3.tgz",
+ "integrity": "sha512-Zq9zI0o5hqXDtKg6yDkSnvMCMuLU6qAVS51PANQx+ZZX5xnzyNLEBO3GZgBUPsV5qIMFhjhqmLDxUqCbnAYy2A==",
+ "requires": {}
+ },
+ "@firebase/component": {
+ "version": "0.6.11",
+ "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.11.tgz",
+ "integrity": "sha512-eQbeCgPukLgsKD0Kw5wQgsMDX5LeoI1MIrziNDjmc6XDq5ZQnuUymANQgAb2wp1tSF9zDSXyxJmIUXaKgN58Ug==",
+ "requires": {
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/data-connect": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/@firebase/data-connect/-/data-connect-0.1.2.tgz",
+ "integrity": "sha512-Bcf29mntFCt5V7aceMe36wnkHrG7cwbMlUVbDHOlh2foQKx9VtSXEONw9r6FtL1sFobHVYOM5L6umX35f59m5g==",
+ "requires": {
+ "@firebase/auth-interop-types": "0.2.4",
+ "@firebase/component": "0.6.11",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/database": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.0.10.tgz",
+ "integrity": "sha512-sWp2g92u7xT4BojGbTXZ80iaSIaL6GAL0pwvM0CO/hb0nHSnABAqsH7AhnWGsGvXuEvbPr7blZylPaR9J+GSuQ==",
+ "requires": {
+ "@firebase/app-check-interop-types": "0.3.3",
+ "@firebase/auth-interop-types": "0.2.4",
+ "@firebase/component": "0.6.11",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.10.2",
+ "faye-websocket": "0.11.4",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/database-compat": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-2.0.1.tgz",
+ "integrity": "sha512-IsFivOjdE1GrjTeKoBU/ZMenESKDXidFDzZzHBPQ/4P20ptGdrl3oLlWrV/QJqJ9lND4IidE3z4Xr5JyfUW1vg==",
+ "requires": {
+ "@firebase/component": "0.6.11",
+ "@firebase/database": "1.0.10",
+ "@firebase/database-types": "1.0.7",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/database-types": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.7.tgz",
+ "integrity": "sha512-I7zcLfJXrM0WM+ksFmFdAMdlq/DFmpeMNa+/GNsLyFo5u/lX5zzkPzGe3srVWqaBQBY5KprylDGxOsP6ETfL0A==",
+ "requires": {
+ "@firebase/app-types": "0.9.3",
+ "@firebase/util": "1.10.2"
+ }
+ },
+ "@firebase/firestore": {
+ "version": "4.7.5",
+ "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.7.5.tgz",
+ "integrity": "sha512-OO3rHvjC07jL2ITN255xH/UzCVSvh6xG8oTzQdFScQvFbcm1fjCL1hgAdpDZcx3vVcKMV+6ktr8wbllkB8r+FQ==",
+ "requires": {
+ "@firebase/component": "0.6.11",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.10.2",
+ "@firebase/webchannel-wrapper": "1.0.3",
+ "@grpc/grpc-js": "~1.9.0",
+ "@grpc/proto-loader": "^0.7.8",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/firestore-compat": {
+ "version": "0.3.40",
+ "resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.3.40.tgz",
+ "integrity": "sha512-18HopMN811KYBc9Ptpr1Rewwio0XF09FF3jc5wtV6rGyAs815SlFFw5vW7ZeLd43zv9tlEc2FzM0H+5Vr9ZRxw==",
+ "requires": {
+ "@firebase/component": "0.6.11",
+ "@firebase/firestore": "4.7.5",
+ "@firebase/firestore-types": "3.0.3",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/firestore-types": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-3.0.3.tgz",
+ "integrity": "sha512-hD2jGdiWRxB/eZWF89xcK9gF8wvENDJkzpVFb4aGkzfEaKxVRD1kjz1t1Wj8VZEp2LCB53Yx1zD8mrhQu87R6Q==",
+ "requires": {}
+ },
+ "@firebase/functions": {
+ "version": "0.11.10",
+ "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.11.10.tgz",
+ "integrity": "sha512-TP+Dzebazhw6+GduBdWn1kOJRFH84G2z+BW3pNVfkpFRkc//+uT1Uw2+dLpMGSSBRG7FrcDG91vcPnOFCzr15w==",
+ "requires": {
+ "@firebase/app-check-interop-types": "0.3.3",
+ "@firebase/auth-interop-types": "0.2.4",
+ "@firebase/component": "0.6.11",
+ "@firebase/messaging-interop-types": "0.2.3",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/functions-compat": {
+ "version": "0.3.16",
+ "resolved": "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.3.16.tgz",
+ "integrity": "sha512-FL7EXehiiBisNIR7mlb0i+moyWKLVfcEJgh/Wq6ZV6BdrCObpCTz7w5EvuRIEFX5e9cNL2oWInKg8S5X4HtINg==",
+ "requires": {
+ "@firebase/component": "0.6.11",
+ "@firebase/functions": "0.11.10",
+ "@firebase/functions-types": "0.6.3",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/functions-types": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.6.3.tgz",
+ "integrity": "sha512-EZoDKQLUHFKNx6VLipQwrSMh01A1SaL3Wg6Hpi//x6/fJ6Ee4hrAeswK99I5Ht8roiniKHw4iO0B1Oxj5I4plg=="
+ },
+ "@firebase/installations": {
+ "version": "0.6.11",
+ "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.11.tgz",
+ "integrity": "sha512-w8fY8mw6fxJzsZM2ufmTtomopXl1+bn/syYon+Gpn+0p0nO1cIUEVEFrFazTLaaL9q1CaVhc3HmseRTsI3igAA==",
+ "requires": {
+ "@firebase/component": "0.6.11",
+ "@firebase/util": "1.10.2",
+ "idb": "7.1.1",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/installations-compat": {
+ "version": "0.2.11",
+ "resolved": "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.11.tgz",
+ "integrity": "sha512-SHRgw5LTa6v8LubmJZxcOCwEd1MfWQPUtKdiuCx2VMWnapX54skZd1PkQg0K4l3k+4ujbI2cn7FE6Li9hbChBw==",
+ "requires": {
+ "@firebase/component": "0.6.11",
+ "@firebase/installations": "0.6.11",
+ "@firebase/installations-types": "0.5.3",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/installations-types": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.5.3.tgz",
+ "integrity": "sha512-2FJI7gkLqIE0iYsNQ1P751lO3hER+Umykel+TkLwHj6plzWVxqvfclPUZhcKFVQObqloEBTmpi2Ozn7EkCABAA==",
+ "requires": {}
+ },
+ "@firebase/logger": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.4.tgz",
+ "integrity": "sha512-mH0PEh1zoXGnaR8gD1DeGeNZtWFKbnz9hDO91dIml3iou1gpOnLqXQ2dJfB71dj6dpmUjcQ6phY3ZZJbjErr9g==",
+ "requires": {
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/messaging": {
+ "version": "0.12.14",
+ "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.14.tgz",
+ "integrity": "sha512-cSGP34jJswFvME8tdMDkvJvW6T1jEekyMSyq84AMBZ0KEpJbDWuC9n4wKT2lxUm1jaL651iZnn6g51yCl77ICg==",
+ "requires": {
+ "@firebase/component": "0.6.11",
+ "@firebase/installations": "0.6.11",
+ "@firebase/messaging-interop-types": "0.2.3",
+ "@firebase/util": "1.10.2",
+ "idb": "7.1.1",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/messaging-compat": {
+ "version": "0.2.14",
+ "resolved": "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.14.tgz",
+ "integrity": "sha512-r9weK8jTEA2aGiwy0IbMQPnzuJ0DHkOQaMxGJOlU2QZ1a7fh6RHpNtaoM+LKnn6u1NQgmAOWYNr9vezVQEm9zw==",
+ "requires": {
+ "@firebase/component": "0.6.11",
+ "@firebase/messaging": "0.12.14",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/messaging-interop-types": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.3.tgz",
+ "integrity": "sha512-xfzFaJpzcmtDjycpDeCUj0Ge10ATFi/VHVIvEEjDNc3hodVBQADZ7BWQU7CuFpjSHE+eLuBI13z5F/9xOoGX8Q=="
+ },
+ "@firebase/performance": {
+ "version": "0.6.11",
+ "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.6.11.tgz",
+ "integrity": "sha512-FlkJFeqLlIeh5T4Am3uE38HVzggliDIEFy/fErEc1faINOUFCb6vQBEoNZGaXvRnTR8lh3X/hP7tv37C7BsK9g==",
+ "requires": {
+ "@firebase/component": "0.6.11",
+ "@firebase/installations": "0.6.11",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/performance-compat": {
+ "version": "0.2.11",
+ "resolved": "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.11.tgz",
+ "integrity": "sha512-DqeNBy51W2xzlklyC7Ht9JQ94HhTA08PCcM4MDeyG/ol3fqum/+YgtHWQ2IQuduqH9afETthZqLwCZiSgY7hiA==",
+ "requires": {
+ "@firebase/component": "0.6.11",
+ "@firebase/logger": "0.4.4",
+ "@firebase/performance": "0.6.11",
+ "@firebase/performance-types": "0.2.3",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/performance-types": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.2.3.tgz",
+ "integrity": "sha512-IgkyTz6QZVPAq8GSkLYJvwSLr3LS9+V6vNPQr0x4YozZJiLF5jYixj0amDtATf1X0EtYHqoPO48a9ija8GocxQ=="
+ },
+ "@firebase/remote-config": {
+ "version": "0.4.11",
+ "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.4.11.tgz",
+ "integrity": "sha512-9z0rgKuws2nj+7cdiqF+NY1QR4na6KnuOvP+jQvgilDOhGtKOcCMq5XHiu66i73A9kFhyU6QQ2pHXxcmaq1pBw==",
+ "requires": {
+ "@firebase/component": "0.6.11",
+ "@firebase/installations": "0.6.11",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/remote-config-compat": {
+ "version": "0.2.11",
+ "resolved": "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.11.tgz",
+ "integrity": "sha512-zfIjpwPrGuIOZDmduukN086qjhZ1LnbJi/iYzgua+2qeTlO0XdlE1v66gJPwygGB3TOhT0yb9EiUZ3nBNttMqg==",
+ "requires": {
+ "@firebase/component": "0.6.11",
+ "@firebase/logger": "0.4.4",
+ "@firebase/remote-config": "0.4.11",
+ "@firebase/remote-config-types": "0.3.3",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/remote-config-types": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.3.3.tgz",
+ "integrity": "sha512-YlRI9CHxrk3lpQuFup9N1eohpwdWayKZUNZ/YeQ0PZoncJ66P32UsKUKqVXOaieTjJIOh7yH8JEzRdht5s+d6g=="
+ },
+ "@firebase/storage": {
+ "version": "0.13.4",
+ "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.13.4.tgz",
+ "integrity": "sha512-b1KaTTRiMupFurIhpGIbReaWev0k5O3ouTHkAPcEssT+FvU3q/1JwzvkX4+ZdB60Fc43Mbp8qQ1gWfT0Z2FP9Q==",
+ "requires": {
+ "@firebase/component": "0.6.11",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/storage-compat": {
+ "version": "0.3.14",
+ "resolved": "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.3.14.tgz",
+ "integrity": "sha512-Ok5FmXJiapaNAOQ8W8qppnfwgP8540jw2B8M0c4TFZqF4BD+CoKBxW0dRtOuLNGadLhzqqkDZZZtkexxrveQqA==",
+ "requires": {
+ "@firebase/component": "0.6.11",
+ "@firebase/storage": "0.13.4",
+ "@firebase/storage-types": "0.8.3",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/storage-types": {
+ "version": "0.8.3",
+ "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.8.3.tgz",
+ "integrity": "sha512-+Muk7g9uwngTpd8xn9OdF/D48uiQ7I1Fae7ULsWPuKoCH3HU7bfFPhxtJYzyhjdniowhuDpQcfPmuNRAqZEfvg==",
+ "requires": {}
+ },
+ "@firebase/util": {
+ "version": "1.10.2",
+ "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.2.tgz",
+ "integrity": "sha512-qnSHIoE9FK+HYnNhTI8q14evyqbc/vHRivfB4TgCIUOl4tosmKSQlp7ltymOlMP4xVIJTg5wrkfcZ60X4nUf7Q==",
+ "requires": {
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/vertexai": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@firebase/vertexai/-/vertexai-1.0.1.tgz",
+ "integrity": "sha512-f48MGSofhaS05ebpN7zMIv4tBqYf19pXr5/4njKtNZVLbjxUswDma0SuFDoO+IwgbdkhFxgtNctM+C1zfI/O1Q==",
+ "requires": {
+ "@firebase/app-check-interop-types": "0.3.3",
+ "@firebase/component": "0.6.11",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.10.2",
+ "tslib": "^2.1.0"
+ }
+ },
+ "@firebase/webchannel-wrapper": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.3.tgz",
+ "integrity": "sha512-2xCRM9q9FlzGZCdgDMJwc0gyUkWFtkosy7Xxr6sFgQwn+wMNIWd7xIvYNauU1r64B5L5rsGKy/n9TKJ0aAFeqQ=="
+ },
+ "@grpc/grpc-js": {
+ "version": "1.9.15",
+ "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.15.tgz",
+ "integrity": "sha512-nqE7Hc0AzI+euzUwDAy0aY5hCp10r734gMGRdU+qOPX0XSceI2ULrcXB5U2xSc5VkWwalCj4M7GzCAygZl2KoQ==",
+ "requires": {
+ "@grpc/proto-loader": "^0.7.8",
+ "@types/node": ">=12.12.47"
+ }
+ },
+ "@grpc/proto-loader": {
+ "version": "0.7.13",
+ "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz",
+ "integrity": "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==",
+ "requires": {
+ "lodash.camelcase": "^4.3.0",
+ "long": "^5.0.0",
+ "protobufjs": "^7.2.5",
+ "yargs": "^17.7.2"
+ }
+ },
"@humanwhocodes/config-array": {
"version": "0.13.0",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz",
@@ -2666,12 +4060,74 @@
"fastq": "^1.6.0"
}
},
+ "@protobufjs/aspromise": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
+ "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ=="
+ },
+ "@protobufjs/base64": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
+ "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg=="
+ },
+ "@protobufjs/codegen": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz",
+ "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg=="
+ },
+ "@protobufjs/eventemitter": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz",
+ "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q=="
+ },
+ "@protobufjs/fetch": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz",
+ "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==",
+ "requires": {
+ "@protobufjs/aspromise": "^1.1.1",
+ "@protobufjs/inquire": "^1.1.0"
+ }
+ },
+ "@protobufjs/float": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
+ "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ=="
+ },
+ "@protobufjs/inquire": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz",
+ "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q=="
+ },
+ "@protobufjs/path": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
+ "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA=="
+ },
+ "@protobufjs/pool": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
+ "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw=="
+ },
+ "@protobufjs/utf8": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
+ "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw=="
+ },
"@types/minimist": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==",
"dev": true
},
+ "@types/node": {
+ "version": "22.9.0",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.0.tgz",
+ "integrity": "sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==",
+ "requires": {
+ "undici-types": "~6.19.8"
+ }
+ },
"@types/normalize-package-data": {
"version": "2.4.4",
"resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz",
@@ -2712,14 +4168,12 @@
"ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
},
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dev": true,
"requires": {
"color-convert": "^2.0.1"
}
@@ -2815,11 +4269,20 @@
"supports-color": "^7.1.0"
}
},
+ "cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "requires": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ }
+ },
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "dev": true,
"requires": {
"color-name": "~1.1.4"
}
@@ -2827,8 +4290,7 @@
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "dev": true
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"colord": {
"version": "2.9.3",
@@ -2953,8 +4415,7 @@
"emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "dev": true
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
"error-ex": {
"version": "1.3.2",
@@ -2965,6 +4426,11 @@
"is-arrayish": "^0.2.1"
}
},
+ "escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="
+ },
"escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
@@ -3144,6 +4610,14 @@
"reusify": "^1.0.4"
}
},
+ "faye-websocket": {
+ "version": "0.11.4",
+ "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz",
+ "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==",
+ "requires": {
+ "websocket-driver": ">=0.5.1"
+ }
+ },
"file-entry-cache": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
@@ -3172,6 +4646,41 @@
"path-exists": "^4.0.0"
}
},
+ "firebase": {
+ "version": "11.0.2",
+ "resolved": "https://registry.npmjs.org/firebase/-/firebase-11.0.2.tgz",
+ "integrity": "sha512-w4T8BSJpzdZA25QRch5ahLsgB6uRvg1LEic4BaC5rTD1YygroI1AXp+W+rbMnr8d8EjfAv6t4k8doULIjc1P8Q==",
+ "requires": {
+ "@firebase/analytics": "0.10.10",
+ "@firebase/analytics-compat": "0.2.16",
+ "@firebase/app": "0.10.16",
+ "@firebase/app-check": "0.8.10",
+ "@firebase/app-check-compat": "0.3.17",
+ "@firebase/app-compat": "0.2.46",
+ "@firebase/app-types": "0.9.3",
+ "@firebase/auth": "1.8.1",
+ "@firebase/auth-compat": "0.5.16",
+ "@firebase/data-connect": "0.1.2",
+ "@firebase/database": "1.0.10",
+ "@firebase/database-compat": "2.0.1",
+ "@firebase/firestore": "4.7.5",
+ "@firebase/firestore-compat": "0.3.40",
+ "@firebase/functions": "0.11.10",
+ "@firebase/functions-compat": "0.3.16",
+ "@firebase/installations": "0.6.11",
+ "@firebase/installations-compat": "0.2.11",
+ "@firebase/messaging": "0.12.14",
+ "@firebase/messaging-compat": "0.2.14",
+ "@firebase/performance": "0.6.11",
+ "@firebase/performance-compat": "0.2.11",
+ "@firebase/remote-config": "0.4.11",
+ "@firebase/remote-config-compat": "0.2.11",
+ "@firebase/storage": "0.13.4",
+ "@firebase/storage-compat": "0.3.14",
+ "@firebase/util": "1.10.2",
+ "@firebase/vertexai": "1.0.1"
+ }
+ },
"flat-cache": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
@@ -3201,6 +4710,11 @@
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"dev": true
},
+ "get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
+ },
"glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
@@ -3326,6 +4840,16 @@
"integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==",
"dev": true
},
+ "http-parser-js": {
+ "version": "0.5.8",
+ "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz",
+ "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q=="
+ },
+ "idb": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz",
+ "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ=="
+ },
"ignore": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
@@ -3406,8 +4930,7 @@
"is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
- "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "dev": true
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
},
"is-glob": {
"version": "4.0.3",
@@ -3533,6 +5056,11 @@
"p-locate": "^5.0.0"
}
},
+ "lodash.camelcase": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
+ "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA=="
+ },
"lodash.merge": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
@@ -3545,6 +5073,11 @@
"integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==",
"dev": true
},
+ "long": {
+ "version": "5.2.3",
+ "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz",
+ "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q=="
+ },
"lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
@@ -3822,6 +5355,25 @@
"integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
"dev": true
},
+ "protobufjs": {
+ "version": "7.4.0",
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz",
+ "integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==",
+ "requires": {
+ "@protobufjs/aspromise": "^1.1.2",
+ "@protobufjs/base64": "^1.1.2",
+ "@protobufjs/codegen": "^2.0.4",
+ "@protobufjs/eventemitter": "^1.1.0",
+ "@protobufjs/fetch": "^1.1.0",
+ "@protobufjs/float": "^1.0.2",
+ "@protobufjs/inquire": "^1.1.0",
+ "@protobufjs/path": "^1.1.2",
+ "@protobufjs/pool": "^1.1.0",
+ "@protobufjs/utf8": "^1.1.0",
+ "@types/node": ">=13.7.0",
+ "long": "^5.0.0"
+ }
+ },
"punycode": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
@@ -3889,6 +5441,11 @@
"strip-indent": "^4.0.0"
}
},
+ "require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="
+ },
"require-from-string": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
@@ -3925,6 +5482,11 @@
"queue-microtask": "^1.2.2"
}
},
+ "safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
+ },
"semver": {
"version": "7.6.3",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
@@ -4011,7 +5573,6 @@
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "dev": true,
"requires": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
@@ -4022,7 +5583,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
"requires": {
"ansi-regex": "^5.0.1"
}
@@ -4214,6 +5774,11 @@
"integrity": "sha512-jRKj0n0jXWo6kh62nA5TEh3+4igKDXLvzBJcPpiizP7oOolUrYIxmVBG9TOtHYFHoddUk6YvAkGeGoSVTXfQXQ==",
"dev": true
},
+ "tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ },
"type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
@@ -4229,6 +5794,11 @@
"integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
"dev": true
},
+ "undici-types": {
+ "version": "6.19.8",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
+ "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw=="
+ },
"uri-js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
@@ -4254,6 +5824,21 @@
"spdx-expression-parse": "^3.0.0"
}
},
+ "websocket-driver": {
+ "version": "0.7.4",
+ "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz",
+ "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==",
+ "requires": {
+ "http-parser-js": ">=0.5.1",
+ "safe-buffer": ">=5.1.0",
+ "websocket-extensions": ">=0.1.1"
+ }
+ },
+ "websocket-extensions": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz",
+ "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg=="
+ },
"which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@@ -4269,6 +5854,16 @@
"integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
"dev": true
},
+ "wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ }
+ },
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
@@ -4285,12 +5880,38 @@
"signal-exit": "^4.0.1"
}
},
+ "y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="
+ },
"yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
},
+ "yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "requires": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "dependencies": {
+ "yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="
+ }
+ }
+ },
"yargs-parser": {
"version": "20.2.9",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
diff --git a/package.json b/package.json
index 72a1821..5ffc4e9 100644
--- a/package.json
+++ b/package.json
@@ -16,5 +16,8 @@
"eslint-config-google": "^0.14.0",
"stylelint": "^15.10.3",
"stylelint-config-standard": "^34.0.0"
+ },
+ "dependencies": {
+ "firebase": "^11.0.2"
}
}
diff --git a/www/penn_shield.svg b/www/penn_shield.svg
new file mode 100644
index 0000000..16e3a6d
--- /dev/null
+++ b/www/penn_shield.svg
@@ -0,0 +1 @@
+
\ No newline at end of file