Back to js-functions
09-holi-colors.js
JavaScript
1/**
2 * 🎨 Holi Color Mixer - Pure Functions
3 *
4 * Holi ka festival hai! Rang mix karne hain. Lekin PURE FUNCTIONS use
5 * karne hain — matlab:
6 * 1. Input ko KABHI modify mat karo (no mutation)
7 * 2. Same input pe HAMESHA same output aaye
8 * 3. Koi side effects nahi (no console.log, no external state changes)
9 *
10 * Har color object: { name: string, r: number, g: number, b: number }
11 * where r, g, b are 0-255 (RGB values)
12 *
13 * Functions:
14 *
15 * 1. mixColors(color1, color2)
16 * - Mix two colors by averaging their RGB values
17 * - New name: `${color1.name}-${color2.name}`
18 * - Round RGB values to integers
19 * - MUST NOT modify color1 or color2
20 * - Agar either color null/invalid, return null
21 *
22 * 2. adjustBrightness(color, factor)
23 * - Multiply each RGB by factor, clamp to 0-255 range
24 * - Round to integers using Math.round
25 * - Name stays same
26 * - MUST NOT modify original color
27 * - Agar color null or factor not number, return null
28 *
29 * 3. addToPalette(palette, color)
30 * - Return NEW array with color added at end
31 * - MUST NOT modify original palette array
32 * - Agar palette not array, return [color]
33 * - Agar color null/invalid, return copy of palette
34 *
35 * 4. removeFromPalette(palette, colorName)
36 * - Return NEW array without the color with that name
37 * - MUST NOT modify original palette
38 * - Agar palette not array, return []
39 *
40 * 5. mergePalettes(palette1, palette2)
41 * - Merge two palettes into NEW array
42 * - No duplicate names (keep first occurrence)
43 * - MUST NOT modify either original palette
44 * - Agar either not array, treat as empty array
45 *
46 * Hint: Use spread operator [...arr], Object spread {...obj} to create
47 * copies. NEVER use push, splice, or direct property assignment on inputs.
48 *
49 * @example
50 * const red = { name: "red", r: 255, g: 0, b: 0 };
51 * const blue = { name: "blue", r: 0, g: 0, b: 255 };
52 * mixColors(red, blue)
53 * // => { name: "red-blue", r: 128, g: 0, b: 128 }
54 * // red and blue objects are UNCHANGED
55 */
56export function mixColors(color1, color2) {
57 if(color1 === null || color2 === null || typeof color1 !== "object" || typeof color2 !== "object"){
58 return null
59 }
60
61 const name = `${color1.name}-${color2.name}`
62 const r = Math.round((color1.r + color2.r)/2)
63 const g = Math.round((color1.g + color2.g)/2)
64 const b = Math.round((color1.b + color2.b)/2)
65
66 return {name,r,g,b}
67}
68
69export function adjustBrightness(color, factor) {
70 if(color === null || typeof factor !== "number"){
71 return null
72 }
73 const r = Math.round(Math.min(255, Math.max(0, color.r * factor)))
74 const g = Math.round(Math.min(255, Math.max(0, color.g * factor)))
75 const b = Math.round(Math.min(255, Math.max(0, color.b * factor)))
76
77 return {name:color.name, r,g,b}
78}
79
80export function addToPalette(palette, color) {
81 if(!Array.isArray(palette)){
82 return [color]
83 }
84 if(color === null){
85 return [...palette]
86 }
87
88 return [...palette, color]
89}
90
91export function removeFromPalette(palette, colorName) {
92 if (!Array.isArray(palette)) return [];
93 return palette.filter((color) => color.name !== colorName);
94}
95
96export function mergePalettes(palette1, palette2) {
97 const p1 = Array.isArray(palette1) ? palette1 : [];
98 const p2 = Array.isArray(palette2) ? palette2 : [];
99 const merged = [...p1];
100
101 p2.forEach((color) => {
102 const alreadyExists = merged.some((c) => c.name === color.name);
103 if (!alreadyExists) merged.push(color);
104 });
105
106 return merged;
107}
108