forked from steger/pr3-ws202526
airport starting point
parent
2d1eec66ea
commit
c3fed07a8f
|
|
@ -0,0 +1,63 @@
|
|||
# Assignment - Airport Simulation
|
||||
This go-program is a simulation of the departure process of an airport that consists of *aircrafts*, *passengers*, *checkin-counter*, *security-checks*, *gates*, a *baggage handling system*, a *runway*, a *flight schedule* and *gates*. Passengers go through the following steps:
|
||||
- **Checkin**: The ticket is verified, baggage is checked in and handed over to the baggage handling system, and a boarding pass is issued.
|
||||
- **Security-Check**: The boarding pass is verified and the passenger is checked for prohibited items.
|
||||
- **Gate**: The passenger walks to the correct gate and waits there until boarding time. The gate takes then care of boarding the aircraft, while simultaneously loading baggage into the aircraft.
|
||||
|
||||
Each step has a processing time and there are several waiting times in between.
|
||||
|
||||
Aircrafts arrive at the gate on boarding time and leave to the runway on departure time according to the flight schedule.
|
||||
|
||||
## Task
|
||||
|
||||
Your task is to complete the implementation by going through the **TODO** statements in the files `baggageHandlingSystem.go`, `securityCheck.go`, and `gate.go`. All other files already contain an implementation.
|
||||
|
||||
**Hint**: The expected behavior is defined in detail in the corresponding unit tests.
|
||||
|
||||
**Hint**: Be aware of synchronization issues between the different goroutines for all actors. Use `channels` whenever applicable. See `checkin.go` for inspiration.
|
||||
|
||||
## Example Output
|
||||
|
||||
```
|
||||
Flight Number Destination Gate Boarding Time Departure Time
|
||||
--------------------------------------------------------------------------------
|
||||
AF2062 ZAG 7 13:59:27 13:59:57
|
||||
BA8851 SOF 9 13:59:47 14:00:17
|
||||
SK4243 FRA 5 14:01:46 14:02:16
|
||||
KL5728 WAW 9 14:03:06 14:03:36
|
||||
SK8183 PRG 8 14:03:12 14:03:42
|
||||
AF8488 LIS 5 13:59:45 14:00:15
|
||||
KL5937 RIX 1 14:01:26 14:01:56
|
||||
AY1065 BRU 7 14:00:37 14:01:07
|
||||
BA1529 ZRH 5 14:02:03 14:02:33
|
||||
IB2405 IST 3 14:01:51 14:02:21
|
||||
What/Who arrives at airport? (p for passenger, c for car, t for train, q to quit): p
|
||||
stoic_dijkstra has arrived at the airport for the flight number IB2405 to IST in 3.11 minutes with 2 bags and carry-on items: [Medicine Knife Sharpener]
|
||||
stoic_dijkstra completed the checkin procedure and is now heading to security
|
||||
stoic_dijkstra has successfully passed the security check and is now walking to the gate
|
||||
elated_hellman has arrived at the airport for the flight number KL5728 to WAW in 4.19 minutes with 2 bags and carry-on items: [Explosives]
|
||||
vibrant_maxwell has arrived at the airport for the flight number BA8851 to SOF in 0.88 minutes with 2 bags and carry-on items: [Keys Matches]
|
||||
dazzling_lewin has arrived at the airport for the flight number AF2062 to ZAG in 0.54 minutes with 1 bags and carry-on items: []
|
||||
nifty_hermann has arrived at the airport for the flight number IB2405 to IST in 2.94 minutes with 1 bags and carry-on items: [Resistance Bands Gloves]
|
||||
elated_hellman completed the checkin procedure and is now heading to security
|
||||
vibrant_maxwell completed the checkin procedure and is now heading to security
|
||||
elated_hellman: prohibited item detected: [Explosives]
|
||||
flight AF2062 is ready for boarding
|
||||
dazzling_lewin completed the checkin procedure and is now heading to security
|
||||
vibrant_maxwell has successfully passed the security check and is now walking to the gate
|
||||
nifty_hermann completed the checkin procedure and is now heading to security
|
||||
dazzling_lewin has successfully passed the security check and is now walking to the gate
|
||||
nifty_hermann has successfully passed the security check and is now walking to the gate
|
||||
dazzling_lewin has successfully boarded flight AF2062 to ZAG
|
||||
flight AF8488 is ready for boarding
|
||||
flight BA8851 is ready for boarding
|
||||
loaded baggage {[Goggles Fire Extinguisher Controller]} onto flight BA8851
|
||||
loaded baggage {[Book Clipboard]} onto flight BA8851
|
||||
vibrant_maxwell has successfully boarded flight BA8851 to SOF
|
||||
boarding completed for flight number AF2062
|
||||
Flight AF2062 is waiting for takeoff
|
||||
Flight AF2062 to ZAG is taking off
|
||||
Flight AF2062 to ZAG has taken off with 1 passengers and 0 bags on board
|
||||
Closing airport
|
||||
The following baggage was lost today: []
|
||||
```
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
package airport
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type Aircraft struct {
|
||||
Flight Flight
|
||||
Passengers []Passenger
|
||||
Baggage []Baggage
|
||||
}
|
||||
|
||||
var _ BaggageProcessor = &Aircraft{}
|
||||
|
||||
func NewAircraft(flight Flight) Aircraft {
|
||||
return Aircraft{flight, []Passenger{}, []Baggage{}}
|
||||
}
|
||||
|
||||
func (ac *Aircraft) ProcessBaggage(fn FlightNumber, b Baggage) error {
|
||||
if fn != ac.Flight.Id {
|
||||
return fmt.Errorf("wrong flight %s", fn)
|
||||
}
|
||||
ac.Baggage = append(ac.Baggage, b)
|
||||
fmt.Printf("loaded baggage %v onto flight %v\n", b, fn)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ac *Aircraft) Process(p Passenger) error {
|
||||
if p.BoardingPass.FlightNumber != ac.Flight.Id {
|
||||
return fmt.Errorf("%s is unauthorized to enter aircraft", p.Name)
|
||||
}
|
||||
ac.Passengers = append(ac.Passengers, p)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ac *Aircraft) Start(gate *Gate, rwy *Runway) {
|
||||
gate.ProcessAircraft(ac)
|
||||
rwy.ProcessAircraft(*ac)
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
package airport
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type Airport struct {
|
||||
Checkin Checkin
|
||||
Security SecurityCheck
|
||||
Gates map[GateNumber]*Gate
|
||||
Runway Runway
|
||||
Bhs *BaggageHandlingSystem
|
||||
FlightSchedule FlightSchedule
|
||||
}
|
||||
|
||||
func DefaultAirport() Airport {
|
||||
|
||||
ap := Airport{
|
||||
Security: NewSecurityCheck(time.Duration(1 * time.Second)),
|
||||
Gates: NewGates(10),
|
||||
Runway: NewRunway(time.Duration(3 * time.Second)),
|
||||
}
|
||||
|
||||
fs := GenerateRandomFlightSchedule(ap.Gates, 10)
|
||||
ap.FlightSchedule = fs
|
||||
|
||||
baggageSinks := make(map[FlightNumber](BaggageProcessor))
|
||||
for _, g := range ap.Gates {
|
||||
|
||||
var flightsForGate []Flight
|
||||
for _, f := range fs.AllFlights() {
|
||||
if f.GateNumber == g.id {
|
||||
flightsForGate = append(flightsForGate, f)
|
||||
}
|
||||
baggageSinks[f.Id] = g
|
||||
}
|
||||
|
||||
g.SetFlights(flightsForGate)
|
||||
ap.Gates[g.id] = g
|
||||
}
|
||||
|
||||
bhs := NewBaggageHandlingSystem(time.Duration(1*time.Second), baggageSinks)
|
||||
ap.Bhs = &bhs
|
||||
ap.Checkin = NewCheckin(time.Duration(1*time.Second), &fs, &bhs)
|
||||
|
||||
return ap
|
||||
}
|
||||
|
||||
func (a *Airport) Start() {
|
||||
go a.Checkin.Start()
|
||||
go a.Security.Start()
|
||||
go a.Bhs.Start()
|
||||
go a.Runway.Start()
|
||||
|
||||
for _, g := range a.Gates {
|
||||
go g.Start()
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Airport) NewPassenger() Passenger {
|
||||
return NewRandomPassenger(a.FlightSchedule.AllFlights())
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
package airport
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type BaggageProcessor interface {
|
||||
ProcessBaggage(FlightNumber, Baggage) error
|
||||
}
|
||||
|
||||
type BaggageHandlingSystem struct {
|
||||
processingTime time.Duration
|
||||
sinks map[FlightNumber]BaggageProcessor
|
||||
//TODO: extend
|
||||
}
|
||||
|
||||
type LostBaggage struct {
|
||||
Baggage
|
||||
FlightNumber FlightNumber
|
||||
Err error
|
||||
}
|
||||
|
||||
var _ BaggageProcessor = &BaggageHandlingSystem{}
|
||||
|
||||
func NewBaggageHandlingSystem(processingTime time.Duration, sinks map[FlightNumber]BaggageProcessor) BaggageHandlingSystem {
|
||||
return BaggageHandlingSystem{
|
||||
processingTime: processingTime,
|
||||
sinks: sinks,
|
||||
}
|
||||
}
|
||||
|
||||
func (bhs *BaggageHandlingSystem) ProcessBaggage(fn FlightNumber, b Baggage) error {
|
||||
//TODO: implement
|
||||
return nil
|
||||
}
|
||||
|
||||
func (bhs *BaggageHandlingSystem) CollectLostBaggage() []LostBaggage {
|
||||
//TODO: implement
|
||||
return nil
|
||||
}
|
||||
|
||||
func (bhs *BaggageHandlingSystem) Start() {
|
||||
//TODO: implement
|
||||
}
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
package airport_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"gitty.informatik.hs-mannheim.de/steger/pr3-code/go/06-airport/airport"
|
||||
)
|
||||
|
||||
type BaggageSpyData struct {
|
||||
fn airport.FlightNumber
|
||||
b airport.Baggage
|
||||
t time.Time
|
||||
}
|
||||
|
||||
type BaggageProcessorSpy struct {
|
||||
Baggage []BaggageSpyData
|
||||
Err error
|
||||
}
|
||||
|
||||
func (bps *BaggageProcessorSpy) ProcessBaggage(fn airport.FlightNumber, b airport.Baggage) error {
|
||||
bps.Baggage = append(bps.Baggage, BaggageSpyData{fn, b, time.Now()})
|
||||
return bps.Err
|
||||
}
|
||||
|
||||
var _ airport.BaggageProcessor = &BaggageProcessorSpy{}
|
||||
|
||||
func compareSink(t *testing.T, expected []airport.Baggage, expectedFlightNumber airport.FlightNumber, got BaggageProcessorSpy, start time.Time) {
|
||||
for _, b := range got.Baggage {
|
||||
if elapsed := b.t.Sub(start); elapsed < 1*time.Millisecond {
|
||||
t.Errorf("processing time too short: got %v, want at least 1ms", elapsed)
|
||||
}
|
||||
|
||||
if b.fn != expectedFlightNumber {
|
||||
t.Errorf("expected flight number: %v, got: %v", expectedFlightNumber, b.fn)
|
||||
}
|
||||
}
|
||||
|
||||
if len(got.Baggage) != len(expected) {
|
||||
t.Errorf("expected number of baggage: %d, got: %d", len(expected), len(got.Baggage))
|
||||
}
|
||||
|
||||
deliveredBaggage := []airport.Baggage{}
|
||||
for _, b := range got.Baggage {
|
||||
deliveredBaggage = append(deliveredBaggage, b.b)
|
||||
}
|
||||
if !reflect.DeepEqual(deliveredBaggage, expected) {
|
||||
t.Errorf("expected delivered baggage for %v: %v, got: %v", expectedFlightNumber, expected, deliveredBaggage)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestBaggageHandlingSystem(t *testing.T) {
|
||||
|
||||
sink123 := BaggageProcessorSpy{nil, nil}
|
||||
sink456 := BaggageProcessorSpy{nil, fmt.Errorf("aircraft already gone")}
|
||||
sinks := map[airport.FlightNumber]airport.BaggageProcessor{
|
||||
airport.FlightNumber("LH123"): &sink123,
|
||||
airport.FlightNumber("LH456"): &sink456,
|
||||
}
|
||||
sut := airport.NewBaggageHandlingSystem(1*time.Millisecond, sinks)
|
||||
go sut.Start()
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
baggage airport.Baggage
|
||||
fn airport.FlightNumber
|
||||
expectErr bool
|
||||
expectDeliveredBaggage123 []airport.Baggage
|
||||
expectDeliveredBaggage456 []airport.Baggage
|
||||
expectLostBaggage []airport.LostBaggage
|
||||
}{
|
||||
{
|
||||
name: "Valid baggage",
|
||||
baggage: airport.Baggage{[]string{"Socks", "Shirts"}},
|
||||
fn: "LH123",
|
||||
expectErr: false,
|
||||
expectDeliveredBaggage123: []airport.Baggage{{[]string{"Socks", "Shirts"}}},
|
||||
expectDeliveredBaggage456: []airport.Baggage{},
|
||||
expectLostBaggage: []airport.LostBaggage{},
|
||||
},
|
||||
{
|
||||
name: "Aircraft already gone",
|
||||
baggage: airport.Baggage{[]string{"Socks", "Shirts"}},
|
||||
fn: "LH456",
|
||||
expectErr: false,
|
||||
expectDeliveredBaggage123: []airport.Baggage{},
|
||||
expectDeliveredBaggage456: []airport.Baggage{{[]string{"Socks", "Shirts"}}},
|
||||
expectLostBaggage: []airport.LostBaggage{
|
||||
{
|
||||
airport.Baggage{[]string{"Socks", "Shirts"}},
|
||||
"LH456",
|
||||
fmt.Errorf("aircraft already gone"),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Unknown flight",
|
||||
baggage: airport.Baggage{[]string{"Socks", "Shirts"}},
|
||||
fn: "XX999",
|
||||
expectErr: true,
|
||||
expectDeliveredBaggage123: []airport.Baggage{},
|
||||
expectDeliveredBaggage456: []airport.Baggage{},
|
||||
expectLostBaggage: []airport.LostBaggage{},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
sink123.Baggage = []BaggageSpyData{}
|
||||
sink456.Baggage = []BaggageSpyData{}
|
||||
start := time.Now()
|
||||
|
||||
err := sut.ProcessBaggage(tc.fn, tc.baggage)
|
||||
|
||||
time.Sleep(10 * time.Millisecond) //not really threadsafe because the 10 milliseconds have never been guaranteed. TODO: replace by sync mechanism
|
||||
|
||||
if (err != nil) != tc.expectErr {
|
||||
t.Errorf("expected error: %v, got: %v", tc.expectErr, err != nil)
|
||||
}
|
||||
|
||||
compareSink(t, tc.expectDeliveredBaggage123, "LH123", sink123, start)
|
||||
compareSink(t, tc.expectDeliveredBaggage456, "LH456", sink456, start)
|
||||
|
||||
lostBaggage := sut.CollectLostBaggage()
|
||||
if !reflect.DeepEqual(lostBaggage, tc.expectLostBaggage) {
|
||||
t.Errorf("expected lost baggage: %v, got: %v", tc.expectLostBaggage, lostBaggage)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
package airport
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Checkin struct {
|
||||
processingTime time.Duration
|
||||
queue chan passengerCheckinData
|
||||
flightProvider FlightProvider
|
||||
baggageProcessor BaggageProcessor
|
||||
}
|
||||
|
||||
type passengerCheckinData struct {
|
||||
p *Passenger
|
||||
err chan error
|
||||
}
|
||||
|
||||
func NewCheckin(processingTime time.Duration, fp FlightProvider, bp BaggageProcessor) Checkin {
|
||||
return Checkin{
|
||||
processingTime: processingTime,
|
||||
queue: make(chan passengerCheckinData),
|
||||
flightProvider: fp,
|
||||
baggageProcessor: bp,
|
||||
}
|
||||
}
|
||||
|
||||
func (c Checkin) Process(p *Passenger) error {
|
||||
err := make(chan error)
|
||||
c.queue <- passengerCheckinData{p: p, err: err}
|
||||
return <-err
|
||||
}
|
||||
|
||||
func (c Checkin) Start() {
|
||||
defer fmt.Println("checkin terminated")
|
||||
for element := range c.queue {
|
||||
|
||||
time.Sleep(c.processingTime)
|
||||
|
||||
//1. check ticket
|
||||
if element.p.Name != element.p.Ticket.Name {
|
||||
element.err <- fmt.Errorf("name %s on ticket does not match", element.p.Ticket.Name)
|
||||
continue
|
||||
}
|
||||
|
||||
flight, err := c.flightProvider.GetFlight(element.p.Ticket.FlightNumber)
|
||||
if err != nil {
|
||||
element.err <- err
|
||||
continue
|
||||
}
|
||||
|
||||
//2. issue boarding pass
|
||||
element.p.BoardingPass = &BoardingPass{element.p.Ticket, flight.GateNumber}
|
||||
|
||||
//3. check in bags
|
||||
var baggageErr error
|
||||
for _, bag := range element.p.Bags {
|
||||
if err := c.baggageProcessor.ProcessBaggage(flight.Id, bag); err != nil {
|
||||
baggageErr = errors.Join(baggageErr, err)
|
||||
}
|
||||
}
|
||||
if baggageErr != nil {
|
||||
element.err <- baggageErr
|
||||
continue
|
||||
}
|
||||
element.p.Bags = []Baggage{}
|
||||
|
||||
element.err <- nil
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
package airport_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"gitty.informatik.hs-mannheim.de/steger/pr3-code/go/06-airport/airport"
|
||||
)
|
||||
|
||||
type FlightProviderStub struct {
|
||||
}
|
||||
|
||||
func (fps FlightProviderStub) GetFlight(fn airport.FlightNumber) (airport.Flight, error) {
|
||||
if fn == "LH123" {
|
||||
return airport.Flight{"LH123", "FRA", airport.GateNumber(1), time.Now(), time.Now()}, nil
|
||||
}
|
||||
return airport.Flight{}, fmt.Errorf("unknown flight %v", fn)
|
||||
}
|
||||
|
||||
var _ airport.FlightProvider = FlightProviderStub{}
|
||||
|
||||
func TestCheckin(t *testing.T) {
|
||||
|
||||
fp := FlightProviderStub{}
|
||||
bps := BaggageProcessorSpy{}
|
||||
sut := airport.NewCheckin(1*time.Millisecond, &fp, &bps)
|
||||
go sut.Start()
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
passenger airport.Passenger
|
||||
expectErr bool
|
||||
expectBaggage []airport.Baggage
|
||||
expectBoardingpass *airport.BoardingPass
|
||||
expectBPSBaggage []airport.Baggage
|
||||
}{
|
||||
{
|
||||
name: "Valid passenger with valid flight",
|
||||
passenger: airport.Passenger{
|
||||
"Max Mustermann",
|
||||
airport.Ticket{"Max Mustermann", "FRA", "LH123"},
|
||||
nil,
|
||||
[]airport.Baggage{{[]string{"Socks", "Shirts"}}},
|
||||
[]string{},
|
||||
},
|
||||
expectErr: false,
|
||||
expectBaggage: []airport.Baggage{},
|
||||
expectBoardingpass: &airport.BoardingPass{airport.Ticket{"Max Mustermann", "FRA", "LH123"}, airport.GateNumber(1)},
|
||||
expectBPSBaggage: []airport.Baggage{{[]string{"Socks", "Shirts"}}},
|
||||
},
|
||||
{
|
||||
name: "Passenger with unknown flight",
|
||||
passenger: airport.Passenger{
|
||||
"John Doe",
|
||||
airport.Ticket{"John Doe", "MUC", "LH999"},
|
||||
nil,
|
||||
[]airport.Baggage{{[]string{"Socks", "Shirts"}}},
|
||||
[]string{},
|
||||
},
|
||||
expectErr: true,
|
||||
expectBaggage: []airport.Baggage{{[]string{"Socks", "Shirts"}}},
|
||||
expectBoardingpass: nil,
|
||||
expectBPSBaggage: []airport.Baggage{},
|
||||
},
|
||||
{
|
||||
name: "Passenger with wrong ticket",
|
||||
passenger: airport.Passenger{
|
||||
"Max Mustermann",
|
||||
airport.Ticket{"Someone else", "FRA", "LH123"},
|
||||
nil,
|
||||
[]airport.Baggage{{[]string{"Socks", "Shirts"}}},
|
||||
[]string{},
|
||||
},
|
||||
expectErr: true,
|
||||
expectBaggage: []airport.Baggage{{[]string{"Socks", "Shirts"}}},
|
||||
expectBoardingpass: nil,
|
||||
expectBPSBaggage: []airport.Baggage{},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
bps.Baggage = []BaggageSpyData{}
|
||||
|
||||
start := time.Now()
|
||||
err := sut.Process(&tc.passenger)
|
||||
|
||||
if elapsed := time.Since(start); elapsed < 1*time.Millisecond {
|
||||
t.Errorf("processing time too short: got %v, want at least 1ms", elapsed)
|
||||
}
|
||||
|
||||
if (err != nil) != tc.expectErr {
|
||||
t.Errorf("expected error: %v, got: %v", tc.expectErr, err != nil)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(tc.passenger.BoardingPass, tc.expectBoardingpass) {
|
||||
t.Errorf("expected boarding pass: %v, got: %v", tc.expectBoardingpass, tc.passenger.BoardingPass)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(tc.passenger.Bags, tc.expectBaggage) {
|
||||
t.Errorf("expected baggage: %v, got: %v", tc.expectBaggage, tc.passenger.Bags)
|
||||
}
|
||||
|
||||
gotBPSBaggage := []airport.Baggage{}
|
||||
for _, b := range bps.Baggage {
|
||||
gotBPSBaggage = append(gotBPSBaggage, b.b)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(gotBPSBaggage, tc.expectBPSBaggage) {
|
||||
t.Errorf("expected baggage processor baggage: %v, got: %v", tc.expectBPSBaggage, gotBPSBaggage)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
package airport
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type FlightNumber string
|
||||
|
||||
type Flight struct {
|
||||
Id FlightNumber
|
||||
Destination string
|
||||
GateNumber GateNumber
|
||||
BoardingTime time.Time
|
||||
DepartureTime time.Time
|
||||
}
|
||||
|
||||
type FlightProvider interface {
|
||||
GetFlight(FlightNumber) (Flight, error)
|
||||
}
|
||||
|
||||
type FlightSchedule struct {
|
||||
flights map[FlightNumber]Flight
|
||||
}
|
||||
|
||||
var possibleDestinations = []string{
|
||||
"AMS", "ATH", "BCN", "BRU", "BUD", "CPH", "DUB", "DUS", "EDI", "FCO",
|
||||
"FRA", "GVA", "HEL", "IST", "LIS", "LYS", "MAD", "MUC", "OSL", "PRG",
|
||||
"RIX", "SOF", "STO", "TLL", "VIE", "WAW", "ZAG", "ZRH", "LUX", "MLA",
|
||||
}
|
||||
|
||||
func GenerateRandomFlightNumbers(count int) []FlightNumber {
|
||||
|
||||
airlines := []string{"LH", "AF", "KL", "BA", "SK", "AZ", "IB", "TK", "AY", "OS"}
|
||||
flightNumbers := make([]FlightNumber, count)
|
||||
|
||||
for i := 0; i < count; i++ {
|
||||
airline := airlines[rand.Intn(len(airlines))]
|
||||
number := rand.Intn(9000) + 1000 // Random 4-digit number
|
||||
flightNumbers[i] = FlightNumber(fmt.Sprintf("%s%04d", airline, number))
|
||||
}
|
||||
|
||||
return flightNumbers
|
||||
}
|
||||
|
||||
func GenerateRandomFlightSchedule(gates map[GateNumber]*Gate, count int) FlightSchedule {
|
||||
flightNumbers := GenerateRandomFlightNumbers(count)
|
||||
flights := make(map[FlightNumber]Flight)
|
||||
|
||||
gateNumbers := make([]GateNumber, 0, len(gates))
|
||||
for gn, _ := range gates {
|
||||
gateNumbers = append(gateNumbers, gn)
|
||||
}
|
||||
|
||||
for _, flightNumber := range flightNumbers {
|
||||
destination := possibleDestinations[rand.Intn(len(possibleDestinations))]
|
||||
|
||||
gateNumber := gateNumbers[rand.Intn(len(gateNumbers))]
|
||||
departureTime := time.Now().Add(time.Duration(rand.Intn(5*60)) * time.Second)
|
||||
boardingTime := departureTime.Add(-30 * time.Second)
|
||||
|
||||
flights[flightNumber] = Flight{
|
||||
Id: flightNumber,
|
||||
Destination: destination,
|
||||
GateNumber: gateNumber,
|
||||
BoardingTime: boardingTime,
|
||||
DepartureTime: departureTime,
|
||||
}
|
||||
}
|
||||
|
||||
return FlightSchedule{flights: flights}
|
||||
}
|
||||
|
||||
func (fs *FlightSchedule) AllFlights() []Flight {
|
||||
flights := make([]Flight, 0, len(fs.flights))
|
||||
for _, flight := range fs.flights {
|
||||
flights = append(flights, flight)
|
||||
}
|
||||
return flights
|
||||
}
|
||||
|
||||
func (fs *FlightSchedule) GetFlight(flightNumber FlightNumber) (Flight, error) {
|
||||
if flight, ok := fs.flights[flightNumber]; ok {
|
||||
return flight, nil
|
||||
} else {
|
||||
return Flight{}, fmt.Errorf("invalid flight number %v", flightNumber)
|
||||
}
|
||||
}
|
||||
|
||||
func (fs *FlightSchedule) Print() {
|
||||
fmt.Printf("%-15s %-15s %-10s %-20s %-20s\n", "Flight Number", "Destination", "Gate", "Boarding Time", "Departure Time")
|
||||
fmt.Println(strings.Repeat("-", 80))
|
||||
for _, flight := range fs.AllFlights() {
|
||||
fmt.Printf("%-15s %-15s %-10d %-20s %-20s\n",
|
||||
flight.Id,
|
||||
flight.Destination,
|
||||
flight.GateNumber,
|
||||
flight.BoardingTime.Format("15:04:05"),
|
||||
flight.DepartureTime.Format("15:04:05"),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
package airport
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
var distantFuture = time.Unix(1<<63-1, 0) // Max value for Unix timestamp
|
||||
|
||||
type GateNumber int
|
||||
|
||||
type Gate struct {
|
||||
id GateNumber
|
||||
walkingTimeFromSecurity time.Duration
|
||||
taxiTimeToRunway time.Duration
|
||||
//TODO: extend
|
||||
}
|
||||
|
||||
var _ BaggageProcessor = &Gate{}
|
||||
|
||||
func NewGate(id GateNumber, walkingTimeFromSecurity time.Duration, taxiTimeToRunway time.Duration) Gate {
|
||||
|
||||
return Gate{id,
|
||||
walkingTimeFromSecurity,
|
||||
taxiTimeToRunway,
|
||||
}
|
||||
}
|
||||
|
||||
func NewGates(count int) map[GateNumber]*Gate {
|
||||
gates := make(map[GateNumber]*Gate)
|
||||
for i := range count {
|
||||
walkingTime := time.Duration(5+rand.Intn(6)) * time.Second
|
||||
taxiTime := time.Duration(5+rand.Intn(6)) * time.Second
|
||||
|
||||
gate := NewGate(GateNumber(i+1), walkingTime, taxiTime)
|
||||
gates[GateNumber(i+1)] = &gate
|
||||
}
|
||||
return gates
|
||||
}
|
||||
|
||||
func (g *Gate) SetFlights(flights []Flight) {
|
||||
//TODO: implement
|
||||
}
|
||||
|
||||
// Blocks for the walking distance to the gate + the time until the passenger has boarded
|
||||
func (g *Gate) Process(passenger Passenger) error {
|
||||
//TODO: implement
|
||||
return nil
|
||||
}
|
||||
|
||||
// Blocks until departure (includes taxi time to runway)
|
||||
func (g *Gate) ProcessAircraft(ac *Aircraft) {
|
||||
//TODO: implement
|
||||
}
|
||||
|
||||
func (g *Gate) ProcessBaggage(fn FlightNumber, b Baggage) error {
|
||||
//TODO: implement
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g Gate) Start() {
|
||||
//TODO: implement
|
||||
}
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
package airport_test
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"gitty.informatik.hs-mannheim.de/steger/pr3-code/go/06-airport/airport"
|
||||
)
|
||||
|
||||
func TestGateSingleFlight(t *testing.T) {
|
||||
|
||||
sut := airport.NewGate(airport.GateNumber(25), time.Duration(3*time.Millisecond), time.Duration(1*time.Millisecond))
|
||||
flight := airport.Flight{"LH123", "FRA", 25, time.Now().Add(5 * time.Millisecond), time.Now().Add(10 * time.Millisecond)}
|
||||
sut.SetFlights([]airport.Flight{
|
||||
flight,
|
||||
})
|
||||
go sut.Start()
|
||||
|
||||
start := time.Now()
|
||||
wg := sync.WaitGroup{}
|
||||
|
||||
//the aircraft
|
||||
wg.Add(1)
|
||||
ac := airport.NewAircraft(flight)
|
||||
departureTime := time.Now()
|
||||
go func() { sut.ProcessAircraft(&ac); departureTime = time.Now(); wg.Done() }()
|
||||
|
||||
//the baggage
|
||||
wg.Add(1)
|
||||
baggage := airport.Baggage{[]string{"socks", "shirt"}}
|
||||
var bag1err error
|
||||
go func() { bag1err = sut.ProcessBaggage("LH123", baggage); wg.Done() }()
|
||||
|
||||
//a passenger arriving on time
|
||||
wg.Add(1)
|
||||
ticket1 := airport.Ticket{"John Doe", "FRA", "LH123"}
|
||||
pax1 := airport.Passenger{"John Doe", ticket1, &airport.BoardingPass{ticket1, 25}, []airport.Baggage{}, []string{}}
|
||||
pax1boardingTime := time.Now()
|
||||
var pax1err error
|
||||
go func() { pax1err = sut.Process(pax1); pax1boardingTime = time.Now(); wg.Done() }()
|
||||
|
||||
//another passenger arriving too late
|
||||
wg.Add(1)
|
||||
ticket2 := airport.Ticket{"Jane Doe", "FRA", "LH123"}
|
||||
pax2 := airport.Passenger{"Jane Doe", ticket2, &airport.BoardingPass{ticket2, 25}, []airport.Baggage{}, []string{}}
|
||||
var pax2err error
|
||||
go func() { time.Sleep(8 * time.Millisecond); pax2err = sut.Process(pax2); wg.Done() }()
|
||||
|
||||
//another passenger arriving sometime during boarding
|
||||
wg.Add(1)
|
||||
ticket3 := airport.Ticket{"Alex Smith", "FRA", "LH123"}
|
||||
pax3 := airport.Passenger{"Alex Smith", ticket3, &airport.BoardingPass{ticket3, 25}, []airport.Baggage{}, []string{}}
|
||||
pax3boardingTime := time.Now()
|
||||
var pax3err error
|
||||
go func() {
|
||||
time.Sleep(6 * time.Millisecond)
|
||||
pax3err = sut.Process(pax3)
|
||||
pax3boardingTime = time.Now()
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
//------------------------FROM HERE: checking ----------------------------------
|
||||
wg.Wait()
|
||||
|
||||
//--------------------------check aircraft-------------------
|
||||
if elapsed := departureTime.Sub(start); elapsed < 11*time.Millisecond {
|
||||
t.Errorf("departure time too short: got %v, want at least 11ms", elapsed)
|
||||
}
|
||||
|
||||
expectedBoardedPax := []airport.Passenger{pax1, pax3}
|
||||
if !reflect.DeepEqual(expectedBoardedPax, ac.Passengers) {
|
||||
t.Errorf("boarded passengers mismatch: got %v, want %v", ac.Passengers, expectedBoardedPax)
|
||||
}
|
||||
|
||||
expectedBaggageOnboard := []airport.Baggage{baggage}
|
||||
if !reflect.DeepEqual(expectedBaggageOnboard, ac.Baggage) {
|
||||
t.Errorf("baggage on board mismatch: got %v, want %v", ac.Baggage, expectedBaggageOnboard)
|
||||
}
|
||||
|
||||
//----------------------------check baggage--------------------
|
||||
|
||||
if bag1err != nil {
|
||||
t.Errorf("baggage encountered an error during processing: %v", bag1err)
|
||||
}
|
||||
|
||||
//--------------------------check passengers-------------------
|
||||
|
||||
//boarding can only happen between boarding (5ms from start) and departure (10ms from start)
|
||||
if elapsed := pax1boardingTime.Sub(start); elapsed < 5*time.Millisecond || elapsed > 10*time.Millisecond {
|
||||
t.Errorf("passenger 1 boarding time out of range: got %v, want between 5ms and 10ms", elapsed)
|
||||
}
|
||||
|
||||
if pax1err != nil {
|
||||
t.Errorf("passenger 1 encountered an error during boarding: %v", pax1err)
|
||||
}
|
||||
|
||||
if pax2err == nil {
|
||||
t.Errorf("passenger 2 did not encounter an error during boarding, but was expected to")
|
||||
}
|
||||
|
||||
//boarding can only happen after boarding (5ms from start)
|
||||
if elapsed := pax3boardingTime.Sub(start); elapsed < 5*time.Millisecond {
|
||||
t.Errorf("passenger 3 boarding time out of range: got %v, want more than 5ms", elapsed)
|
||||
}
|
||||
|
||||
if pax3err != nil {
|
||||
t.Errorf("passenger 3 encountered an error during boarding: %v", pax3err)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
package airport
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/pkg/namesgenerator"
|
||||
)
|
||||
|
||||
type Ticket struct {
|
||||
Name string
|
||||
Destination string
|
||||
FlightNumber FlightNumber
|
||||
}
|
||||
|
||||
type BoardingPass struct {
|
||||
Ticket
|
||||
Gate GateNumber
|
||||
}
|
||||
|
||||
type Baggage struct {
|
||||
Items []string
|
||||
}
|
||||
|
||||
type Passenger struct {
|
||||
Name string
|
||||
Ticket Ticket
|
||||
BoardingPass *BoardingPass
|
||||
Bags []Baggage
|
||||
CarryOnItems []string
|
||||
}
|
||||
|
||||
var PossibleItems = []string{
|
||||
"Laptop", "Tablet", "Smartphone", "Headphones", "Charger", "Book", "Magazine", "Notebook", "Pen", "Pencil", "Carabiner",
|
||||
"Water Bottle", "Snacks", "Sandwich", "Camera", "Tripod", "Gun", "Clothes", "Shoes", "Toothbrush", "Toothpaste",
|
||||
"Shampoo", "Conditioner", "Soap", "Deodorant", "Perfume", "Makeup Kit", "Hairbrush", "Comb", "Razor", "Shaving Cream",
|
||||
"First Aid Kit", "Medicine", "Umbrella", "Hat", "Sunglasses", "Scarf", "Gloves", "Wallet", "Passport", "Camping Gear",
|
||||
"Keys", "Watch", "Jewelry", "Flashlight", "Power Bank", "Knife", "USB Drive", "External Hard Drive", "Gaming Console", "Controller",
|
||||
"Board Game", "Puzzle", "Toy", "Explosives", "Stuffed Animal", "Blanket", "Pillow", "Sleeping Bag", "Towel", "Swimsuit",
|
||||
"Goggles", "Flip Flops", "Backpack", "Handbag", "Suitcase", "Briefcase", "Binoculars", "Map", "Guidebook", "Notebook",
|
||||
"Sketchpad", "Paints", "Brushes", "Musical Instrument", "Sheet Music", "Sports Equipment", "Yoga Mat", "Jump Rope", "Resistance Bands",
|
||||
"Tent", "Cooking Utensils", "Portable Stove", "Food Containers", "Water Filter", "Fishing Rod", "Knife Sharpener", "Multi-tool", "Rope",
|
||||
"Compass", "GPS Device", "Safety Vest", "Helmet", "Protective Gear", "Fire Extinguisher", "Matches", "Lighter", "Candles", "Notebook",
|
||||
"Clipboard", "Calculator", "Documents", "Folders", "Envelopes",
|
||||
}
|
||||
|
||||
func NewRandomPassenger(flights []Flight) Passenger {
|
||||
|
||||
// Generate random ticket details
|
||||
name := namesgenerator.GetRandomName(0)
|
||||
flight := flights[rand.Intn(len(flights))]
|
||||
|
||||
ticket := Ticket{
|
||||
Name: name,
|
||||
Destination: flight.Destination,
|
||||
FlightNumber: flight.Id,
|
||||
}
|
||||
|
||||
// Generate random baggage
|
||||
numBags := rand.Intn(3) // Random number of bags (0 to 2)
|
||||
bags := make([]Baggage, numBags)
|
||||
for i := 0; i < numBags; i++ {
|
||||
numItems := rand.Intn(5) + 1 // Random number of items (1 to 5)
|
||||
items := make([]string, numItems)
|
||||
for j := 0; j < numItems; j++ {
|
||||
items[j] = PossibleItems[rand.Intn(len(PossibleItems))]
|
||||
}
|
||||
bags[i] = Baggage{
|
||||
Items: items,
|
||||
}
|
||||
}
|
||||
|
||||
// Generate random carry-on items
|
||||
numCarryOnItems := rand.Intn(3) // Random number of carry-on items (0 to 2)
|
||||
carryOnItems := make([]string, numCarryOnItems)
|
||||
for i := 0; i < numCarryOnItems; i++ {
|
||||
carryOnItems[i] = PossibleItems[rand.Intn(len(PossibleItems))]
|
||||
}
|
||||
|
||||
return Passenger{
|
||||
Name: name,
|
||||
Ticket: ticket,
|
||||
BoardingPass: nil,
|
||||
Bags: bags,
|
||||
CarryOnItems: carryOnItems,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Passenger) Start(ap *Airport) {
|
||||
|
||||
fmt.Printf("%s has arrived at the airport for the flight number %s to %s in %.02f minutes with %d bags and carry-on items: %v\n",
|
||||
p.Name,
|
||||
p.Ticket.FlightNumber,
|
||||
p.Ticket.Destination,
|
||||
time.Until(ap.FlightSchedule.flights[p.Ticket.FlightNumber].DepartureTime).Minutes(),
|
||||
len(p.Bags),
|
||||
p.CarryOnItems)
|
||||
|
||||
err := ap.Checkin.Process(p)
|
||||
if err != nil {
|
||||
fmt.Printf("\033[31m%s: %v\033[0m\n", p.Name, err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("%s completed the checkin procedure and is now heading to security\n", p.Name)
|
||||
|
||||
err = ap.Security.Process(*p)
|
||||
if err != nil {
|
||||
fmt.Printf("\033[31m%s: %v\033[0m\n", p.Name, err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("%s has successfully passed the security check and is now walking to the gate\n", p.Name)
|
||||
|
||||
gate, ok := ap.Gates[p.BoardingPass.Gate]
|
||||
if !ok {
|
||||
fmt.Printf("\033[31m%s: invalid gate number %v\033[0m\n", p.Name, p.BoardingPass.Gate)
|
||||
return
|
||||
}
|
||||
|
||||
err = gate.Process(*p)
|
||||
if err != nil {
|
||||
fmt.Printf("\033[31mError: %s: %v\033[0m\n", p.Name, err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("\033[32m%s has successfully boarded flight %s to %s\033[0m\n", p.Name, p.Ticket.FlightNumber, p.Ticket.Destination)
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
package airport
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Runway struct {
|
||||
takeoffDuration time.Duration
|
||||
queue chan Aircraft
|
||||
}
|
||||
|
||||
func NewRunway(takeoffDuration time.Duration) Runway {
|
||||
return Runway{
|
||||
takeoffDuration: takeoffDuration,
|
||||
queue: make(chan Aircraft),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Runway) Start() {
|
||||
defer fmt.Println("runway terminated")
|
||||
|
||||
for ac := range r.queue {
|
||||
fmt.Printf("Flight %v to %v is taking off\n", ac.Flight.Id, ac.Flight.Destination)
|
||||
time.Sleep(r.takeoffDuration)
|
||||
fmt.Printf("\033[32mFlight %v to %v has taken off with %v passengers and %v bags on board\033[0m\n", ac.Flight.Id, ac.Flight.Destination, int(len(ac.Passengers)), int(len(ac.Baggage)))
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Runway) ProcessAircraft(ac Aircraft) {
|
||||
fmt.Printf("Flight %v is waiting for takeoff\n", ac.Flight.Id)
|
||||
r.queue <- ac
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package airport
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
var prohibitedItems = map[string]bool{"Knife": true, "Gun": true, "Explosives": true}
|
||||
|
||||
type SecurityCheck struct {
|
||||
processingTime time.Duration
|
||||
//TODO: extend
|
||||
}
|
||||
|
||||
func NewSecurityCheck(processingTime time.Duration) SecurityCheck {
|
||||
return SecurityCheck{
|
||||
processingTime: processingTime,
|
||||
}
|
||||
}
|
||||
|
||||
// processes one passenger at a time. Each passenger must at least spend the processingTime at the security check
|
||||
func (sc *SecurityCheck) Start() {
|
||||
//TODO: implement
|
||||
}
|
||||
|
||||
// returns an error if
|
||||
// - the passenger has no boarding pass
|
||||
// - the passenger's boardings pass does not match the name
|
||||
// - the passenger carries a prohibited item
|
||||
func (sc SecurityCheck) Process(p Passenger) error {
|
||||
//TODO: implement
|
||||
return nil
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
package airport_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"gitty.informatik.hs-mannheim.de/steger/pr3-code/go/06-airport/airport"
|
||||
)
|
||||
|
||||
func TestSecurityCheck(t *testing.T) {
|
||||
|
||||
sut := airport.NewSecurityCheck(1 * time.Millisecond)
|
||||
go sut.Start()
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
passenger airport.Passenger
|
||||
expectErr bool
|
||||
}{
|
||||
{
|
||||
name: "Valid passenger",
|
||||
passenger: airport.Passenger{
|
||||
"Max Mustermann",
|
||||
airport.Ticket{"Max Mustermann", "FRA", "LH123"},
|
||||
&airport.BoardingPass{airport.Ticket{"Max Mustermann", "FRA", "LH123"}, airport.GateNumber(1)},
|
||||
[]airport.Baggage{},
|
||||
[]string{"Laptop", "Hat"},
|
||||
},
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "Passenger without boarding pass",
|
||||
passenger: airport.Passenger{
|
||||
"Max Mustermann",
|
||||
airport.Ticket{"Max Mustermann", "FRA", "LH123"},
|
||||
nil,
|
||||
[]airport.Baggage{},
|
||||
[]string{"Laptop", "Hat"},
|
||||
},
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
name: "Passenger with wrong boarding pass",
|
||||
passenger: airport.Passenger{
|
||||
"Max Mustermann",
|
||||
airport.Ticket{"Max Mustermann", "FRA", "LH123"},
|
||||
&airport.BoardingPass{airport.Ticket{"Someone else", "FRA", "LH123"}, airport.GateNumber(1)},
|
||||
[]airport.Baggage{},
|
||||
[]string{"Laptop", "Hat"},
|
||||
},
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
name: "Passenger with prohibited item",
|
||||
passenger: airport.Passenger{
|
||||
"Max Mustermann",
|
||||
airport.Ticket{"Max Mustermann", "FRA", "LH123"},
|
||||
&airport.BoardingPass{airport.Ticket{"Max Mustermann", "FRA", "LH123"}, airport.GateNumber(1)},
|
||||
[]airport.Baggage{},
|
||||
[]string{"Laptop", "Hat", "Knife"},
|
||||
},
|
||||
expectErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
|
||||
start := time.Now()
|
||||
err := sut.Process(tc.passenger)
|
||||
|
||||
if elapsed := time.Since(start); elapsed < 1*time.Millisecond {
|
||||
t.Errorf("processing time too short: got %v, want at least 1ms", elapsed)
|
||||
}
|
||||
|
||||
if (err != nil) != tc.expectErr {
|
||||
t.Errorf("expected error: %v, got: %v", tc.expectErr, err != nil)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
module gitty.informatik.hs-mannheim.de/steger/pr3-code/go/06-airport
|
||||
|
||||
go 1.25.0
|
||||
|
||||
require github.com/docker/docker v28.3.3+incompatible
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
github.com/docker/docker v28.3.3+incompatible h1:Dypm25kh4rmk49v1eiVbsAtpAsYURjYkaKubwuBdxEI=
|
||||
github.com/docker/docker v28.3.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"gitty.informatik.hs-mannheim.de/steger/pr3-code/go/06-airport/airport"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ap := airport.DefaultAirport()
|
||||
|
||||
ap.FlightSchedule.Print()
|
||||
defer func() {
|
||||
lostBaggage := ap.Bhs.CollectLostBaggage()
|
||||
fmt.Println("The following baggage was lost today: ", lostBaggage)
|
||||
}()
|
||||
|
||||
ap.Start()
|
||||
|
||||
for _, flight := range ap.FlightSchedule.AllFlights() {
|
||||
ac := airport.NewAircraft(flight)
|
||||
gate := ap.Gates[flight.GateNumber]
|
||||
go ac.Start(gate, &ap.Runway)
|
||||
}
|
||||
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
|
||||
fmt.Print("What/Who arrives at airport? (p for passenger, c for car, t for train, q to quit): ")
|
||||
for {
|
||||
input, _ := reader.ReadString('\n')
|
||||
input = strings.TrimSpace(input)
|
||||
|
||||
switch input {
|
||||
case "q":
|
||||
fmt.Println("Closing airport")
|
||||
return
|
||||
case "p":
|
||||
p := ap.NewPassenger()
|
||||
go p.Start(&ap)
|
||||
case "c":
|
||||
for i := 0; i < 4; i++ {
|
||||
p := ap.NewPassenger()
|
||||
go p.Start(&ap)
|
||||
}
|
||||
case "t":
|
||||
for i := 0; i < 50; i++ {
|
||||
p := ap.NewPassenger()
|
||||
go p.Start(&ap)
|
||||
}
|
||||
default:
|
||||
fmt.Println("Invalid command.")
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue