-
Notifications
You must be signed in to change notification settings - Fork 11
feat(government): add upkeep price calculator tool #339
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
feat(government): add upkeep price calculator tool #339
Conversation
…nd add building summary
👷 Deploy request for prunplanner-preview pending review.Visit the deploys page to approve it
|
|
@jplacht Take your time reviewing this one - it's a complex feature. Feel free to suggest any changes, even if it means reworking the entire interface. I'm open to any feedback. |
| export const UPKEEP_NEED_TYPES: UpkeepNeedType[] = [ | ||
| "safety", | ||
| "health", | ||
| "comfort", | ||
| "culture", | ||
| "education", | ||
| ]; | ||
|
|
||
| export const UPKEEP_BUILDINGS: IUpkeepBuilding[] = [ | ||
| { | ||
| ticker: "SST", | ||
| name: "Safety Station", | ||
| materials: [ | ||
| { ticker: "DW", qtyPerDay: 10 }, | ||
| { ticker: "OFF", qtyPerDay: 10 }, | ||
| { ticker: "SUN", qtyPerDay: 2 }, | ||
| ], | ||
| needs: { safety: 833.3, health: 0, comfort: 0, culture: 0, education: 0 }, | ||
| }, | ||
| { | ||
| ticker: "SDP", | ||
| name: "Space Defense Platform", | ||
| materials: [ | ||
| { ticker: "POW", qtyPerDay: 1 }, | ||
| { ticker: "RAD", qtyPerDay: 0.47 }, | ||
| { ticker: "CCD", qtyPerDay: 0.07 }, | ||
| { ticker: "SUD", qtyPerDay: 0.07 }, | ||
| ], | ||
| needs: { safety: 1250, health: 0, comfort: 0, culture: 0, education: 0 }, | ||
| }, | ||
| { | ||
| ticker: "EMC", | ||
| name: "Emergency Center", | ||
| materials: [ | ||
| { ticker: "PK", qtyPerDay: 2 }, | ||
| { ticker: "POW", qtyPerDay: 0.4 }, | ||
| { ticker: "BND", qtyPerDay: 4 }, | ||
| { ticker: "RED", qtyPerDay: 0.07 }, | ||
| { ticker: "BSC", qtyPerDay: 0.07 }, | ||
| ], | ||
| needs: { safety: 200, health: 200, comfort: 0, culture: 0, education: 0 }, | ||
| }, | ||
| { | ||
| ticker: "INF", | ||
| name: "Infirmary", | ||
| materials: [ | ||
| { ticker: "OFF", qtyPerDay: 10 }, | ||
| { ticker: "TUB", qtyPerDay: 6.67 }, | ||
| { ticker: "STR", qtyPerDay: 0.67 }, | ||
| ], | ||
| needs: { safety: 0, health: 833.33, comfort: 0, culture: 0, education: 0 }, | ||
| }, | ||
| { | ||
| ticker: "HOS", | ||
| name: "Hospital", | ||
| materials: [ | ||
| { ticker: "PK", qtyPerDay: 2 }, | ||
| { ticker: "SEQ", qtyPerDay: 0.4 }, | ||
| { ticker: "BND", qtyPerDay: 4 }, | ||
| { ticker: "SDR", qtyPerDay: 0.07 }, | ||
| { ticker: "RED", qtyPerDay: 0.07 }, | ||
| { ticker: "BSC", qtyPerDay: 0.13 }, | ||
| ], | ||
| needs: { safety: 0, health: 833.33, comfort: 0, culture: 0, education: 0 }, | ||
| }, | ||
| { | ||
| ticker: "WCE", | ||
| name: "Wellness Center", | ||
| materials: [ | ||
| { ticker: "KOM", qtyPerDay: 4 }, | ||
| { ticker: "OLF", qtyPerDay: 2 }, | ||
| { ticker: "DW", qtyPerDay: 6 }, | ||
| { ticker: "DEC", qtyPerDay: 0.67 }, | ||
| { ticker: "PFE", qtyPerDay: 2.67 }, | ||
| { ticker: "SOI", qtyPerDay: 6.67 }, | ||
| ], | ||
| needs: { safety: 0, health: 166.67, comfort: 166.7, culture: 0, education: 0 }, | ||
| }, | ||
| { | ||
| ticker: "PAR", | ||
| name: "Park", | ||
| materials: [ | ||
| { ticker: "DW", qtyPerDay: 10 }, | ||
| { ticker: "FOD", qtyPerDay: 6 }, | ||
| { ticker: "PFE", qtyPerDay: 2 }, | ||
| { ticker: "SOI", qtyPerDay: 3.33 }, | ||
| { ticker: "DEC", qtyPerDay: 0.33 }, | ||
| ], | ||
| needs: { safety: 0, health: 0, comfort: 500, culture: 0, education: 0 }, | ||
| }, | ||
| { | ||
| ticker: "4DA", | ||
| name: "4D Arena", | ||
| materials: [ | ||
| { ticker: "POW", qtyPerDay: 2 }, | ||
| { ticker: "MHP", qtyPerDay: 2 }, | ||
| { ticker: "OLF", qtyPerDay: 4 }, | ||
| { ticker: "BID", qtyPerDay: 0.2 }, | ||
| { ticker: "HOG", qtyPerDay: 0.2 }, | ||
| { ticker: "EDC", qtyPerDay: 0.2 }, | ||
| ], | ||
| needs: { safety: 0, health: 0, comfort: 833.3, culture: 0, education: 0 }, | ||
| }, | ||
| { | ||
| ticker: "ACA", | ||
| name: "Academy", | ||
| materials: [ | ||
| { ticker: "COF", qtyPerDay: 8 }, | ||
| { ticker: "OLF", qtyPerDay: 2 }, | ||
| { ticker: "VIT", qtyPerDay: 8 }, | ||
| { ticker: "DW", qtyPerDay: 10 }, | ||
| { ticker: "GL", qtyPerDay: 6.67 }, | ||
| { ticker: "DEC", qtyPerDay: 0.67 }, | ||
| ], | ||
| needs: { safety: 0, health: 0, comfort: 166.7, culture: 166.7, education: 0 }, | ||
| }, | ||
| { | ||
| ticker: "ART", | ||
| name: "Art Gallery", | ||
| materials: [ | ||
| { ticker: "MHP", qtyPerDay: 1 }, | ||
| { ticker: "HOG", qtyPerDay: 1 }, | ||
| { ticker: "UTS", qtyPerDay: 0.67 }, | ||
| { ticker: "DEC", qtyPerDay: 0.67 }, | ||
| ], | ||
| needs: { safety: 0, health: 0, comfort: 0, culture: 625, education: 0 }, | ||
| }, | ||
| { | ||
| ticker: "VRT", | ||
| name: "Virtual Reality Theater", | ||
| materials: [ | ||
| { ticker: "POW", qtyPerDay: 1.4 }, | ||
| { ticker: "MHP", qtyPerDay: 2 }, | ||
| { ticker: "HOG", qtyPerDay: 1.4 }, | ||
| { ticker: "OLF", qtyPerDay: 4 }, | ||
| { ticker: "BID", qtyPerDay: 0.33 }, | ||
| { ticker: "DEC", qtyPerDay: 0.67 }, | ||
| ], | ||
| needs: { safety: 0, health: 0, comfort: 0, culture: 833.3, education: 0 }, | ||
| }, | ||
| { | ||
| ticker: "PBH", | ||
| name: "Public Broadcast Hub", | ||
| materials: [ | ||
| { ticker: "OFF", qtyPerDay: 10 }, | ||
| { ticker: "MHP", qtyPerDay: 1 }, | ||
| { ticker: "SP", qtyPerDay: 1.33 }, | ||
| { ticker: "AAR", qtyPerDay: 0.67 }, | ||
| { ticker: "EDC", qtyPerDay: 0.27 }, | ||
| { ticker: "IDC", qtyPerDay: 0.13 }, | ||
| ], | ||
| needs: { safety: 0, health: 0, comfort: 0, culture: 166.7, education: 166.7 }, | ||
| }, | ||
| { | ||
| ticker: "LIB", | ||
| name: "Library", | ||
| materials: [ | ||
| { ticker: "MHP", qtyPerDay: 1 }, | ||
| { ticker: "HOG", qtyPerDay: 1 }, | ||
| { ticker: "CD", qtyPerDay: 0.33 }, | ||
| { ticker: "DIS", qtyPerDay: 0.33 }, | ||
| { ticker: "BID", qtyPerDay: 0.2 }, | ||
| ], | ||
| needs: { safety: 0, health: 0, comfort: 0, culture: 0, education: 500 }, | ||
| }, | ||
| { | ||
| ticker: "UNI", | ||
| name: "University", | ||
| materials: [ | ||
| { ticker: "COF", qtyPerDay: 10 }, | ||
| { ticker: "REA", qtyPerDay: 10 }, | ||
| { ticker: "TUB", qtyPerDay: 10 }, | ||
| { ticker: "BID", qtyPerDay: 0.33 }, | ||
| { ticker: "HD", qtyPerDay: 0.67 }, | ||
| { ticker: "IDC", qtyPerDay: 0.2 }, | ||
| ], | ||
| needs: { safety: 0, health: 0, comfort: 0, culture: 0, education: 833.3 }, | ||
| }, | ||
| ]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@adrian-cancio Could we move this into a separate file, with "constants" or something in its name. Think this would be easier to maintain.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done! Moved constants to upkeepCalculations.constants.ts
| * @param getPriceFunc Function to get material prices | ||
| * @returns Array of material calculations sorted by price per need | ||
| */ | ||
| export async function calculateMaterialsForNeed( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please also add some tests for your new functions? There should be loads you can pick from in the /tests folder, also if you need to setup some prices / materials or other things as test data (see how I test pricing for example).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done! Added tests in src/tests/features/government/upkeepCalculations.test.ts
|
The name of some of the I would actually consider removing the "relative price" column. I know I included it on my governor sheet in the past, but it also shows you the "anchor material", which those prices are relative to. I think it's a little confusing though, and I have removed it from my other, newer tools. ( https://oogcapitalmanagement.com/governing-mats/ ) The intent with relative price was to help you shop prices, which was useful before we had automated price imports and good pricing models. I also do something similar; for mixed use buildings, I double the value of the contribution since it's providing two needs. I think there's room for a better split of the value, but this is a good choice since the tool operates on one need at a time. Maybe you want to make note of the way mixed-use buildings are added up in the UI for the end-user. |
|
So thinking about the "Building Summary" section. I guess the calculated values there are based on filling all of the materials for a given building. I don't think that's useful because, No one really does that, and we shouldn't encourage it. Choosing individual materials on their $/Need from different buildings is going to result in lower prices. There's no bonus for filling a building entirely, and often they'll contain a mix of really effective and very ineffective upkeep choices. So showing the total cost of a building is meaningless and potentially misleading. There might be value in showing the Need/day produced by a building (or by each material in a building, since the number of items in a building varies quite a bit). But that's really only valuable when you've imported the That leads me towards recommending removing the Building Summary section, at least in this tool's current form. |
|
@andykorth Okay, I'll get on it. |
…ding summary section
|
Hey @andykorth, thanks for the feedback! I've made all the changes you suggested:
I agree that showing total building costs could be misleading since mixing materials from different buildings is usually the better approach. I can't upload screenshots right now, but if you need them to verify the changes I can add them later. Let me know if anything else needs adjusting! |
Summary
Screenshots
4. Building Summary Table
Closes #187