feat(calculation-details): improve the overall ability of this component (#74)

This commit is contained in:
Patric Stout
2024-03-05 22:44:49 +01:00
committed by GitHub
parent 133b162c44
commit 0e519bd03a
4 changed files with 144 additions and 195 deletions

View File

@@ -33,183 +33,81 @@ Hammerhead II x1
export const hashFit =
"fit:v1:H4sIAAAAAAAAClXOMQ7CMAwF0L2n6AE8xD92bLMiRhi4AQMSrND7i7itGrG9JHb+R4QLnet8fyzL8zOf5tv7+7pcaWIoiTY04u7WrcGrLe/LZk+zppkA7CODdTBIGOydKFTVoiRzzfMdIFZrmYdKHOyWlEEdW0ZQW3N7hYNxsJZBHsRgL+ammRagypZBU9RO3yid1bKuEkRyylDy0CxIxTBthXQdScmmIt7I/+72D6JNPx7qugdyAQAA";
export const fullFit = {
name: "C3 Ratter : NishEM",
ship_type_id: 29984,
description: "",
items: [
{
flag: 125,
quantity: 1,
type_id: 45626,
},
{
flag: 126,
quantity: 1,
type_id: 45591,
},
{
flag: 127,
quantity: 1,
type_id: 45601,
},
{
flag: 128,
quantity: 1,
type_id: 45615,
},
{
flag: 11,
quantity: 1,
type_id: 22291,
},
{
flag: 12,
quantity: 1,
type_id: 22291,
},
{
flag: 13,
quantity: 1,
type_id: 22291,
},
{
flag: 19,
quantity: 1,
type_id: 41218,
},
{
flag: 20,
quantity: 1,
type_id: 35790,
},
{
flag: 21,
quantity: 1,
type_id: 2281,
},
{
flag: 22,
quantity: 1,
type_id: 15766,
},
{
flag: 23,
quantity: 1,
type_id: 19187,
},
{
flag: 24,
quantity: 1,
type_id: 19187,
},
{
flag: 25,
quantity: 1,
type_id: 35790,
},
{
flag: 27,
quantity: 1,
type_id: 25715,
charge: {
type_id: 20308,
},
},
{
flag: 28,
quantity: 1,
type_id: 25715,
charge: {
type_id: 20308,
},
},
{
flag: 29,
quantity: 1,
type_id: 25715,
charge: {
type_id: 20308,
},
},
{
flag: 30,
quantity: 1,
type_id: 25715,
charge: {
type_id: 20308,
},
},
{
flag: 31,
quantity: 1,
type_id: 25715,
charge: {
type_id: 20308,
},
},
{
flag: 32,
quantity: 1,
type_id: 25715,
charge: {
type_id: 20308,
},
},
{
flag: 33,
quantity: 1,
type_id: 28756,
},
{
flag: 92,
quantity: 1,
type_id: 31724,
},
{
flag: 93,
quantity: 1,
type_id: 31824,
},
{
flag: 94,
quantity: 1,
type_id: 31378,
},
{
flag: 5,
quantity: 3720,
type_id: 24492,
},
{
flag: 5,
quantity: 5472,
type_id: 2679,
},
{
flag: 5,
quantity: 1,
type_id: 35795,
},
{
flag: 5,
quantity: 1,
type_id: 35794,
},
{
flag: 5,
quantity: 8,
type_id: 30486,
},
{
flag: 5,
quantity: 1,
type_id: 35794,
},
{
flag: 5,
quantity: 396,
type_id: 24492,
},
],
};
export const fullFits = [
{
name: "Tengu",
ship_type_id: 29984,
description: "",
items: [
{ flag: 125, quantity: 1, type_id: 45626 },
{ flag: 126, quantity: 1, type_id: 45591 },
{ flag: 127, quantity: 1, type_id: 45601 },
{ flag: 128, quantity: 1, type_id: 45615 },
{ flag: 11, quantity: 1, type_id: 22291 },
{ flag: 12, quantity: 1, type_id: 22291 },
{ flag: 13, quantity: 1, type_id: 22291 },
{ flag: 19, quantity: 1, type_id: 41218 },
{ flag: 20, quantity: 1, type_id: 35790 },
{ flag: 21, quantity: 1, type_id: 2281 },
{ flag: 22, quantity: 1, type_id: 15766 },
{ flag: 23, quantity: 1, type_id: 19187 },
{ flag: 24, quantity: 1, type_id: 19187 },
{ flag: 25, quantity: 1, type_id: 35790 },
{ flag: 27, quantity: 1, type_id: 25715, charge: { type_id: 20308 } },
{ flag: 28, quantity: 1, type_id: 25715, charge: { type_id: 20308 } },
{ flag: 29, quantity: 1, type_id: 25715, charge: { type_id: 20308 } },
{ flag: 30, quantity: 1, type_id: 25715, charge: { type_id: 20308 } },
{ flag: 31, quantity: 1, type_id: 25715, charge: { type_id: 20308 } },
{ flag: 32, quantity: 1, type_id: 25715, charge: { type_id: 20308 } },
{ flag: 33, quantity: 1, type_id: 28756 },
{ flag: 92, quantity: 1, type_id: 31724 },
{ flag: 93, quantity: 1, type_id: 31824 },
{ flag: 94, quantity: 1, type_id: 31378 },
{ flag: 5, quantity: 3720, type_id: 24492 },
{ flag: 5, quantity: 5472, type_id: 2679 },
{ flag: 5, quantity: 1, type_id: 35795 },
{ flag: 5, quantity: 1, type_id: 35794 },
{ flag: 5, quantity: 8, type_id: 30486 },
{ flag: 5, quantity: 1, type_id: 35794 },
{ flag: 5, quantity: 396, type_id: 24492 },
],
},
{
name: "Legion",
ship_type_id: 29986,
description: "",
items: [
{ flag: 21, quantity: 1, type_id: 527 },
{ flag: 19, quantity: 1, type_id: 2024 },
{ flag: 15, quantity: 1, type_id: 2364 },
{ flag: 27, quantity: 1, type_id: 3025, charge: { type_id: 253 } },
{ flag: 28, quantity: 1, type_id: 3025, charge: { type_id: 253 } },
{ flag: 29, quantity: 1, type_id: 3025, charge: { type_id: 253 } },
{ flag: 30, quantity: 1, type_id: 3025, charge: { type_id: 253 } },
{ flag: 31, quantity: 1, type_id: 3025, charge: { type_id: 253 } },
{ flag: 32, quantity: 1, type_id: 3025, charge: { type_id: 253 } },
{ flag: 20, quantity: 1, type_id: 3244 },
{ flag: 11, quantity: 1, type_id: 3530 },
{ flag: 14, quantity: 1, type_id: 5839 },
{ flag: 34, quantity: 1, type_id: 11578 },
{ flag: 5, quantity: 6, type_id: 12826 },
{ flag: 12, quantity: 1, type_id: 14072 },
{ flag: 13, quantity: 1, type_id: 14072 },
{ flag: 33, quantity: 1, type_id: 28756 },
{ flag: 5, quantity: 2, type_id: 30832 },
{ flag: 5, quantity: 2, type_id: 30834 },
{ flag: 92, quantity: 1, type_id: 31055 },
{ flag: 94, quantity: 1, type_id: 31071 },
{ flag: 93, quantity: 1, type_id: 31215 },
{ flag: 5, quantity: 1, type_id: 32014 },
{ flag: 5, quantity: 1, type_id: 33474 },
{ flag: 22, quantity: 1, type_id: 35656 },
{ flag: 126, quantity: 1, type_id: 45586 },
{ flag: 128, quantity: 1, type_id: 45598 },
{ flag: 125, quantity: 1, type_id: 45612 },
{ flag: 127, quantity: 1, type_id: 45622 },
],
},
];
export const fullFit = fullFits[0];

View File

@@ -1,7 +1,7 @@
import type { Decorator, Meta, StoryObj } from "@storybook/react";
import React from "react";
import { fullFit } from "../../.storybook/fits";
import { fullFits } from "../../.storybook/fits";
import { DogmaEngineProvider } from "../DogmaEngineProvider";
import { EsiProvider } from "../EsiProvider";
@@ -18,7 +18,9 @@ const meta: Meta<typeof CalculationDetail> = {
export default meta;
type Story = StoryObj<typeof CalculationDetail>;
const useShipSnapshotProvider: Decorator<{ source: "Ship" | { Item: number } }> = (Story, context) => {
const useShipSnapshotProvider: Decorator<{
source: "Ship" | "Char" | "Structure" | "Target" | { Item?: number; Cargo?: number };
}> = (Story, context) => {
const [skills, setSkills] = React.useState<Record<string, number>>({});
return (
@@ -41,7 +43,7 @@ export const Default: Story = {
decorators: [useShipSnapshotProvider],
parameters: {
snapshot: {
fit: fullFit,
fit: fullFits[1],
},
},
};

View File

@@ -29,17 +29,42 @@ const Effect = (props: { effect: ShipSnapshotItemAttributeEffect }) => {
const eveAttribute = eveData.dogmaAttributes?.[props.effect.source_attribute_id];
let sourceName;
let attribute;
let sourceName = "Unknown";
let attribute = undefined;
if (props.effect.source === "Ship") {
sourceName = "Ship";
attribute = shipSnapshot.hull?.attributes.get(props.effect.source_attribute_id);
} else if (props.effect.source.Item !== undefined) {
const item = shipSnapshot.items?.[props.effect.source.Item];
} else if (props.effect.source === "Char") {
sourceName = "Char";
attribute = shipSnapshot.char?.attributes.get(props.effect.source_attribute_id);
} else if (props.effect.source === "Structure") {
sourceName = "Structure";
attribute = shipSnapshot.structure?.attributes.get(props.effect.source_attribute_id);
} else if (props.effect.source === "Target") {
sourceName = "Target";
attribute = shipSnapshot.target?.attributes.get(props.effect.source_attribute_id);
} else {
let item = undefined;
let sourceType = undefined;
/* Lookup the source of the effect. */
if (props.effect.source.Item !== undefined) {
item = shipSnapshot.items?.[props.effect.source.Item];
sourceType = "Item";
} else if (props.effect.source.Skill !== undefined) {
item = shipSnapshot.skills?.[props.effect.source.Skill];
sourceType = "Skill";
} else if (props.effect.source.Charge !== undefined) {
item = shipSnapshot.items?.[props.effect.source.Charge].charge;
sourceType = "Charge";
}
/* Find the attribute on the source. */
if (item === undefined) {
sourceName = "Unknown";
sourceName = `Unknown ${sourceType}`;
} else {
sourceName = eveData.typeIDs?.[item?.type_id]?.name;
sourceName = `${sourceType} - ` + eveData.typeIDs?.[item?.type_id]?.name ?? sourceName;
attribute = item?.attributes.get(props.effect.source_attribute_id);
}
}
@@ -50,6 +75,7 @@ const Effect = (props: { effect: ShipSnapshotItemAttributeEffect }) => {
<span>
{attribute?.value || eveAttribute?.defaultValue}
{props.effect.penalty ? " (penalized)" : ""}
{attribute?.value === undefined ? " (default)" : ""}
</span>
<span>
{sourceName} - {eveAttribute?.name}
@@ -63,8 +89,6 @@ const CalculationDetailMeta = (props: { attributeId: number; attribute: ShipSnap
const eveData = React.useContext(EveDataContext);
const eveAttribute = eveData.dogmaAttributes?.[props.attributeId];
let index = 0;
const sortedEffects = props.attribute.effects.sort((a, b) => {
const aIndex = Object.keys(EffectOperatorOrder).indexOf(a.operator);
const bIndex = Object.keys(EffectOperatorOrder).indexOf(b.operator);
@@ -74,6 +98,7 @@ const CalculationDetailMeta = (props: { attributeId: number; attribute: ShipSnap
return aIndex - bIndex;
});
let index = 0;
return (
<div className={styles.line}>
<div className={styles.entry} onClick={() => setExpanded(!expanded)}>
@@ -88,7 +113,7 @@ const CalculationDetailMeta = (props: { attributeId: number; attribute: ShipSnap
<div className={styles.effect}>
<span>=</span>
<span>{props.attribute.base_value}</span>
<span>base value {props.attributeId < 0 && <>(list of effects might be incomplete)</>}</span>
<span>Base value {props.attributeId < 0 && <>(list of effects might be incomplete)</>}</span>
</div>
{sortedEffects.map((effect) => {
index += 1;
@@ -103,17 +128,31 @@ const CalculationDetailMeta = (props: { attributeId: number; attribute: ShipSnap
* Show in detail for each attribute how the value came to be. This includes
* the base value, all effects (and their source) and the final value.
*/
export const CalculationDetail = (props: { source: "Ship" | { Item: number } }) => {
export const CalculationDetail = (props: {
source: "Ship" | "Char" | "Structure" | "Target" | { Item?: number; Charge?: number };
}) => {
const shipSnapshot = React.useContext(ShipSnapshotContext);
let attributes;
let attributes: [number, ShipSnapshotItemAttribute][] = [];
if (props.source === "Ship") {
attributes = [...(shipSnapshot.hull?.attributes.entries() || [])];
} else if (props.source === "Char") {
attributes = [...(shipSnapshot.char?.attributes.entries() || [])];
} else if (props.source === "Structure") {
attributes = [...(shipSnapshot.structure?.attributes.entries() || [])];
} else if (props.source === "Target") {
attributes = [...(shipSnapshot.target?.attributes.entries() || [])];
} else if (props.source.Item !== undefined) {
const item = shipSnapshot.items?.[props.source.Item];
if (item !== undefined) {
attributes = [...item.attributes.entries()];
}
} else if (props.source.Charge !== undefined) {
const item = shipSnapshot.items?.[props.source.Charge].charge;
if (item !== undefined) {
attributes = [...item.attributes.entries()];
}
}
return (

View File

@@ -6,7 +6,7 @@ import { EveDataContext } from "../EveDataProvider";
export interface ShipSnapshotItemAttributeEffect {
operator: string;
penalty: boolean;
source: "Ship" | { Item: number };
source: "Ship" | "Char" | "Structure" | "Target" | { Item?: number; Charge?: number; Skill?: number };
source_category: string;
source_attribute_id: number;
}
@@ -55,8 +55,14 @@ export type ShipSnapshotSlotsType = keyof ShipSnapshotSlots;
interface ShipSnapshot {
loaded?: boolean;
hull?: ShipSnapshotItem;
items?: ShipSnapshotItem[];
skills?: ShipSnapshotItem[];
char?: ShipSnapshotItem;
structure?: ShipSnapshotItem;
target?: ShipSnapshotItem;
slots: ShipSnapshotSlots;
fit?: EsiFit;
@@ -349,6 +355,10 @@ export const ShipSnapshotProvider = (props: ShipSnapshotProps) => {
loaded: true,
hull: snapshot.hull,
items: snapshot.items,
skills: snapshot.skills,
char: snapshot.char,
structure: snapshot.structure,
target: snapshot.target,
slots,
fit: currentFit,
};