遊戯王カードをドローするコマンドを作りました

この記事は クソアプリ 2 Advent Calendar 2019 の 6 日目の記事です。

遊戯王カードをドローしたくなったので作りました。
なぜならデュエリストだから。

1. 使い方

  1. インストール
$ go get github.com/Doarakko/draw

注意:Go のインストールが必要です。

  1. 実行
$ draw

f:id:Doarakko:20191205033930p:plain

2. 補足

Visual Studio Code 上では動きません。

コマンドライン上の画像表示については、猫の画像を表示するコマンド nyanko をパクりました。

3. カード画像の取得元

カード画像は Yu-Gi-Oh! API by YGOPRODeck のランダムなカードを取得する API を使って取ってきています。

上記 API のクライアントライブラリも自作しました。
Go4 Advent Calendar 2019 で記事を書いています。

Go 言語で初めてのライブラリ開発

4. おわりに

遊戯王カードをドローしたいときに使ってください。

俺のターン!!ドロー!

f:id:Doarakko:20191205033947p:plain

5. 参考資料

Go 言語で初めてのライブラリ開発

この記事は Go4 Advent Calendar 2019 の 5 日目の記事です。

2019 年の締めに作りました。
どんなものを作ったのか、その際に何をやったのかまとめます。

1. 作ったライブラリ

遊戯王のカード情報(英語版)を取得できる APIYu-Gi-Oh! API by YGOPRODeck」のクライアントライブラリ「go-yugioh」を作りました。

README を英語で書いてバッチをつけるだけでそれっぽく見えます。

f:id:Doarakko:20191205032216p:plain

API 自体が英語版のみ(フランス語版は非公式)の対応のため日本語版のカード情報は取ってこれません。

使用例

  • カード名に dragon が含まれる光属性融合モンスターを取得
import (
    "fmt"

    "github.com/Doarakko/go-yugioh/yugioh"
)

func main() {
    client := yugioh.NewClient()
    cards, _, _ := client.Cards.List(
        &yugioh.CardsListOptions{
            KeyWord: "dragon", Type: "Fusion Monster", Attribute: "light"})

    for _, card := range cards {
        fmt.Printf("Name: %v\nType: %v\nRace: %v\nDescription:\n%v\n\n",
            card.Name, card.Type, card.Race, card.Description)
    }
}
Name: A-to-Z-Dragon Buster Cannon
Type: Fusion Monster
Race: Machine
Description:
"ABC-Dragon Buster" + "XYZ-Dragon Cannon"
Must be Special Summoned (from your Extra Deck) by banishing cards you control with the above original names, and cannot be Special Summoned by other ways. (You do not use "Polymerization".) During either player's turn, when your opponent activates a Spell/Trap Card, or monster effect: You can discard 1 card; negate the activation, and if you do, destroy that card. During either player's turn: You can banish this card, then target 1 each of your banished "ABC-Dragon Buster", and "XYZ-Dragon Cannon"; Special Summon them.

Name: ABC-Dragon Buster
Type: Fusion Monster
Race: Machine
Description:
"A-Assault Core" + "B-Buster Drake" + "C-Crush Wyvern"
Must first be Special Summoned (from your Extra Deck) by banishing the above cards you control and/or from your Graveyard. (You do not use "Polymerization".) Once per turn, during either player's turn: You can discard 1 card, then target 1 card on the field; banish it. During your opponent's turn: You can Tribute this card, then target 3 of your banished LIGHT Machine-Type Union monsters with different names; Special Summon them (this is a Quick Effect).
...
  • ランダムなカードを取得
    • API の仕様でパラメータ指定不可
func main() {
    client := yugioh.NewClient()

    card, _, _ := client.RandomCards.One()
    fmt.Printf("Name: %v\nType: %v\nRace: %v\nDescription:\n%v\n",
        card.Name, card.Type, card.Race, card.Description)
}
Name: Formula Synchron
Type: Synchro Tuner Monster
Race: Machine
Description:
1 Tuner + 1 non-Tuner monster
When this card is Synchro Summoned: You can draw 1 card. Once per Chain, during your opponent's Main Phase, you can: Immediately after this effect resolves, Synchro Summon using this card you control (this is a Quick Effect).
  • Amazoness に関連する魔法カードを取得
    • 対応しているカードグループ(AmazonessBlue-Eyes など)は client.Archetypes.List() から取得可能
func main() {
    client := yugioh.NewClient()
    cards, _, _ := client.Cards.List(
        &yugioh.CardsListOptions{Archetype: "Amazoness", Type: "Spell Card"})

    for _, card := range cards {
        fmt.Printf("Name: %v\nType: %v\nRace: %v\nDescription:\n%v\n\n",
            card.Name, card.Type, card.Race, card.Description)
    }
}
Name: Amazoness Call
Type: Spell Card
Race: Quick-Play
Description:
Take 1 "Amazoness" card from your Deck, except "Amazoness Call", and either add it to your hand or send it to the GY. During your Main Phase: You can banish this card from your GY, then target 1 "Amazoness" monster you control; this turn, that monster can attack all monsters your opponent controls, once each, also other monsters you control cannot attack. You can only activate 1 "Amazoness Call" per turn.

Name: Amazoness Fighting Spirit
Type: Spell Card
Race: Continuous
Description:
If an "Amazoness" monster attacks a monster with higher ATK, the attacking monster gains 1000 ATK during damage calculation only.
...

go-yugioh で作った CLI

実際にライブラリを使って遊戯王カードをドローするコマンド draw を作りました。

f:id:Doarakko:20191205032339p:plain

実行するとランダムな遊戯王カードがコマンドライン上に表示されます。
遊戯王カードをドローしたいときに使ってください。

クソアプリ 2 Advent Calendar 2019 で記事を書いてます。

遊戯王カードをドローするコマンドを作りました

2. 開発した経緯

2019 年新しく挑戦したこととして真っ先に思い浮かんだのが Go 言語でした。

せっかくなので最後に Go 言語の Advent Calendar の記事を書こうと思い、なんとなくライブラリ開発をすることにしました。

3. どんなライブラリを作るか

ライブラリを作ることを目的にスタートしたため、アイディアも何もない状態でした。
せっかく作るなら少しでも使われるものを作りたいということで、以下 2 つを条件にしました。

  1. 明確にユーザを定義できる

  2. 他の方が作っていない

そこで思いついたのが API のクライアントライブラリです。

  1. 明確にユーザを定義できる
    Go 言語でその API を使って開発を行う人

  2. 他の方が作っていない
    API はたくさんあるので、探せばクライアントライブラリが作られていないものが見つかるだろう

Go 言語初心者なので、参考にできるライブラリ(他のクライアントライブラリ)がたくさんあるというのも大きかったです。

4. やったこと

4.1 API 探し

以下 2 つを条件にしました。

  • Go 言語でクライアントライブラリが作成されていない
  • 特定の領域でメジャー
    • OK: カバディAPI の中で 1 番目に使われている
    • NG: サッカーの API の中で 2 番目に使われている

「<適当なキーワード> + API」 でググって、API を見つけたら GitHub でライブラリが作られていないか確認するというのを繰り返し行いました。

これは作られてないだろというものも結構ライブラリが作られていてびっくりしました。

4.2 ドキュメントを読みながら実際に API を使用

実際に公開されているすべてのエンドポイントを curl コマンドで叩いて確認しました。

4.3 他の Go 言語製のクライアントライブラリのソースを読む

主に参考にしたのが以下 2 つです。

URL に API のオプションをつける処理であったり、HTTP リクエストを送る処理はそのまま流用しました。

4.4 ライブラリ作成

API のドキュメントを見ながら構造体に落とし込みます。
多少フィール名を元の API から変えてます。

type Card struct {
    ID          int32   `json:"id,string"`
    Name        string  `json:"name"`
    Type        string  `json:"type"`
    Description string  `json:"desc"`
    Race        string  `json:"race"`
    Archetype   string  `json:"archetype"`
    Sets        []Set   `json:"card_sets"`
    Images      []Image `json:"card_images"`
...

type Prices struct {
    // Euro
    Cardmarket float32 `json:"cardmarket_price,string"`

    // Dollar
    Tcgplayer float32 `json:"tcgplayer_price,string"`
    Ebay      float32 `json:"ebay_price,string"`
    Amazon    float32 `json:"amazon_price,string"`
}

API のレスポンスの Key を構造体のフィールドの右に指定する(json:"name")と自動でパースしてくれるのはびっくりしました。
最高です。

int や float で使いたいもの(ID や値段)が文字列できたので、string とつけて対処(json:"id,string")しました。

Package json: func Marshal

今回の API は特にアカウント登録などなかったので、認証周りを気にする必要はありませんでした。

4.5 API 開発元 に Issue を立てる

この API ではパラメータにグループ(AmazonessBlue-Eyes など)を指定することで、そのグループに関連するカードのみを取得できます。
ただこのグループは遊戯王公式が一覧を公開している訳ではなく API 開発者が独自に行なっています。

[YGOPRODeck] Missing Archetypes - Master List #10

API 利用者からすると、対応しているグループが分からないのでパラメータの指定が難しいです。
そこで API から対応しているグループのリストを取得できるように開発者に頼むことにしました。

API 自体のソースは公開されていませんが、バグ報告用のリポジトリが公開されていたのでそちらから Issue を立てました。

[YGOPRODeck] New API: return archetype master #118

それが必要な理由と自分が作ったライブラリの紹介、API を作っていることに対するお礼を書きました。

Issue を立てた 5、6 時間後にはエンドポイントが新たに公開されてドキュメントも更新されたのでびっくりしました。
個人開発をずっと続けていたので、こうやって開発で誰かと関われたのは本当に嬉しかったです。

f:id:Doarakko:20191205032553p:plain

4.6 ライブラリに反映

新しく公開されたエンドポイントに合わせて、コード追加とドキュメント更新、サンプルプログラムの追加を行いました。

[go-yugioh] All card archetypes #2

4.7 GoDoc 登録・Go Report チェック

f:id:Doarakko:20191205032216p:plain

見た目それっぽくするためにつけました。
GoDoc はソースコードのコメントから自動で生成されます。

ライブラリのインポートパス(github.com/Doarakko/go-yugioh)を入力して、Go を押すと GoDoc に登録されます。

f:id:Doarakko:20191205032643p:plain

Go Report では、フォーマットやライセンスファイルがあるか、スペルミスがないかなどがチェックされてランクがつきます。

f:id:Doarakko:20191205032815p:plain

右上のバッジから取得した MarkDown 用のリンクを README に貼れば完了です。

4.8 ライブラリを使って CLI を開発

記事冒頭で紹介した、遊戯王カードをドローするコマンド draw を作りました。

f:id:Doarakko:20191205032830p:plain

私がこのライブラリ初の利用者です。

5. おわりに

クライアントライブラリなので開発自体に面白みはないですが、他の方のコードを読んだり、ライブラリを作って公開するまでの流れを経験できるのは初心者にちょうどいいんじゃないでしょうか。

今回は API 開発元に要望を送って、それが対応されて自分のライブラリに反映させるという貴重な体験もできました。

新しい職場で Go 言語を扱うことになったので、2020 年はより楽しい Go ライフを送れそうです。
ありがとうございました。

6. 参考資料

【OSS にプルリク送ってみた】 GitHub Trend を表示するコマンド「ght」の修正

GitHub Trend を表示するコマンドを作ろうと思い、既に作られていないか探したら「ght」というものがありました。
試しに使って見たら動かなかったので「ght」を修正することにしました。

GitHub Trend とは

GitHubリポジトリのトレンドを言語、期間(日、週、月)別にみることができるページです。

f:id:Doarakko:20191130122546p:plain

ght とは

Go 言語で作られた GitHub Trend を表示するコマンドです。
GitHub Trend を言語別に取得でき、実行するとリポジトリの URL と説明文がコマンドライン上に表示されます。

  • インストール
$ go get github.com/mattn/ght
  • 実行(修正後)

f:id:Doarakko:20191130122657p:plain

問題点

何も表示されない。

f:id:Doarakko:20191130122733p:plain

修正手順

1. Issues・Pull requests を確認

Issues・Pull requests を見て他の方がすでにバグの報告をしていないか、修正中かどうか確認します。
今回は特にありませんでした。

OSS によっては Issue を立てたりプルリクエストを送る際のルールがあるので注意します。
README.mdCONTRIBUTING.md に記載されていることが多いです。

上記ファイルはもちろんですが、他の方の Issue やプルリクエストも参考にします。

2. リポジトリをフォーク

f:id:Doarakko:20191130122814p:plain

Fork を押すと自分のリポジトリ一覧にフォークしたリポジトリのコピーができます。

3. フォークしたリポジトリをローカルに落とす

$ git clone https://github.com/<your account>/ght

4. ソースを読んで原因調査

以下 3 つから、GitHub Trend ページの HTML が変更されたことによりデータをうまく取得できていないことが原因ではないかと予想しました。

  • ght コマンド実行時にエラーが表示されない
    • 使用しているライブラリのバグではない可能性が高い
  • ght の最終更新が 4 年前
  • プログラム上で HTML のタグやクラスを指定している
    • API を叩いてる訳ではない
doc.Find(".repo-list-item").Each(func(_ int, s *goquery.Selection) {
    if href, ok := s.Find(".repo-list-name a").First().Attr("href"); ok {

予想を元に Chromeデベロッパーツールを使って .repo-list-item を検索したところヒットしませんでした。

f:id:Doarakko:20191130122855p:plain

原因が特定できたので、現在の GitHub Trend ページにあわせてプログラムを修正します。

5. 修正

GitHub Trend の HTML はそこまで変更されていなかったため、タグ・クラスを現在のものに変えるだけで OK でした。

f:id:Doarakko:20191130122913p:plain

ローカルで試しに実行してきちんと動作することを確認します。

f:id:Doarakko:20191130122928p:plain

6. 自分のリポジトリに反映

$ git add main.go
$ git commit -m 'fix selector' main.go
$ git push

7. プルリクエス

修正内容を本家 ght に反映してくれるようリクエストします。

f:id:Doarakko:20191130122945p:plain

動かなかった原因を書いて修正前後のスクショを貼りました。
開発者は日本人の方ですが GitHub は海外の方も見るので英語で書きました。

8. マージ

f:id:Doarakko:20191130123007p:plain

開発者の方がマージすると本家 ght に反映されます。

f:id:Doarakko:20191130122657p:plain

動いたー!

おわりに

Issue を立てたりプルリクエストを送ることで、その OSS を使う多くのユーザの助けになります。
それはとても意義があり大切なことです。

ただ、私は単純に自分のプルリクエストがマージされるのがすごく嬉しいです。
よくわからないけどすごく嬉しいです。

まだまだタイポなどのちょっとしたことしかできていません。
これからはより OSS 開発に力を入れていきます。

V 言語で競技プログラミング

V 言語が競技プログラミングに適しているかどうかはわかりませんが、ちょっと V 言語をさわってみたかったので試しに競プロやってみます。

1. V 言語とは

2019 年 6 月に公開されたプログラミング言語です。
構文は Go 言語っぽいです。

  • なんか速いらしい
  • ヌルがない
  • C 言語のソースを V 言語に変換可能
    • バージョン 0.3 で追加予定(現在 v0.1.21)
  • バックエンドが C

私はこれくらいのことしか知らないので、もっと詳しく知りたい方は GitHub へ!

名称は公式が「V」としています。
話すときに Go 言語みたいに「ブイラング」と言うのは避けたほうがいいのでしょうか。

Please note that the name of the language is "V", not "Vlang" or "V-Lang" etc.
公式ドキュメント参照

2. 概要と方針

V 言語で競技プログラミングやります。
ただメジャーリリース(2019 年 12 月予定)がされていない状態で、V 言語対応している競プロサイトはおそらくないです。

V 1.0 release is planned for December 2019. Right now V is in an alpha stage.
GitHub 参照

そこで V 言語のソースを「間接的に」競プロサイトに提出します。
V 言語はバックエンドが C 言語ということもあり、-keep_c オプションをつけることで C 言語のファイルを出力することができます。

出力された C 言語のソースを提出することで、V 言語で間接的に競プロサイトのオンラインジャッジ機能を使えます。

3. V 言語の環境構築

README の手順通りにやりました。

  1. インストール
$ git clone https://github.com/vlang/v
$ cd v
$ make
  1. シンボリックリンク
    別のディレクトリでも V コマンドを実行できるようにします。
$ sudo ./v symlink

ディレクトリに移動して試して見ます。

$ v -h
Usage: v [options/commands] [file.v | directory]

   When V is run without any arguments, it is run in REPL mode.

// 省略

アップデートは以下のコマンドです。

$ v up

4. やってみる

V 言語で初の「AtCoder に登録したら解くべき精選過去問 10 問を 〇〇 言語 で解いてみた」の記事を出せるぞと意気揚々とググってみたら、すでにやられている方がいらっしゃいました。
はやすぎる...

記事はこちらです。

上記記事でも書いてありますが、V 言語には 2019 年 10 月現在、標準入力のライブラリがありません。
ただ C 言語のライブラリを呼び出せるのでそちらを使います。

今回は AOJAtCoder の問題を 1 問ずつ解いてみます。
V 言語の GitHub のソースを見ると、インデントはスペースではなく「タブ」のようです。

AtCoder Beginner Contest 143: A - Curtain

V 言語のソース

  • mut をつけずに宣言した変数は変更不可
  • C.hoge で C 言語のライブラリを呼び出し
fn main(){
    a := 0
    b := 0
    C.scanf("%d %d", &a, &b)

    mut ans := a - b * 2
    if ans < 0{
        ans = 0
    }

    println(ans)
}

mut をつけて変更がない変数があった場合はコンパイルエラーになります。

<file>.v:11:11: `ans` is declared as mutable, but it was never changed

宣言して使われないない変数があった場合は、コンパイルは通りますが警告が出ます。

warning: <file>.v:5:5: `a` declared and not used

出力された C 言語のソース

以下コマンドで、<file>.tmp.c というファイルが出力されます。

$ v run <file>.v -keep_c

とんでもない行数のソースが出力されるので、該当箇所だけ切り抜きました。

 void main__main() {

int a= 0 ;

int b= 0 ;

 scanf ( "%d %d" ,  & a ,  & b ) ;

int ans= a - b * 2 ;

 if ( ans < 0 ) {

 ans  =  0 ;

 }
 ;

 /*opt*/printf ("%d\n",  ans ) ;

 }

これで V 言語で AtCoder に参加することができます!

AOJ: Ring

V 言語のソース

C 言語の文字列を V 言語の文字列に変換する必要あります。
そこは Qiita の記事を参考にしました。

fn main(){
    s := malloc(1)
    p := malloc(1)
    C.scanf("%s %s", s, p)
    s_str := string(s) + string(s)
    p_str := string(p)

    mut flag := false
    for i := 0; i < (s_str.len / 2); i++ {
        if p_str == s_str.substr(i, i + p_str.len) {
            flag = true
        }
    }

    if flag {
        println("Yes")
    }else{
        println("No")
    }
}

私が確認した範囲では文字列を検索する関数はなかったのでループ回してます。

AOJ の提出コード長の制約

出力される C 言語のコードは 80,000 文字以上になりますが、AOJ では 30,000 文字以上のコードは提出することができません。

f:id:Doarakko:20191023002441p:plain

出力された C 言語のソースのメイン関数を読みながら、不要な箇所を削除(必要な箇所だけ追加)する必要があります。
V 言語と一緒に C 言語も勉強したい方にはおすすめです。

5. おわりに

C 言語のソース出力はオプションつけるだけなので記事にするほどではないかなと思いましたが、ドキュメント等に C 言語のソースを出力できることについての記載がなく、コマンドのヘルプ出して初めてわかったのでまとめてみました。

V 言語の公式 Twitter では、度々構文などについてどれがいいかアンケートが行われています。

どれくらい開発に影響しているかわかりませんがおもしろいです。
今後の V 言語に注目していきたいと思います。

6. 参考資料

Kaggle 公式にフォローされました!

やったー!

f:id:Doarakko:20191010171803p:plain

Kagoole とは

Kaggle のコンペと解法を、データや予測の形式・評価指標などから探せる Web アプリです。
現在、約 350 件のコンペと約 1,400 件の解法(ノイズもあります)が登録されています。

このアプリの Twitter アカウントが Kaggle 公式からフォローされたという話です。
小さいことかもしれませんが、とても感激です。

kagoole sample

以下は開発備忘録です。
気になる方は読んでみてください。

Kagoole Twitter アカウント

Kagoole の Twitter アカウントでは、新規にコンペが開催されると自動でツイートするようにしています。

公式よりもはやく新規コンペのツイートしています。
ぜひフォローしてみてください!

ビッグバーガーを表示するコマンドを作りました

Biiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiig burger!

sample

1. 使い方

インストール

$ go get github.com/Doarakko/bigburger

実行

$ bigburger -p 3 -t 2 -n 3 -c 2 -l 2 -i 0.6

2. オプション

現在以下のトッピングを追加可能です。

  • バン
  • トマト
  • レタス

f:id:Doarakko:20191006164845p:plain

Usage of bigburger:
  -C int
        how many cat
  -R    flip vertical
  -b int
        how many bun
  -c int
        how many cheese
  -i float
        rate of intervals (default 1)
  -l int
        how many lettuce
  -n int
        number of big burger (default 1)
  -o string
        output image file
  -p int
        how many putty (default 1)
  -r    flip holizontal
  -t int
        how many tomato

こちらの手順でやれば簡単にトッピングを新規に追加することができます。

3. 作った経緯

Twitterコマンドライン上に「長い猫」を表示する longcat というコマンドを知り、「そうだ、ビックバーガー表示させよう」と思いました。

longcat をフォークして bigburger を作ってます。

終わりに

Go でのコマンド作成と配布の簡単さを知れてよかったです。

最後に私の大好きなダブルチーズバーガーの画像を貼っておきます。

f:id:Doarakko:20191006164926p:plain

Kaggle のコンペと解法を探せる Web アプリ「Kagoole」を作りました

Kaggle のコンペと解法を, データや予測の形式・評価指標などから探せる Web アプリ「Kagoole」を作りました.

f:id:Doarakko:20190808152201p:plain

Kaggle のことを知らない方のために Wikipedia の一文とわかりやすいスライドを貼って起きます.

Kaggleは企業や研究者がデータを投稿し、世界中の統計家やデータ分析家がその最適モデルを競い合う、予測モデリング及び分析手法関連プラットフォーム及びその運営会社である。(Wikipedia

以下は開発備忘録です.
Kagoole に興味のある方や Web アプリを作ろうと思っている方の参考になれば幸いです.

0. 目次

  1. Kagoole 構成
  2. 開始時点のスキル・知識
  3. 開発する目的
  4. 技術選定
  5. アプリ開発前にやったこと
  6. 苦労した・悩んだ点
  7. 反省点
  8. Kagoole の課題
  9. 感想

1. Kagoole 構成

フロントエンドとバックエンドで2つの Heroku アプリが動いています.
別々にした方がデプロイが楽そうだと思ったのですが, ドメインが別になったことで CORS 地獄にはまりました.

f:id:Doarakko:20190808155605j:plain

10分おきに Kaggle API を叩いて新規コンペの取得と開催中のコンペ情報(チーム数, 終了日)の更新を行なっています.

2. 開始時点のスキル・知識

  • Web アプリケーション開発
    • 業務経験ゼロ
    • Golang で「漢番付」という Web アプリを作成
    • 全体の雰囲気はイメージできている
  • REST API
    • 使ったことはあるが作ったことはない
  • Heroku
  • 英語
    • 読むのはそこまで苦ではない
    • Google 翻訳の助けは必要

バックエンド

フロントエンド

  • HTML, CSS
    • 基本的なことはわかる
  • JavaScript
    • HTML で onclickalert()confirm() を書いたことがあるくらい
  • React
    • ゼロ

3. 開発する目的

  • 類似コンペや, 業務と関連がありそうなコンペを探せるようにする
  • 解法のまとめ
    • 現状いろいろなところに散らばっていて探すのが面倒

個人的に

  • フロントエンドの勉強
  • フロントエンドとバックエンドが別れた(Web フレームワークの固有 Web テンプレートをつかわない)アプリがどう動いているのか理解する

4. 技術選定

方針

1. メジャーなものを選ぶ

  • GitHub の Used by・Watch・Star・Fork 数, 更新頻度

初心者の勉強ということもありとりあえずメジャーなものを選ぶことにしました.
またシンプルな CRUD アプリのため, メジャーなものを選べば困ることはないだろうという判断です.

2. ちょっと調べる

メジャーなものが複数あった場合には, 要件を満たすか・それぞれの長所と短所を軽く調べます.
長くても1時間くらいで切り上げました.

3. 好きなものを使う

  • 名前, ロゴがかっこいい
  • Twitter でつぶやいている人がいる

素人が1人で調べたところで限界がある(or 膨大な時間がかかる)ので最後は適当です.
プライベートは好きなことをした方が健康に良いです.

クラウド: Heroku

最初は GCPAWS に挑戦しようと思っていたのですが, 以下理由により逃げの Heroku にしました.

  • お金を1円もかけたくなかった
    • GCPAWS が無料でどこまでできるかわからない
  • 直近で GCP にてインスタンス消し忘れで数万円持ってかれた

Heroku は何も知らなければお金がかからないのでおすすめです.

DB: PostgreSQL

Heroku のアドオンです.

DjangoArrayFieldPostgreSQL のみの対応だったことが理由です.
ここは開発途中に決めました.

ArrayField は ['apple', 'orange', 'pineapple'] のようなデータのために使います.

本アプリでは以下で使用しました.

  • Tags
  • Data Types

言語: Python

Kaggle API を使うためです.
Kaggle API は通常コマンドラインから使用しますが, Python 製ライブラリのため Python スクリプトから使用できます.
これにより Kaggle コマンドからは取得できないデータを取ってこれます.

気になる方はこちらの記事を見てください.

REST のエンドポイントも探せばわかるのかもしれませんが, そこまでして別の言語を使う必要はないと判断しました.

Web フレームワーク: Django

解法の登録・更新・削除権限を管理するために, Flask よりも Django を使った方が実装が楽そうだと判断したためです.

現在は権限管理は行なっていません.
理由は「6. 苦労した・悩んだ点」で話します.

フロントエンドフレームワーク: React

ロゴが写輪眼みたいでかっこよかったので React にしました.

ライブラリ

開発しながらライブラリのドキュメントやデモをみたり, 実際に動かしながら決めました.

メジャーな言語とフレームワークを選んでおけば大抵周りのライブラリは誰かが作ってくれています.
感謝です.

5. アプリ開発前にやったこと

開始時点ではアプリ完成までの道筋がまったく見えていません.

「2. 開始時点のスキル・知識」から, 以下を勉強する必要がありました.

5.1 やったもの

1. Django Girls Tutorial

Django Girls という非営利の団体が作っているチュートリアルです.
多くの言語に翻訳されていて内容もわかりやすく Web アプリを開発したことがない人にもおすすめです.

ブログアプリの作成を環境構築からデプロイまでやっています.
Django の公式チュートリアル よりもこちらの方が良さげだったのでこっちにしました.

2. Django REST framework: tutorial

Django REST framework の公式チュートリアルです.
内容が濃かったのでたいていのことはカバーしているのではないでしょうか.

私は自分が作成するアプリに使わなそうなところは流しました.

3. Build a To-Do application Using Django and React

個人のブログ記事で Todo アプリを作成しています.
私はこの時点では React は何もやっておらず, React のコードは思考停止コピペです.

Django + React でのチュートリアル記事はどれも微妙だったので,
時間をかけずに Django + React での開発の全体の雰囲気を確認することを目的にしました.

私かチュートリアル自体の問題かはわかりませんが, うまく動かないところがあるので注意してください.

4. React: step-by-step guide

React の公式チュートリアルです.
途中途中で React の思想的?なことや, こういう風にコードを書いた方が方が良いみたいなことも書いてあり楽しかったです.
日本語版もあります.

5.2 どのチュートリアルを行うかを決める手順

基本的には公式チュートリアルをやります.

1. 英語でググる

日本語で書かれたチュートリアルにも素晴らしい・新しいものはたくさんありますが, 古いものやノイズを多く含みます.

私は良いもの悪いもの(正しいもの正しくないもの)が判断できない知識レベルの時にはなるべく英語の情報を見るようにしています.

2. 更新日時, 使用している言語・フレームワークのバージョンを確認

少しバージョンが古い(2.7 と 2.9 など)くらいは大抵問題ないですが, 古すぎると以下のようなことがあるので気をつけます.

  • 書き方が違う
  • 重大なバグがある
  • 新しいバージョンで便利な機能が追加されている

3. チュートリアルをさらっとみて作りたいものと関連がありそうなものを選ぶ

  • Todo を登録・更新・削除するところを解法に置き換えればなんかできそう
  • create-react-app で別アプリとしてフロントエンドアプリ作ってる
  • etc

6. 苦労した・悩んだ点

1. Kaggle API で取得したデータの加工

コンペのデータと予測形式はタグから抽出しています.

f:id:Doarakko:20190808151528p:plain

API から取得したデータをみると Kaggle 公式(or コンペ開いた団体)がタグ付けを始めたのは 2015年あたりからです.
また現在のタグ付けもしっかりされているわけではないので, そのまま使うと空が多くなります.

f:id:Doarakko:20190808151754p:plain

そこで以下のようなルールベースでの補完を行いました.

  • 評価指標が「AUC」なら予測形式は「分類」
  • コンペのタイトルや説明文に「classification」が入っていたら「分類」
  • 評価指標に「image」が含まれていたらデータの形式は「画像」
  • etc

詳しくはこちらのコードを見て見てください.

現状コンペのデータは編集不可です.
理由は Kaggle API から取得したデータと手動で登録したデータを一緒に扱った場合,
(Kaggle API から取得したデータを加工するプログラムを編集した場合などに)コンペデータを再取得して更新する際の手動登録したデータの扱いが面倒です.
何もしなければ, 手動登録したデータは全部上書きされて消えてしまいます.

ここら辺どのような形にするべきか考え中です.

2. 検索機能

検索をフロントエンドとバックエンドのどちらで実装するべきか悩みました.

こういうロジック的なことはバックエンドの方でやるべきなのではと思ったのですが,
以下理由によりフロントエンドで行いました.

  • キーワード入力してリクエスト送って返ってきたデータ表示するのは遅い
  • そこまでの検索機能は必要ないのでは
  • データ数が多くないのでフィルターでパフォーマンス上問題ない

検索というよりはフィルターによる絞り込みです.
これにより複数キーワードでの検索ができないという問題が生じています.

フロントエンド側での検索とは別に, 「Advanced Search」というような形でバックエンド側での実装を考えています.

3. 解法の登録・削除権限

方法として以下の4つが考えられました.

  • アカウントを作成した人のみ解法の登録が可能
    • 全ての解法を削除可能
    • 自分が登録した解法のみ削除可能
  • アカウントなしで解法の登録が可能
    • すべての解法を削除可能
    • 削除不可

現在はアカウントなしで解法の登録とすべての解法の削除ができるガバガバ状態です.
一定期間履歴を残しており削除時には通知を飛ばしているので, 何かあったときはすぐに管理画面から復元できます.

理由は以下です.

  • アカウント作るのが面倒

開発するのもユーザが作るのも面倒です.
私はユーザにアカウントを作成させる行為は非常に重いものだと考えているので, なるべくやりたくありません.

  • 利用対象者がエンジニア

今の状態だと誰でも解法を全削除できますが, アカウント制にしてもしなくてもエンジニアなら簡単に削除できると思います.

また Wiki のように誰でもいじれるようにしたかったので, 自分が登録した解法のみ削除可能というのもちょっと違うなと思いました.

  • アカウントなし削除不可にした場合の削除対応が面倒

フォーム作って, リクエスト来たら内容確認して, 手作業で削除が面倒です.

権限については何か問題が起きてから考えます.

7. 反省点

1. チュートリアル中に飽きる

最初にチュートリアル(「アプリ開発前にやったこと」参照)をまとめてやったのですが, 飽きてだらだらしてしまいました.
チュートリアルの区切りで, 学んだことをブログなどにアウトプットするなどして気分転換すればよかったです.

1ヶ月くらいチュートリアルやってました.

2. フロンドエンド雰囲気で動かしている

JavaScript の勉強を何もせず作ったので, React という言語を勉強したような状態です.
なんかわからないけど動いちゃっています.

JavaScript の勉強のために Chrome 拡張機能でも作ろうかなと思っています.

3. Twitter の有益情報を見て見ぬ振り

以下のような今回の開発と関連のある Tweet が流れてきましたが、キャパオーバーだったので見て見ぬ振りをしました.

  • 今の React で class を使う必要はない
  • export default は使わない方がいい
  • REST よりも gRPC
  • etc

メモは残しているのでここら辺も消化していきます.

4. タスク・スケジュール・工数管理

チュートリアル含めて1ヶ月で完成する予定でしたが2ヶ月ちょいかかりました.

タスク管理は GitHub のプロジェクトで行いました.
やらなければいけないことを書き出してやる順番で並べ替えていました.
リリース後でよい(疲れたので後回し)ものは issue に移しています.

スケジュールと工数管理は何もやってないです.
趣味開発であることも考慮して自分の中で妥協点を見つけたいです.

8. Kagoole の課題

機能的には現在20個以上 issue があり山積みです.
ただ大きな課題としては「使ってもらう」に尽きると思います.

  • 必要なアプリなのか
  • 現状何人の人が使ったのか
  • どれくらいの頻度で使うものか
  • 定期的に使われているのか
  • etc

わからないことだらけなので, まずはログをとることと宣伝が必要です.

9. 感想

予定よりも時間はかかりましたが最終的に完成したのはよかったです.

本当にフロントエンドエンジニアの方には尊敬しかないです.
いつもありがとうございます.