@@ -121,15 +121,52 @@ export const colorMatrix = [
121121 limeColorShade ,
122122] ;
123123
124+ function getShadeByRate (
125+ baseH : number ,
126+ baseS : number ,
127+ rates : number [ ] ,
128+ rate : number
129+ ) : string {
130+ const sortedRates = [ ...rates ] . sort ( ( a , b ) => a - b ) ;
131+ const minRate = sortedRates [ 0 ] ,
132+ maxRate = sortedRates [ sortedRates . length - 1 ] ;
133+ // Example: min maps to 90 (lightest), max maps to 20 (darkest).
134+ const minL = 90 ;
135+ const maxL = 20 ;
136+ let l = minL ;
137+ if ( maxRate !== minRate ) {
138+ l = minL - ( ( rate - minRate ) / ( maxRate - minRate ) ) * ( minL - maxL ) ;
139+ }
140+ return hslColor ( baseH , baseS , Math . round ( l ) ) ;
141+ }
142+
124143export const getColorForSeeds = (
125144 rates : number [ ] ,
126145 rate : number ,
127146 varietyIndex : number ,
128147 trialPlots ?: any [ ] ,
129148 variety ?: string
130149) => {
131- // First, new logic: try to find and return color if exact match in trialPlots
132150 if ( trialPlots && variety ) {
151+ // Gather all dosages for this variety and build a map: color (hex) → array of {rate, color}
152+ const colorRatesMap : { [ color : string ] : number [ ] } = { } ;
153+ for ( const trialPlot of trialPlots ) {
154+ const dosages = trialPlot ?. properties ?. seeds ?. rates_and_dosages ?? [ ] ;
155+ for ( const dosage of dosages ) {
156+ if (
157+ dosage . variety === variety &&
158+ dosage . color &&
159+ typeof dosage . color === "string" &&
160+ dosage . color . trim ( ) . length > 0
161+ ) {
162+ const color = dosage . color . trim ( ) . toLowerCase ( ) ;
163+ if ( ! colorRatesMap [ color ] ) colorRatesMap [ color ] = [ ] ;
164+ colorRatesMap [ color ] . push ( Number ( dosage . rate ) ) ;
165+ }
166+ }
167+ }
168+
169+ // Now, find the color (if any) for THIS rate, and check if the color applies to multiple rates
133170 for ( const trialPlot of trialPlots ) {
134171 const dosages = trialPlot ?. properties ?. seeds ?. rates_and_dosages ?? [ ] ;
135172 for ( const dosage of dosages ) {
@@ -140,7 +177,15 @@ export const getColorForSeeds = (
140177 typeof dosage . color === "string" &&
141178 dosage . color . trim ( ) . length > 0
142179 ) {
143- return dosage . color ;
180+ const color = dosage . color . trim ( ) . toLowerCase ( ) ;
181+ const ratesForColor = colorRatesMap [ color ] ;
182+ if ( ratesForColor && ratesForColor . length > 1 ) {
183+ // CASE 1: Multiple rates share this color for this variety! Apply HSL lightness transformation.
184+ const { h, s } = hexToHSL ( color ) ;
185+ return getShadeByRate ( h , s , ratesForColor , rate ) ;
186+ }
187+ // CASE 2: Only one rate for this color, just use normal color
188+ return color ;
144189 }
145190 }
146191 }
@@ -174,6 +219,59 @@ export const getColorForSeeds = (
174219 return colorShade [ 50 ] ;
175220} ;
176221
222+ // export const getColorForSeeds = (
223+ // rates: number[],
224+ // rate: number,
225+ // varietyIndex: number,
226+ // trialPlots?: any[],
227+ // variety?: string
228+ // ) => {
229+ // // First, new logic: try to find and return color if exact match in trialPlots
230+ // if (trialPlots && variety) {
231+ // for (const trialPlot of trialPlots) {
232+ // const dosages = trialPlot?.properties?.seeds?.rates_and_dosages ?? [];
233+ // for (const dosage of dosages) {
234+ // if (
235+ // dosage.variety === variety &&
236+ // Number(dosage.rate) === Number(rate) &&
237+ // dosage.color &&
238+ // typeof dosage.color === "string" &&
239+ // dosage.color.trim().length > 0
240+ // ) {
241+ // return dosage.color;
242+ // }
243+ // }
244+ // }
245+ // }
246+
247+ // // Old/Default logic:
248+ // const colorShade = colorMatrix[varietyIndex % colorMatrix.length] ?? [];
249+ // const average = rates.reduce((sum, r) => sum + r, 0) / rates.length;
250+
251+ // if (rate === average) return colorShade[50];
252+
253+ // if (rate < average) {
254+ // const lowerThanAvg = rates.filter((r) => r < average).sort((a, b) => b - a);
255+ // const position = lowerThanAvg.indexOf(rate);
256+ // if (position === 0) return colorShade[40];
257+ // if (position === 1) return colorShade[30];
258+ // return colorShade[20];
259+ // }
260+
261+ // if (rate > average) {
262+ // const higherThanAvg = rates
263+ // .filter((r) => r > average)
264+ // .sort((a, b) => a - b);
265+ // const position = higherThanAvg.indexOf(rate);
266+ // if (position === 0) return colorShade[60];
267+ // if (position === 1) return colorShade[70];
268+ // if (position === 2) return colorShade[80];
269+ // return colorShade[90];
270+ // }
271+
272+ // return colorShade[50];
273+ // };
274+
177275export const getColorForBiologicals = (
178276 treated : boolean ,
179277 index : number ,
0 commit comments