forked from Chiv2-Community/polehammer.net
-
Notifications
You must be signed in to change notification settings - Fork 0
Absolute/Relative radars #31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Jacoby6000
wants to merge
18
commits into
main
Choose a base branch
from
radar-modes
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
073810e
radar work
Jacoby6000 f8bbe70
Merge remote-tracking branch 'origin/main' into radar-modes
Jacoby6000 425025a
absolute radars
Jacoby6000 16a300f
no graph swap on small screen
Jacoby6000 a11cd5d
Merge branch 'main' into radar-modes
mergify[bot] 8ca55c1
Merge branch 'main' into radar-modes
mergify[bot] a549789
Merge branch 'main' into radar-modes
mergify[bot] c1716c6
Merge branch 'main' into radar-modes
mergify[bot] b5ee3c6
Merge branch 'main' into radar-modes
Jacoby6000 7cf8674
Merge branch 'main' into radar-modes
mergify[bot] 70aa17e
Merge branch 'main' into radar-modes
mergify[bot] 67c0839
Merge branch 'main' into radar-modes
mergify[bot] 8e117fc
Merge branch 'main' into radar-modes
mergify[bot] 88e4b57
Merge branch 'main' into radar-modes
mergify[bot] 73d7db6
Merge branch 'main' into radar-modes
mergify[bot] a3e1396
Merge branch 'main' into radar-modes
mergify[bot] 9c4924f
Merge branch 'main' into radar-modes
mergify[bot] a8d97a4
Merge branch 'main' into radar-modes
mergify[bot] File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,7 @@ | ||
|
|
||
| import { Chart, ChartData, registerables } from "chart.js"; | ||
| import ALL_WEAPONS, { weaponByName, weaponById } from "./all_weapons"; | ||
| import { MetricLabel } from "./metrics"; | ||
| import { labelGroup, MetricLabel, Unit } from "./metrics"; | ||
| import { | ||
| generateMetrics, | ||
| unitGroupStats, | ||
|
|
@@ -9,8 +10,8 @@ import { | |
| } from "./stats"; | ||
| import "./style.scss"; | ||
| import { Target } from "./target"; | ||
| import { borderDash, weaponColor, weaponDash, metricColor } from "./ui"; | ||
| import { shuffle } from "./util"; | ||
| import { weaponColor, weaponDash, metricColor, createRadarChart, chartData, createBarChart, getViewport } from "./ui"; | ||
| import { shuffle, subsets } from "./util"; | ||
| import { Weapon, WeaponType } from "./weapon"; | ||
|
|
||
| Chart.defaults.font.family = "'Lato', sans-serif"; | ||
|
|
@@ -22,16 +23,22 @@ let horsebackDamageMultiplier = 1.0; | |
|
|
||
| let stats: WeaponStats = generateMetrics(ALL_WEAPONS, 1, 1, Target.VANGUARD_ARCHER); | ||
| let unitStats: UnitStats = unitGroupStats(stats); | ||
| let absoluteRadarsEnabled = false; | ||
| let selectedRadar = Unit.DAMAGE; | ||
|
|
||
| let selectedTab = "radar-content-tab"; | ||
|
|
||
| const selectedWeapons: Set<Weapon> = new Set<Weapon>(); | ||
| const selectedCategories: Set<MetricLabel> = new Set<MetricLabel>(); | ||
| const searchResults: Set<Weapon> = new Set<Weapon>(); | ||
|
|
||
|
|
||
| const bigRadarDiv = document.querySelector<HTMLDivElement>("#bigRadar")! | ||
| const smallRadarsDiv = document.querySelector<HTMLDivElement>("#smallRadars")! | ||
| const weaponSearchResults = document.querySelector<HTMLDivElement>("#weaponSearchResults")! | ||
| const displayedWeapons = document.querySelector<HTMLFieldSetElement>("#displayedWeapons")!; | ||
|
|
||
|
|
||
| function toId(str: string) { | ||
| return str | ||
| .replaceAll(" ", "_") | ||
|
|
@@ -43,95 +50,15 @@ function toId(str: string) { | |
| // Normalization will only occur for stat types that have a unit present in the provided normalizationStats. | ||
| // This allows for selective normalization, like for bar charts where we wan't mostly raw data, except for | ||
| // "speed" (or other inverse metrics) which only make sense as a normalized value | ||
| function chartData( | ||
| dataset: WeaponStats, | ||
| categories: Set<MetricLabel>, | ||
| normalizationStats: UnitStats, | ||
| setBgColor: boolean | ||
| ): ChartData { | ||
| let sortedCategories = Array.from(categories); | ||
| sortedCategories.sort((a,b) => { | ||
| return Object.values(MetricLabel).indexOf(a) - Object.values(MetricLabel).indexOf(b); | ||
| }); | ||
|
|
||
| return { | ||
| labels: [...sortedCategories], | ||
| datasets: [...selectedWeapons].map((w) => { | ||
| return { | ||
| label: w.name, | ||
| data: [...sortedCategories].map((c) => { | ||
| const metric = dataset.get(w.name)!.get(c)!; | ||
| let value = metric.value.result; | ||
| const maybeUnitStats = normalizationStats.get(c); | ||
| if (maybeUnitStats) { | ||
| const unitMin = maybeUnitStats!.min; | ||
| const unitMax = maybeUnitStats!.max; | ||
|
|
||
| // Normalize | ||
| return (value - unitMin) / (unitMax - unitMin); | ||
| } | ||
| return value; | ||
| }), | ||
| backgroundColor: setBgColor ? weaponColor(w, 0.6) : weaponColor(w, 0.1), | ||
| borderColor: weaponColor(w, 0.6), | ||
| borderDash: borderDash(w), | ||
| }; | ||
| }), | ||
| }; | ||
| } | ||
|
|
||
| const radar: Chart = new Chart( | ||
| document.getElementById("radar") as HTMLCanvasElement, | ||
| { | ||
| type: "radar", | ||
| options: { | ||
| animation: false, | ||
| plugins: { | ||
| legend: { | ||
| display: false, | ||
| position: "bottom", | ||
| }, | ||
| }, | ||
| responsive: true, | ||
| maintainAspectRatio: true, | ||
| scales: { | ||
| radial: { | ||
| min: 0, | ||
| max: 1, | ||
| ticks: { | ||
| display: false, | ||
| maxTicksLimit: 2, | ||
| }, | ||
| }, | ||
| }, | ||
| }, | ||
| data: chartData(stats, selectedCategories, unitStats, false), | ||
| } | ||
| ); | ||
| const relativeRadar: Chart = createRadarChart( | ||
| document.querySelector<HTMLCanvasElement>("#relativeRadar")!, | ||
| chartData(stats, Array.from(selectedWeapons), selectedCategories, unitStats, false, null), | ||
| {min: 0, max: 1} | ||
| ) | ||
|
|
||
| const bars = new Array<Chart>(); | ||
|
|
||
| function createBarChart(element: HTMLCanvasElement, category: MetricLabel) { | ||
| const barUnitStats: UnitStats = new Map(); | ||
| if(category.includes("Speed")) { | ||
| barUnitStats.set(category, unitStats.get(category)!); | ||
| } | ||
|
|
||
| return new Chart(element as HTMLCanvasElement, { | ||
| type: "bar", | ||
| options: { | ||
| animation: false, | ||
| plugins: { | ||
| legend: { | ||
| display: false, | ||
| }, | ||
| }, | ||
| responsive: true, | ||
| maintainAspectRatio: false, | ||
| }, | ||
| data: chartData(stats, new Set([category]), barUnitStats, true), | ||
| }); | ||
| } | ||
| const absoluteRadars = new Array<Chart>(); | ||
|
|
||
| function redrawBars() { | ||
| const barsElem = document.getElementById("bars")!; | ||
|
|
@@ -149,11 +76,11 @@ function redrawBars() { | |
| const elem = document.createElement("canvas"); | ||
| outer.appendChild(elem); | ||
| barsElem.appendChild(outer); | ||
| bars.push(createBarChart(elem, c)); | ||
| bars.push(createBarChart(elem, Array.from(selectedWeapons), c, stats, unitStats)); | ||
| }); | ||
| } | ||
|
|
||
| function redrawTable(dataset: WeaponStats, unitStats: UnitStats) { | ||
| function redrawTable() { | ||
| let sortedCategories = Array.from(selectedCategories); | ||
| sortedCategories.sort((a,b) => { | ||
| return Object.values(MetricLabel).indexOf(a) - Object.values(MetricLabel).indexOf(b); | ||
|
|
@@ -201,7 +128,7 @@ function redrawTable(dataset: WeaponStats, unitStats: UnitStats) { | |
| table.appendChild(head); | ||
|
|
||
| selectedWeapons.forEach(weapon => { | ||
| let weaponData = dataset.get(weapon.name)!; | ||
| let weaponData = stats.get(weapon.name)!; | ||
|
|
||
| let row = document.createElement("tr"); | ||
|
|
||
|
|
@@ -267,7 +194,8 @@ function redraw() { | |
| radar.update(); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [tsc] <2304> reported by reviewdog 🐶 |
||
|
|
||
| redrawBars(); | ||
| redrawTable(stats, unitStats); | ||
| redrawTable(); | ||
| redrawRadars(); | ||
|
|
||
| // Update content of location string so we can share | ||
| const params = new URLSearchParams(); | ||
|
|
@@ -279,6 +207,84 @@ function redraw() { | |
| window.history.replaceState(null, "", `?${params.toString()}`); | ||
| } | ||
|
|
||
| function redrawRadars() { | ||
| if(absoluteRadarsEnabled) { | ||
| absoluteRadarsButton.classList.add('active'); | ||
| relativeRadarsButton.classList.remove('active'); | ||
| relativeRadarsDiv.classList.add('d-none'); | ||
| absoluteRadarsDiv.classList.remove('d-none'); | ||
| } else { | ||
| relativeRadarsButton.classList.add('active'); | ||
| absoluteRadarsButton.classList.remove('active'); | ||
| absoluteRadarsDiv.classList.add('d-none'); | ||
| relativeRadarsDiv.classList.remove('d-none'); | ||
| } | ||
|
|
||
| relativeRadar.data = chartData(stats, Array.from(selectedWeapons), selectedCategories, unitStats, false, null); | ||
| relativeRadar.update(); | ||
|
|
||
| let categoryGroups = subsets(selectedCategories, labelGroup) | ||
| let cateoryGroupsKeys = Array.from(categoryGroups.keys()); | ||
| absoluteRadars.forEach(r => { | ||
| r.clear(); | ||
| r.destroy(); | ||
| }); | ||
| absoluteRadars.splice(0, absoluteRadars.length); | ||
| if(!cateoryGroupsKeys.includes(selectedRadar)) { | ||
| selectedRadar = cateoryGroupsKeys[0]; | ||
| } | ||
|
|
||
| bigRadarDiv.innerHTML = ""; | ||
| smallRadarsDiv.innerHTML = ""; | ||
|
|
||
| cateoryGroupsKeys.forEach(unit => { | ||
| let parent = unit === selectedRadar ? bigRadarDiv : smallRadarsDiv | ||
|
|
||
| let label = | ||
| unit === Unit.SPEED ? "Speed*" : | ||
| unit === Unit.DAMAGE ? "Damage" : | ||
| unit === Unit.RANGE ? "Range" : | ||
| "Unknown" | ||
|
|
||
| let newLabel = document.createElement("div"); | ||
| newLabel.classList.add("category-group"); | ||
| newLabel.classList.add("text-center"); | ||
| newLabel.innerHTML = label; | ||
| parent.append(newLabel); | ||
|
|
||
| if(categoryGroups.get(unit)!.size < 3) { | ||
| let newMessage = document.createElement("div"); | ||
| newMessage.innerHTML = "Select 3 or more categories of this type for this chart to display."; | ||
| newMessage.classList.add("text-center"); | ||
| newMessage.classList.add("my-5"); | ||
| parent.append(newMessage); | ||
| } else { | ||
| let newCanvasDiv = document.createElement("div"); | ||
| newCanvasDiv.classList.add("col-xs-6") | ||
| newCanvasDiv.classList.add("col-md-12") | ||
| let newCanvas = document.createElement("canvas"); | ||
|
|
||
| let viewport = getViewport(); | ||
| if(["xl", "lg", "md"].includes(viewport)) { | ||
| newCanvas.onclick = () => { selectedRadar = unit; redrawRadars(); } | ||
| } | ||
| newCanvasDiv.appendChild(newCanvas); | ||
| parent.appendChild(newCanvasDiv); | ||
|
|
||
| absoluteRadars.push( | ||
| createRadarChart( | ||
| newCanvas, | ||
| chartData(stats, Array.from(selectedWeapons), categoryGroups.get(unit)!, new Map(), false, x => x.split(' - ')[1]), | ||
| { min: 0, max: unitStats.get(unit)!.max } | ||
| ) | ||
| ); | ||
| } | ||
| }); | ||
|
|
||
| absoluteRadars.forEach(r => r.draw()); | ||
|
|
||
| } | ||
|
|
||
| function addWeaponDiv(weapon: Weapon) { | ||
| const div = document.createElement("div"); | ||
| div.id = weapon.name; | ||
|
|
@@ -443,14 +449,29 @@ document.getElementById("random")!.onclick = random; | |
| document.getElementById("all")!.onclick = all; | ||
| document.getElementById("reset")!.onclick = reset; | ||
|
|
||
| let absoluteRadarsButton = document.querySelector<HTMLButtonElement>("#absoluteRadars")!, | ||
| relativeRadarsButton = document.querySelector<HTMLButtonElement>("#relativeRadars")!, | ||
| absoluteRadarsDiv = document.querySelector<HTMLButtonElement>("#absoluteRadarsDiv")!, | ||
| relativeRadarsDiv = document.querySelector<HTMLButtonElement>("#relativeRadarsDiv")!; | ||
|
|
||
| absoluteRadarsButton.onclick = () => { | ||
| absoluteRadarsEnabled = true; | ||
| redrawRadars(); | ||
| } | ||
|
|
||
| relativeRadarsButton.onclick = () => { | ||
| absoluteRadarsEnabled = false; | ||
| redrawRadars(); | ||
| } | ||
|
|
||
| // Link up Share button | ||
| document.getElementById("share")!.onclick = () => { | ||
| navigator.clipboard.writeText(window.location.toString()); | ||
| alert("Copied to clipboard!"); | ||
| }; | ||
|
|
||
| let numberOfTargetsInput = document.querySelector<HTMLInputElement>("#numberOfTargets")!; | ||
| let numberOfTargetsOutput = document.getElementById("numberOfTargetsOutput")!; | ||
| let numberOfTargetsInput = document.querySelector<HTMLInputElement>("#numberOfTargets")!, | ||
| numberOfTargetsOutput = document.getElementById("numberOfTargetsOutput")!; | ||
|
|
||
| numberOfTargetsInput.oninput = () => { | ||
| numberOfTargetsOutput.innerHTML = numberOfTargetsInput.value | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🚫 [tsc] <6133> reported by reviewdog 🐶
'ChartData' is declared but its value is never read.