Skip to content

Commit

Permalink
Merge pull request #96 from DurhamAcademy/add-multiscouting
Browse files Browse the repository at this point in the history
Add multiscouting
  • Loading branch information
Ryan-Bauroth authored Feb 16, 2024
2 parents 328541a + 9e27c5d commit 3678404
Show file tree
Hide file tree
Showing 12 changed files with 210 additions and 70 deletions.
23 changes: 22 additions & 1 deletion app.config.ts
Original file line number Diff line number Diff line change
@@ -1 +1,22 @@
export default defineAppConfig({})
export default defineAppConfig({
ui: {
primary: 'coral',
gray: 'cool'
},
buildModules: ['@nuxtjs/pwa'],
pwa: {
manifest: {
name: 'Fire hydrant surveyor',
short_name: 'Hydrant Surveyor',
lang: 'en',
display: 'standalone',
},
workbox: {
enabled: true
}
},
notifications: {
// Show toasts at the top right of the screen
position: 'top-0 right-0'
}
})
7 changes: 3 additions & 4 deletions components/FilterMultiSelect.vue
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,15 @@ const value = computed({
}
}
for(let selectedOption of value){
if(!props.options.includes(selectedOption)){
if(!props.options.includes(selectedOption)) {
let optionExists = false
for(let option in props.options){
if(props.options[2].id == selectedOption.id){
for (let option of props.options) {
if (option.id == selectedOption.id) {
optionExists = true
}
}
if(!optionExists){
props.options.push(selectedOption)
}
}
}
Expand Down
21 changes: 21 additions & 0 deletions components/OuterComponents.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,17 @@ import {eventOptions} from "~/utils/eventOptions";
const usersDB = new PouchDB(`${couchDBBaseURL}/_users`, {skip_setup: true});
const session = await usersDB.getSession()
const colorMode = useColorMode()
const isDark = computed({
get () {
return colorMode.value === 'dark'
},
set () {
colorMode.preference = colorMode.value === 'dark' ? 'light' : 'dark'
}
})
let {width, height} = useWindowSize()
let route = useRoute()
Expand Down Expand Up @@ -67,6 +78,16 @@ if (session.userCtx.roles?.indexOf("_admin") != -1) {
<UFormGroup class="inputDiv" label="Event" name="event">
<USelectMenu v-model="selectedEvent" :options="events"/>
</UFormGroup>
<br>
<ClientOnly>
<UButton
:icon="isDark ? 'i-heroicons-moon-20-solid' : 'i-heroicons-sun-20-solid'"
color="gray"
variant="ghost"
aria-label="Theme"
@click="isDark = !isDark"
/>
</ClientOnly>
<template #footer>
<UButton block label="Logout" square @click="logout"/>
</template>
Expand Down
52 changes: 30 additions & 22 deletions nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,38 +29,46 @@ export default defineNuxtConfig({
})
}
],
buildModules: ['@nuxtjs/pwa'],
pwa: {
manifest: {
name: 'Fire hydrant surveyor',
short_name: 'Hydrant Surveyor',
lang: 'en',
display: 'standalone',
},
workbox: {
enabled: true
}
},
plugins: [
'~/plugins/vuetify.ts'
],
devtools: { enabled: true },
ssr: false,
ui: {
global: true,
primary: "rose",
gray: "cool",
notifications: {
// Show toasts at the top right of the screen
position: 'top-0 right-0'
}
},
vite: {
vue: {
template: {
transformAssetUrls,
},
},
},
logLevel: "verbose"
logLevel: "verbose",
runtimeConfig:{
TBA_Key: process.env.TBA_KEY,
},
colorMode: {
preference: 'light' //eventually we will add color mode preference
},
tailwindcss:{
config:{
theme: {
extend: {
colors: {
coral: {
'50': '#fef3f2',
'100': '#fee4e2',
'200': '#fececa',
'300': '#fcaca5',
'400': '#f88379',
'500': '#ee5245',
'600': '#db3527',
'700': '#b9281c',
'800': '#99251b',
'900': '#7f251d',
'950': '#450f0a',
}
}
}
}
}
}
})
2 changes: 1 addition & 1 deletion pages/matches.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ let matc = matche.map(async (doc) => {
})
let matches = await Promise.all(matc)
for (let i=matches.length-1; i>=0; i--) {
if(matches[i].matchNumber === -1 || matches[i].matchNumber === null || (matches[i].event != currentEvent.value)) matches.splice(i, 1)
if(matches[i].matchNumber === -1 || matches[i].matchNumber === null || (matches[i].event != currentEvent)) matches.splice(i, 1)
}
const headers = [
Expand Down
6 changes: 3 additions & 3 deletions pages/scout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ let impData = {
let data = ref({
event: "",
teamNumber: null,
matchNumber: null,
event: "",
auto: {
speakerNA: 0,
amp: 0,
Expand Down Expand Up @@ -94,7 +94,7 @@ function isValidNum() {
}
async function submit() {
data.value.event = selectedEvent.value || ""
data.value.event = selectedEvent || ""
let newDoc = db.post(data.value)
await navigateTo("/matches")
}
Expand Down Expand Up @@ -173,7 +173,7 @@ async function submit() {
</div>
<div>
<h1 class="text-green-600 font-sans">Trap</h1>
<IncrementalButton v-model="data.endgame.trap" style="margin:5px"></IncrementalButton>
<IncrementalButton v-model="data.endgame.trap" :max-value="3" style="margin:5px"></IncrementalButton>
</div>
</div>
<br>
Expand Down
127 changes: 95 additions & 32 deletions pages/teams.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,23 @@ let options = {
}
}
const events = eventOptions
const events = eventOptions.map((event) => event.replace(/[0-9]/g, ''))
const currentEvent = localStorage.getItem('currentEvent') || eventOptions[0]
const fetch = useFetch<Array<any>>("/api/eventMatches/" + currentEvent)
let customOptions = ['Has Climb', 'Has Auto']
for(let event of events){
customOptions.push('event: ' + event)
}
let currentEventID = customOptions.indexOf('event: ' + currentEvent)
let currentEventID = customOptions.indexOf('event: ' + currentEvent.replace(/[0-9]/g, ''))
const filterOptions = ref(
Array(customOptions.length)
.fill({ id: 0, content: "", custom: false})
.map(
(_, index) => ({ id: index, content: customOptions[index], custom: false})
)
)
const currentEventFilter = { id: currentEventID, content: 'event: ' + currentEvent, custom: false }
const currentEventFilter = { id: currentEventID, content: 'event: ' + currentEvent.replace(/[0-9]/g, ''), custom: false }
const selectedFilters = ref<Array<{ id: number, content: string, custom: boolean}>>([currentEventFilter])
watch(selectedFilters, () => {
tableSetup()
Expand All @@ -53,34 +54,86 @@ let teamOrgMatches = new Map<number, Array<any>>()
for(let i = 0; i < match.length; i++){
let currentMatch = (await match[i])
if (!teamOrgMatches.has(currentMatch.teamNumber))
teamOrgMatches.set(currentMatch.teamNumber, [currentMatch])
let team = typeof currentMatch.teamNumber == "string" ? parseInt(currentMatch.teamNumber): currentMatch.teamNumber
if (!teamOrgMatches.has(team))
teamOrgMatches.set(team, [currentMatch])
else
teamOrgMatches.get(currentMatch.teamNumber)!.push(currentMatch)
teamOrgMatches.get(team)!.push(currentMatch)
}
let teamsData= ref<Array<any>>([])
/*
If there are two overlapping matches uses data from only one of them (very basic system needs improvement)
*/
for(let team of teamOrgMatches){
let matches = teamOrgMatches.get(team[0])
let matchNumbers: number[] = []
if(matches) {
for (let i = 0; i < matches.length; i++) {
let currMatch = matches[i].matchNumber
if(matchNumbers.includes(currMatch)) {
teamOrgMatches.set(team[0], team[1].splice(team[1].indexOf(currMatch), 1))
}
else matchNumbers.push(currMatch)
}
}
}
let teamsData = ref<Array<any>>([])
function tableSetup() {
async function tableSetup() {
teamsData.value.length = 0
/*
Creates two arrays that are filters applied on all data for team numbers and events (includes match number filter)
*/
let allowedEvents = []
let allowedTeams = []
let blueAlliance = []
let redAlliance = []
for (let filter of selectedFilters.value) {
if (filter.content.startsWith("event:")) {
allowedEvents.push(filter.content.split(":")[1].trim())
}
if (filter.content.startsWith("team:")) {
allowedTeams.push(filter.content.split(":")[1].trim())
}
if (filter.content.startsWith("match")) {
//TODO figure out async stuff
let tbaMatchData = fetch.data.value
if(tbaMatchData != null){
let userInput = parseInt(filter.content.split(':')[1].trim())
for(let match of tbaMatchData){
if(match.comp_level == "qm" && match.match_number == userInput){
for(let team of match.alliances.blue.team_keys){
let cleanedTeam = team.replace("frc", "")
if(!allowedTeams.includes(cleanedTeam)) {
allowedTeams.push(cleanedTeam)
blueAlliance.push(cleanedTeam)
}
}
for(let team of match.alliances.red.team_keys){
let cleanedTeam = team.replace("frc", "")
if(!allowedTeams.includes(cleanedTeam)) {
allowedTeams.push(cleanedTeam)
redAlliance.push(cleanedTeam)
}
}
}
}
}
}
}
tableLoop: for (let [key, value] of teamOrgMatches) {
/*
Data is an array of all matches, associated with a team (key), for the event filters selected
*/
let data: any = []
let allowedEvents = []
let allowedTeams = []
for(let filter of selectedFilters.value){
if(filter.content.startsWith("event:")){
allowedEvents.push(filter.content.split(":")[1].trim())
}
if(filter.content.startsWith("team:")){
allowedTeams.push(filter.content.split(":")[1].trim())
}
}
if(allowedTeams.includes(key.toString()) || allowedTeams.length == 0){
for(let match of value){
if(allowedEvents.includes(match.event)){
//if sorted by match apply alliance colors
let alliance = blueAlliance.includes(key.toString()) ? "bg-blue-100": redAlliance.includes(key.toString()) ? "bg-red-100": ""
if (allowedTeams.includes(key.toString()) || allowedTeams.length == 0) {
for (let match of value) {
if (allowedEvents.includes(match.event.replace(/[0-9]/g, ''))) {
data.push(match)
}
}
Expand All @@ -90,45 +143,55 @@ function tableSetup() {
*/
for (let filter of selectedFilters.value) {
if(filter.id == 0){
if (filter.id == 0) {
let hasClimb = false
for(let match of data){
if(match.endgame.endgame.includes("Onstage") || match.endgame.endgame.includes("Attempted Onstage")){
for (let match of data) {
if (match.endgame.endgame.includes("Onstage") || match.endgame.endgame.includes("Attempted Onstage")) {
hasClimb = true
break
}
}
if(!hasClimb){
if (!hasClimb) {
continue tableLoop
}
}
if(filter.id == 1){
if (filter.id == 1) {
let hasAuto = false
for(let match of data){
if(match.auto.amp > 0 || match.auto.speaker > 0 || match.auto.mobility == true){
for (let match of data) {
if (match.auto.amp > 0 || match.auto.speaker > 0 || match.auto.mobility == true) {
hasAuto = true
break
}
}
if(!hasAuto){
if (!hasAuto) {
continue tableLoop
}
}
}
if(data.length > 0) {
if (data.length > 0) {
let arr = {
team: key,
amp: getAverageAmpCycles(data).toFixed(2),
speaker: getAverageSpeakerCycles(data).toFixed(2),
mobility: averageAuto(data).toFixed(2),
sentiment: analyzeNotes(data).toFixed(2),
endgame: compileEndgames(data)
endgame: compileEndgames(data),
class: alliance
}
teamsData.value.push(arr)
}
}
//Defaults to the alliance colors being together if match filter is selected
if(redAlliance.length > 0 || blueAlliance.length > 0){
let sortedData = []
for(let team of teamsData.value){
if(team.class == "bg-blue-100") sortedData.unshift(team)
else sortedData.push(team)
}
teamsData.value = sortedData
}
}
function analyzeNotes(teamArrays: Array<any>){
Expand Down
2 changes: 1 addition & 1 deletion pages/users.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
let username = ref("")
let roles = ref([[""]])
const roleOptions = ["Admin", "Coach", "Scout"]
const roleOptions = ["Coach", "Scout"]
let prevRoles: string[][] = [[]]
let resetRoles = false
Expand Down
Loading

0 comments on commit 3678404

Please sign in to comment.