Skip to content

Aircraft

Aircraft

Bases: Group

Aircraft represents a plane used for international travel

Source code in june/groups/travel/aircraft.py
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
class Aircraft(Group):
    """Aircraft represents a plane used for international travel"""

    #class SubgroupType(IntEnum):
    #    passengers = 0  # Single subgroup since aircraft is treated as confined space

    def __init__(
        self, 
        airport=None, 
        flight_duration: float = 3.0,
    ):
        super().__init__()
        self.airport = airport
        self.flight_duration = flight_duration
        self._config = self._load_config()

        # Initialise aircraft layout
        self.num_seats = self._config["num_rows"] * self._config["num_seats_per_row"]
        self.capacity = self.num_seats

        # Create single passengers subgroup
        self.subgroups = [Subgroup(self, self.SubgroupType.passengers)]

        # Track occupancy
        self._occupied_seats = 0

    def _load_config(self):
        """Load aircraft parameters from config"""
        config_path = configs_path / "defaults/groups/travel/aircrafts.yaml"
        with open(config_path) as f:
            return yaml.safe_load(f)

    @property
    def is_full(self) -> bool:
        """Check if aircraft is at capacity

        """
        return self._occupied_seats >= self.capacity

    def add(self, person: Person, activity: str = "international_travel", subgroup_type=None) -> bool:
        """Add passenger to aircraft

        Args:
            person (Person): 
            activity (str, optional): (Default value = "international_travel")
            subgroup_type: (Default value = None)

        """
        if self.is_full:
            return False

        # Add to single passengers subgroup
        super().add(person, activity=activity, subgroup_type=self.SubgroupType.passengers)
        self._occupied_seats += 1
        return True

    def remove(self, person: Person) -> None:
        """Remove passenger from aircraft

        Args:
            person (Person): 

        """
        super().remove_person(person)
        self._occupied_seats -= 1

    def get_interactive_group(self, people_from_abroad=None) -> InteractiveGroup:
        """Create interactive group using InteractiveAircraft

        Args:
            people_from_abroad: (Default value = None)

        """
        return InteractiveAircraft(self, people_from_abroad=people_from_abroad)

is_full property

Check if aircraft is at capacity

add(person, activity='international_travel', subgroup_type=None)

Add passenger to aircraft

Parameters:

Name Type Description Default
person Person
required
activity str

(Default value = "international_travel")

'international_travel'
subgroup_type

(Default value = None)

None
Source code in june/groups/travel/aircraft.py
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
def add(self, person: Person, activity: str = "international_travel", subgroup_type=None) -> bool:
    """Add passenger to aircraft

    Args:
        person (Person): 
        activity (str, optional): (Default value = "international_travel")
        subgroup_type: (Default value = None)

    """
    if self.is_full:
        return False

    # Add to single passengers subgroup
    super().add(person, activity=activity, subgroup_type=self.SubgroupType.passengers)
    self._occupied_seats += 1
    return True

get_interactive_group(people_from_abroad=None)

Create interactive group using InteractiveAircraft

Parameters:

Name Type Description Default
people_from_abroad

(Default value = None)

None
Source code in june/groups/travel/aircraft.py
78
79
80
81
82
83
84
85
def get_interactive_group(self, people_from_abroad=None) -> InteractiveGroup:
    """Create interactive group using InteractiveAircraft

    Args:
        people_from_abroad: (Default value = None)

    """
    return InteractiveAircraft(self, people_from_abroad=people_from_abroad)

remove(person)

Remove passenger from aircraft

Parameters:

Name Type Description Default
person Person
required
Source code in june/groups/travel/aircraft.py
68
69
70
71
72
73
74
75
76
def remove(self, person: Person) -> None:
    """Remove passenger from aircraft

    Args:
        person (Person): 

    """
    super().remove_person(person)
    self._occupied_seats -= 1

Aircrafts

Bases: Supergroup

Collection of aircraft

Source code in june/groups/travel/aircraft.py
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
class Aircrafts(Supergroup):
    """Collection of aircraft"""
    venue_class = Aircraft

    def __init__(self, aircrafts: List[Aircraft]):
        super().__init__(members=aircrafts)

    @classmethod
    def for_airport(cls, airport, n_aircrafts: int = 10) -> "Aircrafts":
        """Create aircraft collection for a specific airport

        Args:
            airport: 
            n_aircrafts (int, optional): (Default value = 10)

        """
        aircrafts = []
        for _ in range(n_aircrafts):
            aircraft = Aircraft(airport=airport)
            aircrafts.append(aircraft)
        return cls(aircrafts)

    @classmethod
    def from_airports(cls, airports) -> "Aircrafts":
        """Create aircraft fleet for multiple airports

        Args:
            airports: 

        """
        all_aircrafts = []
        for airport in airports:
            # Scale number of aircraft based on daily passenger capacity
            n_aircrafts = max(1, int(airport.capacity / 200))
            airport_aircrafts = cls.for_airport(airport, n_aircrafts)
            all_aircrafts.extend(airport_aircrafts.members)

        return cls(all_aircrafts)

    def get_available_aircraft(self, airport) -> Optional[Aircraft]:
        """Get an available aircraft at the given airport

        Args:
            airport: 

        """
        available = [
            aircraft for aircraft in self.members 
            if aircraft.airport == airport and not aircraft.is_full
        ]
        return random.choice(available) if available else None

for_airport(airport, n_aircrafts=10) classmethod

Create aircraft collection for a specific airport

Parameters:

Name Type Description Default
airport
required
n_aircrafts int

(Default value = 10)

10
Source code in june/groups/travel/aircraft.py
134
135
136
137
138
139
140
141
142
143
144
145
146
147
@classmethod
def for_airport(cls, airport, n_aircrafts: int = 10) -> "Aircrafts":
    """Create aircraft collection for a specific airport

    Args:
        airport: 
        n_aircrafts (int, optional): (Default value = 10)

    """
    aircrafts = []
    for _ in range(n_aircrafts):
        aircraft = Aircraft(airport=airport)
        aircrafts.append(aircraft)
    return cls(aircrafts)

from_airports(airports) classmethod

Create aircraft fleet for multiple airports

Parameters:

Name Type Description Default
airports
required
Source code in june/groups/travel/aircraft.py
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
@classmethod
def from_airports(cls, airports) -> "Aircrafts":
    """Create aircraft fleet for multiple airports

    Args:
        airports: 

    """
    all_aircrafts = []
    for airport in airports:
        # Scale number of aircraft based on daily passenger capacity
        n_aircrafts = max(1, int(airport.capacity / 200))
        airport_aircrafts = cls.for_airport(airport, n_aircrafts)
        all_aircrafts.extend(airport_aircrafts.members)

    return cls(all_aircrafts)

get_available_aircraft(airport)

Get an available aircraft at the given airport

Parameters:

Name Type Description Default
airport
required
Source code in june/groups/travel/aircraft.py
166
167
168
169
170
171
172
173
174
175
176
177
def get_available_aircraft(self, airport) -> Optional[Aircraft]:
    """Get an available aircraft at the given airport

    Args:
        airport: 

    """
    available = [
        aircraft for aircraft in self.members 
        if aircraft.airport == airport and not aircraft.is_full
    ]
    return random.choice(available) if available else None

InteractiveAircraft

Bases: InteractiveGroup

Source code in june/groups/travel/aircraft.py
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
class InteractiveAircraft(InteractiveGroup):
    """ """
    def __init__(self, group: "Aircraft", people_from_abroad=None):
        super().__init__(group=group, people_from_abroad=people_from_abroad)
        self.characteristic_time = group.flight_duration

    def get_processed_contact_matrix(self, contact_matrix):
        """Process contact matrix based on current aircraft state.
        Calculates n_infected/n_total ratio.

        Args:
            contact_matrix: 

        """
        ret = np.zeros((1, 1))

        # Count total and infected passengers
        total_passengers = len(self.group.subgroups[0].people)
        infected_passengers = sum(1 for p in self.group.subgroups[0].people if p.infected)

        # Calculate infection ratio
        if total_passengers > 0:
            infection_ratio = infected_passengers / total_passengers
        else:
            infection_ratio = 0

        # Apply base rate scaled by infection ratio
        base_rate = contact_matrix[0][0]
        ret[0, 0] = base_rate * infection_ratio

        # Additional duration effect for long flights
        if self.group.flight_duration > 8:
            # Increase risk by up to 50% for flights over 8 hours
            long_flight_factor = 1.0 + min(0.5, (self.group.flight_duration - 8)/8)
            ret *= long_flight_factor

        return ret

get_processed_contact_matrix(contact_matrix)

Process contact matrix based on current aircraft state. Calculates n_infected/n_total ratio.

Parameters:

Name Type Description Default
contact_matrix
required
Source code in june/groups/travel/aircraft.py
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
def get_processed_contact_matrix(self, contact_matrix):
    """Process contact matrix based on current aircraft state.
    Calculates n_infected/n_total ratio.

    Args:
        contact_matrix: 

    """
    ret = np.zeros((1, 1))

    # Count total and infected passengers
    total_passengers = len(self.group.subgroups[0].people)
    infected_passengers = sum(1 for p in self.group.subgroups[0].people if p.infected)

    # Calculate infection ratio
    if total_passengers > 0:
        infection_ratio = infected_passengers / total_passengers
    else:
        infection_ratio = 0

    # Apply base rate scaled by infection ratio
    base_rate = contact_matrix[0][0]
    ret[0, 0] = base_rate * infection_ratio

    # Additional duration effect for long flights
    if self.group.flight_duration > 8:
        # Increase risk by up to 50% for flights over 8 hours
        long_flight_factor = 1.0 + min(0.5, (self.group.flight_duration - 8)/8)
        ret *= long_flight_factor

    return ret