@@ -55,6 +55,17 @@ function addTableCell(row: HTMLTableRowElement, content: string, rowspan = 1) {
5555 if ( rowspan > 1 ) cell . setAttribute ( "rowspan" , String ( rowspan ) ) ;
5656 row . appendChild ( cell ) ;
5757}
58+
59+ const downloadIcon = " <svg xmlns=\"http://www.w3.org\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"feather feather-download\">\n" +
60+ " <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\"></path><polyline points=\"7 10 12 15 17 10\"></polyline><line x1=\"12\" y1=\"15\" x2=\"12\" y2=\"3\"></line>\n" +
61+ " </svg>"
62+
63+ function addTableCellWithDownloadCSV ( row : HTMLTableRowElement , content : string , rowspan = 1 ) {
64+ const cell = ce ( "td" ) ;
65+ cell . innerHTML = content + " <a class='downloadCSV'>" + downloadIcon + "</a>"
66+ if ( rowspan > 1 ) cell . setAttribute ( "rowspan" , String ( rowspan ) ) ;
67+ row . appendChild ( cell ) ;
68+ }
5869/**
5970 * Fills an HTML row with empty cells
6071 * @param row The HTML row to fill
@@ -63,6 +74,32 @@ function addTableCell(row: HTMLTableRowElement, content: string, rowspan = 1) {
6374function fillTableRow ( row : HTMLTableRowElement , count : number ) {
6475 for ( let i = 0 ; i < count ; i ++ ) addTableCell ( row , "" ) ;
6576}
77+ function makeCsv ( arr : varBuy [ ] ) : string {
78+ let csvTotal = "variable,level,cost,timeStamp\n" ;
79+ for ( let item of arr ) {
80+ csvTotal += `"${ item . variable } ",${ item . level } ,${ logToExp ( item . cost , 2 ) } ${ getCurrencySymbol ( item . symbol ) } ,${ convertTime ( item . timeStamp ) } \n` ;
81+ }
82+ return csvTotal ;
83+ }
84+ function downloadCSV ( csv : string , filename : string ) {
85+ const blob = new Blob ( [ csv ] , { type : 'text/csv;charset=utf-8;' } ) ;
86+ const link = document . createElement ( 'a' ) ;
87+
88+ // Create a URL for the blob
89+ // @ts -ignore
90+ if ( navigator . msSaveBlob ) { // IE 10+
91+ // @ts -ignore
92+ navigator . msSaveBlob ( blob , filename ) ;
93+ } else {
94+ const url = URL . createObjectURL ( blob ) ;
95+ link . setAttribute ( 'href' , url ) ;
96+ link . setAttribute ( 'download' , filename ) ;
97+ link . style . visibility = 'hidden' ;
98+ document . body . appendChild ( link ) ;
99+ link . click ( ) ;
100+ document . body . removeChild ( link ) ; // Clean up the DOM element
101+ }
102+ }
66103
67104/** Binds a var buy list to the last cell of a result row */
68105const bindVarBuy = ( row : HTMLTableRowElement , buys : varBuy [ ] , addToTotal = true ) => {
@@ -76,6 +113,17 @@ const bindVarBuy = (row: HTMLTableRowElement, buys: varBuy[], addToTotal = true)
76113 openVarModal ( buys ) ;
77114 } ;
78115 lastChild . style . cursor = "pointer" ;
116+ let downloadBtns = lastChild . querySelectorAll ( ".downloadCSV" ) ;
117+ if ( downloadBtns . length === 0 ) {
118+ return ;
119+ }
120+ else {
121+ let btn = downloadBtns [ 0 ] as HTMLElement ;
122+ btn . onclick = ( ) => {
123+ const csvOut = makeCsv ( buys ) ;
124+ downloadCSV ( csvOut , "buys.csv" ) ;
125+ }
126+ }
79127 }
80128
81129// Var buy utils
@@ -135,7 +183,7 @@ function writeSingleSimResponse(response: SingleSimResponse) {
135183 addTableCell ( row , formatNumber ( res . pubMulti ) ) ;
136184 addTableCell ( row , res . strat ) ;
137185 addTableCell ( row , res . tauH == 0 ? "0" : formatNumber ( res . tauH ) ) ;
138- addTableCell ( row , convertTime ( res . time ) ) ;
186+ addTableCellWithDownloadCSV ( row , convertTime ( res . time ) ) ;
139187 bindVarBuy ( row , res . boughtVars ) ;
140188 tbody . append ( row ) ;
141189}
@@ -157,7 +205,12 @@ function writeChainSimResponse(response: ChainSimResponse) {
157205 addTableCell ( labelRow , `Average ${ tau } /h` ) ;
158206 addTableCell ( resRow , formatNumber ( response . averageRate , 5 ) ) ;
159207 addTableCell ( labelRow , `Total Time` ) ;
160- addTableCell ( resRow , convertTime ( response . totalTime ) ) ;
208+ if ( generateTotalPurchaseList . checked ) {
209+ addTableCellWithDownloadCSV ( resRow , convertTime ( response . totalTime ) ) ;
210+ }
211+ else {
212+ addTableCell ( resRow , convertTime ( response . totalTime ) ) ;
213+ }
161214
162215 tbody . append ( labelRow ) ;
163216 tbody . append ( resRow ) ;
@@ -174,7 +227,7 @@ function writeStepSimResponse(response: StepSimResponse) {
174227 if ( generateTotalPurchaseList . checked ) {
175228 const resRow = ce < HTMLTableRowElement > ( "tr" ) ;
176229 fillTableRow ( resRow , 8 ) ;
177- addTableCell ( resRow , "Total" ) ;
230+ addTableCellWithDownloadCSV ( resRow , "Total" ) ;
178231 bindVarBuy ( resRow , totalBuys , false ) ;
179232 tbody . append ( resRow ) ;
180233 }
@@ -187,7 +240,7 @@ function writeSimAllResponse(response: SimAllResponse) {
187240 addTableCell ( row , res . strat ) ;
188241 addTableCell ( row , convertTime ( res . time ) ) ;
189242 addTableCell ( row , logToExp ( res . deltaTau , 2 ) ) ;
190- addTableCell ( row , logToExp ( res . pubRho , 2 ) ) ;
243+ addTableCellWithDownloadCSV ( row , logToExp ( res . pubRho , 2 ) ) ;
191244 bindVarBuy ( row , res . boughtVars ) ;
192245 }
193246
@@ -210,33 +263,33 @@ function writeSimAllResponse(response: SimAllResponse) {
210263 if ( response . stratType == "all" ) {
211264 const rowActive = ce < HTMLTableRowElement > ( "tr" ) ;
212265 const rowPassive = ce < HTMLTableRowElement > ( "tr" ) ;
213-
266+
214267 addTableCell ( rowActive , res . theory , 2 ) ;
215268 addTableCell ( rowActive , logToExp ( res . lastPub , 2 ) , 2 ) ;
216269 addTableCell ( rowActive , formatNumber ( res . ratio , 4 ) , 2 ) ;
217-
270+
218271 completeSimAllLine ( rowActive , res . active ) ;
219272 completeSimAllLine ( rowPassive , res . idle ) ;
220-
273+
221274 tbody . appendChild ( rowActive ) ;
222275 tbody . appendChild ( rowPassive ) ;
223276 }
224277 else {
225278 const uniqueRes = response . stratType == "active" ? res . active : res . idle ;
226279 const row = ce < HTMLTableRowElement > ( "tr" ) ;
227-
280+
228281 addTableCell ( row , res . theory ) ;
229282 addTableCell ( row , logToExp ( res . lastPub , 2 ) ) ;
230283 completeSimAllLine ( row , uniqueRes ) ;
231-
284+
232285 tbody . appendChild ( row ) ;
233286 }
234287 } )
235288
236289 if ( i < sets . length - 1 ) {
237290 const bufferRow1 = ce < HTMLTableRowElement > ( "tr" ) ;
238291 const bufferRow2 = ce < HTMLTableRowElement > ( "tr" ) ;
239-
292+
240293 bufferRow1 . style . display = "none" ;
241294 addTableCell ( bufferRow2 , "---" ) ;
242295
@@ -290,4 +343,4 @@ export function writeSimResponse(response: SimResponse) {
290343 case "step" : writeStepSimResponse ( response ) ; break ;
291344 case "all" : writeSimAllResponse ( response ) ; break ;
292345 }
293- }
346+ }
0 commit comments