Jump to content
The simFlight Network Forums

Schedule analyzer


amif2000

Recommended Posts

This is a short rust program to count the number of departing and arriving flights per hour in a specific airport.

Use it by entering the airport code (KATL, LEBL etc.) as a parameter to the exe you created with cargo build

Note that you may need to change the path variable to match your Tower3D install folder

Also, some airports use a different name for the schedule file and the actual airport name inside that file. The code handles EDDM and LEBL (which I own). You may need to add others.

use std::{env, process, fs};

fn main() {
    let args: Vec<String> = env::args().collect();
    if args.len() < 2 {
        eprintln!("error: missing airport name");
        process::exit(1);
    }
    let airport_name = &args[1].to_uppercase();
    let path = "D:\\Program Files (x86)\\FeelThere\\Tower!3D Pro\\Extensions\\Airfields";
    let filename = format!("{}\\{}\\{}_schedule.txt", path, airport_name, airport_name.to_lowercase());
    let airport = if airport_name == "EDDM" {
        "MUC"
    } else if airport_name == "LEBL" {
        "BCN"
    } else {
        &airport_name[1..]
    };
    let contents = fs::read_to_string(filename)
        .expect("error: failed to open file");
    let mut departures: [u32; 24] = [0; 24];
    let mut arrivals: [u32; 24] = [0; 24];
    for line in contents.lines() {
        if line.len() == 0 {
            continue;
        }
        if line.len() >= 2 && &line[0..2] == "//" {
            continue;
        }
        let tokens: Vec<&str> = line.split(",").collect();
        let origin_ap = tokens[0].trim();
        if origin_ap == airport {
            let token6 = tokens[6].trim();
            let hour: usize = token6[0..2].parse()
                .expect("illegal number in dep.hour");
            departures[hour] += 1;
        } else {
            let token5 = tokens[5].trim();
            let hour: usize = token5[0..2].parse()
                .expect("illegal number in arr.hour");
            arrivals[hour] += 1;
        }
    }
    println!(" Hour | Dep | Arr |Total|");
    println!("-------------------------");
    for hour in 0..24 {
        println!("  {:02}  | {:03} | {:03} | {:03} |",
                 hour, departures[hour], arrivals[hour], arrivals[hour] + departures[hour]);
    }
}
  • Like 1
Link to comment
Share on other sites

This is awesome! I don't personally write in Rust or C/C++,  so I also worked out a (fairly inelegant) solution in Python with Pandas dataframes and NumPy inspired by your Rust solution.

Some caveats:

  1. I added headers to each schedule file manually, so if you want to run the code yourself you have to copy and paste the header line into the text file and save as a csv. The header line is: DEP,ARR,AIR,X,N,TIME,LOL,IDK,CALL
  2. You would need to put in your proper file path for each airfield. I really like the elegance of putting multiple airports in the Rust code and I'm thinking of adding that later to this Python code. This also means you have to be aware of the difference between ICAO and 3-letter code (eg, EDDM = MUC).
  3. Later I intend to add graphing support from MatPlotLib, to visualize frequencies across airfields. 

If you don't want to spend the time to compile and run this yourself or if you don't have Python or Rust on your machine, I've also attached each text document with arrival and departure frequency by hour for every airport below except JFK. I haven't quite worked out why, I'm assuming something with the way the JFK data is formatted but the text file turns out wrong each time I run it on the JFK schedule. 

Some possible uses:

  1. Like me, a gamer who just wants to play busy times for a more engaged experience.
  2. If you develop schedules, particularly busy schedules, a quick way to see when your busy times are without playtesting right away.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

print('Hewwo!')

#Reads schedule CSV into Pandas Dataframe, insert your chosen file path.
df = pd.read_csv(r'''YOUR PATH HERE''')


#Loads second clean Dataframe for later determination of arrival or departure.
df2 = pd.DataFrame(columns = ['ARR','TIME','DEP','DEPTIME','ARRORDEPART'],index = df.index)
df2['ARR']=df['ARR']
df2['DEP']=df['DEP']


#For loop to make all arrival time strings into just the first two digits, indicating hour of the 24 hour clock. EG, 11:24 -> 11, 21:31 -> 21.
i = 0
for i in range(0,len(df2)):
	placeholder = df.TIME[i]
	placeholder2 = placeholder[:-3]
	df2.TIME[i] = placeholder2
	i+1


#For loop to make all departure time strings into just the first two digits, indicating hour of the 24 hour clock. EG, 11:24 -> 11, 21:31 -> 21.
j = 0
for j in range(0,len(df2)):
	placeholder = df.LOL[j]
	placeholder2 = placeholder[:-3]
	df2.DEPTIME[j] = placeholder2
	j+1

#Nifty trick with Pandas and Numpy to find and assign arrival or departure values based on the Arrivals column in the second dataframe. Definitely 
#look up a good Stackoverflow if you're curious how this works, I'm still getting the hang of it myself after trying to write a lot of different more 
#standrad loops before this. NOTE: YOU NEED THE SPACE BEFORE THE AIRPORT CODE BASED ON HOW I PERSONALLY SET UP THIS DATAFRAME. I will likely fix this later.
df2.ARRORDEPART = np.where(df2['ARR']==' 3 DIGIT AIRPORT CODE EG JFK or MUC','Arrive','Depart')


#Actually builds out the text files provided. In lines 41 and 43, only standard print functions. In 42 and 44, group by functions to first select what we're counting,
#then group by all the possible hours for arrivals and departures, based on the dataframe. 
print("Arrival Count:", file = open(r'''YOUR PATH HERE\0YOURCITY.txt''',"a"))
print(df2[df2['ARRORDEPART'] == 'Arrive'].groupby('TIME')['ARRORDEPART'].count(), file = open(r'''YOUR PATH HERE\0YOURCITY.txt''',"a"))
print("Departure Count:", file = open(r'''YOUR PATH HERE\0YOURCITY.txt''',"a"))
print(df2[df2['ARRORDEPART'] == 'Depart'].groupby('DEPTIME')['ARRORDEPART'].count(), file = open(r'''YOUR PATH HERE\0YOURCITY.txt''',"a"))

print("Goodbye!")

#At some point, I also intend to explore graphing these sets with Matplotlib, and writing a file chooser so you don't have to manually enter your desired
#airport info.

 

0atlanta.txt

0barcelona.txt

0boston.txt

0lasvegas.txt

0londongatwick.txt

0losangeles.txt

0memphis.txt

0munich.txt

0newyorklaguardia.txt

0orlando.txt

0philadelphia.txt

0phoenix.txt

0sandiego.txt

0sanfrancisco.txt

0stthomas.txt

0stuttgart.txt

0vancouver.txt

Link to comment
Share on other sites

@bingus I love your idea of adding some graphic information. I modified my code slightly to do just that (in ASCII😄)

replace the bottom part of the code with the following snippet.

for hour in 0..24 {
    let total = arrivals[hour] + departures[hour];
    print!("  {:02}  | {:03} | {:03} | {:03} |",
             hour, departures[hour], arrivals[hour], total);
    println!("{}", "#".repeat((total as usize + 4) / 5));
}

The results look like this:

 Hour | Dep | Arr |Total|
-------------------------
  00  | 005 | 005 | 010 |##
  01  | 003 | 001 | 004 |#
  02  | 001 | 000 | 001 |#
  03  | 002 | 001 | 003 |#
  04  | 000 | 007 | 007 |##
  05  | 003 | 014 | 017 |####
  06  | 018 | 030 | 048 |##########
  07  | 037 | 071 | 108 |######################
  08  | 081 | 096 | 177 |####################################
  09  | 083 | 084 | 167 |##################################
  10  | 100 | 049 | 149 |##############################

Link to comment
Share on other sites

On 6/1/2019 at 1:45 AM, alaskaGuy2018 said:

I have the program rust now but don't know what I have to do with it or how to put the information from that screen shot into it for this work 

I haven't dealt with Rust yet. But I liked the idea in this thread.
Since I still had an unused domain, I created a little website (nothing fancy) where you can upload the *schedule.txt and *.gaandlocaltraffic.txt to get a graphical representation of the movements per hour.
If I get the OK from FeelThere, I will post the URL here in the forum.

  • Upvote 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use. Guidelines Privacy Policy We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.