diff --git a/build/process-population.js b/build/process-population.js index 2f9532fe..7ee0c7c6 100644 --- a/build/process-population.js +++ b/build/process-population.js @@ -34,6 +34,7 @@ "data/pop-csv/queso-geyser.csv", "data/pop-csv/queso-river.csv", "data/pop-csv/ronza.csv", + "data/pop-csv/school-of-sorcery.csv", "data/pop-csv/table-of-contents.csv", "data/pop-csv/town-of-digby.csv", "data/pop-csv/town-of-gnawnia.csv", diff --git a/data/_utils.js b/data/_utils.js index 4beeb69c..4c3f4dc6 100644 --- a/data/_utils.js +++ b/data/_utils.js @@ -3,6 +3,18 @@ var json2csv = require("json2csv"); var _ = require("lodash"); var Combinatorics = require("js-combinatorics"); +/** + * @typedef {Object} AttractionData + * @property {string} location + * @property {string} stage + * @property {string} cheese + * @property {string} charm + * @property {string} attraction + * @property {string} mouse + * @property {number} sample + * @property {number} seen + */ + // Location,Phase,Cheese,Charm,Attraction Rate,Mouse,Sample Size exports.POP_FIELDS = [ { label: "Location", value: "location" }, diff --git a/data/pop-csv/school-of-sorcery.csv b/data/pop-csv/school-of-sorcery.csv new file mode 100644 index 00000000..55e3298a --- /dev/null +++ b/data/pop-csv/school-of-sorcery.csv @@ -0,0 +1,47 @@ +"Location","Phase","Cheese","Charm","Attraction Rate","Mouse","Sample Size" +"School of Sorcery","Hallway","SB+/Gouda/Brie","-","100%","Hall Monitor",1 +"School of Sorcery","Arcane Arts","SB+/Gouda/Brie","-","40.88%","Broomstick Bungler",4428 +"School of Sorcery","Arcane Arts","SB+/Gouda/Brie","-","38.26%","Perpetual Detention",4428 +"School of Sorcery","Arcane Arts","SB+/Gouda/Brie","-","20.87%","Misfortune Teller",4428 +"School of Sorcery","Arcane Arts","Apprentice Ambert","-","43.60%","Invisible Fashionista",6802 +"School of Sorcery","Arcane Arts","Apprentice Ambert","-","41.12%","Arcana Overachiever",6802 +"School of Sorcery","Arcane Arts","Apprentice Ambert","-","15.27%","Enchanted Chess Club Champion",6802 +"School of Sorcery","Arcane Arts","Master Mimolette","-","47.44%","Featherlight",1115 +"School of Sorcery","Arcane Arts","Master Mimolette","-","37.76%","Illustrious Illusionist",1115 +"School of Sorcery","Arcane Arts","Master Mimolette","-","14.80%","Constructively Critical Artist",1115 +"School of Sorcery","Shadow Sciences","SB+/Gouda/Brie","-","40.88%","Uncoordinated Cauldron Carrier",4428 +"School of Sorcery","Shadow Sciences","SB+/Gouda/Brie","-","38.26%","Mixing Mishap",4428 +"School of Sorcery","Shadow Sciences","SB+/Gouda/Brie","-","20.87%","Bookworm",4428 +"School of Sorcery","Shadow Sciences","Apprentice Ambert","-","41.12%","Classroom Keener",6802 +"School of Sorcery","Shadow Sciences","Apprentice Ambert","-","43.60%","Audacious Alchemist",6802 +"School of Sorcery","Shadow Sciences","Apprentice Ambert","-","15.27%","Prestigious Prestidigitator",6802 +"School of Sorcery","Shadow Sciences","Master Mimolette","-","47.44%","Teleporting Truant",1115 +"School of Sorcery","Shadow Sciences","Master Mimolette","-","37.76%","Classroom Disrupter",1115 +"School of Sorcery","Shadow Sciences","Master Mimolette","-","14.80%","Magical Multitasker",1115 +"School of Sorcery","Final Exam - Arcane","SB+/Gouda/Brie","-","28.24%","Perpetual Detention",101 +"School of Sorcery","Final Exam - Arcane","SB+/Gouda/Brie","-","34.12%","Broomstick Bungler",101 +"School of Sorcery","Final Exam - Arcane","SB+/Gouda/Brie","-","27.06%","Misfortune Teller",101 +"School of Sorcery","Final Exam - Arcane","SB+/Gouda/Brie","-","10.59%","Sleep Starved Scholar",101 +"School of Sorcery","Final Exam - Arcane","Apprentice Ambert","-","34.50%","Invisible Fashionista",342 +"School of Sorcery","Final Exam - Arcane","Apprentice Ambert","-","31.87%","Arcana Overachiever",342 +"School of Sorcery","Final Exam - Arcane","Apprentice Ambert","-","22.51%","Enchanted Chess Club Champion",342 +"School of Sorcery","Final Exam - Arcane","Apprentice Ambert","-","11.11%","Class Clown",342 +"School of Sorcery","Final Exam - Arcane","Master Mimolette","-","35.12%","Featherlight",951 +"School of Sorcery","Final Exam - Arcane","Master Mimolette","-","30.81%","Illustrious Illusionist",951 +"School of Sorcery","Final Exam - Arcane","Master Mimolette","-","23.66%","Constructively Critical Artist",951 +"School of Sorcery","Final Exam - Arcane","Master Mimolette","-","10.41%","Tyrannical Thaumaturge",951 +"School of Sorcery","Final Exam - Shadow","SB+/Gouda/Brie","-","34.12%","Uncoordinated Cauldron Carrier",101 +"School of Sorcery","Final Exam - Shadow","SB+/Gouda/Brie","-","27.06%","Bookworm",101 +"School of Sorcery","Final Exam - Shadow","SB+/Gouda/Brie","-","28.24%","Mixing Mishap",101 +"School of Sorcery","Final Exam - Shadow","SB+/Gouda/Brie","-","10.59%","Cheat Sheet Conjurer",101 +"School of Sorcery","Final Exam - Shadow","Apprentice Ambert","-","31.87%","Classroom Keener",342 +"School of Sorcery","Final Exam - Shadow","Apprentice Ambert","-","34.50%","Audacious Alchemist",342 +"School of Sorcery","Final Exam - Shadow","Apprentice Ambert","-","22.51%","Prestigious Prestidigitator",342 +"School of Sorcery","Final Exam - Shadow","Apprentice Ambert","-","11.11%","Celestial Summoner",342 +"School of Sorcery","Final Exam - Shadow","Master Mimolette","-","35.12%","Teleporting Truant",951 +"School of Sorcery","Final Exam - Shadow","Master Mimolette","-","30.81%","Classroom Disrupter",951 +"School of Sorcery","Final Exam - Shadow","Master Mimolette","-","23.66%","Magical Multitasker",951 +"School of Sorcery","Final Exam - Shadow","Master Mimolette","-","10.41%","Data Devourer",951 +"School of Sorcery","Arcane Arts - Boss","SB+/Gouda/Brie/Apprentice Ambert/Master Mimolette","-","100%","Arcane Master Sorcerer",1 +"School of Sorcery","Shadow Sciences - Boss","SB+/Gouda/Brie/Apprentice Ambert/Master Mimolette","-","100%","Shadow Master Sorcerer",1 +"School of Sorcery","Final Exam - Boss","SB+/Gouda/Brie/Apprentice Ambert/Master Mimolette","-","100%","Mythical Master Sorcerer",1 diff --git a/data/pop-js/_template.js b/data/pop-js/_template.js index d3e8506b..4336861b 100644 --- a/data/pop-js/_template.js +++ b/data/pop-js/_template.js @@ -134,8 +134,8 @@ module.exports = { ], /** * - * @param {{stage: string, location: string, cheese: string, mouse: string, attraction: string, sample: number}[]} data - * @returns {{stage: string, location: string, cheese: string, mouse: string, attraction: string, sample: number}[]} + * @param {import('../_utils').AttractionData[]} data + * @returns {import('../_utils').AttractionData[]} */ postProcess: function(data) { return data; diff --git a/data/pop-js/school-of-sorcery.js b/data/pop-js/school-of-sorcery.js new file mode 100644 index 00000000..8d325059 --- /dev/null +++ b/data/pop-js/school-of-sorcery.js @@ -0,0 +1,200 @@ +const utils = require("../_utils"); + +const stages = ["Arcane Arts", "Shadow Sciences", "Final Exam - Arcane", "Final Exam - Shadow"]; +const cheeses = ["Standard", "Apprentice Ambert", "Master Mimolette"]; + +const miceByStageThenCheese = { + "Arcane Arts": { + "Standard": [ + "Perpetual Detention", + "Broomstick Bungler", + "Misfortune Teller", + ], + "Apprentice Ambert": [ + "Arcana Overachiever", + "Invisible Fashionista", + "Enchanted Chess Club Champion", + ], + "Master Mimolette": [ + "Illustrious Illusionist", + "Featherlight", + "Constructively Critical Artist", + ] + }, + "Shadow Sciences": { + "Standard": [ + "Mixing Mishap", + "Uncoordinated Cauldron Carrier", + "Bookworm", + ], + "Apprentice Ambert": [ + "Classroom Keener", + "Audacious Alchemist", + "Prestigious Prestidigitator", + ], + "Master Mimolette": [ + "Classroom Disrupter", + "Teleporting Truant", + "Magical Multitasker", + ] + } +} + +// Instead of repeating a lot of line just use previous pools +miceByStageThenCheese["Final Exam - Arcane"] = { + "Standard": [ + ...miceByStageThenCheese["Arcane Arts"]["Standard"], + "Sleep Starved Scholar", + ], + "Apprentice Ambert": [ + ...miceByStageThenCheese["Arcane Arts"]["Apprentice Ambert"], + "Class Clown", + ], + "Master Mimolette": [ + ...miceByStageThenCheese["Arcane Arts"]["Master Mimolette"], + "Tyrannical Thaumaturge", + ] +}; + +miceByStageThenCheese["Final Exam - Shadow"] = { + "Standard": [ + ...miceByStageThenCheese["Shadow Sciences"]["Standard"], + "Cheat Sheet Conjurer", + ], + "Apprentice Ambert": [ + ...miceByStageThenCheese["Shadow Sciences"]["Apprentice Ambert"], + "Celestial Summoner", + ], + "Master Mimolette": [ + ...miceByStageThenCheese["Shadow Sciences"]["Master Mimolette"], + "Data Devourer", + ] +} + +const standardCheeseVarItem = { + vars: { + cheese: { + Brie: true, + "Empowered Brie": true, + Gouda: true, + "SB+": true, + "ESB+": true, + } + }, + fields: { + cheese: "SB+/Gouda/Brie" + } +} + +function genSeries() { + const series = []; + for (const stage of stages) { + for (const cheese of cheeses) { + const config = { + stage: utils.genVarField("stage", stage), + cheese: utils.genVarField("cheese", cheese), + config: [ + { + opts: { + include: miceByStageThenCheese[stage][cheese] + } + } + ] + }; + + // Replace the standard placeholder with actual multi cheese config (see above) + if (cheese === "Standard") { + config.cheese[0] = standardCheeseVarItem; + } + + series.push(config); + } + } + + return series; +} + +module.exports = { + default: { + location: utils.genVarField("location", "School of Sorcery"), + }, + series: genSeries(), + /** + * + * @param {import('../_utils').AttractionData[]} data + * @returns {import('../_utils').AttractionData[]} + */ + postProcess: function(data) { + + // See comments in Zugwangz's Tower about how to combine pools of mice that exist on opposite sides but have same AR + + // To find the matching pair: https://docs.google.com/spreadsheets/d/1LhtH3yf0ImnUv4Z5rGqDskmGxfXvSglDfXqFfeXmFq8/edit?usp=sharing + // Find Arcane Mouse and match its Mouse Power with the Shadow Side. Or look at the MinLuck table. It's the same thing. + const arcaneToShadowMiceMap = { + // Standard + "Perpetual Detention": "Mixing Mishap", + "Broomstick Bungler": "Uncoordinated Cauldron Carrier", + "Misfortune Teller": "Bookworm", + + // AA + "Arcana Overachiever": "Classroom Keener", + "Invisible Fashionista": "Audacious Alchemist", + "Enchanted Chess Club Champion": "Prestigious Prestidigitator", + + // MM + "Illustrious Illusionist": "Classroom Disrupter", + "Featherlight": "Teleporting Truant", + "Constructively Critical Artist": "Magical Multitasker", + + // FE Standard + "Sleep Starved Scholar": "Cheat Sheet Conjurer", + + // FE AA + "Class Clown": "Celestial Summoner", + + // FE MM + "Tyrannical Thaumaturge": "Data Devourer" + } + + data.forEach((run, i) => { + if (run.stage.indexOf('Arcane') > -1) { + const oppStage = run.stage === 'Arcane Arts' ? 'Shadow Sciences' : 'Final Exam - Shadow'; + const oppMouse = arcaneToShadowMiceMap[run.mouse]; + + data + .forEach((other, j) => { + if (other.cheese == run.cheese + && other.stage == oppStage + && other.mouse == oppMouse) { + // Add seen to each other. Recalc AR. + + data[i].seen += data[j].seen; + data[i].sample += data[j].sample; + + data[j].seen = data[i].seen; + data[j].sample = data[i].sample; + + data[i].attraction = (data[i].seen / data[i].sample * 100).toFixed(2) + "%"; + data[j].attraction = (data[j].seen / data[j].sample * 100).toFixed(2) + "%"; + } + }); + } + }); + + // Put this first + data.unshift( + // Hallway, why are you here! + {location: "School of Sorcery", cheese: "SB+/Gouda/Brie", stage: "Hallway", mouse: "Hall Monitor", attraction: "100%", sample: 1}, + ); + + // These last + data.push( + // Manually add boss stages + {location: "School of Sorcery", cheese: "SB+/Gouda/Brie/Apprentice Ambert/Master Mimolette", stage: "Arcane Arts - Boss", mouse: "Arcane Master Sorcerer", attraction: "100%", sample: 1}, + {location: "School of Sorcery", cheese: "SB+/Gouda/Brie/Apprentice Ambert/Master Mimolette", stage: "Shadow Sciences - Boss", mouse: "Shadow Master Sorcerer", attraction: "100%", sample: 1}, + {location: "School of Sorcery", cheese: "SB+/Gouda/Brie/Apprentice Ambert/Master Mimolette", stage: "Final Exam - Boss", mouse: "Mythical Master Sorcerer", attraction: "100%", sample: 1}, + ); + + return data; + } +} diff --git a/data/populations.csv b/data/populations.csv index dfeea4f3..b207a429 100644 --- a/data/populations.csv +++ b/data/populations.csv @@ -2852,31 +2852,3 @@ Twisted Garden,Poured,Lunaria Camembert,-,29.63%,Twisted Carmine, Twisted Garden,Poured,Lunaria Camembert,Shattering,38.86%,Camofusion, Twisted Garden,Poured,Lunaria Camembert,Shattering,36.57%,Fungal Spore, Twisted Garden,Poured,Lunaria Camembert,Shattering,24.57%,Shattered Carmine, -School of Sorcery,Hallway,SB+/Gouda/Brie,-,100.00%,Hall Monitor, -School of Sorcery,Arcane Arts,SB+/Gouda/Brie,-,33.33%,Perpetual Detention, -School of Sorcery,Arcane Arts,SB+/Gouda/Brie,-,33.33%,Broomstick Bungler, -School of Sorcery,Arcane Arts,SB+/Gouda/Brie,-,33.33%,Misfortune Teller, -School of Sorcery,Arcane Arts,Apprentice Ambert,-,40.00%,Arcana Overachiever, -School of Sorcery,Arcane Arts,Apprentice Ambert,-,45.00%,Invisible Fashionista, -School of Sorcery,Arcane Arts,Apprentice Ambert,-,15.00%,Enchanted Chess Club Champion, -School of Sorcery,Arcane Arts,Master Mimolette,-,40.00%,Illustrious Illusionist, -School of Sorcery,Arcane Arts,Master Mimolette,-,45.00%,Featherlight, -School of Sorcery,Arcane Arts,Master Mimolette,-,15.00%,Constructively Critical Artist, -School of Sorcery,Arcane Arts - Boss,SB+/Gouda/Brie/Apprentice Ambert/Master Mimolette,-,100.00%,Arcane Master Sorcerer, -School of Sorcery,Shadow Sciences,SB+/Gouda/Brie,-,33.33%,Mixing Mishap, -School of Sorcery,Shadow Sciences,SB+/Gouda/Brie,-,33.33%,Uncoordinated Cauldron Carrier, -School of Sorcery,Shadow Sciences,SB+/Gouda/Brie,-,33.33%,Bookworm, -School of Sorcery,Shadow Sciences,Apprentice Ambert,-,40.00%,Classroom Keener, -School of Sorcery,Shadow Sciences,Apprentice Ambert,-,45.00%,Audacious Alchemist, -School of Sorcery,Shadow Sciences,Apprentice Ambert,-,15.00%,Prestigious Prestidigitator, -School of Sorcery,Shadow Sciences,Master Mimolette,-,40.00%,Classroom Disrupter, -School of Sorcery,Shadow Sciences,Master Mimolette,-,45.00%,Teleporting Truant, -School of Sorcery,Shadow Sciences,Master Mimolette,-,15.00%,Magical Multitasker, -School of Sorcery,Shadow Sciences - Boss,SB+/Gouda/Brie/Apprentice Ambert/Master Mimolette,-,100.00%,Shadow Master Sorcerer, -School of Sorcery,Final Exam - Arcane,SB+/Gouda/Brie,-,100.00%,Sleep Starved Scholar, -School of Sorcery,Final Exam - Arcane,Apprentice Ambert,-,100.00%,Class Clown, -School of Sorcery,Final Exam - Arcane,Master Mimolette,-,100.00%,Tyrannical Thaumaturge, -School of Sorcery,Final Exam - Shadow,SB+/Gouda/Brie,-,100.00%,Cheat Sheet Conjurer, -School of Sorcery,Final Exam - Shadow,Apprentice Ambert,-,100.00%,Celestial Summoner, -School of Sorcery,Final Exam - Shadow,Master Mimolette,-,100.00%,Data Devourer, -School of Sorcery,Final Exam - Boss,SB+/Gouda/Brie/Apprentice Ambert/Master Mimolette,-,100.00%,Mythical Master Sorcerer, diff --git a/package.json b/package.json index b06ee85b..45e7c7a9 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "pop:prickly": "node data/pop prickly-plains > data/pop-csv/prickly-plains.csv", "pop:queso": "node data/pop queso-river > data/pop-csv/queso-river.csv", "pop:ronza": "node data/pop ronza > data/pop-csv/ronza.csv", + "pop:soso": "node data/pop school-of-sorcery > data/pop-csv/school-of-sorcery.csv", "pop:toc": "node data/pop table-of-contents > data/pop-csv/table-of-contents.csv", "pop:toxic": "node data/pop toxic-spill > data/pop-csv/toxic-spill.csv", "pop:vrift": "node data/pop valour-rift > data/pop-csv/valour-rift.csv",