Skip to content

Commit

Permalink
Bug Fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
DigiWorm0 committed Apr 12, 2022
1 parent f787946 commit 6dc4583
Show file tree
Hide file tree
Showing 11 changed files with 98 additions and 71 deletions.
37 changes: 29 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,37 @@
![Blitz Scouter](https://i.imgur.com/eANWZcA.png "Blitz Scouter")
<p align="center">
<a href="https://team5148.org/#/">
<img alt="Blitz Scouter" src="https://i.imgur.com/eANWZcA.png" />
</a>
</p>

# Features
- Easy to use
- Import from [The Blue Alliance](https://www.thebluealliance.com/)
- Import & Export data without internet access
- Customizable color palette
<p align="center">
<a href="https://github.com/NB-Blitz/BlitzScouter/releases">
<img alt="GitHub all releases" src="https://img.shields.io/github/downloads/NB-Blitz/BlitzScouter/total">
</a>
<a href="https://github.com/NB-Blitz/BlitzScouter/issues">
<img alt="GitHub issues" src="https://img.shields.io/github/issues/NB-Blitz/BlitzScouter">
</a>
</p>

<p align="center">
<img alt="BlitzScouter Matches" src="https://i.imgur.com/6rzXtkB.jpg" width="30%" height="30%" >
<img alt="BlitzScouter Teams" src="https://i.imgur.com/weB4lfc.jpg" width="30%" height="30%" >
</p>

# Download
.APKs can be downloaded and installed under the [Releases](https://github.com/NB-Blitz/BlitzScouter-Offline/releases) tab
At the moment, BlitzScouter is only supported on **Android** devices. APKs can be downloaded and installed under the [Releases](https://github.com/NB-Blitz/BlitzScouter/releases) tab.

# Features
- 🎨 Customizable color palette
- 📋 Customizable scouting templates
- 📷 Take and manage robot photos
- 💾 Take event data from [The Blue Alliance](https://www.thebluealliance.com/) offline
- 📁 Share data using json, csv, or QR codes
- 🥊 Quick match summaries for strategy
- 🧑‍🤝‍🧑 Sort and analyze teams

# Building
Requires [NPM](https://www.npmjs.com/) or [Yarn](https://yarnpkg.com/)
Requires [Node](https://nodejs.org/en/)
1. Install Expo:
```
npm install --global expo-cli
Expand Down
4 changes: 2 additions & 2 deletions app.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"expo": {
"name": "Blitz Scouter",
"slug": "BlitzScouter",
"version": "1.0.3",
"version": "1.1.0",
"orientation": "portrait",
"scheme": "blitz",
"icon": "./assets/images/icon.png",
Expand All @@ -22,7 +22,7 @@
"ios": {
"supportsTablet": true,
"bundleIdentifier": "com.team5148.blitzscouter",
"buildNumber": "1.0.3",
"buildNumber": "1.1.0",
"icon": "./assets/images/icon.png"
},
"android": {
Expand Down
2 changes: 1 addition & 1 deletion components/elements/CheckboxElement.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export default function CheckboxElement(props: ElementProps) {

// Vibrate
if (isChecked)
Vibration.vibrate(10);
Vibration.vibrate(30);
else
Vibration.vibrate(100);

Expand Down
2 changes: 1 addition & 1 deletion components/elements/CounterElement.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export default function CounterElement(props: ElementProps) {

// Vibrate
if (delta > 0)
Vibration.vibrate(10);
Vibration.vibrate(30);
else
Vibration.vibrate(100);

Expand Down
23 changes: 14 additions & 9 deletions hooks/useCompressedData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,21 +75,26 @@ export function useJSONImporter() {

// Check Duplicates
if (importedIDs.includes(decompressedData.exportID)) {
ToastAndroid.show("Duplicate JSON Data", ToastAndroid.SHORT);
return;
}
importedIDs.push(decompressedData.exportID);
setImportedIDs(importedIDs);

// Check Event
if (decompressedData.eventID !== event.id) {
ToastAndroid.show("Invalid Event", ToastAndroid.SHORT);
return;
}

// Append Data
scoutingData.push(...decompressedData.scoutingData);
/* // Check Event
* if (decompressedData.eventID !== event.id) {
* ToastAndroid.show("Invalid Event", ToastAndroid.SHORT);
* return;
* }
*/

// Filter & Append Data
const uniqueData = decompressedData.scoutingData.filter(scoutA =>
scoutingData.findIndex(scoutB => scoutB.id === scoutA.id) === -1
);
scoutingData.push(...uniqueData);
setScoutingData(scoutingData);
ToastAndroid.show("Imported " + scoutingData.length + " matches.", ToastAndroid.SHORT);
ToastAndroid.show("Imported " + uniqueData.length + " matches.", ToastAndroid.SHORT);
}
catch (e) {
ToastAndroid.show("Invalid Data Import", ToastAndroid.SHORT);
Expand Down
2 changes: 1 addition & 1 deletion navigation/RootNavigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export default function RootNavigator() {
<Stack.Screen name="Onboard" component={OnboardingScreen} options={{ headerShown: false }} />
<Stack.Screen name="Match" component={MatchScreen} />
<Stack.Screen name="Team" component={TeamScreen} />
<Stack.Screen name="Media" component={MediaScreen} options={{ headerStyle: { backgroundColor: "#000000" } }} />
<Stack.Screen name="Media" component={MediaScreen} options={{ headerStyle: { backgroundColor: "#000000" }, headerTintColor: "#fff" }} />
<Stack.Screen name="Year" component={YearScreen} />
<Stack.Screen name="Regional" component={RegionalScreen} />
<Stack.Screen name="Download" component={DownloadScreen} />
Expand Down
6 changes: 2 additions & 4 deletions navigation/TabNavigator.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { MaterialIcons } from '@expo/vector-icons';
import { BottomTabBarButtonProps, createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import * as React from 'react';
import { PixelRatio, TouchableNativeFeedback, View } from 'react-native';
import { TouchableNativeFeedback, View } from 'react-native';
import { usePalette } from '../hooks/usePalette';
import MatchesScreen from '../screens/Matches/MatchesScreen';
import SettingsScreen from '../screens/Settings/SettingsScreen';
Expand All @@ -13,8 +13,6 @@ const Tab = createBottomTabNavigator();
export default function TabNavigator() {
const [palette] = usePalette();

const dpi = PixelRatio.get();

const buttonNativeFeedback = ({ children, style, ...props }: BottomTabBarButtonProps) => (
<TouchableNativeFeedback
{...props}
Expand All @@ -37,7 +35,7 @@ export default function TabNavigator() {
tabBarActiveTintColor: palette.navigationTextSelected,
tabBarInactiveTintColor: palette.navigationText,
tabBarStyle: {
height: 170 / dpi,
height: 60,
borderTopWidth: 0
},
tabBarLabelStyle: {
Expand Down
64 changes: 32 additions & 32 deletions screens/Scout/ScoutingScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ import ScoutingElement from '../../components/elements/ScoutingElement';
import Subtitle from '../../components/text/Subtitle';
import Text from '../../components/text/Text';
import Title from '../../components/text/Title';
import useMatch from '../../hooks/useMatch';
import { usePalette } from '../../hooks/usePalette';
import useScoutingData, { getScoutingData, setScoutingData } from '../../hooks/useScoutingData';
import useScoutingData from '../../hooks/useScoutingData';
import useTeam from '../../hooks/useTeam';
import useTemplate from '../../hooks/useTemplate';
import { ElementData, ScoutingData } from '../../types/TemplateTypes';
Expand All @@ -18,45 +19,37 @@ export default function ScoutingScreen({ route }: any) {
const [scoutingData, setScoutingDataHook] = useScoutingData();
const [template] = useTemplate();
const [team] = useTeam(route.params.teamID);
const [match] = useMatch(route.params.matchID);
const [palette] = usePalette();

const isRed = match.redTeamIDs.includes(route.params.teamID);

const onChange = (element: ElementData) => {
const index = template.findIndex(e => e.id === element.id);
if (index >= 0)
template[index] = element;
}
const onSubmit = () => {
let data: ScoutingData = {
id: "s_" + route.params.matchID + "_" + route.params.teamID,
teamID: route.params.teamID,
matchID: route.params.matchID,
values: template.map(elem => elem.value).filter(val => val != undefined) as number[]
};
setScoutingDataHook([...scoutingData, data]);

if (navigator.canGoBack())
navigator.goBack();
if (navigator.canGoBack())
navigator.goBack();
Vibration.vibrate(200);
Alert.alert("Success", "Data has been saved to storage", [
Alert.alert("Are you sure?", "This will save your scouting data to local storage. You won't be able to return to this match in the future", [
{
text: "Undo",
onPress: () => {
getScoutingData().then((data) => {
if (data) {
const oldData = data.splice(scoutingData.length - 1, 1);
setScoutingData(scoutingData);
Vibration.vibrate(200);
Alert.alert("Success", "Last round has been cleared");
}
});
text: "Confirm", onPress: () => {
const data: ScoutingData = {
id: "s_" + route.params.matchID + "_" + route.params.teamID,
teamID: route.params.teamID,
matchID: route.params.matchID,
values: template.map(elem => elem.value).filter(val => val != undefined) as number[]
};
setScoutingDataHook([...scoutingData, data]);

if (navigator.canGoBack())
navigator.goBack();
if (navigator.canGoBack())
navigator.goBack();
Vibration.vibrate(200);
Alert.alert("Success", "Data has been saved to storage");
}
},
{
text: "OK",
style: "cancel"
}
{ text: "Cancel", style: "cancel" },
], { cancelable: true });
}

Expand All @@ -68,11 +61,11 @@ export default function ScoutingScreen({ route }: any) {
{team.mediaPaths.length > 0 ?
<Button
style={styles.thumbnail}
onPress={() => { navigator.navigate("Media", { mediaPath: team.mediaPaths[team.mediaPaths.length - 1] }) }}>
onPress={() => { navigator.navigate("Media", { mediaPath: team.mediaPaths[0] }) }}>
<Image
style={styles.thumbnail}
source={{ uri: team.mediaPaths[team.mediaPaths.length - 1] }}
key={team.id + "-" + (team.mediaPaths.length - 1)} />
source={{ uri: team.mediaPaths[0] }}
key={team.id + "-0"} />
</Button>
: null}
<View style={{ alignSelf: "center", marginLeft: 10 }}>
Expand All @@ -81,6 +74,8 @@ export default function ScoutingScreen({ route }: any) {
</View>
</View>

<View style={[styles.allianceFooter, { backgroundColor: (isRed ? "#e7311f" : "#008cf1") }]} />


{template.map((element, index) =>
<ScoutingElement
Expand Down Expand Up @@ -127,4 +122,9 @@ const styles = StyleSheet.create({
alignItems: "center",
borderRadius: 8
},
allianceFooter: {
borderRadius: 10,
height: 10,
marginTop: 5
},
});
20 changes: 11 additions & 9 deletions screens/Sharing/ExportQRHistory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,34 @@ import StandardButton from '../../components/common/StandardButton';
import Subtitle from '../../components/text/Subtitle';
import Text from '../../components/text/Text';
import Title from '../../components/text/Title';
import { usePalette } from '../../hooks/usePalette';
import useQRHistory from '../../hooks/useQRHistory';


export default function ExportQRHistory({ route }: any) {
const navigator = useNavigation<StackNavigationProp<any>>();
const [palette] = usePalette();
const [qrHistory, setQRHistory] = useQRHistory();
const version = React.useState(0);
const [version, setVersion] = React.useState(0);

// Sort By Date
React.useEffect(() => {
qrHistory.sort((a, b) => Date.parse(a.timestamp) - Date.parse(b.timestamp))
qrHistory.sort((a, b) => Date.parse(b.timestamp) - Date.parse(a.timestamp))
}, [qrHistory])

React.useEffect(() => {
const t = setInterval(() => {

})
const interval = setInterval(() => {
setVersion(v => v + 1);
}, 1000);

return () => {
clearInterval(interval);
}
}, [])

return (
<ScrollView>
<View style={styles.container}>
<Title>QR History</Title>
<Subtitle>Recover Previous Scouting Data</Subtitle>
<Subtitle>Share Previous QR Codes</Subtitle>
{qrHistory.length > 0 ?
qrHistory.map((scan, index) => {
const date = new Date(scan.timestamp);
Expand All @@ -44,7 +46,7 @@ export default function ExportQRHistory({ route }: any) {
return (
<StandardButton
key={index}
iconText={scan.scoutIDs.length.toString()}
iconType={"qr-code"}
title={title}
subtitle={scan.scoutIDs.length + " matches"}
onPress={() => { navigator.push("ExportQR", { scoutIDs: scan.scoutIDs }) }} />
Expand Down
6 changes: 3 additions & 3 deletions screens/Sharing/ExportQRScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,6 @@ export default function ExportQRScreen({ route }: any) {
setQRHistory(qrHistory);
}



Vibration.vibrate(100);
}
const onHistory = () => {
Expand All @@ -91,7 +89,9 @@ export default function ExportQRScreen({ route }: any) {
bgColor="black"
fgColor="white"
/>
<Text style={styles.text}>{scoutingChunk.length} / {scoutIDs !== undefined ? scoutingChunk.length : scoutingData.filter((scout) => !(scout.isQRCodeScanned)).length} Matches</Text>
<Text style={styles.text}>
{scoutingChunk.length} out of {scoutIDs !== undefined ? scoutingChunk.length : scoutingData.filter((scout) => !(scout.isQRCodeScanned)).length} Matches
</Text>
<Button onPress={onCheck} style={[styles.checkButton, { backgroundColor: palette.navigationSelected }]}>
<MaterialIcons name={scoutingChunk.length === MAX_SIZE && scoutIDs === undefined ? "navigate-next" : "done"} size={40} color={palette.navigationTextSelected} />
</Button>
Expand Down
3 changes: 2 additions & 1 deletion screens/Teams/TeamsScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ export default function TeamsScreen() {
selectedValue={sortType}
onValueChange={(type) => { onSort(type) }}
dropdownIconColor={palette.background}
style={{ alignSelf: "flex-end" }}>

style={{ alignSelf: "flex-end", minWidth: 200, color: palette.background }}>

<Picker.Item
label="Team Number"
Expand Down

0 comments on commit 6dc4583

Please sign in to comment.