From 9d20482fa7069d2f71c8ca0d58d9c31ceb93a44f Mon Sep 17 00:00:00 2001 From: Elliptic Ellipsis Date: Wed, 15 Dec 2021 16:58:12 +0000 Subject: [PATCH] Progress boxes constructed separately (Still need to fix numbering) --- .../game-summary/game-summary.component.ts | 4 +- .../game-chart/game-chart.component.ts | 31 +++--- .../game-progress.component.html | 44 +++++++- .../game-progress/game-progress.component.ts | 101 ++++++++---------- src/app/games/game/game.component.html | 9 +- src/app/games/game/game.component.ts | 32 ++++-- src/app/games/games.service.interface.ts | 44 ++++---- src/assets/csv/progress-mm-matching.csv | 1 - src/assets/csv/progress-mm-nonmatching.csv | 1 - src/assets/json/games.json | 66 ++++++------ 10 files changed, 183 insertions(+), 150 deletions(-) diff --git a/src/app/games/game-summaries/game-summary/game-summary.component.ts b/src/app/games/game-summaries/game-summary/game-summary.component.ts index 8d9784b..51b1062 100644 --- a/src/app/games/game-summaries/game-summary/game-summary.component.ts +++ b/src/app/games/game-summaries/game-summary/game-summary.component.ts @@ -34,13 +34,13 @@ export class GameSummaryComponent implements OnChanges { ngOnChanges(): void { // Matching is second - this.gamesService.getGameCSV(this.data.csv_info[1].data).subscribe( + this.gamesService.getGameCSV(this.data.csvData[1]).subscribe( res => { const points = res.split("\n").filter((line) => line != ""); const latestPoint = points[points.length - 1]; const column = latestPoint.split(","); - let i = this.data.charts[0].index; + let i = this.data.progressMeta[0].index; this.total = +column[i] / +column[i + 1]; }, err => console.error(err) diff --git a/src/app/games/game/game-progress/game-chart/game-chart.component.ts b/src/app/games/game/game-progress/game-chart/game-chart.component.ts index 9e2fc4a..7e11d0e 100644 --- a/src/app/games/game/game-progress/game-chart/game-chart.component.ts +++ b/src/app/games/game/game-progress/game-chart/game-chart.component.ts @@ -15,14 +15,10 @@ export class GameChartComponent implements OnChanges { constructor() { } - /** - * The names of the lines to use in this chart. - */ - // @Input() line_names: string[] = null; /** * The CSV data to use for this chart. */ - @Input() datasets: string[] = null; + @Input() csvData: string[] = null; /** * The chart metadata stored in the game settings. */ @@ -34,24 +30,28 @@ export class GameChartComponent implements OnChanges { ngOnChanges(): void { // don't do anything until all inputs are provided - if (typeof this.datasets !== "object" || typeof this.metadata !== "object") { + if (typeof this.csvData !== "object" || typeof this.metadata !== "object") { return; } // set up chart data const metadata = this.metadata; - let nonmatchingData = this.parseData(this.datasets[0]); - let matchingData = this.parseData(this.datasets[1]); + let nonmatchingData = this.parseData(this.csvData[0]); + let matchingData = this.parseData(this.csvData[1]); // Names for lines - let nonmatchingName = this.metadata.line_names[0]; - let matchingName = this.metadata.line_names[1]; + let nonmatchingName = this.metadata.series[0]; + let matchingName = this.metadata.series[1]; let joined = Array.prototype.concat(matchingData, nonmatchingData); joined.sort((a, b) => a["y"] - b["y"]); const interval = 1 / 5; - const max = Math.max(interval, Math.ceil(joined.slice(-1)[0].y / interval) * interval); + let max = Math.max(interval, Math.ceil(joined.slice(-1)[0].y / interval) * interval); + + if (max < 0.9) { + max = null; + } const options: Options = { chart: { type: "line" }, @@ -64,11 +64,11 @@ export class GameChartComponent implements OnChanges { tooltip += `Date: ${new Date(data.x).toLocaleString()}
\n`; tooltip += `Commit: ${data["commit"]}
\n` - tooltip += `Total ${metadata.series[0].metric}: ${(+data.y * 100).toFixed(2)}%
\n` + tooltip += `Total ${metadata.subdivisions[0].metric}: ${(+data.y * 100).toFixed(2)}%
\n` tooltip += `-------------------------------------------
\n`; - for (let i = 0; i < metadata.series.length - 1; i += 1) { - const text = metadata.series[i + 1].description + for (let i = 0; i < metadata.subdivisions.length - 1; i += 1) { + const text = metadata.subdivisions[i + 1].description .replace("{0}", data["metrics"][i][0]) .replace("{1}", data["metrics"][i][1]) .replace("{2}", (+data["metrics"][i][2] * 100).toFixed(2)); @@ -92,7 +92,8 @@ export class GameChartComponent implements OnChanges { type: "line", name: nonmatchingName, data: nonmatchingData, - color: "#ffc107" + color: "#ffc107", + visible: false }, { type: "line", diff --git a/src/app/games/game/game-progress/game-progress.component.html b/src/app/games/game/game-progress/game-progress.component.html index f83f675..2997d31 100644 --- a/src/app/games/game/game-progress/game-progress.component.html +++ b/src/app/games/game/game-progress/game-progress.component.html @@ -1,6 +1,42 @@ + + Last updated + {{ lastUpdate }} +
+
+ + + + + + + + + + + + + + + + + +
{{ name }}
+ Total + + {{ (total * 100).toFixed(2) }}% +
{{ metric.key }} +
{{ (val * 100).toFixed(2) }}%
+
+
+ + + + + + \ No newline at end of file diff --git a/src/app/games/game/game-progress/game-progress.component.ts b/src/app/games/game/game-progress/game-progress.component.ts index cb559f1..9f64b77 100644 --- a/src/app/games/game/game-progress/game-progress.component.ts +++ b/src/app/games/game/game-progress/game-progress.component.ts @@ -1,9 +1,9 @@ import { KeyValue } from '@angular/common'; import { ThrowStmt } from '@angular/compiler'; import { Component, Input, OnChanges, OnInit } from '@angular/core'; -import { forkJoin } from 'rxjs'; +import { concat, forkJoin } from 'rxjs'; import { GamesService } from 'src/app/games/games.service'; -import { IGame } from 'src/app/games/games.service.interface'; +import { IChart, IGame } from 'src/app/games/games.service.interface'; /** * A single project displayed in a box, alongside one or more graphs. @@ -20,83 +20,70 @@ export class GameProgressComponent implements OnChanges { /** * Game object which holds info on how to parse the CSV data. */ - @Input() game: IGame = null; + @Input() meta: IChart = null; + /** + * CSV data. + */ + @Input() csvData: string[] = []; /** * The date time string for when this project was last updated */ - lastUpdate: string = ""; + lastUpdate: string = ""; /** * The simple numbers showing the total progress on respective charts. */ - totals: {[key: string]: number[]}[] = []; + totals: number[] = []; /** * Separate project metrics parsed from the CSV. */ - metrics: {[key: string]: number[]}[] = []; - /** - * CSV data for use with the chart. - */ - datasets: string[]; + metrics: { [key: string]: number[] } = {}; /** * Names for lines for use with the chart. */ - line_names: string[]; + series: string[]; ngOnChanges(): void { - this.line_names = this.game.csv_info.map((info) => info.name); + // don't do anything until all inputs are provided + console.log(this.meta); + if (typeof this.csvData !== "object" || typeof this.meta !== "object") { + return; + } - forkJoin( - this.game.csv_info.map((info) => this.gamesService.getGameCSV(info.data), this) - ).subscribe( - res => { - this.datasets = res; - - // reset on page load - this.totals = []; - this.metrics = []; - this.lastUpdate = null; + // reset on page load + this.totals = []; + this.metrics = {}; + this.lastUpdate = null; + for (const data of this.csvData) { + const points = data.split("\n").filter((line) => line != ""); + const latestPoint = points[points.length - 1]; + const column = latestPoint.split(","); + if (this.lastUpdate === null) { + this.lastUpdate = new Date(+column[1] * 1000).toLocaleString(); + } - for (const _ of this.game.charts) { - this.metrics.push({}); + // this.totals.push({[this.meta.subdivisions[0].metric]: []}); + // this.totals[this.meta.subdivisions[0].metric].push([this.meta.subdivisions[0].metric]); + + let i = this.meta.index; + this.totals.push(+column[i] / +column[i + 1]); + i += 2; + + for (const subdivision of this.meta.subdivisions.slice(1)) { + if (!(subdivision.metric in this.metrics)) { + this.metrics[subdivision.metric] = []; } - - for (const data of res) { - const points = data.split("\n").filter((line) => line != ""); - const latestPoint = points[points.length - 1]; - const column = latestPoint.split(","); - if (this.lastUpdate === null) { - this.lastUpdate = new Date(+column[1] * 1000).toLocaleString(); - } - - for (const chart of this.game.charts) { - this.totals.push({ [chart.series[0].metric]: [] }); - } - - let c = 0; - for (const chart of this.game.charts) { - let i = chart.index; - this.totals[c][chart.series[0].metric].push(+column[i] / +column[i+1]); - i += 2; - - for (const serie of chart.series.slice(1)) { - if (!(serie.metric in this.metrics[c])) { - this.metrics[c][serie.metric] = []; - } - this.metrics[c][serie.metric].push(+column[i] / +column[i+1]); - i += 2; - } - - c += 1; - } - } - }, - err => console.error(err) - ); + this.metrics[subdivision.metric].push(+column[i] / +column[i + 1]); + i += 2; + } + + } + console.log(this.metrics) } + originalOrder(a: KeyValue, b: KeyValue): number { return 0; } diff --git a/src/app/games/game/game.component.html b/src/app/games/game/game.component.html index 0b9bfa3..2930bed 100644 --- a/src/app/games/game/game.component.html +++ b/src/app/games/game/game.component.html @@ -1,7 +1,10 @@

{{ game.title }}

-
- -
+ + +
+ +
+
diff --git a/src/app/games/game/game.component.ts b/src/app/games/game/game.component.ts index df51648..8cb1f55 100644 --- a/src/app/games/game/game.component.ts +++ b/src/app/games/game/game.component.ts @@ -1,10 +1,11 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnChanges, OnInit } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; +import { forkJoin } from 'rxjs'; import { GamesService } from '../games.service'; -import { IGame } from '../games.service.interface'; +import { IChart, IGame } from '../games.service.interface'; /** - * Container component for the tabs and relevant content. + * Container component for relevant content on a game. */ @Component({ selector: 'game', @@ -18,8 +19,13 @@ export class GameComponent implements OnInit { /** * The summary to use to display basic game info. */ - game: IGame; + game: IGame; + /** + * Data obtained from the CSV files. + */ + csvData: string[]; + // Get the CSVs if the navigated slug is correct, otherwise navigate to 404 ngOnInit(): void { this.route.params.subscribe( res => { @@ -27,12 +33,19 @@ export class GameComponent implements OnInit { this.gamesService.getGames().subscribe( res => { // redirect if an unknown slug is provided - const index = res.findIndex((game) => game.slug === slug) - if (index !== -1) { - this.game = res[index]; + const index = res.findIndex((game) => game.slug === slug); + if (index === -1) { + this.router.navigateByUrl("/404", { skipLocationChange: true }); } else { - this.router.navigateByUrl("/404", { skipLocationChange: true }); + this.game = res[index]; + forkJoin([ + this.gamesService.getGameCSV(this.game.csvs.nonmatching), + this.gamesService.getGameCSV(this.game.csvs.matching) + ]).subscribe( + res => this.csvData = res, + err => console.error(err) + ); } }, err => { @@ -43,5 +56,4 @@ export class GameComponent implements OnInit { } ); } - -} +} \ No newline at end of file diff --git a/src/app/games/games.service.interface.ts b/src/app/games/games.service.interface.ts index 72d3154..06dd5a8 100644 --- a/src/app/games/games.service.interface.ts +++ b/src/app/games/games.service.interface.ts @@ -20,22 +20,18 @@ export interface IGame { * Links to display as an icon. The key defines the icon, and the value is the link href. */ links: {[type: string]: string}; - // /** - // * The name of the "matching" CSV to read. - // */ - // matching: string; - // /** - // * The name of the "nonmatching" CSV to read. - // */ - // nonmatching: string; /** - * Information on which csvs to use and what to call them. + * Struct with names of CSVs to use */ - csv_info: ICSVInfo[]; + csvs: ICSVs; /** - * The charts to display for this game. + * Data from CSVs */ - charts: IChart[]; + csvData: string[]; + /** + * The charts and data for each game. + */ + progressMeta: IChart[]; } /** @@ -83,35 +79,35 @@ export interface IChart { /** * The index to start counting pairs from. If none provided, will assume 5. */ - index?: number; - /** - * The series to have for each chart. - */ - series: ISeries[]; + index: number; /** * Names to use for the lines */ - line_names: string[]; + series: string[]; + /** + * The series to have for each chart. + */ + subdivisions: ISubdivision[]; } /** * Describes a csv of chart data and its name. */ -export interface ICSVInfo { +export interface ICSVs { /** - * The name of the csv type to display with the line. + * CSV file to get the matching data from. */ - name?: string; + matching: string; /** - * CSV file to get the data from. + * CSV file to get the nonmatching data from. */ - data: string; + nonmatching: string; } /** * Describes a singles series within a chart. */ -export interface ISeries { +export interface ISubdivision { /** * The name of the metric to display at the top. */ diff --git a/src/assets/csv/progress-mm-matching.csv b/src/assets/csv/progress-mm-matching.csv index f137ce1..5a154c4 100644 --- a/src/assets/csv/progress-mm-matching.csv +++ b/src/assets/csv/progress-mm-matching.csv @@ -1,4 +1,3 @@ -csv_version,timestamp,git_hash,src,total,boot,boot_total,code,code_total,ovl,ovl_total,asm,nonMatchingFunctions,assets,assets_total,archive,archive_total,audio,audio_total,interface,interface_total,misc,misc total,objects,objects_total,scenes,scenes_total,text,text_total 2,1615435438,e788bfecbfb10afd4182332db99bb562ea75b1de,103860,4747680,31572,86160,58624,1065936,13664,3595584,4597948,49,0,40817824,0,434608,0,6029280,0,749728,0,3953872,0,13518320,0,15695712,0,436304 2,1615511099,72f2b6aa4d154514008f61cc35025875a0528e02,103860,4747680,31572,86160,58624,1065936,13664,3595584,4597948,49,0,40817824,0,434608,0,6029280,0,749728,0,3953872,0,13518320,0,15695712,0,436304 2,1615512459,a983d14081b0e0daee4428769e7968071a1e9401,103860,4747680,31572,86160,58624,1065936,13664,3595584,4597948,49,0,40817824,0,434608,0,6029280,0,749728,0,3953872,0,13518320,0,15695712,0,436304 diff --git a/src/assets/csv/progress-mm-nonmatching.csv b/src/assets/csv/progress-mm-nonmatching.csv index 7bc6c3c..6f4240c 100644 --- a/src/assets/csv/progress-mm-nonmatching.csv +++ b/src/assets/csv/progress-mm-nonmatching.csv @@ -1,4 +1,3 @@ -csv_version,timestamp,git_hash,src,total,boot,boot_total,code,code_total,ovl,ovl_total,asm,nonMatchingFunctions,assets,assets_total,archive,archive_total,audio,audio_total,interface,interface_total,misc,misc total,objects,objects_total,scenes,scenes_total,text,text_total 2,1615435438,e788bfecbfb10afd4182332db99bb562ea75b1de,120152,4747680,36352,86160,70136,1065936,13664,3595584,4582152,0,0,40817824,0,434608,0,6029280,0,749728,0,3953872,0,13518320,0,15695712,0,436304 2,1615511099,72f2b6aa4d154514008f61cc35025875a0528e02,120152,4747680,36352,86160,70136,1065936,13664,3595584,4582152,0,0,40817824,0,434608,0,6029280,0,749728,0,3953872,0,13518320,0,15695712,0,436304 2,1615512459,a983d14081b0e0daee4428769e7968071a1e9401,120152,4747680,36352,86160,70136,1065936,13664,3595584,4582152,0,0,40817824,0,434608,0,6029280,0,749728,0,3953872,0,13518320,0,15695712,0,436304 diff --git a/src/assets/json/games.json b/src/assets/json/games.json index ef6eadf..6ca455f 100644 --- a/src/assets/json/games.json +++ b/src/assets/json/games.json @@ -6,23 +6,21 @@ "github": "https://www.github.com/zeldaret/oot" }, "faq": "oot_faq", - "csv_info": [ - { - "name": "nonmatching", - "data": "progress-oot-nonmatching" - }, - { - "name": "matching", - "data": "progress-oot-matching" - } - ], - "charts": [ + "csvs": { + "matching": "progress-oot-matching", + "nonmatching": "progress-oot-nonmatching" + }, + "progressMeta": [ { + "type": "code", "title": "Ocarina of Time MQ Debug Rom", "subtitle": "Code decompilation progress", "index": 3, - "line_names": ["Nonmatching", "Matching"], "series": [ + "Nonmatching", + "Matching" + ], + "subdivisions": [ { "metric": "Code", "description": "{0} / {1} bytes of all code decompiled ({2}%)" @@ -50,34 +48,32 @@ "github": "https://www.github.com/zeldaret/mm" }, "faq": "mm_faq", - "csv_info": [ - { - "name": "nonmatching", - "data": "progress-mm-nonmatching" - }, - { - "name": "matching", - "data": "progress-mm-matching" - } - ], - "charts": [ + "csvs": { + "matching": "progress-mm-matching", + "nonmatching": "progress-mm-nonmatching" + }, + "progressMeta": [ { + "type": "code", "title": "Majora's Mask", "subtitle": "Code decompilation progress", - "line_names": ["Nonmatching", "Matching"], - "index": 3, "series": [ + "Nonmatching", + "Matching" + ], + "index": 3, + "subdivisions": [ { "metric": "Code", "description": "{0} / {1} bytes of all code decompiled ({2}%)" }, { - "metric": "boot", - "description": "{0} / {1} bytes of boot decompiled ({2}%)" + "metric": "Code", + "description": "{0} / {1} bytes of code decompiled ({2}%)" }, { - "metric": "code", - "description": "{0} / {1} bytes of code decompiled ({2}%)" + "metric": "Boot", + "description": "{0} / {1} bytes of boot decompiled ({2}%)" }, { "metric": "Overlays", @@ -86,11 +82,15 @@ ] }, { + "type": "assets", "title": "Majora's Mask", - "subtitle": "Asset decompilation progress", - "line_names": ["Debinarised", "Identified"], - "index": 13, + "subtitle": "Asset analysis progress", "series": [ + "Debinarised", + "Identified" + ], + "index": 13, + "subdivisions": [ { "metric": "Assets", "description": "{0} / {1} bytes of all assets decompiled ({2}%)" @@ -127,4 +127,4 @@ } ] } -] +] \ No newline at end of file