MVP complete

This commit is contained in:
2024-09-09 16:59:00 -04:00
parent e21173c8e4
commit 7c7b152d79
13 changed files with 1314 additions and 705 deletions

View File

@ -1,15 +1,16 @@
type Color = string; // Hex color code
import Color from 'color';
type ColorScheme = {
name: string;
colors: {
primary: { background: Color; foreground: Color };
primary: { background: string; foreground: string };
normal: {
black: Color; red: Color; green: Color; yellow: Color;
blue: Color; magenta: Color; cyan: Color; white: Color;
black: string; red: string; green: string; yellow: string;
blue: string; magenta: string; cyan: string; white: string;
};
bright: {
black: Color; red: Color; green: Color; yellow: Color;
blue: Color; magenta: Color; cyan: Color; white: Color;
black: string; red: string; green: string; yellow: string;
blue: string; magenta: string; cyan: string; white: string;
};
};
};
@ -18,61 +19,108 @@ import knownSchemesData from '../../formatted_themes.json';
const knownSchemes: ColorScheme[] = knownSchemesData;
function generateRandomColor(): Color {
function generateRandomColor(): string {
return '#' + Math.floor(Math.random()*16777215).toString(16).padStart(6, '0');
}
function generateCreativeName(): string {
const adjectives = ['Cosmic', 'Neon', 'Mystic', 'Retro', 'Cyber', 'Ethereal', 'Vibrant', 'Dreamy', 'Futuristic', 'Nostalgic'];
const nouns = ['Sunset', 'Aurora', 'Galaxy', 'Ocean', 'Forest', 'Desert', 'Nebula', 'Horizon', 'Oasis', 'Metropolis'];
return `${adjectives[Math.floor(Math.random() * adjectives.length)]} ${nouns[Math.floor(Math.random() * nouns.length)]}`;
function generateCreativeName(colors: { [key: string]: string }): string {
const allColors = Object.values(colors);
const dominantColor = getDominantColor(allColors);
const mood = getMood(allColors);
const theme = getTheme(dominantColor);
const nameComponents = [mood, theme].filter(Boolean);
if (nameComponents.length === 1) {
nameComponents.push(getRandomAdjective(dominantColor));
}
return nameComponents.join(' ');
}
function getDominantColor(colors: string[]): Color {
return colors.reduce((dominant, color) => {
const current = Color(color);
return current.luminosity() > dominant.luminosity() ? current : dominant;
}, Color(colors[0]));
}
function getMood(colors: string[]): string {
const avgSaturation = colors.reduce((sum, color) => sum + Color(color).saturationl(), 0) / colors.length;
const avgLightness = colors.reduce((sum, color) => sum + Color(color).lightness(), 0) / colors.length;
if (avgSaturation > 50 && avgLightness > 50) return 'Vibrant';
if (avgSaturation < 30 && avgLightness < 40) return 'Muted';
if (avgLightness > 70) return 'Bright';
if (avgLightness < 30) return 'Dark';
return '';
}
function getTheme(dominantColor: Color): string {
const hue = dominantColor.hue();
const themes = [
{ name: 'Sunset', range: [0, 60] },
{ name: 'Citrus', range: [45, 90] },
{ name: 'Forest', range: [90, 150] },
{ name: 'Ocean', range: [150, 210] },
{ name: 'Twilight', range: [210, 270] },
{ name: 'Lavender', range: [270, 330] },
{ name: 'Berry', range: [330, 360] },
];
const theme = themes.find(t => hue >= t.range[0] && hue < t.range[1]);
return theme ? theme.name : '';
}
function getRandomAdjective(color: Color): string {
const adjectives = {
warm: ['Cozy', 'Toasty', 'Snug'],
cool: ['Crisp', 'Fresh', 'Breezy'],
neutral: ['Balanced', 'Harmonious', 'Zen'],
bright: ['Radiant', 'Luminous', 'Gleaming'],
dark: ['Mysterious', 'Enigmatic', 'Shadowy'],
};
const hue = color.hue();
const lightness = color.lightness();
let category: keyof typeof adjectives;
if (hue < 60 || hue > 300) category = 'warm';
else if (hue >= 60 && hue <= 300) category = 'cool';
else if (lightness > 70) category = 'bright';
else if (lightness < 30) category = 'dark';
else category = 'neutral';
return adjectives[category][Math.floor(Math.random() * adjectives[category].length)];
}
function generateRandomScheme(): ColorScheme {
let x = {
name: generateCreativeName() + "rand",
colors: {
primary: { background: generateRandomColor(), foreground: generateRandomColor() },
normal: {
black: generateRandomColor(), red: generateRandomColor(), green: generateRandomColor(), yellow: generateRandomColor(),
blue: generateRandomColor(), magenta: generateRandomColor(), cyan: generateRandomColor(), white: generateRandomColor()
},
bright: {
black: generateRandomColor(), red: generateRandomColor(), green: generateRandomColor(), yellow: generateRandomColor(),
blue: generateRandomColor(), magenta: generateRandomColor(), cyan: generateRandomColor(), white: generateRandomColor()
}
const colors = {
primary: { background: generateRandomColor(), foreground: generateRandomColor() },
normal: {
black: generateRandomColor(), red: generateRandomColor(), green: generateRandomColor(), yellow: generateRandomColor(),
blue: generateRandomColor(), magenta: generateRandomColor(), cyan: generateRandomColor(), white: generateRandomColor()
},
bright: {
black: generateRandomColor(), red: generateRandomColor(), green: generateRandomColor(), yellow: generateRandomColor(),
blue: generateRandomColor(), magenta: generateRandomColor(), cyan: generateRandomColor(), white: generateRandomColor()
}
};
x.colors.primary.background = x.colors.normal.black;
x.colors.primary.foreground = x.colors.bright.white;
colors.primary.background = colors.normal.black;
colors.primary.foreground = colors.bright.white;
return x;
}
function crossTitles(title1: string, title2: string): string {
const words1 = title1.split(' ');
const words2 = title2.split(' ');
const firstWord = Math.random() < 0.5 ? words1[0] : words2[1];
const secondWord = Math.random() < 0.5 ? words2[0] : words1[1];
return `${firstWord} ${secondWord}`;
}
function mutateColor(color: Color): Color {
const r = parseInt(color.slice(1, 3), 16);
const g = parseInt(color.slice(3, 5), 16);
const b = parseInt(color.slice(5, 7), 16);
const mutateComponent = (component: number) => {
const mutation = Math.floor(Math.random() * 51) - 25; // Random number between -25 and 25
return Math.max(0, Math.min(255, component + mutation));
return {
name: generateCreativeName({ ...colors.normal, ...colors.bright }),
colors: colors
};
}
const newR = mutateComponent(r);
const newG = mutateComponent(g);
const newB = mutateComponent(b);
return `#${newR.toString(16).padStart(2, '0')}${newG.toString(16).padStart(2, '0')}${newB.toString(16).padStart(2, '0')}`;
function mutateColor(color: string): string {
const c = Color(color);
const hue = (c.hue() + Math.random() * 30 - 15 + 360) % 360;
const saturation = Math.max(0, Math.min(100, c.saturationl() + Math.random() * 20 - 10));
const lightness = Math.max(0, Math.min(100, c.lightness() + Math.random() * 20 - 10));
return c.hsl(hue, saturation, lightness).hex();
}
function generateSchemeFromGeneticAlgorithm(likedSchemes: ColorScheme[], dislikedSchemes: ColorScheme[]): ColorScheme {
@ -84,26 +132,26 @@ function generateSchemeFromGeneticAlgorithm(likedSchemes: ColorScheme[], dislike
const newScheme: ColorScheme = JSON.parse(JSON.stringify(parentScheme)); // Deep copy
// Mutate colors
Object.keys(newScheme.colors).forEach((colorGroup) => {
Object.keys(newScheme.colors[colorGroup]).forEach((colorName) => {
Object.keys(newScheme.colors).forEach((colorGroup: keyof typeof newScheme.colors) => {
Object.keys(newScheme.colors[colorGroup]).forEach((colorName: string) => {
if (Math.random() < 0.3) { // 30% chance of mutation
newScheme.colors[colorGroup][colorName] = mutateColor(newScheme.colors[colorGroup][colorName]);
(newScheme.colors[colorGroup] as any)[colorName] = mutateColor((newScheme.colors[colorGroup] as any)[colorName]);
}
});
});
// Avoid similarities with disliked schemes
dislikedSchemes.forEach(dislikedScheme => {
Object.keys(newScheme.colors).forEach((colorGroup) => {
Object.keys(newScheme.colors[colorGroup]).forEach((colorName) => {
if (newScheme.colors[colorGroup][colorName] === dislikedScheme.colors[colorGroup][colorName]) {
newScheme.colors[colorGroup][colorName] = mutateColor(newScheme.colors[colorGroup][colorName]);
Object.keys(newScheme.colors).forEach((colorGroup: keyof typeof newScheme.colors) => {
Object.keys(newScheme.colors[colorGroup]).forEach((colorName: string) => {
if ((newScheme.colors[colorGroup] as any)[colorName] === (dislikedScheme.colors[colorGroup] as any)[colorName]) {
(newScheme.colors[colorGroup] as any)[colorName] = mutateColor((newScheme.colors[colorGroup] as any)[colorName]);
}
});
});
});
newScheme.name = generateCreativeName() + "gen";
newScheme.name = generateCreativeName({ ...newScheme.colors.normal, ...newScheme.colors.bright });
return newScheme;
}

View File

@ -0,0 +1,87 @@
import { ColorScheme } from './colorSchemes';
export function generateYAML(scheme: ColorScheme): string {
return `colors:
# Default colors
primary:
background: '${scheme.colors.primary.background}'
foreground: '${scheme.colors.primary.foreground}'
# Normal colors
normal:
black: '${scheme.colors.normal.black}'
red: '${scheme.colors.normal.red}'
green: '${scheme.colors.normal.green}'
yellow: '${scheme.colors.normal.yellow}'
blue: '${scheme.colors.normal.blue}'
magenta: '${scheme.colors.normal.magenta}'
cyan: '${scheme.colors.normal.cyan}'
white: '${scheme.colors.normal.white}'
# Bright colors
bright:
black: '${scheme.colors.bright.black}'
red: '${scheme.colors.bright.red}'
green: '${scheme.colors.bright.green}'
yellow: '${scheme.colors.bright.yellow}'
blue: '${scheme.colors.bright.blue}'
magenta: '${scheme.colors.bright.magenta}'
cyan: '${scheme.colors.bright.cyan}'
white: '${scheme.colors.bright.white}'
`;
}
export function generateJSON(scheme: ColorScheme): string {
return JSON.stringify(scheme.colors, null, 2);
}
export function generateXResources(scheme: ColorScheme): string {
return `*background: ${scheme.colors.primary.background}
*foreground: ${scheme.colors.primary.foreground}
*color0: ${scheme.colors.normal.black}
*color1: ${scheme.colors.normal.red}
*color2: ${scheme.colors.normal.green}
*color3: ${scheme.colors.normal.yellow}
*color4: ${scheme.colors.normal.blue}
*color5: ${scheme.colors.normal.magenta}
*color6: ${scheme.colors.normal.cyan}
*color7: ${scheme.colors.normal.white}
*color8: ${scheme.colors.bright.black}
*color9: ${scheme.colors.bright.red}
*color10: ${scheme.colors.bright.green}
*color11: ${scheme.colors.bright.yellow}
*color12: ${scheme.colors.bright.blue}
*color13: ${scheme.colors.bright.magenta}
*color14: ${scheme.colors.bright.cyan}
*color15: ${scheme.colors.bright.white}
`;
}
export function generateTOML(scheme: ColorScheme): string {
return `[colors.primary]
background = "${scheme.colors.primary.background}"
foreground = "${scheme.colors.primary.foreground}"
[colors.normal]
black = "${scheme.colors.normal.black}"
red = "${scheme.colors.normal.red}"
green = "${scheme.colors.normal.green}"
yellow = "${scheme.colors.normal.yellow}"
blue = "${scheme.colors.normal.blue}"
magenta = "${scheme.colors.normal.magenta}"
cyan = "${scheme.colors.normal.cyan}"
white = "${scheme.colors.normal.white}"
[colors.bright]
black = "${scheme.colors.bright.black}"
red = "${scheme.colors.bright.red}"
green = "${scheme.colors.bright.green}"
yellow = "${scheme.colors.bright.yellow}"
blue = "${scheme.colors.bright.blue}"
magenta = "${scheme.colors.bright.magenta}"
cyan = "${scheme.colors.bright.cyan}"
white = "${scheme.colors.bright.white}"
`;
}