/** * Port "relations" describe the medium a port carries (water, power, gas ...). * Two ports may be connected only when their media are compatible. Colors are * provided by swappable color schemes so the whole diagram can be re-themed. */ export type MediumId = | 'water' | 'hotWater' | 'sewage' | 'gas' | 'steam' | 'air' | 'power' | 'signal' export interface Medium { id: MediumId label: string /** Media (besides itself) this medium may connect to. */ compatibleWith: MediumId[] } export const MEDIA: Record = { water: { id: 'water', label: 'Cold water', compatibleWith: ['hotWater'] }, hotWater: { id: 'hotWater', label: 'Hot water', compatibleWith: ['water', 'steam'] }, sewage: { id: 'sewage', label: 'Sewage', compatibleWith: [] }, gas: { id: 'gas', label: 'Gas', compatibleWith: [] }, steam: { id: 'steam', label: 'Steam', compatibleWith: ['hotWater'] }, air: { id: 'air', label: 'Compressed air', compatibleWith: [] }, power: { id: 'power', label: 'Power line', compatibleWith: [] }, signal: { id: 'signal', label: 'Signal / control', compatibleWith: [] } } export const MEDIUM_IDS = Object.keys(MEDIA) as MediumId[] /** True when a port of medium `a` may be connected to a port of medium `b`. */ export function canConnectMedia(a: MediumId, b: MediumId): boolean { if (a === b) return true return ( MEDIA[a]?.compatibleWith.includes(b) === true || MEDIA[b]?.compatibleWith.includes(a) === true ) } // ---- Color schemes -------------------------------------------------------- export interface ColorScheme { id: string label: string colors: Record } export const COLOR_SCHEMES: ColorScheme[] = [ { id: 'default', label: 'Default', colors: { water: '#2f7fe0', hotWater: '#e0562f', sewage: '#7a5b34', gas: '#e0b62f', steam: '#d14fd1', air: '#3fb6c0', power: '#e0d030', signal: '#9aa0a6' } }, { id: 'colorblind', label: 'Color-blind safe', colors: { water: '#0072B2', hotWater: '#D55E00', sewage: '#8c6d31', gas: '#E69F00', steam: '#CC79A7', air: '#56B4E9', power: '#F0E442', signal: '#999999' } }, { id: 'print', label: 'Print (mono-friendly)', colors: { water: '#1f3a93', hotWater: '#7b241c', sewage: '#4d3b1f', gas: '#7d6608', steam: '#4a235a', air: '#0e6251', power: '#7d6608', signal: '#424949' } } ] export function getColorScheme(id: string): ColorScheme { return COLOR_SCHEMES.find((s) => s.id === id) ?? COLOR_SCHEMES[0] } export function mediumColor(mediumId: MediumId | string, schemeId = 'default'): string { const scheme = getColorScheme(schemeId) return scheme.colors[mediumId as MediumId] ?? '#9aa0a6' }