Magic no R com {scryr}

Magic no R com {scryr}

2022-01-07 · Esta página é feita de pedra

scryr é uma interface em R para o Scryfall, uma API incrível (e grátis!) de Magic: The Gathering. Com o scryr você pode transformar dados de cartas em drata frames nativos, permitindo integração imediata com qualquer fluxo tidy.

Atualmente há 2 famílias de funções principais: cards e sets. As outras 4 (bulk_data, catalogs, rulings, e symbols) são majoritariamente auxiliares.

1# Instalar o scryr
2install.packages("scryr")
3
4# Carregar o scryr com o dplyr
5library(dplyr)
6library(scryr)

Cartas #

Essa família é, de longe, a mais complicada de entender. Antes de usá-la, lembre-se de ler a documentação completa da scry_cards()! Para os curiosos, outras informações relevantes podem ser encontradas em vignette("syntax") (Query Syntax) e em vignette("layouts")` (Layouts and Faces).

A função mais importante aqui é scry_cards(). Ela retorna um data frame de cartas dada uma busca.

 1# Vampiros lendários
 2vampires <- scry_cards("t:vampire t:legend")
 3
 4# Há muitas, muitas colunas
 5print(vampires)
 6#> # A tibble: 48 × 70
 7#>    id         name     set   lang  colors color_identity mana_cost   cmc
 8#>    <chr>      <chr>    <chr> <chr> <list> <list>         <chr>     <dbl>
 9#>  1 913dd06f-… Anje Fa… c19   en    <chr … <chr [2]>      {1}{B}{R}     3
10#>  2 1bfac4ab-… Anje, M… vow   en    <chr … <chr [2]>      {2}{B}{R}     4
11#>  3 b8630ae1-… Anowon,… voc   en    <chr … <chr [1]>      {3}{B}{B}     5
12#>  4 bca84fc4-… Anowon,… znc   en    <chr … <chr [2]>      {2}{U}{B}     4
13#>  5 e811f37a-… Arvad t… dom   en    <chr … <chr [2]>      {3}{W}{B}     5
14#>  6 213ad4ba-… Ascenda… hop   en    <chr … <chr [1]>      {4}{B}{B}     6
15#>  7 e5fb44d7-… Baron S… me1   en    <chr … <chr [1]>      {5}{B}{B…     8
16#>  8 487e843f-… Crovax … tpr   en    <chr … <chr [1]>      {2}{B}{B}     4
17#>  9 2c58ce5e-… Drana, … c17   en    <chr … <chr [1]>      {3}{B}{B}     5
18#> 10 31d0c37f-… Drana, … jmp   en    <chr … <chr [1]>      {1}{B}{B}     3
19#> # … with 38 more rows, and 62 more variables: oracle_text <chr>,
20#> #   power <chr>, toughness <chr>, type_line <chr>, edhrec_rank <int>,
21#> #   keywords <list>, layout <chr>, legalities <list>, oversized <lgl>,
22#> #   reserved <lgl>, oracle_id <chr>, mtgo_id <int>,
23#> #   multiverse_ids <list>, tcgplayer_id <int>, cardmarket_id <int>,
24#> #   uri <chr>, scryfall_uri <chr>, rulings_uri <chr>,
25#> #   prints_search_uri <chr>, artist <chr>, artist_ids <list>, …

Note que várias colunas são list-columns com dados aninhados. Isso é uma consequência do modelo de dados do Scryfall e é a principal razão do scryr precisar de tibbles para funcionar. Mas não se preocupe! Todos os dados são consistentes e bem documentados.

 1# Pegar cartas relacionadas a Anje
 2vampires %>%
 3  filter(name == "Anje, Maid of Dishonor") %>%
 4  pull(all_parts)
 5#> [[1]]
 6#> # A tibble: 2 × 6
 7#>   object       id         component  name     type_line   uri
 8#>   <chr>        <chr>      <chr>      <chr>    <chr>       <chr>
 9#> 1 related_card 1bfac4ab-… combo_pie… Anje, M… Legendary … https://api.s…
10#> 2 related_card a6f374bc-… token      Blood    Token Arti… https://api.s…
11
12# Pegar a identidade de cor da Anje
13vampires %>%
14  filter(name == "Anje Falkenrath") %>%
15  pull(color_identity)
16#> [[1]]
17#> [1] "B" "R"

Também há várias funções “no singular”, ou seja, funções que retornam 1 carta ao invés de muitas. Elas são scry_card() e suas irmãs, todos métodos que encontram uma carta dado um certo identificador.

 1# Usando ID
 2scry_card("913dd06f-ed2f-4128-9c9d-9cd0d8a55425")$name
 3#> [1] "Anje Falkenrath"
 4
 5# Usando nome
 6scry_card_name("Anje Falkenrath")$name
 7#> [1] "Anje Falkenrath"
 8
 9# Usando um número de colecionador e um set
10scry_card_number(37, "c19")$name
11#> [1] "Anje Falkenrath"
12
13# Pegar um commander vampiro aleatório
14scry_card_random("t:vampire t:legend")$name
15#> [1] "Vito, Thorn of the Dusk Rose"

Se você não tiver certeza de qual carta você está procurando, não se preocupe. O Scryfall também tem um endpoint que tenta autocompletar o nome de uma carta e o scryr disponibiliza isso para que você nem precise sair do R para procurar uma carta.

1# Olha lá ela
2autocomplete_name("falken")[12]
3#> [1] "Anje Falkenrath"

Sets #

A outra família principal retorna informações sobre sets. De novo há muitas list-columns, mas, novamente, todas são tratadas consistentemente; seguindo cards, sets também tem uma função “plural” e uma função “singular”. Note que scry_cards() é a única que pode filtrar seus resultados com o argumento q.

 1# Pegar todos os sets
 2scry_sets()
 3#> # A tibble: 721 × 19
 4#>    id     code  name  uri   scryfall_uri search_uri released_at set_type
 5#>    <chr>  <chr> <chr> <chr> <chr>        <chr>      <date>      <chr>
 6#>  1 a6012… tunf  Unfi… http… https://scr… https://a… 2022-04-01  token
 7#>  2 b314f… unf   Unfi… http… https://scr… https://a… 2022-04-01  funny
 8#>  3 b11b2… pw22  Wiza… http… https://scr… https://a… 2022-03-05  promo
 9#>  4 5bd03… tnec  Neon… http… https://scr… https://a… 2022-02-18  token
10#>  5 8bb11… tneo  Kami… http… https://scr… https://a… 2022-02-18  token
11#>  6 5b4d9… nec   Neon… http… https://scr… https://a… 2022-02-18  command…
12#>  7 59a20… neo   Kami… http… https://scr… https://a… 2022-02-18  expansi…
13#>  8 78a7f… cc2   Comm… http… https://scr… https://a… 2022-01-28  command…
14#>  9 5c163… dbl   Inni… http… https://scr… https://a… 2022-01-28  draft_i…
15#> 10 8a673… y22   Alch… http… https://scr… https://a… 2021-12-09  expansi…
16#> # … with 711 more rows, and 11 more variables: card_count <int>,
17#> #   parent_set_code <chr>, digital <lgl>, nonfoil_only <lgl>,
18#> #   foil_only <lgl>, icon_svg_uri <chr>, tcgplayer_id <int>,
19#> #   mtgo_code <chr>, arena_code <chr>, block_code <chr>, block <chr>
20
21# Pegar um único set com um código
22scry_set("vow")
23#> # A tibble: 1 × 19
24#>   id    code  name  mtgo_code arena_code tcgplayer_id uri   scryfall_uri
25#>   <chr> <chr> <chr> <chr>     <chr>             <int> <chr> <chr>
26#> 1 8144… vow   Inni… vow       vow                2862 http… https://scr…
27#> # … with 11 more variables: search_uri <chr>, released_at <date>,
28#> #   set_type <chr>, card_count <int>, printed_size <int>,
29#> #   digital <lgl>, nonfoil_only <lgl>, foil_only <lgl>,
30#> #   block_code <chr>, block <chr>, icon_svg_uri <chr>

Outras Famílias #

Todas as outras famílias retornam muito menos informações do que as acima. Deixo vocês com uma pequena demontração do que o resto do scryr pode fazer:

 1# Pegar informações de um catálogo
 2head(scry_catalog("keyword-actions"))
 3#> [1] "Meld"        "Bolster"     "Clash"       "Fateseal"
 4#> [5] "Manifest"    "Monstrosity"
 5
 6# Pegar regras de uma carta
 7scry_ruling("913dd06f-ed2f-4128-9c9d-9cd0d8a55425")
 8#> # A tibble: 1 × 4
 9#>   oracle_id                            source published_at comment
10#>   <chr>                                <chr>  <date>       <chr>
11#> 1 4dab6a96-4376-4aea-983d-406167993214 wotc   2019-08-23   If you disca…
12
13# Pegar informações sobre símbolos
14scry_symbols()
15#> # A tibble: 34 × 11
16#>    symbol colors   cmc loose_variant english           gatherer_alterna…
17#>    <chr>  <list> <dbl> <chr>         <chr>             <list>
18#>  1 {X}    <NULL>   0   X             X generic mana    <chr [2]>
19#>  2 {Y}    <NULL>   0   Y             Y generic mana    <NULL>
20#>  3 {Z}    <NULL>   0   Z             Z generic mana    <NULL>
21#>  4 {0}    <NULL>   0   0             zero mana         <chr [1]>
22#>  5 {½}    <NULL>   0.5 ½             one-half generic… <chr [1]>
23#>  6 {1}    <NULL>   1   1             one generic mana  <chr [1]>
24#>  7 {2}    <NULL>   2   2             two generic mana  <chr [1]>
25#>  8 {3}    <NULL>   3   3             three generic ma… <chr [1]>
26#>  9 {4}    <NULL>   4   4             four generic mana <chr [1]>
27#> 10 {5}    <NULL>   5   5             five generic mana <chr [1]>
28#> # … with 24 more rows, and 5 more variables: transposable <lgl>,
29#> #   represents_mana <lgl>, appears_in_mana_costs <lgl>, funny <lgl>,
30#> #   svg_uri <chr>
31
32# Processar um custo de mana
33parse_cost("2g2")$cost
34#> [1] "{4}{G}"
35
36# Pegar nomes dos arquivos de massa
37scry_bulk_files()$name
38#> [1] "Oracle Cards"   "Unique Artwork" "Default Cards"  "All Cards"
39#> [5] "Rulings"
40
41# Baixar (e processar) todas as regras da base do Scryfall
42scry_bulk_file("Rulings")
43#> # A tibble: 44,486 × 4
44#>    oracle_id                            source published_at comment
45#>    <chr>                                <chr>  <date>       <chr>
46#>  1 0004ebd0-dfd6-4276-b4a6-de0003e94237 wotc   2004-10-04   If there ar…
47#>  2 0007c283-5b7a-4c00-9ca1-b455c8dff8c3 wotc   2019-08-23   The "comman…
48#>  3 0007c283-5b7a-4c00-9ca1-b455c8dff8c3 wotc   2019-08-23   Certain car…
49#>  4 0007c283-5b7a-4c00-9ca1-b455c8dff8c3 wotc   2019-08-23   If your com…
50#>  5 000e5d65-96c3-498b-bd01-72b1a1991850 wotc   2004-10-04   The target …
51#>  6 0012bc78-e69d-4a67-a302-e5fe0dfd4407 wotc   2019-05-03   A land norm…
52#>  7 00187de2-bc48-4137-97d8-a9a0fafc76c1 wotc   2019-01-25   You can alw…
53#>  8 00187de2-bc48-4137-97d8-a9a0fafc76c1 wotc   2019-01-25   Pteramander…
54#>  9 00187de2-bc48-4137-97d8-a9a0fafc76c1 wotc   2019-01-25   If a creatu…
55#> 10 001c6369-df13-427d-89df-718d5c09f382 wotc   2009-05-01   Vedalken He…
56#> # … with 44,476 more rows