ChannelTaskRoadSideDistraction.java

package org.opentrafficsim.road.gtu.lane.perception.mental.channel;

import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Function;

import org.djutils.exceptions.Throw;
import org.opentrafficsim.base.parameters.ParameterException;
import org.opentrafficsim.core.network.LateralDirectionality;
import org.opentrafficsim.road.gtu.lane.LaneBasedGtu;
import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
import org.opentrafficsim.road.gtu.lane.perception.RelativeLane;
import org.opentrafficsim.road.gtu.lane.perception.mental.AbstractTask;
import org.opentrafficsim.road.gtu.lane.perception.mental.DistractionField;
import org.opentrafficsim.road.network.lane.object.RoadSideDistraction;

/**
 * Channel implementation of task due to road side distraction.
 * <p>
 * Copyright (c) 2026-2026 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
 * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
 * </p>
 * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
 */
public class ChannelTaskRoadSideDistraction extends AbstractTask implements ChannelTask
{

    /** Distraction field. */
    private final DistractionField distractionField;

    /** Direction. */
    private final LateralDirectionality direction;

    /** Filter to retain relevant distractions. */
    private final BiFunction<RelativeLane, RoadSideDistraction, Boolean> filter;

    /**
     * Constructor. This task applies to a subset of distractions depending on the direction:
     * <ul>
     * <li>LEFT: distractions on left lanes with NONE direction, and distractions on current lane with LEFT direction</li>
     * <li>RIGHT: distractions on right lanes with NONE direction, and distractions on current lane with RIGHT direction</li>
     * <li>NONE: distractions on current lane with NONE direction
     * </ul>
     * @param distractionField distraction field, which should be shared amongst instances
     * @param direction direction of applicable distractions
     */
    public ChannelTaskRoadSideDistraction(final DistractionField distractionField, final LateralDirectionality direction)
    {
        super("road-side distraction (" + direction + ")");
        Throw.whenNull(distractionField, "distractionField");
        Throw.whenNull(direction, "direction");
        this.distractionField = distractionField;
        this.direction = direction;
        // all distractions on current lane with direction of this task
        // all distractions on lanes on the side of this task, where the distraction direction is NONE (i.e. on the lane)
        this.filter = (lane, distraction) -> (lane.isCurrent() && this.direction.equals(distraction.getSide()))
                || (this.direction.equals(lane.getLateralDirectionality()) && distraction.getSide().isNone());
    }

    @Override
    protected double calculateTaskDemand(final LanePerception perception) throws ParameterException
    {
        return this.distractionField.getDistraction(this.filter);
    }

    @Override
    public Object getChannel()
    {
        return this.direction.isLeft() ? LEFT : (this.direction.isRight() ? RIGHT : FRONT);
    }

    /**
     * Supplier of distraction tasks. This supplier returns a persistent set in which each distraction task shares a distraction
     * field.
     */
    public static class Supplier implements Function<LanePerception, Set<ChannelTask>>
    {
        /** Set of tasks. */
        private final Set<ChannelTask> set;

        /**
         * Constructor.
         * @param gtu GTU
         */
        public Supplier(final LaneBasedGtu gtu)
        {
            DistractionField distractionField = new DistractionField(gtu);
            this.set = Set.of(new ChannelTaskRoadSideDistraction(distractionField, LateralDirectionality.LEFT),
                    new ChannelTaskRoadSideDistraction(distractionField, LateralDirectionality.NONE),
                    new ChannelTaskRoadSideDistraction(distractionField, LateralDirectionality.RIGHT));
        }

        @Override
        public Set<ChannelTask> apply(final LanePerception t)
        {
            return this.set;
        }
    }

}