myheats

Live heats, scoring and leaderboard for sport events
git clone https://git.in0rdr.ch/myheats.git
Log | Files | Refs | Pull requests | README | LICENSE

utils.js (3938B)


      1 import { supabase } from './supabaseClient'
      2 
      3 export const exportHeatsToCSV = async function(e) {
      4   e.preventDefault()
      5 
      6   const { data, error } = await supabase
      7     .from('heats')
      8     .select('created_at,name,location,planned_start')
      9     .csv()
     10 
     11   if (error !== null) {
     12     alert(error.message)
     13     return
     14   } else if (data.length === 0) {
     15     alert('No heats yet, nothing to export')
     16     return
     17   }
     18 
     19   exportCSV(data, "heats")
     20 }
     21 
     22 export const exportAthletesToCSV = async function(e) {
     23   e.preventDefault()
     24 
     25   const { data, error } = await supabase
     26     .from('athletes')
     27     .select('created_at,nr,firstname,lastname,birthday,school')
     28     .csv()
     29 
     30   if (error !== null) {
     31     alert(error.message)
     32     return
     33   } else if (data.length === 0) {
     34     alert('No athletes yet, nothing to export')
     35     return
     36   }
     37 
     38   exportCSV(data, "athletes")
     39 }
     40 
     41 export const exportLeaderboardToCSV = async function(e, leaderboard, heatSelection, rankingComp) {
     42   e.preventDefault()
     43 
     44   if (leaderboard.length === 0) {
     45     alert('Leaderboard is empty, nothing to export')
     46     return
     47   }
     48 
     49   // concatenante heat labels
     50   const heatNames = heatSelection.map(h => h.label)
     51 
     52   // rank leaderboard by selected comparator
     53   const heatSummaries = leaderboard.sort(rankByHeat(rankingComp)).map(i =>
     54     // for each entry i in the board, for every heat h
     55     heatSelection.map(h =>
     56       // get individual scores of the heat
     57       getScores(i, h) + " = "
     58       // get heat score sum
     59       + i.heats.find(heat => heat.heatId === h.value)?.summary
     60     )
     61   )
     62 
     63   // csv header
     64   let csv = "rank,start_nr,firstname,lastname,birthday,school,"
     65              + heatNames + "," + "best,worst,total\n"
     66 
     67   // append leaderboard score results
     68   for (let i = 0; i < leaderboard.length; i++) {
     69     csv += i+1 + "," + leaderboard[i].nr + "," + leaderboard[i].firstname + "," + leaderboard[i].lastname + ","
     70       + leaderboard[i].birthday + "," + leaderboard[i].school + ","
     71       + heatSummaries[i] + ","
     72       + leaderboard[i].bestHeat + "," + leaderboard[i].worstHeat + "," + leaderboard[i].sum + "\n"
     73   }
     74 
     75   exportCSV(csv, "scores")
     76 }
     77 
     78 // define the ranking logic
     79 export const rankByHeat = function(rankingComp) {
     80   return function(a, b) {
     81     // rank by chosen heat or ranking comparator
     82     for (const r of rankingComp) {
     83       switch(r.value) {
     84         case 'start':
     85           // rank by start number
     86           return b.nr < a.nr
     87         case 'best':
     88           if (b.bestHeat - a.bestHeat !== 0) {
     89             // rank by best heat first
     90             return b.bestHeat - a.bestHeat
     91           }
     92           // rank by least worst heat for identical best heats
     93           return b.worstHeat - a.worstHeat
     94         case 'worst':
     95           // rank by worst heat
     96           return b.worstHeat - a.worstHeat
     97         case 'total':
     98           // rank by total sum across heats
     99           return b.sum - a.sum
    100         default:
    101           // rank by heat totals
    102           if (b.heats.find(h => h.heatId === r.value)?.summary - a.heats.find(h => h.heatId === r.value)?.summary !== 0) {
    103             return b.heats.find(h => h.heatId === r.value)?.summary - a.heats.find(h => h.heatId === r.value)?.summary
    104           }
    105       }
    106     }
    107   }
    108 }
    109 
    110 // Scores concat with "+" for leaderboard entry i and heat h
    111 export const getScores = function(i, h) {
    112   const scores = i.heats.find(heat => heat.heatId === h.value)?.scores?.map(s => s.score).join(" + ")
    113   return scores === "" ? 0 : scores
    114 }
    115 
    116 // export CSV as blob
    117 const exportCSV = function(csv, fileSlug) {
    118   // create blob from csv
    119   const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' })
    120 
    121   // download blob
    122   const url = URL.createObjectURL(blob)
    123   const link = document.createElement('a')
    124   link.href = url
    125   link.download = fileSlug + "-" + new Date().toISOString() + ".csv"
    126   document.body.appendChild(link)
    127   link.click()
    128   document.body.removeChild(link)
    129   // let browser know not to keep the reference to the file
    130   URL.revokeObjectURL(url)
    131 }