Skip to content
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

Enable state-level enhanced CPS runs #2226

Merged
14 changes: 14 additions & 0 deletions src/__tests__/data/reformDefinitionCode.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ describe("Test getReproducibilityCodeBlock", () => {
reformPolicyUS,
"us",
2024,
null,
householdUS,
);

Expand Down Expand Up @@ -245,6 +246,19 @@ describe("Test getImplementationCode", () => {
expect(output).toBeInstanceOf(Array);
expect(output).toContain("baseline = Microsimulation(reform=baseline)");
});
test("If dataset provided, return lines with dataset", () => {
const output = getImplementationCode(
"policy",
"us",
2024,
baselinePolicyUS,
"enhanced_cps",
);
expect(output).toBeInstanceOf(Array);
expect(output).toContain(
"baseline = Microsimulation(dataset='enhanced_cps_2024')",
);
});
});

describe("Test sanitizeStringToPython", () => {
Expand Down
29 changes: 2 additions & 27 deletions src/__tests__/pages/policy/PolicyRightSidebar.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,32 +175,6 @@ describe("Enhanced CPS selector", () => {
"ant-switch-disabled",
);
});
test("Should not be enabled when region is a state", async () => {
const testSearchParams = {
focus: "gov",
region: "ar",
};

useSearchParams.mockImplementation(() => {
return [new URLSearchParams(testSearchParams), jest.fn()];
});

// Declare props
const props = {
metadata: {
...metadataUS,
countryId: "us",
},
policy: standardPolicyUS,
defaultOpen: true,
};

const { getByTestId } = render(<PolicyRightSidebar {...props} />);

expect(getByTestId("enhanced_cps_switch").classList).toContain(
"ant-switch-disabled",
);
});
test("Should change region when selected", () => {
const testSearchParams = {
focus: "gov",
Expand All @@ -209,7 +183,8 @@ describe("Enhanced CPS selector", () => {

const expectedSearchParams = {
focus: "gov",
region: "enhanced_us",
region: "us",
dataset: "enhanced_cps",
};

const mockSetSearchParams = jest.fn();
Expand Down
9 changes: 5 additions & 4 deletions src/data/countries.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,12 @@ export const STATUS_TEXT_COLORS = {
Pending: colors.BLACK,
};

// Map region entries to default datasets;
// at the moment, this only applies to the
// "enhanced_us" region selection
// Map dataset keywords to their equivalents
// in the actual US package; at the moment,
// this only applies to the "enhanced_cps"
// dataset selection
export const DEFAULT_DATASETS = {
enhanced_us: "enhanced_cps_2024",
enhanced_cps: "enhanced_cps_2024",
};

const DEFAULT_US_HOUSEHOLD = {
Expand Down
33 changes: 24 additions & 9 deletions src/data/reformDefinitionCode.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export function getReproducibilityCodeBlock(
policy,
region,
year,
dataset = null,
householdInput = null,
earningVariation = null,
) {
Expand All @@ -27,7 +28,7 @@ export function getReproducibilityCodeBlock(
householdInput,
earningVariation,
),
...getImplementationCode(type, region, year, policy),
...getImplementationCode(type, region, year, policy, dataset),
];
}

Expand Down Expand Up @@ -156,37 +157,51 @@ export function getSituationCode(
return lines;
}

export function getImplementationCode(type, region, timePeriod, policy) {
export function getImplementationCode(
type,
region,
timePeriod,
policy,
dataset,
) {
if (type !== "policy") {
return [];
}

const hasBaseline = Object.keys(policy?.baseline?.data).length > 0;
const hasReform = Object.keys(policy?.reform?.data).length > 0;

// Check if the region has a dataset specified
const hasDatasetSpecified = Object.keys(DEFAULT_DATASETS).includes(region);
const dataset = hasDatasetSpecified ? DEFAULT_DATASETS[region] : "";
// Check if the region has a dataset specified; enhanced_us is legacy implemntation
// whereby enhanced_us region correlated with enhanced_cps dataset
const hasDatasetSpecified =
Object.keys(DEFAULT_DATASETS).includes(dataset) || region === "enhanced_us";

let formattedDataset = null;
if (region === "enhanced_us") {
formattedDataset = "enhanced_cps_2024";
} else if (hasDatasetSpecified) {
formattedDataset = DEFAULT_DATASETS[dataset];
}

return [
"",
"",
`baseline = Microsimulation(${
hasDatasetSpecified && hasBaseline
? `reform=baseline, dataset='${dataset}'`
? `reform=baseline, dataset='${formattedDataset}'`
: hasBaseline
? `reform=baseline`
: hasDatasetSpecified
? `dataset='${dataset}'`
? `dataset='${formattedDataset}'`
: ""
})`,
`reformed = Microsimulation(${
hasDatasetSpecified && hasReform
? `reform=reform, dataset='${dataset}'`
? `reform=reform, dataset='${formattedDataset}'`
: hasReform
? `reform=reform`
: hasDatasetSpecified
? `dataset='${dataset}'`
? `dataset='${formattedDataset}'`
: ""
})`,
`baseline_income = baseline.calculate("household_net_income", period=${timePeriod || defaultYear})`,
Expand Down
20 changes: 18 additions & 2 deletions src/pages/UserProfilePage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -443,11 +443,17 @@ function UserProfileSection(props) {
function PolicySimulationCard(props) {
const { metadata, userPolicy, keyValue } = props;

console.log(userPolicy);

const CURRENT_API_VERSION = metadata?.version;
const geography =
metadata.economy_options.region.filter(
(region) => region.name === userPolicy.geography,
)[0]?.label || "Unknown";
const datasetName =
metadata.economy_options.datasets.filter(
(dataset) => dataset.name === userPolicy.dataset,
)[0]?.label || "Unknown";

const apiVersion = userPolicy.api_version;
const dateAdded = userPolicy.added_date;
Expand Down Expand Up @@ -480,7 +486,12 @@ function PolicySimulationCard(props) {
return (
<Link
key={keyValue}
to={`/${userPolicy.country_id}/policy?focus=policyOutput.policyBreakdown&reform=${userPolicy.reform_id}&baseline=${userPolicy.baseline_id}&timePeriod=${userPolicy.year}&region=${userPolicy.geography}`}
to={
`/${userPolicy.country_id}/policy?focus=policyOutput.policyBreakdown` +
`&reform=${userPolicy.reform_id}&baseline=${userPolicy.baseline_id}` +
`&timePeriod=${userPolicy.year}&region=${userPolicy.geography}` +
`${userPolicy.dataset ? `&dataset=${userPolicy.dataset}` : ""}`
}
style={{ height: "100%" }}
>
<Card
Expand Down Expand Up @@ -516,7 +527,12 @@ function PolicySimulationCard(props) {
Simulated in{" "}
<span style={{ fontWeight: 500 }}>{userPolicy.year}</span> over{" "}
<span style={{ fontWeight: 500 }}>{geography}</span> against{" "}
<span style={{ fontWeight: 500 }}>{userPolicy.baseline_label}</span>.
<span style={{ fontWeight: 500 }}>{userPolicy.baseline_label}</span>
{userPolicy.dataset ? (
<span style={{ fontWeight: 500 }}> ({datasetName})</span>
) : (
"."
)}
</p>
<p>
<span style={{ fontWeight: 500 }}>
Expand Down
2 changes: 2 additions & 0 deletions src/pages/household/output/HouseholdReproducibility.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export default function HouseholdReproducibility(props) {
const [earningVariation, setEarningVariation] = useState(false);
const [searchParams] = useSearchParams();
const region = searchParams.get("region");
const dataset = searchParams.get("dataset");
const mobile = useMobile();

let lines = getReproducibilityCodeBlock(
Expand All @@ -20,6 +21,7 @@ export default function HouseholdReproducibility(props) {
policy,
region,
year,
dataset,
householdInput,
earningVariation,
);
Expand Down
93 changes: 48 additions & 45 deletions src/pages/policy/PolicyRightSidebar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,9 @@ function RegionSelector(props) {
return { value: region.name, label: region.label };
});

// This is a temporary solution that will need to be superseded by
// an improved back end design; removing this value allows
// DatasetSelector to handle choosing between enhanced CPS data and
// standard US data
// The below allows backward compatibility with a past design where enhanced_cps
// was also a region value
options = options.filter((option) => option.value !== "enhanced_us");

// These lines are also a temporary solution; if user accesses the component
// with the enhanced_us region via URL, the component should instead display
// the US
let inputRegion = searchParams.get("region");
if (inputRegion === "enhanced_us") {
inputRegion = "us";
Expand Down Expand Up @@ -145,62 +139,65 @@ function FullLiteToggle() {
}

/**
* A (hopefully temporary) component meant to abstract away the fact
* that the US enhanced CPS data is defined as a region within the US
* country package; this displays the enhanced CPS as a dataset on the
* right-hand policy panel
* This displays the enhanced CPS as a dataset on the right-hand policy panel
* @param {Object} props
* @param {String} presentRegion The region, taken from the searchParams
* @param {String} presentDataset The dataset, taken from the searchParams
* @param {Number|String} timePeriod The year the simulation should run over
* @returns {import("react").ReactElement}
*/
function DatasetSelector(props) {
const { presentRegion, timePeriod } = props;
const { presentDataset, timePeriod } = props;
const [isChecked, setIsChecked] = useState(confirmIsChecked(presentDataset));
const [searchParams, setSearchParams] = useSearchParams();
const displayCategory = useDisplayCategory();

// Determine whether slider should be enabled or disabled
function shouldEnableSlider(presentRegion, timePeriod) {
// Define the regions the slider should be enabled
const showRegions = ["enhanced_us", "us", null];
function confirmIsChecked(presentDataset) {
// Define presentDataset value that activates check
const checkValue = "enhanced_cps";
if (presentDataset === checkValue) {
return true;
}
return false;
}

// Define the times the slider should NOT be enabled
const dontShowTimes = ["2021"];
// Determine whether slider should be enabled or disabled
function shouldEnableSlider(timePeriod) {
// Define earliest year slider should be shown for
const sliderStartYear = 2024;

// Return whether or not slider should be enabled
if (
showRegions.includes(presentRegion) &&
!dontShowTimes.includes(String(timePeriod))
) {
// Null timePeriod reflects no URL param setting yet -
// this is actually default behavior
if (!timePeriod || timePeriod >= sliderStartYear) {
return true;
}

return false;
}

/**
* Switch change handler
* @param {Boolean} isChecked Whether or not the switch is "checked";
* note that the event is not passed to the handler by default
* @returns {undefined|null} Returns null as a safety check in cases where
* switch shouldn't be active in the first place
*/
function handleChange(isChecked) {
// Define our desired states; item 0 corresponds to
// "true" and 1 to "false", since bools can't be used as keys
const outputStates = ["enhanced_us", "us"];

function handleChange() {
// First, safety check - if the button isn't even
// supposed to be shown, do nothing
if (!shouldEnableSlider(presentRegion, timePeriod)) {
if (!shouldEnableSlider(timePeriod)) {
return;
}

// Duplicate the existing search params
let newSearch = copySearchParams(searchParams);

// Set params accordingly
newSearch.set("region", isChecked ? outputStates[0] : outputStates[1]);
if (isChecked) {
newSearch.delete("dataset");
// Allows for backwards compatibility with a past design
// where enhanced_cps was also a region value
if (searchParams.get("region") === "enhanced_us") {
newSearch.set("region", "us");
}
setIsChecked(false);
} else {
newSearch.set("dataset", "enhanced_cps");
setIsChecked(true);
}
setSearchParams(newSearch);
}

Expand All @@ -218,17 +215,15 @@ function DatasetSelector(props) {
data-testid="enhanced_cps_switch"
size={displayCategory !== "mobile" && "small"}
onChange={handleChange}
disabled={!shouldEnableSlider(presentRegion, timePeriod)}
checked={presentRegion === "enhanced_us" ? true : false}
disabled={!shouldEnableSlider(timePeriod)}
checked={presentDataset === "enhanced_cps" ? true : false}
/>
<p
style={{
margin: 0,
fontSize: displayCategory !== "mobile" && "0.95em",
color:
!shouldEnableSlider(presentRegion, timePeriod) && "rgba(0,0,0,0.5)",
cursor:
!shouldEnableSlider(presentRegion, timePeriod) && "not-allowed",
color: !shouldEnableSlider(timePeriod) && "rgba(0,0,0,0.5)",
cursor: !shouldEnableSlider(timePeriod) && "not-allowed",
}}
>
Use Enhanced CPS (beta)
Expand Down Expand Up @@ -534,6 +529,14 @@ export default function PolicyRightSidebar(props) {
const focus = searchParams.get("focus") || "";
const stateAbbreviation = focus.split(".")[2];
const hasHousehold = searchParams.get("household") !== null;

let dataset = searchParams.get("dataset");
// This allows backward compatibility with a past
// design where enhanced_cps was also a region value
if (region === "enhanced_us" && !dataset) {
dataset = "enhanced_cps";
}

const options = metadata.economy_options.region.map((stateAbbreviation) => {
return { value: stateAbbreviation.name, label: stateAbbreviation.label };
});
Expand Down Expand Up @@ -830,7 +833,7 @@ export default function PolicyRightSidebar(props) {
</div>
{metadata.countryId === "us" && (
<DatasetSelector
presentRegion={region}
presentDataset={dataset}
timePeriod={timePeriod}
/>
)}
Expand Down
Loading
Loading