OmniAICreator/Qiita-1.07M huggingface dataset:
Next.JS の API Route でのファイルアップロード受信処理 

# Next.JS の API Route でのフォーム読み込み

Next.JS の API Route 機能におけるフォームの解析処理である bodyParser は multipart に対応していないようだ、、、
req.body に生のリクエストボディが入っているだけ、、、

# なので formidable を利用してリクエストボディを解析してみる

```bash
$ yarn add fomidable @types/fomidable
```

以下、TypeScript で

```api/sample.ts
import type { NextApiRequest, NextApiResponse } from 'next'
import formidable from 'formidable'

// Next.JS の bodyParser を無効化するのを忘れずに
export const config = {
  api : {
    bodyParser : false
  }
}

// 受信 API の処理
export const Sample = async ( req : NextApiRequest, res : NextApiResponse ) => {

  try {

    // POST 以外ならエラー
    if ( req.method !== 'POST' ) {
      throw new Error( `Invalid method [ ${ req.method } ]` )
    }

    // formidable を利用して multipart リクエストボディを解析する
    //     /tmp/sample にアップロードされる （前もってディレクトリは作成しておく)
    const form = new formidable.IncomingForm( { uploadDir : '/tmp/smple' } )

    // リクエストボディのパースが完了するのを待って、結果を　{ files, fields } で受け取る
    const { files, fields } = await new Promise<{ files : formidable.Files, fields : formidable.Fields }>(
      ( resolve, reject ) => {

        // リクエストボディのパースをする
        form.parse( req, ( error, fields, files ) => {

          // エラーなら reject する
          if ( error ) reject( error )

          // 得られたリクエストボディの内容を返して resolve する
          resolve( { files, fields } )
        } )

      }
    )

    // files には file 属性でアップロードされたファイルがフォームの name で指定したプロパティに格納される
    const file = files.<name> as formidable.File           // ファイルの情報が得られる
    const path = file.filepath                             // 格納先ファイルパスが得られる
    const name = file.originalFileame                      // 元のファイル名が得られる
    const mime = file.mimetype                             // ファイル名の形式が得られる

    // fields には、file 以外のフォームの name で指定したプロパティにパラメータと値が入る
    const value = fields.<name>                            // 値が得られる

  } catch ( error ) {

    // エラーの時は 500 で返す
    res.status( 500 ).json( { message : error.message } )
    return

  }

  // 正常終了
  res.status( 200 ).json( {} )
  return
}
```

なんてことないことなのだが、気が付かないと調べても Express 関係の記事が多くて
時間がかかってしまったので

ちょっと記録として

なお、格納したファイルは fs.rm() するのを忘れずに、、、
CSSで使える長さの単位

[ひとりCSS Advent Calendar 2022](https://qiita.com/advent-calendar/2022/css-becolomochi) 8日目です。

最近いろいろと増えたCSSで使える長さの単位をまとめてみました。

## 絶対値

- px - ピクセル
- pt - ポイント
- pc - パイカ
- in - インチ
- cm - 96px/2.54 = 1cm
- mm
- Q - 1cm/40 = 1Q(0.25mm)


## 相対値

### 文字

- em - 親要素のフォントサイズ
- ex - その要素のフォントの文字 x の高さ
- ch - その要素のフォントの文字 0 の幅
- rem - ルート要素のフォントサイズ
- lh - その要素の line-height プロパティと同じ

### ビューポート

- vw - ビューポート幅の1%
- vh - ビューポート高さの1%
- vmin - ビューポート幅と高さを比べて小さい方の1%
- vmax - ビューポート幅と高さを比べて大きい方の1%

以下の単位が追加になった。
例えば主にiOS Safariの挙動に対応できる。

- Large Viewport
    - アドレスバーやツールバーなどがすべて縮まっていたり非表示になり、画面がいちばん広いときのサイズ
    - lvw, lvh, lvmin, lvmax
- Small Viewport
    - アドレスバーやツールバーなどがすべて表示されて画面がいちばん狭いときのサイズ
    - svw, svh, svmin, svmax
- Dynamic Viewport
    - 動的に変わるユーザーエージェントに依存するUIを考慮してサイズが設定される
    - dvw, dvh, dvmin, dvmax

### まとめ

- 紙の単位もあるの知らなかった
- どの状態でも高さいっぱいにしたいときは `100dvh` と書けば良さそう

## 参考

- https://developer.mozilla.org/ja/docs/Learn/CSS/Building_blocks/Values_and_units#lengths%E9%95%B7%E3%81%95
- https://coliss.com/articles/build-websites/operation/css/large-small-dynamic-viewports.html
ターゲットがAndroid12でActivityのないアプリのServiceが起動できなくて試行錯誤した

# はじめに
アプリのtargetSdkを31に上げた場合に[サービスの起動条件](https://developer.android.com/about/versions/12/behavior-changes-12?hl=ja#foreground-service-launch-restrictions)がさらに厳しくなりました。
Serviceを起動する場合は[特殊なケース](https://developer.android.com/guide/components/foreground-services?hl=ja#background-start-restriction-exemptions)に該当しない場合は、たとえstartForegroundService()を実行したとしてもバックグラウンドからServiceを起動すると例外が発生するようになりました。

# やりたかったこと
- 他のアプリから呼び出されたあと、フォアグラウンドサービスのように処理を待機させること。
- Serviceの持つonStartCommand()のようにインスタンスが存在した状態で処理できるようにすること。

# できなかったこと
- 一瞬だけActivityを呼び出してServiceを実行
Android12からActivityがないとServiceが起動できませんでした。
そのため、一瞬だけAvtivityを呼び出そうと思いましたが、バックグラウンドからActivityを起動するためには'SYSTEM_ALERT_WINDOW'のパーミッションが必要なため断念しました。
- CoroutineWorkerからServiceを起動
試してみましたが、通知が出ている状態でもやはりダメなようでした。

# 実際に行ったこと
１. ServiceではなくCoroutineWorkerを使用してServiceの処理を移動
しかし、これでは一瞬で処理が終わってしまうので、Workerを待機させるように

```kotlin
class SampleWorker(context: Context, val param: WorkerParameters) : CoroutineWorker(context, param) {
    override suspend fun doWork(): Result {
        showNotification()
        //onCreateの処理を記述
        mainWork()//ここで一回目のonStartCommandの処理
        try {
            //意図的に終了されるまで待機させておく
            synchronized(lock) {
                while (!isPreparerFinish) {
                    lock.wait()
                }
            }
        } catch (e: InterruptedException) {
            Thread.currentThread().interrupt()
        }
        //onDestroyでの処理を記述
        return Result.success()
    }

    private fun mainWork() {
        //onStartCommandで行っていた処理を記述
    }

    companion object {
        private val lock = Object()
        private var isPreparerFinish:Boolean = false
            set(value) {
                if (value) {
                    synchronized(lock) {
                        lock.notify()
                    }
                }
                field = value
            }
    }
}
```

２.スレッドが待機中の場合はメインの処理へデータを渡して実行する
ServiceのonStartCommandのような動きを再現するために参照を保持してインスタンスへ値を渡すようにします。

```kotlin
//・・・
    override suspend fun doWork(): Result {
        refWorker = WeakReference(this)
        param.inputData.getString(KEY_COMMAND)?.let {
            val data = param.inputData.getString(KEY_DATA)
            mainWork(it, data)//データを渡して処理させる
        }
        //略...
        return Result.success()
    }
    
    //...
    companion object {
        //略...
        private var refWorker: WeakReference<SampleWorker>? = null
        fun sendCommand(context: Context, command: String, data: String) {
            refWorker?.get()?.apply {
                // instanceが存在する場合は直接処理させる
                mainWork(command, data)
            } ?: startWorker(context, command, data)//instanceが存在しない場合はworkerを立ち上げる
        }
    }

```

# 注意点
- Workerをきちんとどこかで終了させるようにしましょう。ずっと残り続けてしまいます。
- 現状CoroutineWorkerはバックグラウンドから10分以上の長期的なタスクとして実行できますが、今後できなくなってしまう可能性があります。
WindowsのPythonとWSL2／UbuntuのPythonの速度差に驚いた 

# はじめに
今回は、ごく些細な話です。
ちょっと意外だったので書いておきます。
# なんかUbuntuの方が速い気がした
僕のPython環境は。
・Windows11にAnaconda/Python3.8
・Windows11のWSL2にインストールしたUbuntu20.04のPython3.8
の２つあります。
どちらもVsCodeから参照して開発・実行できるようにしています。
僕の場合、Pythonはほぼ「自分用ツール作成」に使ってます。
なので、Windows用とUbuntu用をいったりきたりすることが多いですが、なんとなく、同じような処理やテストコードを書いているのに、Ubuntuのpythonの方がなんか速い気がしていました。
# 簡単なコードでベンチマークしてみた
感覚だけではモヤっとするので、以下のような簡単なコードで試してみることにしました。
```
import time


def hoge(x, n):
    for i in range(n):
        x = 1 / (x * (x - 1)) + 4.6
        return x


s = time.perf_counter()
print(hoge(0.5, 10000000000000))
print(hoge(0.5, 10000000000000))
print(hoge(0.5, 10000000000000))
print(hoge(0.5, 10000000000000))
print(hoge(0.5, 10000000000000))
print(hoge(0.5, 10000000000000))
e = time.perf_counter()
print(str((e - s) * 1000000) + "マイクロ秒")
```
処理は以下の記事を参考にしました。
http://verifiedby.me/adiary/0156
これを両方の環境で20回ずつ実行して、平均的な数値で比較してみようというわけです。
# 比較してみた結果
実際、実行都度、同じ環境でもかなり実行速度にバラつきがでます。
特に、最初の1回が極端に遅くなります。
なので、その数値をはぶいて計測してみました。
結果はこうでした。
・WindowsのPython：平均780マイクロ秒
・UbuntuのPython：平均約70マイクロ秒
あれあれ。
10倍以上違います。
四則演算だけのベンチマークですし、たまたまかもしれませんが、なかなかの差です。
同じWindows11上で動くWSL2上のUbuntuで動くPythonが、本体であるWindows11で動くPythonよりも速いという理屈がよくわかりませんが、事実は事実。
機械計算系とか処理時間がかかるのは、今後WSL2/UbuntuのPythonでやろうと思います。
ではでは。
2年間でプロダクトのコードを半減させた話

[Ateam Finergy Inc.× Ateam CommerceTech Inc.× Ateam Wellness Inc. Advent Calendar 2022
](https://qiita.com/advent-calendar/2022/finergy-commerce-tech-wellness)の10日目は、株式会社エイチームウェルネスの@chardenが担当します。

## 概要

私の担当するサービスは2010年にガラケー向けサイトとしてリリースされて現在はスマートフォンアプリとして運営しています。

そのプロダクトの一部の機能群は利用率の低い機能や利用されていないコードなどが存在し、メンテナンス性が良くない状態となっていました。

2年前の時点で今後の事業の変化に迅速に開発していくためには、コードの整理が必要であると判断しました。

我々は、不要なコードの削除に取り組んできて、コードを半減させることができました。

今回は、どのように不要コードの削除に取り組んできたかをお話します。

##  取り組んだこと 

- システムの全体像を明確にする
- 数値的な目標と進捗を追いやすくする
- 利用率の低い機能を廃止する
- 保守Dayを設けて継続的に改善する時間を作る
- ペアプログラミングやモブプログラミングを活用する

## システムの全体像を明確にする 

まずは、システムの全体像を明確にするため、どんな機能が存在し、どんなファイルが存在しているかを確認しました。

- 機能ごとにファイル一覧を出力して更新頻度の低いファイルや把握できていないファイルにチェック
- 機能ごとのテーブルの最新更新日を確認して明らかに更新がかかっていないテーブルや頻度の低いテーブルから使っていない機能を洗い出し

これを行うことで取り組みやすい箇所を発見したり、全体のうちの進捗がどれくらいになっているかが見える化されました。

## 数値的な目標と進捗を追いやすくする

不要コードの削除というのは利用者への価値提供をできる業務ではありません。
また、なくなったからといってすぐに開発体験が変わるものでもありません。

そのため、我々はシンプルにファイル数とコード数が減っていくことをKPIとして実施しました。

計測については [AlDanial/cloc](https://github.com/AlDanial/cloc) というツールを利用しています。

週次でレポーティングすることにより、今週の取り組みの可視化やモチベーションの維持していました。

## 利用率の低い機能を廃止する

過去の施策で導入したが効果が高くなかった機能やだんだんと時流に沿わなくなって衰退してしまった機能が残っていました。

機能moduleごとにPVとMAUを出力して下位の機能については事業全体で機能の継続判断を行いました。

結果的にいくつかの機能は削除によるユーザー影響よりもメンテナンスや保守コストのほうが高いという判断の元削除を実施しました。

エンジニア以外の職種を巻き込むことで取り組みへの理解も得られやすく、大きな改善もやりやすくなります。

## 保守Dayを設けて継続的に改善する時間を作る

今回の取り組みのような事業施策と直接関わりのないものを進めていくには、ある程度の時間確保が必要です。

幸い我々のチームでは週の20％を保守に当てるという運用をしているので、その時間にこの取組みを行うようにしました。

全員で同じ時間に同じ取り組みをすることで下にもあげるペアプロやモブプロも実施しやすいです。

また毎週実施することで週ごとの変化にも気づきやすくなります。


## ペアプログラミングやモブプログラミングを活用する

メンバーの事業の関わっていた時間もバラバラだったため、事業背景やシステムへの理解度も異なっている状況でした。

単純な削除の作業にならないように、削除するコードに対しての議論や影響範囲の確認などもペアプロやモブプロの時間を通して共有するようにしました。

判断に迷う部分も複数人ですすめることができ、迅速に削除を進めることにつながりました。

## コード削減の結果

上記の取り組みを通して、ファイル数で44％、コード行数で58％の削減に成功しました。

## まとめ

我々のチームでこの取り組みを経て、プロダクトのコードを半減させることに成功しました。

減少させた数字については、プロダクトの状況により異なりますが、レガシーなシステムへの対応と初期段階として不要コードの削除を進めていくことはリプレイスの可能性なども含めて有効なアプローチとなります。

レガシーなシステムと戦っている方の参考になれば幸いです。
【備忘録】分布についての微分

$\theta$が分布$q(\theta)$に従うとする．ここで，$q$は確率分布なども考えられる．

このとき，分布$q$についての微分は，以下のようになる．

```math
\frac{\delta}{\delta{q}} \mathbb E_{\theta\sim q}[f(\theta)]=f(\theta)
```

単に$q$についての期待値を外すだけである．

これは，次のような例から直感的な理解ができる．

１変数のとき．．．
$ax$を$x$について微分すると，$x$が消える形になる．
```math
\frac{d}{dx}(ax)=a
```

ベクトルのとき．．．
同様に$\theta$が消える形になる．

```math
\nabla_\theta~(v^\mathsf{T}\theta)=v
```

分布のとき．．．
積分の形に書き直すと，同様に$q$が消える形になる．
```math
\frac{\delta}{\delta{q}}\mathbb E_{\theta\sim q}~[f(\theta)]=\frac{\delta}{\delta{q}}\int f(\theta)q(\theta)d\theta=f(\theta)
```

※これらの例は，$ax$，$v^\mathsf{T}\theta$，$f(\theta)q(\theta)$のようにすべて積になっていることに注意．
【CSS】文字列の真ん中に横線を描く方法

# はじめに
HTML&CSSで、下みたいなUIになるようにしてほしいと言われました。
flex使えないし、さあ困りました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/605286/293b7cdc-a02a-dab6-8f8d-ff64cdffc79c.png)

# 完成したコード
<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="ZERwxaX" data-user="min9000" 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/min9000/pen/ZERwxaX">
  横線</a> by mimori kyoma (<a href="https://codepen.io/min9000">@min9000</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

# 方法
### 前提
前提となるhtmlとCSSは下の通りです。
```html
<div>
  <span>通知は以上です</span>
</div>
```
```css
div {
  /* 見やすくするための箱（本題とは関係ない) */
  width: 300px;
  background: #CAE5CD;
  height: 50px;
  padding: 20px;

  /* 中央寄せ */
  text-align: center;
}

span {
  font-size: 16px;
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/605286/0d261442-35c8-df3e-515e-76013b02265a.png)

### 横線を表示
CSSの当てかたとして、```inline-block```要素で高さ1pxで幅がいっぱいの長方形を２つ作って、「通知は以上です」の両側に配置するイメージで作りました。

ということで、```before```と```after```の擬似要素を使って、左右に長方形を配置します。

ところで、横線の長さは、親要素の幅に追従してほしいですね。
ですので ```width```は、「通知は以上です」の文字列の幅とその左右の余白を引いて２分割しています。

線の長さが決まっているなら、```width```には固定値を入れてください。

```css
/* ... */

/* 長方形を描く */
div::before, div::after {
  content: '';
  background-color: #000;
  height: 1px; 
  width: calc((100% - 132px)/2);
  display: inline-block;
}

span {
  padding: 0 10px; /* 「通知は以上です」の両側の余白 */
}
```
横線が生まれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/605286/239a5441-8261-3870-045c-a7120cac9e84.png)

### 縦の真ん中に配置
真ん中に配置するための設定を追記します。
```css
/* ... */
div span, div::before, div::after {
  /* ... */
  vertical-align: middle;
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/605286/4c0c4efe-9a66-04c7-fc05-9a75b3cbe1e4.png)
大変なことになってしまいました。

### 配置を整える
上みたいな画像になってしまうのは、inline要素を横に並べた際に、謎の余白が要素の間にできるせいです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/605286/2170a869-604c-f430-4bcf-ab547a0859b8.png)

解決法として、並べたいinline要素の親に```font-size: 0;```を指定すると、その余白が消えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/605286/b0b96e7c-5ce6-c571-12ec-48db37011e11.png)

```css
div {
  /* 親要素（今回はdivタグ）に指定 */
  font-size: 0;
}
```
### できあがり
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/605286/e77f9772-bea8-05f5-740a-3c55df391d6f.png)



# まとめ
検索すると、境界線の書き方とかはよく引っかかるのですが、「今回とはやりたいことが違う！そうじゃないんだ〜！」という気持ちになりました。
無事に完成してよかったです。

ちなみに、無事ではありますが、計算でゴリ押したので、各種端末での確認は必須です。
flexを使えるともう少し簡単みたいなので、今度試したいです。
十の位と一の位の計算

# 問題
二桁以上の整数を入力すると、十の位と一の位の数字の足し算、
十の位と一の位の数字の掛け算をそれぞれ行い、
最後に2つの結果を足し合わせて出力するプログラムを
Rubyで作成してください。

##### sample.rb
```
> 二桁の整数を入力してください
> 15

# 1 + 5と 1 * 5をそれぞれ計算

> 足し算結果と掛け算結果の合計値は11です
```
と出力されるようにプログラミングする。

# 解答
```
def addition(a, b)
  a + b
end

def multiplication(a,b)
  a * b
end

def slice_num(num)
  tens_place = (num / 10 ) % 10
  one_place = num % 10
  return tens_place, one_place
end

puts "二桁の整数を入力してください"
input = gets.to_i

X, Y = slice_num(input)
add_result = addition(X, Y)
multiple_result = multiplication(X, Y)

puts "足し算結果と掛け算結果の合計値は#{add_result + multiple_result}です"
```

# 解説
ある整数について任意の桁の数字を取り出す手順
①取り出したい数字の桁数を割る
② ①の結果をさらに10で割った余りが任意の桁の数字

例：「25」の場合
25/10 = 2.5の小数点以下の「5」が一の位となる。
その2.5から 2.5/10 = 0.25の小数点以下「2」が十の位となる。

変数を定義する前に、カンマで区切ることによって、
同時に複数の変数を定義することができる。

ちなみに割り算で商を求める時は「/」余りは「%」で計算する。
【JavaScript】DOMツリーからHTMLの要素を取得する方法


# はじめに

本記事では、JavaScriptでDOMツリーからHTMLの要素を取得する方法についてまとめていきたいと思います。
JavaScriptの初心者向けな内容あとなります。興味のある方はぜひ見て頂けると嬉しいです。

# DOM、DOMツリーとは

DOMツリーからHTMLの要素を取得する方法を書いていく前に、簡単にDOMとDOMツリーについて触れておきます。

DOM（Document Object Model）とは、HTMLを解析してデータを作成する仕組みのことです。
HTMLやCSSがユーザーに閲覧されるまでの流れはご存じでしょうか。
HTMLファイルは単なる文字情報なので、そのまま表示してもユーザーにとって見にくいです。
その為、HTMLを解析してCSSやJavaScriptによる装飾を行った後に画面に映しています。
これを行っているのは、Googleやsafariなどの「ブラウザ」です。
HTMLは階層構造になっていて、この階層構造であるデータのことをDOMツリーやドキュメントツリーと呼びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985441/3d0ae100-5b6d-8e73-2435-f9b428c106af.png)
このDOMツリーを操作してJavaScriptを動かしていきます。
HTMLの要素名やid、classといった属性の情報をもとにDOMツリーから取得し、CSSの変更、要素を増やしたり、削除したりできます。

# HTMLの要素を取得しアラート表示する方法

DOMツリーから要素を取得する場合は大きく3つの方法があります。
- セレクタ名から取得
- id名から取得する
- class名から取得する

# document.getElementById("id名")

document.getElementById("id名")は、DOMツリーから特定の要素を取得する際に使用するメソッドの1つ。引数に設定したidを持つ要素を取得します。

```HTML:HTML
<p id="only">ひとつ</p> 
```

```JavaScript:Javascript
document.getElementById("only") //オブジェクトを取得
let ninja = document.getElementById("only").innerHTML; //アラート表示させるため、変数に代入
alert(ninja); //ポップアップに「ひとつ」が表示される
```

# document.getElementsByClassName("class名")

document.getElementsByClassName("class名")は、classを指定して取得する際に使います。
細かいですが、注意点としてgetElementsと複数形での記述となるのでお気を付けください。
idはHTMLの1つのページで1つだけしか存在できないユニークなものです。なのでdocument.getElementById("id名")は単数形の表示となります。このように覚えておけば、間違えることはないと思います。
こちらも以下のように記述し要素を取得します。

```HTML:HTML
<p class="multi">ふたつ</p> 
```

```JavaScript:Javascript
document.getElementsByClassName("multi"); //オブジェクトを取得
let ninja = getElementsByClassName("multi").innerHTML; //アラート表示させるため、変数に代入
alert(ninja); //ポップアップに「ふたつ」が表示される
```

# document.querySelectorAll("セレクタ名")

document.querySelectorAll("セレクタ名")は、セレクタで取得する際に使います。
セレクタ名とは、CSSでスタイルを適用させるために指定をしている要素です。
HTML上で、引数に指定したセレクタにマッチするものをすべて取得します。
セレクタ名で頻繁に使用するのは、class名、id名、HTMLタグです。
書き方はCSSでセレクタを指定する際と同じで、以下の通りです。

```HTML:HTML
<p id="only">ひとつ</p> 
<p class="multi">ふたつ</p>
<h1 class="multi">みっつ</h1>
```

```JavaScript:Javascript
//class名がmultiの要素を指定する場合
document.querySelectorAll(".multi")

//id名がonlyの要素を指定する場合
document.querySelectorAll("#only")

//h1タグの要素を指定する場合
document.querySelectorAll("h1")
```
こちらもアラートに表示させる場合は、.innerHTMLを追記した上で変数に代入しalert()を使用しましょう。
また、querySelectorというメソッドも存在しており、この場合セレクタ目を指定した要素のうち一番最初に見つかった要素だけを取得します。

# さいごに

今回の記事は以上となります。
コチラの忍者コードでは、JavaScriptの無料問題がたくさん用意されているので是非活用しましょう。

https://ninjacode.work/

最後まで読んでいただきありがとうございました。
ERC-4907：NFT レンタルの紹介

ERC721 NFT がよく知られていますが、2022/06/28、NFT レンタルの規格として、ERC4907 が容認され、EIP が final ステータスになりました。

現時点（2022/12）では、OpenZeppelin にはまだ実装されていない模様です。

## 規格のインタフェース

https://eips.ethereum.org/EIPS/eip-4907

> 本規格は、EIP-721を拡張したものである。アドレスに付与できる追加的な役割（ユーザー）と、その役割が自動的に取り消される（期限切れになる）時間を提案している。ユーザーの役割は、NFTの「使用」許可を意味し、譲渡やユーザー設定の能力はない。

ERC721 には、`オーナー` というロールしかありません。ERC4907 は、ERC721 を拡張して、`ユーザー` というロールを新たに設けた上に、そのロールの有効期限も設けています。


```solidity
interface IERC4907 {

    // Logged when the user of an NFT is changed or expires is changed
    /// @notice Emitted when the `user` of an NFT or the `expires` of the `user` is changed
    /// The zero address for user indicates that there is no user address
    event UpdateUser(uint256 indexed tokenId, address indexed user, uint64 expires);

    /// @notice set the user and expires of an NFT
    /// @dev The zero address indicates there is no user
    /// Throws if `tokenId` is not valid NFT
    /// @param user  The new user of the NFT
    /// @param expires  UNIX timestamp, The new user could use the NFT before expires
    function setUser(uint256 tokenId, address user, uint64 expires) external;

    /// @notice Get the user address of an NFT
    /// @dev The zero address indicates that there is no user or the user is expired
    /// @param tokenId The NFT to get the user address for
    /// @return The user address for this NFT
    function userOf(uint256 tokenId) external view returns(address);

    /// @notice Get the user expires of an NFT
    /// @dev The zero value indicates that there is no user
    /// @param tokenId The NFT to get the user expires for
    /// @return The user expires for this NFT
    function userExpires(uint256 tokenId) external view returns(uint256);
}
```

## ユースケース
ユーザーというロールを新しく設けることによって、今まで `所有権` しかなかった NFT に `利用権` を導入しました。これによって、NFT をもっと実用的に活用されるように見えます。
NFT 発行側のポリシー次第になりますが、たとえば会員制の NFT オーナーしか入れないバーなどの場合、一時的に友達に貸してあげて入って体験してあげるとかはできますね。

また、NFT をレンタルして利益をもらうようなサービスもあります。レンタル方法の１つとして、ERC4907 をサポートされています

https://myforex.com/ja/news/myf22101202.html

https://twitter.com/ishicorodayo/status/1544426507879141377

## まとめ
この２年間 NFT がどんどん注目されてきたんですが、実用についてはまだまだ模索中な状況になっています。レンタルの実装規格ができたおかげで、今後レンタルに関するサービスを期待できますね。
paizaラーニング レベルアップ問題集 paizaの森練習問題コンテスト過去問題7 JavaScript 三冠王

三冠王 (paizaランク B 相当)

https://paiza.jp/works/mondai/forest_contest_007/forest_contest_007__triple_crown

# 解答例
三冠王が見つかったらbreakして大丈夫だが、二冠王が見つかった時にbreakすると間違う。
各指標において一位が複数人いる場合もあるので、三冠王がまだいる可能性がある。

```javascript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");

//n 人の打者の打率、打点、本塁打がそれぞれ b_i, r_i, h_i で与えられる
const [n] = lines[0].split(" ").map(Number);

//首位打者 Batting title 打点王 RBI title 本塁打王 Home Run title　の各最高成績bt,rt,ht
let [bt, rt, ht] = [0, 0, 0];

//各タイトルの最高成績を求める
for (let i = 1; i <= n; i++) {
  const [b, r, h] = lines[i].split(" ").map(Number);
  //最大値の求め方３通り
  bt = Math.max(bt , b);//Math.maxで
  rt = r > rt ? r : rt;//三項演算子で
  if (h > ht) { //普通にifで
    ht = h;
  }
}

//三冠王、二冠王を探す
let triple = false;//三冠王がいるか
let double = false;//二冠王がいるか

for (let i = 1; i <= n; i++) {
  const [b, r, h] = lines[i].split(" ").map(Number);
  if (b === bt && r === rt && h === ht) {
    triple = true;//三冠王いた
    break;//三冠王がいたら探索終わり、なくてもいいが、あると無駄な処理をしないので速い
  } else if (
    (b === bt && r === rt) ||
    (b === bt && h === ht) ||
    (r === rt && h === ht) ){
    double = true;//二冠王いた
    //ただし、各指標において一位が複数人いる場合もあります。
    //三冠王がいるかもしれないので、breakしない
  }
}

if (triple) {
  console.log("Triple");
} else if (double) {
  console.log("Double");
} else {
  console.log("Nobody");
}
```
Azure DevOps で Git の プルリクエスト トリガーで pipelines を実行する


## 概要
Azure DevOps で Git の プルリクエスト トリガーで pipelines を実行する方法を記載します。
GitHub Actions等を利用している場合は、下記のように定義できますが、Azure DevOps Git Repo だとポリシーを設定する必要があります。

```yaml
on: 
 pull_request:
   branches:
     - feature/**
```

## 手順

- 該当するブランチの 「Branch policies」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217019/b797217d-59ac-92c7-f1a8-b61d80486e4c.png)

- ポリシーの中から 「Build Validation」から＋で追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217019/a8582738-c9a2-d8b6-c701-73771208e0a3.png)

- トリガー時に 実行したいpipelineを選択し保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217019/3d187084-f3a6-99bb-7c58-346238605cd6.png)


設定後の状態
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217019/301c3fb8-f06e-2474-4e4e-cf3332eb945c.png)

- ポリシーを設定したブランチにプルリクエストを出すと pipeline が実行されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217019/de3ee1c6-975b-44aa-ad99-950cadc31f7a.png)

## 用途
プルリクエストをレビューする前に、テストの実行やコードの静的解析ができるため 問題の発見がより早くなりレビューコストも削減できます。

## 参考
https://learn.microsoft.com/ja-jp/azure/devops/pipelines/repos/azure-repos-git?view=azure-devops&tabs=yaml#pr-triggers
論文紹介~Interpreting Multivariate Shapley Interactions in DNNs~

こんにちは！
大学院でコンピュータビジョンに関する機械学習の研究をしている住安です。

今回は、ゲーム理論の多変量の相互作用値を提案した論文をスライドにまとめてみました！
詳細などは省いていたり、誤りがあるかもしれません。気になる方は、ぜひ元の論文をお読みください！

論文タイトル：Interpreting Multivariate Shapley Interactions in DNNs
著者：Hao Zhang, Yichen Xie, Longjie Zheng, Die Zhang, Quanshi Zhang

<iframe src="https://docs.google.com/presentation/d/e/2PACX-1vRyB4wPh-OWdti1u2qCzsZKmzrW1ddkl33_hX88vAg4AaTM6m7dyavA97U9EXk7rgn23sL7WYxBmENQ/embed?start=false&loop=false&delayms=3000" frameborder="0" width="960" height="569" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true"></iframe>

## 論文URL
https://arxiv.org/pdf/2010.05045.pdf
【脳科学から考える】アウトプットの意味と正しいやり方

## この記事を読んで欲しい人
```
・記事に一回アウトプットしただけで、技術を習得したと満足している人
・今までアウトプットをなんとなくしてきた人
・一生懸命勉強してもなかなか結果につながらない人
・これからもたくさん記事を書くけど、どうせ書くなら有意義なアウトプットにしたい人
```
## この記事を読む前に
私は医者ではありません。プログラミング初学者です。

ある精神科医が書いた本を読んでいると、```脳の仕組みを理解したアウトプットの方法```がプログラミング学習にも応用できそうだと感じました。特に以下のフレーズは刺さりました。

```
脳の仕組みを無視して、一生懸命勉強しても効果は出ない
```
ちなみに私が読んだ本は「行動最適化大全」という本です。アウトプットに関してはさらに詳しく、同じ著者が「アウトプット大全」という本を出しているみたいです。興味を持ったら読んでみてはいかがでしょうか？？

###### 「行動最適化大全」
https://www.amazon.co.jp/%E4%BB%8A%E6%97%A5%E3%81%8C%E3%82%82%E3%81%A3%E3%81%A8%E6%A5%BD%E3%81%97%E3%81%8F%E3%81%AA%E3%82%8B%E8%A1%8C%E5%8B%95%E6%9C%80%E9%81%A9%E5%8C%96%E5%A4%A7%E5%85%A8-%E3%83%99%E3%82%B9%E3%83%88%E3%82%BF%E3%82%A4%E3%83%A0%E3%81%AB%E3%83%99%E3%82%B9%E3%83%88%E3%83%AB%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%81%A7%E5%B8%B8%E3%81%AB%E3%80%8C%E6%9C%80%E9%AB%98%E3%81%AE1%E6%97%A5%E3%80%8D%E3%82%92%E4%BD%9C%E3%82%8A%E5%87%BA%E3%81%99-%E6%A8%BA%E6%B2%A2-%E7%B4%AB%E8%8B%91/dp/4046047968

###### アウトプット大全
https://www.amazon.co.jp/%E5%AD%A6%E3%81%B3%E3%82%92%E7%B5%90%E6%9E%9C%E3%81%AB%E5%A4%89%E3%81%88%E3%82%8B%E3%82%A2%E3%82%A6%E3%83%88%E3%83%97%E3%83%83%E3%83%88%E5%A4%A7%E5%85%A8-Sanctuary-books-%E6%A8%BA%E6%B2%A2%E7%B4%AB%E8%8B%91/dp/4801400558/ref=sr_1_1?crid=22XCDSLR689EQ&keywords=%E3%82%A2%E3%82%A6%E3%83%88%E3%83%97%E3%83%83%E3%83%88%E5%A4%A7%E5%85%A8&qid=1670402698&s=books&sprefix=%E3%82%A2%E3%82%A6%E3%83%88%E3%83%97%E3%83%83%E3%83%88%E5%A4%A7%E5%85%A8%2Cstripbooks%2C197&sr=1-1

## インプットとアウトプットの違い
まず大前提として、インプットとは、アウトプットとは何か。
```
インプット・・・読む・聞く・見る
アウトプット・・・話す・書く・行動する
```
もちろんブログや記事を書くことも、アウトプットと言えるでしょう。
## アウトプットの頻度
一生懸命勉強しているのに、頭が良くならないという人は、大体がアウトプット不足だそう。
昔は僕もインプットばっかりして、全然成績が上がりませんでした。。。。
ではどれくらいの頻度でアウトプットをすればいいのか。

### インプットとアウトプットの黄金比は3:7

アメリカのコロンビア大学の心理学者アーサーゲイツ博士の研究によると、100人以上の子供たちを複数のグループに分け、同じ時間内に名鑑に書かれた人々のプロフィールを記憶させるという実験を行いました。この時グループごとに、インプットとアウトプットに割く時間の割合をそれぞれ別の割合に設定しました。結果は```インプット30%、アウトプット70%```のグループが一番高得点をとったそうです。

###### ここで言いたいのは、「同じ時間勉強したとしても、インプットとアウトプットにかける時間次第で得られる効果が全く違う」ということです。

###### 参考記事
https://diamond.jp/articles/-/83953?page=2

## アウトプットしなければ情報は消える
ここで脳の仕組みについてです。以下の海馬と側頭葉という用語をざっくりと理解してほしいです。
#### 海馬と側頭葉
```
海馬・・・インプットされた情報が保存される。保存期間は2~3週間で、必要のない情報だと判断した場合は消える。（滅びのバーストストリーム）
側頭葉・・・海馬が大事だと思った情報が保存されるところ。長期にわたって保存される。
```
コンピューターに例えると、```海馬は主記憶装置```、```側頭葉は補助記憶装置```です。

インプットされた情報は脳の海馬という部位に保存されます。
海馬はインプットされた情報を２週間ほど保存しますが、必要ないと判断した情報は捨てます。

逆に海馬が大事だと思った情報は側頭葉という箇所に移します。
側頭葉は情報を長期にわたって保存してくれます。

じゃあ海馬は何をもって大事な情報と判断しているねん、っていう話です。
###### 答えは、２週間で2~３回ほど使われた情報を海馬は大事な情報と判断するそうです。
なのでインプットした情報は２週間に３回はアウトプットする必要があります。一回記事に書いただけでは足りません。（僕はインプットした情報をQitaなどに書いた後、口に出して壁に向かって説明しています。。。）

## まとめ
新しく知ったことは、1回記事に書くだけでは足りない。記事に書く以外にも2週間以内に２~３回、話す・書く・伝えるなどして定着させる。

## 最後に
今回は名鑑に書かれた人々のプロフィールを記憶するという実験例でした。
しかしプログラミングの学習にどこまで記憶が大事かというのは変わってくると思います。
それによってアウトプットに割くべき時間とアウトプットに割くべき時間が変わると思います。
それを今後の学習でも追求していきます。
論文紹介~Transformer Interpretability Beyond Attention Visualization~

こんにちは！
大学院でコンピュータビジョンに関する機械学習の研究をしている住安です。

今回は、ViTに対して有用な可視化手法をスライドにまとめてみました！
詳細などは省いていたり、誤りがあるかもしれません。気になる方は、ぜひ元の論文をお読みください！

論文タイトル：Transformer Interpretability Beyond Attention Visualization
著者：Hila Chefer, Shir Gur, Lior Wolf

<iframe src="https://docs.google.com/presentation/d/e/2PACX-1vTBHRJHAoMBzgJP73kOpUp8FYlGcAvUayjfhcQNLR3twEbNlmIq4Vd_ATf2e1kadtAyd2MbifW7YQZ8/embed?start=false&loop=false&delayms=3000" frameborder="0" width="960" height="569" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true"></iframe>

## 論文URL
https://arxiv.org/pdf/2012.09838.pdf
論文紹介~Masked Autoencoders Are Scalable Vision Learners~

こんにちは！
大学院でコンピュータビジョンに関する機械学習の研究をしている住安です。

今回は、今話題となっているMasked autoencoderをスライドにまとめてみました！
詳細などは省いていたり、誤りがあるかもしれません。気になる方は、ぜひ元の論文をお読みください！

論文タイトル：Masked Autoencoders Are Scalable Vision Learners
著者：Kaiming He, Xinlei Chen, Saining Xie, Yanghao Li, Piotr Dollár, Ross Girshick

<iframe src="https://docs.google.com/presentation/d/e/2PACX-1vQX0DGDeupJYULHEnZYi3ysvY2GjyttJJwu0yPyGgR7HXc6KgvH_b3pGGEOuXVh2liRsasPjIWFR8PF/embed?start=false&loop=false&delayms=3000" frameborder="0" width="960" height="569" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true"></iframe>

## 論文URL
https://arxiv.org/pdf/2111.06377.pdf/
Rails – ActiveStorage系のルーティングを無効にする

# 問題

rails new でプロジェクトを作成したデフォルト状態から利用しないルーティングが有効になっている

```
$ rails routes

                      rails_service_blob GET    /rails/active_storage/blobs/redirect/:signed_id/*filename(.:format)                               active_storage/blobs/redirect#show
                rails_service_blob_proxy GET    /rails/active_storage/blobs/proxy/:signed_id/*filename(.:format)                                  active_storage/blobs/proxy#show
                                         GET    /rails/active_storage/blobs/:signed_id/*filename(.:format)                                        active_storage/blobs/redirect#show
               rails_blob_representation GET    /rails/active_storage/representations/redirect/:signed_blob_id/:variation_key/*filename(.:format) active_storage/representations/redirect#show
         rails_blob_representation_proxy GET    /rails/active_storage/representations/proxy/:signed_blob_id/:variation_key/*filename(.:format)    active_storage/representations/proxy#show
                                         GET    /rails/active_storage/representations/:signed_blob_id/:variation_key/*filename(.:format)          active_storage/representations/redirect#show
                      rails_disk_service GET    /rails/active_storage/disk/:encoded_key/*filename(.:format)                                       active_storage/disk#show
               update_rails_disk_service PUT    /rails/active_storage/disk/:encoded_token(.:format)                                               active_storage/disk#update
                    rails_direct_uploads POST   /rails/active_storage/direct_uploads(.:format)                                                    active_storage/direct_uploads#create
```

# 対策

`config/application.rb` などで `config.active_storage.draw_routes = false` と設定すれば良いようだ

例

 ```rb
require_relative "boot"

require "rails/all"

Bundler.require(*Rails.groups)

module Ex
  class Application < Rails::Application
    config.load_defaults 7.0

    config.active_storage.draw_routes = false

    config.api_only = true
  end
end
```


# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# Twitter

https://twitter.com/YumaInaura
MinikubeでRedmineコンテナを起動する方法をChatGPTに聞いてみた

## はじめに
こんにちは！LIFULLエンジニアの吉永です。
この記事は[LIFULL Advent Calendar 2022](https://qiita.com/advent-calendar/2022/lifull)の9日目の記事です。

本日は最近話題の[ChatGPT](https://openai.com/blog/chatgpt/)にMinikubeでRedmineコンテナを起動する方法を聞いてみた結果を記事にしたいと思います。

## 何故Minikube？

LIFULLでは下記のテックブログにて発信しているように既に主要なサービスのほぼ全てをKubernetesで稼働させているのですが、一部のチームのサービスはまだKubernetesで稼働させていないものもあり、私達のチームのサービスもその一つなので、直近では移行する為の作業を行っています。

https://www.lifull.blog/entry/2019/12/16/000000

https://www.lifull.blog/entry/2020/08/03/113000

https://www.lifull.blog/entry/2021/09/22/114924

このような背景から、私達のチームでもKubernetesに関わる知識が必要になり、ひとまずチュートリアルくらいは触っておこうと先日参照していたページがこちらです。

https://kubernetes.io/ja/docs/setup/learning-environment/minikube/

Kubernetesそのものをがっつり触っていく機会はそんなにはなさそうなのですが、設定用のYAMLやそもそものシステムアーキテクチャとかを理解してないとダメかなーということで、チュートリアル手前のインストールしてローカルで動くかどうか確認するってところまでをやった状態です。
なので、まだKubernetesに関しては理解が浅い状態なのですが、以前自分で起動させたことがあるDockerイメージをMinikubeで起動できるとこまでやってみて、より理解を深めようという狙いがあります。

## MinikubeでRedmineコンテナを起動する記事について

この記事執筆時点では`minikube redmine`というキーワードでググっても、数年前の記事しか出てきませんでした。
なので、そもそもトライしている人が少なそうな印象ですね。
[ChatGPT](https://openai.com/blog/chatgpt/)は学習したデータの中から、他者の著作物を出力することもあるかもしれないので、一応事前に同一の記事のようなものがないかをチェックしておきました。

## ChatGPTとのやりとり

### 質問

minikubeでredmineを起動する手順教えて

### 回答

以下、[ChatGPT](https://openai.com/blog/chatgpt/)からの回答をそのまま張り付けてあります。

-----ここから

minikubeとは、Kubernetesをローカルで実行するためのツールです。以下の手順で、minikubeを使用してredmineを起動することができます。

1 minikubeをインストールします。この作業には、kubectlとVirtualBoxが必要です。
2 minikubeを起動します。

```bash
$ minikube start
```

3 Kubernetesクラスターに接続します。

```bash
$ kubectl config use-context minikube
```

4 redmineのデプロイメントを作成します。

```bash
$ kubectl create deployment redmine --image=redmine
```

5 redmineのサービスを作成します。

```bash
$ kubectl create service nodeport redmine --tcp=3000:3000
```

6 redmineにアクセスするためのURLを取得します。

```bash
$ minikube service redmine --url
```

7 取得したURLにアクセスして、redmineを利用することができます。

上記の手順でredmineを起動することができますが、実際の作業ではもう少し詳細な設定や手順が必要かもしれません。詳細は、redmineのインストールマニュアルやminikubeのドキュメントを参照してください

-----ここまではChatGPTの回答

### 結果

動いた・・・
いやぁ正直あまり期待してなかったのですが、見事にローカルのMinikubeでRedmineコンテナが起動して、アクセスできました。

## まとめ

今話題の[ChatGPT](https://openai.com/blog/chatgpt/)を使ってみようと思い、ちょうど今キャッチアップ中のKubernetes関連で役立てることができないかなーという軽い気持ちで取り組んだのですが、あまりにもあっさり動いてしまいちょっとびっくりしました。

なお、今回[ChatGPT](https://openai.com/blog/chatgpt/)に教えてもらった手順の合間に、とほほさんの下記記事と合わせて、`kubectl`の各種コマンドを打って動作確認するとより理解が深まるので、おすすめです。

https://www.tohoho-web.com/ex/kubernetes.html

ちょっと試してみたい、入門してみたいとかは[ChatGPT](https://openai.com/blog/chatgpt/)に質問して教えてもらうことができそうなので、今後も活用していきたいと思います！

最後までご覧頂きありがとうございました！
また次の記事でお会いしましょう！
過疎地域住まいへっぽこ非エンジニアがTableauPublicで行政区ごとの空き家率を可視化してみた。

## アドベントカレンダーに参加するぞー、おー。

アドベントカレンダーの企画がなんだかどうやって参加するのか、どうしたらプレゼントを頂戴頂ける機会を頂けるのか良く調べもせずに勢いでカレンダー予約してヒイコラいってる過疎地住まいの非エンジニア44歳です。

いつも前振りが長いので今日は先に成果物出します、ドン！

## オープンデータで実感する広島県の人口南高北低傾向

https://public.tableau.com/app/profile/.81026531/viz/20220821_16610646715230/sheet0

マークダウンで埋め込める方法がわからんかったんで、スクショを埋めときます。
上の奴はインタラクティブにマウスオーバーでラベルが出るよ！

![空き家率マップ (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1167883/4b0e5cec-2208-6d5d-5860-fcdf2a56dfe2.png)

地元の社会人向け履修証明プログラムで空き家問題についてデータを可視化する機会がありまして、オープンデータからデータソースと緯度経度を取得・加工・可視化しました。

こちらの記事を参考に作成しましたが、ここまでのものはちょっと私のヨワヨワチョットデキルスキルでは無理でした。
(※というよりマシンパワーが多分足りない)

[オープンデータを使って市区町村別に空き家率を可視化してみよう](https://enjoyworks.jp/tech-blog/8204)


緯度経度をtableauに読ますのが初めてでしたので少し手間取ったんですが、いい経験になりました。

赤ければ赤いほど空き家率が高いことを示しています。
見事に北部山間地域と島しょ部の空き家率が高いですね。

観光地として有名な尾道市の空き家率が高いのは意外でしょうか？

一度作ると手元にソースも残るし色々地域課題の可視化に使えていいね！

tableaupublicはBIツール作成の練習になるのでぜひ皆さんも使ってみてください！
へっぽこノースキル非エンジニアでもこれくらいはできるよ！

[tableau public](https://public.tableau.com/app/discover)


## データソース
[GISホームページ](https://nlftp.mlit.go.jp/index.html)

[平成30年住宅・土地統計調査](https://www.stat.go.jp/data/jyutaku/index.html)



## 参考資料
* [平成 30 年住宅・土地統計調査 結果の概要 総務省統計局](https://www.stat.go.jp/data/jyutaku/2018/pdf/g_gaiyou.pdf)
javascriptのfetchAPIで外部にあるphpファイルやxamppにあるphpファイルにアクセスしようとしたらなんか出来なかった

タイトル通り
しかしjsが記述されてるファイルと呼び出されるphpファイルが同じフォルダに置いてあるとアクセス出来た！
これがCORSか。

jsから外部リソースにアクセスするため、
jsファイル側では、
fetch()の第二引数内でmode: "cors"を指定する。
アクセスされるphp側では header()でAccess-Control-Allow-Originを設定すればアクセス出来る。
paizaラーニング レベルアップ問題集 paizaの森練習問題コンテスト過去問題7 JavaScript 最も大きな最大公約数

最も大きな最大公約数 (paizaランク C 相当)

https://paiza.jp/works/mondai/forest_contest_007/forest_contest_007__max_gcd

# 解答例

1 から n までの範囲にある全ての異なる整数の組、例えば(a, b)をforループで回しながら、
aとbの最大公約数を求め、それが最も大きな最大公約数か判定する。

```javascript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");

const [n] = lines[0].split(" ").map(Number);

//ユークリッドの互除法の関数定義
const gcd = (x, y) => {
  let r;
  while ((r = x % y) !== 0) {
    x = y;
    y = r;
  }
  return y;
};

//1 から n までの範囲にある全ての異なる整数の組(a,b)のうち
//最も大きな最大公約数maxを求める
let max = 1;
for (let a = 1; a < n; a++) {
  for (let b = a + 1; b <= n; b++) {
    max = Math.max(gcd(a, b), max);//関数を実行して、最も大きいか判定
  }
}
console.log(max);
```
paizaラーニング レベルアップ問題集 paizaの森練習問題コンテスト過去問題7 JavaScript ブロックの埋め込み

ブロックの埋め込み (paizaランク C 相当)

https://paiza.jp/works/mondai/forest_contest_007/forest_contest_007__block_filling

# 解答例
法則性がないか考えます。
縦 2 マス、横 1 マスのブロックを配置するとき、
縦nが奇数だと１行余りますが、ブロックは回転できるので、横mが偶数ならばピッタリハマります。
mについても同様です。
したがって、nとmが両方とも奇数のときに、隙間が1つ空きます。

```javascript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");

const [n, m] = lines[0].split(" ").map(Number);

if (n % 2 === 1 && m % 2 === 1) {
  console.log(Math.floor(n * m / 2));//1つ隙間が空く。n*mの1/2切捨てで求まる。
} else {
  console.log(n * m / 2);//ピッタリはまるのでn*mの1/2で求まる。
}
```
メンテナンス時にNewRelicのアラートの有効/無効を切り替えるスクリプトを作った

## 概要

NewRelicで監視しているホストをメンテナンスする時、メンテ起因のアラートが発生してSlackなどに通知が飛んでくる！って状況を避けるために、一時的にアラートをミュートしたいって時がありますよね。

そんな時に、Muting Ruleを作成して一時的にアラートをミュートにするのですが、手作業でポチポチやるのはめんどくさい！ということで**NerdGraph API** を活用して、任意のポリシーに基づくアラートをミュートするスクリプトを作成してみました。


## Muting Rulesを作成する

```bash
API_KEY=xxxx
ACCOUNT_ID=XXXX
POLICY_NAME=$@
NERD_GRAPH="mutation { alertsMutingRuleCreate(accountId: ${ACCOUNT_ID}, rule: {condition: {conditions: {attribute: \\\"policyName\\\" , operator: IN, values: \\\"${POLICY_NAME}\\\"}, operator: AND}, enabled: true, name: \\\"maintenance-${POLICY_NAME}\\\"}) { id  name schedule { startTime endTime } enabled } }"

curl https://api.newrelic.com/graphql \
-H 'Content-Type: application/json' \
-H "API-Key: ${API_KEY}" \
--data-binary "{\"query\": \"${NERD_GRAPH}\"}"
```

**NerdGraph部分を詳しく**

```graphql
mutation {
  alertsMutingRuleCreate(accountId: "${ACCOUNT_ID}", rule: {condition: {conditions: {attribute: "policyName", operator: IN, values: "${POLICY_NAME}"}, operator: AND}, enabled: true, name: "maintenance-${POLICY_NAME}"}) {
    id
    name
    schedule {
      startTime
      endTime
    }
    enabled
  }
}

```

引数として指定した文字列を含むポリシーをミュートするMuting Ruleを作成するNerdGraphになります。
**実行**

`sh maintenance.sh {対象アラートポリシー名}`
引数で指定したアラートポリシー名を部分一致で指定して
これで対象のアラートポリシーがアラート発令するのをストップする。

**レスポンス**
```
{"data":{"alertsMutingRuleCreate":{"enabled":true,"id":"26234454","name":"maintenance-hoge","schedule":null}}}
```

ここで返ってきたidは後にMuting Rulesを止めるために控えておく。

NewRelicでMuting Rulesが作成されてるのを確認します。
![スクリーンショット 2022-12-07 18.11.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689205/24e8da7d-216d-db36-0e16-a5a65e81ae00.png)


## Muting Rulesを破棄する

次にミュート解除シェルを発動させる（メンテナンス終了後に実施しないと永遠にアラートが止まったまんまになります。）

```sh
API_KEY=XXXX
ACCOUNT_ID=XXXX
MUTING_RULE_ID=$@
NERD_GRAPH="mutation {alertsMutingRuleDelete(accountId: ${ACCOUNT_ID}, id: \\\"${MUTING_RULE_ID}\\\") { id } }"

curl https://api.newrelic.com/graphql \
-H 'Content-Type: application/json' \
-H "API-Key: ${API_KEY}" \
--data-binary "{\"query\": \"${NERD_GRAPH}\"}"

```

**実行**
`sh terminate.sh {id}`

**レスポンス**
`{"data":{"alertsMutingRuleDelete":{"id":"0000000"}}}`

Muting Ruleが破棄されたことを確認。

![スクリーンショット 2022-12-07 18.10.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689205/75f230c3-fc75-7442-caf9-0223385f4e52.png)


## 参考

https://docs.newrelic.com/docs/alerts-applied-intelligence/new-relic-alerts/alert-notifications/muting-rules-suppress-notifications/

https://docs.newrelic.com/jp/docs/apis/nerdgraph/get-started/introduction-new-relic-nerdgraph/
(リンクだけです)確率密度関数(Probability_density_function)について調べてみた。

# wikipedia

https://ja.wikipedia.org/wiki/%E7%A2%BA%E7%8E%87%E5%AF%86%E5%BA%A6%E9%96%A2%E6%95%B0#:~:text=%E7%A2%BA%E7%8E%87%E5%AF%86%E5%BA%A6%E9%96%A2%E6%95%B0%20%EF%BC%88%20%E3%81%8B%E3%81%8F%E3%82%8A,%E8%A8%98%E8%BF%B0%E3%81%99%E3%82%8B%E9%96%A2%E6%95%B0%E3%81%A7%E3%81%82%E3%82%8B%E3%80%82

https://en.wikipedia.org/wiki/Probability_density_function


# 学習指導要領

「数学 B」の「（2）統計的な推測」を参照して扱う。＜
数学編 理数編＜高等学校学習指導要領（平成 30 年告示）解説＜平成 30 年 7 月

https://www.mext.go.jp/content/1407073_05_1_2.pdf#page=179

# 出題例

確率密度関数を大学入試数学問題集成で内部検索

https://cse.google.com/cse?cx=a8908fbc24340ebc5&q=%E7%A2%BA%E7%8E%87%E5%AF%86%E5%BA%A6%E9%96%A2%E6%95%B0&oq=%E7%A2%BA%E7%8E%87%E5%AF%86%E5%BA%A6%E9%96%A2%E6%95%B0&gs_l=partner-web.3..0i512l10.1672.1672.0.2579.1.1.0.0.0.0.113.113.0j1.1.0.csems%2Cnrl%3D10...0....1.34.partner-web..0.1.113.9gHPGGf6Y54

(出題例)

https://kamelink.com/blog/2022/12/07/17-4-89-tokyotoritsudai-ri-kou-5/

上と同じです。大学入試数学問題集成＞

https://mathexamtest.web.fc2.com/1989/198911262/1989112620100mj.html#top-0108
アフリカで機械学習をする

# はじめに

[クラウドAI by ナレコム Advent Calendar 2022](URL "https://qiita.com/advent-calendar/2022/knowcom-cloudai") の8日目です。

ナレッジコミュニケーションでは通常AWSやAzureを利用し、中でもAIやデータパイプラインを中心としたサービス提供を行っております。
<br>
私は東アフリカの[ウガンダ](URL "https://ja.wikipedia.org/wiki/%E3%82%A6%E3%82%AC%E3%83%B3%E3%83%80")に来ており、ウガンダでAIをする方法について記載します。

なお、アフリカの中でも南アフリカのような発展した場所やジブチのような特殊な国もあるので地域によって異なると思いますのでご了承ください。

ジブチってどんな国と思った人は[)「アフリカの「若者の失業率60％」の国に行ったら、「日本人はよく働く」の意味がようやくわかった](URL "https://blog.tinect.jp/?p=79225") が非常に興味深いです。
<br>
ウガンダだとPCはWindowsを使っている人が多くマイクロソフトは知っている人が多いですが、Amazon（通販）はアフリカでは唯一エジプトのみで提供されており知っている人は少ないです。

また企業が自社の業務システムをデータセンターに置くといったことも少ないものの、少数ながら国内にいくつかのデータセンターがあるようです。

ウガンダにも数多くのサービスがあり、サービス提供を行っている会社が多く利用しているのは[DigitalOcean デジタルオーシャン](URL "https://www.digitalocean.com/")です。
<br>
私はウガンダに行くことが決まって初めて知った会社ですが、いくつかのウガンダのスタートアップに話を聞くとDigitalOceanを使っている会社が多いです。


# DigitalOceanはどんなサービスか
2011年に設立されたアメリカのクラウドインフラストラクチャプロバイダーです。2011年というとAWSが日本リージョンを立ち上げた年です。

Qiitaにも[タグ](URL "https://qiita.com/tags/digitalocean")があり、いろいろな人が記事を上げています。ただ、AWS 33,631記事・Azure 6,519記事と比べて78記事のみと非常に少ないです。（2022年12月現在）

特徴は前佛さんがインフラエンジニア勉強会「hbstudy」の中で発表した資料が非常にわかりやすいです。 [今日から始めるDigitalOcean](URL "https://www.slideshare.net/zembutsu/all-about-degital-ocean-introduction-distribution-hbstudy")

DigitalOceanの特徴は月の金額の上限設定が決まっているところです。
一番安いサーバであれば月$4で利用することができます。 [DigitalOceanのホームページ](URL "https://www.digitalocean.com/")にも他のクラウドとの料金比較を出しており、転送量も含めると圧倒的なコストパフォーマンスになっています。どのサーバにも1,000GBの転送量が含まれており、超えた時も非常に安価です。 
<br>
ウガンダのように経済的に豊かでない国では、上限が決まっており安価で金額リスクも低いからこそ多くのサービスで利用されているのです。

# DigitalOceanにあるサービス
サービス自体は非常にシンプルで、管理ツールを除けばCompute・Storage・Networking・Databaseの4つのみ提供されています。

2022年6月には企業買収を行いComputeの中にサーバレスサービスが追加されています。

また、リージョンも限定的でアメリカ（3箇所）・オランダ・シンガポール・イギリス・ドイツ・カナダ・インド・オーストラリアの8カ国でのみ提供されています。

# DigitalOceanでAIをするには
2022年12月現在DigitalOceanはGPUを提供しておりません。2021年の公式コミュニティでも[サポートしていない](URL "https://www.digitalocean.com/community/questions/do-you-support-gpu-nvidia")となっておりました。

そのため、GPUを使わないければ実行できないような処理がある場合はDigitalOceanのみで完結することは難しいです。

GPUがないとできない場合は
1. ローカルマシンやローカルサーバでGPU処理のみ実施 
2. その処理のみAWSやAzure、GCPを使う 
3. GPUを使わないでも出来る処理に置き換える 
といった方法が考えられます。

日本の感覚であれば数ドルであれば気軽に使えますが、ウガンダでは影響が大きいのでできるだけ3を考える必要があります。

無料で使えるSaaSが多いこともあり、Googleを使っているユーザーは多いのでコストも考えると以下の方法がウガンダでAIをするベストプラクティスと考えます。なお、AIということでPythonを前提としております。

* Google Colabで処理を作成
    - TPUやGPUは使わない
    - Google Colabで動くなら、DigitalOceanでも動く可能性が高い
* DigitalOceanのサーバレスサービス Functionに実装
    - 0円から使え、90,000GiB秒分の無料枠がある
    - 固定料金がなく従量課金
    - 例えば、1GB Memory×20秒の処理だと45,000回まで無料で実行できる
* 回数などに応じて通常の仮想サーバ Dropletsを活用する
# まとめ
日本にいるときにも予算などを考えてリソースを使っていましたが、ウガンダでは人件費が安いことやサービスから稼ぐことが難しいなど何倍もシビアにリソースを考えて使う必要があります。 
人件費も何倍も違うため、日本なら人件費かけてやるよりはマシンリソースを使って解決しようとなるケースでも、なるべく固定費がかからなくてマンパワーで解決しようとなります。

日本やアメリカでは体験できない貴重な目線でクラウドサービスを見ることができました。
Apple Developer Programについて調べてみた

# Apple Developer Programとは
iOSアプリの開発と配信に必要なすべてのツール、リソース、サポートが含まれている年間メンバーシップのサブスクリプション(「年額$99」、日本円にして「11000〜14000円」ほど)です。登録することでSwiftなどで作成したiOSアプリなどをApp Storeに公開することができます。
また、ベータ版ソフトウェア、Appサービス、テストツール、Appアナリティクスなども利用できます。

詳しく一つずつ見ていきましょう。

# 作成したiOSアプリをApp Storeへ公開
xcodeを使用し、SwiftやObjective-Cの言語で作成したアプリを世界中のユーザーに提供することができます。
もちろんiPhoneのアプリだけでなく、iPad、Mac、Apple Watch、Apple TVのデバイスのアプリケーションも公開することができます。
自分が作成したアプリが世界中のユーザーに使ってもらえると思ったらワクワクしますね。

# 最新のベータ版の取得
OSのアップデートが来ると基本的にユーザーはすぐにアップデートを行います(iPhoneとかは自動アップデートをオンにしている方が多い)。
しかしOSのアップデートが来てから、作成したアプリをそのバージョンに合わせた対応を行っていると、その期間アップデートによる不具合が発生しユーザーへ迷惑がかかる可能性があります。
それが起こらないよう、事前に提供されているベータ版を取得することでアップデートへの対応を行い、リリースに合わせて各OSの最新機能をAppでシームレスに提供することができ、いつでも次世代の機能に対応できるようになります。

# 開発者用ツール
Appサービスの設定、デバイスや開発チームの管理、新しいAppやアップデートの提出に使用する包括的なツールセットをすべて利用できる。
さまざまありますが、一例を紹介します。
#### App Store Connect
- App Storeで配信するAppの提出や管理を簡単に行うことができる
- TestFlightでAppを最大10,000名まで外部テスターを招待することができる
- 売上とトレンドを確認できる

#### Certificates, Identifiers & Provisioning Profile（証明書、ID、プロファイル）
- Appの開発、配信、サービスを有効にします
- 簡単にいうと「このアプリは開発者が認めたアプリ」ですよという証明書が作成できる→これがないとアプリを提供することができない

#### CloudKit Dashboard
- AppにおけるCloudKitのサーバアクティビティを詳しく把握することができる

などなど他にもさまざまあります。

# Appアナリティクス
ユーザーがどのようにしてAppを見つけ、利用しているかを調べることができます。
またアプリのダウンロードに関する情報も確認できます。

#### App Storeのパフォーマンス
- App Storeでの検索やブラウジングを通じて、あなたのAppにたどり着いたユーザー数を確認
- ユーザーがどのAppやWebサイトからプロダクトページにアクセスしているかを調べる頃ができる
- 初回ダウンロード数、再ダウンロード数、合計ダウンロード数などのAppのダウンロードに関するデータの確認
- App Storeでのコンバージョン率を測定

#### Appのエンゲージメントと使用状況
> 各種のユーザーエンゲージメント指標や、ユーザーによる継続的な使用の有無、インストール数、セッション数、アクティブなデバイス数などを把握することができます。こうした情報を活用することで、オンボーディング内容の調整や、スペシャルコンテンツの追加など、Appのアップデートの効果を評価することができます。また、クラッシュや削除に関するデータを、プラットフォーム、Appのバージョン、オペレーティングシステムのバージョンごとに確認できるため、原因の可能性を特定して、ユーザー体験の質を高めることができます。

引用：https://developer.apple.com/jp/app-store-connect/analytics/

#### 購入ユーザーの把握
特定の購入ユーザー数を日、週、月単位で確認することができる
Appに変更を加えた場合にApp内課金の購入にどのように影響するかを分析することもできる

# Appleのエキスパートによるサポート
Apple Developer ProgramおよびApple Developer Enterprise Programのメンバーはバグを修正できない場合や、特定のテクノロジーの実装に関して問題が発生した場合、あるいはコードレベルの質問がある場合に、デベロッパテクニカルサポートのエンジニアによって、コードのトラブルシューティングや回避策など、迅速に開発するためのサポートを受けることができます。

# 最後に
Apple developerに入ると、さまざまなサポートが受けることができることがわかりました。
こちらの記事に記載している内容の他にもたくさんのサポートがあります。
せっかく高い金額を払ってサービスを受けるなら、積極的に活用していきたいですね。
記事の感想や意見、ご指摘等いただけると助かります。
最後までご覧いただき、ありがとうございました。
TaskEither型を使ってResult型を作る

[Next.js + サーバーサイドTypeScript + 関数フレーバーでクリーンなアプリを作ったので実装意図とか書く Advent Calendar 2022](https://qiita.com/advent-calendar/2022/shwld)
の**8日目**。[株式会社mofmof](https://www.mof-mof.co.jp/)に生息している[shwld](https://twitter.com/shwld)です。

前日は[Either型](https://qiita.com/shwld/items/f5f192ace0702d9156e2)について書きました
# TaskEither型を使ってResult型を作る
fp-tsには[TaskEither](https://gcanti.github.io/fp-ts/modules/TaskEither.ts.html)というものがあります。
失敗する可能性のある（Either）非同期処理（Task）を表現することができるものです。

具体的にみていきましょう。

fp-tsの[tryCatch](https://gcanti.github.io/fp-ts/modules/TaskEither.ts.html#trycatch)を使うことで、PromiseをTaskEitherに変換することができます。

```ts
import { tryCatch } from 'fp-ts/TaskEither'

const taskEither = tryCatch(() => {
  saveToDatabase()
}, e => {
  if (e instanceof PrismaClientRustPanicError) {
    return new OriginalDBError(e);
  }
  return new OriginalRuntimeError('error');
}
```

上記で得られる `taskEither` は実行(`taskEither()`)すると`Promise<Either<left, right>>`が返ってきます。
## 嬉しいこと
Eitherの利点については昨日書いたので、ここではTaskの利点について説明します。
Taskを使うことで、複数のPromiseの直列実行、並列実行を操作し一つのPromiseにまとめて、Eitherの配列にしてくれます。

```ts
import { sequenceArray } from 'fp-ts/TaskEither'

const taskEithers = items.map(item => saveToDatabase);
// taskEithers is TaskEither<OriginalDBError, DBResult>[]
const taskEither = sequenceArray(taskEithers)
// taskEither is TaskEither<OriginalDBError, DBResult[]>
const results = await taskEither()
// results is Either<OriginalDBError, DBResult[]>
```

一つのPromiseにまとめてくれることにより、取り出す際に一つ一つawaitしたりすることがなくなるのはもちろん、取り出す以前の状態で、直列、並列実行を指定でき、宣言的に非同期処理を扱えて嬉しい。
## EitherとTaskEitherを区別するのがだるい
EitherとTaskEitherを使えるようになりました。
[fp-ts](https://gcanti.github.io/fp-ts/)には他にもOptionやIOなど連続した処理の流れの中で例外を管理するような仕組みがいくつもあります。

## TaskEitherをResult型として使う
今回自分のテーマとして、関数型を知らない人でも書けるといいなと言う思いがありました。
そこで、選択したのがResult型として、TaskEitherのみを使うという選択です。

EitherをすべてTaskEitherに変換することで、すべての処理の連続の中でResult型だけを気にすれば良くなりました（これがいいのかはわかりませんが）
つまり、すべてPromiseとして扱うということになり、そこは少し抵抗があったのですが、同期でないとやりづらいところはsuffixに`Sync`をつけたバージョンのメソッドを生やすようにしました。

コードをみるとわかりますが、Result型はいたるところに出てきます。

```ts:/domain/core/src/models/account/mutations/build-account.ts
export const build = (
  input: Account_BuildInput
): Result<InvalidAttributesError, Account_BuiltAttributes> => {
  return pipe(
    {
      ...input,
      createdAt: new Date(),
      updatedAt: new Date(),
    },
    validateWith(validationSchema),
    map(v => ({
      ...v,
      __state: STATE_IS_BUILT,
    }))
  );
};
```
[https://github.com/shwld/uzumaki/blob/main/domain/core/src/models/account/mutations/build-account.ts#L39](https://github.com/shwld/uzumaki/blob/main/domain/core/src/models/account/mutations/build-account.ts#L39)

# 次回予告
明日は[エンティティの状態遷移関数](https://qiita.com/shwld/items/894299a730b48b992441)について書きます。
Livebook で kino_benchee (WIP)を動かしてみた

## はじめに

:::note info
リリース後の情報を以下の記事にまとめました

https://qiita.com/RyoWakabayashi/items/1265be26c6f3617a0baa
:::

Kino の GitHub を見ていると、見慣れない単語が

https://github.com/livebook-dev/kino

> Additionally, there are packages with components designed for a specific use cases. The officially supported ones are:
>
> - kino_vega_lite - for data charting
> - kino_db - for database integrations
> - kino_benchee - for rendering Benchee results

kino_benchee ？

すごく、そそる名前

Benchee は Elixir でベンチマークするためのモジュール

処理のパフォーマンス比較が簡単にできるのでいつも重宝しています

https://github.com/bencheeorg/benchee

その Kino 版ということは、 Benchee の出力がますます魅力的になるはず！

なぜ今まで使っていなかったんだ？

と思ったら、まだ WIP でリリースされていませんでした

https://github.com/livebook-dev/kino_benchee

> Benchee integration with Livebook.
>
> Currently WIP.

しかし、どんなものか見ておきたい！

というわけで動かしてみました

以前並列処理を実装したノートブックを改造します

https://github.com/RyoWakabayashi/elixir-learning/blob/main/livebooks/distributed_image_processing/parallel_image_processing.livemd

## インストール

以下のようにして kino と kino_benchee を GitHub から最新版で取得します

```elixir
Mix.install([
  {:download, "~> 0.0.4"},
  {:evision, "~> 0.1"},
  {:nx, "~> 0.4"},
  {:flow, "~> 1.2"},
  {:kino, github: "livebook-dev/kino", branch: :main, override: true},
  {:kino_benchee, "~> 0.1", github: "livebook-dev/kino_benchee", branch: "main"},
])
```

## 通常との比較

そのあとは以前の記事と同じように処理を実行します

https://qiita.com/RyoWakabayashi/items/1a83c962ae03791a988c

すると、最後の Benchee を実行した結果がすごくキレイになります！

```elixir
Benchee.run(%{
  "enum" => fn -> enum_proc.(stream) end,
  "flow 1" => fn -> flow_proc.(stream, 1) end,
  "flow 2" => fn -> flow_proc.(stream, 2) end,
  "flow 4" => fn -> flow_proc.(stream, 4) end,
  "flow 8" => fn -> flow_proc.(stream, 8) end
})
```

![スクリーンショット 2022-12-07 17.43.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/36e3039d-797b-2520-abcc-f32d8916f70b.png)

パフォーマンス比較がデータテーブルとグラフになっています！

すごく視覚的！！

さらに `memory_time` と `reduction_time` も見てみましょう

```elixir
Benchee.run(
  %{
    "enum" => fn -> enum_proc.(stream) end,
    "flow 1" => fn -> flow_proc.(stream, 1) end,
    "flow 2" => fn -> flow_proc.(stream, 2) end,
    "flow 4" => fn -> flow_proc.(stream, 4) end,
    "flow 8" => fn -> flow_proc.(stream, 8) end
  },
  memory_time: 2,
  reduction_time: 2
)
```

![benchee.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/8835ee66-d257-9e0a-f92d-4730eea32cce.gif)

メモリ使用量の差が一目瞭然！

reduction については以下のリンクに説明があります

https://github.com/bencheeorg/benchee#measuring-reductions

## まとめ

kino_benchee の正式リリースが待ち遠しいですね
初期値を入れる方法


引数に=をつけて初期値を入れる。

```javascript

function hoge(num=1){
    console.log(num)
}

```


こうやってもいい。

```javascript

function hoge(num){
    const number = num || 1
    console.log(number)
}

```

---------

：追記
上のコードは間違えてたけど、

https://qiita.com/hari64/items/47568790dc92100e4e77


最近この記事を読んで、直せるかなと試してみた。

修正版
```
function hoge(num){
    const number = num ?? 1
    console.log(number)
}
```

hoge(0);    // 0
hoge('');   //''

おおっ！　いいぞ！


hoge(null); // 1


・・・やっぱり三項演算子を使いましょう。



-------


オブジェクトはこんな感じかな。

```javascript
function hoge(obj={num: 1,club:'soccer'}){
    console.log(obj)
}
```

```javascript
function hoge(obj){
    Object.assign({
        num: 1,
        club:'soccer'
    }, obj);
    console.log(obj)
}

```