diff --git a/components/PlayerNumber.tsx b/components/PlayerNumber.tsx new file mode 100644 index 0000000..66863fe --- /dev/null +++ b/components/PlayerNumber.tsx @@ -0,0 +1,23 @@ +"use client"; + +import type { Card } from "@/lib/scoring/types"; +import { Section } from "./ScoutReport"; +import { resolveResultTheme } from "./finishTheme"; + +export default function PlayerNumber({ card }: { card: Card }) { + const theme = resolveResultTheme(card); + const accent = theme.ink; + + return ( +
+
+
+ {card.squadNumber} +
+
+
+ ); +} diff --git a/components/ResultView.tsx b/components/ResultView.tsx index c2aeaa6..fa8e744 100644 --- a/components/ResultView.tsx +++ b/components/ResultView.tsx @@ -19,6 +19,8 @@ import DistributionPanel from "./DistributionPanel"; import { confettiPalette, resolveResultTheme } from "./finishTheme"; import { useReveal } from "@/hooks/useReveal"; import { burstConfetti } from "@/lib/confetti"; +import PlayerNumber from "./PlayerNumber"; + const HowItWorksModal = dynamic(() => import("./HowItWorksModal"), { ssr: false }); @@ -183,11 +185,12 @@ export default function ResultView({ - {/* right — scouting metrics + distribution */} + {/* right — scouting metrics + squad number + distribution */}
+
diff --git a/components/ScoutReport.tsx b/components/ScoutReport.tsx index 3090e36..b3ba8fa 100644 --- a/components/ScoutReport.tsx +++ b/components/ScoutReport.tsx @@ -97,7 +97,7 @@ function AttributeRow({ label, children }: { label: string; children: React.Reac // Editorial section: an accent dash + tracked label, then content — reads as a // scouting-report section rather than a dashboard card. -function Section({ +export function Section({ title, accent, className, diff --git a/lib/scoring/engine.ts b/lib/scoring/engine.ts index 68ef9c5..e710199 100644 --- a/lib/scoring/engine.ts +++ b/lib/scoring/engine.ts @@ -3,6 +3,8 @@ import { topLanguageLogo } from "../github/languages"; import { deriveMetrics, deriveSkillMoves, deriveStyle, deriveWeakFoot, deriveWorkRate } from "./attributes"; import { ATTACK_STATS, FINISH_LABELS, FOUNDER_OVERALL, FOUNDERS, K, STATS, WEIGHTS } from "./constants"; import { derivePlaystyles } from "./playstyles"; +import { generateSquadNumber } from "./squadNumber"; + import type { Archetype, Card, @@ -212,6 +214,7 @@ export function buildCard(s: Signals): Card { languageLogo, ...(founder ? { founder } : null), legacy: { L }, + squadNumber: generateSquadNumber(s.login, position, overall), report: { skillMoves: skill.value, weakFoot: weak.value, diff --git a/lib/scoring/squadNumber.ts b/lib/scoring/squadNumber.ts new file mode 100644 index 0000000..c160259 --- /dev/null +++ b/lib/scoring/squadNumber.ts @@ -0,0 +1,31 @@ +import type { Position } from "./types"; + +export function generateSquadNumber(login: string, position: Position, overall: number): number { + //Create a hash from the username + let hash = 0; + for (let i = 0; i < login.length; i++) { + hash = login.charCodeAt(i) + ((hash << 5) - hash); + } + + hash = Math.abs(hash); + + //Iconic squad numbers grouped by football positions + const posNumbers: Record = { + ST: [7, 9, 10, 11, 19, 22, 18, 20, 14, 45, 99], + RW: [7, 10, 11, 17, 22, 21, 20, 23, 18, 10, 19], + CAM: [10, 8, 11, 20, 22, 18, 23, 42], + CM: [8, 6, 14, 16, 17, 22, 16, 15, 19, 20, 88], + CDM: [6, 4, 15, 16, 14, 28, 23, 8, 18, 25, 5], + CB: [4, 5, 2, 3, 6, 12, 15, 26, 33], + }; + + const pool = posNumbers[position]||[7, 9, 10, 11]; + + //Elite players (90+ OVR) always get the classic #1 choice for their position + if(overall >= 90){ + return pool[0]; + } + + //Else use the hash to pick a varied, but consistent number + return pool[hash % pool.length]; +} \ No newline at end of file diff --git a/lib/scoring/types.ts b/lib/scoring/types.ts index 0efb058..4c79df6 100644 --- a/lib/scoring/types.ts +++ b/lib/scoring/types.ts @@ -102,5 +102,6 @@ export interface Card { // Set only for gitfut founders — their bespoke card art/accent + hint metadata. // Optional so every other card (and previously serialized ones) stay valid. founder?: FounderMeta; + squadNumber: number; //Squad nnumber generated from login and position report: Report; }