This lab journal demonstrates how academic fields are assigned to
researchers based on their publications.
Custom functions
fpackage.check
: Check if packages are installed (and
install if not) in R (source).
fpackage.check <- function(packages) {
lapply(packages, FUN = function(x) {
if (!require(x, character.only = TRUE)) {
install.packages(x, dependencies = TRUE)
library(x, character.only = TRUE)
}
})
}
Packages
tidyverse
: some tidy data crunching later
on
data.table
: the reduce computing time, especially
using the unique
function with big data
kableExtra
: to make HTML tables
packages = c("tidyverse", "data.table", "kableExtra")
fpackage.check(packages)
Publications data
In order to assign a field to individual researchers, we look at
their publications, and specifically at the journal outlets in which
people publish. For this, we use the publications listed on researchers’
personal NARCIS profiles.
For three PhD’s in our example data frame, we have compiled a
(fictional) publication track record, to show what this publication data
looks like.
The id
variable references the personal identifiers,
which can also be found in the PhD dataset so that PhDs can be matched
to their own publications. Furthermore, the data provide information on
the type
of publication and the date in which the
publication was published (date.issued
). Lastly, the
journal name (journame
) is used alongside ISSN codes (not
pictured in this example dataframe) to match publications to academic
disciplines.
knitr::kable(pubs_metadf, format = "markdown")
Matching journal names
to fields
To match publications with academic disciplines based on journal
names, we use a list of Web of Science indexed journals with associated
fields and subfields, according to the field classification by the U.S.
National Research Council.
Each journal is associated with one or more specific academic
disciplines (subfields), which fall under a broader disciplinary
categorization (fields). In the example here, the entry for the “Journal
of Ecclesiastical History” is associated with the subfields “history”
and “religion”, both of which fall under “humanities”. Since we only
look at the broader discipline, this does not matter for our field
variable, and we can simply assign “humanities” as the field.
knitr::kable(journals_wos[journals_wos$ISSN == "0022-0469", ], format = "markdown")
In some cases, however, a journal is associated with multiple broader
fields. We then assign the field which occurs most frequently within the
journal.
In the case of the journal “ACS Photonics”, this implies that we
assign “engineering” as the broader field.
In the case of the “International Labour Review”, it is more tricky:
the journal is split 50/50 between “social and behavioral sciences” and
“humanities”. In these cases, we randomly pick one of the fields.
knitr::kable(journals_wos[(journals_wos$ISSN == "2330-4022" | journals_wos$ISSN == "0020-7780"), ], format = "markdown")
Next, we match the journals in the Web of Science list to the
publication outlet information in our own publication dataset. We first
match on ISSN, which provides us information on the field of 70% of the
unique journals in our data. Next, we match on journal names, which
increases the recall on our field indicator to 75% of the unique
journals.
In this example dataframe, we randomly picked journals from the Web
of Science list, meaning all publications with a journal can be matched
to a field.
knitr::kable(pubs_field, format = "markdown")
Creating a
time-invariant field variable for each PhD
We determine a researcher’s field based on their publications during
and right after their PhD. Thus, we first exclude publications from more
than 5 years before, or more than three years after they received
doctorate. Next, we tally up the fields across all these publications,
and take the field which occurs most frequently.
# first, we add the publications data to our phd dataframe
phdfield <- left_join(pubs_field, phd_df, by = "id")
# then we clean the date.issued variable
phdfield$pubyear <- as.numeric(substr(phdfield$date.issued, 1, 4))
# selecting publications from during and right after the PhD
phdfield %>%
filter((pubyear < (phd_year + 3)) & (pubyear > (phd_year - 5))) -> phdfield
# field = field which the majority of one's publication fall under
phdfield %>%
group_by(id) %>%
add_count(nrc_field) %>%
slice_max(n) %>%
ungroup() -> phdfield
# maintain a single line per id/field combo
phdfield %>%
group_by(id, nrc_field) %>%
slice_head() %>%
ungroup() -> phdfield
As we see from the results below, one of the three researchers was
assigned a single field. The other two (f and g) are split evenly
between two fields. In this case, we take one of the fields at
random.
knitr::kable(phdfield[, c(1, 5, 16)], format = "markdown")
Selecting a field at random for those who are split exactly evenly
between multiple fields.
phdfield %>%
group_by(id) %>%
slice_sample(n = 1) -> phdfield
Finally, we omit the ‘business’ and ‘law’ fields because they are
small and scientists in these fields tend to have atypical career paths.
Furthermore, we combine ‘social and behavioral sciences’ and ‘education’
under a single category.
phdfield$field2 <- phdfield$field <- phdfield$nrc_field
phdfield$field2 <- fct_collapse(phdfield$field2, `Agricultural Sciences` = "Agricultural Sciences", `Biological and Health Sciences` = "Biological and Health Sciences",
other = c("Business", "Law"), Engineering = "Engineering", Humanities = "Humanities", `Social and Behavioral Sciences` = c("Social and Behavioral Sciences",
"Education"), `Physical and Mathematical Sciences` = "Physical and Mathematical Sciences")
levels(phdfield$field2)[levels(phdfield$field2) == "other"] <- NA
levels(phdfield$field2)
# create and explicit 'missing' category
phdfield <- phdfield %>%
mutate(field = fct_explicit_na(field, na_level = "missing"), field2 = fct_explicit_na(field2, na_level = "missing"))
phdfield$field <- factor(phdfield$field, levels = c("Biological and Health Sciences", "Physical and Mathematical Sciences",
"Social and Behavioral Sciences", "Engineering", "Agricultural Sciences", "Humanities", "Business",
"Education", "Law", "missing"))
phdfield$field2 <- factor(phdfield$field2, levels = c("Biological and Health Sciences", "Physical and Mathematical Sciences",
"Social and Behavioral Sciences", "Engineering", "Agricultural Sciences", "Humanities", "missing"))
Output
After this, we are left with a dataset of PhDs + fields for each PhD
with publications in the specified timeframe.
LS0tDQp0aXRsZTogIkFjYWRlbWljIGZpZWxkcyINCmRhdGU6ICJMYXN0IGNvbXBpbGVkIG9uIGByIGZvcm1hdChTeXMudGltZSgpLCAnJUIsICVZJylgIg0Kb3V0cHV0OiANCiAgaHRtbF9kb2N1bWVudDoNCiAgICBjc3M6IHR3ZWFrcy5jc3MNCiAgICB0b2M6ICB0cnVlDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlDQogICAgY29kZV9mb2xkaW5nOiBzaG93DQogICAgY29kZV9kb3dubG9hZDogeWVzDQotLS0NCg0KDQoNCmBgYHtyLCBnbG9iYWxzZXR0aW5ncywgZWNobz1GQUxTRSwgd2FybmluZz1GQUxTRSwgcmVzdWx0cz0iaGlkZSJ9DQoNCnJlcXVpcmUoa25pdHIpDQpvcHRzX2NodW5rJHNldCh0aWR5Lm9wdHM9bGlzdCh3aWR0aC5jdXRvZmY9MTAwKSx0aWR5PVRSVUUsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFLGNvbW1lbnQgPSAiIz4iLCBjYWNoZT1UUlVFLCBjbGFzcy5zb3VyY2U9YygidGVzdCIpLCBjbGFzcy5vdXRwdXQ9YygidGVzdDIiKSwgY2FjaGUubGF6eSA9IEZBTFNFLCBldmFsID0gRkFMU0UpDQpvcHRpb25zKHdpZHRoID0gMTAwKQ0KcmdsOjpzZXR1cEtuaXRyKCkNCg0KY29sb3JpemUgPC0gZnVuY3Rpb24oeCwgY29sb3IpIHtzcHJpbnRmKCI8c3BhbiBzdHlsZT0nY29sb3I6ICVzOyc+JXM8L3NwYW4+IiwgY29sb3IsIHgpIH0NCg0KYGBgDQoNCmBgYHtyIGtsaXBweSwgZWNobz1GQUxTRSwgaW5jbHVkZT1UUlVFLCBldmFsPVRSVUV9DQprbGlwcHk6OmtsaXBweShwb3NpdGlvbiA9IGMoJ3RvcCcsICdyaWdodCcpKQ0KI2tsaXBweTo6a2xpcHB5KGNvbG9yID0gJ2RhcmtyZWQnKQ0KI2tsaXBweTo6a2xpcHB5KHRvb2x0aXBfbWVzc2FnZSA9ICdDbGljayB0byBjb3B5JywgdG9vbHRpcF9zdWNjZXNzID0gJ0RvbmUnKQ0KYGBgDQoNCi0tLS0NCg0KVGhpcyBsYWIgam91cm5hbCBkZW1vbnN0cmF0ZXMgaG93IGFjYWRlbWljIGZpZWxkcyBhcmUgYXNzaWduZWQgdG8gcmVzZWFyY2hlcnMgYmFzZWQgb24gdGhlaXIgcHVibGljYXRpb25zLiAgICANCiAgDQotLS0tDQoNCg0KYGBge3IsIGVjaG89RkFMU0V9DQoNCnJtKGxpc3QgPSBscygpKQ0KDQpgYGANCg0KDQoNCiMgQ3VzdG9tIGZ1bmN0aW9ucw0KDQotIGBmcGFja2FnZS5jaGVja2A6IENoZWNrIGlmIHBhY2thZ2VzIGFyZSBpbnN0YWxsZWQgKGFuZCBpbnN0YWxsIGlmIG5vdCkgaW4gUiAoW3NvdXJjZV0oaHR0cHM6Ly92YmFsaWdhLmdpdGh1Yi5pby92ZXJpZnktdGhhdC1yLXBhY2thZ2VzLWFyZS1pbnN0YWxsZWQtYW5kLWxvYWRlZC8pKS4gIA0KDQpgYGB7ciBjdXN0b21mdW5jdGlvbnMsIHJlc3VsdHM9J2hpZGUnfQ0KDQpmcGFja2FnZS5jaGVjayA8LSBmdW5jdGlvbihwYWNrYWdlcykgew0KICBsYXBwbHkocGFja2FnZXMsIEZVTiA9IGZ1bmN0aW9uKHgpIHsNCiAgICBpZiAoIXJlcXVpcmUoeCwgY2hhcmFjdGVyLm9ubHkgPSBUUlVFKSkgew0KICAgICAgaW5zdGFsbC5wYWNrYWdlcyh4LCBkZXBlbmRlbmNpZXMgPSBUUlVFKQ0KICAgICAgbGlicmFyeSh4LCBjaGFyYWN0ZXIub25seSA9IFRSVUUpDQogICAgfQ0KICB9KQ0KfQ0KDQpgYGANCg0KLS0tICANCg0KIyBQYWNrYWdlcw0KDQotIGB0aWR5dmVyc2VgOiBzb21lIHRpZHkgZGF0YSBjcnVuY2hpbmcgbGF0ZXIgb24NCg0KLSBgZGF0YS50YWJsZWA6IHRoZSByZWR1Y2UgY29tcHV0aW5nIHRpbWUsIGVzcGVjaWFsbHkgdXNpbmcgdGhlIGB1bmlxdWVgIGZ1bmN0aW9uIHdpdGggYmlnIGRhdGENCg0KLSBga2FibGVFeHRyYWA6IHRvIG1ha2UgSFRNTCB0YWJsZXMNCg0KYGBge3IsIHJlc3VsdHM9J2hpZGUnfQ0KDQpwYWNrYWdlcyA9IGMoInRpZHl2ZXJzZSIsICJkYXRhLnRhYmxlIiwgImthYmxlRXh0cmEiKQ0KDQpmcGFja2FnZS5jaGVjayhwYWNrYWdlcykNCg0KYGBgDQoNCi0tLSANCg0KIyBJbnB1dA0KDQpXZSB1c2UgZm91ciBkYXRhc2V0cyBpbiB0aGlzIGZpbGU6DQoNCiogW2pvdXJuYWxzX3dvc10oaHR0cHM6Ly9naXRodWIuY29tL2FtbXVsZGVycy9hbWF0dGVyb2Z0aW1lL2RhdGEvam91cm5hbHNfZGlzY2lwbGluZS9qb3VybmFsc193b3MucmRhKTogSm91cm5hbHMgaW4gV29TIGFuZCBhc3NvY2lhdGVkIGRpc2NpcGxpbmVzIChleGFtcGxlKQ0KICAgIC0gTmFtZTogYGpvdXJuYWxzX3dvc2AgIA0KICANCiogW3B1YnNfbWV0YWRmXShodHRwczovL2dpdGh1Yi5jb20vYW1tdWxkZXJzL2FtYXR0ZXJvZnRpbWUvZGF0YS9wdWJzX21ldGFkZi5yZGEpOiBQdWJsaWNhdGlvbiBtZXRhZGF0YSBmb3IgdGhyZWUgUGhEcyBmcm9tIHRoZSBleGFtcGxlIGRhdGFzZXQNCiAgICAtIE5hbWU6IGBwdWJzX21ldGFkZmANCg0KKiBbcHVic19maWVsZF0oaHR0cHM6Ly9naXRodWIuY29tL2FtbXVsZGVycy9hbWF0dGVyb2Z0aW1lL2RhdGEvam91cm5hbHNfZGlzY2lwbGluZS9wdWJzX2ZpZWxkLnJkYSk6IE1hdGNoZWQgcHVibGljYXRpb24gYW5kIGZpZWxkIGRhdGFzZXQgZm9yIHRoZSB0aHJlZSBQaERzIGluIFsocHVic19tZXRhZGYpXQ0KICAgIC0gTmFtZTogYHB1YnNfbWV0YWRmYA0KICAgIA0KKiBbcGhkZ2VuZGVyXShodHRwczovL2dpdGh1Yi5jb20vYW1tdWxkZXJzL2FtYXR0ZXJvZnRpbWUvZGF0YS9wcm9jZXNzZWQvcGhkZ2VuZGVyLnJkYSk6IFByb2Nlc3NlZCBQaEQgZGF0YSBpbmNsdWRpbmcgZ2VuZGVyIGFuZCBldGhuaWNpdHkgdmFyaWFibGVzDQogICAgLSBOYW1lOiBgcGhkZ2VuZGVyYCAgDQogDQoNCmBgYCB7ciBkYXRhIGxvYWRpbmcsIGNhY2hlID0gVFJVRX0NCg0KIyBleGFtcGxlIG9mIFdvUyBqb3VybmFsLWZpZWxkIGxpc3QNCmxvYWQoImRhdGEvam91cm5hbHNfZGlzY2lwbGluZS9qb3VybmFsc193b3MucmRhIikNCg0KIyBMb2FkIHB1YmxpY2F0aW9uIG1ldGFkYXRhIA0KbG9hZCgiZGF0YS9wdWJzX21ldGFkZi5yZGEiKQ0KDQojIFB1YmxpY2F0aW9ucyB3aXRoIGZpZWxkcyBhdHRhY2hlZA0KbG9hZCgiZGF0YS9qb3VybmFsc19kaXNjaXBsaW5lL3B1YnNfZmllbGQucmRhIikNCg0KIyBMb2FkIFBoRCBkYXRhc2V0DQpsb2FkKCJkYXRhL3Byb2Nlc3NlZC9waGRnZW5kZXIucmRhIikNCnBoZF9kZiA8LSBwaGRnZW5kZXINCg0KYGBgDQoNCi0tLQ0KDQoNCiMgUHVibGljYXRpb25zIGRhdGENCg0KSW4gb3JkZXIgdG8gYXNzaWduIGEgZmllbGQgdG8gaW5kaXZpZHVhbCByZXNlYXJjaGVycywgd2UgbG9vayBhdCB0aGVpciBwdWJsaWNhdGlvbnMsIGFuZCBzcGVjaWZpY2FsbHkgYXQgdGhlIGpvdXJuYWwgb3V0bGV0cyBpbiB3aGljaCBwZW9wbGUgcHVibGlzaC4gRm9yIHRoaXMsIHdlIHVzZSB0aGUgcHVibGljYXRpb25zIGxpc3RlZCBvbiByZXNlYXJjaGVycycgcGVyc29uYWwgTkFSQ0lTIHByb2ZpbGVzLiANCg0KRm9yIHRocmVlIFBoRCdzIGluIG91ciBleGFtcGxlIGRhdGEgZnJhbWUsIHdlIGhhdmUgY29tcGlsZWQgYSAoZmljdGlvbmFsKSBwdWJsaWNhdGlvbiB0cmFjayByZWNvcmQsIHRvIHNob3cgd2hhdCB0aGlzIHB1YmxpY2F0aW9uIGRhdGEgbG9va3MgbGlrZS4NCg0KVGhlIGBpZGAgdmFyaWFibGUgcmVmZXJlbmNlcyB0aGUgcGVyc29uYWwgaWRlbnRpZmllcnMsIHdoaWNoIGNhbiBhbHNvIGJlIGZvdW5kIGluIHRoZSBQaEQgZGF0YXNldCBzbyB0aGF0IFBoRHMgY2FuIGJlIG1hdGNoZWQgdG8gdGhlaXIgb3duIHB1YmxpY2F0aW9ucy4gRnVydGhlcm1vcmUsIHRoZSBkYXRhIHByb3ZpZGUgaW5mb3JtYXRpb24gb24gdGhlIGB0eXBlYCBvZiBwdWJsaWNhdGlvbiBhbmQgdGhlIGRhdGUgaW4gd2hpY2ggdGhlIHB1YmxpY2F0aW9uIHdhcyBwdWJsaXNoZWQgKGBkYXRlLmlzc3VlZGApLiBMYXN0bHksIHRoZSBqb3VybmFsIG5hbWUgKGBqb3VybmFtZWApIGlzIHVzZWQgYWxvbmdzaWRlIElTU04gY29kZXMgKG5vdCBwaWN0dXJlZCBpbiB0aGlzIGV4YW1wbGUgZGF0YWZyYW1lKSB0byBtYXRjaCBwdWJsaWNhdGlvbnMgdG8gYWNhZGVtaWMgZGlzY2lwbGluZXMuIA0KDQoNCmBgYHtyfQ0KDQprbml0cjo6a2FibGUocHVic19tZXRhZGYsIGZvcm1hdD0ibWFya2Rvd24iKQ0KDQoNCmBgYA0KDQoNCg0KIyBNYXRjaGluZyBqb3VybmFsIG5hbWVzIHRvIGZpZWxkcw0KDQpUbyBtYXRjaCBwdWJsaWNhdGlvbnMgd2l0aCBhY2FkZW1pYyBkaXNjaXBsaW5lcyBiYXNlZCBvbiBqb3VybmFsIG5hbWVzLCB3ZSB1c2UgYSBsaXN0IG9mIFdlYiBvZiBTY2llbmNlIGluZGV4ZWQgam91cm5hbHMgd2l0aCBhc3NvY2lhdGVkIGZpZWxkcyBhbmQgc3ViZmllbGRzLCBhY2NvcmRpbmcgdG8gdGhlIGZpZWxkIGNsYXNzaWZpY2F0aW9uIGJ5IHRoZSBVLlMuIE5hdGlvbmFsIFJlc2VhcmNoIENvdW5jaWwuIA0KDQpFYWNoIGpvdXJuYWwgaXMgYXNzb2NpYXRlZCB3aXRoIG9uZSBvciBtb3JlIHNwZWNpZmljIGFjYWRlbWljIGRpc2NpcGxpbmVzIChzdWJmaWVsZHMpLCB3aGljaCBmYWxsIHVuZGVyIGEgYnJvYWRlciBkaXNjaXBsaW5hcnkgY2F0ZWdvcml6YXRpb24gKGZpZWxkcykuIEluIHRoZSBleGFtcGxlIGhlcmUsIHRoZSBlbnRyeSBmb3IgdGhlICJKb3VybmFsIG9mIEVjY2xlc2lhc3RpY2FsIEhpc3RvcnkiIGlzIGFzc29jaWF0ZWQgd2l0aCB0aGUgc3ViZmllbGRzICJoaXN0b3J5IiBhbmQgInJlbGlnaW9uIiwgYm90aCBvZiB3aGljaCBmYWxsIHVuZGVyICJodW1hbml0aWVzIi4gU2luY2Ugd2Ugb25seSBsb29rIGF0IHRoZSBicm9hZGVyIGRpc2NpcGxpbmUsIHRoaXMgZG9lcyBub3QgbWF0dGVyIGZvciBvdXIgZmllbGQgdmFyaWFibGUsIGFuZCB3ZSBjYW4gc2ltcGx5IGFzc2lnbiAiaHVtYW5pdGllcyIgYXMgdGhlIGZpZWxkLiANCg0KDQpgYGB7cn0NCg0Ka25pdHI6OmthYmxlKGpvdXJuYWxzX3dvc1tqb3VybmFsc193b3MkSVNTTj09IjAwMjItMDQ2OSIsXSwgZm9ybWF0PSJtYXJrZG93biIpDQoNCmBgYA0KDQoNCkluIHNvbWUgY2FzZXMsIGhvd2V2ZXIsIGEgam91cm5hbCBpcyBhc3NvY2lhdGVkIHdpdGggbXVsdGlwbGUgYnJvYWRlciBmaWVsZHMuIFdlIHRoZW4gYXNzaWduIHRoZSBmaWVsZCB3aGljaCBvY2N1cnMgbW9zdCBmcmVxdWVudGx5IHdpdGhpbiB0aGUgam91cm5hbC4gDQoNCkluIHRoZSBjYXNlIG9mIHRoZSBqb3VybmFsICJBQ1MgUGhvdG9uaWNzIiwgdGhpcyBpbXBsaWVzIHRoYXQgd2UgYXNzaWduICJlbmdpbmVlcmluZyIgYXMgdGhlIGJyb2FkZXIgZmllbGQuDQoNCkluIHRoZSBjYXNlIG9mIHRoZSAiSW50ZXJuYXRpb25hbCBMYWJvdXIgUmV2aWV3IiwgaXQgaXMgbW9yZSB0cmlja3k6IHRoZSBqb3VybmFsIGlzIHNwbGl0IDUwLzUwIGJldHdlZW4gInNvY2lhbCBhbmQgYmVoYXZpb3JhbCBzY2llbmNlcyIgYW5kICJodW1hbml0aWVzIi4gSW4gdGhlc2UgY2FzZXMsIHdlIHJhbmRvbWx5IHBpY2sgb25lIG9mIHRoZSBmaWVsZHMuIA0KDQpgYGB7cn0NCg0KDQprbml0cjo6a2FibGUoam91cm5hbHNfd29zWyhqb3VybmFsc193b3MkSVNTTj09IjIzMzAtNDAyMiJ8am91cm5hbHNfd29zJElTU049PSIwMDIwLTc3ODAiKSxdLCBmb3JtYXQ9Im1hcmtkb3duIikNCg0KYGBgDQoNCg0KTmV4dCwgd2UgbWF0Y2ggdGhlIGpvdXJuYWxzIGluIHRoZSBXZWIgb2YgU2NpZW5jZSBsaXN0IHRvIHRoZSBwdWJsaWNhdGlvbiBvdXRsZXQgaW5mb3JtYXRpb24gaW4gb3VyIG93biBwdWJsaWNhdGlvbiBkYXRhc2V0LiBXZSBmaXJzdCBtYXRjaCBvbiBJU1NOLCB3aGljaCBwcm92aWRlcyB1cyBpbmZvcm1hdGlvbiBvbiB0aGUgZmllbGQgb2YgNzAlIG9mIHRoZSB1bmlxdWUgam91cm5hbHMgaW4gb3VyIGRhdGEuIE5leHQsIHdlIG1hdGNoIG9uIGpvdXJuYWwgbmFtZXMsIHdoaWNoIGluY3JlYXNlcyB0aGUgcmVjYWxsIG9uIG91ciBmaWVsZCBpbmRpY2F0b3IgdG8gNzUlIG9mIHRoZSB1bmlxdWUgam91cm5hbHMuIA0KDQpJbiB0aGlzIGV4YW1wbGUgZGF0YWZyYW1lLCB3ZSByYW5kb21seSBwaWNrZWQgam91cm5hbHMgZnJvbSB0aGUgV2ViIG9mIFNjaWVuY2UgbGlzdCwgbWVhbmluZyBhbGwgcHVibGljYXRpb25zIHdpdGggYSBqb3VybmFsIGNhbiBiZSBtYXRjaGVkIHRvIGEgZmllbGQuIA0KDQpgYGB7cn0NCg0Ka25pdHI6OmthYmxlKHB1YnNfZmllbGQsIGZvcm1hdD0ibWFya2Rvd24iKQ0KDQoNCmBgYA0KDQoNCiMgQ3JlYXRpbmcgYSB0aW1lLWludmFyaWFudCBmaWVsZCB2YXJpYWJsZSBmb3IgZWFjaCBQaEQNCg0KV2UgZGV0ZXJtaW5lIGEgcmVzZWFyY2hlcidzIGZpZWxkIGJhc2VkIG9uIHRoZWlyIHB1YmxpY2F0aW9ucyBkdXJpbmcgYW5kIHJpZ2h0IGFmdGVyIHRoZWlyIFBoRC4gVGh1cywgd2UgZmlyc3QgZXhjbHVkZSBwdWJsaWNhdGlvbnMgZnJvbSBtb3JlIHRoYW4gNSB5ZWFycyBiZWZvcmUsIG9yIG1vcmUgdGhhbiB0aHJlZSB5ZWFycyBhZnRlciB0aGV5IHJlY2VpdmVkIGRvY3RvcmF0ZS4gTmV4dCwgd2UgdGFsbHkgdXAgdGhlIGZpZWxkcyBhY3Jvc3MgYWxsIHRoZXNlIHB1YmxpY2F0aW9ucywgYW5kIHRha2UgdGhlIGZpZWxkIHdoaWNoIG9jY3VycyBtb3N0IGZyZXF1ZW50bHkuIA0KDQpgYGB7cn0NCg0KIyBmaXJzdCwgd2UgYWRkIHRoZSBwdWJsaWNhdGlvbnMgZGF0YSB0byBvdXIgcGhkIGRhdGFmcmFtZQ0KcGhkZmllbGQgPC0gbGVmdF9qb2luKHB1YnNfZmllbGQsIHBoZF9kZiwgYnk9ImlkIikNCg0KDQojIHRoZW4gd2UgY2xlYW4gdGhlIGRhdGUuaXNzdWVkIHZhcmlhYmxlDQpwaGRmaWVsZCRwdWJ5ZWFyIDwtIGFzLm51bWVyaWMoc3Vic3RyKHBoZGZpZWxkJGRhdGUuaXNzdWVkLCAxLCA0KSkNCg0KIyBzZWxlY3RpbmcgcHVibGljYXRpb25zIGZyb20gZHVyaW5nIGFuZCByaWdodCBhZnRlciB0aGUgUGhEDQpwaGRmaWVsZCAlPiUNCiAgZmlsdGVyKChwdWJ5ZWFyIDwgKHBoZF95ZWFyICsgMykpICYgKHB1YnllYXIgPiAocGhkX3llYXItNSkpKSAtPiBwaGRmaWVsZA0KDQojIGZpZWxkID0gZmllbGQgd2hpY2ggdGhlIG1ham9yaXR5IG9mIG9uZSdzIHB1YmxpY2F0aW9uIGZhbGwgdW5kZXINCnBoZGZpZWxkICU+JQ0KICBncm91cF9ieShpZCkgJT4lDQogIGFkZF9jb3VudChucmNfZmllbGQpICU+JQ0KICBzbGljZV9tYXgobikgJT4lDQogIHVuZ3JvdXAoKSAtPiBwaGRmaWVsZA0KDQojIG1haW50YWluIGEgc2luZ2xlIGxpbmUgcGVyIGlkL2ZpZWxkIGNvbWJvDQpwaGRmaWVsZCAlPiUNCiAgZ3JvdXBfYnkoaWQsIG5yY19maWVsZCkgJT4lDQogIHNsaWNlX2hlYWQoKSAlPiUgdW5ncm91cCgpIC0+IHBoZGZpZWxkDQoNCmBgYA0KDQpBcyB3ZSBzZWUgZnJvbSB0aGUgcmVzdWx0cyBiZWxvdywgb25lIG9mIHRoZSB0aHJlZSByZXNlYXJjaGVycyB3YXMgYXNzaWduZWQgYSBzaW5nbGUgZmllbGQuIFRoZSBvdGhlciB0d28gKGYgYW5kIGcpIGFyZSBzcGxpdCBldmVubHkgYmV0d2VlbiB0d28gZmllbGRzLiBJbiB0aGlzIGNhc2UsIHdlIHRha2Ugb25lIG9mIHRoZSBmaWVsZHMgYXQgcmFuZG9tLg0KDQpgYGB7cn0NCg0Ka25pdHI6OmthYmxlKHBoZGZpZWxkWyxjKDEsNSwxNildLCBmb3JtYXQ9Im1hcmtkb3duIikNCg0KYGBgDQoNClNlbGVjdGluZyBhIGZpZWxkIGF0IHJhbmRvbSBmb3IgdGhvc2Ugd2hvIGFyZSBzcGxpdCBleGFjdGx5IGV2ZW5seSBiZXR3ZWVuIG11bHRpcGxlIGZpZWxkcy4gDQoNCmBgYHtyfQ0KDQpwaGRmaWVsZCAlPiUNCiAgZ3JvdXBfYnkoaWQpICU+JQ0KICBzbGljZV9zYW1wbGUobiA9IDEpIC0+IHBoZGZpZWxkDQoNCg0KYGBgDQoNCg0KRmluYWxseSwgd2Ugb21pdCB0aGUgJ2J1c2luZXNzJyBhbmQgJ2xhdycgZmllbGRzIGJlY2F1c2UgdGhleSBhcmUgc21hbGwgYW5kIHNjaWVudGlzdHMgaW4gdGhlc2UgZmllbGRzIHRlbmQgdG8gaGF2ZSBhdHlwaWNhbCBjYXJlZXIgcGF0aHMuIEZ1cnRoZXJtb3JlLCB3ZSBjb21iaW5lICdzb2NpYWwgYW5kIGJlaGF2aW9yYWwgc2NpZW5jZXMnIGFuZCAnZWR1Y2F0aW9uJyB1bmRlciBhIHNpbmdsZSBjYXRlZ29yeS4gIA0KDQpgYGB7cn0NCg0KDQpwaGRmaWVsZCRmaWVsZDIgPC0gcGhkZmllbGQkZmllbGQgPC0gcGhkZmllbGQkbnJjX2ZpZWxkDQoNCnBoZGZpZWxkJGZpZWxkMiA8LSBmY3RfY29sbGFwc2UocGhkZmllbGQkZmllbGQyLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdBZ3JpY3VsdHVyYWwgU2NpZW5jZXMnID0gIkFncmljdWx0dXJhbCBTY2llbmNlcyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0Jpb2xvZ2ljYWwgYW5kIEhlYWx0aCBTY2llbmNlcycgPSAiQmlvbG9naWNhbCBhbmQgSGVhbHRoIFNjaWVuY2VzIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAib3RoZXIiID0gYygiQnVzaW5lc3MiLCAiTGF3IiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRW5naW5lZXJpbmcgPSAiRW5naW5lZXJpbmciLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEh1bWFuaXRpZXMgPSAiSHVtYW5pdGllcyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ1NvY2lhbCBhbmQgQmVoYXZpb3JhbCBTY2llbmNlcycgPSBjKCJTb2NpYWwgYW5kIEJlaGF2aW9yYWwgU2NpZW5jZXMiLCAiRWR1Y2F0aW9uIiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ1BoeXNpY2FsIGFuZCBNYXRoZW1hdGljYWwgU2NpZW5jZXMnID0gIlBoeXNpY2FsIGFuZCBNYXRoZW1hdGljYWwgU2NpZW5jZXMiKQ0KDQoNCmxldmVscyhwaGRmaWVsZCRmaWVsZDIpW2xldmVscyhwaGRmaWVsZCRmaWVsZDIpPT0ib3RoZXIiXSA8LSBOQQ0KbGV2ZWxzKHBoZGZpZWxkJGZpZWxkMikNCg0KDQojIGNyZWF0ZSBhbmQgZXhwbGljaXQgJ21pc3NpbmcnIGNhdGVnb3J5DQpwaGRmaWVsZCA8LSBwaGRmaWVsZCAlPiUgDQogIG11dGF0ZShmaWVsZCA9IGZjdF9leHBsaWNpdF9uYShmaWVsZCwgbmFfbGV2ZWw9Im1pc3NpbmciKSwNCiAgICAgICAgIGZpZWxkMiA9IGZjdF9leHBsaWNpdF9uYShmaWVsZDIsIG5hX2xldmVsPSJtaXNzaW5nIikpIA0KDQoNCnBoZGZpZWxkJGZpZWxkIDwtIGZhY3RvcihwaGRmaWVsZCRmaWVsZCwgbGV2ZWxzID0gYygiQmlvbG9naWNhbCBhbmQgSGVhbHRoIFNjaWVuY2VzIiwgIlBoeXNpY2FsIGFuZCBNYXRoZW1hdGljYWwgU2NpZW5jZXMiLCAiU29jaWFsIGFuZCBCZWhhdmlvcmFsIFNjaWVuY2VzIiwgIkVuZ2luZWVyaW5nIiwgIkFncmljdWx0dXJhbCBTY2llbmNlcyIsICJIdW1hbml0aWVzIiwgIkJ1c2luZXNzIiwgIkVkdWNhdGlvbiIsICJMYXciLCAibWlzc2luZyIpKQ0KDQpwaGRmaWVsZCRmaWVsZDIgPC0gZmFjdG9yKHBoZGZpZWxkJGZpZWxkMiwgbGV2ZWxzID0gYygiQmlvbG9naWNhbCBhbmQgSGVhbHRoIFNjaWVuY2VzIiwgIlBoeXNpY2FsIGFuZCBNYXRoZW1hdGljYWwgU2NpZW5jZXMiLCAiU29jaWFsIGFuZCBCZWhhdmlvcmFsIFNjaWVuY2VzIiwgIkVuZ2luZWVyaW5nIiwgIkFncmljdWx0dXJhbCBTY2llbmNlcyIsICJIdW1hbml0aWVzIiwgIm1pc3NpbmciKSkNCg0KDQoNCmBgYA0KDQoNCg0KIyBPdXRwdXQgIA0KDQpBZnRlciB0aGlzLCB3ZSBhcmUgbGVmdCB3aXRoIGEgZGF0YXNldCBvZiBQaERzICsgZmllbGRzIGZvciBlYWNoIFBoRCB3aXRoIHB1YmxpY2F0aW9ucyBpbiB0aGUgc3BlY2lmaWVkIHRpbWVmcmFtZS4gDQoNCmBgYHtyLCBlY2hvPUZBTFNFfQ0KDQpwaGRmaWVsZCA8LSBzdWJzZXQocGhkZmllbGQsIHNlbGVjdD1jKGlkLCBmaXJzdG5hbWUsIGxhc3RuYW1lX2Z1bGwsIGZpZWxkLCBmaWVsZDIsIGdlbmRlciwgZXRobmljaXR5LCBldGhuaWNpdHkyLCB1bmksIHBoZF95ZWFyKSkNCg0KYGBgDQoNCmBgYHtyLCBlY2hvPUZBTFNFfQ0KDQpwaGRmaWVsZCAlPiUNCiAga2FibGUoKSAlPiUNCiAga2FibGVfc3R5bGluZygpICU+JQ0KICBzY3JvbGxfYm94KHdpZHRoPSIxMDAlIikNCg0KDQpgYGANCg0KDQoNCmBgYHtyLCBlY2hvPUZBTFNFLCBldmFsPUZBTFNFfQ0KDQpzYXZlKHBoZGZpZWxkLCBmaWxlPSJkYXRhL3Byb2Nlc3NlZC9waGRmaWVsZC5yZGEiKQ0KDQpgYGANCg0KLS0tICANCg0K
Copyright © 2023