diff --git a/CHANGELOG.md b/CHANGELOG.md index e2d88c0..2478a42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.4.3] - 2026-04-25 + +### Fixed +- Overstable disc flight paths now show a realistic left-hooking finish instead of appearing to straighten out at the end. All flight paths also fly straighter for longer before curving. +- CSV import and export now include all newer disc attributes: Secondary Color, Secondary Pattern, and Custom Flight Numbers (Glide, Turn, Fade). Previously these fields were silently dropped during import/export. +- CSV export now includes the Vault name for each disc. + ## [0.4.2] - 2026-04-25 ### Added diff --git a/package.json b/package.json index 1a35ada..99da2ac 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "discvault", - "version": "0.4.2", + "version": "0.4.3", "private": true, "scripts": { "dev": "next dev -p 3001", diff --git a/src/app/actions/inventory.ts b/src/app/actions/inventory.ts index 2018e87..4c8b4ad 100644 --- a/src/app/actions/inventory.ts +++ b/src/app/actions/inventory.ts @@ -244,6 +244,9 @@ export async function importDiscs(records: any[], targetCollectionId?: string) { condition: parseInt(record.condition) || null, ink: record.ink || null, notes: record.notes || null, + userGlide: parseFloat(record.userGlide) || null, + userTurn: parseFloat(record.userTurn) || null, + userFade: parseFloat(record.userFade) || null, } }) successCount++ @@ -261,7 +264,8 @@ export async function importDiscs(records: any[], targetCollectionId?: string) { export async function exportInventory() { return await prisma.inventory.findMany({ include: { - mold: true + mold: true, + collection: true, }, orderBy: { createdAt: 'desc' diff --git a/src/components/CSVImporter.tsx b/src/components/CSVImporter.tsx index f69add9..26075f3 100644 --- a/src/components/CSVImporter.tsx +++ b/src/components/CSVImporter.tsx @@ -33,12 +33,17 @@ const SCHEMA_FIELDS = [ { id: 'fade', label: 'Fade' }, { id: 'category', label: 'Category' }, { id: 'color', label: 'Color' }, + { id: 'secondaryColor', label: 'Secondary Color' }, + { id: 'secondaryPattern', label: 'Secondary Pattern' }, { id: 'stamp', label: 'Stamp' }, { id: 'stampFoil', label: 'Stamp Foil' }, { id: 'location', label: 'Location' }, { id: 'condition', label: 'Condition (1-10)' }, { id: 'ink', label: 'Ink Status' }, { id: 'notes', label: 'Notes' }, + { id: 'userGlide', label: 'Custom Glide' }, + { id: 'userTurn', label: 'Custom Turn' }, + { id: 'userFade', label: 'Custom Fade' }, ] interface Vault { diff --git a/src/components/ExportButton.tsx b/src/components/ExportButton.tsx index 0333922..16e1753 100644 --- a/src/components/ExportButton.tsx +++ b/src/components/ExportButton.tsx @@ -30,6 +30,7 @@ export default function ExportButton({ variant = 'default' }: { variant?: 'defau const data = await exportInventory() const flatData = data.map(item => ({ + Vault: item.collection?.name || '', Manufacturer: item.mold.brand, Mold: item.mold.name, Category: item.mold.category, @@ -40,12 +41,17 @@ export default function ExportButton({ variant = 'default' }: { variant?: 'defau Plastic: item.plastic || '', Weight: item.weight || '', Color: item.color || '', + SecondaryColor: item.secondaryColor || '', + SecondaryPattern: item.secondaryPattern || '', Stamp: item.stamp || '', StampFoil: item.stampFoil || '', Location: item.location || '', Condition: item.condition || '', Ink: item.ink || '', Notes: item.notes || '', + UserGlide: item.userGlide ?? '', + UserTurn: item.userTurn ?? '', + UserFade: item.userFade ?? '', AddedDate: new Date(item.createdAt).toLocaleDateString() })) diff --git a/src/lib/flightPath.ts b/src/lib/flightPath.ts index 50477e7..d3a226d 100644 --- a/src/lib/flightPath.ts +++ b/src/lib/flightPath.ts @@ -37,20 +37,25 @@ export function generateFlightPath( // Calculate horizontal intensity of turn and fade // Turn is typically negative (right for RHBH), Fade is positive (left for RHBH). - // On our chart, more positive is left (overstable), more negative is right (understable). + // On our chart, more positive stability is left (overstable), more negative is right (understable). // Adjust turn/fade intensity by speed (higher speed discs have more pronounced curves) const speedFactor = Math.max(1, speed / 7); - const turnIntensity = turn * 15 * speedFactor; - const fadeIntensity = fade * 10 * speedFactor; + const turnIntensity = turn * 10 * speedFactor; + const fadeIntensity = fade * 12 * speedFactor; - // Release point is usually vertical, so C1 is shifted by turn - const cp1x = startX - turnIntensity; - const cp1y = startY - (startY - endY) * 0.4; + // CP1 handles the high-speed turn phase. + // Placed at 70% of the flight distance so the disc flies mostly straight + // before any turn displacement kicks in — mimicking real flight where + // the disc holds its line for the majority of the throw. + const cp1x = startX - (turnIntensity * 0.5); + const cp1y = startY - (startY - endY) * 0.7; - // C2 is shifted by fade relative to the end position - const cp2x = endX - (fadeIntensity * 0.5); - const cp2y = endY + (startY - endY) * 0.2; + // CP2 handles the low-speed fade phase. + // Pushed PAST the endpoint in the fade direction so the curve + // arrives at the endpoint already hooking left, rather than straightening out. + const cp2x = endX + (fadeIntensity * 0.6); + const cp2y = endY + (startY - endY) * 0.1; return `M ${startX} ${startY} C ${cp1x} ${cp1y}, ${cp2x} ${cp2y}, ${endX} ${endY}`; }