VaccinationConfigGroup.java
- package org.matsim.episim;
- import com.google.common.base.Joiner;
- import com.google.common.base.Splitter;
- import org.matsim.core.config.ConfigGroup;
- import org.matsim.core.config.ReflectiveConfigGroup;
- import org.matsim.episim.model.VaccinationType;
- import org.matsim.episim.model.VirusStrain;
- import org.matsim.episim.model.vaccination.VaccinationModel;
- import java.time.LocalDate;
- import java.util.EnumMap;
- import java.util.Map;
- import java.util.NavigableMap;
- import java.util.TreeMap;
- import java.util.stream.Collectors;
- /**
- * Config option specific to vaccination and measures performed in {@link VaccinationModel}.
- */
- public class VaccinationConfigGroup extends ReflectiveConfigGroup {
- private static final Splitter.MapSplitter SPLITTER = Splitter.on(";").withKeyValueSeparator("=");
- private static final Joiner.MapJoiner JOINER = Joiner.on(";").withKeyValueSeparator("=");
- private static final String COMPLIANCE = "compliance";
- private static final String CAPACITY = "vaccinationCapacity";
- private static final String RECAPACITY = "reVaccinationCapacity";
- private static final String SHARE = "vaccinationShare";
- private static final String FROM_FILE = "vaccinationFile";
- private static final String DAYS_VALID = "daysValid";
- private static final String BETA = "beta";
- private static final String IGA = "IGA";
- private static final String TIME_PERIOD_IGA = "timePeriodIgA";
- private static final String VALID_DEADLINE = "validDeadline";
- private static final String GROUPNAME = "episimVaccination";
- /**
- * Amount of vaccinations available per day.
- */
- private final NavigableMap<LocalDate, Integer> vaccinationCapacity = new TreeMap<>();
- /**
- * Amount of re-vaccinations available per day.
- */
- private final NavigableMap<LocalDate, Integer> reVaccinationCapacity = new TreeMap<>();
- /**
- * Share of vaccination for the different {@link VaccinationType}.
- */
- private final NavigableMap<LocalDate, Map<VaccinationType, Double>> vaccinationShare = new TreeMap<>(Map.of(LocalDate.EPOCH, Map.of(VaccinationType.generic, 1d)));
- /**
- * Load vaccinations from file instead.
- */
- private String fromFile;
- /**
- * Validity of vaccination in days.
- */
- private int daysValid = 180;
- /**
- * Needed for antibody model.
- */
- private double beta = 1.0;
- /**
- * Needed for antibody model.
- */
- private boolean useIgA = false;
- private double timePeriodIgA = 120.;
- /**
- * Deadline after which days valid is in effect.
- */
- private LocalDate validDeadline = LocalDate.of(2022, 2, 1);
- /**
- * Vaccination compliance by age groups. Keys are the left bounds of age group intervals.
- * -1 is used as lookup when no age is present.
- */
- private final NavigableMap<Integer, Double> compliance = new TreeMap<>(Map.of(-1, 1.0));
- /**
- * Holds all specific vaccination params.
- */
- private final Map<VaccinationType, VaccinationParams> params = new EnumMap<>(VaccinationType.class);
- /**
- * Default constructor.
- */
- public VaccinationConfigGroup() {
- super(GROUPNAME);
- // add default params
- getOrAddParams(VaccinationType.generic);
- }
- /**
- * Get config parameter for a specific vaccination type.
- */
- public VaccinationParams getParams(VaccinationType type) {
- if (!params.containsKey(type))
- throw new IllegalStateException("Vaccination type " + type + " is not configured.");
- return params.get(type);
- }
- /**
- * Whether config contains certain type.
- */
- public boolean hasParams(VaccinationType type) {
- return params.containsKey(type);
- }
- /**
- * Get an existing or add new parameter set.
- */
- public VaccinationParams getOrAddParams(VaccinationType type) {
- if (!params.containsKey(type)) {
- VaccinationParams p = new VaccinationParams();
- p.type = type;
- addParameterSet(p);
- return p;
- }
- return params.get(type);
- }
- @Override
- public ConfigGroup createParameterSet(String type) {
- if (VaccinationParams.SET_TYPE.equals(type)) {
- return new VaccinationParams();
- }
- throw new IllegalArgumentException("Unknown type " + type);
- }
- @Override
- public void addParameterSet(final ConfigGroup set) {
- if (VaccinationParams.SET_TYPE.equals(set.getName())) {
- VaccinationParams p = (VaccinationParams) set;
- params.put(p.type, p);
- super.addParameterSet(set);
- } else
- throw new IllegalStateException("Unknown set type " + set.getName());
- }
- /**
- * Set vaccination compliance by age.
- *
- * @see #compliance
- */
- public void setCompliancePerAge(Map<Integer, Double> compliance) {
- this.compliance.clear();
- this.compliance.putAll(compliance);
- }
- /**
- * Get vaccination compliance by age.
- */
- public NavigableMap<Integer, Double> getCompliancePerAge() {
- return compliance;
- }
- @StringSetter(COMPLIANCE)
- void setCompliance(String compliance) {
- Map<String, String> map = SPLITTER.split(compliance);
- setCompliancePerAge(map.entrySet().stream().collect(Collectors.toMap(
- e -> Integer.parseInt(e.getKey()), e -> Double.parseDouble(e.getValue())
- )));
- }
- @StringGetter(COMPLIANCE)
- String getComplianceString() {
- return JOINER.join(compliance);
- }
- /**
- * Sets the vaccination capacity for individual days. If a day has no entry the previous will be still valid.
- * If empty, default is 0.
- *
- * @param capacity map of dates to changes in capacity.
- */
- public void setVaccinationCapacity_pers_per_day(Map<LocalDate, Integer> capacity) {
- vaccinationCapacity.clear();
- vaccinationCapacity.putAll(capacity);
- }
- public NavigableMap<LocalDate, Integer> getVaccinationCapacity() {
- return vaccinationCapacity;
- }
- @StringSetter(CAPACITY)
- void setVaccinationCapacity(String capacity) {
- if (capacity.isBlank())
- return;
- Map<String, String> map = SPLITTER.split(capacity);
- setVaccinationCapacity_pers_per_day(map.entrySet().stream().collect(Collectors.toMap(
- e -> LocalDate.parse(e.getKey()), e -> Integer.parseInt(e.getValue())
- )));
- }
- @StringGetter(CAPACITY)
- String getVaccinationCapacityString() {
- return JOINER.join(vaccinationCapacity);
- }
- @StringSetter(FROM_FILE)
- public void setFromFile(String fromFile) {
- this.fromFile = fromFile;
- }
- @StringGetter(FROM_FILE)
- public String getFromFile() {
- return fromFile;
- }
- @StringSetter(DAYS_VALID)
- public void setDaysValid(int daysValid) {
- this.daysValid = daysValid;
- }
- @StringGetter(DAYS_VALID)
- int getDaysValid() {
- return daysValid;
- }
- @StringSetter(BETA)
- public void setBeta(double beta) {
- this.beta = beta;
- }
- @StringGetter(BETA)
- public double getBeta() {
- return beta;
- }
- @StringSetter(IGA)
- public void setUseIgA(boolean useIgA) {
- this.useIgA = useIgA;
- }
- @StringGetter(IGA)
- public boolean getUseIgA() {
- return useIgA;
- }
- @StringSetter(TIME_PERIOD_IGA)
- public void setTimePeriodIgA(double timePeriodIgA) {
- this.timePeriodIgA = timePeriodIgA;
- }
- @StringGetter(TIME_PERIOD_IGA)
- public double getTimePeriodIgA() {
- return this.timePeriodIgA;
- }
- @StringSetter(VALID_DEADLINE)
- public void setValidDeadline(String validDeadline) {
- this.validDeadline = LocalDate.parse(validDeadline);
- }
- public void setValidDeadline(LocalDate validDeadline) {
- this.validDeadline = validDeadline;
- }
- @StringGetter(VALID_DEADLINE)
- public LocalDate getValidDeadline() {
- return validDeadline;
- }
- /**
- * Check if person is recently recovered or vaccinated.
- */
- public boolean hasGreenPass(EpisimPerson person, int day, LocalDate date) {
- return hasGreenPass(person, day, date, daysValid);
- }
- /**
- * Check 2G plus status, but use given {@code daysValid}.
- */
- public boolean hasGreenPass(EpisimPerson person, int day, LocalDate date, int daysValid) {
- return hasRecoveredStatus(person, day, date, daysValid > -1 ? daysValid : this.daysValid) || hasValidVaccination(person, day, date, daysValid > -1 ? daysValid : this.daysValid);
- }
- /**
- * Special type of green pass with separate setting for boostered or equivalent status.
- */
- public boolean hasGreenPassForBooster(EpisimPerson p, int day, LocalDate date, int greenPassValidDays, int greenPassBoosterValidDays) {
- int valid = greenPassValidDays;
- // infected and vaccinated count as booster
- if (p.getReVaccinationStatus() == EpisimPerson.VaccinationStatus.yes || (p.getNumInfections() >= 1 && p.getVaccinationStatus() == EpisimPerson.VaccinationStatus.yes))
- valid = greenPassBoosterValidDays;
- return hasGreenPass(p, day, date, valid);
- }
- /**
- * Check whether person has the recovered status.
- */
- private boolean hasRecoveredStatus(EpisimPerson person, int day, LocalDate date, int daysValid) {
- // Initial the threshold was 180 days, this setting is adjusted to the threshold after the deadline
- return date.isBefore(validDeadline) ? person.isRecentlyRecovered(day, 180) : person.isRecentlyRecovered(day, daysValid);
- }
- /**
- * Check if person has a valid vaccination card.
- *
- * @param person person to check
- * @param day current simulation day
- * @param date simulation date
- */
- public boolean hasValidVaccination(EpisimPerson person, int day, LocalDate date) {
- return hasValidVaccination(person, day, date, getDaysValid());
- }
- public boolean hasValidVaccination(EpisimPerson person, int day, LocalDate date, int daysValid) {
- if (person.getVaccinationStatus() == EpisimPerson.VaccinationStatus.no)
- return false;
- boolean fullyVaccinated = person.daysSince(EpisimPerson.VaccinationStatus.yes, day) > getParams(person.getVaccinationType()).getDaysBeforeFullEffect();
- boolean booster = person.getReVaccinationStatus() == EpisimPerson.VaccinationStatus.yes;
- if (date.isBefore(validDeadline))
- return fullyVaccinated || booster;
- return (fullyVaccinated || booster) && person.daysSince(EpisimPerson.VaccinationStatus.yes, day) <= daysValid;
- }
- /**
- * Computes the minimum factor over all vaccinations.
- * @param person person
- * @param day current iteration
- * @param f function of VaccinationParams to retrieve the desired factor
- * @return minimum factor or 1 if not vaccinated
- */
- public double getMinFactor(EpisimPerson person, int day, VaccinationFactorFunction f) {
- if (person.getNumVaccinations() == 0)
- return 1;
- double factor = 1d;
- for (int i = 0; i < person.getNumVaccinations(); i++) {
- VaccinationType type = person.getVaccinationType(i);
- factor = Math.min(factor, f.getFactor(getParams(type), person.getVirusStrain(), person.daysSince(EpisimPerson.VaccinationStatus.yes, day)));
- }
- return factor;
- }
- /**
- * @see #setVaccinationCapacity_pers_per_day(Map)
- */
- public void setReVaccinationCapacity_pers_per_day(Map<LocalDate, Integer> capacity) {
- reVaccinationCapacity.clear();
- reVaccinationCapacity.putAll(capacity);
- }
- public NavigableMap<LocalDate, Integer> getReVaccinationCapacity() {
- return reVaccinationCapacity;
- }
- @StringSetter(RECAPACITY)
- void setReVaccinationCapacity(String capacity) {
- if (capacity.isBlank())
- return;
- Map<String, String> map = SPLITTER.split(capacity);
- setReVaccinationCapacity_pers_per_day(map.entrySet().stream().collect(Collectors.toMap(
- e -> LocalDate.parse(e.getKey()), e -> Integer.parseInt(e.getValue())
- )));
- }
- @StringGetter(RECAPACITY)
- String getReVaccinationCapacityString() {
- return JOINER.join(reVaccinationCapacity);
- }
- /**
- * Set the vaccination share per date.
- */
- public void setVaccinationShare(Map<LocalDate, Map<VaccinationType, Double>> share) {
- for (Map<VaccinationType, Double> v : share.values()) {
- double total = v.values().stream().sorted().mapToDouble(Double::doubleValue).sum();
- if (total > 1) throw new IllegalArgumentException("Sum of shares must be < 1");
- }
- this.vaccinationShare.clear();
- this.vaccinationShare.putAll(share);
- }
- /**
- * Return vaccination share per date.
- */
- public NavigableMap<LocalDate, Map<VaccinationType, Double>> getVaccinationShare() {
- return vaccinationShare;
- }
- /**
- * Return the cumulative probability for all vaccination types, based on {@link #getVaccinationShare()}.
- *
- * @param date date to lookup
- */
- public Map<VaccinationType, Double> getVaccinationTypeProb(LocalDate date) {
- EnumMap<VaccinationType, Double> prob = new EnumMap<>(VaccinationType.class);
- Map<VaccinationType, Double> share = EpisimUtils.findValidEntry(vaccinationShare, null, date);
- if (share == null)
- share = Map.of(VaccinationType.generic, 1d);
- double total = share.values().stream().sorted().mapToDouble(Double::doubleValue).sum();
- double sum = 1 - total;
- for (VaccinationType t : VaccinationType.values()) {
- sum += share.getOrDefault(t, 0d);
- prob.put(t, sum);
- }
- return prob;
- }
- @StringGetter(SHARE)
- String getVaccinationShareString() {
- Map<LocalDate, String> collect =
- vaccinationShare.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> JOINER.join(e.getValue())));
- return Joiner.on("|").withKeyValueSeparator(">").join(collect);
- }
- @StringSetter(SHARE)
- void setVaccinationShare(String value) {
- Map<String, String> share = Splitter.on("|").withKeyValueSeparator(">").split(value);
- Map<LocalDate, Map<VaccinationType, Double>> collect = share.entrySet().stream().collect(Collectors.toMap(
- e -> LocalDate.parse(e.getKey()),
- e -> SPLITTER.split(e.getValue()).entrySet().stream().collect(Collectors.toMap(k -> VaccinationType.valueOf(k.getKey()), k -> Double.parseDouble(k.getValue())))
- ));
- setVaccinationShare(collect);
- }
- /**
- * Holds strain specific options.
- */
- public static final class VaccinationParams extends ReflectiveConfigGroup {
- static final String SET_TYPE = "vaccinationParams";
- private static final String TYPE = "type";
- private static final String DAYS_BEFORE_FULL_EFFECT = "daysBeforeFullEffect";
- private static final String EFFECTIVENESS = "effectiveness";
- private static final String INFECTIVITY = "infectivity";
- private static final String BOOST_EFFECTIVENESS = "boostEffectiveness";
- private static final String BOOST_INFECTIVITY = "boostInfectivity";
- private static final String BOOST_WAIT_PERIOD = "boostWaitPeriod";
- private static final String FACTOR_SHOWINGS_SYMPTOMS = "factorShowingSymptoms";
- private static final String FACTOR_SERIOUSLY_SICK = "factorSeriouslySick";
- private static final String FACTOR_CRITICAL = "factorCritical";
- private VaccinationType type;
- /**
- * Number of days until vaccination goes into full effect.
- */
- private int daysBeforeFullEffect = 28;
- /**
- * Wait period before boost can be applied.
- */
- private int boostWaitPeriod = 5 * 30;
- /**
- * Effectiveness, i.e. how much susceptibility is reduced.
- */
- private Map<VirusStrain, Parameter> effectiveness = new EnumMap<>(Map.of(VirusStrain.SARS_CoV_2,
- forStrain(VirusStrain.SARS_CoV_2)
- .atDay(4, 0)
- .atDay(5, 0.45)
- .atFullEffect(0.9)
- ));
- /**
- * Infectivity of a vaccinated person towards others.
- */
- private Map<VirusStrain, Parameter> infectivity = new EnumMap<>(Map.of(VirusStrain.SARS_CoV_2,
- forStrain(VirusStrain.SARS_CoV_2)
- .atDay(0, 1)
- .atFullEffect(1.0)
- ));
- /**
- * Effectiveness after booster shot.
- */
- private Map<VirusStrain, Parameter> boostEffectiveness = new EnumMap<>(VirusStrain.class);
- /**
- * Infectivity of a vaccinated person towards others.
- */
- private Map<VirusStrain, Parameter> boostInfectivity = new EnumMap<>(Map.of(VirusStrain.SARS_CoV_2,
- forStrain(VirusStrain.SARS_CoV_2)
- .atDay(0, 1)
- .atFullEffect(1.0)
- ));
- /**
- * Factor for probability if person is vaccinated.
- */
- private Map<VirusStrain, Parameter> factorShowingSymptoms = new EnumMap<>(Map.of(VirusStrain.SARS_CoV_2,
- forStrain(VirusStrain.SARS_CoV_2)
- .atDay(5, 0.5)
- ));
- /**
- * Factor for probability if person is vaccinated.
- */
- private Map<VirusStrain, Parameter> factorSeriouslySick = new EnumMap<>(Map.of(VirusStrain.SARS_CoV_2,
- forStrain(VirusStrain.SARS_CoV_2)
- .atDay(5, 0.5)
- ));
- /**
- * Factor for probability if person is vaccinated.
- */
- private Map<VirusStrain, Parameter> factorCritical = new EnumMap<>(Map.of(VirusStrain.SARS_CoV_2,
- forStrain(VirusStrain.SARS_CoV_2)
- .atDay(0, 1)
- ));
- VaccinationParams() {
- super(SET_TYPE);
- }
- @StringGetter(TYPE)
- public VaccinationType getType() {
- return type;
- }
- @StringSetter(TYPE)
- public void setType(VaccinationType type) {
- this.type = type;
- }
- @StringGetter(DAYS_BEFORE_FULL_EFFECT)
- public int getDaysBeforeFullEffect() {
- return daysBeforeFullEffect;
- }
- @StringSetter(DAYS_BEFORE_FULL_EFFECT)
- public VaccinationParams setDaysBeforeFullEffect(int daysBeforeFullEffect) {
- this.daysBeforeFullEffect = daysBeforeFullEffect;
- return this;
- }
- @StringSetter(BOOST_WAIT_PERIOD)
- public VaccinationParams setBoostWaitPeriod(int boostWaitPeriod) {
- this.boostWaitPeriod = boostWaitPeriod;
- return this;
- }
- @StringGetter(BOOST_WAIT_PERIOD)
- public int getBoostWaitPeriod() {
- return boostWaitPeriod;
- }
- private VaccinationParams setParamsInternal(Map<VirusStrain, Parameter> map, Parameter[] params) {
- for (Parameter p : params) {
- for (VirusStrain s : p.strain) {
- p.setDaysBeforeFullEffect(getDaysBeforeFullEffect());
- map.put(s, p);
- }
- }
- return this;
- }
- /**
- * Interpolate parameter for day after vaccination.
- *
- * @param map map for lookup
- * @param strain virus strain
- * @param day days since vaccination
- * @return interpolated factor
- */
- private double getParamsInternal(Map<VirusStrain, Parameter> map, VirusStrain strain, int day) {
- Parameter p = map.getOrDefault(strain, map.get(VirusStrain.SARS_CoV_2));
- return p.get(day);
- }
- public VaccinationParams setEffectiveness(Parameter... parameters) {
- return setParamsInternal(effectiveness, parameters);
- }
- public VaccinationParams setInfectivity(Parameter... parameters) {
- return setParamsInternal(infectivity, parameters);
- }
- public VaccinationParams setBoostEffectiveness(Parameter... parameters) {
- return setParamsInternal(boostEffectiveness, parameters);
- }
- public VaccinationParams setBoostInfectivity(Parameter... parameters) {
- return setParamsInternal(boostInfectivity, parameters);
- }
- public VaccinationParams setFactorShowingSymptoms(Parameter... parameters) {
- return setParamsInternal(factorShowingSymptoms, parameters);
- }
- public VaccinationParams setFactorSeriouslySick(Parameter... parameters) {
- return setParamsInternal(factorSeriouslySick, parameters);
- }
- public VaccinationParams setFactorCritical(Parameter... parameters) {
- return setParamsInternal(factorCritical, parameters);
- }
- public double getEffectiveness(VirusStrain strain, int day) {
- return getParamsInternal(effectiveness, strain, day);
- }
- public double getInfectivity(VirusStrain strain, int day) {
- return getParamsInternal(infectivity, strain, day);
- }
- public double getBoostInfectivity(VirusStrain strain, int day) {
- return getParamsInternal(boostInfectivity, strain, day);
- }
- public double getBoostEffectiveness(VirusStrain strain, int day) {
- return getParamsInternal(boostEffectiveness.containsKey(strain) ? boostEffectiveness : effectiveness, strain, day);
- }
- public double getFactorShowingSymptoms(VirusStrain strain, int day) {
- return getParamsInternal(factorShowingSymptoms, strain, day);
- }
- public double getFactorSeriouslySick(VirusStrain strain, int day) {
- return getParamsInternal(factorSeriouslySick, strain, day);
- }
- public double getFactorCritical(VirusStrain strain, int day) {
- return getParamsInternal(factorCritical, strain, day);
- }
- /**
- * Load serialized parameters
- */
- private void setParamsInternal(Map<VirusStrain, Parameter> map, String value) {
- map.clear();
- if (value.isBlank()) return;
- map.clear();
- for (Map.Entry<String, String> e : SPLITTER.split(value).entrySet()) {
- map.put(VirusStrain.valueOf(e.getKey()), Parameter.parse(e.getValue()));
- }
- }
- private String getParamsInternal(Map<VirusStrain, Parameter> map) {
- Map<VirusStrain, String> result = map.entrySet().stream().collect(Collectors.toMap(
- Map.Entry::getKey,
- e -> e.getValue().toString()
- ));
- return JOINER.join(result);
- }
- @StringSetter(EFFECTIVENESS)
- void setEffectiveness(String value) {
- setParamsInternal(effectiveness, value);
- }
- @StringGetter(EFFECTIVENESS)
- String getEffectivenessString() {
- return getParamsInternal(effectiveness);
- }
- @StringSetter(BOOST_EFFECTIVENESS)
- void setBoostEffectiveness(String value) {
- setParamsInternal(boostEffectiveness, value);
- }
- @StringGetter(BOOST_EFFECTIVENESS)
- String getBoostEffectivenessString() {
- return getParamsInternal(boostEffectiveness);
- }
- @StringSetter(FACTOR_SHOWINGS_SYMPTOMS)
- void setFactorShowingSymptoms(String value) {
- setParamsInternal(factorShowingSymptoms, value);
- }
- @StringGetter(FACTOR_SHOWINGS_SYMPTOMS)
- String getFactorShowingSymptoms() {
- return getParamsInternal(factorShowingSymptoms);
- }
- @StringSetter(FACTOR_SERIOUSLY_SICK)
- void setFactorSeriouslySick(String value) {
- setParamsInternal(factorSeriouslySick, value);
- }
- @StringGetter(FACTOR_SERIOUSLY_SICK)
- String getFactorSeriouslySick() {
- return getParamsInternal(factorSeriouslySick);
- }
- @StringSetter(FACTOR_CRITICAL)
- void setFactorCritical(String value) {
- setParamsInternal(factorCritical, value);
- }
- @StringGetter(FACTOR_CRITICAL)
- public String getFactorCritical() {
- return getParamsInternal(factorCritical);
- }
- @StringSetter(INFECTIVITY)
- void setInfectivity(String value) {
- setParamsInternal(infectivity, value);
- }
- @StringGetter(INFECTIVITY)
- public String getInfectivity() {
- return getParamsInternal(infectivity);
- }
- @StringSetter(BOOST_INFECTIVITY)
- void setBoostInfectivity(String value) {
- setParamsInternal(boostInfectivity, value);
- }
- @StringGetter(BOOST_INFECTIVITY)
- public String getBoostInfectivity() {
- return getParamsInternal(boostInfectivity);
- }
- /**
- * Return effectiveness against base variant.
- *
- * @deprecated use {@link #getEffectiveness(VirusStrain, int)}
- */
- @Deprecated
- public double getEffectiveness() {
- return getEffectiveness(VirusStrain.SARS_CoV_2, getDaysBeforeFullEffect());
- }
- /**
- * Return effectiveness against base variant.
- *
- * @deprecated use {@link #setEffectiveness(Parameter...)}
- */
- @Deprecated
- public void setEffectiveness(double effectiveness) {
- throw new UnsupportedOperationException("Use .setEffectiveness(Parameter...)");
- }
- @Deprecated
- public VaccinationParams setFactorSeriouslySick(double factorSeriouslySick) {
- throw new UnsupportedOperationException("Use .setFactorSeriouslySick(Parameter...)");
- }
- @Deprecated
- public VaccinationParams setFactorShowingSymptoms(double factorShowingSymptoms) {
- throw new UnsupportedOperationException("Use .setFactorShowingSymptoms(Parameter...)");
- }
- }
- /**
- * Creates an empty {@link Parameter} progression for one or multiple strain.
- */
- public static Parameter forStrain(VirusStrain... strain) {
- return new Parameter(strain);
- }
- /**
- * Holds the temporal progression of certain value for each virus strains.
- */
- public static final class Parameter {
- private static final Splitter.MapSplitter SPLITTER = Splitter.on("|").withKeyValueSeparator(">");
- private static final Joiner.MapJoiner JOINER = Joiner.on("|").withKeyValueSeparator(">");
- private final VirusStrain[] strain;
- private final NavigableMap<Integer, Double> map = new TreeMap<>();
- private Parameter(VirusStrain[] strain) {
- this.strain = strain;
- }
- private Parameter(Map<String, String> map) {
- this.strain = new VirusStrain[0];
- for (Map.Entry<String, String> e : map.entrySet()) {
- this.map.put(Integer.parseInt(e.getKey()), Double.parseDouble(e.getValue()));
- }
- }
- /**
- * Sets the value for a parameter at a specific day.
- */
- public Parameter atDay(int day, double value) {
- map.put(day, value);
- return this;
- }
- /**
- * Sets the value for parameter for the day of full effect.
- * {@link VaccinationParams#setDaysBeforeFullEffect(int)} has to be set before calling this method!
- */
- public Parameter atFullEffect(double value) {
- map.put(Integer.MAX_VALUE, value);
- return this;
- }
- /**
- * Interpolate for given day.
- */
- private double get(int day) {
- Map.Entry<Integer, Double> floor = map.floorEntry(day);
- if (floor == null)
- return map.firstEntry().getValue();
- if (floor.getKey().equals(day))
- return floor.getValue();
- Map.Entry<Integer, Double> ceil = map.ceilingEntry(day);
- // there is no higher entry to interpolate
- if (ceil == null)
- return floor.getValue();
- double between = ceil.getKey() - floor.getKey();
- double diff = day - floor.getKey();
- return floor.getValue() + diff * (ceil.getValue() - floor.getValue()) / between;
- }
- private void setDaysBeforeFullEffect(int daysBeforeFullEffect) {
- if (map.containsKey(Integer.MAX_VALUE))
- map.put(daysBeforeFullEffect, map.remove(Integer.MAX_VALUE));
- }
- @Override
- public String toString() {
- return JOINER.join(map);
- }
- private static Parameter parse(String value) {
- Map<String, String> m = SPLITTER.split(value);
- return new Parameter(m);
- }
- }
- }