Created
February 13, 2024 19:49
-
-
Save kaligrafy/fd482247bdd77897220e72d323eb5475 to your computer and use it in GitHub Desktop.
od_mtl_2023 Person class
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import moment from 'moment-business-days'; | |
import _cloneDeep from 'lodash/cloneDeep'; | |
import { | |
BasePerson, | |
BasePersonAttributes, | |
ExtendedPersonAttributes | |
} from 'evolution-common/lib/services/baseObjects/BasePerson'; | |
import { parseDate } from 'evolution-common/lib/utils/DateUtils'; | |
import { BasePlaceAttributes } from 'evolution-common/lib/services/baseObjects/BasePlace'; | |
import { BaseTripAttributes } from 'evolution-common/lib/services/baseObjects/BaseTrip'; | |
import { BaseVisitedPlaceAttributes } from 'evolution-common/lib/services/baseObjects/BaseVisitedPlace'; | |
import * as PAttr from './attributeTypes/PersonAttributes'; | |
import * as GAttr from './attributeTypes/GeneralAttributes'; | |
import { BasePlace, ExtendedPlaceAttributes } from 'evolution-common/lib/services/baseObjects/BasePlace'; | |
import { BaseAddressAttributes } from 'evolution-common/lib/services/baseObjects/BaseAddress'; | |
import { VisitedPlace, VisitedPlaceAttributes } from './VisitedPlace'; | |
import { Trip, TripAttributes } from './Trip'; | |
import { convertNullToUndefined, convertStringsToNumbers } from './utils/Utils'; | |
import ParamsValidatorTools from './utils/ParamsValidatorTools'; | |
import parser from '../parsers/person.parser'; | |
import config from 'chaire-lib-common/lib/config/shared/project.config'; | |
const displayName = 'Person'; | |
type PersonAttributes = { | |
_completedSections?: PAttr.CompletedSection; | |
_sequence?: number; | |
_color?: string; // hex color for map | |
_isProxy?: boolean; // for export, use isProxy method to calculate | |
ageIsApproximate?: boolean; // od_mtl_2023 | Priority audit: 1 √ | |
departurePlaceIsHome?: GAttr.YesNoDontKnow; // all | Priority audit: 1 √ | |
departurePlaceIsHomeConfirm?: GAttr.YesNoDontKnow; // od_mtl_pilote_2021, od_mtl_pilote_2022 | Priority audit: 1 √ | |
departurePlaceOther?: PAttr.DeparturePlaceOther; // od_mtl_2023, od_mtl_ete_2023, od_qc_2023 | Priority audit: 1 √ | |
departurePlaceType?: PAttr.DeparturePlaceType; // od_mtl_pilote_2021 | Priority audit: 1 √ | |
didTripsOnTripsDate?: GAttr.YesNoDontKnow; // od_mtl_pilote_2021 | Priority audit: 1 √ // moved to personDidTrips in constructor | |
drivingLicenseOwner?: GAttr.YesNoDontKnow; // all | Priority audit: 1 √ | |
transitPassOwner?: GAttr.YesNoDontKnow; // od_mtl_pilote_2021, od_mtl_pilote_2022 | Priority audit: 1 √ | |
// Before 2023-10-18: bixiBikesharingUsage: (choices: 'seasonal', 'monthly', 'noSubscription', 'subscriptionWithPay'): | |
bixiBikesharingUsage?: PAttr.BixiBikesharingUsage; // all except od_qc_2023, od_mtl_2023: only part of the sample | Priority audit: 2 √ | |
// After 2023-10-18: bixiBikesharingUsage_NewOptions2023-10-18 (choices: 'monthlySeasonalAnnual', 'payPerTrip'): | |
['bixiBikesharingUsage_NewOptions2023-10-18']?: PAttr.BixiBikesharingUsageV2; // od_mtl_2023: only part of the sample | Priority audit: 2 √ | |
bixiBikesharingUsageV2?: PAttr.BixiBikesharingUsageV2; // added by parser, not in original questionnaire | Priority audit: 2 √ | |
bikeOwnership?: GAttr.YesNoDontKnow; // od_mtl_pilote_2021, od_mtl_pilote_2022 | Priority audit: 2 √ | |
canRemoteWork?: PAttr.CanRemoteWork; // od_mtl_2023, od_mtl_ete_2023 | Priority audit: 2 √ | |
communautoFlexCarsharingUsage?: PAttr.CommunautoFlexCarSharingUsage; // od_mtl_pilote_2021, od_mtl_pilote_2022 | Priority audit: 2 √ | |
daysAtOfficePerWeek?: PAttr.DaysAtOfficePerWeek; // source: number, but convert into string using choice labels; // od_mtl_2023, od_mtl_ete_2023 | Priority audit: 2 | |
disabilities?: PAttr.Disability[]; // all except od_qc_2023 | Priority audit: 3 > | |
disabilitiesComments?: string; // all except od_qc_2023 | Priority audit: 0 √ | |
//doesNotStudiesFromFixedLocationReason?: PAttr.DoesNotStudyFromFixedLocationReason; // od_mtl_ete_2023, change into doesNotStudyFromFixedLocationReason in create | |
doesNotStudyFromFixedLocationReason?: PAttr.DoesNotStudyFromFixedLocationReason; // od_mtl_2023 | Priority audit: 3 √ | |
educationalAttainment?: PAttr.EducationalAttainment; // override default values of basePerson | Priority audit: 2 | |
electricBikeOwnership?: GAttr.YesNoDontKnow; // od_mtl_pilote_2021, od_mtl_pilote_2022 | Priority audit: 2 √ | |
enrolledInSchool?: PAttr.EnrolledInSchool; // all | Priority audit: 1 √ | |
everUsedBixiBikesharingServices?: GAttr.YesNoDontKnowNonApplicable; // od_mtl_pilote_2021, od_mtl_pilote_2022 | Priority audit: 2 √ | |
everUsedCommunautoFlexCarsharingServicesAsADriver?: GAttr.YesNoDontKnow; // od_mtl_pilote_2021, od_mtl_pilote_2022 | Priority audit: 2 √ | |
freeParkingAtSchool?: PAttr.FreeParking; // od_mtl_2023, od_mtl_ete_2023 | Priority audit: 2 √ | |
freeParkingAtWork?: PAttr.FreeParking; // od_mtl_2023, od_mtl_ete_2023 | Priority audit: 2 √ | |
genderCustom?: string; // od_mtl_pilote_2021 | Priority audit: 3 √ | |
genderSpecify?: string; // all except od_qc_2023 | Priority audit: 3 √ | |
hasDisability?: GAttr.YesNoPreferNotToAnswer; // all | Priority audit: 1 √ | |
hasOmittedActiveModesTrips?: boolean; // od_mtl_2023, od_mtl_ete_2023 | Priority audit: 1 √ | |
hasUsualSchoolPlace?: boolean; // od_mtl_pilote_2021, od_mtl_pilote_2022 | Priority audit: 1 √ | |
hasUsualWorkPlace?: boolean; // od_mtl_pilote_2021, od_mtl_pilote_2022 | Priority audit: 1 √ | |
job?: string; // all except od_qc_2023 | Priority audit: 3 √ | |
jobActivitySector?: PAttr.JobActivitySector; // od_mtl_pilote_2021, od_mtl_pilote_2022 | Priority audit: 3 √ | |
jobCategory?: PAttr.JobCategory; // override default values of basePerson | Priority audit: 3 √ | |
jobCompatibleWithTelecommuting?: PAttr.JobCompatibleWithTelecommuting; // od_mtl_pilote_2021, od_mtl_pilote_2022 | Priority audit: 2 √ | |
jobHoursFlexibility?: PAttr.JobHoursFlexibility; // od_mtl_pilote_2021, od_mtl_pilote_2022 | Priority audit: 2 √ | |
jobHoursSchedulesType?: PAttr.JobHoursSchedulesType; // od_mtl_pilote_2021, od_mtl_pilote_2022 | Priority audit: 2 √ | |
jobType?: PAttr.JobType; // all except od_qc_2023 | Priority audit: 1 √ | |
mobilityAssistiveDevices?: PAttr.MobilityAssistiveDevice[]; // all except od_qc_2023 | Priority audit: 3 √ | |
mobilityAssistiveDevicesSpecify?: string; // all except od_qc_2023 | Priority audit: 3 √ | |
mostUsedMobilityAssistiveDevice?: PAttr.MobilityAssistiveDevice; // all except od_qc_2023 | Priority audit: 3 √ | |
// ignore nickname altogether | |
noSchoolTripReasonV1?: PAttr.NoSchoolTripReasonV1; // od_mtl_pilote_2021 (v1), od_mtl_pilote_2022 (v1) | Priority audit: 2 √ | |
noSchoolTripReasonV2?: PAttr.NoSchoolTripReasonV2; // od_mtl_2023 (v2), od_qc_2023 (v2) | Priority audit: 2 √ | |
noSchoolTripReasonSpecify?: string; // od_mtl_pilote_2021, od_mtl_pilote_2022, od_mtl_2023, od_qc_2023 | Priority audit: 3 √ | |
noUsualSchoolPlaceReason?: PAttr.NoUsualSchoolPlaceReason; // od_mtl_pilote_2021, od_mtl_pilote_2022 | Priority audit: 2 √ | |
noWorkOrStudyTripReason?: PAttr.NoWorkOrStudyTripReason; // od_mtl_ete_2023 | Priority audit: 2 √ | |
noWorkTripReasonV1?: PAttr.NoSchoolTripReasonV1; // od_mtl_pilote_2021 (v1), od_mtl_pilote_2022 (v1) | Priority audit: 2 √ | |
noWorkTripReasonV2?: PAttr.NoSchoolTripReasonV2; // od_mtl_2023 (v2), od_qc_2023 (v2) | Priority audit: 2 √ | |
noWorkTripReasonSpecify?: string; // od_mtl_pilote_2021, od_mtl_pilote_2022, od_mtl_2023, od_qc_2023 | Priority audit: 2 √ | |
occupationQC?: PAttr.OccupationQC; // od_qc_2023 | Priority audit: 1 | |
occupationV1?: PAttr.OccupationV1; // od_mtl_pilote_2021 | Priority audit: 1 | |
occupationV2?: PAttr.OccupationV2; // od_mtl_pilote_2022 | Priority audit: 1 | |
occupationV3?: PAttr.OccupationV3; // od_mtl_ete_2023, od_mtl_2023 | Priority audit: 1 | |
occupationSpecify?: string; // all | Priority audit: 3 √ | |
parentConsent?: PAttr.ParentConsent; // od_qc_2023 | Priority audit: 1 √ | |
consentConfirm?: boolean; // od_qc_2023 (only true is posible) | Priority audit: 1 √ | |
personDidTrips?: GAttr.YesNoDontKnow; // all | Priority audit: 1 √ | |
personDidTripsChangeConfirm?: GAttr.YesNo; // all | Priority audit: 1 √ | |
previousWeekDidTripsDays?: Date[] | string[]; // od_mtl_pilote_2021 | Priority audit: 2 √ | |
previousWeekNoWorkingDaysReasons?: PAttr.PreviousWeekNoWorkingDaysReason[]; // od_mtl_pilote_2021 | Priority audit: 2 √ | |
previousWeekWentToSchoolOutsideHomeDays?: Date[] | string[]; // od_mtl_pilote_2021 | Priority audit: 2 √ | |
previousWeekWentToWorkOutsideHomeDays?: Date[] | string[]; // od_mtl_pilote_2021 | Priority audit: 2 √ | |
previousWeekWorkingDays?: Date[] | string[]; // od_mtl_pilote_2021 | Priority audit: 2 √ | |
// refuseAge?: string; // od_qc_2023 (only yes or undefined values possible): ignore, implicit if ageGroup is set | |
remoteStudyDays?: PAttr.WeekDaysNoPreferNotToAnswer[]; // od_qc_2023 | Priority audit: 2 √ | |
remoteWorkDays?: PAttr.WeekDaysNoPreferNotToAnswer[]; // od_qc_2023 | Priority audit: 2 √ | |
schoolType?: PAttr.SchoolType; // od_qc_2023 | Priority audit: 1 √ | |
shortTripSectionDidSchoolTripsOnTripsDate?: GAttr.YesNoDontKnow; // od_mtl_pilote_2022 | Priority audit: 2 √ | |
shortTripSectionDidTripsOnTripsDate?: GAttr.YesNoDontKnow; // od_mtl_pilote_2022 | Priority audit: 2 √ | |
shortTripSectionDidTripsToUsualSchoolPlaceOnTripsDate?: GAttr.YesNoDontKnow; // od_mtl_pilote_2022 | Priority audit: 2 √ | |
shortTripSectionDidTripsToUsualWorkPlaceOnTripsDate?: GAttr.YesNoDontKnow; // od_mtl_pilote_2022 | Priority audit: 2 √ | |
shortTripSectionDidWorkTripsOnTripsDate?: GAttr.YesNoDontKnow; // od_mtl_pilote_2022 | Priority audit: 2 √ | |
studentType?: PAttr.StudentType; // all except od_qc_2023 | Priority audit: 1 √ | |
studiesFromFixedLocation?: GAttr.YesNoDontKnow; // od_mtl_2023, od_mtl_ete_2023 | Priority audit: 1 √ | |
transitPassTypes?: PAttr.TransitPassType[]; // od_qc_2023 -> move from transitFares in od_qc_2023 only | Priority audit: 2 √ | |
transitFaresUsed?: PAttr.TransitFareUsed[]; // od_mtl_2023, od_mtl_ete_2023 -> move from transitFares in od_mtl_ete_2023 | Priority audit: 2 √ | |
transitPassesV1?: PAttr.TransitPassMtlV1[]; // od_mtl_pilote_2021 | Priority audit: 2 √ | |
transitPassesV2?: PAttr.TransitPassMtlV2[]; // od_mtl_pilote_2022, od_mtl_ete_2023, od_mtl_2023 | Priority audit: 2 √ | |
transitPassesQC?: PAttr.TransitPassQC[]; // od_qc_2023 | Priority audit: 2 √ | |
transitPassSpecify?: string; // od_mtl_pilote_2022, od_mtl_2023, od_mtl_ete_2023 | Priority audit: 3 √ | |
travelToStudyDays?: PAttr.WeekDaysNoPreferNotToAnswer[]; // od_qc_2023 | Priority audit: 2 √ | |
travelToWorkDays?: PAttr.WeekDaysNoPreferNotToAnswer[]; // od_qc_2023 | Priority audit: 2 √ | |
useBikeForUtilitarianTravel?: GAttr.YesNoDontKnow; // od_mtl_pilote_2021, od_mtl_pilote_2022 | Priority audit: 2 √ | |
usedBixiBikesharingServicesInLast30Days?: GAttr.YesNoDontKnow; // od_mtl_2023 | Priority audit: 2 √ | |
usedBixiBikesharingServicesInLast6Months?: GAttr.YesNoDontKnow; // od_mtl_ete_2023 | Priority audit: 2 √ | |
usedCommunautoCarsharingServicesAsADriverInLast6Months?: GAttr.YesNoDontKnow; // od_mtl_2023, od_mtl_ete_2023 | Priority audit: 2 √ | |
usedTransitInLast30Days?: GAttr.YesNoDontKnow; // audited, od_mtl_2023, od_mtl_ete_2023 | Priority audit: 2 √ | |
useParatransit?: GAttr.YesNoDontKnowPreferNotToAnswer; // od_mtl_pilote_2022: YesNoDontKnow, od_mtl_ete_2023: YesNoDontKnow but dontKnow was labeled preferNotToAnswer, od_mtl_2023: YesNoPreferNotToAnswer | Priority audit: 2 √ | |
usualSchoolPlaceParkingType?: PAttr.UsualPlaceParkingType; // od_mtl_pilote_2021?, od_mtl_pilote_2022 | Priority audit: 2 √ | |
usualWorkPlaceIsHome?: boolean; // od_mtl_pilote_2021, od_mtl_pilote_2022 | Priority audit: 1 √ | |
usualWorkPlaceParkingType?: PAttr.UsualPlaceParkingType; // od_mtl_pilote_2021?, od_mtl_pilote_2022 | Priority audit: 2 √ | |
usualWorkPlaceUsageAtLeastOnceAWeek?: PAttr.UsualWorkPlaceUsageAtLeastOnceAWeek; // od_mtl_pilote_2021, od_mtl_pilote_2022 | Priority audit: 2 √ | |
usualWorkPlaceWasHomeBeforeThePandemic?: PAttr.UsualWorkPlaceWasHomeBeforeThePandemic; // od_mtl_pilote_2021, od_mtl_pilote_2022 | Priority audit: 2 √ | |
whoAnsweredForThisPerson?: string; // uuid of the person who answered. od_mtl_pilote_2021 | Priority audit: 1 √ | |
whoWillAnswerForThisPerson?: string; // uuid of the person who will answer. all surveys | Priority audit: 1 √ | |
workerAndStudentType?: PAttr.WorkerAndStudentType; // od_mtl_pilote_2021 | Priority audit: 2 √ | |
workingPlace?: PAttr.WorkingPlace; // od_mtl_2023, od_mtl_ete_2023 | Priority audit: 1 √ | |
workOnTheRoad?: boolean; // all except od_qc_2023 | Priority audit: 1 √ | |
worksFromFixedLocation?: boolean; // od_mtl_2023, od_mtl_ete_2023 | Priority audit: 1 √ | |
workTripsDaysCountPerWeek?: PAttr.WorkTripsDaysCountPerWeek; // od_mtl_pilote_2021, od_mtl_pilote_2022 | Priority audit: 2 √ | |
workType?: PAttr.WorkType; // od_qc_2023 | Priority audit: 1 √ | |
// generated from flattened attributes: | |
modeFrequencies?: PAttr.FrequencyByTripTypeAndModeV1AndV2; // generated from multiple input | Priority audit: 2 √ | |
} & ExtendedPersonAttributes; | |
class Person { | |
workPlaces?: BasePlace[]; | |
schoolPlaces?: BasePlace[]; | |
basePerson: BasePerson; | |
visitedPlaces?: VisitedPlace[]; | |
trips?: Trip[]; | |
_completedSections?: PAttr.CompletedSection; | |
_sequence?: number; | |
_color?: string; | |
_isProxy?: boolean; | |
ageIsApproximate?: boolean; | |
bixiBikesharingUsage?: PAttr.BixiBikesharingUsage; | |
['bixiBikesharingUsage_NewOptions2023-10-18']?: PAttr.BixiBikesharingUsageV2; // deleted by parser | |
bixiBikesharingUsageV2?: PAttr.BixiBikesharingUsageV2; | |
bikeOwnership?: GAttr.YesNoDontKnow; | |
drivingLicenseOwner?: GAttr.YesNoDontKnow; // move to basePerson drivingLicenseOwnership | |
transitPassOwner?: GAttr.YesNoDontKnow; // move to basePerson transitPassOwnership | |
communautoFlexCarsharingUsage?: PAttr.CommunautoFlexCarSharingUsage; | |
canRemoteWork?: PAttr.CanRemoteWork; | |
daysAtOfficePerWeek?: PAttr.DaysAtOfficePerWeek; | |
departurePlaceIsHome?: GAttr.YesNoDontKnow; | |
departurePlaceIsHomeConfirm?: GAttr.YesNoDontKnow; | |
departurePlaceOther?: PAttr.DeparturePlaceOther; | |
departurePlaceType?: PAttr.DeparturePlaceType; // od_qc_2023 only | |
didTripsOnTripsDate?: GAttr.YesNoDontKnow; // show in validation dashboard | |
disabilities?: PAttr.Disability[]; | |
disabilitiesComments?: string; | |
doesNotStudyFromFixedLocationReason?: PAttr.DoesNotStudyFromFixedLocationReason; | |
educationalAttainment?: PAttr.EducationalAttainment; | |
electricBikeOwnership?: GAttr.YesNoDontKnow; | |
enrolledInSchool?: PAttr.EnrolledInSchool; // show in validation dashboard | |
everUsedBixiBikesharingServices?: GAttr.YesNoDontKnowNonApplicable; | |
everUsedCommunautoFlexCarsharingServicesAsADriver?: GAttr.YesNoDontKnow; | |
freeParkingAtSchool?: PAttr.FreeParking; | |
freeParkingAtWork?: PAttr.FreeParking; | |
genderCustom?: string; | |
genderSpecify?: string; | |
hasDisability?: GAttr.YesNoPreferNotToAnswer; // show in validation dashboard | |
hasOmittedActiveModesTrips?: boolean; // show in validation dashboard | |
hasUsualSchoolPlace?: boolean; // show in validation dashboard | |
hasUsualWorkPlace?: boolean; // show in validation dashboard | |
job?: string; | |
jobActivitySector?: PAttr.JobActivitySector; | |
jobCategory?: PAttr.JobCategory; // override default values of basePerson | |
jobCompatibleWithTelecommuting?: PAttr.JobCompatibleWithTelecommuting; | |
jobHoursFlexibility?: PAttr.JobHoursFlexibility; | |
jobHoursSchedulesType?: PAttr.JobHoursSchedulesType; | |
jobType?: PAttr.JobType; | |
mobilityAssistiveDevices?: PAttr.MobilityAssistiveDevice[]; | |
mobilityAssistiveDevicesSpecify?: string; | |
mostUsedMobilityAssistiveDevice?: PAttr.MobilityAssistiveDevice; | |
// ignore nickname altogether | |
noSchoolTripReasonV1?: PAttr.NoSchoolTripReasonV1; | |
noSchoolTripReasonV2?: PAttr.NoSchoolTripReasonV2; | |
noSchoolTripReasonSpecify?: string; | |
noUsualSchoolPlaceReason?: PAttr.NoUsualSchoolPlaceReason; | |
noWorkOrStudyTripReason?: PAttr.NoWorkOrStudyTripReason; | |
noWorkTripReasonV1?: PAttr.NoWorkTripReasonV1; | |
noWorkTripReasonV2?: PAttr.NoWorkTripReasonV2; | |
noWorkTripReasonSpecify?: string; | |
occupationQC?: PAttr.OccupationQC; // show in validation dashboard | |
occupationV1?: PAttr.OccupationV1; // show in validation dashboard | |
occupationV2?: PAttr.OccupationV2; // show in validation dashboard | |
occupationV3?: PAttr.OccupationV3; // show in validation dashboard | |
occupationSpecify?: string; // show in validation dashboard | |
parentConsent?: PAttr.ParentConsent; // show in validation dashboard | |
consentConfirm?: boolean; // show in validation dashboard | |
personDidTrips?: GAttr.YesNoDontKnow; // show in validation dashboard | |
personDidTripsChangeConfirm?: GAttr.YesNo; | |
previousWeekDidTripsDays?: Date[]; | |
previousWeekNoWorkingDaysReasons?: PAttr.PreviousWeekNoWorkingDaysReason[]; | |
previousWeekWentToSchoolOutsideHomeDays?: Date[]; | |
previousWeekWentToWorkOutsideHomeDays?: Date[]; | |
previousWeekWorkingDays?: Date[]; | |
// refuseAge?: string; // ignore, implicit if ageGroup is set | |
remoteStudyDays?: PAttr.WeekDaysNoPreferNotToAnswer[]; | |
remoteWorkDays?: PAttr.WeekDaysNoPreferNotToAnswer[]; | |
schoolType?: PAttr.SchoolType; // show in validation dashboard | |
shortTripSectionDidSchoolTripsOnTripsDate?: GAttr.YesNoDontKnow; | |
shortTripSectionDidTripsOnTripsDate?: GAttr.YesNoDontKnow; | |
shortTripSectionDidTripsToUsualSchoolPlaceOnTripsDate?: GAttr.YesNoDontKnow; | |
shortTripSectionDidTripsToUsualWorkPlaceOnTripsDate?: GAttr.YesNoDontKnow; | |
shortTripSectionDidWorkTripsOnTripsDate?: GAttr.YesNoDontKnow; | |
studentType?: PAttr.StudentType; // show in validation dashboard | |
studiesFromFixedLocation?: GAttr.YesNoDontKnow; // show in validation dashboard | |
transitPassTypes?: PAttr.TransitPassType[]; | |
transitFaresUsed?: PAttr.TransitFareUsed[]; | |
transitPassesV1?: PAttr.TransitPassMtlV1[]; | |
transitPassesV2?: PAttr.TransitPassMtlV2[]; | |
transitPassesQC?: PAttr.TransitPassQC[]; | |
transitPassSpecify?: string; | |
travelToStudyDays?: PAttr.WeekDaysNoPreferNotToAnswer[]; | |
travelToWorkDays?: PAttr.WeekDaysNoPreferNotToAnswer[]; | |
useBikeForUtilitarianTravel?: GAttr.YesNoDontKnow; | |
usedBixiBikesharingServicesInLast30Days?: GAttr.YesNoDontKnow; | |
usedBixiBikesharingServicesInLast6Months?: GAttr.YesNoDontKnow; | |
usedCommunautoCarsharingServicesAsADriverInLast6Months?: GAttr.YesNoDontKnow; | |
usedTransitInLast30Days?: GAttr.YesNoDontKnow; | |
useParatransit?: GAttr.YesNoDontKnowPreferNotToAnswer; | |
usualSchoolPlaceParkingType?: PAttr.UsualPlaceParkingType; | |
usualWorkPlaceIsHome?: boolean; // show in validation dashboard | |
usualWorkPlaceParkingType?: PAttr.UsualPlaceParkingType; | |
usualWorkPlaceUsageAtLeastOnceAWeek?: PAttr.UsualWorkPlaceUsageAtLeastOnceAWeek; | |
usualWorkPlaceWasHomeBeforeThePandemic?: PAttr.UsualWorkPlaceWasHomeBeforeThePandemic; | |
whoAnsweredForThisPerson?: string; // show in validation dashboard | |
whoWillAnswerForThisPerson?: string; // show in validation dashboard | |
workerAndStudentType?: PAttr.WorkerAndStudentType; // show in validation dashboard | |
workingPlace?: PAttr.WorkingPlace; | |
workOnTheRoad?: boolean; // show in validation dashboard | |
worksFromFixedLocation?: boolean; // show in validation dashboard | |
workTripsDaysCountPerWeek?: PAttr.WorkTripsDaysCountPerWeek; | |
workType?: PAttr.WorkType; // show in validation dashboard | |
// generated from flattened attributes: | |
modeFrequencies?: PAttr.FrequencyByTripTypeAndModeV1AndV2; | |
// do not export these: | |
static _confidentialAttributes: string[] = [ | |
'nickname', // replace by P1, P2, P3... in interview summary (validation), but not in the questionnaire validation itself | |
'disabilitiesComments', // show in validation though | |
'genderSpecify', | |
'genderCustom' | |
]; | |
constructor( | |
params: { | |
basePerson: BasePerson; | |
visitedPlaces?: VisitedPlace[]; | |
trips?: Trip[]; | |
workPlaces?: BasePlace[]; | |
schoolPlaces?: BasePlace[]; | |
} & PersonAttributes | |
) { | |
this.basePerson = params.basePerson; | |
this.visitedPlaces = params.visitedPlaces || []; | |
this.trips = params.trips || []; | |
this.workPlaces = params.workPlaces || []; | |
this.schoolPlaces = params.schoolPlaces || []; | |
this._completedSections = params._completedSections; | |
this._sequence = params._sequence; | |
this._color = params._color; | |
this.ageIsApproximate = params.ageIsApproximate; | |
this.bixiBikesharingUsage = params.bixiBikesharingUsage; | |
this['bixiBikesharingUsage_NewOptions2023-10-18'] = params['bixiBikesharingUsage_NewOptions2023-10-18']; | |
this.bixiBikesharingUsageV2 = params.bixiBikesharingUsageV2; | |
this.bikeOwnership = params.bikeOwnership; | |
this.drivingLicenseOwner = params.drivingLicenseOwner; | |
this.transitPassOwner = params.transitPassOwner; | |
this.communautoFlexCarsharingUsage = params.communautoFlexCarsharingUsage; | |
this.canRemoteWork = params.canRemoteWork; | |
this.daysAtOfficePerWeek = params.daysAtOfficePerWeek; | |
this.departurePlaceIsHome = params.departurePlaceIsHome; | |
this.departurePlaceIsHomeConfirm = params.departurePlaceIsHomeConfirm; | |
this.departurePlaceOther = params.departurePlaceOther; | |
this.departurePlaceType = params.departurePlaceType; | |
this.doesNotStudyFromFixedLocationReason = params.doesNotStudyFromFixedLocationReason; | |
this.didTripsOnTripsDate = params.didTripsOnTripsDate; | |
this.disabilities = params.disabilities; | |
this.disabilitiesComments = params.disabilitiesComments; | |
this.educationalAttainment = params.educationalAttainment; | |
this.electricBikeOwnership = params.electricBikeOwnership; | |
this.enrolledInSchool = params.enrolledInSchool; | |
this.everUsedBixiBikesharingServices = params.everUsedBixiBikesharingServices; | |
this.everUsedCommunautoFlexCarsharingServicesAsADriver = | |
params.everUsedCommunautoFlexCarsharingServicesAsADriver; | |
this.freeParkingAtSchool = params.freeParkingAtSchool; | |
this.freeParkingAtWork = params.freeParkingAtWork; | |
this.genderCustom = params.genderCustom; | |
this.genderSpecify = params.genderSpecify; | |
this.hasDisability = params.hasDisability; | |
this.hasOmittedActiveModesTrips = params.hasOmittedActiveModesTrips; | |
this.hasUsualSchoolPlace = params.hasUsualSchoolPlace; | |
this.hasUsualWorkPlace = params.hasUsualWorkPlace; | |
this.job = params.job; | |
this.jobActivitySector = params.jobActivitySector; | |
this.jobCategory = params.jobCategory; | |
this.jobCompatibleWithTelecommuting = params.jobCompatibleWithTelecommuting; | |
this.jobHoursFlexibility = params.jobHoursFlexibility; | |
this.jobHoursSchedulesType = params.jobHoursSchedulesType; | |
this.jobType = params.jobType; | |
this.mobilityAssistiveDevices = params.mobilityAssistiveDevices; | |
this.mobilityAssistiveDevicesSpecify = params.mobilityAssistiveDevicesSpecify; | |
this.mostUsedMobilityAssistiveDevice = params.mostUsedMobilityAssistiveDevice; | |
// ignore nickname altogether | |
this.noSchoolTripReasonV1 = params.noSchoolTripReasonV1; | |
this.noSchoolTripReasonV2 = params.noSchoolTripReasonV2; | |
this.noSchoolTripReasonSpecify = params.noSchoolTripReasonSpecify; | |
this.noUsualSchoolPlaceReason = params.noUsualSchoolPlaceReason; | |
this.noWorkOrStudyTripReason = params.noWorkOrStudyTripReason; | |
this.noWorkTripReasonV1 = params.noWorkTripReasonV1; | |
this.noWorkTripReasonV2 = params.noWorkTripReasonV2; | |
this.noWorkTripReasonSpecify = params.noWorkTripReasonSpecify; | |
this.occupationQC = params.occupationQC; | |
this.occupationV1 = params.occupationV1; | |
this.occupationV2 = params.occupationV2; | |
this.occupationV3 = params.occupationV3; | |
this.occupationSpecify = params.occupationSpecify; | |
this.parentConsent = params.parentConsent; | |
this.consentConfirm = params.consentConfirm; | |
this.personDidTrips = params.personDidTrips; | |
this.personDidTripsChangeConfirm = params.personDidTripsChangeConfirm; | |
this.previousWeekDidTripsDays = | |
params.previousWeekDidTripsDays !== undefined | |
? params.previousWeekDidTripsDays.map((date) => parseDate(date)) | |
: undefined; | |
this.previousWeekNoWorkingDaysReasons = params.previousWeekNoWorkingDaysReasons; | |
this.previousWeekWentToSchoolOutsideHomeDays = | |
params.previousWeekWentToSchoolOutsideHomeDays !== undefined | |
? params.previousWeekWentToSchoolOutsideHomeDays.map((date) => parseDate(date)) | |
: undefined; | |
this.previousWeekWentToWorkOutsideHomeDays = | |
params.previousWeekWentToWorkOutsideHomeDays !== undefined | |
? params.previousWeekWentToWorkOutsideHomeDays.map((date) => parseDate(date)) | |
: undefined; | |
this.previousWeekWorkingDays = | |
params.previousWeekWorkingDays !== undefined | |
? params.previousWeekWorkingDays.map((date) => parseDate(date)) | |
: undefined; | |
//this.refuseAge = params.refuseAge; // ignore, implicit if ageGroup is set | |
this.remoteStudyDays = params.remoteStudyDays; | |
this.remoteWorkDays = params.remoteWorkDays; | |
this.schoolType = params.schoolType; | |
this.shortTripSectionDidSchoolTripsOnTripsDate = params.shortTripSectionDidSchoolTripsOnTripsDate; | |
this.shortTripSectionDidTripsOnTripsDate = params.shortTripSectionDidTripOnTripsDate; | |
this.shortTripSectionDidTripsToUsualSchoolPlaceOnTripsDate = | |
params.shortTripSectionDidTripToUsualSchoolPlaceOnTripsDate; | |
this.shortTripSectionDidTripsToUsualWorkPlaceOnTripsDate = | |
params.shortTripSectionDidTripToUsualWorkPlaceOnTripsDate; | |
this.shortTripSectionDidWorkTripsOnTripsDate = params.shortTripSectionDidWorkTripsOnTripsDate; | |
this.studentType = params.studentType; | |
this.studiesFromFixedLocation = params.studiesFromFixedLocation; | |
this.transitPassTypes = params.transitPassTypes; | |
this.transitFaresUsed = params.transitFaresUsed; | |
this.transitPassesV1 = params.transitPassesV1; | |
this.transitPassesV2 = params.transitPassesV2; | |
this.transitPassesQC = params.transitPassesQC; | |
this.transitPassSpecify = params.transitPassSpecify; | |
this.travelToStudyDays = params.travelToStudyDays; | |
this.travelToWorkDays = params.travelToWorkDays; | |
this.useBikeForUtilitarianTravel = params.useBikeForUtilitarianTravel; | |
this.usedBixiBikesharingServicesInLast30Days = params.usedBixiBikesharingServicesInLast30Days; | |
this.usedBixiBikesharingServicesInLast6Months = params.usedBixiBikesharingServicesInLast6Months; | |
this.usedCommunautoCarsharingServicesAsADriverInLast6Months = | |
params.usedCommunautoCarsharingServicesAsADriverInLast6Months; | |
this.usedTransitInLast30Days = params.usedTransitInLast30Days; | |
this.useParatransit = params.useParatransit; | |
this.usualSchoolPlaceParkingType = params.usualSchoolPlaceParkingType; | |
this.usualWorkPlaceIsHome = params.usualWorkPlaceIsHome; | |
this.usualWorkPlaceParkingType = params.usualWorkPlaceParkingType; | |
this.usualWorkPlaceUsageAtLeastOnceAWeek = params.usualWorkPlaceUsageAtLeastOnceAWeek; | |
this.usualWorkPlaceWasHomeBeforeThePandemic = params.usualWorkPlaceWasHomeBeforeThePandemic; | |
this.whoAnsweredForThisPerson = params.whoAnsweredForThisPerson; | |
this.whoWillAnswerForThisPerson = params.whoWillAnswerForThisPerson; | |
this.workerAndStudentType = params.workerAndStudentType; | |
this.workingPlace = params.workingPlace; | |
this.workOnTheRoad = params.workOnTheRoad; | |
this.worksFromFixedLocation = params.worksFromFixedLocation; | |
this.workTripsDaysCountPerWeek = params.workTripsDaysCountPerWeek; | |
this.workType = params.workType; | |
this._isProxy = this.isProxy(); | |
// generated from flattened attributes: | |
this.modeFrequencies = params.modeFrequencies; | |
} | |
// will not check for error, data must be sanitized before | |
static unserialize( | |
attributes: PersonAttributes & { | |
trips?: (TripAttributes & { baseTrip: BaseTripAttributes })[]; | |
visitedPlaces?: (VisitedPlaceAttributes & { | |
baseVisitedPlace: BaseVisitedPlaceAttributes & { | |
basePlace: BasePlaceAttributes & { address?: BaseAddressAttributes }; | |
}; | |
})[]; | |
workPlaces?: (BasePlaceAttributes & { address?: BaseAddressAttributes })[]; | |
schoolPlaces?: (BasePlaceAttributes & { address?: BaseAddressAttributes })[]; | |
basePerson: BasePersonAttributes; | |
} | |
): Person { | |
const serializedTrips = attributes.trips || []; | |
const trips = []; | |
for (let i = 0, count = serializedTrips.length; i < count; i++) { | |
trips.push(Trip.unserialize(serializedTrips[i])); | |
} | |
const serializedVisitedPlaces = attributes.visitedPlaces || []; | |
const visitedPlaces = []; | |
for (let i = 0, count = serializedVisitedPlaces.length; i < count; i++) { | |
visitedPlaces.push(VisitedPlace.unserialize(serializedVisitedPlaces[i])); | |
} | |
const serializedWorkPlaces = attributes.workPlaces || []; | |
const workPlaces = []; | |
for (let i = 0, count = serializedWorkPlaces.length; i < count; i++) { | |
workPlaces.push(BasePlace.unserialize(serializedWorkPlaces[i])); | |
} | |
const serializedSchoolPlaces = attributes.schoolPlaces || []; | |
const schoolPlaces = []; | |
for (let i = 0, count = serializedSchoolPlaces.length; i < count; i++) { | |
schoolPlaces.push(BasePlace.unserialize(serializedSchoolPlaces[i])); | |
} | |
const basePerson = BasePerson.unserialize(attributes.basePerson); | |
const person = new Person({ ...attributes, basePerson, trips, visitedPlaces, workPlaces, schoolPlaces }); | |
return person; | |
} | |
// checks if minimum required information have been completed/declared | |
// TODO: test | |
isCompleteMinimum(): boolean { | |
return ( | |
(this.basePerson.age !== undefined || this.basePerson.ageGroup) && | |
this._sequence !== undefined && | |
this._sequence > 0 && | |
(this.ageCompare(16) < 0 || this.basePerson.drivingLicenseOwnership !== undefined) && | |
this.basePerson.occupation !== undefined && | |
this.personDidTrips !== undefined && | |
this._isProxy !== undefined && | |
// no need to check for age with transit pass ownership because all surveys would set to nonApplicable for too young: | |
this.basePerson.transitPassOwnership !== undefined | |
// TODO: school/work/Type if needed | |
// TODO: usualWork/School/Place if needed | |
// TODO: workOnTheRoad if needed | |
); | |
} | |
hasAtLeastOneTransitSegment(): boolean { | |
return this.getTrips().some((trip) => trip.hasAtLeastOneTransitSegment()); | |
} | |
// needed to get the usual place and save it into basePerson, no matter which survey: | |
// od_mtl_2023 only asks for usual work/school place if none declared in travel diary | |
// TODO: test | |
setupWorkPlaces(): void { | |
const usualWorkVisitedPlaces = this.getUsualWorkVisitedPlaces(); | |
if ( | |
(this.shouldHaveAUsualWorkPlace() || usualWorkVisitedPlaces.length > 0) && | |
(this.workPlaces === undefined || this.workPlaces.length === 0) | |
) { | |
if (usualWorkVisitedPlaces.length > 0) { | |
this.workPlaces = usualWorkVisitedPlaces.map((visitedPlace) => visitedPlace.baseVisitedPlace.basePlace); | |
} | |
} | |
} | |
// check if this person should declare a usual work place | |
shouldHaveAUsualWorkPlace(): boolean | undefined { | |
return ( | |
this.isWorker() === true && // isWorker could be undefined if missing attributes/occupation | |
(this.hasUsualWorkPlace === true || | |
(this.worksFromFixedLocation === true && this.isFullTimeWorker() === true) || // od_mtl_pilote_2022, od_mtl_ete_2023, od_mtl_2023 (part-time: not asked in od_mtl_2023) | |
(this.hasUsualWorkPlace === undefined && this.usualWorkPlaceIsHome === false) || // od_mtl_pilote_2021 | |
(this.workType !== undefined && | |
[ | |
// od_qc_2023 | |
'onLocation', | |
'hybrid', | |
'onTheRoadWithUsualPlace' | |
].includes(this.workType))) | |
); | |
} | |
// TODO: test | |
wentToUsualWorkPlace(): boolean { | |
return this.getUsualWorkVisitedPlaces().length > 0; | |
} | |
// TODO: test | |
getUsualWorkVisitedPlaces(): VisitedPlace[] { | |
const visitedPlaces = this.getVisitedPlaces(); | |
const usualWorkVisitedPlaces = []; | |
for (let i = 0, count = visitedPlaces.length; i < count; i++) { | |
const visitedPlace = visitedPlaces[i]; | |
if (visitedPlace.baseVisitedPlace.activity === 'workUsual') { | |
usualWorkVisitedPlaces.push(visitedPlace); | |
} | |
} | |
return usualWorkVisitedPlaces; | |
} | |
// TODO: test | |
getVisitedPlaces(): VisitedPlace[] { | |
return this.visitedPlaces || []; | |
} | |
// TODO: test | |
getTrips(): Trip[] { | |
return this.trips || []; | |
} | |
// TODO: test | |
countTrips(): number { | |
return this.getTrips().length || 0; | |
} | |
// TODO: test | |
countVisitedPlaces(): number { | |
return this.getVisitedPlaces().length || 0; | |
} | |
// TODO: test | |
getVisitedPlaceByUuid(visitedPlaceUuid: string): VisitedPlace | undefined { | |
return this.getVisitedPlaces().find((visitedPlace) => visitedPlace.baseVisitedPlace._uuid === visitedPlaceUuid); | |
} | |
// TODO: test | |
getVisitedPlaceBySequence(sequence: number): VisitedPlace | undefined { | |
return this.getVisitedPlaces().find((visitedPlace) => visitedPlace._sequence === sequence); | |
} | |
// TODO: test | |
getTripByUuid(tripUuid: string): Trip | undefined { | |
return this.getTrips().find((trip) => trip.baseTrip._uuid === tripUuid); | |
} | |
// TODO: test | |
getTripBySequence(sequence: number): Trip | undefined { | |
return this.getTrips().find((trip) => trip._sequence === sequence); | |
} | |
// TODO: test | |
sortVisitedPlaces() { | |
this.visitedPlaces = this.visitedPlaces?.sort((a, b) => { | |
return a._sequence - b._sequence; | |
}); | |
} | |
// TODO: test | |
sortTrips() { | |
this.trips = this.trips?.sort((a, b) => { | |
return a._sequence - b._sequence; | |
}); | |
} | |
getAge(): number | undefined { | |
return this.basePerson.age; | |
} | |
getAgeGroup(): string | undefined { | |
return this.basePerson.ageGroup; | |
} | |
isWorker(): boolean | undefined { | |
if (this.jobType !== undefined) { | |
// all except od_qc_2023 and od_mtl_pilote_2021 | |
return ['yesFullTime', 'yesPartTime'].includes(this.jobType); | |
} else if (this.occupationQC !== undefined) { | |
// in od_qc_2023, cannot be both student and worker | |
return ['fullTimeWorker', 'partTimeWorker'].includes(this.occupationQC); | |
} else if (this.occupationV1 !== undefined) { | |
// od_mtl_pilote_2021 | |
return ['fullTimeWorker', 'partTimeWorker', 'workerAndStudent'].includes(this.occupationV1); | |
} | |
return undefined; | |
} | |
isFullTimeWorker(): boolean | undefined { | |
if (this.jobType !== undefined) { | |
// all except od_qc_2023 | |
return this.jobType === 'yesFullTime'; | |
} else if (this.occupationQC !== undefined) { | |
// in od_qc_2023, cannot be both student and worker | |
return this.occupationQC === 'fullTimeWorker'; | |
} else if (this.occupationV1 !== undefined) { | |
// od_mtl_pilote_2021: occupation or workerAndStudentType if both student and worker | |
return this.occupationV1 === 'fullTimeWorker' || this.workerAndStudentType.startsWith('fullTimeWork'); | |
} | |
return undefined; | |
} | |
isPartTimeWorker(): boolean | undefined { | |
if (this.jobType !== undefined) { | |
// all except od_qc_2023 | |
return this.jobType === 'yesPartTime'; | |
} else if (this.occupationQC !== undefined) { | |
// in od_qc_2023, cannot be both student and worker | |
return this.occupationQC === 'partTimeWorker'; | |
} else if (this.occupationV1 !== undefined) { | |
// od_mtl_pilote_2021: occupation or workerAndStudentType if both student and worker | |
return this.occupationV1 === 'partTimeWorker' || this.workerAndStudentType.startsWith('partTimeWork'); | |
} | |
return undefined; | |
} | |
isStudent() { | |
if (this.studentType !== undefined) { | |
return ['yesFullTime', 'yesPartTime'].includes(this.studentType); | |
} else if (this.enrolledInSchool !== undefined) { | |
return [ | |
'kindergartenFor4YearsOld', | |
'kindergarten', | |
'primarySchool', | |
'secondarySchool', | |
'collegeCegepDepAep', | |
'university', | |
'schoolAtHome', | |
'other' // not sure what to do with other... | |
].includes(this.enrolledInSchool); | |
} else if (this.occupationV1) { | |
// od_mtl_pilote_2021 | |
return ['fullTimeStudent', 'partTimeStudent', 'workerAndStudent'].includes(this.occupationV1); | |
} | |
return undefined; | |
} | |
isFullTimeStudent() { | |
// only used in od_mtl_2023 and od_qc_2023 | |
if (this.studentType !== undefined) { | |
return this.studentType === 'yesFullTime'; | |
} else if (this.enrolledInSchool !== undefined) { | |
// not sure what to do with other, but in the helper, it returned false here | |
return [ | |
'kindergartenFor4YearsOld', | |
'kindergarten', | |
'primarySchool', | |
'secondarySchool', | |
'schoolAtHome', | |
'other' // not sure what to do with other... | |
].includes(this.enrolledInSchool); | |
} else if (this.occupationV1) { | |
// od_mtl_pilote_2021 | |
return ( | |
['fullTimeStudent'].includes(this.occupationV1) || this.workerAndStudentType.endsWith('FullTimeStudies') | |
); | |
} else if (this.occupationQC) { | |
// in od_qc_2023, cannot be both student and worker | |
return this.occupationQC === 'fullTimeStudent'; | |
} | |
} | |
isPartTimeStudent() { | |
// only used in od_mtl_2023 and od_qc_2023 | |
if (this.studentType !== undefined) { | |
return this.studentType === 'yesPartTime'; | |
} else if (this.occupationV1) { | |
// od_mtl_pilote_2021 | |
return ( | |
['partTimeStudent'].includes(this.occupationV1) || this.workerAndStudentType.endsWith('PartTimeStudies') | |
); | |
} else if (this.occupationQC) { | |
// in od_qc_2023, cannot be both student and worker | |
return this.occupationQC === 'partTimeStudent'; | |
} | |
} | |
isSelfDeclared() { | |
// the person responded for themselves | |
const ageComparison = this.ageCompare(config.selfResponseMinimumAge || 14); | |
if (ageComparison !== undefined && ageComparison >= 0) { | |
if (this.whoWillAnswerForThisPerson !== undefined) { | |
return this.whoWillAnswerForThisPerson === this.basePerson._uuid; | |
} else if (this.whoAnsweredForThisPerson !== undefined) { | |
return this.whoAnsweredForThisPerson === this.basePerson._uuid; | |
} else { | |
return undefined; | |
} | |
} | |
if (ageComparison === undefined) { | |
return undefined; | |
} else { | |
// too young, auto proxy | |
return false; | |
} | |
} | |
isProxy() { | |
// another household member responded for this person | |
const isSelfDeclared = this.isSelfDeclared(); | |
if (isSelfDeclared !== undefined) { | |
return !isSelfDeclared; | |
} | |
return undefined; | |
} | |
mayHaveDisability() { | |
if (this.hasDisability !== undefined) { | |
return this.hasDisability !== 'no'; // accept yes and preferNotToAnswer | |
} | |
return undefined; | |
} | |
/** | |
* Compare the age of a person with a requested age. This will look at the age | |
* field, if set, or see if the desired age is within the ageGroup | |
* | |
* @param age The age to compare to | |
* @return -1 if the person age or age group is lower than the value, 0 if the | |
* age is equal or the ageGroup includes the age, 1 if the person age or | |
* ageGroup is higher than requested age, or undefined if the age and ageGroup are | |
* unavailable | |
*/ | |
ageCompare(age: number): number | undefined { | |
const personAge = this.basePerson.age; | |
if (typeof personAge === 'number') { | |
return personAge < age ? -1 : personAge === age ? 0 : 1; | |
} | |
const ageGroup = this.basePerson.ageGroup; | |
if (typeof ageGroup !== 'string') { | |
return undefined; | |
} | |
const separatorDashPos = ageGroup.indexOf('-'); | |
if (separatorDashPos !== -1) { | |
const minAge = parseInt(ageGroup.substring(0, separatorDashPos)); | |
const maxAge = parseInt(ageGroup.substring(separatorDashPos + 1)); | |
if (!Number.isNaN(minAge) && !Number.isNaN(maxAge)) { | |
return maxAge < age ? -1 : minAge > age ? 1 : 0; | |
} | |
return undefined; | |
} | |
const separatorPlusPos = ageGroup.indexOf('+'); | |
if (separatorPlusPos !== -1) { | |
const minMaxAge = parseInt(ageGroup.substring(0, separatorPlusPos)); | |
if (!Number.isNaN(minMaxAge)) { | |
return minMaxAge < age ? -1 : minMaxAge === age ? 0 : 1; | |
} | |
} | |
return undefined; | |
} | |
/** | |
* Function that converts and move all versions of mode frequencies to a normalized format | |
* @param dirtyParams | |
* @returns modeFrequencies: PAttr.FrequencyByTripTypeAndModeV1AndV2 | |
*/ | |
static moveModeFrequencies( | |
dirtyParams: { [key: string]: any }, | |
surveyShortname | |
): PAttr.FrequencyByTripTypeAndModeV1AndV2 { | |
/* | |
anyTripModeFrequenciesWalk?: PAttr.ModeFrequencyV1 | PAttr.ModeFrequencyV2; // all except od_qc_2023 (v1), od_mtl_2023 (v2) | |
anyTripModeFrequenciesBicycle?: PAttr.ModeFrequencyV1 | PAttr.ModeFrequencyV2; // all except od_qc_2023 (v1), od_mtl_2023 (v2) | |
anyTripModeFrequenciesCarDriver?: PAttr.ModeFrequencyV1 | PAttr.ModeFrequencyV2; // all except od_qc_2023 (v1), od_mtl_2023 (v2) | |
anyTripModeFrequenciesCarPassenger?: PAttr.ModeFrequencyV1 | PAttr.ModeFrequencyV2; // all except od_qc_2023 (v1), od_mtl_2023 (v2) | |
anyTripModeFrequenciesTransit?: PAttr.ModeFrequencyV1 | PAttr.ModeFrequencyV2; // od_mtl_2023 (v2), od_mtl_ete_2023 (v1) | |
anyTripModeFrequenciesTransitBus?: PAttr.ModeFrequencyV1 | PAttr.ModeFrequencyV2; // od_mtl_pilote_2021 (v1), od_mtl_pilote_2022 (v1) | |
anyTripModeFrequenciesTransitSubway?: PAttr.ModeFrequencyV1 | PAttr.ModeFrequencyV2; // od_mtl_pilote_2021 (v1), od_mtl_pilote_2022 (v1) | |
anyTripModeFrequenciesTransitTrainREM?: PAttr.ModeFrequencyV1 | PAttr.ModeFrequencyV2; // od_mtl_pilote_2021 (v1), od_mtl_pilote_2022 (v1) | |
anyTripModeFrequenciesSchoolBus?: PAttr.ModeFrequencyV1 | PAttr.ModeFrequencyV2; // od_mtl_2023 (v2), od_mtl_ete_2023 (v1) | |
anyTripModeFrequenciesTaxi?: PAttr.ModeFrequencyV1 | PAttr.ModeFrequencyV2; // od_mtl_2023 (v2), od_mtl_ete_2023 (v1) | |
// can start with homeWorkTripFrequencies too: | |
workCommutingFrequenciesWalk?: PAttr.ModeFrequencyV1 | PAttr.ModeFrequencyV2; // od_mtl_2023 (v2), od_mtl_ete_2023 (v1), od_mtl_pilote_2021 (v1), od_mtl_pilote_2022 (v1) | |
workCommutingFrequenciesBicycle?: PAttr.ModeFrequencyV1 | PAttr.ModeFrequencyV2; // od_mtl_2023 (v2), od_mtl_ete_2023 (v1), od_mtl_pilote_2021 (v1), od_mtl_pilote_2022 (v1) | |
workCommutingFrequenciesCarDriver?: PAttr.ModeFrequencyV1 | PAttr.ModeFrequencyV2; // od_mtl_2023 (v2), od_mtl_ete_2023 (v1), od_mtl_pilote_2021 (v1), od_mtl_pilote_2022 (v1) | |
workCommutingFrequenciesCarPassenger?: PAttr.ModeFrequencyV1 | PAttr.ModeFrequencyV2; // od_mtl_2023 (v2), od_mtl_ete_2023 (v1), od_mtl_pilote_2021 (v1), od_mtl_pilote_2022 (v1) | |
workCommutingFrequenciesTransit?: PAttr.ModeFrequencyV1 | PAttr.ModeFrequencyV2; // od_mtl_2023 (v2), od_mtl_ete_2023 (v1) | |
workCommutingFrequenciesTransitBus?: PAttr.ModeFrequencyV1 | PAttr.ModeFrequencyV2; // od_mtl_pilote_2021 (v1), od_mtl_pilote_2022 (v1) | |
workCommutingFrequenciesTransitSubway?: PAttr.ModeFrequencyV1 | PAttr.ModeFrequencyV2; // od_mtl_pilote_2021 (v1), od_mtl_pilote_2022 (v1) | |
workCommutingFrequenciesTransitTrainREM?: PAttr.ModeFrequencyV1 | PAttr.ModeFrequencyV2; // od_mtl_pilote_2021 (v1), od_mtl_pilote_2022 (v1) | |
workCommutingFrequenciesSchoolBus?: PAttr.ModeFrequencyV1 | PAttr.ModeFrequencyV2; // unused | |
workCommutingFrequenciesTaxi?: PAttr.ModeFrequencyV1 | PAttr.ModeFrequencyV2; // unused | |
// can start with homeSchoolTripFrequencies too: | |
schoolCommutingFrequenciesWalk?: PAttr.ModeFrequencyV1 | PAttr.ModeFrequencyV2; // od_mtl_2023 (v2), od_mtl_ete_2023 (v1), od_mtl_pilote_2021 (v1), od_mtl_pilote_2022 (v1) | |
schoolCommutingFrequenciesBicycle?: PAttr.ModeFrequencyV1 | PAttr.ModeFrequencyV2; // od_mtl_2023 (v2), od_mtl_ete_2023 (v1), od_mtl_pilote_2021 (v1), od_mtl_pilote_2022 (v1) | |
schoolCommutingFrequenciesCarDriver?: PAttr.ModeFrequencyV1 | PAttr.ModeFrequencyV2; // od_mtl_2023 (v2), od_mtl_ete_2023 (v1), od_mtl_pilote_2021 (v1), od_mtl_pilote_2022 (v1) | |
schoolCommutingFrequenciesCarPassenger?: PAttr.ModeFrequencyV1 | PAttr.ModeFrequencyV2; // od_mtl_2023 (v2), od_mtl_ete_2023 (v1), od_mtl_pilote_2021 (v1), od_mtl_pilote_2022 (v1) | |
schoolCommutingFrequenciesTransit?: PAttr.ModeFrequencyV1 | PAttr.ModeFrequencyV2; // od_mtl_2023 (v2), od_mtl_ete_2023 (v1) | |
schoolCommutingFrequenciesTransitBus?: PAttr.ModeFrequencyV1 | PAttr.ModeFrequencyV2; // od_mtl_pilote_2021 (v1), od_mtl_pilote_2022 (v1) | |
schoolCommutingFrequenciesTransitSubway?: PAttr.ModeFrequencyV1 | PAttr.ModeFrequencyV2; // od_mtl_pilote_2021 (v1), od_mtl_pilote_2022 (v1) | |
schoolCommutingFrequenciesTransitTrainREM?: PAttr.ModeFrequencyV1 | PAttr.ModeFrequencyV2; // od_mtl_pilote_2021 (v1), od_mtl_pilote_2022 (v1) | |
schoolCommutingFrequenciesSchoolBus?: PAttr.ModeFrequencyV1 | PAttr.ModeFrequencyV2; // od_mtl_2023 (v2) | |
schoolCommutingFrequenciesTaxi?: PAttr.ModeFrequencyV1 | PAttr.ModeFrequencyV2; // unused | |
*/ | |
let modeFrequencies: PAttr.FrequencyByTripTypeAndModeV1AndV2 | undefined = undefined; | |
if (!dirtyParams.modeFrequencies) { | |
modeFrequencies = { | |
anyTripV1: { | |
walk: surveyShortname !== 'od_mtl_2023' ? dirtyParams.anyTripModeFrequenciesWalk : undefined, | |
bicycle: surveyShortname !== 'od_mtl_2023' ? dirtyParams.anyTripModeFrequenciesBicycle : undefined, | |
carDriver: | |
surveyShortname !== 'od_mtl_2023' ? dirtyParams.anyTripModeFrequenciesCarDriver : undefined, | |
carPassenger: | |
surveyShortname !== 'od_mtl_2023' ? dirtyParams.anyTripModeFrequenciesCarPassenger : undefined, | |
transit: surveyShortname !== 'od_mtl_2023' ? dirtyParams.anyTripModeFrequenciesTransit : undefined, | |
transitBus: | |
surveyShortname !== 'od_mtl_2023' ? dirtyParams.anyTripModeFrequenciesTransitBus : undefined, | |
transitSubway: | |
surveyShortname !== 'od_mtl_2023' ? dirtyParams.anyTripModeFrequenciesTransitSubway : undefined, | |
transitTrainREM: | |
surveyShortname !== 'od_mtl_2023' | |
? dirtyParams.anyTripModeFrequenciesTransitTrainREM | |
: undefined, | |
schoolBus: | |
surveyShortname !== 'od_mtl_2023' ? dirtyParams.anyTripModeFrequenciesSchoolBus : undefined, | |
taxi: surveyShortname !== 'od_mtl_2023' ? dirtyParams.anyTripModeFrequenciesTaxi : undefined | |
}, | |
anyTripV2: { | |
walk: surveyShortname === 'od_mtl_2023' ? dirtyParams.anyTripModeFrequenciesWalk : undefined, | |
bicycle: surveyShortname === 'od_mtl_2023' ? dirtyParams.anyTripModeFrequenciesBicycle : undefined, | |
carDriver: | |
surveyShortname === 'od_mtl_2023' ? dirtyParams.anyTripModeFrequenciesCarDriver : undefined, | |
carPassenger: | |
surveyShortname === 'od_mtl_2023' ? dirtyParams.anyTripModeFrequenciesCarPassenger : undefined, | |
transit: surveyShortname === 'od_mtl_2023' ? dirtyParams.anyTripModeFrequenciesTransit : undefined, | |
transitBus: | |
surveyShortname === 'od_mtl_2023' ? dirtyParams.anyTripModeFrequenciesTransitBus : undefined, | |
transitSubway: | |
surveyShortname === 'od_mtl_2023' ? dirtyParams.anyTripModeFrequenciesTransitSubway : undefined, | |
transitTrainREM: | |
surveyShortname === 'od_mtl_2023' | |
? dirtyParams.anyTripModeFrequenciesTransitTrainREM | |
: undefined, | |
schoolBus: | |
surveyShortname === 'od_mtl_2023' ? dirtyParams.anyTripModeFrequenciesSchoolBus : undefined, | |
taxi: surveyShortname === 'od_mtl_2023' ? dirtyParams.anyTripModeFrequenciesTaxi : undefined | |
}, | |
workCommutingV1: { | |
walk: | |
surveyShortname !== 'od_mtl_2023' | |
? dirtyParams.workCommutingModeFrequenciesWalk || | |
dirtyParams.homeWorkTripModeFrequenciesWalk || | |
dirtyParams.homeWorkTripModeFrequencies?.walk | |
: undefined, | |
bicycle: | |
surveyShortname !== 'od_mtl_2023' | |
? dirtyParams.workCommutingModeFrequenciesBicycle || | |
dirtyParams.homeWorkTripModeFrequenciesBicycle || | |
dirtyParams.homeWorkTripModeFrequencies?.bicycle | |
: undefined, | |
carDriver: | |
surveyShortname !== 'od_mtl_2023' | |
? dirtyParams.workCommutingModeFrequenciesCarDriver || | |
dirtyParams.homeWorkTripModeFrequenciesCarDriver || | |
dirtyParams.homeWorkTripModeFrequencies?.CarDriver | |
: undefined, // yes with a capital C! | |
carPassenger: | |
surveyShortname !== 'od_mtl_2023' | |
? dirtyParams.workCommutingModeFrequenciesCarPassenger || | |
dirtyParams.homeWorkTripModeFrequenciesCarPassenger || | |
dirtyParams.homeWorkTripModeFrequencies?.CarPassenger | |
: undefined, // yes with a capital C! | |
transit: | |
surveyShortname !== 'od_mtl_2023' | |
? dirtyParams.workCommutingModeFrequenciesTransit || | |
dirtyParams.homeWorkTripModeFrequenciesTransit || | |
dirtyParams.homeWorkTripModeFrequencies?.transit | |
: undefined, | |
transitBus: | |
surveyShortname !== 'od_mtl_2023' | |
? dirtyParams.workCommutingModeFrequenciesTransitBus || | |
dirtyParams.homeWorkTripModeFrequenciesTransitBus || | |
dirtyParams.homeWorkTripModeFrequencies?.transitBus | |
: undefined, | |
transitSubway: | |
surveyShortname !== 'od_mtl_2023' | |
? dirtyParams.workCommutingModeFrequenciesTransitSubway || | |
dirtyParams.homeWorkTripModeFrequenciesTransitSubway || | |
dirtyParams.homeWorkTripModeFrequencies?.transitSubway | |
: undefined, | |
transitTrainREM: | |
surveyShortname !== 'od_mtl_2023' | |
? dirtyParams.workCommutingModeFrequenciesTransitTrainREM || | |
dirtyParams.homeWorkTripModeFrequenciesTransitTrainREM || | |
dirtyParams.homeWorkTripModeFrequencies?.transitTrainREM | |
: undefined, | |
schoolBus: | |
surveyShortname !== 'od_mtl_2023' | |
? dirtyParams.workCommutingModeFrequenciesSchoolBus || | |
dirtyParams.homeWorkTripModeFrequenciesSchoolBus || | |
dirtyParams.homeWorkTripModeFrequencies?.schoolBus | |
: undefined, | |
taxi: | |
surveyShortname !== 'od_mtl_2023' | |
? dirtyParams.workCommutingModeFrequenciesTaxi || | |
dirtyParams.homeWorkTripModeFrequenciesTaxi || | |
dirtyParams.homeWorkTripModeFrequencies?.taxi | |
: undefined | |
}, | |
workCommutingV2: { | |
walk: | |
surveyShortname === 'od_mtl_2023' | |
? dirtyParams.workCommutingModeFrequenciesWalk || | |
dirtyParams.homeWorkTripModeFrequenciesWalk | |
: undefined, | |
bicycle: | |
surveyShortname === 'od_mtl_2023' | |
? dirtyParams.workCommutingModeFrequenciesBicycle || | |
dirtyParams.homeWorkTripModeFrequenciesBicycle | |
: undefined, | |
carDriver: | |
surveyShortname === 'od_mtl_2023' | |
? dirtyParams.workCommutingModeFrequenciesCarDriver || | |
dirtyParams.homeWorkTripModeFrequenciesCarDriver | |
: undefined, | |
carPassenger: | |
surveyShortname === 'od_mtl_2023' | |
? dirtyParams.workCommutingModeFrequenciesCarPassenger || | |
dirtyParams.homeWorkTripModeFrequenciesCarPassenger | |
: undefined, | |
transit: | |
surveyShortname === 'od_mtl_2023' | |
? dirtyParams.workCommutingModeFrequenciesTransit || | |
dirtyParams.homeWorkTripModeFrequenciesTransit | |
: undefined, | |
transitBus: | |
surveyShortname === 'od_mtl_2023' | |
? dirtyParams.workCommutingModeFrequenciesTransitBus || | |
dirtyParams.homeWorkTripModeFrequenciesTransitBus | |
: undefined, | |
transitSubway: | |
surveyShortname === 'od_mtl_2023' | |
? dirtyParams.workCommutingModeFrequenciesTransitSubway || | |
dirtyParams.homeWorkTripModeFrequenciesTransitSubway | |
: undefined, | |
transitTrainREM: | |
surveyShortname === 'od_mtl_2023' | |
? dirtyParams.workCommutingModeFrequenciesTransitTrainREM || | |
dirtyParams.homeWorkTripModeFrequenciesTransitTrainREM | |
: undefined, | |
schoolBus: | |
surveyShortname === 'od_mtl_2023' | |
? dirtyParams.workCommutingModeFrequenciesSchoolBus || | |
dirtyParams.homeWorkTripModeFrequenciesSchoolBus | |
: undefined, | |
taxi: | |
surveyShortname === 'od_mtl_2023' | |
? dirtyParams.workCommutingModeFrequenciesTaxi || | |
dirtyParams.homeWorkTripModeFrequenciesTaxi | |
: undefined | |
}, | |
schoolCommutingV1: { | |
walk: | |
surveyShortname !== 'od_mtl_2023' | |
? dirtyParams.schoolCommutingModeFrequenciesWalk || | |
dirtyParams.homeSchoolTripModeFrequenciesWalk | |
: undefined, | |
bicycle: | |
surveyShortname !== 'od_mtl_2023' | |
? dirtyParams.schoolCommutingModeFrequenciesBicycle || | |
dirtyParams.homeSchoolTripModeFrequenciesBicycle | |
: undefined, | |
carDriver: | |
surveyShortname !== 'od_mtl_2023' | |
? dirtyParams.schoolCommutingModeFrequenciesCarDriver || | |
dirtyParams.homeSchoolTripModeFrequenciesCarDriver | |
: undefined, | |
carPassenger: | |
surveyShortname !== 'od_mtl_2023' | |
? dirtyParams.schoolCommutingModeFrequenciesCarPassenger || | |
dirtyParams.homeSchoolTripModeFrequenciesCarPassenger | |
: undefined, | |
transit: | |
surveyShortname !== 'od_mtl_2023' | |
? dirtyParams.schoolCommutingModeFrequenciesTransit || | |
dirtyParams.homeSchoolTripModeFrequenciesTransit | |
: undefined, | |
transitBus: | |
surveyShortname !== 'od_mtl_2023' | |
? dirtyParams.schoolCommutingModeFrequenciesTransitBus || | |
dirtyParams.homeSchoolTripModeFrequenciesTransitBus | |
: undefined, | |
transitSubway: | |
surveyShortname !== 'od_mtl_2023' | |
? dirtyParams.schoolCommutingModeFrequenciesTransitSubway || | |
dirtyParams.homeSchoolTripModeFrequenciesTransitSubway | |
: undefined, | |
transitTrainREM: | |
surveyShortname !== 'od_mtl_2023' | |
? dirtyParams.schoolCommutingModeFrequenciesTransitTrainREM || | |
dirtyParams.homeSchoolTripModeFrequenciesTransitTrainREM | |
: undefined, | |
schoolBus: | |
surveyShortname !== 'od_mtl_2023' | |
? dirtyParams.schoolCommutingModeFrequenciesSchoolBus || | |
dirtyParams.homeSchoolTripModeFrequenciesSchoolBus | |
: undefined, | |
taxi: | |
surveyShortname !== 'od_mtl_2023' | |
? dirtyParams.schoolCommutingModeFrequenciesTaxi || | |
dirtyParams.homeSchoolTripModeFrequenciesTaxi | |
: undefined | |
}, | |
schoolCommutingV2: { | |
walk: | |
surveyShortname === 'od_mtl_2023' | |
? dirtyParams.schoolCommutingModeFrequenciesWalk || | |
dirtyParams.homeSchoolTripModeFrequenciesWalk | |
: undefined, | |
bicycle: | |
surveyShortname === 'od_mtl_2023' | |
? dirtyParams.schoolCommutingModeFrequenciesBicycle || | |
dirtyParams.homeSchoolTripModeFrequenciesBicycle | |
: undefined, | |
carDriver: | |
surveyShortname === 'od_mtl_2023' | |
? dirtyParams.schoolCommutingModeFrequenciesCarDriver || | |
dirtyParams.homeSchoolTripModeFrequenciesCarDriver | |
: undefined, | |
carPassenger: | |
surveyShortname === 'od_mtl_2023' | |
? dirtyParams.schoolCommutingModeFrequenciesCarPassenger || | |
dirtyParams.homeSchoolTripModeFrequenciesCarPassenger | |
: undefined, | |
transit: | |
surveyShortname === 'od_mtl_2023' | |
? dirtyParams.schoolCommutingModeFrequenciesTransit || | |
dirtyParams.homeSchoolTripModeFrequenciesTransit | |
: undefined, | |
transitBus: | |
surveyShortname === 'od_mtl_2023' | |
? dirtyParams.schoolCommutingModeFrequenciesTransitBus || | |
dirtyParams.homeSchoolTripModeFrequenciesTransitBus | |
: undefined, | |
transitSubway: | |
surveyShortname === 'od_mtl_2023' | |
? dirtyParams.schoolCommutingModeFrequenciesTransitSubway || | |
dirtyParams.homeSchoolTripModeFrequenciesTransitSubway | |
: undefined, | |
transitTrainREM: | |
surveyShortname === 'od_mtl_2023' | |
? dirtyParams.schoolCommutingModeFrequenciesTransitTrainREM || | |
dirtyParams.homeSchoolTripModeFrequenciesTransitTrainREM | |
: undefined, | |
schoolBus: | |
surveyShortname === 'od_mtl_2023' | |
? dirtyParams.schoolCommutingModeFrequenciesSchoolBus || | |
dirtyParams.homeSchoolTripModeFrequenciesSchoolBus | |
: undefined, | |
taxi: | |
surveyShortname === 'od_mtl_2023' | |
? dirtyParams.schoolCommutingModeFrequenciesTaxi || | |
dirtyParams.homeSchoolTripModeFrequenciesTaxi | |
: undefined | |
} | |
}; | |
// fill out missing aggregated transit if more precise data exists: | |
for (const tripsType in modeFrequencies) { | |
if (modeFrequencies[tripsType].transit === undefined) { | |
if (tripsType.endsWith('V1')) { | |
modeFrequencies[tripsType].transit = PAttr.highestFrequencyV1([ | |
modeFrequencies[tripsType].transitBus, | |
modeFrequencies[tripsType].transitSubway, | |
modeFrequencies[tripsType].transitTrainREM | |
]); | |
} else if (tripsType.endsWith('V2')) { | |
modeFrequencies[tripsType].transit = PAttr.highestFrequencyV2([ | |
modeFrequencies[tripsType].transitBus, | |
modeFrequencies[tripsType].transitSubway, | |
modeFrequencies[tripsType].transitTrainREM | |
]); | |
} | |
} | |
} | |
} | |
return modeFrequencies || dirtyParams.modeFrequencies; | |
} | |
/** | |
* Factory that validates input from an interview and makes | |
* sure types and required fields are valid before returning a new object | |
* @param dirtyParams | |
* @param surveyShortname required for some pre-parsing (like moving/converting mode frequencies) | |
* @param previousDay required to get correct dates to replace 'everyday' in previousWeekDidTripsDay and other questions with dates | |
* @returns Person | Error[] | |
*/ | |
static async create( | |
dirtyParams: { [key: string]: any }, | |
surveyShortname: string, | |
previousDay: Date | string | |
): Promise<Person | Error[]> { | |
// Get validated data, but use original responses for some attributes: | |
const _dirtyParams = _cloneDeep(dirtyParams); | |
dirtyParams.previousWeekDidTripsDays = | |
dirtyParams.previousWeekDidTripsDays !== undefined | |
? dirtyParams.previousWeekDidTripsDays.map((date) => parseDate(date)) | |
: undefined; | |
dirtyParams.previousWeekWentToSchoolOutsideHomeDays = | |
dirtyParams.previousWeekWentToSchoolOutsideHomeDays !== undefined | |
? dirtyParams.previousWeekWentToSchoolOutsideHomeDays.map((date) => parseDate(date)) | |
: undefined; | |
dirtyParams.previousWeekWentToWorkOutsideHomeDays = | |
dirtyParams.previousWeekWentToWorkOutsideHomeDays !== undefined | |
? dirtyParams.previousWeekWentToWorkOutsideHomeDays.map((date) => parseDate(date)) | |
: undefined; | |
dirtyParams.previousWeekWorkingDays = | |
dirtyParams.previousWeekWorkingDays !== undefined | |
? dirtyParams.previousWeekWorkingDays.map((date) => parseDate(date)) | |
: undefined; | |
if (typeof _dirtyParams.hasDisability === 'boolean') { | |
// some surveys have hasDisability as a boolean | |
_dirtyParams.hasDisability = | |
_dirtyParams.hasDisability === true ? 'yes' : _dirtyParams.hasDisability === false ? 'no' : undefined; | |
} | |
// convert null values to undefined: | |
convertNullToUndefined(_dirtyParams); | |
// convert strings to numbers: | |
const numberTypeAttributes = ['age']; | |
for (let i = 0, count = numberTypeAttributes.length; i < count; i++) { | |
const attribute = numberTypeAttributes[i]; | |
_dirtyParams[attribute] = convertStringsToNumbers(_dirtyParams[attribute]); | |
} | |
// convert ageIsApproximate to boolean: TODO: test | |
if (_dirtyParams.ageIsApproximate !== undefined) { | |
_dirtyParams.ageIsApproximate = _dirtyParams.ageIsApproximate === 'yes'; | |
} else { | |
_dirtyParams.ageIsApproximate = false; | |
} | |
// convert and move mode frequencies to normalized object, with V1 and V2 frequency choices: | |
const modeFrequencies = Person.moveModeFrequencies(_dirtyParams, surveyShortname); | |
_dirtyParams.modeFrequencies = modeFrequencies; | |
// fix typo in educational attainment: | |
if (_dirtyParams.educationalAttainment === 'diplomaBellowBachelor') { | |
_dirtyParams.educationalAttainment = 'diplomaBelowBachelor'; | |
} | |
// convert noSchoolTripReason and noWorkTripReason to v1 or v2 | |
if (['od_mtl_pilote_2021', 'od_mtl_pilote_2022'].includes(surveyShortname)) { | |
_dirtyParams.noSchoolTripReasonV1 = _dirtyParams.noSchoolTripReason; | |
_dirtyParams.noSchoolTripReasonV2 = undefined; | |
_dirtyParams.noWorkTripReasonV1 = _dirtyParams.noWorkTripReason; | |
_dirtyParams.noWorkTripReasonV2 = undefined; | |
} else if (['od_mtl_2023', 'od_qc_2023'].includes(surveyShortname)) { | |
_dirtyParams.noSchoolTripReasonV2 = _dirtyParams.noSchoolTripReason; | |
_dirtyParams.noSchoolTripReasonV1 = undefined; | |
_dirtyParams.noWorkTripReasonV2 = _dirtyParams.noWorkTripReason; | |
_dirtyParams.noWorkTripReasonV1 = undefined; | |
} | |
delete _dirtyParams.noSchoolTripReason; | |
delete _dirtyParams.noWorkTripReason; | |
// convert parentConsent to string (od_qc_2023 only): | |
if (_dirtyParams.parentConsent) { | |
if (_dirtyParams.parentConsent === -1) { | |
_dirtyParams.parentConsent = 'parentNotAvailable'; | |
} else if (_dirtyParams.parentConsent === 0) { | |
_dirtyParams.parentConsent = 'parentAvailable'; | |
} else if (_dirtyParams.parentConsent === 1) { | |
_dirtyParams.parentConsent = 'parentAlreadyThere'; | |
} else { | |
_dirtyParams.parentConsent = undefined; | |
} | |
} | |
// fix typos in attribute names: | |
if ( | |
_dirtyParams.doesNotStudiesFromFixedLocationReason !== undefined && | |
_dirtyParams.doesNotStudyFromFixedLocationReason === undefined | |
) { | |
_dirtyParams.doesNotStudyFromFixedLocationReason = _dirtyParams.doesNotStudiesFromFixedLocationReason; | |
delete _dirtyParams.doesNotStudiesFromFixedLocationReason; | |
} | |
const previousDayMoment = previousDay !== undefined ? moment(parseDate(previousDay)) : undefined; // we assume previousDay is a valid date | |
// convert some arrays created from previous day to date[]: | |
const stringDateAttributes = [ | |
'previousWeekDidTripsDays', | |
'previousWeekWentToSchoolOutsideHomeDays', | |
'previousWeekWentToWorkOutsideHomeDays', | |
'previousWeekWorkingDays' | |
]; | |
for (let attributeI = 0; attributeI < stringDateAttributes.length; attributeI++) { | |
const attribute = stringDateAttributes[attributeI]; | |
const value = _dirtyParams[attribute]; | |
// TODO: add more testing or a try catch to make sure it works even with bad data | |
if (previousDayMoment && value !== undefined && Array.isArray(value)) { | |
if (value.length === 1 && value[0] === 'none') { | |
_dirtyParams[attribute] = []; | |
} else if (value.length === 1 && value[0] === 'everyday') { | |
_dirtyParams[attribute] = []; | |
for (let i = 6; i >= 0; i--) { | |
_dirtyParams[attribute].push(previousDayMoment.clone().subtract(i, 'days').toDate()); | |
} | |
} else if (value.length > 1) { | |
for (let i = 0; i < value.length; i++) { | |
const date = new Date(value[i] + 'T00:00:00'); | |
if (!(date instanceof Date) || isNaN(date.getDate())) { | |
_dirtyParams[attribute].push(new Date(value[i] + 'T00:00:00')); | |
} | |
} | |
} | |
} | |
} | |
// move transitFares to transitPassTypes (od_qc_2023) or transitFaresUsed (od_mtl_ete_2023) | |
if (surveyShortname === 'od_qc_2023' && _dirtyParams.transitFares !== undefined) { | |
_dirtyParams.transitPassTypes = _dirtyParams.transitFares; | |
} else if (surveyShortname === 'od_mtl_ete_2023' && _dirtyParams.transitFares !== undefined) { | |
_dirtyParams.transitFaresUsed = _dirtyParams.transitFares; | |
} | |
delete _dirtyParams.transitFares; | |
// correct useParaTransit: | |
if (_dirtyParams.useParatransit !== undefined) { | |
// there was an incorrect labelling in od_mtl_ete_2023: | |
if (surveyShortname === 'od_mtl_ete_2023' && _dirtyParams.useParatransit === 'dontKnow') { | |
_dirtyParams.useParatransit = 'preferNotToAnswer'; | |
} | |
} | |
const errors: Error[] = []; | |
const workPlaces: BasePlace[] = []; | |
const schoolPlaces: BasePlace[] = []; | |
// move and homogenize usual school and work places: | |
const usualSchoolPlaceDirtyParams: BasePlaceAttributes = { | |
geography: undefined, | |
name: undefined, | |
lastAction: undefined, | |
geocodingQueryString: undefined, | |
deviceUsed: undefined, | |
zoom: undefined | |
}; | |
let usualSchoolPlaceParamsGeography: GeoJSON.Feature<GeoJSON.Point, { [key: string]: any }> | undefined = | |
undefined; | |
if (_dirtyParams.usualSchoolPlace?.geometry) { | |
usualSchoolPlaceParamsGeography = _dirtyParams.usualSchoolPlace; | |
} else if (_dirtyParams.usualSchoolPlace?.geography) { | |
usualSchoolPlaceParamsGeography = _dirtyParams.usualSchoolPlace.geography; | |
} else if (_dirtyParams.usualStudyPlaceNameGeographie) { | |
usualSchoolPlaceParamsGeography = _dirtyParams.usualStudyPlaceNameGeographie; | |
} | |
if (usualSchoolPlaceParamsGeography) { | |
usualSchoolPlaceDirtyParams.geography = usualSchoolPlaceParamsGeography; | |
if (usualSchoolPlaceDirtyParams.geography?.properties === undefined) { | |
usualSchoolPlaceDirtyParams.geography.properties = {}; | |
} | |
usualSchoolPlaceDirtyParams.name = | |
_dirtyParams.usualSchoolPlaceName || | |
_dirtyParams.usualSchoolPlace?.name || | |
_dirtyParams.usualStudyPlaceName; | |
usualSchoolPlaceDirtyParams.lastAction = usualSchoolPlaceParamsGeography.properties?.lastAction; | |
usualSchoolPlaceDirtyParams.geocodingQueryString = | |
usualSchoolPlaceParamsGeography.properties?.geocodingQueryString; | |
usualSchoolPlaceDirtyParams.deviceUsed = usualSchoolPlaceParamsGeography.properties?.platform; | |
usualSchoolPlaceDirtyParams.zoom = usualSchoolPlaceParamsGeography.properties?.zoom; | |
if (usualSchoolPlaceParamsGeography.properties?.geocodingResultsData) { | |
if (!usualSchoolPlaceDirtyParams.geography.properties) { | |
usualSchoolPlaceDirtyParams.geography.properties = {}; | |
} | |
usualSchoolPlaceDirtyParams.geography.properties.googleFormattedAddress = | |
usualSchoolPlaceParamsGeography.properties.geocodingResultsData.formatted_address; | |
usualSchoolPlaceDirtyParams.geography.properties.googleTypes = | |
usualSchoolPlaceParamsGeography.properties.geocodingResultsData.types; | |
usualSchoolPlaceDirtyParams.geography.properties.googlePlaceId = | |
usualSchoolPlaceParamsGeography.properties.geocodingResultsData.place_id; | |
usualSchoolPlaceDirtyParams.geography.properties.googlePlaceName = | |
usualSchoolPlaceParamsGeography.properties.geocodingResultsData.name; | |
delete usualSchoolPlaceDirtyParams.geography.properties.geocodingResultsData; | |
} | |
if (usualSchoolPlaceDirtyParams && usualSchoolPlaceDirtyParams.geography) { | |
errors.push(...BasePlace.validateParams(usualSchoolPlaceDirtyParams)); | |
if (errors.length === 0) { | |
schoolPlaces.push(new BasePlace(usualSchoolPlaceDirtyParams)); | |
} | |
} | |
} | |
const usualWorkPlaceDirtyParams: BasePlaceAttributes = { | |
geography: undefined, | |
name: undefined, | |
lastAction: undefined, | |
geocodingQueryString: undefined, | |
deviceUsed: undefined, | |
zoom: undefined | |
}; | |
let usualWorkPlaceParamsGeography: GeoJSON.Feature<GeoJSON.Point, { [key: string]: any }> | undefined = | |
undefined; | |
if (_dirtyParams.usualWorkPlace?.geometry) { | |
usualWorkPlaceParamsGeography = _dirtyParams.usualWorkPlace; | |
} else if (_dirtyParams.usualWorkPlace?.geography) { | |
usualWorkPlaceParamsGeography = _dirtyParams.usualWorkPlace.geography; | |
} else if (_dirtyParams.usualWorkPlaceNameGeographie) { | |
usualWorkPlaceParamsGeography = _dirtyParams.usualWorkPlaceNameGeographie; | |
} | |
if (usualWorkPlaceParamsGeography) { | |
usualWorkPlaceDirtyParams.geography = usualWorkPlaceParamsGeography; | |
if (usualWorkPlaceDirtyParams.geography?.properties === undefined) { | |
usualWorkPlaceDirtyParams.geography.properties = {}; | |
} | |
usualWorkPlaceDirtyParams.name = | |
_dirtyParams.usualWorkPlaceName || | |
_dirtyParams.usualWorkPlace?.name || | |
_dirtyParams.usualStudyPlaceName; | |
usualWorkPlaceDirtyParams.lastAction = usualWorkPlaceParamsGeography.properties?.lastAction; | |
usualWorkPlaceDirtyParams.geocodingQueryString = | |
usualWorkPlaceParamsGeography.properties?.geocodingQueryString; | |
usualWorkPlaceDirtyParams.deviceUsed = usualWorkPlaceParamsGeography.properties?.platform; | |
usualWorkPlaceDirtyParams.zoom = usualWorkPlaceParamsGeography.properties?.zoom; | |
if (usualWorkPlaceParamsGeography.properties?.geocodingResultsData) { | |
if (!usualWorkPlaceDirtyParams.geography.properties) { | |
usualWorkPlaceDirtyParams.geography.properties = {}; | |
} | |
usualWorkPlaceDirtyParams.geography.properties.googleFormattedAddress = | |
usualWorkPlaceParamsGeography.properties.geocodingResultsData.formatted_address; | |
usualWorkPlaceDirtyParams.geography.properties.googleTypes = | |
usualWorkPlaceParamsGeography.properties.geocodingResultsData.types; | |
usualWorkPlaceDirtyParams.geography.properties.googlePlaceId = | |
usualWorkPlaceParamsGeography.properties.geocodingResultsData.place_id; | |
usualWorkPlaceDirtyParams.geography.properties.googlePlaceName = | |
usualWorkPlaceParamsGeography.properties.geocodingResultsData.name; | |
delete usualWorkPlaceDirtyParams.geography.properties.geocodingResultsData; | |
} | |
if (usualWorkPlaceDirtyParams && usualWorkPlaceDirtyParams.geography) { | |
errors.push(...BasePlace.validateParams(usualWorkPlaceDirtyParams)); | |
if (errors.length === 0) { | |
workPlaces.push(new BasePlace(usualWorkPlaceDirtyParams)); | |
} | |
} | |
} | |
// generate departurePlaceIsHome from od_mtl_pilote_2021 departurePlaceType | |
if ( | |
surveyShortname === 'od_mtl_pilote_2021' && | |
_dirtyParams.departurePlaceType !== undefined && | |
_dirtyParams.departurePlaceIsHome === undefined | |
) { | |
if (_dirtyParams.departurePlaceType === 'home') { | |
_dirtyParams.departurePlaceIsHome = 'yes'; | |
delete _dirtyParams.departurePlaceType; | |
} else if (_dirtyParams.departurePlaceType === 'other') { | |
_dirtyParams.departurePlaceIsHome = 'no'; | |
delete _dirtyParams.departurePlaceType; | |
} | |
} | |
// generate personDidTrips from od_mtl_pilote_2021 didTripsOnTripsDate | |
if ( | |
surveyShortname === 'od_mtl_pilote_2021' && | |
_dirtyParams.didTripsOnTripsDate !== undefined && | |
_dirtyParams.personDidTrips === undefined | |
) { | |
if (_dirtyParams.didTripsOnTripsDate === 'yes') { | |
_dirtyParams.personDidTrips = 'yes'; | |
delete _dirtyParams.didTripsOnTripsDate; | |
} else if (_dirtyParams.didTripsOnTripsDate === 'no') { | |
_dirtyParams.personDidTrips = 'no'; | |
delete _dirtyParams.didTripsOnTripsDate; | |
} else if (_dirtyParams.didTripsOnTripsDate === 'dontKnow') { | |
_dirtyParams.personDidTrips = 'dontKnow'; | |
delete _dirtyParams.didTripsOnTripsDate; | |
} | |
} | |
// convert bixi usage to new version: | |
if (_dirtyParams['bixiBikesharingUsage_NewOptions2023-10-18'] !== undefined) { | |
_dirtyParams.bixiBikesharingUsageV2 = _dirtyParams['bixiBikesharingUsage_NewOptions2023-10-18']; | |
} | |
delete _dirtyParams['bixiBikesharingUsage_NewOptions2023-10-18']; | |
if (_dirtyParams.bixiBikesharingUsage !== undefined) { | |
if (['seasonal', 'monthly', 'subscriptionWithPay'].includes(_dirtyParams.bixiBikesharingUsage)) { | |
_dirtyParams.bixiBikesharingUsageV2 = 'monthlySeasonalAnnual'; | |
} else if (['noSubscription'].includes(_dirtyParams.bixiBikesharingUsage)) { | |
_dirtyParams.bixiBikesharingUsageV2 = 'payPerTrip'; | |
} | |
} | |
// fix missing lowercase for supportAndClericalStaff | |
if (_dirtyParams.jobCategory === 'SupportAndClericalStaff') { | |
_dirtyParams.jobCategory = 'supportAndClericalStaff'; | |
} | |
// convert daysAtOfficePerWeek fron number to string | |
if (_dirtyParams.daysAtOfficePerWeek !== undefined) { | |
if (_dirtyParams.daysAtOfficePerWeek < 0 || _dirtyParams.daysAtOfficePerWeek > 5) { | |
_dirtyParams.daysAtOfficePerWeek = undefined; | |
} | |
if (_dirtyParams.daysAtOfficePerWeek === 0) { | |
_dirtyParams.daysAtOfficePerWeek = 'lessThan1'; | |
} else if (_dirtyParams.daysAtOfficePerWeek >= 1 && _dirtyParams.daysAtOfficePerWeek < 5) { | |
_dirtyParams.daysAtOfficePerWeek = _dirtyParams.daysAtOfficePerWeek.toString(); | |
} else if (_dirtyParams.daysAtOfficePerWeek === 5) { | |
_dirtyParams.daysAtOfficePerWeek = '5+'; | |
} | |
} | |
// convert occupations: | |
_dirtyParams.occupationV1 = undefined; | |
_dirtyParams.occupationV2 = undefined; | |
_dirtyParams.occupationV3 = undefined; | |
_dirtyParams.occupationQC = undefined; | |
if ( | |
(surveyShortname === 'od_mtl_2023' || surveyShortname === 'od_mtl_ete_2023') && | |
_dirtyParams.occupation !== undefined | |
) { | |
_dirtyParams.occupationV3 = _dirtyParams.occupation; | |
delete _dirtyParams.occupation; | |
} else if (surveyShortname === 'od_mtl_pilote_2021' && _dirtyParams.occupation !== undefined) { | |
_dirtyParams.occupationV1 = _dirtyParams.occupation; | |
delete _dirtyParams.occupation; | |
} else if (surveyShortname === 'od_mtl_pilote_2022' && _dirtyParams.occupation !== undefined) { | |
_dirtyParams.occupationV2 = _dirtyParams.occupation; | |
delete _dirtyParams.occupation; | |
} else if (surveyShortname === 'od_qc_2023' && _dirtyParams.occupation !== undefined) { | |
_dirtyParams.occupationQC = _dirtyParams.occupation; | |
delete _dirtyParams.occupation; | |
} | |
// convert transitPasses: | |
_dirtyParams.transitPassesV1 = undefined; | |
_dirtyParams.transitPassesV2 = undefined; | |
_dirtyParams.transitPassesQC = undefined; | |
if (_dirtyParams.transitPasses !== undefined && Array.isArray(_dirtyParams.transitPasses)) { | |
if ( | |
surveyShortname === 'od_mtl_2023' || | |
surveyShortname === 'od_mtl_ete_2023' || | |
surveyShortname === 'od_mtl_pilote_2022' | |
) { | |
_dirtyParams.transitPassesV2 = _dirtyParams.transitPasses; | |
delete _dirtyParams.transitPasses; | |
} else if (surveyShortname === 'od_mtl_pilote_2021') { | |
_dirtyParams.transitPassesV1 = _dirtyParams.transitPasses; | |
delete _dirtyParams.transitPasses; | |
} else if (surveyShortname === 'od_qc_2023') { | |
_dirtyParams.transitPassesQC = _dirtyParams.transitPasses; | |
delete _dirtyParams.transitPasses; | |
} | |
} | |
// fix typos in short section did trips: | |
if ( | |
_dirtyParams.shortTripSectionDidTripOnTripsDate !== undefined && | |
_dirtyParams.shortTripSectionDidTripsOnTripsDate === undefined | |
) { | |
_dirtyParams.shortTripSectionDidTripsOnTripsDate = _dirtyParams.shortTripSectionDidTripOnTripsDate; | |
delete _dirtyParams.shortTripSectionDidTripOnTripsDate; | |
} | |
if ( | |
_dirtyParams.shortTripSectionDidTripToUsualSchoolPlaceOnTripsDate !== undefined && | |
_dirtyParams.shortTripSectionDidTripsToUsualSchoolPlaceOnTripsDate === undefined | |
) { | |
_dirtyParams.shortTripSectionDidTripsToUsualSchoolPlaceOnTripsDate = | |
_dirtyParams.shortTripSectionDidTripToUsualSchoolPlaceOnTripsDate; | |
delete _dirtyParams.shortTripSectionDidTripToUsualSchoolPlaceOnTripsDate; | |
} | |
if ( | |
_dirtyParams.shortTripSectionDidTripToUsualWorkPlaceOnTripsDate !== undefined && | |
_dirtyParams.shortTripSectionDidTripsToUsualWorkPlaceOnTripsDate === undefined | |
) { | |
_dirtyParams.shortTripSectionDidTripsToUsualWorkPlaceOnTripsDate = | |
_dirtyParams.shortTripSectionDidTripToUsualWorkPlaceOnTripsDate; | |
delete _dirtyParams.shortTripSectionDidTripToUsualWorkPlaceOnTripsDate; | |
} | |
// fix wrong label in od_mtl_2023 for useParatransit: | |
if (surveyShortname === 'od_mtl_2023' && _dirtyParams.useParatransit === 'dontKnow') { | |
_dirtyParams.useParatransit = 'preferNotToAnswer'; | |
} | |
// remove usual places, trips and visited places from params (will be created separately): | |
delete _dirtyParams.trips; | |
delete _dirtyParams.visitedPlaces; | |
delete _dirtyParams.schoolPlaces; | |
delete _dirtyParams.workPlaces; | |
// validate params for both interview and baseInterview: | |
errors.push(...BasePerson.validateParams(_dirtyParams), ...Person.validateParams(_dirtyParams)); | |
if (errors.length > 0) { | |
return errors; | |
} else { | |
const basePerson = BasePerson.create(_dirtyParams) as BasePerson; | |
const person = new Person({ basePerson, ..._dirtyParams } as { basePerson: BasePerson } & PersonAttributes); | |
person.workPlaces = workPlaces; | |
person.schoolPlaces = schoolPlaces; | |
await parser(person); | |
return person; | |
} | |
} | |
/** | |
* Validates attribute types of params: | |
* @param dirtyParams The parameters to validate. | |
* @returns Error[] TODO: specialize this error class | |
*/ | |
static validateParams(dirtyParams: { [key: string]: any }): Error[] { | |
const errors: Error[] = []; | |
errors.push( | |
...ParamsValidatorTools.isInstanceOf('basePerson', dirtyParams.basePerson, displayName, BasePerson) | |
); | |
errors.push( | |
...ParamsValidatorTools.isBoolean( | |
'_completedSections.profile', | |
dirtyParams._completedSections?.profile, | |
displayName | |
) | |
); | |
errors.push( | |
...ParamsValidatorTools.isBoolean( | |
'_completedSections.segments', | |
dirtyParams._completedSections?.segments, | |
displayName | |
) | |
); | |
errors.push( | |
...ParamsValidatorTools.isBoolean( | |
'_completedSections.travelBehavior', | |
dirtyParams._completedSections?.travelBehavior, | |
displayName | |
) | |
); | |
errors.push( | |
...ParamsValidatorTools.isBoolean( | |
'_completedSections.tripsIntro', | |
dirtyParams._completedSections?.tripsIntro, | |
displayName | |
) | |
); | |
errors.push( | |
...ParamsValidatorTools.isBoolean( | |
'_completedSections.visitedPlaces', | |
dirtyParams._completedSections?.visitedPlaces, | |
displayName | |
) | |
); | |
errors.push(...ParamsValidatorTools.isRequired('_sequence', dirtyParams._sequence, displayName)); | |
errors.push(...ParamsValidatorTools.isPositiveInteger('_sequence', dirtyParams._sequence, displayName)); | |
errors.push(...ParamsValidatorTools.isBoolean('ageIsApproximate', dirtyParams.ageIsApproximate, displayName)); | |
errors.push( | |
...ParamsValidatorTools.isString('bixiBikesharingUsage', dirtyParams.bixiBikesharingUsage, displayName) | |
); | |
errors.push( | |
...ParamsValidatorTools.isString( | |
'bixiBikesharingUsage_NewOptions2023-10-18', | |
dirtyParams['bixiBikesharingUsage_NewOptions2023-10-18'], | |
displayName | |
) | |
); | |
errors.push( | |
...ParamsValidatorTools.isString('bixiBikesharingUsageV2', dirtyParams.bixiBikesharingUsageV2, displayName) | |
); | |
errors.push(...ParamsValidatorTools.isString('bikeOwnership', dirtyParams.bikeOwnership, displayName)); | |
errors.push( | |
...ParamsValidatorTools.isString('drivingLicenseOwner', dirtyParams.drivingLicenseOwner, displayName) | |
); | |
errors.push(...ParamsValidatorTools.isString('transitPassOwner', dirtyParams.transitPassOwner, displayName)); | |
errors.push( | |
...ParamsValidatorTools.isString( | |
'communautoFlexCarsharingUsage', | |
dirtyParams.communautoFlexCarsharingUsage, | |
displayName | |
) | |
); | |
errors.push(...ParamsValidatorTools.isString('canRemoteWork', dirtyParams.canRemoteWork, displayName)); | |
errors.push( | |
...ParamsValidatorTools.isString('daysAtOfficePerWeek', dirtyParams.daysAtOfficePerWeek, displayName) | |
); | |
errors.push( | |
...ParamsValidatorTools.isString('departurePlaceIsHome', dirtyParams.departurePlaceIsHome, displayName) | |
); | |
errors.push( | |
...ParamsValidatorTools.isString( | |
'departurePlaceIsHomeConfirm', | |
dirtyParams.departurePlaceIsHomeConfirm, | |
displayName | |
) | |
); | |
errors.push( | |
...ParamsValidatorTools.isString('departurePlaceOther', dirtyParams.departurePlaceOther, displayName) | |
); | |
errors.push( | |
...ParamsValidatorTools.isString('departurePlaceType', dirtyParams.departurePlaceType, displayName) | |
); | |
errors.push( | |
...ParamsValidatorTools.isString('didTripsOnTripsDate', dirtyParams.didTripsOnTripsDate, displayName) | |
); | |
errors.push(...ParamsValidatorTools.isArrayOfStrings('disabilities', dirtyParams.disabilities, displayName)); | |
errors.push( | |
...ParamsValidatorTools.isString('disabilitiesComments', dirtyParams.disabilitiesComments, displayName) | |
); | |
errors.push( | |
...ParamsValidatorTools.isString( | |
'doesNotStudiesFromFixedLocationReason', | |
dirtyParams.doesNotStudiesFromFixedLocationReason, | |
displayName | |
) | |
); | |
errors.push( | |
...ParamsValidatorTools.isString( | |
'doesNotStudyFromFixedLocationReason', | |
dirtyParams.doesNotStudyFromFixedLocationReason, | |
displayName | |
) | |
); | |
errors.push( | |
...ParamsValidatorTools.isString('educationalAttainment', dirtyParams.educationalAttainment, displayName) | |
); | |
errors.push( | |
...ParamsValidatorTools.isString('electricBikeOwnership', dirtyParams.electricBikeOwnership, displayName) | |
); | |
errors.push(...ParamsValidatorTools.isString('enrolledInSchool', dirtyParams.enrolledInSchool, displayName)); | |
errors.push( | |
...ParamsValidatorTools.isString( | |
'everUsedBixiBikesharingServices', | |
dirtyParams.everUsedBixiBikesharingServices, | |
displayName | |
) | |
); | |
errors.push( | |
...ParamsValidatorTools.isString( | |
'everUsedCommunautoFlexCarsharingServicesAsADriver', | |
dirtyParams.everUsedCommunautoFlexCarsharingServicesAsADriver, | |
displayName | |
) | |
); | |
errors.push( | |
...ParamsValidatorTools.isString('freeParkingAtSchool', dirtyParams.freeParkingAtSchool, displayName) | |
); | |
errors.push(...ParamsValidatorTools.isString('freeParkingAtWork', dirtyParams.freeParkingAtWork, displayName)); | |
errors.push(...ParamsValidatorTools.isString('genderCustom', dirtyParams.genderCustom, displayName)); | |
errors.push(...ParamsValidatorTools.isString('genderSpecify', dirtyParams.genderSpecify, displayName)); | |
errors.push(...ParamsValidatorTools.isString('hasDisability', dirtyParams.hasDisability, displayName)); | |
errors.push( | |
...ParamsValidatorTools.isBoolean( | |
'hasOmittedActiveModesTrips', | |
dirtyParams.hasOmittedActiveModesTrips, | |
displayName | |
) | |
); | |
errors.push( | |
...ParamsValidatorTools.isBoolean('hasUsualSchoolPlace', dirtyParams.hasUsualSchoolPlace, displayName) | |
); | |
errors.push(...ParamsValidatorTools.isBoolean('hasUsualWorkPlace', dirtyParams.hasUsualWorkPlace, displayName)); | |
errors.push(...ParamsValidatorTools.isString('job', dirtyParams.job, displayName)); | |
errors.push(...ParamsValidatorTools.isString('jobActivitySector', dirtyParams.jobActivitySector, displayName)); | |
errors.push(...ParamsValidatorTools.isString('jobCategory', dirtyParams.jobCategory, displayName)); | |
errors.push( | |
...ParamsValidatorTools.isString( | |
'jobCompatibleWithTelecommuting', | |
dirtyParams.jobCompatibleWithTelecommuting, | |
displayName | |
) | |
); | |
errors.push( | |
...ParamsValidatorTools.isString('jobHoursFlexibility', dirtyParams.jobHoursFlexibility, displayName) | |
); | |
errors.push( | |
...ParamsValidatorTools.isString('jobHoursSchedulesType', dirtyParams.jobHoursSchedulesType, displayName) | |
); | |
errors.push(...ParamsValidatorTools.isString('jobType', dirtyParams.jobType, displayName)); | |
errors.push( | |
...ParamsValidatorTools.isArrayOfStrings( | |
'mobilityAssistiveDevices', | |
dirtyParams.mobilityAssistiveDevices, | |
displayName | |
) | |
); | |
errors.push( | |
...ParamsValidatorTools.isString( | |
'mobilityAssistiveDevicesSpecify', | |
dirtyParams.mobilityAssistiveDevicesSpecify, | |
displayName | |
) | |
); | |
errors.push( | |
...ParamsValidatorTools.isString( | |
'mostUsedMobilityAssistiveDevice', | |
dirtyParams.mostUsedMobilityAssistiveDevice, | |
displayName | |
) | |
); | |
// ignore nickname altogether | |
errors.push( | |
...ParamsValidatorTools.isString('noSchoolTripReasonV1', dirtyParams.noSchoolTripReasonV1, displayName) | |
); | |
errors.push( | |
...ParamsValidatorTools.isString('noSchoolTripReasonV2', dirtyParams.noSchoolTripReasonV2, displayName) | |
); | |
errors.push( | |
...ParamsValidatorTools.isString( | |
'noSchoolTripReasonSpecify', | |
dirtyParams.noSchoolTripReasonSpecify, | |
displayName | |
) | |
); | |
errors.push( | |
...ParamsValidatorTools.isString( | |
'noUsualSchoolPlaceReason', | |
dirtyParams.noUsualSchoolPlaceReason, | |
displayName | |
) | |
); | |
errors.push( | |
...ParamsValidatorTools.isString('noUsualWorkPlaceReason', dirtyParams.noUsualWorkPlaceReason, displayName) | |
); | |
errors.push( | |
...ParamsValidatorTools.isString('noWorkTripReasonV1', dirtyParams.noWorkTripReasonV1, displayName) | |
); | |
errors.push( | |
...ParamsValidatorTools.isString('noWorkTripReasonV2', dirtyParams.noWorkTripReasonV2, displayName) | |
); | |
errors.push( | |
...ParamsValidatorTools.isString( | |
'noWorkTripReasonSpecify', | |
dirtyParams.noWorkTripReasonSpecify, | |
displayName | |
) | |
); | |
errors.push( | |
...ParamsValidatorTools.isString( | |
'noWorkOrStudyTripReason', | |
dirtyParams.noWorkOrStudyTripReason, | |
displayName | |
) | |
); | |
errors.push(...ParamsValidatorTools.isString('occupationV1', dirtyParams.occupationV1, displayName)); | |
errors.push(...ParamsValidatorTools.isString('occupationV2', dirtyParams.occupationV2, displayName)); | |
errors.push(...ParamsValidatorTools.isString('occupationV3', dirtyParams.occupationV3, displayName)); | |
errors.push(...ParamsValidatorTools.isString('occupationQC', dirtyParams.occupationQC, displayName)); | |
errors.push(...ParamsValidatorTools.isString('occupationSpecify', dirtyParams.occupationSpecify, displayName)); | |
errors.push(...ParamsValidatorTools.isString('parentConsent', dirtyParams.parentConsent, displayName)); | |
errors.push(...ParamsValidatorTools.isBoolean('consentConfirm', dirtyParams.consentConfirm, displayName)); | |
errors.push(...ParamsValidatorTools.isString('personDidTrips', dirtyParams.personDidTrips, displayName)); | |
errors.push( | |
...ParamsValidatorTools.isString( | |
'personDidTripsChangeConfirm', | |
dirtyParams.personDidTripsChangeConfirm, | |
displayName | |
) | |
); | |
errors.push( | |
...ParamsValidatorTools.isArrayOf( | |
'previousWeekDidTripsDays', | |
dirtyParams.previousWeekDidTripsDays, | |
displayName, | |
Date | |
) | |
); | |
errors.push( | |
...ParamsValidatorTools.isArrayOfStrings( | |
'previousWeekNoWorkingDaysReasons', | |
dirtyParams.previousWeekNoWorkingDaysReasons, | |
displayName | |
) | |
); | |
errors.push( | |
...ParamsValidatorTools.isArrayOf( | |
'previousWeekWentToSchoolOutsideHomeDays', | |
dirtyParams.previousWeekWentToSchoolOutsideHomeDays, | |
displayName, | |
Date | |
) | |
); | |
errors.push( | |
...ParamsValidatorTools.isArrayOf( | |
'previousWeekWentToWorkOutsideHomeDays', | |
dirtyParams.previousWeekWentToWorkOutsideHomeDays, | |
displayName, | |
Date | |
) | |
); | |
errors.push( | |
...ParamsValidatorTools.isArrayOf( | |
'previousWeekWorkingDays', | |
dirtyParams.previousWeekWorkingDays, | |
displayName, | |
Date | |
) | |
); | |
//errors.push(...ParamsValidatorTools.isString('refuseAge', dirtyParams.refuseAge, displayName)); // ignore, implicit if ageGroup is set | |
errors.push( | |
...ParamsValidatorTools.isArrayOfStrings('remoteStudyDays', dirtyParams.remoteStudyDays, displayName) | |
); | |
errors.push( | |
...ParamsValidatorTools.isArrayOfStrings('remoteWorkDays', dirtyParams.remoteWorkDays, displayName) | |
); | |
errors.push(...ParamsValidatorTools.isString('schoolType', dirtyParams.schoolType, displayName)); | |
errors.push( | |
...ParamsValidatorTools.isString( | |
'shortTripSectionDidSchoolTripsOnTripsDate', | |
dirtyParams.shortTripSectionDidSchoolTripsOnTripsDate, | |
displayName | |
) | |
); | |
errors.push( | |
...ParamsValidatorTools.isString( | |
'shortTripSectionDidTripsOnTripsDate', | |
dirtyParams.shortTripSectionDidTripsOnTripsDate, | |
displayName | |
) | |
); | |
errors.push( | |
...ParamsValidatorTools.isString( | |
'shortTripSectionDidTripsToUsualSchoolPlaceOnTripsDate', | |
dirtyParams.shortTripSectionDidTripsToUsualSchoolPlaceOnTripsDate, | |
displayName | |
) | |
); | |
errors.push( | |
...ParamsValidatorTools.isString( | |
'shortTripSectionDidTripsToUsualWorkPlaceOnTripsDate', | |
dirtyParams.shortTripSectionDidTripsToUsualWorkPlaceOnTripsDate, | |
displayName | |
) | |
); | |
errors.push( | |
...ParamsValidatorTools.isString( | |
'shortTripSectionDidWorkTripsOnTripsDate', | |
dirtyParams.shortTripSectionDidWorkTripsOnTripsDate, | |
displayName | |
) | |
); | |
errors.push(...ParamsValidatorTools.isString('studentType', dirtyParams.studentType, displayName)); | |
errors.push( | |
...ParamsValidatorTools.isString( | |
'studiesFromFixedLocation', | |
dirtyParams.studiesFromFixedLocation, | |
displayName | |
) | |
); | |
errors.push( | |
...ParamsValidatorTools.isArrayOfStrings('transitPassTypes', dirtyParams.transitPassTypes, displayName) | |
); | |
errors.push( | |
...ParamsValidatorTools.isArrayOfStrings('transitFaresUsed', dirtyParams.transitFaresUsed, displayName) | |
); | |
errors.push( | |
...ParamsValidatorTools.isArrayOfStrings('transitPassesV1', dirtyParams.transitPassesV1, displayName) | |
); | |
errors.push( | |
...ParamsValidatorTools.isArrayOfStrings('transitPassesV2', dirtyParams.transitPassesV2, displayName) | |
); | |
errors.push( | |
...ParamsValidatorTools.isArrayOfStrings('transitPassesQC', dirtyParams.transitPassesQC, displayName) | |
); | |
errors.push( | |
...ParamsValidatorTools.isString('transitPassSpecify', dirtyParams.transitPassSpecify, displayName) | |
); | |
errors.push( | |
...ParamsValidatorTools.isArrayOfStrings('travelToStudyDays', dirtyParams.travelToStudyDays, displayName) | |
); | |
errors.push( | |
...ParamsValidatorTools.isArrayOfStrings('travelToWorkDays', dirtyParams.travelToWorkDays, displayName) | |
); | |
errors.push( | |
...ParamsValidatorTools.isString( | |
'useBikeForUtilitarianTravel', | |
dirtyParams.useBikeForUtilitarianTravel, | |
displayName | |
) | |
); | |
errors.push( | |
...ParamsValidatorTools.isString( | |
'usedBixiBikesharingServicesInLast30Days', | |
dirtyParams.usedBixiBikesharingServicesInLast30Days, | |
displayName | |
) | |
); | |
errors.push( | |
...ParamsValidatorTools.isString( | |
'usedBixiBikesharingServicesInLast6Months', | |
dirtyParams.usedBixiBikesharingServicesInLast6Months, | |
displayName | |
) | |
); | |
errors.push( | |
...ParamsValidatorTools.isString( | |
'usedCommunautoCarsharingServicesAsADriverInLast6Months', | |
dirtyParams.usedCommunautoCarsharingServicesAsADriverInLast6Months, | |
displayName | |
) | |
); | |
errors.push( | |
...ParamsValidatorTools.isString( | |
'usedTransitInLast30Days', | |
dirtyParams.usedTransitInLast30Days, | |
displayName | |
) | |
); | |
errors.push(...ParamsValidatorTools.isString('useParatransit', dirtyParams.useParatransit, displayName)); | |
errors.push( | |
...ParamsValidatorTools.isString( | |
'usualSchoolPlaceParkingType', | |
dirtyParams.usualSchoolPlaceParkingType, | |
displayName | |
) | |
); | |
errors.push( | |
...ParamsValidatorTools.isBoolean('usualWorkPlaceIsHome', dirtyParams.usualWorkPlaceIsHome, displayName) | |
); | |
errors.push( | |
...ParamsValidatorTools.isString( | |
'usualWorkPlaceParkingType', | |
dirtyParams.usualWorkPlaceParkingType, | |
displayName | |
) | |
); | |
errors.push( | |
...ParamsValidatorTools.isString( | |
'usualWorkPlaceUsageAtLeastOnceAWeek', | |
dirtyParams.usualWorkPlaceUsageAtLeastOnceAWeek, | |
displayName | |
) | |
); | |
errors.push( | |
...ParamsValidatorTools.isString( | |
'usualWorkPlaceWasHomeBeforeThePandemic', | |
dirtyParams.usualWorkPlaceWasHomeBeforeThePandemic, | |
displayName | |
) | |
); | |
errors.push( | |
...ParamsValidatorTools.isUuid( | |
'whoAnsweredForThisPerson', | |
dirtyParams.whoAnsweredForThisPerson, | |
displayName | |
) | |
); | |
errors.push( | |
...ParamsValidatorTools.isUuid( | |
'whoWillAnswerForThisPerson', | |
dirtyParams.whoWillAnswerForThisPerson, | |
displayName | |
) | |
); | |
errors.push( | |
...ParamsValidatorTools.isString('workerAndStudentType', dirtyParams.workerAndStudentType, displayName) | |
); | |
errors.push(...ParamsValidatorTools.isString('workingPlace', dirtyParams.workingPlace, displayName)); | |
errors.push(...ParamsValidatorTools.isBoolean('workOnTheRoad', dirtyParams.workOnTheRoad, displayName)); | |
errors.push( | |
...ParamsValidatorTools.isBoolean('worksFromFixedLocation', dirtyParams.worksFromFixedLocation, displayName) | |
); | |
errors.push( | |
...ParamsValidatorTools.isString( | |
'workTripsDaysCountPerWeek', | |
dirtyParams.workTripsDaysCountPerWeek, | |
displayName | |
) | |
); | |
errors.push(...ParamsValidatorTools.isString('workType', dirtyParams.workType, displayName)); | |
for (const tripsType in dirtyParams.modeFrequencies) { | |
for (const mode in dirtyParams.modeFrequencies[tripsType]) { | |
errors.push( | |
...ParamsValidatorTools.isString( | |
'modeFrequencies.' + tripsType + '.' + mode, | |
dirtyParams.modeFrequencies[tripsType][mode], | |
displayName | |
) | |
); | |
} | |
} | |
return errors; | |
} | |
} | |
export { Person, PersonAttributes }; | |
/* | |
_uuid: validated in BasePerson | |
age: validated in BasePerson | |
ageGroup: validated in BasePerson | |
gender: validated in BasePerson | |
drivingLicenseOwnership: validated in BasePerson | |
transitPassOwnership: validated in BasePerson | |
carsharingMember: validated in BasePerson | |
carsharingUser: validated in BasePerson | |
bikesharingMember: validated in BasePerson | |
bikesharingUser: validated in BasePerson | |
ridesharingMember: validated in BasePerson | |
ridesharingUser: validated in BasePerson | |
occupation: validated in BasePerson | |
jobCategory: override in Person | |
jobName: validated in BasePerson | |
isOnTheRoadWorker: validated in BasePerson | |
isJobTelecommuteCompatible: validated in BasePerson | |
educationalAttainment: validated in BasePerson | |
_completedSections.profile: validateParams: boolean | |
_completedSections.segments: validateParams: boolean | |
_completedSections.travelBehavior: validateParams: boolean | |
_completedSections.tripsIntro: validateParams: boolean | |
_completedSections.visitedPlaces: validateParams: boolean | |
_sequence: validateParams: positive integer | |
bixiBikesharingUsage | |
bixiBikesharingUsage_NewOptions2023-10-18 // -> removed in parser | |
bixiBikesharingUsageV2 | |
bikeOwnership | |
canRemoteWork | |
communautoFlexCarsharingUsage | |
daysAtOfficePerWeek | |
departurePlaceIsHome | |
departurePlaceIsHomeConfirm | |
departurePlaceOther | |
departurePlaceType | |
didTripsOnTripsDate | |
disabilities | |
disabilitiesComments | |
doesNotStudiesFromFixedLocationReason | |
doesNotStudyFromFixedLocationReason | |
drivingLicenseOwner // -> move to basePerson drivingLicenseOwnership | |
electricBikeOwnership | |
enrolledInSchool | |
everUsedBixiBikesharingServices | |
everUsedCommunautoFlexCarsharingServicesAsADriver | |
freeParkingAtSchool | |
freeParkingAtWork | |
genderCustom | |
genderSpecify | |
hasDisability | |
hasOmittedActiveModesTrips | |
hasUsualSchoolPlace | |
hasUsualWorkPlace | |
job | |
jobActivitySector | |
jobCategory | |
jobCompatibleWithTelecommuting | |
jobHoursFlexibility | |
jobHoursSchedulesType | |
jobType | |
mobilityAssistiveDevices | |
mobilityAssistiveDevicesSpecify | |
mostUsedMobilityAssistiveDevice | |
nickname // remove/ignored (confidential) | |
noSchoolTripReason | |
noSchoolTripReasonSpecify | |
noUsualSchoolPlaceReason | |
noWorkOrStudyTripReason | |
noWorkTripReason | |
noWorkTripReasonSpecify | |
occupationSpecify | |
parentConsent | |
consentConfirm | |
personDidTrips | |
personDidTripsChangeConfirm | |
previousWeekDidTripsDays | |
previousWeekNoWorkingDaysReasons | |
previousWeekWentToSchoolOutsideHomeDays | |
previousWeekWentToWorkOutsideHomeDays | |
previousWeekWorkingDays | |
refuseAge // ignore | |
remoteStudyDays | |
remoteWorkDays | |
schoolType | |
shortTripSectionDidSchoolTripsOnTripsDate | |
shortTripSectionDidTripOnTripsDate | |
shortTripSectionDidTripToUsualSchoolPlaceOnTripsDate | |
shortTripSectionDidTripToUsualWorkPlaceOnTripsDate | |
shortTripSectionDidWorkTripsOnTripsDate | |
studentType | |
studiesFromFixedLocation | |
transitFares // move to transitPassTypes (od_qc_2023) or transitFaresUsed (od_mtl_ete_2023) | |
transitFaresUsed | |
transitPassOwner // -> move to basePerson transitPassOwnership | |
transitPasses | |
transitPassSpecify | |
travelToStudyDays | |
travelToWorkDays | |
useBikeForUtilitarianTravel | |
usedBixiBikesharingServicesInLast30Days | |
usedBixiBikesharingServicesInLast6Months | |
usedCommunautoCarsharingServicesAsADriverInLast6Months | |
usedTransitInLast30Days | |
useParatransit | |
usualSchoolPlaceParkingType | |
usualWorkPlaceIsHome | |
usualWorkPlaceParkingType | |
usualWorkPlaceUsageAtLeastOnceAWeek | |
usualWorkPlaceWasHomeBeforeThePandemic | |
whoAnsweredForThisPerson | |
whoWillAnswerForThisPerson | |
workerAndStudentType | |
workingPlace | |
workOnTheRoad | |
worksFromFixedLocation | |
workTripsDaysCountPerWeek | |
workType | |
usualSchoolPlace | |
usualSchoolPlace.geography | |
usualSchoolPlace.geography.geometry.coordinates.# | |
usualSchoolPlace.geography.geometry.type | |
usualSchoolPlace.geography.id | |
usualSchoolPlace.geography.properties.geocodingQueryString | |
usualSchoolPlace.geography.properties.geocodingResultsData.formatted_address | |
usualSchoolPlace.geography.properties.geocodingResultsData.place_id | |
usualSchoolPlace.geography.properties.geocodingResultsData.types.# | |
usualSchoolPlace.geography.properties.lastAction | |
usualSchoolPlace.geography.properties.platform | |
usualSchoolPlace.geography.properties.zoom | |
usualSchoolPlace.geography.type | |
usualSchoolPlace.geometry.coordinates.# | |
usualSchoolPlace.geometry.type | |
usualSchoolPlace.id | |
usualSchoolPlace.name | |
usualSchoolPlace.properties.geocodingQueryString | |
usualSchoolPlace.properties.lastAction | |
usualSchoolPlace.properties.zoom | |
usualSchoolPlace.type | |
usualSchoolPlaceName // move to usualSchoolPlace.name | |
usualStudyPlaceName // move to usualSchoolPlace.name | |
usualStudyPlaceNameGeographie.geometry.coordinates.# // incorrect naming, move to usualSchoolPlace.geography | |
usualStudyPlaceNameGeographie.geometry.type // incorrect naming, move to usualSchoolPlace.geography | |
usualStudyPlaceNameGeographie.id // incorrect naming, move to usualSchoolPlace.geography | |
usualStudyPlaceNameGeographie.properties.geocodingQueryString // incorrect naming, move to usualSchoolPlace.geography | |
usualStudyPlaceNameGeographie.properties.geocodingResultsData.formatted_address // incorrect naming, move to usualSchoolPlace.geography | |
usualStudyPlaceNameGeographie.properties.geocodingResultsData.place_id // incorrect naming, move to usualSchoolPlace.geography | |
usualStudyPlaceNameGeographie.properties.geocodingResultsData.types.# // incorrect naming, move to usualSchoolPlace.geography | |
usualStudyPlaceNameGeographie.properties.lastAction // incorrect naming, move to usualSchoolPlace.geography | |
usualStudyPlaceNameGeographie.properties.zoom // incorrect naming, move to usualSchoolPlace.geography | |
usualStudyPlaceNameGeographie.type // incorrect naming, move to usualSchoolPlace.geography | |
usualWorkPlace | |
usualWorkPlace.geography | |
usualWorkPlace.geography.geometry.coordinates.# | |
usualWorkPlace.geography.geometry.type | |
usualWorkPlace.geography.id | |
usualWorkPlace.geography.properties.geocodingQueryString | |
usualWorkPlace.geography.properties.geocodingResultsData.formatted_address | |
usualWorkPlace.geography.properties.geocodingResultsData.place_id | |
usualWorkPlace.geography.properties.geocodingResultsData.types.# | |
usualWorkPlace.geography.properties.lastAction | |
usualWorkPlace.geography.properties.platform | |
usualWorkPlace.geography.properties.zoom | |
usualWorkPlace.geography.type | |
usualWorkPlace.geometry.coordinates.# | |
usualWorkPlace.geometry.type | |
usualWorkPlace.id | |
usualWorkPlace.name | |
usualWorkPlace.properties.geocodingQueryString | |
usualWorkPlace.properties.lastAction | |
usualWorkPlace.properties.zoom | |
usualWorkPlace.type | |
usualWorkPlaceName // move to usualWorkPlace.name | |
usualWorkPlaceNameGeographie // incorrect naming, move to usualWorkPlace.geography | |
usualWorkPlaceNameGeographie.geometry.coordinates.# // incorrect naming, move to usualWorkPlace.geography | |
usualWorkPlaceNameGeographie.geometry.type // incorrect naming, move to usualWorkPlace.geography | |
usualWorkPlaceNameGeographie.id // incorrect naming, move to usualWorkPlace.geography | |
usualWorkPlaceNameGeographie.properties.geocodingQueryString // incorrect naming, move to usualWorkPlace.geography | |
usualWorkPlaceNameGeographie.properties.geocodingResultsData.formatted_address // incorrect naming, move to usualWorkPlace.geography | |
usualWorkPlaceNameGeographie.properties.geocodingResultsData.place_id // incorrect naming, move to usualWorkPlace.geography | |
usualWorkPlaceNameGeographie.properties.geocodingResultsData.types.# // incorrect naming, move to usualWorkPlace.geography | |
usualWorkPlaceNameGeographie.properties.lastAction // incorrect naming, move to usualWorkPlace.geography | |
usualWorkPlaceNameGeographie.properties.zoom // incorrect naming, move to usualWorkPlace.geography | |
usualWorkPlaceNameGeographie.type // incorrect naming, move to usualWorkPlace.geography | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment