OmniAICreator/Qiita-1.07M huggingface dataset:
DOMについて

# はじめに
この記事は[Webの基礎をおさらいカレンダー Advent Calendar 2022](https://qiita.com/advent-calendar/2022/basic_review)です。
このカレンダーでは、なんとなくわかった気になっている、Webの知識をおさらいするカレンダーです。
興味をもし持ってくださった方は、購読いただけると嬉しいです！

## DOMとは

Document Object Modelの略で、HTMLやXMLを操作するための仕組みです。

```html
<!DOCTYPE html>
<html>
 <head><title>example</title></head>
 <body><p>hoge</p></body>
</html>
```

例えば、HTMLで上記のように表されるものは、DOMだと下記のように表される。
一意に場所を指し示すので、操作ができるようになるというわけです。

```DOM
└Document
  └Doctype: html
  └Element: html class="e"
    └Element: head
      └Element: title
        └Text: example
    └Text: ⏎␣
    └Element: body
      └Text: hoge⏎
```

上記のように階層構造が取られていて、各要素をノードと呼ぶ。
対象のノードから
上位階層にあるものを親ノード、
下位にあるものを子ノードと呼び、
同一階層にあるものを兄弟姉妹ノードと表現する。

## 実際にDOMの操作を行ってみる

```
<!DOCTYPE html>
<html>
 <head><title>example</title></head>
 <body>
   <p id='target'>hoge</p>
  </body>
</html>
```

pタグにid属性を付与することで、そのページ内で一意のものだと宣言できます。

JavaScriptで、下記のメソッドを使用することで、id名がtargetのものを特定できます。
`document.getElementById('target')`

上記にさらにstyleのcolor属性を指定してみると、色が青に変わります。
`document.getElementById('target').style.color = 'blue';`

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="qBydgmr" data-user="yutaroud" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/yutaroud/pen/qBydgmr">
  Untitled</a> by yuki (<a href="https://codepen.io/yutaroud">@yutaroud</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

 
# まとめ
以上、DOMについての説明でした！
DOM操作はよく使うので、必ず覚えておきましょう！

[Webの基礎をおさらいカレンダー Advent Calendar 2022](https://qiita.com/advent-calendar/2022/basic_review)でした。
興味をもし持ってくださった方は、購読いただけると嬉しいです！

## 参考文献
[DOM](https://dom.spec.whatwg.org/)
[JavaDrive DOMとは](https://www.javadrive.jp/javascript/dom/index1.html)
HTTPリクエストメソッドについて


# はじめに
この記事は[Webの基礎をおさらいカレンダー Advent Calendar 2022](https://qiita.com/advent-calendar/2022/basic_review)です。
このカレンダーでは、なんとなくわかった気になっている、Webの知識をおさらいするカレンダーです。
興味をもし持ってくださった方は、購読いただけると嬉しいです！

今回の記事ではHTTPリクエストメソッドについて説明します！

## HTTPリクエストメソッドとは

リソースに対して実行したいアクションを指し示すリクエストを役割ごとに定義したものです。
[RFC](https://datatracker.ietf.org/doc/html/rfc7231#section-4.3)のメソッド定義に記載されているものを紹介します。

## HTTPリクエストメソッドの種類
### GET
情報の取得をリクエストする。
一番定番のメソッドです。

### HEAD
GETリクエストとほぼ同じですが、レスポンスの本文がないです。
通信量の節約のために使います。
例えば、存在チェックなど。

### POST
副作用を伴うデータの送信ができます。
新規データの作成でよく使います。
GETの次によく使うメソッドです。

### PUT
更新用のメソッドです。
元データがない場合は生成が行われ、すでに存在する場合は置換されます。

### DELETE
指定したリソースの削除を行います。

### CONNECT
プロキシサーバーに対して接続を確立するように依頼をします。

### OPTIONS
主にプリフライトリクエスト時に使用されます。
指定されたURLまたはサーバが許可している通信オプションを依頼します。
レスポンスにはAllow ヘッダーが入ります。
プリフライトリクエストでは、本命のリクエストの前に、事前にリクエストを送信して、
リクエストが受け付けられるかどうかを確認します。


### TRACE
基本的にデバッグ用です。
HTTPレスポンスにHTTPリクエストの内容をそのままオウム返し的に返却します。

### PATCH
データの一部を変更するために使用されます。
 
# まとめ

以上、HTTPリクエストメソッドについての説明でした。
意識して、使い分けができるようにしていきましょう！

[Webの基礎をおさらいカレンダー Advent Calendar 2022](https://qiita.com/advent-calendar/2022/basic_review)でした。
興味をもし持ってくださった方は、購読いただけると嬉しいです！

## 参考文献
[MDN HTTP リクエストメソッド](https://developer.mozilla.org/ja/docs/Web/HTTP/Methods)
[実はそんなに怖くないTRACEメソッド](https://blog.tokumaru.org/2013/01/TRACE-method-is-not-so-dangerous-in-fact.html)
大学生が考える「経営者と技術者と倫理」ビジネスとリスクヘッジ...どっちが大事？

# 前置き
アドベントカレンダーの企画に参加するために記事を書いてみました！
こちらの企画↓


https://qiita.com/advent-calendar/2022/newspicks

### 一部抜粋すると
>######  "「経営と技術の分断をつなぎ直す──。」"
>######  "エンジニアがビジネスとどう関わっていくべきなのかを考える"
要は、エンジニアがどうやってビジネスやビジネス職の方とかかわっていくのかについての投稿をしていく。

大学生の身としては現場でのコミュニケーションについては書けないが、倫理と言う視点と起業を考えれいる者としての視点で少し考えをまとめてみる。


# エンジニア　VS　経営者
このような状況は今も昔もあった。 
具体例として多くの方も知っているであろう **「世界三大失敗」** や電気学会倫理委員会の出版する　**「事例で学ぶ技術者倫理」**　などをもとに検討していきたい。

`補足:世界三大失→ コメット号(飛行機)墜落/リバティー号（貨物船）沈没/タコマ橋崩壊`
`破壊の原因となった具体的な物理現象`
`→コメット号：疲労破壊/リバティー号：脆性破壊/タコマ橋崩壊：自励振動`


# 1. コメット号(飛行機)墜落
英国製の飛行機の話です。1954年1月に事件は起きた。
### なんと、巡航中に機体が突然空中分解してしまった・・・
１万機以上が同時に世界中を飛び交う現代では、そんなこと起こるとは誰しもが思わないだろう。
原因は、「疲労破壊」であった。これは針金などを何度も折り曲げすると脆くなってれてしまう現象みたいなもの。　
実はこの原因が解明される前には２度も空中分離が起きている。１度目以降に多くの対策をとったものの原因追求はできていなかったのだ。

この事件以来、疲労破壊の分野での研究が進められ現在では耐久性の高いジュラルミンなどが用いられている。

# 2. タコマ橋崩壊
1940年アメリカのワシントン州でタコマ橋の完成後わずか4ヶ月のち、
### 風速19m/sの横風のために橋が歪みそのまま壊れた・・・
`(台風の暴風域は風速25m/s)`

これの画像を見てほしい。
<img width="400" src="https://www.st.nagasaki-u.ac.jp/ken/matsuda/bridge-culture-tech/s-image/pic180.jpg">  

参考：長崎大学「５章　橋の近代技術の変遷 ---事故の教訓---」
https://www.st.nagasaki-u.ac.jp/ken/matsuda/bridge-culture-tech/

橋の右側がこんなにも波打っている。
こちらも現在は多くの研究が行われ対策などが施されている。



# 3. スペースシャトル・チャレンジャー号の事故
次にこちらも有名な話だが、個人的には　
### スペースシャトルの爆発は防げたのでは・・・　
と考えている。　
　
ある寒い日、アメリカでスペースシャトルの打ち上げを行った。ゴム製のOリングが寒さで硬化してしまっていた。。。それを知っている **CTO（技術担当副社長）と現場の技術者** は、 **経営者(上級副社長)** に懸念を伝えたが、最終的には **経営者とCTO** がロケットを飛ばすと決定してしまった。
初めは、打ち上げに反対していたCTOも最終的には説得させられてしまった。　
ここで軽く関係をまとめる 

||CTO（技術担当副社長）|現場の技術者|経営者（上級副社長）|
|:---|:---|:----|:--|
|役職|技術責任|現場を一番知る者|経営上の判断をしないといけない|
|状況|経営陣と現場の技術者に挟まれる|部品の耐久性を以前から懸念|NASAからの圧力を受ける|


### Take off your engineering hat and put on your management hat.
### 技術者の帽子を脱いで、経営者の帽子を被りたまえ
と経営者に言われた技術担当者は説得させられてしまった。　

### もしも自分がCTOなら・・・経営者なら・・・
と考えると・・・


# 4. 東海道新幹線の開発　
最後の例として日本の例をあげる。　
日本の新幹線車内での死亡事故は０であると言われている。　
（ただしこれは、新幹線列車内の乗客が死亡する列車事故がないと言うことはある。）　　
地震の例を一つ挙げたい。　


新潟県中越地震の際に新幹線が脱線したが被害を最小限に抑えられたのは、阪神・淡路大震災を受けて
### 特に補修が必要であると考えられる架橋の補修工事を進めていた。　
地盤を調査し、優先的に補修をしたおかげて線路の崩壊を防げたとのことだ。　

このように前もってリスクヘッジを行う大切さがわかる

# もしも自分が技術者なら・・・経営者なら・・・　
どちらの立場も重要であるとは思う。しかし、対立が起きた際、方針を確定させないといけない時は必ずある。起業を考える私の立場からすると悩ましいことであった。

#### エンジニア　VS　経営者

> 倫理を考えると私ならば、技術者の帽子はいつまでも被っていたい。
>エンジニアのかっこよさは何にも敵わない
>お金儲けをしても、悲しむ人が出てしまうならその経営方法は必要はない

そう、強く思う
しかし、本当にその判断ができる自信もない。　
何を軸に倫理観をもっていくのか改めて認識した。　

# 倫理に正解はない　（ありがちだが、、、）
人それぞれの考え方あるとは思う。　
少しこの記事を見て、経営者も技術者も欠かせないし、お互いの信念があることを再認識したい。　
>######  "「経営と技術の分断をつなぎ直す──。」"
>######  "エンジニアがビジネスとどう関わっていくべきなのかを考える

### 「分断」
は強い言葉だとは思うが、行動の軸は確実に経営と技術は違うと思う。
このギャップを埋めるのは日々のコミュニケーションとお互いの相手の考え方を理解する姿勢が大事だお思う。　

### エンジニア
はビジネスにもっと関わるべきだとも思う。専門性だけでは乗り越えない時代が来ると思う。　


# 最後に
ここまで読んでいただいてありがとうございます。　
乱丁で読みにくいなと自分でも思いましたがご容赦ください。　

やさしい世界を作るには、何が必要なのかしっかり考える必要がありそうだと感じます。　
何をすればよかったのか、何をしたのが行けなかったのか、過去を見ることもたまには良いのではないでしょうか。その時の最善を尽くすために、１回の判断を間違わないために経験だけでなく過去の知識もあるといいのかもしれませんね

## 　参考文献 
・事例で学ぶ技術者倫理　電気学会倫理委員会出版


https://www.aero.jaxa.jp/topics/column/0201.html


https://www.st.nagasaki-u.ac.jp/ken/matsuda/bridge-culture-tech/5-chap.html
2022/12/24主にITとかセキュリティの記事

159サイトを運用するサーバに不正プログラム、CMSを侵害か - 山形大
https://www.security-next.com/142321

複数アパレル通販サイトが不正アクセス被害 - 一部サイトの脆弱性から拡大
https://www.security-next.com/142431

シャープのデジタル複合機に脆弱性 - 管理者PWの適切な管理を
https://www.security-next.com/142460

「LINE」のKeep機能に不具合 - 特定条件下で別アカウントより閲覧可能に
https://www.security-next.com/142450

古河市のFacebookアカウントが乗っ取り被害 - フォロー解除を
https://www.security-next.com/142477

スマホアプリ「＋メッセージ」にURL偽装が可能となる脆弱性
https://www.security-next.com/142478

2023年も激化するフィッシングメール詐欺　メールセキュリティ企業Vadeが語る、傾向と対策(12/20)
https://enterprisezine.jp/article/detail/17103

NTTデータの海外子会社がGDPR違反で制裁金、ついに日系IT企業が摘発対象に(12/23)
https://xtech.nikkei.com/atcl/nxt/column/18/00989/122100105/

楽天グループが選んだIT基盤の統合先、オンプレミスかパブリッククラウドか？(12/23)
https://xtech.nikkei.com/atcl/nxt/column/18/01672/122100044/

セキュリティープロトコル「TLS」の古いバージョンが使用禁止に、なぜ危ないのか(12/23)
https://xtech.nikkei.com/atcl/nxt/column/18/02306/121900001/
MapLibre GL JSで地理院標高タイルを利用するためのモジュールを公開しました

:::note info
これは [MIERUNE AdventCalendar 2022](https://qiita.com/advent-calendar/2022/mierune)　24日目の記事です。
昨日は @sorami さんによる [国土地理院「地名集日本」を餅から米](https://qiita.com/sorami/items/804dcaa90091f3f3445b) でした。
:::

## TL;DR

![screenshot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73197/a8945daf-1d3f-801b-d40f-8e06ccfa1af4.png)*（こいついつも富士山の3D地図作ってんな…）*

MapLibre GL JSで地理院標高タイルを扱えるようにする`maplibre-gl-gsi-terrain`を公開しました

https://github.com/Kanahiro/maplibre-gl-gsi-terrain

https://kanahiro.github.io/maplibre-gl-gsi-terrain/example/

## 使い方

```sh
npm install maplibre-gl-gsi-terrain@0.0.2
```

```typescript
import maplibreGl, { Map } from 'maplibre-gl';
import { useGsiTerrainSource } from 'maplibre-gl-gsi-terrain';

// そのままsourcesに追加出来るデータが得られる
const gsiTerrainSource = useGsiTerrainSource(maplibreGl.addProtocol);

new Map({
    container: 'app',
    style: {
        version: 8,
        sources: {
            terrain: gsiTerrainSource,
        },
        terrain: {
            source: 'terrain',
            exaggeration: 1.2,
        },
    },
});
```

## 技術的な補足

基本的な考え方は、[以前に書いた記事](https://qiita.com/Kanahiro/items/1e9c1a4ad6be76b27f0f)が詳しいです。ただし以下の2点で改善しています。

1. Float32Array -> PNGの変換に[fast-png](https://github.com/image-js/fast-png)を利用
2. タイルリクエストがキャンセルされた際の処理を追加

インターフェースが

```typescript
const gsiTerrainSource = useGsiTerrainSource(maplibreGl.addProtocol);
```

と、やや奇妙ですが、一番シンプルだと考えています。gsiTerrainSourceは`type=raster-dem`のsourceです。

## その他

- やってることの割にバンドルサイズが大きい。原因はおそらく`fast-png`。ほかによい手段があれば乗り換えたい。

- その他の地理院標高タイルx富士山シリーズ

https://qiita.com/Kanahiro/items/e22594b738655a189c1d

https://qiita.com/Kanahiro/items/3e7358a28684af905a19

:::note info
明日は@DevKoukiMaedaさんです！
:::
Ectoでクエリ発行した時のタイムアウト時間を延ばす

DBの負荷が高くレスポンスが遅延する時に、Ectoでクエリ発行した時のタイムアウト時間を延ばしたい時があると思います。デフォルトでは、１５秒になっているので、以下のようにして変更すればＯＫです。

## 環境準備
```Elixir
$ mix phx.new tran_testpj
・・・省略
Fetch and install dependencies? [Yn] y
・・・省略
$ cd tran_testpj
$ mix phx.gen.html Blog Post posts title:string body:text
```

`tran_testpj\lib\tran_testpj_web\router.ex`に
`resources "/posts", PostController`を追加

```Elixir
defmodule TranTestpjWeb.Router do
  use TranTestpjWeb, :router

  pipeline :browser do
    plug :accepts, ["html"]
    plug :fetch_session
    plug :fetch_live_flash
    plug :put_root_layout, {TranTestpjWeb.LayoutView, :root}
    plug :protect_from_forgery
    plug :put_secure_browser_headers
  end

  pipeline :api do
    plug :accepts, ["json"]
  end

  scope "/", TranTestpjWeb do
    pipe_through :browser

    get "/", PageController, :index

    resources "/posts", PostController #追加
  end
・・・省略
```

## タイムアウト時間の延長
ミリ秒なのでデフォルトの倍の３０秒に設定します。

`tran_testpj\config\dev.exs`を修正

```elixir
import Config

# Configure your database
config :tran_testpj, TranTestpj.Repo,
  username: "postgres",
  password: "postgres",
  hostname: "localhost",
  database: "tran_testpj_dev",
  stacktrace: true,
  show_sensitive_data_on_connection_error: true,
  pool_size: 10, # カンマを追加
  timeout: 30000 # 追加

# For development, we disable any cache and enable
# debugging and code reloading.
・・・省略

```

## 動作確認
ターミナルを２つ開いて、１つ目で以下を実行してテーブルロックをかける

```
$ psql -d tran_testpj_dev -U postgres 
tran_testpj_dev=# BEGIN;
BEGIN
tran_testpj_dev=*# LOCK TABLE posts IN EXCLUSIVE MODE;
LOCK TABLE
```

2つめのターミナルで、プロジェクトフォルダに移動して、以下を実行
```
$ mix phx.server
```
ブラウザで以下のURLにアクセスして、フォームに適当な値を入力してＳＡＶＥボタンを押す。
http://localhost:4000/posts/new

自身で設定したタイムアウト時間が過ぎれば、ブラウザが遷移し、
以下のエラーメッセージが表示される

tcp send: closed (the connection was closed by the pool, possibly due to a timeout or because the pool has been terminated)

テーブルロックを解除する場合は、テーブルロックしたターミナルで、引き続き以下を入力します。
（動作確認が終わった後に解除ください）
```
tran_testpj_dev=*# COMMIT;
COMMIT
```

上記psqlのCOMMITコマンドを、クエリのタイムアウト前に実行すると、
エラー無く、DBにフォーム入力したデータが登録されます。
これでは、上記エラーでも明記されている通り、クエリがpoolされ、実行待ちになっているためです。

Ectoだと、特別な考慮をすることなく、発行したクエリが自動的にpoolされ、DBのロックが解除されれば、DB処理を続行してくれるので、とても便利です。

以上
gem pg　が入らない時の手順

エラーメッセージ
extconf.rb:40:in `popen': Permission denied - /usr/local/Cellar/libpq/15.1 (Errno::EACCES)
        from extconf.rb:40:in `<main>'



1.rbenvを再インストール
`% rbenv uninstall 3.0.2`
`% RUBY_CFLAGS="-Wno-error=implicit-function-declaration" arch -x86_64 rbenv 
install 3.0.2`


2.gemを削除,Gemfile.lockを削除
`% sudo rm -rf vendor/bundle`
`Gemfile.lockを削除`


3.bundleインストール
`% bundle config build.pg --with-pg-config=/usr/local/Cellar/postgresql@14/14.6/bin/pg_config`
=>config=の後はpg_configのフルパスを書く

`% bundle config build.pg --with-pg-config=/opt/homebrew/Cellar/libpq/14.5/bin/pg_config`
`% bundle install`
繰り返し（ループ）処理機能（Laravel）

## 始めに
最近よく、ループ処理を実装するので
備忘録として記事にしました。

ループ処理の認識（自分の）
　→ ある条件になるまで繰り返し処理すること

## 環境
| 開発環境    |バージョン |
|-----------|------------|
| __Laravel__ | 8.83.19 |
| __PHP__     | 7.3.10  |

## ループ処理内容

```PHP:LoopController.php
// ループ処理機能
public function loop()
{
    Log::debug(__FUNCTION__);

    try {
        $i = 0;
        // 繰り返し処理（60秒経過するまで）
        while(true) {

            Log::debug('loopメソッドのwhile文処理中');

            // 60秒が経過した時
            if($i >= 6) {
                // 繰り返し処理を終了する
                break;
            }

            // 処理を停止する（10秒間）
            sleep(10);
            $i++;
        }

    } catch (Exception $e) {
        // ログ出力
        Log::error(get_class($this).':'.__FUNCTION__);
        Log::error($e->getMessage());
    }
}
```

データベースの値、ステータス等を参照する時によく使っています。

無限ループにならないように注意です！
（サーバーに負荷がかかるため）

## 終わりに
閲覧ありがとうございました。
ご指摘、ご意見ありましたらコメントいただけると
ありがたいです。
よろしくお願いします。
SeparatedInterface Registry Plugin ServiceStub

![export 20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11525/744df4d0-5215-5d4b-e445-d35ccf548f35.png)

https://bliki-ja.github.io/pofeaa/SeparatedInterface/

https://bliki-ja.github.io/pofeaa/Registry/

https://bliki-ja.github.io/pofeaa/Plugin/

https://bliki-ja.github.io/pofeaa/ServiceStub/

残りは「ベースパターン」です。構成のうえでは最後になっているので、まるでオマケのようですが、実は場合ごとに分かれたこれまでのパターン群よりも汎用的で、より基礎になってくるのがこのペースパターン群です。

Separated Interface は保守性と拡張性がともに高いアーキテクチャ設計において、あらゆることの基本になる大事なパターンです。原則とさえ言えるかもしれません。

段階的に理解するために、まずは Registry パターンがフォーカスしている問題の方を、先に説明しておきましょう。

いくらオブジェクト指向をサポートするプログラミング言語を使っていても、大規模で複雑なオブジェクト構造を辿って目的のオブジェクトを取り出す必要がある作りになっていると、プログラミングはどんどん難しくなっていきます。よく使われるオブジェクトや設定値、状態変数にすぐにアクセスできる経路があると便利です。Registry は、どこからでも即座にアクセスでき、すぐに目的のオブジェクトが見つけてくれるサービスです。

Registry は便利ですが、それは本質的にグローバル変数です。グローバル変数は、いつ誰が変更するかわからない怖いものです。実行時に変更が起きないものなら安心かというと、まだそうとも言えません。大きなものに依存して、取り出したものを使い放題だと、それに依存しすぎるリスクを抱えています。依存関係が明示的でなく、コンパクトに閉じていない作りは、Registry 利用者の単体テストを困難にします。単体テストが困難だということは、さまざまな変更影響を受ける、安定度の低い部分になるということです。

システムサービスについての Registry は、よく知られた言葉で言うと、つまり「サービスロケーター」のことです。

Separated Interface は、実装クラスを持つパッケージより安定度のはるかに高いパッケージにそのインターフェースを設け、利用者はそのインターフェースだけに依存するようにするパターンです。こうしておくと、実装の有無にかかわらず、オブジェクトを利用するプログラムを書くことができます。実装もまた、この安定したインターフェースに依存するかたちになります。

```plantuml
interface ServiceInterface
package impl {
  class ServiceImpl
}

ServiceInterface <- ClientCode
ServiceInterface <|--- ServiceImpl
```

より良く設計されたオブジェクト指向プログラムは、オブジェクトを取り出さなくても問題を解決できるように作られます。問題解決に必要な関連オブジェクトまで、委譲のバトンリレーをするのです。インターフェースにさえ依存していれば、後は Tell, Dont Ask スタイルだけで目的を果たせるのが理想です。

インターフェースの実装は、依存性注入の考え方で割り当てるのが適当です。Domain Model が Repository インターフェースの持つ、呼ぶだけでエンティティを得られるメソッドを使う様子 (実装は問わない) は、Separated Interface を物語るよい例です。

PoEAA のパターンが実践されていた当時は、まだサービスロケーターへの批判も、依存性注入という言葉もありませんでした。後にそれらを明文化したのは、PoEAA の著者、マーチン・ファウラーその人です。

実装と分離されたインターフェースという前提があれば、Plugin パターンによる拡張性の確保も可能です。リリース後に追加機能が求められても、インターフェースを満たす実装を後で足しさえすれば、本体システムの変更なしに拡張できるのが Plugin です。

Plugin は SOLID の開放閉鎖原則 (OCP) にうまくマッチします。拡張できる箇所が多い場合は、GoF デザインパターンの Observer パターンを有効活用できます。

システムがまだ完成していないときにも、分離されたインターフェースは役に立ちます。分業で開発している別のサービスがまだ実装されていなくても、そのインターフェースさえ決まっていれば、Service Stub で代用して、自分の作業分をテストすることができます。Service Stub はテスト用にだけ使える、中身のないダミーサービスを仮に作ってテストを進めるパターンです。

現在では、多くの単体テストツールに、スタブ(単なるダミー)やモック(正しく呼び出されたかを検証できるダミー)を作る機能を持っています。サービスがリモートコールだった場合は、Swagger によるスタブサーバーや Docker が利用できます。

こうしたアーキテクチャ設計の感覚を、概要説明だけで得られる人はまれです。前提となる感覚を持っておくのに、拙著「ちょうぜつソフトウェア設計入門」はたいへんオススメの一冊となっております。

https://amzn.asia/d/1CG31tg

宣伝っぽいですが、もしこれが他人の本でも、全く同じ内容だったら確定でオススメしています。なぜなら、イチから適切な洋書の約本を何冊も選び、買い揃え、読破するのは、費用面でも労力面でも、大変すぎるからです。
分析のコードレビューってどうする！？Streamlitを試してみました

本記事はモチベーションクラウドシリーズ Advent Calendar 2022の24日目になります。

リンクアンドモチベーションでデータサイエンティストをしている東山です。
突然ですが、みなさんgoogle colabなどの分析のレビューってどうしていますか？
弊社ではレビューをできるように[Streamlit](https://streamlit.io/)を導入してみましたという記事です。
まだまだ試験的な取り組みですが、少しメリット/デメリットが見えてきたのでまとめてみました。


# 課題: 新人の育成
弊社のデータチームは現在7名なのですが、中途のエンジニアはマネージャーの僕を含めて3名で、まだまだ新人が多い状況です。
そのため、彼らの育成がチームのケイパビリティをあげていく上でもっとも重要なポイントと考えています。

## データサイエンティスト育成のためにコードレビューを実施したい
自分が受けてきたアプリエンジニアとしての「育成」を振り返ってみて、もっともありがたかったなと思うのは「コードレビュー」でした。
良い名前の付け方の指摘は、自分の認知と他者の受け取り方の差分を明確にしてくれます。
先輩の指摘でどんどんシンプルになるコードが魔法のようでした。
また、昼休みなどに同僚の受けているコードレビューを見ていると勉強になる瞬間が多くありました。

この個人的な経験からコードレビューに期待する育成効果をまとめると、下記になると思います。
1. チームで保守しやすいコーディングの習得
1. 他の人が受けてるコードレビューの知見の習得（集合知化）

## コードレビューで新人育成したいけどDiffが見にくい

コードレビューを通して育成していくうえで、通常のアプリエンジニアとデータサイエンティストでは若干環境が異なる部分があると考えています。
データサイエンティストが実務でよく使うのは、google colabやjupyter notebookなど、メタデータを含むjson形式が多いと思います。
これをgit管理してPRを作成すると、Diffがとても見づらいのです。
実際、それを補うための[nbdime](https://nbdime.readthedocs.io/en/latest/)というライブラリも存在し、この課題感がある程度共有可能なものだという証拠かなと思います。

この差分把握の煩雑さから、これまで細かいところまで分析コードのレビューが十分にできませんでした。

# 打ち手: Streamlitでコードレビューできるようにした

この課題に光明が差したのがStreamlitの登場です。
多くの記事で紹介されているのでStreamlit自体についてはあまり語りませんが、フロントエンドの知識をほとんど必要とせず、pythonだけでデータwebアプリケーションを作成することができるフレームワークです。

これにより、純粋なpythonコードだけでnotebookのような分析結果を確認できるなと思いました。

# メリット/デメリット

データサイエンティストの育成目的で導入したStreamlitですが、副次的な効果もいろいろ見えてきたので、メリット/デメリットをまとめてみました。

- メリット
    1. （狙い通り）コードレビューは格段にやりやすくなった
    1. （副次的）google colabで分析を行なっていると散らかりがちだったnotebook群が[複数ページにまとめて体系化](https://docs.streamlit.io/library/get-started/multipage-apps)することが可能になった
    1. （副次的）CI/CDを組み合わせることができるようになった
- デメリット
    1. ちょろっとした分析をして軽く共有したいような内容の場合、いちいちPRまで作成するのは煩雑
    1. colabに慣れた新人たちにはstreamlit自体の学習コストがかかる → そもそもPR作成が遅れがち
    1. colabではなかった個人ごとのPCでの環境差の影響を受けやすい

# 結論: とはいえ、おすすめです

メリットの1をもう少し補足すると、streamlitでのPRが作成されることにより、「適切にディレクトリを作成し再利用可能なコードを作成しましょう！」というインセンティブが働くようになりました。
メリットの3と合わせて、時間が経つほど開発効率が向上するのではないか？と考えています。
デメリットの2に関しても、習熟と共にカバーできるようになると楽観視してます。

今後としては、コードレビューをたくさん積み上げて、新人たちにそれぞれのコードレビューでの学びの共有会を実施して集合知として行けたら良いなと思っています。

# むすびに

データサイエンティストの育成に関して、今回はコードレビューを取り上げましたが、うちではこんな工夫しているよ！というアドバイスなどあれば是非とも交流させて下さい！
以上です、最後までお読み頂きありがとうございました。
あなたしばらく出禁ね！【AWS WAF】

同一のIPからアタックのような大量のアクセスを受けた場合に、
AWSのWAFを使ってしばらくそのIPを出禁にするようにしました
サクッと設定が可能ですので、攻撃等を防ぐ一手目として設定してみてください

## 設定
Web ACLs(Access Control List)は任意の名称で作成、ALBやCloudFrontなどの接続先を設定しておきます
作成したWeb ACLsに対してルールを付与します
![スクリーンショット 2022-12-24 2.35.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422294/dc08425d-3949-486f-6840-c3fe7c4e96b9.png)
Add rulesより、Add my own rules and rule groupsを選択
ルールタイプはRule Builderを選択します

![スクリーンショット 2022-12-24 2.38.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422294/b21b2fe5-8ffc-09ad-ce4e-77908485667a.png)
任意の名前を入力しましたら、次はTypeをRate-based ruleというものにします

Rate limitは5分間でのアクセス数の上限を設定します
今回は10,000リクエストに到達すると出禁をさせることにしました
IPアドレスを対象に制限をかけるのでSource IP addressに
最後の項目は、一部にルールを設けたい場合のみ設定しますが、今回はサイト全体が対象です
![スクリーンショット 2022-12-24 2.42.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422294/ccbc4bfb-0439-f108-a50b-2d9ccc51ab6c.png)

Actionを設定していきましょう
出禁にするのでもちろんBlockを選択
Custom responseを設定したかったので、Response code 429を返すようにしました
![スクリーンショット 2022-12-24 2.47.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422294/6e3eb0cc-d972-c4a2-6d71-2dfa1ec21966.png)

また、レスポンスをbodyを任意のものを返したかったので、
このようなJSON形式でstatusには429, error内容としてToo Many Requestsを返すように設定しました
![スクリーンショット 2022-12-24 2.49.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422294/53dcd084-26fa-a7fa-415a-1ccba6904c06.png)

以上で設定は完了なので、Add ruleをクリックしましょう
これで無事、屈強な門番を構えることができました！

## 確認
本当にブロックされるかどうかなどはApacheBenchを使って、大量のアクセスを行なってみてください
ある一定以上になるとブロックされているのが確認できるかと思います
ブロックされている事を確認したのちに、curlコマンドやPostmanなどを使ってアクセスを試みるとカスタムされたレスポンスが返ってくることも確認できました

なお、ブロックは5分間はブロックされ、その後問題がなければ解除されるみたいですが、詳細な時間等はわかりませんでした
私は、門番の気分次第なのかなと呑気に捉えています:relaxed:

これにて失礼
性格診断の分布で各国をクラスタリングしてみた【16-personalities】【階層型クラスタリング】

# はじめに
性格の人口割合を国ごとにまとめたものが、[16-personalities](https://www.16personalities.com/ja)の[profileサイト](https://www.16personalities.com/country-profiles/japan)に載っているので、このデータを使って各国をクラスタリングしてみたらどのような結果になるか興味を持ちました。今回はその解析結果をまとめました。

https://www.16personalities.com/ja

https://www.16personalities.com/country-profiles/japan



# データ収集
profileサイトをスクレイピングしました。スクレイピングについては、以前の私の記事が参考になるかと思います。

https://qiita.com/RisaM/items/da3650243005dcc25680

その結果以下のようなテーブルが得られました。単位は％です。行が性格32パターンを表し、列が182ヵ国を表しています。
|                      |   Afghanistan |   Åland Islands |   Albania |   Algeria |   Andorra |
|:---------------------|--------------:|----------------:|----------:|----------:|----------:|
| Turbulent Mediator   |          4.82 |           13.4  |      8.36 |     12.18 |     10.23 |
| Turbulent Campaigner |          4.06 |            6.88 |      6.47 |      5.23 |      9.3  |
| Assertive Consul     |          5.94 |            4.06 |      3.99 |      2.75 |      3.72 |
| Assertive Campaigner |          3.9  |            5.47 |      3.98 |      3.34 |      8.37 |
| Turbulent Advocate   |          3.13 |            7.76 |      5.84 |      5.83 |      3.72 |

# 階層クラスタリング
以下のサイトを参考にして階層クラスタリングを行いました。

https://qiita.com/yasaigirai/items/ec3c3aaaab5bc9b930a2

このサイトに従って、三つの指標を確認したところ、最適なクラスタ数は4でした。クラスターごとに色分けしたデンドログラムです。

![dendoro2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461625/acf71700-c58d-6ab6-8a05-15b1a190fe44.png)


# どの国同士が性格が近いか
デンマークとノルウェイ、ベトナムとカンボジア、UKとアイルランド、アメリカとカナダ、オーストラリアとニュージーランド、メキシコとコロンビア、エジプトとサウジアラビアなど、隣国同士は似ている傾向がありました。面白いと思った隣同士の組み合わせは以下のようになりました。
- 日本とフランス
- 香港と台湾
- イタリアとブラジル

# 性格の一覧
![16perso.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461625/d73b4d81-b155-ff44-ef40-6b0d1ac4b6d7.jpeg)


# クラスターごとのz-score
各クラスターが平均からどの程度離れているかを確認するため、z-scoreを使いました。その結果を表にまとめました。
デンドログラムの色との対応：オレンジ→クラスター1 緑→クラスター2 赤→クラスター3 紫→クラスター4 
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461625/3fc8cd68-0a7a-4d26-00ea-094b3bcad35f.png"> 　　　　　　<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461625/d2932195-811d-e0bc-c6e0-e62f3f898c94.png">

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461625/a55b3211-ca64-05c5-d3d5-d4286c34aea5.png"> 　　　　　　<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461625/ac28c61c-1b85-a14d-848c-f54fda2db9d0.png">

1以上のものを緑色、-1以下のものを赤色で塗りました。
- クラスター1
提唱者と仲介者が平均より高いということで、温和に解決しようとする人が多そうです。領事官タイプが低めでした。
- クラスター2
緑で塗られている4つの性格は、四つの分類のうちすべて分析家に当てはまりました。数字に強い人が多そうです。このクラスターにはインドが含まれているので、確かにと思いました。
- クラスター3 
クラスター1とは逆で領事官が高めでした。他は幹部や起業家が高く、組織を引っ張っていく系の人が多そうです。
- クラスター4
一番属する国が多かったので、平均と近めになっています。

# クラスターごとの世界地図への色分け
近日中に公開します。

# おわりに
16-personalitiesは質問数も多く、かなり信頼できる性格診断ではないかと個人的には思っています。ぜひやってみてください。
scrapy-s3pipeline利用時にスクレイピングしたアイテムが最後の要素で上書きされてしまう

# 環境・前提条件
python:3.9.15
Scrapy:2.7.1
scrapy-s3pipeline:0.7.0
※ Dockerコンテナ上で動作

# ソースコード
scrapyやscrapy-s3pipelineのお作法に則って、下記の通り記載していました。
```spider.py
class MySpider(CrawlSpider):
    name = "my-spider"
    allowed_domains = ["xxx.jp"]
    start_urls = ("https://xxx.jp")
    rules = [
        Rule(LinkExtractor(allow=r'/yyy/'), callback='myparser')
    ]
    #(中略)

    def myparser(self, response):
        my_item = MyCrawlerItem()
        items = response.css(".class")
        for item in items:
            item_info = item.css(".class2")
            for item_detail in item_info:
                my_item["name"] = item_detail.css("div::text").get()
                tbodys = item.css("table tbody")

                for tbody in tbodys:
                    my_item["content"] = tbody.css("li::text").get()
                    yield my_item
```
```items.py
class MyCrawlerItem(scrapy.Item):
    name = scrapy.Field()
    content = scrapy.Field()
```
```settings.py
ITEM_PIPELINES = {
    's3pipeline.S3Pipeline': 100
}

S3PIPELINE_URL = 's3://property-info-storage/{name}/{time}/items.{chunk:07d}.jl.gz'
```

# 問題
scrapy-s3pipelineを利用し、
Amazon S3にスクレイピングしたitemをJsonLine形式でアップロードしたのですが、
アップロードしたjson itemが上書きされてしまいました。

```sample.jl
#期待記載内容
{“a”:1,”b”:2}
{“c”:3,”d”:4}

#確認された記載内容
{“c”:3,”d”:4}　←上書きされてしまっている
{“c”:3,”d”:4}
```

# 原因
s3pipelineにpushしたアイテムは、複数のアイテムをsample.jlとして纏めて出力するために、一時的にリストに溜め込んでいます。  
しかしながら、アイテムがミュータブルな型(dictなど)の場合、
上記のコードだと、同じIDのアイテムをパイプラインに渡してしまうため、新しいアイテムを登録するたびに古いアイテムが上書きされてしまう現象が起きてしまいます。

```s3pipeline.pipeline.py
    def process_item(self, item, spider):
        """
        Process single item. Add item to items and then upload to S3/GCS
        if size of items >= max_chunk_size.
        """
        self._timer_cancel()
        self.items.append(item) #itemのオブジェクトIDが以前のitemと同じ場合、問題となる。
        if len(self.items) >= self.max_chunk_size:
            self._upload_chunk()
```

# 対策
spider.pyを以下のように書き換えることによって、上書きを防ぐことができました。copy.deepcopy()を使用します。

```spider.py
import copy #新規追加

class MySpider(CrawlSpider):
    #(中略)

    def myparser(self, response):
        my_item = MyCrawlerItem()
        items = response.css(".class")
        for item in items:
            item_info = item.css(".class2")
            for item_detail in item_info:
                my_item["name"] = item_detail.css("div::text").get()
                tbodys = item.css("table tbody")

                for tbody in tbodys:
                    my_item["content"] = tbody.css("li::text").get()
                    copy_item = copy.deepcopy(my_item) #新規追加
                    yield copy_item #変更
```

# 参考
↓コピーしたオブジェクトの上書き問題について
https://qiita.com/kokorinosoba/items/e9ab9398af5b44d2ac9a

↓scrapy-s3pipeline
https://github.com/orangain/scrapy-s3pipeline

↓scrapyの書き方
https://scrapy-docs-ja.readthedocs.io/ja/latest/index.html
Quickstart: Compose and Rails を WSL2で試して躓いた時のメモ

### モチベーション
業務でRailsを使うことが決まったので、そのためのキャッチアップをなと。
環境構築の際に、1からやるの面倒なので[Quickstart: Compose and Rails](https://github.com/docker/awesome-compose/tree/master/official-documentation-samples/rails/)を使用してひな形をすぐに手に入れようとしたら思った以上に面倒だった。
なので、再度環境を作るといったときに、同じ轍を踏まないようにメモを残そうかなと思った次第です。

サイトにあるものから変数名すら変えていないので、初学者の方はもしかしたらコピペで対応できるかもです。（初学者がWSL2で開発するかどうかは知りません。。。
### 環境
OS: Microsoft Windows 10 Home
WSLのLinuxディストリビューションは以下の通り
```
$cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04.5 LTS (Focal Fossa)"
```
インストールしてから特に変更はないディストロ。

なお、基本的にVsCodeでWSL内に入り、Vscodeのターミナルからコマンド操作している。

以下躓いた部分を箇条書き。

### build時にconnectionエラー
＊エラー文のキャプチャ忘れてた。。
最初はdocker loginを試してみたが、治らず。

色々とググってみると、[この記事](https://qiita.com/iwaiktos/items/33ab69a42c3a1cc35dfb#3init-4010-error-utilconnecttointeropserver300-connect-failed-2)がヒット。

この通りにやればbuildが問題なくできた。（もちろん、sourceで反映した後でコマンドを実行しました。）
### docker-compose upにてDBコンテナが立ち上がらない。
以下、docker-compose up を実行時に出力されたlog
```
sampleapp-db-1   | fixing permissions on existing directory /var/lib/postgresql/data ... initdb: error: could not change permissions of directory "/var/lib/postgresql/data": Operation not permitted
```
調べてみると、色々難しそうな話が出てきます。が、docker-compose.ymlで指定している 
`./tmp/db`と`/var/lib/postgresql/data`がそれぞれ違うuser_id,group_idであることが原因っぽいなと。
権限変える方法もいくつかありますが、手っ取り早くdocker-compose.ymlの記述を加えて対応。

```
services:
  db:
    image: postgres
    volumes:
        #  ./tmp/db: -> postgres_volumeへ変更
      - postgres_volume:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: password
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db
# NEW!! volumeを指定
volumes:
  postgres_volume:
```
コメントした2か所を変更・追記すればDBコンテナが無事立ち上がった。ちなみに、指定した/var/lib/postgresql/dataの内容はpostgres_volumeに自動的に反映される（はず

volumeが無事できた場合は、以下のように表示されるので確認したいときは参考に
```
$ docker volume ls
DRIVER    VOLUME NAME
local     sampleapp_postgres_volume
```



### 雑記
初投稿でした。他記事と比べて内容薄いなーと感じましたし、色々とアウトプットしている人は改めてすごいなと。
nRF9160のADCを利用する (nRF Connect SDK 2.1.0)

さくらのアドベントカレンダー2022 23日目の記事です。

https://qiita.com/advent-calendar/2022/sakura

こんにちは、さくらインターネットのこたまごです。


さくらインターネットではクラウド接続向けフルMVNOのSIMとして「さくらのセキュアモバイルコネクト」を提供しています。
また、単純なLTEの回線だけではなく、組み込み向けのプロトコルでクラウド側のプラットフォームとセットで提供する「モノプラットフォーム」と組み合わせた利用も可能です。
標準でサポートするモデム兼MCUとしてNordic社のnRF9160を推奨しています。

Nordic社のnRF9160はワンチップにLTEモデムとARMのMCUを搭載しており、LTEで通信する組み込み開発をこのチップ一枚で行うことができる一風変わったマイコンになっています。

組み込み向けリアルタイムOSのZephyrを利用した "nRF Connect SDK (ncs)" が提供されており、簡単に開発ができる環境が提供されています。

今基板から作って開発しているものが出来上がったらSDKの使い方を公開していこうと思っています。

今日は、SDKの使い方のうち、ドキュメントを漁っても、ググってもなかなか動く状態にできなかったADCについてメモを残しておこうと思います。

NCSはv2系で少し大きめの変更が入っており、v1系の時のサンプルが動かなくなっている部分があるためググって出てきた解説ではダメな時があるので要注意です。

# nRF9160 と nRF Connect SDK v2.1.1 でADCを動かす

ADCを利用するためにする作業は3つです

* prj.conf でADCを有効にする
* デバイスツリーファイル (dts) にADCの定義を追加する
* CのコードでADCを利用する

## prj.conf

ADCを有効にするために必要なオプションは次の一行だけです。

```
CONFIG_ADC=y
```


## デバイスツリーファイル

デバイスツリーには以下の定義を追加します。
この例ではnRF9160のアナログ入力のうち `AIN7` を利用し、ゲインとして1/6を利用している例です。

```dts
&adc {
	status = "okay";
	channel@0 {
		reg = <7>;
		zephyr,gain = "ADC_GAIN_1_6";
		zephyr,reference = "ADC_REF_INTERNAL";
		zephyr,vref-mv = <600>;
		zephyr,acquisition-time = <ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 20)>;
		zephyr,resolution = <12>;
		zephyr,oversampling = <3>;
		zephyr,input-positive = <NRF_SAADC_AIN7>;
	};
};
```

## Cのコード

抜粋ですが、ADCの初期化とサンプリングを行う関数定義は次のようになります。

```c
#include <drivers/adc.h>
#include <hal/nrf_saadc.h>

static const struct device *adc_dev = DEVICE_DT_GET(DT_NODELABEL(adc));
static const struct adc_channel_cfg battsence_channel_cfg =
    ADC_CHANNEL_CFG_DT(DT_CHILD(DT_NODELABEL(adc), channel_0));

int adc_init(void) {
  int err;

  if (!adc_dev) {
    LOG_ERR("device_get_binding adc failed");
    return -1;
  }
  err = adc_channel_setup(adc_dev, &battsence_channel_cfg);
  if (err) {
    LOG_ERR("Error in adc setup: %d", err);
    return -1;
  }

  return 0;
}

int16_t measure_batt_mv() {
  int err;

  int16_t m_sample_buffer;
  const struct adc_sequence sequence = {
      .channels = BIT(7),
      .buffer = &m_sample_buffer,
      .buffer_size = sizeof(m_sample_buffer),
      .resolution = 12,
      .oversampling = 3,
  };

  if (!adc_dev) {
    return -1;
  }

  err = adc_read(adc_dev, &sequence);
  if (err) {
    LOG_ERR("ADC read err: %d", err);
    return -1;
  }

  double adc_value = (double)m_sample_buffer;
  adc_value = adc_value * 3600.0d; // MAX3.6V
  adc_value = adc_value / 4095.0d; // 12bit
  LOG_DBG("ADC raw value: %d", m_sample_buffer);
  LOG_INF("Measured voltage: %d mV", (int)adc_value);

  return (int16_t)adc_value;
}
```

# まとめ

nRF9160は超省電力な装置を作ることができるLTE搭載のマイコンです。
省電力のため、バッテリーで駆動させる製品を作ることも出てくるため、電池電圧の計測などADCの利用が必須となってくるでしょう。

ところが、ADCの例が少ないためなかなか動くコードを書くことができませんでした。
本記事は SDK v2.1.1 で実際に動くことをメモとして残しておくことでnRF9160のADCで困る人が減るといいなと思って書きました。

すごくニッチな内容になってしまってすいません...

Merry Christmas and Happy New year !
2022年を振り返って

## はじめに

2022年も12月になり、アドベントカレンダーも終わりになります。
もうそろそろで新年になるこのタイミングで1年を振り返ろうと思います。

:::note
この記事はポエムですが、最後まで読んでいただけると嬉しいです。
:::

## 今年を一言で表すと…

今年1年を一言で表すと『**アウトプット**』になると思います。
今年は2月から毎週1記事を目標にQiitaでアウトプットを続けてきました。

きっかけは単純です。
2022年になって社内のCX向上Gが毎週1記事を目標にアウトプットし、社内でちゃんとアウトプットしようという風潮を広めていく活動を始めました。私はその活動を見て、フォロワーとして一緒に頑張ることで、CX向上Gの応援と風潮を広める手助けをするため週1のアウトプットを始めました。

*CX向上Gの~~せいで~~おかげで、Qiitaに記事を書くために、土日も含め毎日楽しく過ごしています。*


## 週1アウトプットを始めてみて…
今まで定期的にアウトプットしてきていなかった僕からすると、始めのうちはテーマ探しに苦戦したり、テーマが決まってもどのように書き進めていいかわからず1記事書くのに何日も使っていました。

特にテーマを決めるのが一番苦労しました。*（今でも大変ですが…笑）*

当時はインプットはQiitaやnote, X(Twitter)が中心で界隈での話題が限定的なものでした。
そのため、インプットが圧倒的に足りなく、そこまで深い知識があったわけもないので書けそうな話題を見つけても誰かを真似したような記事になったり、理解しにくい文章になっていました。

そこで私は、日本語ベースのインプットから英語ベースのインプットに変更することで、誰かの真似という感覚から、翻訳をするような感覚に変わり、ある程度文章が書きやすくなりました。

また、英文の記事の方が自分の知らない知識などが多くあるように感じたのでだんだんと知識もついてきたと思います。
副作用として、Google翻訳やdeeplを駆使して英語を理解していく中で、英語のドキュメントへの抵抗がなくなりました。


## アウトプットを振り返ると…

今年1年で100いいねを超える記事を5記事も書くことができました。
contributionも1年で3000を超えるくらいになりました。
*（個人的には嬉しいです。）*

今年バズった&読んでほしい記事はこちらになります。

https://qiita.com/degudegu2510/items/d529ccb82276619d3f5e

↑ この記事は100いいねを突破できた初めての記事です。
グラデーションについて論理的に解説しているので、ためになる記事だったのかなと思います。
　

https://qiita.com/degudegu2510/items/37bb28c44b8c4a2fd429

↑この記事は、ポケモン言えるかなの曲のノリで擬似クラスを紹介する記事です。
現在主要ブラウザで開発中の擬似クラスも含めて紹介しています！
🎶 ラ・ラ・ラ 言えるかな？ 🎶
　

https://qiita.com/degudegu2510/items/8f2a5cce3de08096e06b

↑この記事は、ドロップシャドウについて論理的に解説する記事です。
グラデーションの記事がバズったので、別のシリーズとして書きました。
似たような記事をまた書きたいですが、いいテーマが見つからないです...
　

https://qiita.com/degudegu2510/items/48fac7653a1c032d95bd

↑この記事は、普段のCSSキャッチアップしているサイトを紹介した記事です。
英文の記事を多めに紹介したのがよかったのでしょう。
　

https://qiita.com/degudegu2510/items/1821047debbd58384117

↑この記事は11月28日に公開した記事で、カードのレアリティ表現をCSSを使って表現した記事になります。
この記事を書いたことを聞かっけに`blend-mode` や `filter`などをしっかり触り勉強になりました。


これらの記事をご一読いただけると嬉しいです。

## アウトプットをはじめてよかったこと

アウトプットを定期的にはじめてから、変わったことは、色々な機会をいただけるようになりました。
社内からだけではなく、社外からも声が掛かるようになりました。

具体的には、`イベントの登壇`・`お仕事の依頼`・`転職のスカウト`などなど..
お小遣い程度ですが、お金もいただきました。

普段の活動がちゃんと誰かの目に届いて、僕に頼みたいと思ってもらえているだけでも、モチベーションになります。

来年以降は、イベント登壇の回数を少しずつ増やしていけるように頑張ります。
*（お仕事お待ちしています。　笑）*

## まとめ
こんな1年を送っていた私ですが、今年の締めくくりとして、1人でアドベントカレンダーの完走を目指して、25記事書いています。

CSSで作ったモンスターボールを25種類以上紹介する予定です。
ぜひこちらのカレンダーを購読して、記事にいいねお願いします。

https://qiita.com/advent-calendar/2022/degudegu2510

このカレンダーだけでなく、他のカレンダーにもちょくちょく参加しているので、見つけたらカレンダーの購読と記事のいいねを忘れずにお願いします。


---

最後まで読んでくださってありがとうございます！

普段はデザインやフロントエンドを中心にQiitaに記事を投稿しているので、ぜひQiitaのフォローとX(Twitter)のフォローをお願いします。

https://twitter.com/degudegu2510
JavaScriptのvar, let, constの違い

||let|var|const|
|:-:|:-:|:-:|:-:|
|再宣言|不可能|可能|不可能|
|再代入|可能|可能|不可能|
|スコープ|ブロックスコープ|関数スコープ|ブロックスコープ|
|繰り返し構文|可能|可能|不可能|

##### 参考サイト
https://techplay.jp/column/1619
【ポケモン】 ターミナルでポケモンを出そう!!

# 結論
日本語入力でターミナルにポケモンが出せます！！！(可愛い！！)

![ 2022-12-24 0.26.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487820/e6048be1-949f-5478-1883-2041feb0536c.png)



# はじめに
本家のpokemon-colorscriptsを日本語対応させたものになります。(一から全て作ったわけではないです)

動機はポケモンの英語名が日本語と違いすぎて使いにくかったからです。


- 本家のgit(英語版)

https://gitlab.com/phoneybadger/pokemon-colorscripts

- github(英語版+日本語入力対応)

https://github.com/sergicalsix/pokemon-script-jap

# 使い方
## 環境設定
```bash
$ git clone https://github.com/sergicalsix/pokemon-script-jap.git
$ cd cd pokemon-script-jap
$ sudo ./install.sh
```
以上で使えるようになります。（こけた場合は、ページ末尾のHelpをご覧ください）

## 実行方法
```bash
$ pokemon-colorscripts -n [好きなポケモンの名前(カタカナ)]
```

# 実行例
実行例をいくつか乗せます！可愛いのでぜひ使ってみてください！

![ 2022-12-24 0.14.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487820/48253a11-625b-c36a-ea3e-fec9f0fd4e8d.png)
![ 2022-12-24 0.16.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487820/dd10363c-fa4f-d5ee-c117-70173329dc24.png)
![ 2022-12-24 0.14.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487820/46838275-b987-190a-dfa6-a36e02b5273c.png)


ちなみに存在しないポケモン名(入力が間違っているor例外)を入力すると以下のようになります。

```bash
$ pokemon-colorscripts -n ほげ
Invalid pokemon ほげ
$ 
```


# 終わりに
日本語入力対応をどのようにして実装したかについては後日記事を出します！
プログラムはpythonで記述されていて、かつ短いのでご自身で改造してみるのも面白いと思います！

以下今後のTODOです。

- テストコード作る
- 全ポケモンに対応させる
- 本家にPR送る

ありがとうございました！

Zennもやっていますのでよかったらご覧ください

https://zenn.dev/sergicalsix



# Help
- `coreutils`を入れる
```bash
% sudo port selfupdate           
% sudo port install coreutils      # これが必要
```
EditorUtilityWidgetを使用したツール制作について

# はじめに
この記事は[Unreal Engine (UE) Advent Calendar 2022](https://qiita.com/advent-calendar/2022/ue
 "「Unreal Engine (UE) Advent Calendar 2022」")の25日目の記事になります。
お仕事でEditorUtilityWidgetを使用する事が増えてきたので、自分の復習もかねて記事に残しておこうと思います。
今までツール制作を行った事がなかったので、苦手意識みたいなものが少なからずありましたが、実際に触ってみると凄くユーザーライクで組み込みも非常に簡単でかつ短時間で終わるため、開発には非常に強力なツールだと思いました。

# 検証環境
Unreal Engine 5.1

# EditorUtilityWidgetについて
PIEを実行しなくてもエディター上で動作するUI要素を簡単に追加する事が出来ます。
UnrealMotionGraphics(UMG)をベースにしている事もあり、WidgetやBlueprintsを触った事がある人なら非プログラマでも簡単に拡張する事が出来ます。
詳しくは[公式リファレンス](https://docs.unrealengine.com/4.27/ja/InteractiveExperiences/UMG/UserGuide/EditorUtilityWidgets/)をご参照ください。

# 参考サイト
〇　こちらのロジカルビートさんのブログが初心者ライクで非常にわかりやすいです。
https://logicalbeat.jp/blog/5236/

〇 ぶっちゃけキンアジさんのブログを見るとだいたいの内容が理解できると思います。
https://kinnaji.com/tag/editorutilitywidget/

〇 少し凝った事を画像付きで解説されているのでオススメです。
https://anapurna.co.jp/ue4/641/

# EditorUtilityWidgetの生成
右クリックからメニューを開き、「エディターユーティリティ → エディターユーティリティウィジェット」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/980013/2a0f6311-56f2-f06a-5877-5554edeae42f.png)

Widgetと同様にButtonを配置してみてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/980013/605c336d-6b42-648f-dd57-75af22890cfb.png)


作成したEditorUtilityWidgetを右クリックし「エディターユーティリティウィジェットを実行」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/980013/56ea2664-b4df-9d07-da23-4db43315c37d.png)

新規でウィンドウが表示され設定したUMGが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/980013/a02049b1-9f69-b2cd-5948-bcf454ecaa47.png)

# コンテンツブラウザ上で選択しているStatticMeshの取得
EditorUtilityWidgetにTextを追加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/980013/87d85499-56b3-61a3-ffd3-f1b53a8c9f4a.png)
「Get Selected Assets」を使用する事でコンテンツブラウザ上で選択しているアセットを取得する事が出来ます。
ボタンが押されたタイミングで選択しているAssetを取得
配列で取得できるため複数選択にも対応しています。この辺りは各自良い感じにしてください。
今回はボタンを押したら選択しているStaticMeshを取得できるようにしておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/980013/5543f388-84ad-1a41-2be1-43db4e58e349.png)

後は取得したAssetを元に名前を表示させるなど、取得したアセットの情報をEditorUtilityWidgetに表示させてあげましょう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/980013/1ad4686e-33f3-4489-ec0e-01c975fdb6b0.png)
取得したStaticMeshを元にMaterilを変更したり、一部パラメータを書き換えたりとアセット編集を行う事が出来ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/980013/f4afa65c-f5ab-fb0a-9e47-3cc5799ebb76.png)

# EditorUtilityWidgetでパラメータを変更し、セーブ → チェックアウトを自動化
選択したStaticMeshを適当にMaterialを書き換えてみる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/980013/b583d791-b4b2-3d15-dda4-3d942dde8c60.png)

画像のようにチェックアウトからセーブを一連の流れで実装する事が出来ます。
※ ソースコントロールに接続しておく必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/980013/dae6d09d-d757-87e9-5f49-f68320694fa8.png)

# 今年のふりかえり
今年はツール年というぐらいに色々なツールを作ってきました。
EditorUtilityWidgetを使用する事も多く、今年はよりUnreal Engineを学ぶ事が出来たかなと思います。
ぜひ来年もよろしくお願いいたします。
Arduino スケッチを PC で動かすために

LovyanGFX for PC を使うと Arduino core for the ESP32 用のスケッチなどを PC で動かしてみることができますが、ソースコードを 完全に共通化はできません。

Arduino の API を使うところなどちょこまかと変更しなければなりませんが、その差異を吸収するためのライブラリを作り、

「LovyanGFX for PC で Arduino スケッチを動かすために」
https://qiita.com/nanbuwks/items/50e8c7f8848a6499b5b0

で紹介、その後

「LovyanGFX for PC 完全体を g++ on Ubuntu で」
https://qiita.com/nanbuwks/items/e316398aa12a90576cc7

で日本語フォントも g++ で使えるよう改良しました。

ところが @pokibon さんより

> windowsのVisual Studio上では、最初の10行のfont関連のinclude内で定義されているフォントデータが二重定義になっちゃいます。

と指摘がありました。

元々 LavyanGFX for PC は MS-Windows + Visual Studio Community + CMake + Clang の組み合わせで公開されていますが、僕は Linux +  g++ + Visual Studio Code で動かしていたのでその違いかな?

なので条件コンパイルを使って Clang でもエラーが出ずに使えるように変更しました。

```

#ifdef LGFX_USE_V1
#ifdef  __GNUC__
#include <lgfx/Fonts/IPA/lgfx_font_japan.h>
#include <lgfx/Fonts/efont/lgfx_efont_cn.h>
#include <lgfx/Fonts/efont/lgfx_efont_ja.h>
#include <lgfx/Fonts/efont/lgfx_efont_kr.h>
#include <lgfx/Fonts/efont/lgfx_efont_tw.h>
#include <lgfx/Fonts/IPA/lgfx_font_japan.c>
#include <lgfx/Fonts/efont/lgfx_efont_cn.c>
#include <lgfx/Fonts/efont/lgfx_efont_ja.c>
#include <lgfx/Fonts/efont/lgfx_efont_kr.c>
#include <lgfx/Fonts/efont/lgfx_efont_tw.c>
#endif
#endif


#define millis(num) SDL_GetTicks()
#define String(num) to_string(num)
#define delay(msec) SDL_Delay(msec)
#include <stdint.h>
#include <stdlib.h>
#include <string>
using namespace std;
class SerialDummy
{
  public:
    void begin(int speed){
    }
    void print(string contents){
            printf("%s",contents.c_str());
    }
    void print(int contents){
            printf("%d",contents);
    }
    void println(void){
            printf("\n");
    }
    void println(int contents){
            printf("%d\n",contents);
    }
    void println(string contents){
            printf("%s\n",contents.c_str());
    }
};
SerialDummy Serial;
#ifndef LGFX_USE_V1
#include <SDL2/SDL.h>
#define setup() int setup()
#define loop() int loop()
int setup();
int loop();
int main();
main(){
int dummy;
   setup();
   while(1){
     loop();
   }
}
#endif

```

PC の場合はこれをインクルードすると、

- PC 用のライブラリの読み込み
- delay() 関数を SDL関数に置き換え 
- millis() 関数を SDL関数に置き換え
- String(num) 関数を to_string(num) に置き換え
- g++ を使った場合のフォント参照エラーの抑制
- Serial.print などを使えるようにして標準出力に表示

するようにしています。

また、LovyanGFX を使わないスケッチでも main を作り setup() や loop() の面倒を見ることで、PC で動かすことができる(かもしれない)。
当然ながら PC には GPIO 入出力が無いので、digitalRead や digitalWrite などはできません。 

# GitHub

おもちゃのような内容で足りない機能がたくさんありますが、最初に完全を目指すのではなく必要に応じて足すつもりで。
随時拡張したソースは github に置くようにしましたので、使ってみたい方はこちらから。

「library for to run arduino sketch on pc」
https://github.com/nanbuwks/arduinolib_for_PC

不足機能は各位で書き足して補っていただくことになりますが、よろしければプルリクなどいただけましたら幸いです。


# 今後

> 当然ながら PC には GPIO 入出力が無いので、digitalRead や digitalWrite などはできません。 

と書きましたが、ゆくゆくはエミュレータ的な環境を作りたいなあ・・・
ReactHooksについてまとめる（Other Hooks useId）

# 概要
ReactHooksのOther Hooksについてのメモ記事です。基本的にReactの公式ドキュメントの咀嚼記事となっています。

今回はuseId編です。

## useId
useIdは、アクセシビリティ属性に渡す一意のIDを生成するためのReact Hookです。


> リスト内のキーを生成するために useId を呼び出さないでください。キーはあなたのデータから生成されるべきです。

### アクセシビリティ属性のためのユニークなIDを生成する
例えば、`aria-describeby`のような2つのタグが関連していることを示すための属性があります。通常のhtmlでは以下のように指定して使用します。

```html
<label>
  Password:
  <input
    type="password"
    aria-describedby="password-hint"
  />
</label>
<p id="password-hint">
  The password should contain at least 18 characters
</p>
```

しかし、これをjsxで記述するReactコンポーネントを作成する場合にはハードコードするのは適していません。この際にuseIdを使用してユニークなIDを生成することができ、ハードコードも回避することができます。


```jsx
import { useId } from 'react';

function PasswordField() {
  const passwordHintId = useId();
  return (
    <>
      <label>
        Password:
        <input
          type="password"
          aria-describedby={passwordHintId}
        />
      </label>
      <p id={passwordHintId}>
        The password should contain at least 18 characters
      </p>
    </>
  );
}
```

### 複数の関連する要素のIDを生成する

以下のように複数の関連要素にIDを扶養する必要がある場合には、useIdを呼び出し接頭辞として使用することもできます。

```jsx
import { useId } from 'react';

export default function Form() {
  const id = useId();
  return (
    <form>
      <label htmlFor={id + '-firstName'}>First Name:</label>
      <input id={id + '-firstName'} type="text" />
      <hr />
      <label htmlFor={id + '-lastName'}>Last Name:</label>
      <input id={id + '-lastName'} type="text" />
    </form>
  );
}
```


## 参考

https://beta.reactjs.org/apis/react/useId
Yt-dlpをPythonから実行し、時間指定した動画をダウンロードする

この記事は呉高専アドベントカレンダーの24日目の記事です。
https://adventar.org/calendars/7908
呉高専を卒業し、大学に3年次編入してから2年目の乗算記号と申します。
普段はUnityでゲームを作ったり、卒研でPythonいじったりしています。
初めて記事を書くため、読みづらい部分はご容赦ください。


# yt-dlpとは

yt-dlpとはyoutube、twichといった動画配信サービスから高画質・高音質な動画をダウンロードできるプログラムです。ちなみにあのGitHubから追放されかけた(実際された)ことで有名なYoutubeDLからの派生プロジェクトになります。使用目的としては機械学習のような大量の動画や音源が必要なときに大変重宝されます。基本的にはcliから使用しますが、pythonスクリプト上からも動作できます。


https://github.com/yt-dlp/yt-dlp



# yt-dlpで時間を指定した上でダウンロードする。
ある動画を時間指定してダウンロードする関数を定義して使用してみます。
ソースコードは以下のようになります。


```python
from yt_dlp import YoutubeDL


def ytdlp_bytime(movie_url: str, start_time: int, end_time: int):

    def set_download_ranges(info_dict, self):
        duration_opt = [{
            'start_time': start_time,
            'end_time': end_time
        }]
        return duration_opt

    ydl_opts = {
        'download_ranges': set_download_ranges
    }

    movieURL: str = movie_url

    with YoutubeDL(ydl_opts) as ydl:
        ydl.download(movieURL)


def main():
    movie_url: str = 'https://www.youtube.com/watch?v=6T8Jia_4tZc'
    start_time: int = 10
    end_time: int = 45

    ytdlp_bytime(movie_url, start_time, end_time)


if __name__ == "__main__":
    main()

```

- **解説**
```python
    def set_download_ranges(info_dict, self):
        duration_opt = [{
            'start_time': start_time,
            'end_time': end_time
        }]
        return duration_opt
```
上記の部分で辞書型の`duaration_opt`に開始時間と終了時間を渡し、それらを返し値に持つ`set_download_range`という関数を宣言します。

```python
    ydl_opts = {
        'download_ranges': set_download_ranges
    }

    movieURL: str = movie_url

    with YoutubeDL(ydl_opts) as ydl:
        ydl.download(movieURL)
```
また、ここでjson型の`ydl_opts`下の`download_ranges`に先程作成した`set_duration_opt`**関数自体**を渡します。ここで直接辞書型や変数を渡してはいけません。

このことはソースコードのYoutubeDLクラス内に記載されているコメントにかかれています。

https://github.com/yt-dlp/yt-dlp/blob/8791e78cccd68db8161f06dc8567280e0d99a5e1/yt_dlp/YoutubeDL.py#L442


# おわりに
この部分は私が研究を勧めている際に躓いた部分です。
わからないのは私だけかと思いきや、友人も躓いていたので記事にしました。
技術系の記事を初めて書いたため至らない点もあるかと思いますが、どなたかのお役に立てれば幸いです。

# 参考文献
https://github.com/yt-dlp

https://note.com/note_fumi/n/n72b755dac88a

https://www.youtube.com/watch?v=6T8Jia_4tZc
azureポータル操作まとめ


・Azureポータルのサブスクリプション管理画面にあるプロパティメニューからサービス管理者の確認や変更が可能。

・リソースプロバイダーの管理は、AZureポータルのサブスクリプションのリソースプロバイダーのメニューから行う。

・Azureポータルからリソースグループを作成するには、サービス一覧から全般のカテゴリ内にあるリソースグループをクリックし、表示される画面で作成をクリック。

・作成後別のリソースグループへ移動したい場合は、Azureポータルで移動したいリソースの洗濯後に移動メニュー内にある別のリソースグループに移動するをクリックし、移動先のリソースグループなどを選択すればリソースを移動できる。

・クイックスタートテンプレートを利用するには、ポータルメニューのリソースの作成からテンプーレとを検索すると表示される「テンプレートのデプロイ」メニューをクリックして作成をクリック、表示されたカスタムデプロイ画面で利用するテンプレートを選択できる。

・Azureポータルでえサービス一覧からIDカテゴリないのAzure Active Directryをクリックすると、最初に表示される概要メニューで現在のテナントを確認できる。

・Azureポータルで新しいテナントを作成するには、Azure Active Directoryの概要メニュー内でテナントの管理・作成の順にクリックし、画面のテナントの種類でAzure Active Directoryを選択。

・カスタムドメイン名の設定は、AzureポータルのAzure Active Directoryのカスタムドメイン名のメニューから行う。

・Azureポータルでのユーザー作成は、Azure Active Direvtoryのユーザーメニューで新しいユーザーをクリック。

・ユーザーに対してロールを割り当てるには、AzureポータルのAZure Active Directoryのロールと管んりしゃのメニューか、ユーザーの詳細設定画面の割り当てられたロールのメニューを使用して設定する。

・
タイムゾーンにご注意

# はじめに
Kubernetes Cronjob で前日分の集計処理を日次バッチで実行していたのですが、なぜか出力結果が前日分になっていました。原因はタイムゾーンが想定と異なっていたからでした。何が問題だったのか備忘録として残しておきます。

# 問題のコード
前日分の処理をするので、以下のように対象日を取得していました。

```python
from datetime import datetime, timedelta

target_date = (datetime.now() - timedelta(1)).strftime("%Y-%m-%d")
```

このバッチを日本時間の午前1時に実行していたとします。もし **datetime.now()** が日本時間での日にちを返していれば、**target_date** は前日の日にちを得ることができます。しかし UTC だとしたらどうでしょう？**datetime.now()** は前日の午後4時となりますので、そこから 1 日前は前々日になってしまいます。これが私のバッチで起きていた問題でした。

# 対処方法
サーバのタイムゾーンをいちいち把握してからプログラムを調整するのは面倒です。そこで以下のように修正しました。

```python
from datetime import datetime, timedelta, timezone

today_jst = datetime.now(timezone.utc) + timedelta(hours=9)
target_date = (today_jst - timedelta(1)).strftime("%Y-%m-%d")
```

# 結び
注意深く考えれば、ごくごく当たり前のことなので、私のチョンボに他なりません。とはいえ、日次バッチのプログラムを書いていると、うっかりやってしまいそうなミスなので、ドキュメントとして残すことにしました。
Ruby で Quarto を活用する

これは [Ruby アドベントカレンダー 2022](https://qiita.com/advent-calendar/2022/ruby) の23日目の記事です。

## Quarto とは何か？

[Quarto](https://quarto.org/) は、[Pandoc](https://pandoc.org/) 上に構築されたオープンソースの主に科学技術分野での利用を想定した出版システムです。

Quarto は下記の特徴を持つ、と https://quarto.org/ は主張しています。

- Python、R、Julia、および Observable を使用して動的なコンテンツを作る。
- ドキュメントをプレーンテキストのマークダウン、または Jupyter ノートブックでもって執筆する。
- 高品質の記事、レポート、プレゼンテーション、Web サイト、ブログ、書籍を HTML、PDF、MS Word、ePub などで公開する。
- 数式、引用、相互参照、図パネル、吹き出し、高度なレイアウトなどを含む、科学に関するマークダウンを用いて執筆する。

2 番目のリスト項目内の「マークダウン、または Jupyter ノートブックでもって執筆」って所はまあまあ重要です。
「ふーん、R マークダウンや Myst マークダウンと何か違うの？」って思われるかと思います。
ぶっちゃけ機能的にすげー変わるかというとめちゃくちゃは変わらん気もします。
が「R でも Python でも **同じ Quarto という出版システム** (と qmd というマークダウン拡張) によって科学的な記述が簡単に行える」ってあたりがうれしいんじゃないかなと。

3 と 4 番目のリスト項目もほぼほぼ「Rマークダウン / Myst マークダウン のオイシイ所」なんですが、ここも先のリスト項目同様の点がうれしいんじゃないかなと。

## で「Ruby と何か関係あんのか？」

「関係ある」というか「関係を持たせることができる」というか、「関係を持たせて Ruby も Quarto 恩恵の仲間入りさせたい」と思っています。

前節の `Python、R、Julia、および Observable を使用して動的なコンテンツを作る。` と述べた所は、
`Jupyter、Rmd および Observable を使用して動的なコンテンツを作る。` とした方が正確です。
Ruby は IRuby カーネルを用いて Jupyter から利用することが可能です。
そのため Ruby も Quarto の恩恵を受けることができます。

## で「どうやったらそれ試せるの？」

https://github.com/kozo2/quarto4rubydata の赤丸のバッジをクリックすると Ruby で Quarto を試していただけます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7591/07cbfd3d-b1de-2175-0154-8cd3d5743d4a.png)


Jupyter 環境が立ち上がるまで時間がかかるかもしれませんが気長にお待ちください。
(「立ち上がるまで遅い！」and「自分で Docker 使える」という方はご自身でローカルでDockerイメージのビルド+実行を行っていただくことも可能です。)

すると下記のような画面に到達するかと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7591/9e9ec290-6f4f-0fe4-2a18-f649181f3834.png)

あとは赤線の ipynb ファイルをダブルクリックしていただいて、そこに書かれている通りの操作を行っていただければ
下記のような html が ipynb から生成され、「Ruby で Quarto」を(最低限で)試していただけたことになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7591/1654eba6-0cba-2d33-939d-18ff8747558f.png)

## ipynb からこんな html が作れて何がうれしいの？

先の html だと「Code ブロックを畳む・開く」程度しか凝れてませんが、
Quarto を使うと他にも凝った html を generate することができます。

先の `try_irubykernel_with_quarto.ipynb` に続いて `redamber.ipynb` も Terminal 内で `quarto render redamber.ipynb --to html` してみてください。
すると添付画像のように
- 画面右側に目次が追加されている
- テーブルに css が適用されている


html が generate されていると思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7591/b0a4e135-90c9-6eb7-42e7-439fc4b2b285.png)

これは ipynb の最初の `raw` セルに下記の Quarto 用オプションを書いているからです。

```
---
title: "redamber"
format: 
  html:
    toc: true
    css: table4ruby.css
    code-fold: true
jupyter: ruby
---
```

こんな感じで Quarto を使うと
1. Jupyter での Ruby 試行
1. ↑ の成果を共有するための html 等での publishing (スタイリングとか目次付けたりをオプション追加だけで実現)

のワークフローがシステマチックに行えるようになります。

## もっといい例がほしいんだけど...

今の所、上記くらいしか例を作れていません。
が今後もっと魅力的なコンテンツを作ろうと思います。
もしこの投稿に興味を持たれたら [red-data-tools の gitter](https://gitter.im/red-data-tools/ja) にご参加ください。
では。