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