Soybean Data


Top 10 Global Crops

  • Dataframe: top10_crops_2021.df
  • Data Source: FAOSTATS
    • Downloaded global crop production data for 2021
    • Imported CSV data into Excel (world_crop_data_2021.xlsx)
    • Sorted by tons descending to find Top 10 crops
    • Divided tons by 1 billion to give billion_tons
    • Exported crop, tons, billion_tons columns as CSV file (top10_crops_2021.csv)

    top10_crops_2021.df <- read.csv(“top10_crops_2021.csv”) %>% arrange(desc(billion_tons))

Global Soybean Production

  • Dataframe: top5_countries.df

  • Data Source: USDA/IPAD

    Top 5 Soy Countries
    top5_countries <- c(‘Brazil’, ‘United States’, ‘China’, ‘Argentina’, ‘India’)

    Pct of Soy Production
    top5_countries_pct <- c(42, 31, 7, 5, 3)

    Create Top 5 Soy Countries df
    top5_countries.df <- data.frame(top5_countries, top5_countries_pct) %>%
    arrange(desc(top5_countries_pct))

Soybean Production - All States

  • Table: prod_yield_all_states_2000_2022

  • Data Source: soybeans_prod_yield_2000-22.csv

  • SQL Query: project_check_null_production_values 

    SELECT Value
    FROM prod_yield_all_states_2000_2022
    WHERE Value IS NULL
     

  • SQL Query: project_check_max_min_production_values 

    SELECT
    Max(Value) as max_value,
    MIN(Value) as min_value
    FROM prod_yield_all_states_2000_2022
     

FIPS State Codes

  • Table: bigquery-public-data.census_utility.fips_codes_states

Top 11 Soybean Producing States

  • Table: top_11_soy_states

    • Created separate table for Top 11 States to facilitate JOINS with weather tables

  • SQL Query: project_create_table_top11_states

    CREATE TABLE top_11_soy_states AS
    SELECT
    State as state,
    fips.state_postal_abbreviation as st_abv, – from BiqQuery - Census FIPS Utility dataset
    SUM(Value) AS bushels_total,
    ROUND((SUM(Value) / (SELECT SUM(Value) FROM prod_yield_all_states_2000_2022)) * 100, 2) AS pct_total_bushels,
    ROUND(SUM(SUM(Value)) OVER (ORDER BY SUM(Value) DESC ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) / (SELECT SUM(Value) FROM prod_yield_all_states_2000_2022) * 100, 2) AS cumulative_pct
    FROM prod_yield_all_states_2000_2022 AS soy
    LEFT JOIN bigquery-public-data.census_utility.fips_codes_states AS fips
    ON soy.State = UPPER(fips.state_name)
    GROUP BY state, st_abv
    ORDER BY bushels_total DESC
    LIMIT 11
     

Soybean Production - Top 11 States

  • Table: prod_yield_top11_states

  • SQL Query: project_create_table_prod_data_top11_states

    # Create Table of Selected Soy Data Columns for Top 11 States
    CREATE TABLE prod_yield_top11_states AS
    SELECT
    # filter for the relevant data columns found in the complete dataset
    all_states.Year as year,
    all_states.State as state,
    # Rename Data_Item values to more concise descriptors
    CASE all_states.Data_Item
    WHEN ‘SOYBEANS - PRODUCTION, MEASURED IN BU’ THEN ‘total_bushels’
    WHEN ‘SOYBEANS - YIELD, MEASURED IN BU / ACRE’ THEN ‘bushels_acre’
    ELSE all_states.Data_Item
    END as measure, # rename column to more concise descriptor
    all_states.Value as quantity # rename column to more concise descriptor
    # Soybeans dataset from NASS for all states
    From prod_yield_all_states_2000_2022 as all_states
    # Subset of all_states dataset to filter for top 11 soybean producing states
    JOIN top_11_soy_states as top_states
    ON all_states.State = top_states.state # Inner Join filters dataset for top 11 states
    GROUP BY state, year, measure, quantity
    ORDER BY year, state, measure
     

Soybean Monthly Prices for All States: 2000-2022

  • Table: prices_bushel_pct_parity_2000-22
  • Data Source: soybeans_prices_2000-2022.csv

Soybean Monthly Prices for Top 11 States: 2000-2022

  • Table: soybean_prices_monthly_top11_states

  • SQL Query: project_create_table_monthly_prices_2000-22_top_11_states

    # Create Table of Monthly Soybean Prices for Top 11 States
    CREATE TABLE soybean_prices_monthly_top11_states AS
    SELECT
    # Cast Year(INT) as STRING, then Concat with Period(MON) and parse the resulting string as DATE
    PARSE_DATE(‘%Y %b’, CONCAT(CAST(all_states.Year as STRING),” “, all_states.Period)) as price_period,
    all_states.State as state,
    top_states.st_abv,
    CAST(all_states.Value AS FLOAT64) as usd_bushel, –value in dataset is USD/bushels; cast as INT
    # Soybeans dataset from NASS for all states
    From prices_bushel_pct_parity_2000-22 as all_states
    # Subset of all_states dataset to filter for top 11 soybean producing states
    JOIN top_11_soy_states as top_states
    ON all_states.State = top_states.state # Inner Join filters dataset for top 11 states
    WHERE NOT CONTAINS_SUBSTR(all_states.Value,”(D)“) # NASS witholds data that will identify specific growers
    GROUP BY state, st_abv, price_period, usd_bushel
    ORDER BY price_period
     


Weather Data


Global NOAA GSOD Stations

  • Table: bigquery-public-data.noaa_gsod.stations

  • SQL Query: project_verify_usaf_wban_lengths 

    # verify lengths of the usaf and wban codes used in the NOAA stations table
    SELECT
    MIN(CHAR_LENGTH(usaf)) as min_usaf_length,
    MAX(CHAR_LENGTH(usaf)) as max_usaf_length,
    MIN(CHAR_LENGTH(wban)) as min_length_wban,
    MAX(CHAR_LENGTH(wban)) as max_length_wban
    FROM bigquery-public-data.noaa_gsod.stations
     

NOAA GSOD Stations for Top 11 Soybean States

  • Table: soy_states_noaa_stns

  • SQL Query: project_verify_stn_code_max_min_length  

    # verify the length of the station code used in annual GSOD tables
    SELECT
    MIN(CHAR_LENGTH(stn)) as min_stn_length,
    MAX(CHAR_LENGTH(stn)) as max_stn_length
    FROM bigquery-public-data.noaa_gsod.gsod2000 
     

  • SQL Query: project_us_weather_stns_nulls 

    – check whether generic code ‘999999’ used for usaf codes for stations within top soy states
    SELECT *  FROM bigquery-public-data.noaa_gsod.stations as noaa
    JOIN top_11_soy_states as soy
    ON noaa.state = soy.st_abv
    WHERE noaa.usaf = ‘999999’ # gsod.stations uses ‘999999’ as generic station code for multiple stations 
     

  • SQL Query: project_concat_wban_soy_states 

    # verify whether gsod station reports used 5 digit wban codes with a leading “0” as the 6 digit stn code
    WITH soy_wban AS
    (SELECT CONCAT(“0”,wban) as xwban
    FROM soy_states_noaa_stns
    WHERE wban != “99999”) # “99999” used as null values
    SELECT
    DISTINCT(gs.station),
    gs.location,
    gs.state
    FROM weather_top11_states as gs
    JOIN soy_wban
    ON soy_wban.xwban = gs.station
    ORDER BY gs.station
     

  • SQL Query: project_create_table_soy_states_noaa_stns  

    CREATE TABLE soy_states_noaa_stns AS
    SELECT usaf, wban, name, soy.state, st_abv
    FROM bigquery-public-data.noaa_gsod.stations as noaa
    JOIN top_11_soy_states as soy
    ON noaa.state = soy.st_abv
    WHERE noaa.usaf != ‘999999’ – gsod.stations uses ‘999999’ as generic station code for multiple stations
    ORDER BY noaa.state
     

Weather Data 2000-2022 for Top 11 Soybean States

  • Table: weather_top11_states

  • SQL Query: project_create_table_weather_top11_states_nulls 

    # – Create Table of Weather Data for Top 11 States
    CREATE TABLE weather_top11_states_nulls AS
    SELECT
    all_states.stn as station,
    # Concat with year, mo, da and parse the resulting string as a DATE
    PARSE_DATE(‘%F’, CONCAT(all_states.year,“-”,all_states.mo,“-”,all_states.da)) as weather_date,
    top_states.name as location,
    top_states.state,
    top_states.st_abv,
    NULLIF(all_states.temp, 9999.9) as mean_temp,
    NULLIF(all_states.max, 9999.9) as max_temp,
    NULLIF(all_states.min, 9999.9) as min_temp,
    NULLIF(all_states.prcp, 99.99) as precip
    # Weather dataset from Big Query GSOD - Union all datasets 2000-2022 for all states
    From bigquery-public-data.noaa_gsod.gsod20* as all_states
    # Join on Top 11 States NOAA stations to filter for top 11 States
    JOIN soy_states_noaa_stns as top_states
    ON
    all_states.stn = top_states.usaf # Inner Join filters dataset by NOAA stations for top 11 states
    WHERE
    NOT all_states.stn = “999999” – Generic code assigned to numerous stations globally
    AND
    NOT CONTAINS_SUBSTR(all_states.year, “2023”)
    GROUP BY
    station, location, state, st_abv, weather_date, mean_temp, max_temp, min_temp, precip
     

LS0tDQp0aXRsZTogIlNveWJlYW5zIERhdGFzZXRzIENoYW5nZSBMb2ciDQphdXRob3I6ICJSZWVkIFNsYWNrIg0KZGF0ZTogIkxhc3QgVXBkYXRlZDogYHIgU3lzLkRhdGUoKWAiDQpvdXRwdXQ6IA0KICBodG1sX25vdGVib29rOg0KICAgIHRoZW1lOiBjZXJ1bGVhbg0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19kZXB0aDogNA0KICAgIHRvY19mbG9hdDogdHJ1ZQ0KICANCi0tLQ0KDQpgYGB7Y3NzLCBlY2hvPUZBTFNFfQ0KcCwgYm9keSB7DQogIGZvbnQtc2l6ZTogMTZweDsNCn0NCmBgYA0KDQpcDQoNCiMjIyAqKlNveWJlYW4gRGF0YSoqDQpcDQoNCiMjIyMgKlRvcCAxMCBHbG9iYWwgQ3JvcHMqIA0KDQotICoqRGF0YWZyYW1lOioqIHRvcDEwX2Nyb3BzXzIwMjEuZGYNCi0gKipEYXRhIFNvdXJjZToqKiBbRkFPU1RBVFNdKGh0dHBzOi8vd3d3LmZhby5vcmcvZmFvc3RhdC9lbi8jZGF0YS9RQ0wpDQogIC0gRG93bmxvYWRlZCBnbG9iYWwgY3JvcCBwcm9kdWN0aW9uIGRhdGEgZm9yIDIwMjENCiAgLSBJbXBvcnRlZCBDU1YgZGF0YSBpbnRvIEV4Y2VsICh3b3JsZF9jcm9wX2RhdGFfMjAyMS54bHN4KQ0KICAtIFNvcnRlZCBieSB0b25zIGRlc2NlbmRpbmcgdG8gZmluZCBUb3AgMTAgY3JvcHMNCiAgLSBEaXZpZGVkIHRvbnMgYnkgMSBiaWxsaW9uIHRvIGdpdmUgYmlsbGlvbl90b25zDQogIC0gRXhwb3J0ZWQgY3JvcCwgdG9ucywgYmlsbGlvbl90b25zIGNvbHVtbnMgYXMgQ1NWIGZpbGUgKHRvcDEwX2Nyb3BzXzIwMjEuY3N2KQ0KXA0KXA0KDQogID4gdG9wMTBfY3JvcHNfMjAyMS5kZiA8LSByZWFkLmNzdigidG9wMTBfY3JvcHNfMjAyMS5jc3YiKSAlPiUgDQogIGFycmFuZ2UoZGVzYyhiaWxsaW9uX3RvbnMpKQ0KDQojIyMjICpHbG9iYWwgU295YmVhbiBQcm9kdWN0aW9uKg0KLSAqKkRhdGFmcmFtZToqKiB0b3A1X2NvdW50cmllcy5kZg0KLSAqKkRhdGEgU291cmNlOioqIFtVU0RBL0lQQURdKGh0dHBzOi8vaXBhZC5mYXMudXNkYS5nb3YvY3JvcGV4cGxvcmVyL2Nyb3B2aWV3L2NvbW1vZGl0eVZpZXcuYXNweD9jcm9waWQ9MjIyMjAwMCZzZWxfeWVhcj0yMDIyJnJhbmtieT1Qcm9kdWN0aW9uKQ0KDQogID5Ub3AgNSBTb3kgQ291bnRyaWVzXA0KdG9wNV9jb3VudHJpZXMgPC0gYygnQnJhemlsJywgJ1VuaXRlZCBTdGF0ZXMnLCAnQ2hpbmEnLCAnQXJnZW50aW5hJywgJ0luZGlhJylcDQpcDQpQY3Qgb2YgU295IFByb2R1Y3Rpb25cDQp0b3A1X2NvdW50cmllc19wY3QgPC0gYyg0MiwgMzEsIDcsIDUsIDMpXA0KXA0KQ3JlYXRlIFRvcCA1IFNveSBDb3VudHJpZXMgZGZcDQp0b3A1X2NvdW50cmllcy5kZiA8LSBkYXRhLmZyYW1lKHRvcDVfY291bnRyaWVzLCB0b3A1X2NvdW50cmllc19wY3QpICU+JSBcDQogIGFycmFuZ2UoZGVzYyh0b3A1X2NvdW50cmllc19wY3QpKVwNCg0KDQoNCiMjIyMgKlNveWJlYW4gUHJvZHVjdGlvbiAtIEFsbCBTdGF0ZXMqIFwNCg0KICAtICoqVGFibGU6KiogcHJvZF95aWVsZF9hbGxfc3RhdGVzXzIwMDBfMjAyMiANCiAgLSAqKkRhdGEgU291cmNlOioqIHNveWJlYW5zX3Byb2RfeWllbGRfMjAwMC0yMi5jc3YNCiAgLSAqKlNRTCBRdWVyeToqKiBwcm9qZWN0X2NoZWNrX251bGxfcHJvZHVjdGlvbl92YWx1ZXNcIA0KDQogICAgPjxmb250IHNpemU9LTE+U0VMRUNUIFZhbHVlIFwNCkZST00gcHJvZF95aWVsZF9hbGxfc3RhdGVzXzIwMDBfMjAyMiBcDQpXSEVSRSBWYWx1ZSBJUyBOVUxMPC9mb250PiBcIA0KXA0KICAtICoqU1FMIFF1ZXJ5OioqIHByb2plY3RfY2hlY2tfbWF4X21pbl9wcm9kdWN0aW9uX3ZhbHVlc1wgDQoNCiAgICA+PGZvbnQgc2l6ZT0tMT5TRUxFQ1QgXA0KICBNYXgoVmFsdWUpIGFzIG1heF92YWx1ZSxcDQogIE1JTihWYWx1ZSkgYXMgbWluX3ZhbHVlIFwNCkZST00gcHJvZF95aWVsZF9hbGxfc3RhdGVzXzIwMDBfMjAyMjwvZm9udD4gXCANClwNCg0KIyMjIyAqRklQUyBTdGF0ZSBDb2RlcyoNCg0KLSAqKlRhYmxlOioqIGJpZ3F1ZXJ5LXB1YmxpYy1kYXRhLmNlbnN1c191dGlsaXR5LmZpcHNfY29kZXNfc3RhdGVzXA0KXA0KDQojIyMjICpUb3AgMTEgU295YmVhbiBQcm9kdWNpbmcgU3RhdGVzKlwNCg0KLSAqKlRhYmxlOioqIHRvcF8xMV9zb3lfc3RhdGVzDQogICsgQ3JlYXRlZCBzZXBhcmF0ZSB0YWJsZSBmb3IgVG9wIDExIFN0YXRlcyB0byBmYWNpbGl0YXRlIEpPSU5TIHdpdGggd2VhdGhlciB0YWJsZXNcDQpcDQotICoqU1FMIFF1ZXJ5OioqIHByb2plY3RfY3JlYXRlX3RhYmxlX3RvcDExX3N0YXRlcyBcDQoNCiAgPjxmb250IHNpemU9LTE+Q1JFQVRFIFRBQkxFIHRvcF8xMV9zb3lfc3RhdGVzIEFTIFwNClNFTEVDVCBcDQogIFN0YXRlIGFzIHN0YXRlLCBcDQogIGZpcHMuc3RhdGVfcG9zdGFsX2FiYnJldmlhdGlvbiBhcyBzdF9hYnYsIC0tIGZyb20gQmlxUXVlcnkgLSBDZW5zdXMgRklQUyBVdGlsaXR5IGRhdGFzZXQgXA0KICBTVU0oVmFsdWUpIEFTIGJ1c2hlbHNfdG90YWwsIFwNCiAgUk9VTkQoKFNVTShWYWx1ZSkgLyAoU0VMRUNUIFNVTShWYWx1ZSkgRlJPTSBwcm9kX3lpZWxkX2FsbF9zdGF0ZXNfMjAwMF8yMDIyKSkgKiAxMDAsIDIpIEFTIHBjdF90b3RhbF9idXNoZWxzLCBcDQogIFJPVU5EKFNVTShTVU0oVmFsdWUpKSBPVkVSIChPUkRFUiBCWSBTVU0oVmFsdWUpIERFU0MgUk9XUyBCRVRXRUVOIFVOQk9VTkRFRCBQUkVDRURJTkcgQU5EIENVUlJFTlQgUk9XKSAvIChTRUxFQ1QgU1VNKFZhbHVlKSBGUk9NIHByb2RfeWllbGRfYWxsX3N0YXRlc18yMDAwXzIwMjIpICogMTAwLCAyKSBBUyBjdW11bGF0aXZlX3BjdCBcDQpGUk9NIHByb2RfeWllbGRfYWxsX3N0YXRlc18yMDAwXzIwMjIgQVMgc295IFwNCkxFRlQgSk9JTiBiaWdxdWVyeS1wdWJsaWMtZGF0YS5jZW5zdXNfdXRpbGl0eS5maXBzX2NvZGVzX3N0YXRlcyBBUyBmaXBzIFwNCk9OIHNveS5TdGF0ZSA9IFVQUEVSKGZpcHMuc3RhdGVfbmFtZSkgXA0KR1JPVVAgQlkgc3RhdGUsIHN0X2FidiBcDQpPUkRFUiBCWSBidXNoZWxzX3RvdGFsIERFU0MgXA0KTElNSVQgMTE8L2ZvbnQ+XCANClwNCg0KIyMjIyAqU295YmVhbiBQcm9kdWN0aW9uIC0gVG9wIDExIFN0YXRlcypcDQoNCi0gKipUYWJsZToqKiBwcm9kX3lpZWxkX3RvcDExX3N0YXRlc1wNCi0gKipTUUwgUXVlcnk6KiogcHJvamVjdF9jcmVhdGVfdGFibGVfcHJvZF9kYXRhX3RvcDExX3N0YXRlcyBcDQoNCiAgPjxmb250IHNpemU9LTE+IyBDcmVhdGUgVGFibGUgb2YgU2VsZWN0ZWQgU295IERhdGEgQ29sdW1ucyBmb3IgVG9wIDExIFN0YXRlcyBcDQpDUkVBVEUgVEFCTEUgcHJvZF95aWVsZF90b3AxMV9zdGF0ZXMgQVMgXA0KU0VMRUNUIFwNCiAgIyBmaWx0ZXIgZm9yIHRoZSByZWxldmFudCBkYXRhIGNvbHVtbnMgZm91bmQgaW4gdGhlIGNvbXBsZXRlIGRhdGFzZXRcDQogIGFsbF9zdGF0ZXMuWWVhciBhcyB5ZWFyLFwNCiAgYWxsX3N0YXRlcy5TdGF0ZSBhcyBzdGF0ZSxcDQogICMgUmVuYW1lIERhdGFfSXRlbSB2YWx1ZXMgdG8gbW9yZSBjb25jaXNlIGRlc2NyaXB0b3JzXA0KICBDQVNFIGFsbF9zdGF0ZXMuRGF0YV9JdGVtXA0KICAgICAgV0hFTiAnU09ZQkVBTlMgLSBQUk9EVUNUSU9OLCBNRUFTVVJFRCBJTiBCVScgVEhFTiAndG90YWxfYnVzaGVscydcDQogICAgICBXSEVOICdTT1lCRUFOUyAtIFlJRUxELCBNRUFTVVJFRCBJTiBCVSAvIEFDUkUnIFRIRU4gJ2J1c2hlbHNfYWNyZSdcDQogICAgICBFTFNFIGFsbF9zdGF0ZXMuRGF0YV9JdGVtXA0KICAgICAgRU5EIGFzIG1lYXN1cmUsICMgcmVuYW1lIGNvbHVtbiB0byBtb3JlIGNvbmNpc2UgZGVzY3JpcHRvclwNCiAgYWxsX3N0YXRlcy5WYWx1ZSBhcyBxdWFudGl0eSAjIHJlbmFtZSBjb2x1bW4gdG8gbW9yZSBjb25jaXNlIGRlc2NyaXB0b3JcDQojIFNveWJlYW5zIGRhdGFzZXQgZnJvbSBOQVNTIGZvciBhbGwgc3RhdGVzIFwNCkZyb20gcHJvZF95aWVsZF9hbGxfc3RhdGVzXzIwMDBfMjAyMiBhcyBhbGxfc3RhdGVzXA0KIyBTdWJzZXQgb2YgYWxsX3N0YXRlcyBkYXRhc2V0IHRvIGZpbHRlciBmb3IgdG9wIDExIHNveWJlYW4gcHJvZHVjaW5nIHN0YXRlc1wNCkpPSU4gdG9wXzExX3NveV9zdGF0ZXMgYXMgdG9wX3N0YXRlc1wNCk9OIGFsbF9zdGF0ZXMuU3RhdGUgPSB0b3Bfc3RhdGVzLnN0YXRlICMgSW5uZXIgSm9pbiBmaWx0ZXJzIGRhdGFzZXQgZm9yIHRvcCAxMSBzdGF0ZXNcDQpHUk9VUCBCWSBzdGF0ZSwgeWVhciwgbWVhc3VyZSwgcXVhbnRpdHlcDQpPUkRFUiBCWSB5ZWFyLCBzdGF0ZSwgbWVhc3VyZTwvZm9udD5cIA0KXA0KICAgIA0KIyMjIyAqU295YmVhbiBNb250aGx5IFByaWNlcyBmb3IgQWxsIFN0YXRlczogMjAwMC0yMDIyKg0KLSAqKlRhYmxlOioqIHByaWNlc19idXNoZWxfcGN0X3Bhcml0eV8yMDAwLTIyXA0KLSAqKkRhdGEgU291cmNlOioqIHNveWJlYW5zX3ByaWNlc18yMDAwLTIwMjIuY3N2XA0KXA0KDQojIyMjICpTb3liZWFuIE1vbnRobHkgUHJpY2VzIGZvciBUb3AgMTEgU3RhdGVzOiAyMDAwLTIwMjIqDQogICAgDQogIC0gKipUYWJsZToqKiBzb3liZWFuX3ByaWNlc19tb250aGx5X3RvcDExX3N0YXRlcw0KICAtICoqU1FMIFF1ZXJ5OioqIHByb2plY3RfY3JlYXRlX3RhYmxlX21vbnRobHlfcHJpY2VzXzIwMDAtMjJfdG9wXzExX3N0YXRlcyAgXA0KDQogICAgPjxmb250IHNpemU9LTE+IyBDcmVhdGUgVGFibGUgb2YgTW9udGhseSBTb3liZWFuIFByaWNlcyBmb3IgVG9wIDExIFN0YXRlc1wNCkNSRUFURSBUQUJMRSBzb3liZWFuX3ByaWNlc19tb250aGx5X3RvcDExX3N0YXRlcyBBU1wNClNFTEVDVFwNCiAgIyBDYXN0IFllYXIoSU5UKSBhcyBTVFJJTkcsIHRoZW4gQ29uY2F0IHdpdGggUGVyaW9kKE1PTikgYW5kIHBhcnNlIHRoZSByZXN1bHRpbmcgc3RyaW5nIGFzIERBVEVcDQogIFBBUlNFX0RBVEUoJyVZICViJywgQ09OQ0FUKENBU1QoYWxsX3N0YXRlcy5ZZWFyIGFzIFNUUklORyksIiAiLCBhbGxfc3RhdGVzLlBlcmlvZCkpIGFzIHByaWNlX3BlcmlvZCxcDQogIGFsbF9zdGF0ZXMuU3RhdGUgYXMgc3RhdGUsXA0KICB0b3Bfc3RhdGVzLnN0X2FidixcDQogIENBU1QoYWxsX3N0YXRlcy5WYWx1ZSBBUyBGTE9BVDY0KSBhcyB1c2RfYnVzaGVsLCAtLXZhbHVlIGluIGRhdGFzZXQgaXMgVVNEL2J1c2hlbHM7IGNhc3QgYXMgSU5UXA0KIyBTb3liZWFucyBkYXRhc2V0IGZyb20gTkFTUyBmb3IgYWxsIHN0YXRlcyBcDQpGcm9tIHByaWNlc19idXNoZWxfcGN0X3Bhcml0eV8yMDAwLTIyIGFzIGFsbF9zdGF0ZXNcDQojIFN1YnNldCBvZiBhbGxfc3RhdGVzIGRhdGFzZXQgdG8gZmlsdGVyIGZvciB0b3AgMTEgc295YmVhbiBwcm9kdWNpbmcgc3RhdGVzXA0KSk9JTiB0b3BfMTFfc295X3N0YXRlcyBhcyB0b3Bfc3RhdGVzXA0KT04gYWxsX3N0YXRlcy5TdGF0ZSA9IHRvcF9zdGF0ZXMuc3RhdGUgIyBJbm5lciBKb2luIGZpbHRlcnMgZGF0YXNldCBmb3IgdG9wIDExIHN0YXRlc1wNCldIRVJFIE5PVCBDT05UQUlOU19TVUJTVFIoYWxsX3N0YXRlcy5WYWx1ZSwgIihEKSIpICMgTkFTUyB3aXRob2xkcyBkYXRhIHRoYXQgd2lsbCBpZGVudGlmeSBzcGVjaWZpYyBncm93ZXJzXA0KR1JPVVAgQlkgc3RhdGUsIHN0X2FidiwgcHJpY2VfcGVyaW9kLCB1c2RfYnVzaGVsXA0KT1JERVIgQlkgcHJpY2VfcGVyaW9kPC9mb250PlwgDQoNClwNCg0KIyMjICoqV2VhdGhlciBEYXRhKioNClwNCg0KIyMjIyAqR2xvYmFsIE5PQUEgR1NPRCBTdGF0aW9ucyogXA0KDQogIC0gKipUYWJsZToqKiBiaWdxdWVyeS1wdWJsaWMtZGF0YS5ub2FhX2dzb2Quc3RhdGlvbnMNCiAgLSAqKlNRTCBRdWVyeToqKiAgcHJvamVjdF92ZXJpZnlfdXNhZl93YmFuX2xlbmd0aHNcIA0KDQogICAgPjxmb250IHNpemU9LTE+IyB2ZXJpZnkgbGVuZ3RocyBvZiB0aGUgdXNhZiBhbmQgd2JhbiBjb2RlcyB1c2VkIGluIHRoZSBOT0FBIHN0YXRpb25zIHRhYmxlXA0KU0VMRUNUIFwNCiAgTUlOKENIQVJfTEVOR1RIKHVzYWYpKSBhcyBtaW5fdXNhZl9sZW5ndGgsXA0KICBNQVgoQ0hBUl9MRU5HVEgodXNhZikpIGFzIG1heF91c2FmX2xlbmd0aCxcDQogIE1JTihDSEFSX0xFTkdUSCh3YmFuKSkgYXMgbWluX2xlbmd0aF93YmFuLFwNCiAgTUFYKENIQVJfTEVOR1RIKHdiYW4pKSBhcyBtYXhfbGVuZ3RoX3diYW4gXA0KRlJPTSBiaWdxdWVyeS1wdWJsaWMtZGF0YS5ub2FhX2dzb2Quc3RhdGlvbnMgPC9mb250PiBcIA0KXA0KDQojIyMjICpOT0FBIEdTT0QgU3RhdGlvbnMgZm9yIFRvcCAxMSBTb3liZWFuIFN0YXRlcyogXA0KDQogIC0gKipUYWJsZToqKiBzb3lfc3RhdGVzX25vYWFfc3Rucw0KDQogIC0gKipTUUwgUXVlcnk6KiogcHJvamVjdF92ZXJpZnlfc3RuX2NvZGVfbWF4X21pbl9sZW5ndGggXCANCg0KICAgID48Zm9udCBzaXplPS0xPiMgdmVyaWZ5IHRoZSBsZW5ndGggb2YgdGhlIHN0YXRpb24gY29kZSB1c2VkIGluIGFubnVhbCBHU09EIHRhYmxlcyBcDQpTRUxFQ1QgXA0KICBNSU4oQ0hBUl9MRU5HVEgoc3RuKSkgYXMgbWluX3N0bl9sZW5ndGgsXA0KICBNQVgoQ0hBUl9MRU5HVEgoc3RuKSkgYXMgbWF4X3N0bl9sZW5ndGhcDQpGUk9NIGJpZ3F1ZXJ5LXB1YmxpYy1kYXRhLm5vYWFfZ3NvZC5nc29kMjAwMFwgDQo8L2ZvbnQ+IFwgDQpcDQoNCiAgLSAqKlNRTCBRdWVyeToqKiBwcm9qZWN0X3VzX3dlYXRoZXJfc3Ruc19udWxsc1wgDQoNCiAgICA+PGZvbnQgc2l6ZT0tMT4tLSBjaGVjayB3aGV0aGVyIGdlbmVyaWMgY29kZSAnOTk5OTk5JyB1c2VkIGZvciB1c2FmIGNvZGVzIGZvciBzdGF0aW9ucyB3aXRoaW4gdG9wIHNveSBzdGF0ZXNcDQpTRUxFQ1QgKlwgDQpGUk9NIGJpZ3F1ZXJ5LXB1YmxpYy1kYXRhLm5vYWFfZ3NvZC5zdGF0aW9ucyBhcyBub2FhXA0KSk9JTiB0b3BfMTFfc295X3N0YXRlcyBhcyBzb3lcDQpPTiBub2FhLnN0YXRlID0gc295LnN0X2FidlwNCldIRVJFIG5vYWEudXNhZiA9ICc5OTk5OTknICAjIGdzb2Quc3RhdGlvbnMgdXNlcyAnOTk5OTk5JyBhcyBnZW5lcmljIHN0YXRpb24gY29kZSBmb3IgbXVsdGlwbGUgc3RhdGlvbnNcIDwvZm9udD4gXCANClwNCg0KICAtICoqU1FMIFF1ZXJ5OioqIHByb2plY3RfY29uY2F0X3diYW5fc295X3N0YXRlc1wgDQoNCiAgICA+PGZvbnQgc2l6ZT0tMT4jIHZlcmlmeSB3aGV0aGVyIGdzb2Qgc3RhdGlvbiByZXBvcnRzIHVzZWQgNSBkaWdpdCB3YmFuIGNvZGVzIHdpdGggYSBsZWFkaW5nICIwIiBhcyB0aGUgNiBkaWdpdCBzdG4gY29kZSBcDQpXSVRIIHNveV93YmFuIEFTXA0KKFNFTEVDVCBDT05DQVQoIjAiLHdiYW4pIGFzIHh3YmFuIFwNCkZST00gc295X3N0YXRlc19ub2FhX3N0bnMgXA0KV0hFUkUgd2JhbiAhPSAiOTk5OTkiKSAjICI5OTk5OSIgdXNlZCBhcyBudWxsIHZhbHVlcyBcDQpTRUxFQ1QgXA0KICBESVNUSU5DVChncy5zdGF0aW9uKSxcDQogIGdzLmxvY2F0aW9uLFwNCiAgZ3Muc3RhdGVcDQpGUk9NIHdlYXRoZXJfdG9wMTFfc3RhdGVzIGFzIGdzXA0KSk9JTiBzb3lfd2JhblwNCk9OIHNveV93YmFuLnh3YmFuID0gZ3Muc3RhdGlvblwNCk9SREVSIEJZIGdzLnN0YXRpb248L2ZvbnQ+IFwgDQpcDQoNCiAgLSAqKlNRTCBRdWVyeToqKiBwcm9qZWN0X2NyZWF0ZV90YWJsZV9zb3lfc3RhdGVzX25vYWFfc3RucyBcIA0KDQogICAgPjxmb250IHNpemU9LTE+Q1JFQVRFIFRBQkxFIHNveV9zdGF0ZXNfbm9hYV9zdG5zIEFTIFwNClNFTEVDVCB1c2FmLCB3YmFuLCBuYW1lLCBzb3kuc3RhdGUsIHN0X2FidiBcDQpGUk9NIGJpZ3F1ZXJ5LXB1YmxpYy1kYXRhLm5vYWFfZ3NvZC5zdGF0aW9ucyBhcyBub2FhXA0KSk9JTiB0b3BfMTFfc295X3N0YXRlcyBhcyBzb3lcDQpPTiBub2FhLnN0YXRlID0gc295LnN0X2FidiBcDQpXSEVSRSBub2FhLnVzYWYgIT0gJzk5OTk5OScgLS0gZ3NvZC5zdGF0aW9ucyB1c2VzICc5OTk5OTknIGFzIGdlbmVyaWMgc3RhdGlvbiBjb2RlIGZvciBtdWx0aXBsZSBzdGF0aW9ucyBcDQpPUkRFUiBCWSBub2FhLnN0YXRlPC9mb250PiBcIA0KXA0KDQoNCiMjIyMgKldlYXRoZXIgRGF0YSAyMDAwLTIwMjIgZm9yIFRvcCAxMSBTb3liZWFuIFN0YXRlcyogXA0KDQogIC0gKipUYWJsZToqKiB3ZWF0aGVyX3RvcDExX3N0YXRlcw0KDQogIC0gKipTUUwgUXVlcnk6KiogcHJvamVjdF9jcmVhdGVfdGFibGVfd2VhdGhlcl90b3AxMV9zdGF0ZXNfbnVsbHNcIA0KDQogICAgPjxmb250IHNpemU9LTE+IyAtLSBDcmVhdGUgVGFibGUgb2YgV2VhdGhlciBEYXRhIGZvciBUb3AgMTEgU3RhdGVzIFwNCkNSRUFURSBUQUJMRSB3ZWF0aGVyX3RvcDExX3N0YXRlc19udWxscyBBU1wNClNFTEVDVFwNCiAgYWxsX3N0YXRlcy5zdG4gYXMgc3RhdGlvbixcDQogICMgQ29uY2F0IHdpdGggeWVhciwgbW8sIGRhIGFuZCBwYXJzZSB0aGUgcmVzdWx0aW5nIHN0cmluZyBhcyBhIERBVEVcDQogIFBBUlNFX0RBVEUoJyVGJywgQ09OQ0FUKGFsbF9zdGF0ZXMueWVhciwiLSIsYWxsX3N0YXRlcy5tbywiLSIsYWxsX3N0YXRlcy5kYSkpIGFzIHdlYXRoZXJfZGF0ZSxcDQogIHRvcF9zdGF0ZXMubmFtZSBhcyBsb2NhdGlvbixcDQogIHRvcF9zdGF0ZXMuc3RhdGUsXA0KICB0b3Bfc3RhdGVzLnN0X2FidixcDQogIE5VTExJRihhbGxfc3RhdGVzLnRlbXAsIDk5OTkuOSkgYXMgbWVhbl90ZW1wLFwNCiAgTlVMTElGKGFsbF9zdGF0ZXMubWF4LCA5OTk5LjkpIGFzIG1heF90ZW1wLFwNCiAgTlVMTElGKGFsbF9zdGF0ZXMubWluLCA5OTk5LjkpIGFzIG1pbl90ZW1wLFwNCiAgTlVMTElGKGFsbF9zdGF0ZXMucHJjcCwgOTkuOTkpIGFzIHByZWNpcFwNCiMgV2VhdGhlciBkYXRhc2V0IGZyb20gQmlnIFF1ZXJ5IEdTT0QgLSBVbmlvbiBhbGwgZGF0YXNldHMgMjAwMC0yMDIyIGZvciBhbGwgc3RhdGVzIFwNCkZyb20gYmlncXVlcnktcHVibGljLWRhdGEubm9hYV9nc29kLmdzb2QyMCogYXMgYWxsX3N0YXRlc1wNCiMgSm9pbiBvbiBUb3AgMTEgU3RhdGVzIE5PQUEgc3RhdGlvbnMgdG8gZmlsdGVyIGZvciB0b3AgMTEgU3RhdGVzXA0KSk9JTiBzb3lfc3RhdGVzX25vYWFfc3RucyBhcyB0b3Bfc3RhdGVzXA0KT05cDQphbGxfc3RhdGVzLnN0biA9IHRvcF9zdGF0ZXMudXNhZiAjIElubmVyIEpvaW4gZmlsdGVycyBkYXRhc2V0IGJ5IE5PQUEgc3RhdGlvbnMgZm9yIHRvcCAxMSBzdGF0ZXNcDQpXSEVSRVwNCiAgTk9UIGFsbF9zdGF0ZXMuc3RuID0gIjk5OTk5OSIgLS0gR2VuZXJpYyBjb2RlIGFzc2lnbmVkIHRvIG51bWVyb3VzIHN0YXRpb25zIGdsb2JhbGx5XA0KICBBTkRcDQogIE5PVCBDT05UQUlOU19TVUJTVFIoYWxsX3N0YXRlcy55ZWFyLCAiMjAyMyIpXA0KR1JPVVAgQllcDQogIHN0YXRpb24sIGxvY2F0aW9uLCBzdGF0ZSwgc3RfYWJ2LCB3ZWF0aGVyX2RhdGUsIG1lYW5fdGVtcCwgbWF4X3RlbXAsIG1pbl90ZW1wLCBwcmVjaXBcDQo8L2ZvbnQ+IFwgDQpcDQoNCg==