Skip to content

Commit

Permalink
Merge branch 'development'
Browse files Browse the repository at this point in the history
  • Loading branch information
Acr515 committed Mar 8, 2024
2 parents 8a050b6 + b3c31f3 commit 9f1909c
Show file tree
Hide file tree
Showing 41 changed files with 3,843 additions and 1,963 deletions.
5,122 changes: 3,276 additions & 1,846 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "fortyeight",
"version": "3.1.0",
"version": "3.1.1",
"description": "",
"homepage": "./",
"main": "index.js",
Expand All @@ -19,6 +19,7 @@
"@babel/preset-env": "^7.16.0",
"@babel/preset-react": "^7.16.0",
"babel-loader": "^8.2.3",
"copy-webpack-plugin": "^12.0.2",
"css-loader": "^6.5.1",
"eslint": "^8.32.0",
"eslint-config-react": "^1.1.7",
Expand All @@ -33,7 +34,8 @@
"url-loader": "^4.1.1",
"webpack": "^5.64.0",
"webpack-cli": "^5.0.1",
"webpack-dev-server": "^4.4.0"
"webpack-dev-server": "^4.4.0",
"workbox-webpack-plugin": "^7.0.0"
},
"dependencies": {
"@babel/runtime": "^7.17.9",
Expand Down
Binary file added public/favicon.ico
Binary file not shown.
4 changes: 3 additions & 1 deletion public/index.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
<!DOCTYPE html>
<html>
<head>
<title>Live Development Build</title>
<title>FortyEight Scouting App</title>
<link rel="manifest" href="./manifest.json" />
<meta name="viewport" content="width=device-width, initial-scale=0.9">
</head>
<body>
<div id="app"></div>
Expand Down
30 changes: 30 additions & 0 deletions public/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"short_name": "FortyEight",
"name": "FortyEight: FRC Scouting",
"icons": [
{
"src": "../pwa-icons/icon_1024.png",
"sizes": "1024x1024",
"type": "image/png"
},
{
"src": "../pwa-icons/icon_512.png",
"sizes": "512x512",
"type": "image/png"
},
{
"src": "../pwa-icons/icon_196.png",
"sizes": "196x196",
"type": "image/png"
},
{
"src": "../pwa-icons/icon_144.png",
"sizes": "144x144",
"type": "image/png"
}
],
"start_url": "../",
"display": "standalone",
"theme_color": "#4941B1",
"background_color": "#fff"
}
Binary file added src/assets/images/pwa-icons/icon_1024.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/images/pwa-icons/icon_144.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/images/pwa-icons/icon_196.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/images/pwa-icons/icon_512.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/images/three-dots.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/images/three-lines.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions src/components/DialogBox/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,15 @@ export default function DialogBox({options, revealed, revealFunction}) {
action={() => { options.confirmFunction(); revealFunction(); }}
marginTop={1}
marginBottom={1}
style={{ minWidth: 150, display: "inline-block", marginRight: 16 }}
style={{ minWidth: 120 }}
/>
)}
<Button
text={options.cancelLabel}
action={options.cancelFunction}
marginTop={1}
marginBottom={1}
style={{ minWidth: 150, display: "inline-block" }}
style={{ minWidth: 120 }}
/>
</div>
</div>
Expand Down
6 changes: 4 additions & 2 deletions src/components/DialogBox/style.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
._DialogBox {
position: fixed;
z-index: 10;
z-index: 200;
top: 0;
bottom: 0;
left: 0;
Expand Down Expand Up @@ -28,7 +28,9 @@
text-align: center;
}
.button-area {
text-align: center;
display: flex;
justify-content: center;
gap: 8px;
margin-top: 30px;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/FeedbackModal/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

._FeedbackModal {
position: absolute;
z-index: 5;
z-index: 150;
top: 16px;
left: 0;
right: 0;
Expand Down
5 changes: 3 additions & 2 deletions src/components/Input/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ import Chevron from '../../assets/images/chevron.png';
* @param labelStyle Any custom CSS styles to apply to the label
* @param externalUpdate If you wish to have control over this input's values using state from its parent, its state should be set using this property. A `useEffect()` hook will run when it changes
* @param getExternalUpdate This function should return a value that will be used to set the value state of this input component
* @param floodLabel Optional. When true, floods the available space with the label instead of the normal 50/50 width split
*/
export default function Input({label, prefill, id, onInput, isCheckbox, isNumerical, optionList, marginBottom, alignLabel = "middle", textArea = false, required = false, disabled = false, warning = false, style = {}, labelStyle = {}, externalUpdate = null, getExternalUpdate = null}) {
export default function Input({ label, prefill, id, onInput, isCheckbox, isNumerical, optionList, marginBottom, alignLabel = "middle", textArea = false, required = false, disabled = false, warning = false, style = {}, labelStyle = {}, externalUpdate = null, getExternalUpdate = null, floodLabel = false }) {

optionList = typeof optionList !== "undefined" ? optionList : false;

Expand Down Expand Up @@ -54,7 +55,7 @@ export default function Input({label, prefill, id, onInput, isCheckbox, isNumeri
}, [externalUpdate])

return (
<div className="_Input" style={{ ...style, marginBottom: marginBottom || 18 }}>
<div className={`_Input ${floodLabel ? "flood-label" : ""}`} style={{ ...style, marginBottom: marginBottom || 18 }}>
{ typeof label !== 'undefined' && (
<label
htmlFor={id}
Expand Down
11 changes: 11 additions & 0 deletions src/components/Input/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,15 @@
}
}
}

&.flood-label {
label {
flex-grow: 1;
}
.input-area {
flex-grow: 0;
width: unset;
margin-left: auto;
}
}
}
8 changes: 7 additions & 1 deletion src/components/PageHeader/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,10 @@
._BackButton .back-button-image {
transform: translateY(-6px) rotate(-90deg);
}
}
}

@media screen and (max-width: 850px) {
._PageHeader {
padding-left: 58px;
}
}
12 changes: 9 additions & 3 deletions src/components/PlayoffHelperTeam/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export default function PlayoffHelperTeam({ team, isOnTheClock = false, captain

// Get flag #s
let breakdowns = 0, fouls = 0;
getTeamData(team.teamNumber).data.forEach(match => {
if (getTeamData(team.teamNumber) !== null) getTeamData(team.teamNumber).data.forEach(match => {
breakdowns += match.performance.notes.broken;
fouls += match.performance.notes.fouls;
});
Expand All @@ -103,11 +103,17 @@ export default function PlayoffHelperTeam({ team, isOnTheClock = false, captain
{ (breakdowns > 0 || fouls > 0) &&
<div className="row">Broke down in <span className="strong">{breakdowns}</span> matches, drew excessive fouls in <span className="strong">{fouls}</span> matches</div>
}
{ team.uniqueStrengthAdded != -1 &&
{ (team.uniqueStrengthAdded != -1 && team.uniqueStrengthAdded > 0) &&
<div className="row">Ranks <span className="strong">{getOrdinalSuffix(team.uniqueStrengthAddedRank)}</span> against remaining teams in improving the alliance&apos;s weaknesses ({Math.round(team.uniqueStrengthAdded * playoffHelper.data.config.weightOfUniqueStrengths * 10) / 10} points added to base score above)</div>
}
{ (team.uniqueStrengthAdded != -1 && team.uniqueStrengthAdded == 0) &&
<div className="row">No measurable addition to alliance&apos;s skillset</div>
}
{ team.simulatedWinRate != -1 &&
<div className="row">Simulator estimates a <span className="strong">{estimatedWinRate}%</span> win rate against alliance&apos;s first round opponent ({getOrdinalSuffix(team.simulatedWinRateRank)} among remaining teams)</div>
<div className="row">
Simulator estimates a <span className="strong">{estimatedWinRate}%</span> win rate against alliance&apos;s first round opponent
{ estimatedWinRate > 0 ? `(${getOrdinalSuffix(team.simulatedWinRateRank)} among remaining teams)` : "" }
</div>
}
</>
};
Expand Down
6 changes: 3 additions & 3 deletions src/config.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
export const VERSION_NAME = "2024.1.0";
export const VERSION_NAME = "2024.1.1";

export const VERSION_NUMBER = 2024.10;
export const VERSION_NUMBER = 2024.11;

export const PACKAGE_VERSION_NUMBER = "3.1.0";
export const PACKAGE_VERSION_NUMBER = "3.1.1";

export const TBA_KEY = "dX1DPbvtl0K3mmtRLUCnep8YnigOGsgOpW449DOBgxWD7fIL5kOzdPLFf7x1liKm";

Expand Down
5 changes: 4 additions & 1 deletion src/data/PlayoffHelperData.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ const PlayoffHelperFunctions = {
* @param {function} phSetter The state setter from the FRAME screen
* @param {PlayoffHelperState} mode Either `SIMULATED_DRAFT` or `LIVE_DRAFT` based on user input
* @param {boolean} backupSelections If true, alliances will have four teams
* @returns 1 if successful, 0 otherwise
*/
setup: (ph, phSetter, mode, backupSelections) => {
let playoffHelper = clonePlayoffHelper(ph);
Expand All @@ -108,11 +109,12 @@ const PlayoffHelperFunctions = {
let returnValue = team.calculatePowerScores();
if (returnValue !== null) emptyTeams.push(returnValue);
});
console.log(emptyTeams)
if (emptyTeams.length > 0) {
// Throw error
phSetter(playoffHelper);
console.error("Analysis was halted- the following teams don't have data in memory: " + emptyTeams.toString());
return;
return 0;
}

// Rank every attribute of every team
Expand All @@ -138,6 +140,7 @@ const PlayoffHelperFunctions = {
playoffHelper.config.backupSelections = backupSelections;

phSetter(playoffHelper);
return 1;
},

/**
Expand Down
6 changes: 3 additions & 3 deletions src/data/game_specific/Simulator/2024.js
Original file line number Diff line number Diff line change
Expand Up @@ -282,14 +282,14 @@ const SimulationInformation = {
// For every TWO notes scored in the AMP, provide amplification of 1-4 SPEAKER notes, dependent on the rate of speaker scoring
// Count # of possible amplifications during the course of the game and the number of possible amplified speaker scores
let teleopAmpNotes = 0, speakerNotes = 0, maxAmplifications = 0;
const AMPLIFY_PERIOD = 120, AMPLIFY_COOLDOWN = 15; // assuming that amplification would only possibly happen during teleop and not during last 15 seconds, also assuming 15 seconds between amplifications
const AMPLIFY_PERIOD = 120, AMPLIFY_COOLDOWN = 12; // assuming that amplification would only possibly happen during teleop and not during last 15 seconds, also assuming 12 seconds between amplifications
performances.forEach(p => {
teleopAmpNotes += p.teleop.amp;
speakerNotes += p.teleop.speaker;
});

maxAmplifications = Math.min(teleopAmpNotes / 2, AMPLIFY_PERIOD / AMPLIFY_COOLDOWN); // there is a ceiling to the # of amplifications in a match
if (maxAmplifications > 1) maxAmplifications = Math.max(2, maxAmplifications - Math.round(rng())); // randomly remove an amplification
maxAmplifications = Math.min(teleopAmpNotes / 2, AMPLIFY_PERIOD / AMPLIFY_COOLDOWN); // there is a ceiling to the # of amplifications in a match
//if (maxAmplifications > 1) maxAmplifications = Math.max(2, maxAmplifications - Math.round(rng())); // randomly remove an amplification
let speakerRate = speakerNotes / AMPLIFY_PERIOD; // # of notes in speaker per second
gameStats.amplifiedNotes = Math.min(maxAmplifications * 4, Math.ceil(10 * maxAmplifications * speakerRate));// 10 seconds of amplification * # of amplifications * speaker notes per second = # of amplified notes
},
Expand Down
11 changes: 6 additions & 5 deletions src/data/game_specific/calculateRPI/2024.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export default function calculateRPI(team) {
export function calculateSingleRPI(data, round) {
let RPI = 0;
RPI += ScoreCalculator.Auto.getScore(data) + ScoreCalculator.Teleop.getScore(data) + ScoreCalculator.Endgame.getScore(data);
RPI += data.performance.teleop.amp * .5 + data.performance.auto.amp;

if (data.performance.notes.fouls) RPI -= 3;

Expand All @@ -33,10 +34,10 @@ export function calculateSingleRPI(data, round) {
*/
export function getRPIRating(rpi) {
if (rpi <= 5) return "Very Poor";
else if (rpi <= 11) return "Poor";
else if (rpi <= 17) return "Average";
else if (rpi <= 25) return "Good";
else if (rpi <= 32) return "Very Good";
else if (rpi <= 41) return "Excellent";
else if (rpi <= 10) return "Poor";
else if (rpi <= 16) return "Average";
else if (rpi <= 23) return "Good";
else if (rpi <= 30) return "Very Good";
else if (rpi <= 39) return "Excellent";
else return "Godly";
}
20 changes: 15 additions & 5 deletions src/data/game_specific/weighTeam/2024.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,21 @@ export const Weights = {
* for a team to be ranked "the best" in
*/
export const WeightSets = {
// Composite score focuses on amp scoring ability
AmpScorer: {
Autonomous: 1.35,
Speaker: 0.25,
Amp: 2.5,
Endgame: 0.75,
Defense: 0.25,
Flags: 1.75
},
// Every year should have a `WellRounded` set, which uses a wholistic approach to analyze a team
WellRounded: {
Autonomous: 2,
Speaker: 2.8,
Speaker: 2.4,
Amp: 2.2,
Endgame: 1.8,
Endgame: 1.6,
Defense: 1,
Flags: 1
},
Expand All @@ -32,15 +41,16 @@ export const WeightSets = {
Endgame: 1.5,
Defense: 2.75,
Flags: 2
}
},
};

/**
* Converts the above weight sets into readable names.
*/
export const WeightSetNames = {
WellRounded: "well-rounded",
Defensive: "defensive",
AmpScorer: "amp-focused",
WellRounded: "well-rounded",
}

/**
Expand Down Expand Up @@ -78,7 +88,7 @@ export default function weighTeam(team, weights) {
// Compile a team's negative flags (penalties, break-downs)
if (match.performance.notes.misses) score.Flags -= 1;
if (match.performance.notes.fouls) score.Flags -= 2;
if (match.performance.notes.broken) score.Flags -= 3.5;
if (match.performance.notes.broken) score.Flags -= 3;
});

let composite = 0;
Expand Down
4 changes: 3 additions & 1 deletion src/index.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
<!DOCTYPE html>
<html>
<head>
<title>FortyEight Scouting Program</title>
<title>FortyEight Scouting App</title>
<link rel="manifest" href="./manifest.json" />
<meta name="viewport" content="width=device-width, initial-scale=0.9">
</head>
<body>
<div id="app"></div>
Expand Down
11 changes: 11 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,17 @@ import ReactDOM from 'react-dom';
import App from './App';
import { HashRouter } from 'react-router-dom';

if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/service-worker.js')
.then(registration => {
console.log('SW registered: ', registration);
}).catch(registrationError => {
console.log('SW registration failed: ', registrationError);
});
});
}

ReactDOM.render(
<HashRouter>
<App />
Expand Down
Loading

0 comments on commit 9f1909c

Please sign in to comment.