wip
This commit is contained in:
@@ -6,8 +6,8 @@ import { Standing } from '@gridpilot/racing/domain/entities/Standing';
|
||||
|
||||
import type { FeedItem } from '@gridpilot/social/domain/entities/FeedItem';
|
||||
import type { FriendDTO } from '@gridpilot/social/application/dto/FriendDTO';
|
||||
import { faker } from '@gridpilot/testing-support';
|
||||
import { getTeamLogo, getLeagueBanner, getDriverAvatar } from '@gridpilot/testing-support';
|
||||
import { faker } from '../faker/faker';
|
||||
import { getTeamLogo, getLeagueBanner, getDriverAvatar } from '../images/images';
|
||||
|
||||
export type RacingMembership = {
|
||||
driverId: string;
|
||||
@@ -346,20 +346,25 @@ function createFeedEvents(
|
||||
const events: FeedItem[] = [];
|
||||
const now = new Date();
|
||||
const completedRaces = races.filter((race) => race.status === 'completed');
|
||||
const globalDrivers = faker.helpers.shuffle(drivers).slice(0, 10);
|
||||
|
||||
globalDrivers.forEach((driver, index) => {
|
||||
// Focus the global feed around a stable “core” of demo drivers
|
||||
const coreDrivers = faker.helpers.shuffle(drivers).slice(0, 16);
|
||||
|
||||
coreDrivers.forEach((driver, index) => {
|
||||
const league = pickOne(leagues);
|
||||
const race = completedRaces[index % Math.max(1, completedRaces.length)];
|
||||
const minutesAgo = 15 + index * 10;
|
||||
|
||||
const minutesAgo = 10 + index * 5;
|
||||
const baseTimestamp = new Date(now.getTime() - minutesAgo * 60 * 1000);
|
||||
|
||||
const actorFriendId = driver.id;
|
||||
|
||||
// Joined league
|
||||
events.push({
|
||||
id: `friend-joined-league:${driver.id}:${minutesAgo}`,
|
||||
type: 'friend-joined-league',
|
||||
timestamp: baseTimestamp,
|
||||
actorDriverId: driver.id,
|
||||
actorFriendId,
|
||||
leagueId: league.id,
|
||||
headline: `${driver.name} joined ${league.name}`,
|
||||
body: 'They are now registered for the full season.',
|
||||
@@ -367,24 +372,66 @@ function createFeedEvents(
|
||||
ctaHref: `/leagues/${league.id}`,
|
||||
});
|
||||
|
||||
// Finished race / podium highlight
|
||||
const finishingPosition = (index % 5) + 1;
|
||||
events.push({
|
||||
id: `friend-finished-race:${driver.id}:${minutesAgo}`,
|
||||
type: 'friend-finished-race',
|
||||
timestamp: new Date(baseTimestamp.getTime() - 10 * 60 * 1000),
|
||||
timestamp: new Date(baseTimestamp.getTime() - 8 * 60 * 1000),
|
||||
actorDriverId: driver.id,
|
||||
actorFriendId,
|
||||
leagueId: race.leagueId,
|
||||
raceId: race.id,
|
||||
position: (index % 5) + 1,
|
||||
headline: `${driver.name} finished P${(index % 5) + 1} at ${race.track}`,
|
||||
body: `${driver.name} secured a strong result in ${race.car}.`,
|
||||
position: finishingPosition,
|
||||
headline: `${driver.name} finished P${finishingPosition} at ${race.track}`,
|
||||
body:
|
||||
finishingPosition <= 3
|
||||
? `${driver.name} scored a podium in ${race.car}.`
|
||||
: `${driver.name} secured a strong result in ${race.car}.`,
|
||||
ctaLabel: 'View results',
|
||||
ctaHref: `/races/${race.id}/results`,
|
||||
});
|
||||
|
||||
// New personal best
|
||||
events.push({
|
||||
id: `friend-new-personal-best:${driver.id}:${minutesAgo}`,
|
||||
type: 'friend-new-personal-best',
|
||||
timestamp: new Date(baseTimestamp.getTime() - 20 * 60 * 1000),
|
||||
actorDriverId: driver.id,
|
||||
actorFriendId,
|
||||
leagueId: race.leagueId,
|
||||
raceId: race.id,
|
||||
headline: `${driver.name} set a new personal best at ${race.track}`,
|
||||
body: 'Consistency and pace are trending up this season.',
|
||||
ctaLabel: 'View lap chart',
|
||||
ctaHref: `/races/${race.id}/analysis`,
|
||||
});
|
||||
|
||||
// Joined team (where applicable)
|
||||
const driverFriendships = friendships.filter((f) => f.driverId === driver.id);
|
||||
if (driverFriendships.length > 0) {
|
||||
const friend = pickOne(driverFriendships);
|
||||
const teammate = drivers.find((d) => d.id === friend.friendId);
|
||||
if (teammate) {
|
||||
events.push({
|
||||
id: `friend-joined-team:${driver.id}:${minutesAgo}`,
|
||||
type: 'friend-joined-team',
|
||||
timestamp: new Date(baseTimestamp.getTime() - 30 * 60 * 1000),
|
||||
actorDriverId: driver.id,
|
||||
actorFriendId,
|
||||
headline: `${driver.name} and ${teammate.name} are now teammates`,
|
||||
body: 'They will be sharing strategy and setups this season.',
|
||||
ctaLabel: 'View team',
|
||||
ctaHref: '/teams',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// League highlight
|
||||
events.push({
|
||||
id: `league-highlight:${league.id}:${minutesAgo}`,
|
||||
type: 'league-highlight',
|
||||
timestamp: new Date(baseTimestamp.getTime() - 30 * 60 * 1000),
|
||||
timestamp: new Date(baseTimestamp.getTime() - 45 * 60 * 1000),
|
||||
leagueId: league.id,
|
||||
headline: `${league.name} active with ${drivers.length}+ drivers`,
|
||||
body: 'Participation is growing. Perfect time to join the grid.',
|
||||
@@ -393,6 +440,40 @@ function createFeedEvents(
|
||||
});
|
||||
});
|
||||
|
||||
// Global “system” events: new race scheduled and results posted
|
||||
const upcomingRaces = races.filter((race) => race.status === 'scheduled').slice(0, 8);
|
||||
upcomingRaces.forEach((race, index) => {
|
||||
const minutesAgo = 60 + index * 15;
|
||||
const timestamp = new Date(now.getTime() - minutesAgo * 60 * 1000);
|
||||
events.push({
|
||||
id: `new-race-scheduled:${race.id}`,
|
||||
type: 'new-race-scheduled',
|
||||
timestamp,
|
||||
leagueId: race.leagueId,
|
||||
raceId: race.id,
|
||||
headline: `New race scheduled at ${race.track}`,
|
||||
body: `${race.car} • ${race.scheduledAt.toLocaleString()}`,
|
||||
ctaLabel: 'View schedule',
|
||||
ctaHref: `/races/${race.id}`,
|
||||
});
|
||||
});
|
||||
|
||||
completedRaces.slice(0, 8).forEach((race, index) => {
|
||||
const minutesAgo = 180 + index * 20;
|
||||
const timestamp = new Date(now.getTime() - minutesAgo * 60 * 1000);
|
||||
events.push({
|
||||
id: `new-result-posted:${race.id}`,
|
||||
type: 'new-result-posted',
|
||||
timestamp,
|
||||
leagueId: race.leagueId,
|
||||
raceId: race.id,
|
||||
headline: `Results posted for ${race.track}`,
|
||||
body: 'Standings and stats updated across the grid.',
|
||||
ctaLabel: 'View classification',
|
||||
ctaHref: `/races/${race.id}/results`,
|
||||
});
|
||||
});
|
||||
|
||||
const sorted = events
|
||||
.slice()
|
||||
.sort((a, b) => b.timestamp.getTime() - a.timestamp.getTime());
|
||||
@@ -428,7 +509,15 @@ export function createStaticRacingSeed(seed: number): RacingSeedData {
|
||||
|
||||
/**
|
||||
* Singleton seed used by website demo helpers.
|
||||
* This mirrors the previous apps/website/lib/demo-data/index.ts behavior.
|
||||
*
|
||||
* Alpha demo dataset (deterministic, in-memory only):
|
||||
* - 90+ drivers across multiple leagues
|
||||
* - Leagues with precomputed races, results and standings
|
||||
* - Team memberships and friendships forming social “circles”
|
||||
* - Feed events referencing real driver, league, race and team IDs
|
||||
*
|
||||
* This mirrors the previous apps/website/lib/demo-data/index.ts behavior while
|
||||
* keeping a stable shape for the website alpha experience.
|
||||
*/
|
||||
const staticSeed = createStaticRacingSeed(42);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user