satyacode
Background
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