わたねこコーリング

野良プログラマ発、日々のアウトプット

Nuxt3 で Bulma の Admin Template を表示するまで

Nuxt3、長らく RC だったのがようやく正式リリースされましたね。

github.com

早速試してみたんですが、テキストで Hello だけでは味気ないので、どうせならリアクティブ系 F/W と相性が良い Bulma と抱き合わせたやつにしてみようと思います。Free Bulma Templates という27種のテンプレートセットがあるので(下記)、この中の「Admin (Light)」を表示させる、というお題でやってみました。

bulmatemplates.github.io

上記 Github から一式をダウンロード・解凍します。今回はこの中の以下を使います。

bulma-templates-master/templates/admin.html
bulma-templates-master/css/admin.css

では作業開始。npx で Nuxt3 プロジェクトを作成します。

npx nuxi init nuxt3-bulma-admin
cd nuxt3-bulma-admin
yarn install

後々のことを考えると、Bulma は CDN 参照じゃなくてローカルにインスコして SCSS でカスタマイズできるようしておきたいので、これに必要なモジュールをインストール。

yarn add --dev sass bulma @fortawesome/fontawesome-free

Font Awesome のウェブフォントは public/ ディレクトリ(旧 static/)にコピーしておきます。

mkdir public
cp -r node_modules/@fortawesome/fontawesome-free/webfonts public/

以上をアプリで利用できるよう、assets/scss/index.scss を以下の内容で設置します。最後の v4-shims は、Admin テンプレート中で v4 のアイコンを使ってるみたいなので。通常は必要無いかと思います。

@charset "utf-8";

@import "../node_modules/bulma/bulma.sass";

$fa-font-path: "/webfonts" !default;
@import "../node_modules/@fortawesome/fontawesome-free/scss/fontawesome.scss";
@import "../node_modules/@fortawesome/fontawesome-free/scss/solid.scss";
@import "../node_modules/@fortawesome/fontawesome-free/scss/regular.scss";
@import "../node_modules/@fortawesome/fontawesome-free/scss/v4-shims.scss";

Admin テンプレート用の CSSbulma-templates-master/css/admin.cssassets/ にデプロイしておきます。

cp (Admin テンプレートを解凍した場所)/bulma-templates-master/css/admin.css assets/

さて、CSS まわりの準備が出来たので、pages/index.vue を作り、template タグの中に Admin テンプレート bulma-templates-master/templates/admin.htmlbody タグの中身をコピーします。最後の script タグは不要みたい。

<template>
  <!-- START NAV -->
  <nav class="navbar is-white">
    <div class="container">
      <div class="navbar-brand">
      (中略)
      </div>
    </div>
  </div>
</template>

上記ページのルーティングが有効になるよう、app.vue を以下のように書き換えます。

<template>
  <div>
    <NuxtPage />
  </div>
</template>

最後に設定を。nuxt.config.ts にて以下のように追記します。

export default defineNuxtConfig({
  css: [
    'assets/scss/index.scss',
    'assets/admin.css'
  ],
  app: {
    head: {
      title: 'Admin - Free Bulma template'
    }
  }
})

以上です。yarn dev して以下が表示できればオケーイ。

【ワールドカップ】グループリーグの全試合結果を API で取得する

ワールドカップ、盛り上がってきましたね。サッカーというかスポーツ全般への関心は人並み以下な自分ですが、これだけ SMG (スーパー・ミラクル・ゲームw)を見せられると流石に気分が高揚してしまいます。さて、グループリーグも結果が出揃い、ふと「全試合結果ってネットから API で取れたりするのかな?」と思って調べたところ、こんなのが↓。

github.com

イランの基礎科学研究所という所が運営している API の叩き方が纏められています。簡単そうなので、早速手順に従ってやってみます(bashcurl, jq が必要となります)。

この API を利用するにはユーザ登録が必要とのことなので、ログイン名とメールアドレス・パスワードを指定して POST でリクエストします。

$ curl --location --request POST 'http://api.cup2022.ir/api/v1/user' \
    --header 'Content-Type: application/json' \
    --data-raw '{
    "name" : "<ログイン名>",
    "email": "<メールアドレス>",
    "password": "<パスワード>",
    "passwordConfirm" : "<パスワード>"
    }' | jq .
{
  "status": "success",
  "message": "User created",
  "data": {
    "token": "<アクセストークン>"
  }
}

レスポンスされた JSON にアクセストークンが払い出されているので、以後の API 利用ではこれを使って Bearer 認証します。最初に全試合一覧を取得・保存してみます。

$ curl --location --request GET 'http://api.cup2022.ir/api/v1/match' \
    --header 'Authorization: Bearer <アクセストークン>' \
    --header 'Content-Type: application/json' | jq . > matches.json

取得したデータを覗いてみます。

$ cat matches.json
{
  "status": "success",
  "data": [
    {
      "_id": "629c9c8a5749c4077500ead4",
      "away_score": 2,
      "away_scorers": [
        "Cody Gakpo,Davy Klaassen\n"
      ],
      "away_team_id": "4",
      "finished": "TRUE",
      "group": "A",
      "home_score": 0,
      "home_scorers": [
        "null"
      ],
      "home_team_id": "3",
      "id": "1",
      "local_date": "11/21/2022 19:00",
      "matchday": "2",
      "persian_date": "1400-08-30 19:30",
      "stadium_id": "1",
      "time_elapsed": "finished",
      "type": "group",
      "home_team_fa": "سنگال",
      "away_team_fa": "هلند",
      "home_team_en": "Senegal",
      "away_team_en": "Netherlands",
      "home_flag": "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fd/Flag_of_Senegal.svg/125px-Flag_of_Senegal.svg.png",
      "away_flag": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/20/Flag_of_the_Netherlands.svg/125px-Flag_of_the_Netherlands.svg.png"
    },
    (中略)
  ]
}

ふむふむ、このデータ中の .data[].type が "group" のレコードがグループリーグの試合のよう。グループ名・試合日時(現地)・ホームチーム・アウェイチーム・ホーム得点・アウェイ得点はそれぞれ、.data[].group .local_date .home_team_en .away_team_en .home_score .away_score から取れば良さげ。では、jq にこれらの抽出スクリプトを指定して、タブ区切りデータに加工します。

$ jq -r '.data[] | select(.type == "group") | [.group, .local_date, .home_team_en, .away_team_en, .home_score, .away_score] | @tsv' matches.json | sort
A	11/20/2022 19:00	Qatar	Ecuador	0	2
A	11/21/2022 19:00	Senegal	Netherlands	0	2
A	11/25/2022 16:00	Qatar	Senegal	1	3
A	11/25/2022 19:00	Netherlands	Ecuador	1	1
A	11/29/2022 18:00	Ecuador	Senegal	1	2
(後略)

これで全48試合の結果データが取得できますた!

タブ区切りデータを Excel で読み出すとこんな感じ

【Chrome】表示中サイトのクッキーを Cookie-Editor で一発クリア

とあるウェブサービスの利用中に数ヶ月おきくらいの頻度で、ログインしてもページ移動すると勝手にログアウトされてしまうという不具合に悩まされてます。クッキーを全クリアすると解消するようなので、「しゃーねーなー」とボヤきながらその都度、Chrome の設定から当該サイトのクッキーを削除してますが、たまの作業ではあっても地味に面倒。そんな折、こんな Chrome 拡張機能を見つけました。

chrome.google.com

設定に移動しなくとも、ページを表示しながら当該サイトのクッキーを確認や編集、削除できるというスグレモノ。使い方はかんたんで、ツールバーCookie-Editor アイコンをクリックすると、当該サイトのクッキー一覧がポップアップ表示される(↓)ので、

下部のゴミ箱アイコンをクリックすると全クッキーの削除が完了(↓)。

ウェブアプリ開発時にクッキーの値を確認したい時なんかも便利そう。開発者の Christophe Gagnier さんに拍手。

【matplotlib】 boxplot() で whis='range' が使えなくなった件

jupyter (matplotlib は 3.5.3)でデータ集計をしていて、久々に箱ひげ図を作ろうとしたら表題件に気づきました。

この作業ではデータの性格上、外れ値は考慮しなくて良いので、

plt.boxplot(datas, whis='range')

としたら、こんなエラーが。

ValueError: whis must be a float or list of percentiles

はて、以前はこれで良かったのに…と調べたら、matplotlib 3.2.0 (2020.3.4 リリース)から仕様が変わったみたいです。

https://matplotlib.org/3.1.3/api/_as_gen/matplotlib.pyplot.boxplot.html
https://matplotlib.org/3.2.0/api/_as_gen/matplotlib.pyplot.boxplot.html

で、どうすれば良いか言えば、上記ドキュメントに

浮動小数点数のペアの場合、ひげを描画するパーセンタイルを示します (例: (5, 95))。 特に、これを (0, 100) に設定すると、ひげがデータの全範囲をカバーします。

とあるので、

plt.boxplot(datas, whis=(0, 100))

でオケーイ。

2022年第3四半期 プライムビデオで観た音楽系コンテンツ

今年7〜9月にアマプラで観た音楽系コンテンツをミニレビュー。毎度恒例、ネタバレ御免につきご注意を。

アメリカン・ユートピア (字幕版)

デヴィッド・バーンのライヴ・ドキュメンタリーですが、若い世代から評判が良いようなので「え?何で?」という興味から。正直、ヘッズの頃から彼の音楽的搾取を軸にした世界観には、「世界も歴史もそんな単純なものでは無いだろう」という違和感が強かった自分です。それから40年を経て、老境に入ってもなお白人富裕層の文化簒奪者であることを贖罪し続けるような姿を誠実と見るか停滞と見るかはアレですが、ニヒリズムに陥らず希望を感じさせるパフォーマンスは良いモノかもと思ったり。練り上げられた舞台表現は素直に凄いと感じたし、評価されているのは背景の思想ではなくこちらのほうかな、と解釈しました。

アンドレア・ボチェッリ 奇跡のテノール(字幕版)

どちらかというとサラ・ブライトマンの歌として認識してた「タイム・トゥ・セイ・グッバイ(コン・テ・パルティロ)」のオリジネイター歌手の伝記。盲目だとは知りませんでしたが、両親から十分に愛を注がれているし音楽活動の傍ら弁護士資格まで取っている等、ハンディキャップを埋めて余りある天賦の才を見せつけられるので、悲壮感を感じることなく楽しめるのはイイことなのかな? 故郷のトスカーナの映像が美しい。ラストシーンでのサンレモは「コン・テ・パルティロ」を初めて歌った時かしら。予備知識無さすぎで、ちょっと損したかも。

グッド・ヴァイブレーションズ(字幕版)

ベルファスト・パンクのゴッドファーザー」と呼ばれた、テリー・フーリーの'70年代を描いた伝記映画。続発するテロで寂れゆく街に活気を、と開いたレコ屋の親父が地元パンクバンドと出会い、レコーディングからプロモートにまで奔走。けど商才は無かったらしく、ビジネス的にダメダメな姿が例えばマルコム・マクラーレンあたりとは対照的な善人像で、作品に温かみと笑いをもたらしてます。欲を言えば、当時二十代後半でヒッピー世代な彼の音楽観に、パンクの勃興がどう映ったのかを描いてほしかったかなーと。
[asin:B082YJPL1Q:detail]

ショウ・ボート(字幕版)

1880年代のミシシッピ沿岸で巡業する劇場船を舞台にした家族愛&ラブストーリー(1951年作)。古い映画を観る時、現在の価値観とのギャップで素直に楽しめないことが多くなって来ましたが、本作のラストシーンもそんな感じ。劇中に当時の南部音楽がどれだけ盛り込まれているかが目当てだったのですが、これは当て外れだったようでショボーン (´・ω・`)

ウェブブラウザで HyperCard 名作スタックを楽しむ

Drug Store (山本徹・作)

敬老の日にちなんでインターネット老人会的なネタを。きっかけは12年前につぶやいたこんなツイートに、先日メンションが付いたことでした。

ナウなヤングの方々に説明すると、HyperCard (ハイパーカード)とは主に1990年代、Classic OS 時代のマッキントッシュで隆盛を誇ったマルチメディア(死語)オーサリングソフトウェアで、ウェブのご先祖様みたいなもんです。無料でバンドルされておりプログラミング言語の習得無しにマルチメディアコンテンツ(「スタック」と呼ばれた)の製作が可能で、市井のクリエイター達が多くの優れた作品を創り出しました。日本では絵本作家の山本徹氏が有名で、個人的には「Drug Store(ドラッグ・ストア)」という作品が好きでした。残念ながら HyperCard は OS-X には移植されず、名作スタックの数々は歴史の彼方に埋もれ知る人も少なくなてきた昨今… そこに「Internet Archive (米国のマルチメディア資料保管サービス)で HyperCard、動くよ」とのお知らせだった訳です。山本徹氏の作品はここ↓から閲覧できます。

archive.org

URL にアクセスすると ブラウザ内で旧マッキントッシュが起動してこんな画面が。

なるほど、開いたフォルダーに何やら山本徹氏の作品が集められている模様。「Drug Store Folder」をダブルクリックしてみます。

「Drug Store(English)」をダブルクリック。

スタックが起動されたみたいです。画面をクリックすると…

場面が進んで、森景に佇む妖しい雑貨屋が。ドアをクリックして、冒険の始まりです。

とまぁ、こんな感じで懐かしの HyperCard スタックがウェブブラウザ上で寸分違わず動いちゃってます。メンションツイートをくださった英ゲーム開発者の Matt Sephton さんによると、これは PCE.js という Classic OS をエミュレートする JavaScript プロダクトを使っているとのこと。すげーな… 他にも4000近くのスタックがアーカイブされているようで、軽く懐かし死にしそうです。

自分も当時、細々とスタックを作っていたもので、週刊モーニングに連載してた「帽子男シリーズ」(上野顕太郎・著)でマンガを切り取ってパラパラアニメを作ろう、てな企画があったのでスタックを作って送りつけた思い出が。どうやら応募者は私一人だったようで、めでたく賞品のうえけんさん使い古し冷蔵庫と色紙をゲットしたというオチでしたw Internet Archive への登録は、著作権的にアレなのでちょっと躊躇いますけどね。

【AWS SSM】パラメータストアから環境変数ファイルを生成する

AWS Systems Manager のパラメータストアで管理している定数から、アプリケーションプログラムで使う .env の類をシェルスクリプティングで生成する、という小ネタでつ。

本件では、下記を前提とします。

  • パラメータストアでのパラメータは全て文字列型。
  • 開発系・本番系などでパラメータを振り分けたいので、パラメータ名には、名前空間として /my-prod/dev/DATABASE_HOST のように製品名や系統を埋め込んだプリフィックスを付与している。
  • AWS-CLIJSON 出力するように設定。
  • JSON 操作に jq を使用。
  • シェルは bash で。

さて、パラメータを取り出して環境変数の記述に変換する際には、変数名からプリフィックスを取り除いたりしたいので、プリフィックスを記憶しておきます。

export PREFIX=/my-prod/dev/

AWS-CLI でプレフィクスを指定してパラメータを全て取り出すにはこんな感じ。

aws ssm get-parameters-by-path --path "${PREFIX}" > parameters.json

出力された JSON データから、パラメータ名と値を取り出して(名前からプリフィックスは除去)いったんタブ切りに変換します。

cat parameters.json | jq -r '.Parameters[] | [.Name['${#PREFIX}':], .Value] | @tsv' > parameters.tsv

最後にこれを「変数名=値」の書式に変換。

cat parameters.tsv | awk '{ print $1 "=" $2 }'

以上をパイプで繋いで完成です。AWS-CLI でのページングや「変数名=値」でのエスケープ等は端折ってありますが、適宜よろしくやって下さいw

aws ssm get-parameters-by-path --path "${PREFIX}" \
  | jq -r '.Parameters[] | [.Name['${#PREFIX}':], .Value] | @tsv' \
  | awk '{ print $1 "=" $2 }'