@@ -20,23 +20,24 @@ smapi.statsPage = function (options) {
2020 modsByType : {
2121 // display names for each mod type (omitted mod types are shown as-is)
2222 labels : {
23- "SMAPI" : "SMAPI (C#)" ,
24- "Pathoschild.ContentPatcher" : "Content Patcher" ,
25- "XNB" : "XNB" ,
26- "PeacefulEnd.AlternativeTextures" : "Alternative Textures" ,
27- "spacechase0.JsonAssets" : "Json Assets" ,
28- "PeacefulEnd.FashionSense" : "Fashion Sense" ,
29- "Digus.ProducerFrameworkMod" : "Producer Framework Mod" ,
30- "DIGUS.MailFrameworkMod" : "Mail Framework Mod" ,
31- "Esca.FarmTypeManager" : "Farm Type Manager" ,
32- "Cherry.ShopTileFramework" : "Shop Tile Framework" ,
33- "Platonymous.TMXLoader" : "TMXL" ,
23+ // keys must be lowercase
24+ "smapi" : "SMAPI (C#)" ,
25+ "pathoschild.contentpatcher" : "Content Patcher" ,
26+ "xnb" : "XNB" ,
27+ "peacefulend.alternativetextures" : "Alternative Textures" ,
28+ "spacechase0.jsonassets" : "Json Assets" ,
29+ "peacefulend.fashionsense" : "Fashion Sense" ,
30+ "digus.producerframeworkmod" : "Producer Framework Mod" ,
31+ "digus.mailframeworkmod" : "Mail Framework Mod" ,
32+ "esca.farmtypemanager" : "Farm Type Manager" ,
33+ "cherry.shoptileframework" : "Shop Tile Framework" ,
34+ "platonymous.tmxloader" : "TMXL" ,
3435 "cat.betterartisangoodicons" : "Better Artisan Good Icons" ,
35- "spacechase0.DynamicGameAssets " : "Dynamic Game Assets" ,
36- "Platonymous.CustomFurniture " : "Custom Furniture" ,
37- "Platonymous.CustomMusic " : "Custom Music" ,
38- "leroymilo.FurnitureFramework " : "Furniture Framework" ,
39- "Paritee.BetterFarmAnimalVariety " : "Better Farm Animal Variety" ,
36+ "spacechase0.dynamicgameassets " : "Dynamic Game Assets" ,
37+ "platonymous.customfurniture " : "Custom Furniture" ,
38+ "platonymous.custommusic " : "Custom Music" ,
39+ "leroymilo.furnitureframework " : "Furniture Framework" ,
40+ "paritee.betterfarmanimalvariety " : "Better Farm Animal Variety" ,
4041 "other" : "other (<100 packs)"
4142 } ,
4243
@@ -85,12 +86,13 @@ smapi.statsPage = function (options) {
8586 costs : {
8687 // colors for each service (omitted entries cycle through the colorPalette)
8788 colors : {
88- "GitHub" : "#ddcc77" , // gold
89- "MongoDB" : "#aa4499" , // magenta
90- "Azure hosting" : "#db4437" , // muted rose
91- "Amazon hosting" : "#332288" , // dark indigo
92- "Amazon SSL" : "#44aa99" , // turquoise
93- "Amazon domains" : "#117733" // dark green
89+ // keys must be lowercase
90+ "github" : "#ddcc77" , // gold
91+ "mongodb" : "#aa4499" , // magenta
92+ "azure hosting" : "#db4437" , // muted rose
93+ "amazon hosting" : "#332288" , // dark indigo
94+ "amazon ssl" : "#44aa99" , // turquoise
95+ "amazon domains" : "#117733" // dark green
9496 } ,
9597
9698 // notable events which may affect costs, indexed by their date in smapi-costs.jsonl
@@ -271,7 +273,7 @@ smapi.statsPage = function (options) {
271273 this . modsByType . loadFailed = true ; // override on success
272274 if ( modsByTypeRows ) {
273275 try {
274- const rows = modsByTypeRows ;
276+ const rows = modsByTypeRows . map ( lowercaseKeys ) ;
275277
276278 // parse data
277279 const lastRow = rows [ rows . length - 1 ] ;
@@ -302,7 +304,7 @@ smapi.statsPage = function (options) {
302304
303305 this . modsByType . total = total ;
304306 this . modsByType . topThree = topThree ;
305- this . modsByType . xnbPercent = getPercent ( curData . lastRow [ "XNB " ] , total ) ;
307+ this . modsByType . xnbPercent = getPercent ( curData . lastRow [ "xnb " ] , total ) ;
306308 }
307309
308310 // derive 'new mods this month' stats
@@ -585,7 +587,7 @@ smapi.statsPage = function (options) {
585587 {
586588 id : "modsByTypeOverTimeExcludingOutliers" ,
587589 title : "Mods by type over time (excluding SMAPI and Content Patcher)" ,
588- modTypes : curData . modTypes . filter ( key => isSpecificModType ( key ) && key !== "SMAPI " && key !== "Pathoschild.ContentPatcher " )
590+ modTypes : curData . modTypes . filter ( key => isSpecificModType ( key ) && key !== "smapi " && key !== "pathoschild.contentpatcher " )
589591 }
590592 ] ;
591593
@@ -1137,7 +1139,7 @@ smapi.statsPage = function (options) {
11371139 * @returns {string }
11381140 */
11391141 function getLabel ( lookup , key ) {
1140- return lookup [ key ] ?? key ;
1142+ return lookup [ key . toLowerCase ( ) ] ?? key ;
11411143 }
11421144
11431145 /**
@@ -1147,7 +1149,7 @@ smapi.statsPage = function (options) {
11471149 * @returns {string }
11481150 */
11491151 function getColor ( lookup , key ) {
1150- return lookup [ key ] ?? "#808080" ;
1152+ return lookup [ key . toLowerCase ( ) ] ?? "#808080" ;
11511153 }
11521154
11531155 /**
@@ -1186,6 +1188,20 @@ smapi.statsPage = function (options) {
11861188 return `rgba(${ r } ,${ g } ,${ b } ,${ alpha } )` ;
11871189 }
11881190
1191+ /**
1192+ * Get a copy of an object with all its keys lowercased.
1193+ * @param {object } row The object to map.
1194+ * @returns {object }
1195+ */
1196+ function lowercaseKeys ( row ) {
1197+ const copy = { } ;
1198+
1199+ for ( const [ key , value ] of Object . entries ( row ) )
1200+ copy [ key . toLowerCase ( ) ] = value ;
1201+
1202+ return copy ;
1203+ }
1204+
11891205 /**
11901206 * Get the unique keys from a column-per-key row, sorted by their value in the latest row.
11911207 * @param {array<object> } rows The parsed rows over time.
@@ -1217,7 +1233,9 @@ smapi.statsPage = function (options) {
12171233 */
12181234 function assignColors ( colorMap , keys ) {
12191235 let index = 0 ;
1220- for ( const key of keys ) {
1236+ for ( const rawKey of keys ) {
1237+ const key = rawKey . toLowerCase ( ) ;
1238+
12211239 if ( ! colorMap [ key ] )
12221240 colorMap [ key ] = config . colorPalette [ index ++ % config . colorPalette . length ] ;
12231241 }
0 commit comments