From 0e519bd03ac03be4fefccca425d573aa3fe9d998 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Tue, 5 Mar 2024 22:44:49 +0100 Subject: [PATCH] feat(calculation-details): improve the overall ability of this component (#74) --- .storybook/fits.ts | 258 ++++++------------ .../CalculationDetail.stories.tsx | 8 +- src/CalculationDetail/CalculationDetail.tsx | 61 ++++- .../ShipSnapshotProvider.tsx | 12 +- 4 files changed, 144 insertions(+), 195 deletions(-) diff --git a/.storybook/fits.ts b/.storybook/fits.ts index 441af73..607d6e4 100644 --- a/.storybook/fits.ts +++ b/.storybook/fits.ts @@ -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]; diff --git a/src/CalculationDetail/CalculationDetail.stories.tsx b/src/CalculationDetail/CalculationDetail.stories.tsx index 775d415..a3f0e98 100644 --- a/src/CalculationDetail/CalculationDetail.stories.tsx +++ b/src/CalculationDetail/CalculationDetail.stories.tsx @@ -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 = { export default meta; type Story = StoryObj; -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>({}); return ( @@ -41,7 +43,7 @@ export const Default: Story = { decorators: [useShipSnapshotProvider], parameters: { snapshot: { - fit: fullFit, + fit: fullFits[1], }, }, }; diff --git a/src/CalculationDetail/CalculationDetail.tsx b/src/CalculationDetail/CalculationDetail.tsx index 971299f..c2fef6b 100644 --- a/src/CalculationDetail/CalculationDetail.tsx +++ b/src/CalculationDetail/CalculationDetail.tsx @@ -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 }) => { {attribute?.value || eveAttribute?.defaultValue} {props.effect.penalty ? " (penalized)" : ""} + {attribute?.value === undefined ? " (default)" : ""} {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 (
setExpanded(!expanded)}> @@ -88,7 +113,7 @@ const CalculationDetailMeta = (props: { attributeId: number; attribute: ShipSnap
= {props.attribute.base_value} - base value {props.attributeId < 0 && <>(list of effects might be incomplete)} + Base value {props.attributeId < 0 && <>(list of effects might be incomplete)}
{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 ( diff --git a/src/ShipSnapshotProvider/ShipSnapshotProvider.tsx b/src/ShipSnapshotProvider/ShipSnapshotProvider.tsx index 5bcd6fd..bd1b09e 100644 --- a/src/ShipSnapshotProvider/ShipSnapshotProvider.tsx +++ b/src/ShipSnapshotProvider/ShipSnapshotProvider.tsx @@ -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, };