Skip to content

Commit

Permalink
DPS Tool Improvements (#590)
Browse files Browse the repository at this point in the history
* Add all weapons setting to DPS tool

* fix the clear button at dps tool

* Simple text modifications

---------

Co-authored-by: Petr Vecera <vecera.petr@gmail.com>
  • Loading branch information
KingDarBoja and petrvecera committed Sep 27, 2024
1 parent a1c172d commit 117ef94
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 41 deletions.
54 changes: 42 additions & 12 deletions components/unitStats/dps/dpsChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ import {
Select,
LoadingOverlay,
Center,
Button,
} from "@mantine/core";
import { UnitSearch } from "./unitSearch";
import { DpsUnitCustomizing } from "./dpsUnitCustomizing";
import { EbpsType, getEbpsStats } from "../../../src/unitStats/mappingEbps";
// import slash from "slash";
import { getWeaponStats, WeaponType } from "../../../src/unitStats/mappingWeapon";
import { getSbpsStats, SbpsType } from "../../../src/unitStats/mappingSbps";
import { IconAdjustments } from "@tabler/icons-react";
Expand Down Expand Up @@ -264,6 +264,7 @@ export const DpsChart = (props: IDPSProps) => {
// const [isStaircase, setStaircase] = useState(false);
const [isStaircase] = useState(false);
const [showDpsHealth, setShowDpsHealth] = useState(false);
const [allowAllWeapons, setAllowAllWeapons] = useState(false);

// const { classes } = useStyles();
const theme = useMantineTheme();
Expand Down Expand Up @@ -344,8 +345,14 @@ export const DpsChart = (props: IDPSProps) => {
}

// synchronize selection field with presented units
function onSelectionChange(selection: string, index: number) {
// add new units
function onSelectionChange(selection: string | null, index: number) {
if (!selection) {
// @ts-ignore Because we can not pass an empty object, otherwise we would
// need to put `.?` safe accessor everywhere.
activeData[index] = undefined;
setRerender(!rerender);
return;
}

AnalyticsDPSExplorerSquadSelection(selection);

Expand Down Expand Up @@ -448,8 +455,6 @@ export const DpsChart = (props: IDPSProps) => {
return (
<>
<Container>
{/* */}

<Grid>
<Grid.Col span={10}>
<Title order={2}>Company of Heroes 3 DPS Benchmark Tool </Title>
Expand All @@ -467,20 +472,43 @@ export const DpsChart = (props: IDPSProps) => {
<Group>
<HoverCard width={400} shadow="md">
<HoverCard.Target>
<div>
<IconAdjustments opacity={0.6} />
</div>
<Button
variant="default"
leftSection={<IconAdjustments opacity={0.6} />}
size="xs"
>
Settings
</Button>
</HoverCard.Target>
<HoverCard.Dropdown>
<Stack mb={12}>
<Space />
<Text size="sm">Toggle DPS mode.</Text>
<Stack>
<Text size="md">Advanced Options</Text>
<Switch
label={"DPS / Target Health (%)"}
checked={showDpsHealth}
onChange={(event) => setShowDpsHealth(event.currentTarget.checked)}
//onClick={() => setCurve(isCurve)}
size="xs"
// size="xs"
/>
<Space />
<Switch
label={
<Stack gap="0">
<>Allow All Weapons</>
<Text size="xs" c="dimmed">
Deselects current units
</Text>
</Stack>
}
checked={allowAllWeapons}
onChange={(event) => {
setAllowAllWeapons(event.currentTarget.checked);
// Reset selected units so it loads the units
onSelectionChange(null, 0);
onSelectionChange(null, 1);
}}
//onClick={() => setCurve(isCurve)}
// size="xs"
/>
</Stack>
</HoverCard.Dropdown>
Expand Down Expand Up @@ -554,6 +582,7 @@ export const DpsChart = (props: IDPSProps) => {
index={0}
ebps={ebpsData1}
weapons={weaponData1}
allowAllWeapons={allowAllWeapons}
/>
</Box>
)}
Expand Down Expand Up @@ -623,6 +652,7 @@ export const DpsChart = (props: IDPSProps) => {
index={1}
ebps={ebpsData2}
weapons={weaponData2}
allowAllWeapons={allowAllWeapons}
/>
</Box>
)}
Expand Down
16 changes: 10 additions & 6 deletions components/unitStats/dps/dpsUnitCustomizing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
CustomizableUnit,
getSbpsUpgrades,
getSbpsWeapons,
mapWeaponMember,
resolveFactionLinkid,
WeaponMember,
} from "../../../src/unitStats/dpsCommon";
Expand All @@ -33,10 +34,11 @@ import { HitpointCard } from "../../unit-cards/hitpoints-card";

interface IUnitProps {
unit: CustomizableUnit;
onChange: any;
onChange: (...args: any[]) => void;
index: number;
ebps: EbpsType[];
weapons: WeaponType[];
allowAllWeapons: boolean;
}

export const DpsUnitCustomizing = (props: IUnitProps) => {
Expand All @@ -47,14 +49,16 @@ export const DpsUnitCustomizing = (props: IUnitProps) => {
// Create weapon list, `useEffect` to listen for props changes and refresh the
// weapon data.
useEffect(() => {
const weapons = getSbpsWeapons(props.unit.sbps, props.ebps, props.weapons);
const weaponUpgrades = getSbpsUpgrades(props.unit.sbps, props.ebps, props.weapons);
const sbpsWeapons = getSbpsWeapons(props.unit.sbps, props.ebps, props.weapons);
const weaponUpgrades = props.allowAllWeapons
? props.weapons.map((weapon) => mapWeaponMember(props.unit.sbps, props.ebps[0], weapon))
: getSbpsUpgrades(props.unit.sbps, props.ebps, props.weapons);
for (const weaponUpgrade of weaponUpgrades) {
// check if weapon is already available
if (weapons.find((member) => member.weapon_id == weaponUpgrade.weapon_id)) continue;
weapons.push(weaponUpgrade);
if (sbpsWeapons.find((member) => member.weapon_id == weaponUpgrade.weapon_id)) continue;
sbpsWeapons.push(weaponUpgrade);
}
setWeaponList(weapons);
setWeaponList(sbpsWeapons);
}, [props.ebps, props.unit.sbps, props.weapons]);

function onAddWeapon(selectionItem: WeaponMember) {
Expand Down
11 changes: 5 additions & 6 deletions components/unitStats/dps/unitSearch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,15 +116,13 @@ const renderSelectOption: SelectProps["renderOption"] = ({ option }) => {
};

interface ISearchProps {
searchData: any[];

onSelect(selection: any, position: number): any;

searchData: CustomizableUnit[];
onSelect(selection: string | null, position: number): any;
position: number;
}

export const UnitSearch = (props: ISearchProps) => {
function onSelectionChange(id: string) {
function onSelectionChange(id: string | null) {
//const selectedItems: any[] = [];

// remove last element so we have never more than 2
Expand All @@ -148,12 +146,13 @@ export const UnitSearch = (props: ISearchProps) => {
clearable
renderOption={renderSelectOption}
data={props.searchData}
defaultValue={null}
// data = {[]}
// valueComponent={Value}
searchable
maxDropdownHeight={600}
nothingFoundMessage="Nobody here. War is over!"
onChange={(value) => onSelectionChange(value as string)}
onChange={(value) => onSelectionChange(value)}
/>
);
};
Expand Down
7 changes: 4 additions & 3 deletions components/unitStats/dps/weaponSearch.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Group, Text, Image, Select, SelectProps } from "@mantine/core";
import { WeaponMember } from "../../../src/unitStats/dpsCommon";

interface ItemProps extends React.ComponentPropsWithoutRef<"div"> {
image: string;
Expand Down Expand Up @@ -33,8 +34,8 @@ const renderSelectOption: SelectProps["renderOption"] = ({ option }) => {
};

interface ISearchProps {
searchData: any[];
onSelect(selection: any): any;
searchData: WeaponMember[];
onSelect(selection: WeaponMember): any;
}

export const WeaponSearch = (props: ISearchProps) => {
Expand All @@ -43,7 +44,7 @@ export const WeaponSearch = (props: ISearchProps) => {
function onSelectionChange(id: string) {
//selectedLabels = id; // remember what is selected so we can set it as long dropdown is open
//id.forEach((selection) => {
const item = props.searchData.find((item) => item.value == id);
const item = props.searchData.find((item) => item.weapon_id == id);
if (item) props.onSelect(item);
//});
}
Expand Down
2 changes: 1 addition & 1 deletion pages/explorer/dps.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ interface DpsProps {
sbpsData: SbpsType[];
ebpsData: EbpsType[];
upgradesData: UpgradesType[];
locstring: any;
locstring: Record<string, string | null>;
generalInfo: any;
properties: any;
}
Expand Down
38 changes: 25 additions & 13 deletions src/unitStats/dpsCommon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ import { getSquadTotalCost, getSquadTotalUpkeepCost } from "./squadTotalCost";
import { getFactionIcon } from "./unitStatsLib";
import { getSingleWeaponDPS } from "./weaponLib";

type CoordinatesDPS = { x: number; y: number };

type WeaponMember = {
weapon_id: string; // Weapon id
/** Weapon ID. */
weapon_id: string;
num: number;
unit: string;
crew_size: number;
Expand All @@ -17,8 +20,9 @@ type WeaponMember = {
image: string;
label: string;
description: string;
/** Value seems to be the same as weapon ID. */
value: string;
dps_default: [];
dps_default: CoordinatesDPS[];
};

export const resolveFactionLinkid = (factionFolderName: string) => {
Expand All @@ -32,25 +36,33 @@ export const resolveFactionLinkid = (factionFolderName: string) => {
}
};

const mapWeaponMember = (
/**
*
* @param sbps_selected Does nothing beside storing the sbps.
* @param ebps_selected Does nothing beside storing the ebps.
* @param weapon The weapon data
* @param loadout_num Quantity of weapon carried by the entity.
* @returns
*/
export const mapWeaponMember = (
sbps_selected: SbpsType,
ebps_selected: EbpsType,
weapon: WeaponType,
loadout_num = 1,
) => {
const member = {
weapon_id: weapon.id, // Weapon id
const member: WeaponMember = {
weapon_id: weapon.id,
num: loadout_num,
unit: ebps_selected.id,
crew_size: ebps_selected.crew_size,
sbps: sbps_selected,
ebps: ebps_selected,
weapon: weapon,
image: (weapon as any).image, // intermediate solution
image: "",
label: weapon.id,
description: weapon.description,
value: weapon.id,
dps_default: [] as any,
dps_default: [],
};
// (clone as any).unit = loadout.id;
if (weapon.icon_name != "") member.image = getIconsPathOnCDN("icons/" + weapon.icon_name);
Expand Down Expand Up @@ -418,7 +430,7 @@ export const getDpsVsHealth = (
unit1: CustomizableUnit,
unit2?: CustomizableUnit,
) => {
const dpsData: any[] = getCombatDps(unit1, unit2);
const dpsData: CoordinatesDPS[] = getCombatDps(unit1, unit2);
let health = unit1.health;

// compute opponents health
Expand All @@ -431,7 +443,7 @@ export const getDpsVsHealth = (

export const getCombatDps = (unit1: CustomizableUnit, unit2?: CustomizableUnit) => {
// compute dps for first squad
let dpsTotal: any[] = [];
let dpsTotal: CoordinatesDPS[] = [];

// compute total dps for complete loadout
unit1.weapon_member.forEach((ldout) => {
Expand All @@ -455,7 +467,7 @@ export const getCombatDps = (unit1: CustomizableUnit, unit2?: CustomizableUnit)

const getDpsByDistance = (distance = 0, unit1: CustomizableUnit, unit2?: CustomizableUnit) => {
// compute dps for first squad
let dpsTotal: any[] = [];
let dpsTotal: CoordinatesDPS[] = [];

// compute total dps for complete loadout
unit1.weapon_member.forEach((ldout) => {
Expand All @@ -478,10 +490,10 @@ const getDpsByDistance = (distance = 0, unit1: CustomizableUnit, unit2?: Customi
};

// sums up two dps lines
export const addDpsData = (dps1: any[], dps2: any[]) => {
export const addDpsData = (dps1: CoordinatesDPS[], dps2: CoordinatesDPS[]) => {
if (dps1.length == 0) return dps2;
// set with {x,y} touples
const newSet: any[] = [];
const newSet: CoordinatesDPS[] = [];

let ind_2 = 0; // loop only once through second line
for (let ind_1 = 0; ind_1 < dps1.length; ind_1++) {
Expand Down Expand Up @@ -518,7 +530,7 @@ export const addDpsData = (dps1: any[], dps2: any[]) => {
return newSet;
};

export const mergePoints = (xPoint: any, yPoint: any) => {
export const mergePoints = (xPoint: CoordinatesDPS, yPoint: CoordinatesDPS) => {
return { x: xPoint.x, y: xPoint.y + yPoint.y };
};

Expand Down

0 comments on commit 117ef94

Please sign in to comment.