OmniAICreator/Qiita-1.07M huggingface dataset:
POST で primary key を取得できない場合は 400 or 404のどっちを選べばいいの？

### 疑問

とあるエンドポイントを呼び出し時にuser_idを指定するが、
DBにuser情報がない場合 404 or 400 or 503 何を選べばよい？


### 事前情報と参考文献

https://postd.cc/choosing-an-http-status-code/

> 4XX の早見表 Start -> No -> No-> Yes -> No(※) -> No -> 404
> 4XX の早見表 Start -> No -> No-> Yes -> Yes(※) -> Yes -> No * 5 -> 400

※ 問「リソースは存在する？」で 400 と 404 は分岐する
※ 下記の引用に示されるように 「リソースは存在する？」 は「接続可能なURIであるか？」を意味する
※ このとき、 form dataは考慮されない

https://meetup-jp.toast.com/931

> 資源（RESOURCE） – URI



### 端的に言うと？

routingだけ機能したときに実行対象のAPIが発見できない場合が404。


##### RESTful APIに従っている場合(CURD の Createのみ担当している場合) の 404

urlのアドレス先が無いなら404。
こんな感じに endpointのpathでuser_idを含む場合で、
リクエストのuser_idからuser情報がない場合は404

```bash
endpoint_A_path="https://${domain}/user/${user_id}/create_unique_key"
curl -X POST \
  ${endpoint_A_path} \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'foo=baz'
```

##### RESTful APIに従っている場合(CURD の Createのみ担当している場合) の 400

必然的に リクエストのuser_idからuser情報がない場合以外のエラー になるから
作成に失敗する場合は400(or 503)を返却する。

```bash
endpoint_A_path="https://${domain}/user/${user_id}/create_unique_key"
curl -X POST \
  ${endpoint_A_path} \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'foo=baz'
```

##### RESTful APIに従っていない場合(CURD の Create, Updateを担当している場合)  の 400

こんな感じに endpointのpathで含まないならurlのアドレス先はあるはずだから404ではない。
リクエストのuser_idからuser情報がない場合も、
リクエストのuser_idからuser情報がない場合以外のエラー も
通常、400 を返却する。
urlのアドレス先はあるけど、パラメータが間違っていてサーバーエラーが発生するから。

```bash
endpoint_A_path="https://${domain}/users/create_unique_key"
curl -X POST \
  ${endpoint_A_path} \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d "user=${user_id}&foo=baz"
```
【Vue.js】v-onディレクティブでボタンを押したら数字が増える


```vue
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>

<div id="app">
  <p>{{ number }}回目のクリックです</p>
  <button @click="countUp">ボタン</button>
</div>
```

```ruby

new Vue({
	el: '#app',
  data: {
  	number: 0,
  },
  methods: {
    countUp: function() {
      this.number += 1
    },
  }
})
```

これで![スクリーンショット 2021-03-03 20.20.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628093/5b28812b-2802-ae97-a835-bc25e0b3df3a.png)

ボタンを押すと、数字が増えていくようなものが出来あがる。

```<button @click="countUp">ボタン</button>```
この@clickは本当は,v-on:clickと記述するが、このように@で省略する記法もある。
string型にnilを入れる黒魔術

良いか悪いかといったら、どう考えても悪い。


```
package main

import (
	"fmt"
)

type text struct {
	text string
}

func main() {
	var a string
	a = fmt.Sprint(nil)
	fmt.Println(a)
	fmt.Println(a == "nil")
	//fmt.Println(a == nil) //invalid operation: a == nil (mismatched types string and nil)

	var t text
	t.text = fmt.Sprint(nil)
	fmt.Println(t.text)
	fmt.Println(t.text == "nil")
	// fmt.Println(t == nil) // invalid operation: t == nil (mismatched types text and nil)
}
```
CCSにC2000wareをいれる方法

## C2000wareDL
https://www.ti.com/tool/C2000WARE
上記のURLからDLする。Tiアカウントが必要。

## C2000wareインストール
ダウンロードしたexeを実行してインストールしよう。

## CCSに入れる
1. Windowタブを開く
2. Preferencesを開く
3. Code Composer Studioタブを開く
4. Productsを押す
5. Addより，インストールしたc2000wareを選択していれる。
6. Apply and Closeより適用する
Power Automate Desktop触ってみる

# 実施内容
Power Automate Desktopをもちいてブラウザの操作を自動化してみた

# ■ 画面操作
日本Seleniumユーザーコミュニティの[テストサイト](http://www.selenium.jp/test-site)を利用

### 1. フロー作成
- 新しいフローから新規作成
![qiita_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256753/f0533638-2337-793c-50af-0d60adcacc86.png)

- フロー名入力
![qiita_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256753/c3900339-cfef-d44a-fb2b-9727ee590a7b.png)

- 作成画面
![qiita_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256753/9c153e92-4f7b-54ee-702c-432b709a4173.png)

### 2. アクション作成
- 左側のアクション一覧から「新しいFirefoxを起動する」をドラッグアンドドロップ

![qiita_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256753/7376f77e-3cb9-a180-d731-db2622ba8e89.png)

- アクションのパラメータ入力
![qiita_5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256753/f51b6c6f-1f79-2579-8d02-fd5a672b499c.png)

- 左側のアクション一覧から「Webページ内のテキストフィールドに入力する」をドラッグアンドドロップ

![qiita_6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256753/f8c18b39-f7dc-6c38-74b7-eeaf24e57fb7.png)

- パラメータのUI要素はマウスカーソルを合わせてで簡単に取得可能

![qiita_8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256753/d5140bf5-b6d4-d09b-a8f8-e32c40b6f7f7.png)

![qiita_9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256753/176fa0db-3825-1f95-5dc0-e3f215543125.png)

![qiita_10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256753/aea2ddab-f01b-3ed1-b4b9-8b0d0eac0f9a.png)

![qiita_11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256753/f9496301-4880-981f-5b38-5fe0630c6c9f.png)

- あとは同じように名前の入力、ボタンの実行のアクションを追加
![qiita_12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256753/d0d9c6b8-d99f-29df-18d8-f4a5b866d854.png)

### 3. 実行
![qiita_13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256753/ebf7b047-6c61-1d78-0fb0-159d2fc34853.png)

### 3. 実行結果
![qiita_14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256753/d182f875-07bf-89f2-db37-2a36a7cfe911.png)
![qiita_15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256753/d071317d-5b5d-cf2d-27b2-4bd4aea2beb5.png)

### 動画
<iframe width="560" height="315" src="https://www.youtube.com/embed/GMcwwaLFWIs" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

# ■ 感想
[以前](https://qiita.com/manchan/items/fe09e1075e908554596c)にも同様のブラウザ操作をPuppeteerで試したが
Power Automate Desktopは直観的に作成できたので簡単な操作ならばエンジニア以外の方でも利用できそう。
[Vue]ページ遷移時にページを画面のトップに戻したい

#概要
Vue Routerでページ遷移する時、前のページのスクロール位置のまま遷移してしまうので画面が中途半端な位置になってしまいます。

ページ遷移した時に画面トップに戻る処理を実装できるのが`scrollBehavior関数`です。

#実装

```.js
const router = new VueRouter({
  mode: 'history',
  routes: [
    {
      path: '/',
      name: 'home',
      component: HomeComponent,
      props: true,
      meta: {isPublic: true},
      children: [
        {
          path: '/trend',
          name: 'trend',
          components: {
            trend: TrendTimeline,
          },
          props: true,
          meta: {isPublic: true},
        },
        {
          path: '/item',
          name: 'item',
          components: {
            item: TrendItem,
          },
          props: true,
          meta: {isPublic: true},
        }
      ]
    },
  ],
  scrollBehavior (to, from, savedPosition) {
    if (savedPosition) {
      return savedPosition
    } else {
      return { x: 0, y: 0 }
    }
  }
})
```

to: 遷移先のルート情報
from: 遷移元のルート情報
savedPosition: ブラウザの戻る/進むボタンがトリガーされた時にのみ使う

上記だとブラウザ戻る、進むボタンが押された時以外はページトップに戻るようになっております。

特定のルートだけページ位置を戻したくない場合は、

```.js
  scrollBehavior (to, from, savedPosition) {
    if (savedPosition || to.name == 'home' ||to.name == 'trend' || to.name == 'item') {
      return savedPosition
    } else {
      return { x: 0, y: 0 }
    }
  }
```

のようにto.nameで指定することで実装することができます。
IBM Security Verify APIで ユーザープロファイル変更したときの通知メールを無効化する

# はじめに
IBM Security Verify(ISV) APIでユーザープロファイルを更新したときに送付される通知メールを無効化する方法についてご紹介いたします。

# APIのリファレンス
APIのリファレンスは、以下のURLから確認できます。
https://<自分のテナント名＞.verify.ibm.com/developer/explorer/#

- ユーザーの取得に利用するAPIは、以下の項目になります。
- Users Management Version 2.0 

APIに関するKCのヘルプはこちらです。
https://www.ibm.com/support/knowledgecenter/ja/SSCT62/com.ibm.iamservice.doc/concepts/apis.html

# 1.APIでユーザーの属性を変更した場合のメール通知について
デフォルトでは、ユーザー属性更新時に、ユーザープロファイルの変更がメール通知されます。
ユーザープロファイルの優先言語に従い、通知メールが送付されます。

##1.1優先言語がen-USの場合
![notification (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/dc529623-6b82-a9d8-6046-b8e5eec83f25.png)
通知メールは英語となります。
![notification (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/c4dcf2a4-981c-3356-f4d1-a3988b6b85e6.png)


##1.2優先言語がja-JPの場合
![notification (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/fedcd917-b961-a118-b0e7-f083bfa6b751.png)
通知メールは日本語となります。
![notification (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/e1f78141-9430-398e-56c4-0a1dc2916ae2.png)



# 2.APIでユーザーの属性を変更した場合のメール通知を無効化する方法について
PATCHリクエストでユーザー更新したときのメール通知を無効化するためには、
"urn:ietf:params:scim:schemas:extension:ibm:2.0:Notification:notifyType"属性をNoneに設定します。

```
curl -i -X PATCH https://<テナント名＞.verify.ibm.com/v2.0/Users/<ユーザーID＞ --header "Content-Type: application/scim+json" --header "Authorization: Bearer <アクセストークン>" --data-raw "{\"schemas\":[\"urn:ietf:params:scim:api:messages:2.0:PatchOp\"],\"Operations\":[{\"op\":\"replace\",\"path\":\"active\",\"value\":false},{\"op\":\"replace\",\"path\":\"urn:ietf:params:scim:schemas:extension:ibm:2.0:Notification:notifyType\",\"value\":\"NONE\"}]}"
```

![notification (5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/1cfa54ab-379c-c983-b9b7-d57873fe505f.png)



# 最後に
IBM Security VerifyのAPIを利用してユーザープロファイル変更する際に送付される通知メールを無効化する方法についてご紹介しました。
Rails 6.1で発生する"Calling `<<` to an ActiveModel::Errors message array in order to add an error is deprecated"警告を修正する

Ruby on Rails 6.1に上げると以下のような警告が出ることがある。

``` 
DEPRECATION WARNING: Calling `<<` to an ActiveModel::Errors message array in order to add an error is deprecated. Please call `ActiveModel::Errors#add` instead.
```

この問題は次のように修正する。

```diff 
-record.errors[:base] << "Something went wrong."
+record.errors.add :base, "Something went wrong."
```

## 応用：正規表現でプロジェクト全体のコードを一括置換する

が、数が多いと大変なので、エディタのGrep置換機能と正規表現を使ってこんなふうに一括置換すると便利かも。


- 検索条件 = `errors\[:(\w+)\] <<`
- 置換文字列 = `errors.add :$1,` （エディタによっては`$1`ではなく`\1`になることもある）

もちろん、これはプロジェクト全体で`errors[:hoge] <<`が同じフォーマットで書かれていることが前提なので、フォーマットに一貫性がないときは置換対象から外れたり、おかしな置換結果になったりする場合があるので注意。

### 正規表現がわからん！という場合
僕が以前書いた正規表現の入門記事を見ればわかるはずです！

- [初心者歓迎！手と目で覚える正規表現入門・その１「さまざまな形式の電話番号を検索しよう」 \- Qiita](https://qiita.com/jnchito/items/893c887fbf19e17d3ff9)
- [初心者歓迎！手と目で覚える正規表現入門・その２「微妙な違いを許容しつつ置換しよう」 \- Qiita](https://qiita.com/jnchito/items/64c3fdc53766ac6f2008)
Qiitaはじめました

# 自己紹介
初めまして！この度Qiitaを始めました**(自称)やまだけんいち**です。学生です。
# 得意とする言語
WEBアプリを開発しています。まだまだ初心者中の初心者ですが、頑張って勉強していきます。  以下、得意な言語です。

- HTML
- JavaScript
- CSS
どれも、WEBアプリ開発でお馴染みの言語ですね(^^)
# 作ったもの
まだ1つしか公開していませんが、これからどんどん公開していきます。

- 半永久的に計れるタイマー<br>[アプリはこちらから](https://r-40021.github.io/countdown-timer/)

# ソーシャル
- [Twitter](https://twitter.com/r_40120)
- [GitHub](https://github.com/r-40021)

# 最後に
末長くよろしくお願いいたします。
Flownet2をpytorch1.0、CUDA10.2で動かす

Nvidiaが公開しているflownet2のpytorchライブラリがCUDA9、flownet0.40でしか動かず、CUDAをインストールし直すのも面倒だったので、CUDA10で動かす方法を調べたのでメモしておく。
https://github.com/NVIDIA/flownet2-pytorch

もしdockerを使う場合は、DockerfileのベースイメージをCUDA10対応のものにし、pytorchのインストール方法を修正する必要がある。

ただ、これだけだと、`` bash install.sh``でCUDA周りでのエラーが出る。

issueをググったところ、いくつかの方法が見つかったが、下記のように書き直すのが妥当そうだったので、これのとおりに書き直した。
https://github.com/NVIDIA/flownet2-pytorch/issues/131

修正後`` bash install.sh`` で無事にインストールできた。

修正後、下記コマンドで学習を開始するところまで確認できた。

```
$ python3 main.py --batch_size 2 --model FlowNet2 --loss=L1Loss --optimizer=Adam --optimizer_lr=1e-4 --save=./work2 \
--training_dataset FlyingChairs --training_dataset_root $(pwd)/FlyingChairs_release/data \
--validation_dataset MpiSintelClean --validation_dataset_root $(pwd)/training 
```

ただ手持ちの1050tiだと、`` cuda runtime error(2): out of memory ``を起こして停止するので、とりあえず下記リンクを参考に原因を調査する。
https://pytorch.org/docs/stable/notes/faq.html#my-model-reports-cuda-runtime-error-2-out-of-memory
HoloLens 2 のセンサー関連について調査するために使われている英語の略式をまとめる

* HoloLens 2 のセンサー関連について調査するために、https://github.com/microsoft/HoloLens2ForCV を読み進めています。
* 英語の略式を見て、すぐに何の略式かが出てこないことがあるので、暗記するためにまとめました。
* 一般的に浸透している略式、この資料限定的な略式を同居させてしまっています。
* 英文を読んでいるときは、謎の略語に恐怖感をいただきましたが、まとめてみると大したことないということがわかりました。

|略式|正式|メモ|
|:----|:----|:----|
|CV|Computer Vision|リポジトリ名のForCVのCVは、おそらく、Computer Visonの略|
|AB|Active Brightness |デプスが有効な範囲の明るさと捉えてよいのだろうか？|
|AHAT|Articulated HAnd Tracking|関節式ハンドトラッキング|
|ECCV|European Conference on Computer Vision|ヨーロッパで行われるコンピュータービジョンのカンファレンス|
|HPU|Holographic Processing Unit|Holographicに特化した演算装置|
|IMU|Inertial Measurement Unit |慣性関連の情報を計算する装置|
|SLAM|Simultaneous Localization and Mapping| |
|VLC |Visible-Light Camera|可視光カメラ|
|ToF|Time of Flight|飛行時間をもとに（深度を計算する）|
|MRC|Mixed Reality Caputure|ホログラムと物理環境の複合写真、複合ビデオ|
|SoC|System On a Chip|チップの上に複数のシステムを実装する|
|DoF|Depth of Field|被写界深度|
|IR|Infrared Radiation|赤外線|
|-|Spatial Mapping|空間マッピング|
|-|aliased depth|0と1がはっきりした深度という意味で使われていると思われる|
LaravelでNotification::fake()を使ったテストでNotification::assertSentToがうまく通らない

## 経緯
Laravelのテストで、Notification Fake
https://readouble.com/laravel/8.x/ja/mocking.html
を使用して、テスト時に実際にはslackに通知を飛ばさないようにしておいて、
`Notification::assertSentTo`
で、通知が送信される処理は行われていることをテストしようとして、

```php
Notification::assertSentTo(
    new AnonymousNotifiable,
    SlackNotification::class
);
```

と書いたのだけど、どうあがいても

```
The expected [App\Notifications\SlackNotification] notification was not sent.
Failed asserting that false is true.
```

と怒られてしまう。
指定の仕方とか色々試したけど、assertSentToではどうあがいてもうまくテストが通らなかった。。。。


## 解決策
`Notification::assertTimesSent`
を使用することで解決

```php
Notification::assertTimesSent(
    1,
    SlackNotification::class
);
```
第一引数に通知が送信されるべき回数（期待値）を指定してやればOK
テストでは一旦通知内容は確認しなくてOKだったので、通知が飛ばされる回数をテストしてやる形でテストが通った

通知が送られる処理の直前で

```php
Notification::assertTimesSent(
    0,
    SlackNotification::class
);
```
と記述しても通ったので、とりあえず問題なさそう。

assertSentTo使う場合はどう書けばいいのかモヤモヤするけど、一旦忘れる！


## 追記
本記事を公開後、ちょっと調べてたら、以下の記事を見つけた
https://qiita.com/harukei/items/26f0a1c0d6128f681c00
`Notification::fake()　が　Mail::fake()　を上から潰しているようです。`

確かに僕のコードでも

```php
    public function test__invoke()
    {
        Mail::fake();
        Notification::fake();
```
とNotification::fake() と　Mail::fake()の両方を使用しているので、assertSentToがうまく動作しないのはこのせいなのかもしれない。。。
Passport.jsのローカル認証で特定のディレクトリ以下にアクセス制限をかける

## はじめに
HTMLなどの静的ファイルを置いたディレクトリに対し登録済みユーザーのみアクセス可能なアクセス制限をかけようと、Node.js＋Express.js＋Passport.jsでWEBサイトを構築しました。
ローカル認証方式で特定のディレクトリだけでなく配下のすべてのディレクトリとファイルに対しアクセス制限を掛ける方法がネットでは見つけられずハマったので解決法を共有します。


## ソース
Passport.jsの設定等は他のサイトをご参照下さい。
/app/restrict というディレクトリ以下すべてに対するGETメソッドについて認証を求める方法は以下の通りです。

```javascript
app.get(/app\/restrict/ , (req, res, next) => {
    if (!req.isAuthenticated()) {
        req.session.originalUrlSave=req.originalUrl;
        res.render('login', { error: req.flash('error'), title: 'ログインページ' });
    }
    else {
        return next();
    }
});
```
* ディレクトリの指定に正規表現を使います
* 認証済みなら return next(); でGETしに来たファイルがそのまま返ります
* restrictディレクトリ配下のURLに直接アクセスして来た場合に、ログイン画面でログイン成功したらそのURLに飛べるよう元のURLをセッションに保存しておきます。

## 終わりに
最初は

```javascript
app.get('/app/restrict' , (req, res, next) => {
```

と書いていて、restrictディレクトリは意図通りアクセス制限が効くのですが、
/app/restrict/js
のようなサブディレクトリには全くアクセス制限が効いていないことに気づいて焦りました。
「指定したディレクトリの配下も掛かるハズ」と言った先入観を捨ててテストはしっかりやらないと怖いですね。
Get all containers log for one namespace

Pods managed by deploy or daemonset don't have a fixed name, you must get the pod name and then get the log for the pods and containers.

Here is a simple script gets all pods in one namespace and get logs for all containers in that pod.

```bash

#!/bin/bash

ns=some-namespace
for pname in `kubectl -n $ns get pods | grep Running | awk '{ print $1}'`; do
  # pname=$(echo $pname | tr -d '"')
  pbody=$(kubectl -n $ns get pods $pname -o json)
  csize=$(echo $pbody | jq '.status.containerStatuses | length')
  echo "pod $pname has $csize containers"
  
  for i in $( seq 0 $(($csize - 1)) ); do
    cname=$(echo $pbody | jq .status.containerStatuses[$i].name | tr -d '"')
    echo "  get logs for $cname"
    kubectl -n $ns logs $pname -c $cname >"$pname-$cname".log
    echo "  get logs for previous $cname"
    kubectl -n $ns logs $pname -c $cname -p >"$pname-$cname-previous".log 2>&1
  done
done


```
[UE4]ParticleのEmitterに設定されたMaterialに動的にパラメーターを渡す方法

#【概要】
ParticleのEmitterに設定されたMaterialに、動的にパラメーターを渡したい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601695/7e7669d0-bc9c-a12e-208e-072e7fd9c9db.png)

Materialには`ColorParam`というVectorパラメーターを作成した。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601695/d6a6fde9-e443-37e1-8f7a-4e4cb52bd622.png)

#【実装】
StaticMeshComponentなどで行うのと同じように、DynamicMaterialInstanceを作って、それに対してパラメーターを渡すだけで上手くいった。
Emitterが複数ある場合は、ElementIndexにEmitterの番号を指定する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601695/ba14f922-95ed-f6cb-b58f-0a4ef253582c.png)

無事赤くなった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601695/d40d1689-b71c-077b-dcef-a4843f95aa1c.png)

#【まとめ】
StaticMeshComponentと同じ方法で出来て、意外に楽に実装出来た。
「オブジェクト名の変更」でアップロード済み画像のサムネイル生成を簡単に

## クラウドファンクションでサムネイル生成

FirebaseのCloud Storageに画像をアップロードして、サムネイルをCloud Functionsで生成しているケースは多いと思います。
[公式のサンプル](https://github.com/firebase/functions-samples/blob/master/generate-thumbnail/functions/index.js)でもCloud StorageのonFinalizeをトリガーにして、サムネイルを生成していますよね。
ただし、途中からサムネイルを生成するようになった、サムネイルのサイズを増やしたいなどのパターンでは、新規のクラウドファンクションを作成しても、すでにアップロードされた画像はonFinalizeのトリガーが発生せずに、サムネイルが生成されません。
そのため、他の方法を考える必要があります。

## 前提条件

今回この記事で参考になりそうな方はこのような条件です。

- Cloud FunctionsのonFinalizeトリガーでサムネイルを生成している。
- すでにアップロード済みの画像に対してサムネイル生成したい。
- 簡単な実装でonFinalizeトリガーを発生させたい。
- node.jsでスクリプトを書いて全ファイルに対して一括処理させたい。

## ファイルをローカルにダウンロードしてアップロードしなおす（没案）

没案なので、読み飛ばしてもらって構いません。
当初は、画像をローカルの一時フォルダに格納し、それを同じ場所にアップロードし直せばonFinalizeトリガーが発生するので良いのではと考えていました。

### 没案となった実装内容
アップロード処理に関してはコミット履歴に残っていなかったのでTODOコメントとしました。
１行でかける処理だと思います。

```js
// Storageから取得した画像パスに対する処理
imagePaths.forEach((imagePath) => {
    // 一時ディレクトリにdownloadディレクトリを作成する
    const downloadPath = os.tmpdir() + '/download/'

    // downloadディレクトリにStorageから取得した画像のパスを結合して、ローカル上の一時的なファイルパスとする
    const tempFilePath = downloadPath + imagePath;

    // storageから画像をローカルに保存する
    await bucket.file(imagePath).download({destination: tempFilePath});

    // TODO: アップロード処理
}
```

もちろんこれでも実現できますし、そんなに実装量も気にするほどではありませんが、デメリットも考えられます。

### デメリット

- 自分のPCのローカルストレージに一時的にファイルを置くため、ストレージ容量が足りないなどの問題が発生する可能性がある。
- ダウンロードしてアップロードしなおす時のファイルパスが完全に一致するか検証しなければならない。

そして何よりもっとシンプルに書く方法はないかと辿り着いた結果が採用案になります。

## オブジェクト名を変更する（採用案）

### Cloud StorageのonFinalizeトリガーについて

Cloud StorageのonFinalizeトリガーは、バケットで新しいオブジェクト（または既存オブジェクトの新しい世代）が正常に作成された場合に送信されます。既存のオブジェクトのコピーまたは書き換えを行った場合にも送信されます。アップロードが失敗した場合、このイベントはトリガーされません。

[Cloud Storageのトリガー](https://firebase.google.com/docs/functions/gcp-storage-events?hl=ja)

### 既存のオブジェクトの名前を変更

「既存のオブジェクトのコピーまたは書き換えを行った場合」がポイントです。
オブジェクト名の変更を行うことでonFinalizeトリガーが動くのではないかという予想が立ちました。
ただし、オブジェクト名は変更しますが、違う名前に書き換えてしまうと参照先のパスも変わってしまうので同じ名称に変更しなければなりません。
同じ名称にしたときに、オブジェクト名の変更として扱ってくれるかというのはポイントでしたが、問題ありませんでした。

[オブジェクトの名前変更、コピー、移動についての公式ドキュメントはこちら](https://cloud.google.com/storage/docs/renaming-copying-moving-objects?hl=ja)

### 採用した実装内容

```js
imagePaths.forEach((imagePath) => {
    await file.move(imagePath);
}
```

はい、すごくシンプルな実装にすることができました。
画像パスの面倒な結合処理などもなくなりましたし、ダウンロード => アップロードといった手順を踏まず、ファイルに対してmoveとすれば良いだけです。
ローカルのストレージを使用することもないので、容量を気にする必要もありません。
こちらを実行するとオブジェクト名の変更が行われ、onFinalizeが呼び出されました。
それによってアップロード済みの画像のサムネイルも生成することができました。

## 最後に
これに辿り着けたのは弊社内でペアプロを実施したのが大きかったです。
もともと前任の方のソースコードを引き継いでいて、アップロードからダウンロード処理するものだと思い込んでいたんですが、すごくシンプルな案にまとめることができました。
jazzyのエラーが解決できない人向けの記事( could not successfully run `xcodebuild`. Please check the build arguments. Failed to generate documentation)

検索でヒットする記事を見ても解決できなかったので備忘録として、そして同じエラーを繰り返さないために記事を残しておきます。
※間違っていたらご指摘お願い致します。

#エラー内容
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409860/02e1523f-633b-5a0a-431b-3a8f65ec9fe5.png)
スクリーンショット 2021-02-28 11.50.59


#エラー原因
色々試した結果アプリがビルド可能な状態でないと、jazzyもドキュメント化できないようです。


#参考サイト
・メインで役立った記事 https://dev.classmethod.jp/articles/generate-documentation-using-jazzy/
・ドキュメントの書き方 https://qiita.com/Qiita/items/c686397e4a0f4f11683d
・jazzyのインストール方法 https://qiita.com/satoshi-baba-0823/items/826d38bc72230e4b5f6a
・見ておくと役に立つかもしれない記事 https://qiita.com/uhooi/items/d900c2de03e9d9f39b95
マイグレーションファイルを一括でロールバックする rails db:rollback

# 動機
何個か前のマイグレーションファイルまで遡りたいときにrails db:rollbackを何度も入力するのが面倒！
そう思ったので、解決策をサクッとまとめました。

# STEP数を指定してロールバック
戻る数を指定してロールバックする方法

```
rails db:rollback STEP=ステップ数
```

# drop、create、migrate全てやてくれる
```
rails db:migrate:reset
```
# drop、create、schema.rbから復帰させる
```
rails db:reset
```

# 以上
短くなってしまいましたが、よかったら使ってみてください。
django-allauthでsignupするときにemailフィールドを表示しない方法

# 前提
認証周りにdjango-allauthを使用してるのだが、サインアップ(Signup)の際にemail入力のinputが出てくるのを消したい

# ビフォーアフター
## Before
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450257/179c19a6-f993-eaa9-2cad-bd18a884152a.png)

## After
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450257/d0342d13-491b-5a01-be88-88d31bf9e8e8.png)

# 結論
django-allauth側ではそのような設定はできなかった。
かなり時間をかけて、その設定を探したが、Emailのフィールドは消せない。
結局、django-allauthが用意しているテンプレートである`signup.html`にJavascriptを書きそのDOMをremoveすることで解決した。

# 方法
1. templates/base.htmlに自作のJavascriptが書けるようにする

```base.html
<body>
    {% include 'navbar.html' %}
    <div class="container-fluid">
        {% include 'messages.html' %}

        {% block content %}
        {% endblock content %}
    </div>

    <!-- Bootstrap JS -->
    {% include 'js.html' %}
    # ↓以下の2行を追加
    {% block myJs %} 
    {% endblock myJs %}
</body>
```

2.templatesフォルダにdjango-allauthが提供しているテンプレートをプロジェクトのフォルダに持ってくる。account/signup.htmlでjavascriptを設定

```templates/account/signup.html
{% load i18n %}
{% load bootstrap4 %}

{% block head_title %}{% trans "Signup" %}{% endblock %}

{% block content %}
<h1>{% trans "Sign Up" %}</h1>

<p>{% blocktrans %}Already have an account? Then please <a href="{{ login_url }}">sign in</a>.{% endblocktrans %}</p>

<form class="signup" id="signup_form" class="" method="post" action="{% url 'account_signup' %}">
  {% csrf_token %}
  {% bootstrap_form form layout='horizontal' %}
  {% if redirect_field_value %}
  <input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" />
  {% endif %}
  <button type="submit">{% trans "Sign Up" %} &raquo;</button>
</form>

{% endblock %}

######## この部分を追加 ############
{% block myJs %}
<script>
  forms = document.getElementsByClassName('form-group row')
  forms[1].remove()
</script>

{% endblock myJs %}
######################################
```

こうすることによってform-groupとrowクラスが付いたものの中からemailのフォームだけを取り除くことができる。

cssで`display: none;`をするよりクールだと思う笑
Java で シェルソート[Shell Sort]

## はじめに

最近プログラミングテストにハマっていて，ソートの問題があったのですが，
**シェルソート**に出会ったことがなかったので，まとめます．

## シェルソート

**シェルソート**は**挿入ソート**が改良されたアルゴリズムです．
**挿入ソート**では，隣合う要素同士で比較・交換が行われますが，**シェルソート**はn個ずつ離れた要素同士で比較・交換を行います．
n個離れた要素を整列する処理を**n-ソート**と言います．
**シェルソート**はnの値を段々と小さくして行き，最終的に n=1 となるまで比較・交換を繰り返します． n=1 となった時はほとんど整列が行われている状態で**挿入ソート**が行われるので，整列が可能となります．

## コード

今回は n = 4 とします．

``` Main.java
import java.util.*;
import java.io.*;


public class Main {
    // Main
    public static void main(String[] args) throws Exception {
        int[] numbers = new int[100];
        Random rand = new Random();

        // ソート前の表示
        System.out.println("ソート前");
        for(int i = 0; i < numbers.length; i++) {
            numbers[i] = rand.nextInt(5);
            System.out.print(numbers[i] + " ");
        }
        
        shellSort(numbers); // シェルソートの実行
        
        // ソート後の表示
        System.out.println("\nソート後");
        for(int i = 0; i < numbers.length; i++) {
            System.out.print(numbers[i] + " ");
        }
    }
    
    // シェルソート
    public static void shellSort(int[] numbers) throws Exception {
        int n = 4; // n-ソート
        int tmp; // 配列交換で一時的に保存する領域
        while (n > 0) {
            for (int i = 0; i < numbers.length; i++) {
                int j = i;
                tmp = numbers[i]; // 入れ替え元の配列の中身の保存
                // n-ソートを行う為にindex番号を進める また n個前の配列と比較して交換の必要があったら交換する．
                while ((j >= n) && (numbers[j-n] > tmp)) {
                    numbers[j] = numbers[j - n];
                    j = j - n; // n個 ずつ確認をするための処理
                }
                numbers[j] = tmp; // 最後に更新された配列の中身に，入れ替え元を入れる．
            }
            n -= 1; // n の更新
         }
    }
}
```

```　:入力
171 269 25 57 57 18 291 273 14 118 292 170 90 129 162 203 233 121 267 81 246 33 259 165 154 104 27 94 57 167 287 260 288 133 165 9 92 105 122 199 195 199 111 195 161 100 193 4 188 140 109 101 1 78 244 205 263 127 22 69 258 293 270 99 191 219 182 150 99 13 293 102 134 110 288 47 9 294 85 91 299 87 79 232 117 168 10 245 293 47 154 119 170 96 232 48 259 103 185 264 
```

``` :出力
1 4 9 9 10 13 14 18 22 25 27 33 47 47 48 57 57 57 69 78 79 81 85 87 90 91 92 94 96 99 99 100 101 102 103 104 105 109 110 111 117 118 119 121 122 127 129 133 134 140 150 154 154 161 162 165 165 167 168 170 170 171 182 185 188 191 193 195 195 199 199 203 205 219 232 232 233 244 245 246 258 259 259 260 263 264 267 269 270 273 287 288 288 291 292 293 293 293 294 299
```

## 終わりに
n によって処理速度は変わりますが，以上のコードでソートはできていそうです．
テストは行っていないので，行い次第更新したいと思います！！！
正規表現でエスケープ文字\にマッチさせる方法

文字列中の"\\"を正規表現で一致させたいとき、"\\\\"のようにバックスラッシュを2つ並べただけだと、上手くいきません。

"\\\\\\\\"という感じで、バックスラッシュを4つ並べると上手くいきます。

```Python:escape_match.py
import re

escape_regex = "\\\\"
path = r"C:\User\shinonomehakase"

escape_list = [escape for escape in re.findall(escape_regex, path)]

print(escape_list)
# output ['\\', '\\']
```

もしくは、raw文字列を使って、

```Python:escape_match.py
escape_regex = r"\\"

escape_list = [escape for escape in re.findall(escape_regex, path)]

print(escape_list)
# output ['\\', '\\']
```

とすることもできます。

参考

「&yen;マーク文字の存在チェックについて」
https://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=28495&forum=7
「re --- 正規表現操作」
https://docs.python.org/ja/3/library/re.html
Chrome拡張機能の審査に引っかかったときの解決策の一つ

Notification()でデスクトップ通知を行うために、notifications権限を要求しているのに、

違反事項: 次の権限をリクエストしているが使用していない。
notifications

と言われてしまったときの解決策

Notification()を、chrome.notifications.create()に変える。

それだけ
Laravel:標準ログイン機能実装後に既存テーブルにuser_idカラム追加する方法

# 概要
Laravelで標準Auth認証を用いてログイン機能を実装した後に、既存のテーブルにuser_idを追加する場合の方法です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308656/e4e2988d-bbf6-712f-69cd-ebdf367b67cd.png)

## 追加用のマイグレーションファイルを作成

```
//書き方
$ php artisan make:migration add_カラム名_to_追加先のテーブル名_table --table=追加先のテーブル名

//今回の場合はこんな感じ
$ php artisan make:migration add_user_id_to_memos_table --table=memos
```

実行するとアプリ名/database/migrations配下に作成したマイグレーションファイルが作成されます。

## マイグレーションファイルを編集
出来上がったマイグレーションファイルを見ると↓↓↓な感じのが出来上がっている

```2021_03_02_131812_add_user_id_to_memos_table.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class AddUserIdToMemosTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('memos', function (Blueprint $table) {
            //

        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('memos', function (Blueprint $table) {
            //
        });
    }
}
```

ここからUPの部分にuser_idを追加します。
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

```2021_03_02_131812_add_user_id_to_memos_table.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class AddUserIdToMemosTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('memos', function (Blueprint $table) {
            $table->bigInteger('user_id')->unsigned();
            $table->foreign('user_id')
                ->references('id')->on('users')
                ->onDelete('cascade');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('memos', function (Blueprint $table) {
            //
        });
    }
}
```


１）user_idのデータ型をUsersテーブルのidのデータ型と合わせる
→データ型はbigIntなので、bigIntegerで指定します。
※合ってないとマイグレーションコマンドを実行した時にエラーになります
→unsignedは符号なしということ（整数のみで-1とかは登録できないようにするということ）

２）この時に外部キー(userテーブルのidと紐づけること)の設定も行う
→foreignメソッドやreferencesメソッドを用いる
→userが削除された時にmemosテーブルに紐づいているデータも一緒に削除されるようにonDeleteメソッドも用いる

## マイグレーションを実行
下記のコマンドを実行するとmemosテーブルにカラムが追加されます。

```
$ php artisan migrate
```

# 各モデルにリレーションを設定する
## Userモデル
Userは複数のmemoのデータを持つので、1対多の関係になります。
なのでUserモデルにhasManyの記述をします。（※Mが大文字なので注意）

```User.php

<?php

namespace App;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

class User extends Authenticatable
{
              {中略}

    public function memos(){
        return $this->hasMany('App\Memo');
    }
}
```

## Memoモデル
Memoテーブルは１つのmemoに対して1人のUserのデータを持つので、
なのでMemoモデルにbelongToの記述をします。（※Tが大文字なので注意）

```Memo.php

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Memo extends Model
{
              {中略}

  public function User(){
    return $this->belongsTo('App\User');
  }
}
```


以上となります。
VSCode 選択テキスト 大文字・小文字変換 キーボードショートカット

# 環境
- Win10Home
- VSCode1.53.2

# 手順
## キーボードショートカット設定を開く
![Image 2021-03-03 14.38.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149342/b839a5e7-ca85-c88c-eeac-2ab3e68a3395.png)

## ショートカットコマンドを設定
![Image 2021-03-03 14.45.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149342/20ec8a62-de5c-a610-65d4-809b02f1c2e7.png)

- コマンド検索窓に「editor.action.transformTo」と入力すると、お目当ての変換コマンドが探せる（現在使える変換コマンドは4つだった
- 鉛筆アイコンから、直接ショートカットを登録できる

## すでにそのコマンドは使用されていると怒られる
- が、↓大抵もうDefaultで使用されていて、アラートが出る（そのコマンドすでに使われてるよ！

![Image 2021-03-03 14.49.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149342/2f0e6046-57c2-3513-75d2-cce98f1cfb97.png)

## なので、ショートカットコマンドを利用する条件定義をする

![Image 2021-03-03 14.45.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149342/5d994b77-dc50-c25c-f558-3d321e706c51.png)

- 先のショートカット一覧右上のファイルアイコンをクリック
- keybindings.jsonが開くので、自分のための設定を記述

![keybindings.json - test - Visual Studio Code 2021-.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149342/2e115cd9-d6bf-1f84-b27c-d2da140c52c2.png)


```json
// Place your key bindings in this file to override the defaults
[
  {
    //A->a
    "key": "ctrl+u",
    "command": "editor.action.transformToLowercase",
    "when": "editorHasSelection && editorTextFocus"
  },
  {
    //a->A
    "key": "ctrl+shift+u",
    "command": "editor.action.transformToUppercase",
    "when": "editorHasSelection && editorTextFocus"
  },
  {
    //ApplePie->apple_pie
    "key": "ctrl+shift+s",
    "command": "editor.action.transformToSnakecase",
    "when": "editorHasSelection && editorTextFocus"
  },
  {
    //apple->Apple
    "key": "ctrl+shift+t",
    "command": "editor.action.transformToTitlecase",
    "when": "editorHasSelection && editorTextFocus"
  }
]
```
- `"when": `のところが条件の記述
    - この場合は、「範囲選択が行われていること」（editorHasSelection）と「エディタにフォーカスがあること」（editorTextFocus）
- 記述したら 保存して終了でショートカット使えるようになる

# お世話になった記事 :bow::bow:
- VS Codeで選択範囲のテキストの大文字／小文字を切り替えるには：Visual Studio Code TIPS - ＠IT https://www.atmarkit.co.jp/ait/articles/1808/24/news030.html
- VSCodeでキーバインドを設定する。keybindings.jsonが無い時の対処法 - Qiita https://qiita.com/keitean/items/04727aeb673d1822107e
漸化式 - 例題１

# 漸化式

- [漸化式 - 例題１](/bobchin/items/1cf180e9c6abe948c945)
- [漸化式 - 例題２](/bobchin/items/cf1e6eb7b96e09ddcc72)
- [漸化式 - 例題３](/bobchin/items/6b4abfd5a735008aebff)
- [漸化式 - 例題４](/bobchin/items/4abc2b2d4a9185d768d7)

### [1.等差型](/bobchin/items/1cf180e9c6abe948c945#1%E7%AD%89%E5%B7%AE%E5%9E%8B-1)
### [2.等比型](/bobchin/items/1cf180e9c6abe948c945#2%E7%AD%89%E6%AF%94%E5%9E%8B-1)
### [3.階差型](/bobchin/items/1cf180e9c6abe948c945#3%E9%9A%8E%E5%B7%AE%E5%9E%8B-1)
### [4.特殊解型](/bobchin/items/cf1e6eb7b96e09ddcc72#4%E7%89%B9%E6%AE%8A%E8%A7%A3%E5%9E%8B)
### [5.指数型](/bobchin/items/cf1e6eb7b96e09ddcc72#5%E6%8C%87%E6%95%B0%E5%9E%8B)
### [6.Ｎ次式型](/bobchin/items/cf1e6eb7b96e09ddcc72#6%EF%BD%8E%E6%AC%A1%E5%BC%8F%E5%9E%8B)
### [7.階比型](/bobchin/items/6b4abfd5a735008aebff#7%E9%9A%8E%E6%AF%94%E5%9E%8B)
### [8.次数相異型](/bobchin/items/6b4abfd5a735008aebff#8%E6%AC%A1%E6%95%B0%E7%9B%B8%E7%95%B0%E5%9E%8B)
### [9.分数型](/bobchin/items/6b4abfd5a735008aebff#9%E5%88%86%E6%95%B0%E5%9E%8B)
### [10. Snを含む漸化式](https://qiita.com/bobchin/items/4abc2b2d4a9185d768d7#10-sn%E3%82%92%E5%90%AB%E3%82%80%E6%BC%B8%E5%8C%96%E5%BC%8F)
### []()
### []()


# 漸化式 - 例題１

## 1.等差型

```math
ex)　a_{n+1} = a_n + 3, a_1 = 2 \\
\begin{array}{l} \\
a_n &= 2 + (n - 1) \cdot 3 \\
    &= 3n - 1 \\
\end{array} \\
```

- [wolframalphaで確認](https://www.wolframalpha.com/input/?i=a%28n%2B1%29%3Da%28n%29%2B3%2Ca%281%29%3D2&lang=ja)

## 2.等比型

```math
ex)　a_{n+1} = 2 a_n, a_1 = 5 \\
\begin{array}{l} \\
\\
a_n = 5 \cdot 2^{n - 1} \\
\end{array} \\
```

- [wolframalphaで確認](https://www.wolframalpha.com/input/?i=a%28n%2B1%29%3D2a%28n%29%2Ca%281%29%3D5&lang=ja)

## 3.階差型

```math
ex)　a_{n+1} = a_n + 2n - 1, a_1 = 4 \\
\begin{array}{l} \\
a_n \ge 2 のとき\\
a_n = 4 + \sum_{k=1}^{n-1}(2k-1) \\
= 4 + 2\sum_{k=1}^{n-1}k - \sum_{k=1}^{n-1}1 \\
= 4 + 2(\frac{n(n-1)}{2}) - (n-1) \\
= n^2 - 2n + 5\\
\\
これはn = 1 でも成り立つので、\\
a_n = n^2 - 2n + 5\\
\end{array} \\
```

- [wolframalphaで確認](https://www.wolframalpha.com/input/?i=a%28n%2B1%29%3Da%28n%29+%2B+2n+-+1%2Ca%281%29%3D4&lang=ja)
Node.js で Synology の WebDAV にアクセスする

ライブラリーのインストール

```bash
sudo npm install -g webdav
```

フォルダーの一覧

```js:webdav_list.js
#! /usr/bin/node
//
//	webdav_list.js
//
//						Mar/03/2021
// ---------------------------------------------------------------
const { createClient } = require("webdav")

const client = createClient(
	"https://example.synology.me:5006/",
	{
		username: "scott",
		password: "secret"
	}
)


// ---------------------------------------------------------------
async function webdevListfile (folder)
{
	const directoryItems = await client.getDirectoryContents(folder)

	console.log(directoryItems)
}

// ---------------------------------------------------------------
const folder = "/homes/scott/tmp"
webdevListfile(folder)
// ---------------------------------------------------------------
```

実行スクリプト

```bash
export NODE_PATH=/usr/lib/node_modules
#
./webdav_list.js
```

ファイルのアップロード

```js:webdav_put.js
#! /usr/bin/node
//
//	webdav_put.js
//
//						Mar/03/2021
// ---------------------------------------------------------------
var fs = require("fs")
// ---------------------------------------------------------------
const { createClient } = require("webdav");

const client = createClient(
	"https://example.synology.me:5006/",
	{
		username: "scott",
		password: "secret"
	}
);


// ---------------------------------------------------------------
async function webdevPutfile (file_in, file_out)
{
	const str = fs.readFileSync (file_in,'utf8')

	await client.putFileContents(file_out, str)
}

// ---------------------------------------------------------------
const file_in = "./tmp01.txt"
const file_out = "/homes/scott/tmp/tmp01.txt"

webdevPutfile(file_in,file_out)
// ---------------------------------------------------------------
```

実行スクリプト

```bash
export NODE_PATH=/usr/lib/node_modules
#
./webdav_put.js
```

ファイルのダウンロード

```js:webdav_get.js
#! /usr/bin/node
//
//	webdav_get.js
//
//						Mar/03/2021
// ---------------------------------------------------------------
var fs = require("fs")
// ---------------------------------------------------------------
const { createClient } = require("webdav");

const client = createClient(
	"https://example.synology.me:5006/",
	{
		username: "scott",
		password: "secret"
	}
);


// ---------------------------------------------------------------
async function webdevGetfile (file_in, file_out)
{
	const strx = await client.getFileContents(file_in, { format: "text" });

	fs.writeFile (file_out,strx, function (err)
		{
		if (err) {
			console.log("Error on write: " + err)
		} else {
			console.log("File written.")
			}
		})

}

// ---------------------------------------------------------------
const file_in = "/homes/scott/tmp/tmp02.txt"
const file_out = "./tmp02.txt"

webdevGetfile(file_in,file_out)
// ---------------------------------------------------------------
```

実行スクリプト

```bash
export NODE_PATH=/usr/lib/node_modules
#
./webdav_get.js
```
ナップサック問題を題材に、Fixstars Amplify を使って量子コンピュータを体験してみる

量子コンピュータが何なのか、あまりわかっていませんが、
[Fixstars Amplify](https://amplify.fixstars.com/) を使うと量子コンピュータの体験してみることができると知り試してみました。

チュートリアルが丁寧で、循環セールスマン問題やグラフ彩色問題を体験できました。
今回は、自分で条件を作る練習をするために、ナップサック問題を題材に選びました。

こちらの記事で、Google の OR-Tools というライブラリを使ってナップサック問題を解く方法の解説が行われていますが、今回は、同じ問題を Fixstars Amplify を使って解いてみようと思います。

https://qiita.com/ttabata/items/bcadc03004418f32f49d


## 問題
ナップサックの中の荷物の価値の最大値を求めよ。
ただし、ナップサックに入る荷物の体積の最大値は12である。

| アイテム          |  A   |  B   |  C   |  D   |  E   |
| :---------------- | :--: | :--: | :--: | :--: | :--: |
| インデックス番号 |  0   |  1   |  2   |  3   |  4   |
| 体積            |  3   |  4   |  6   |  1   |  5   |
| 価値            |  6   |  7   |  8   |  1   |  4   |


## 解き方

制約条件と目的関数を考える
制約条件は絶対に満たさなくてはならない条件で、目的関数はできるだけ満たしたい条件。

### 制約条件
この場合、ナップサックに入る荷物の体積の最大値 <= 12 というのが絶対に満たさなくてはならない条件である。

### 目的条件
価値の合計が大きければ多いほうが良いというのが目的条件になる。

## コード

これらの条件をコードに落としてく

```python
from amplify import BinaryPoly, gen_symbols, sum_poly, BinaryQuadraticModel, Solver, decode_solution
from amplify.constraint import less_equal
from amplify.client import FixstarsClient

a = [3, 4, 6, 1, 5] # 体積
c = [6, 7, 8, 1, 4] # 価値

# 変数の作成
q = gen_symbols(BinaryPoly, 5)

# 制約条件
constraint1 = less_equal(sum_poly(len(a), lambda x: q[x] * a[x]), 12)

# 目的条件 (最小化問題なので、-1倍している。)
objective = -1 * sum([j * c[i] for i, j in enumerate(q)])

k = 0.1 # ハイパーパラメータ

loss = constraint1 + k * objective
client = FixstarsClient()
client.token = 'XXXXXXXXXXXXXXXXXXXXXXX' # 無料登録で入手できるToken
client.parameters.timeout = 1000

solver = Solver(client)
result = solver.solve(loss)

for r in result:
    print(r.energy)
    print(r.values)
    print(decode_solution(q, r.values))
```

出力は、

```
-0.17
{2: 0, 4: 1, 3: 0, 0: 1, 1: 1}
[1, 1, 0, 0, 1]
```

となり、ちゃんと正解が導けました。
とても短いコードで表現できるのが面白いです。
他にもいろいろな問題を試してみようと思います。
IBM Security Verify API で ユーザーのアカウントを無効化する

# はじめに
IBM Security Verify(ISV) APIを利用して、一定期間ログインしていないユーザーを無効化する方法についてご紹介いたします。

# APIのリファレンス
APIのリファレンスは、以下のURLから確認できます。
https://<自分のテナント名＞.verify.ibm.com/developer/explorer/#

- ユーザーの取得に利用するAPIは、以下の項目になります。
- Users Management Version 2.0 

APIに関するKCのヘルプはこちらです。
https://www.ibm.com/support/knowledgecenter/ja/SSCT62/com.ibm.iamservice.doc/concepts/apis.html

# 1.IBM Security VerifyへのAPIクライアントの登録
OAuth アクセストークンを取得するために使用するクライアント ID とクライアントシークレットを準備します。
ブラウザで、IBM Security Verifyの管理画面にアクセスします。
https://<自分のテナント名＞.verify.ibm.com/ui/admin

「構成」-「API クライアント」タブを開きます。
![OTP-000002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/9799fa7c-cb28-7726-df1d-ccdece0060e8.png)
「APIクライアントの追加」をクリックします。
![OTP-000003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/47e91160-3fd1-5d26-c341-612cd77249f5.png)


アクセス件を与えるAPIとしては以下を選択して、「保存」します。
- ユーザーおよび標準グループの管理

読み込みだけであれば、ユーザーおよび標準グループの読み取り でも可能です。

![qiita (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/24a0918e-101a-c91f-659e-9e84f785b481.png)

登録したAPIクライアントを編集モードにすると、クライアントID/クライアント秘密鍵をコピーできます。


# 2.アクセストークンの取得

```
curl -X POST "https://<テナント名＞.verify.ibm.com/oidc/endpoint/default/token" --header "Content-Type: application/x-www-form-urlencoded" --data-urlencode "grant_type=client_credentials" --data-urlencode "client_id=<クライアントID>" --data-urlencode "client_secret=＜クライアント秘密鍵＞"
```
取得したアクセストークンは赤枠部分になります。
![qiita (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/e28268f3-3827-0a17-9f99-0743503435c8.png)


# 3.ユーザー一覧の取得
ユーザー一覧を取得するためには、以下のコマンドを実行します。

```
curl -i -X GET https://<テナント名＞.verify.ibm.com/v2.0/Users --header "Content-Type: application/json" --header "Authorization: Bearer <アクセストークン>"
```
レスポンスコードは200になります。
![qiita (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/01e4a156-9f9f-c3e4-c675-d7fc6fa6ff1c.png)

ユーザー情報はJSON形式で出力されます。
![qiita (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/855c4e29-1bd0-9b3d-8a19-4548692c914c.png)



# 4.特定ユーザーアカウントの無効化
ユーザーの無効化のためには、ユーザー属性の１つであるactive属性をFalseに設定します。
3の手順で確認したユーザーIDを指定して、特定ユーザーを無効化します。


```
curl -i -X PATCH https://<テナント名＞.verify.ibm.com/v2.0/Users/<ユーザーID＞ --header "Content-Type: application/scim+json" --header "Authorization: Bearer <アクセストークン>" --data-raw "{\"schemas\":[\"urn:ietf:params:scim:api:messages:2.0:PatchOp\"],\"Operations\":[{\"op\":\"replace\",\"path\":\"active\",\"value\":false}]}"
```

レスポンスコードは204になります。
![deactive (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/2f876bb5-3a74-cc4d-21c2-041592a0bed4.png)

管理画面からユーザー情報を確認すると、状況が無効となっていることが確認できます。

![deactive (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/231ccf9d-6799-b911-265c-8c2bd01b8f7d.png)

# 5.無効化されたアカウントでのログイン試行
無効化されたアカウントでログインを試行すると、「CSIAH0320E アカウントが無効になっています。管理者にお問い合わせください。」というエラーが表示されます。

![deactive (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/6dad7a70-850d-e7a8-6042-90a5cec82c4f.png)


# 最後に
IBM Security VerifyのAPIを利用してアカウントを無効化する方法についてご紹介しました。
「0から作るDeepLearning」の5章を写経した時のエラー原因

こんにちは！

今日のエラー原因を書きます。

使用した本：「０から作るDeepLearning」

#１「two_layer_net.py」の写経について
・5行目の[「common.layers」がなぜか
「ModuleNotFoundError: No module named 'common'」
とエラー表示された。

#２「train_neuralnet.py」の写経について
・6行目の「dataset.mnist」がなぜか
「ModuleNotFoundError: No module named 'dataset'」
とエラー表示された。

#エラー対策
１，２共に練習用に作ったpracticeディレクトリの中にcommonとdatesetをコピペしたら無事に直りました。


#所感
今回はネットで調べたエラー対策方法で直って安心しました。
後写しているときに目がいかれそう。
Google Chromeでfont-sizeを10px以下にする方法

#概要
先日、Webサイトを作成していた際に、font-sizeを10px以下にしようとしたところ、数値を10px以下に設定してもブラウザに適用されませんでした(ブラウザは、Google Chromeを使用)。
調べた結果、解決策が分かったので、今回は、Google Chromeでfont-sizeが10px以下にならない時の解決方法を紹介します。

##目次
- 事前知識
- font-sizeを10px以下にする方法
- 最後に...

##事前知識
>Google Chromeでは、CSSでfont-sizeを10px以下に設定しても、ブラウザ上で10px以下にはならない。

##font-sizeを10px以下にする方法

```html:HTML例文
<p class="small">文字サイズ9px</p>
```

```css:CSS例文
.small{
  -webkit-transform: scale(0.9);
  -webkit-transform-origin:0 0;
}
```

「-webkit-transform」を使って、要素を90%の大きさに縮小します。
「-webkit-transform」のみを指定すると、縮小の基準点が要素の真ん中になってしまうので上下左右に余白が空くことになります。
その為、状況に合わせて、臨機応変に対応する必要があります。
今回は、「-webkit-transform-origin」を使って、縮小の基準点を左上(0,0)に設定しています。

>補足
・「transform」は、要素の移動、拡大縮小、回転などを制御できます。
・「-webkit-」を使用した場合、safariにも効いてしまうので、他のブラウザには、効かせたくない場合は注意が必要です。

###最後に...
今回は、Google Chromeでfont-sizeを10px以下にする方法を紹介しました。

最後まで、読んでいただきありがとうございました。
環境構築　2　Homebrew

#環境構築
###Catalina以降の方の環境構築です。


**Mojave以前の方は、こちらのURLを確認。**
https://qiita.com/mtakahashi11/items/c5e3a28cd5edcb0dd2aa

以下をターミナルに入力する。

```
% chsh -s /bin/zsh

% echo $SHELL

以下のように表示されれば成功
/bin/zsh
```

##1. Command Line Toolsをインストール

```
% xcode-select --install

```

進めていきインストールする。

##2. Homebrewの用意
**M1モデルのMacを使用されている方は手順が違いますのでお気をつけ下さい。**
####2-1. Homebrewをインストール

```
% cd  # ホームディレクトリに移動
% pwd  # ホームディレクトリにいるかどうか確認
% /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" # コマンドを実行
```

鍵マークがでたらPCのパスワードを入力しましょう。

Press RETERN to continue or any other key to abortが表示されたら、エンターキーを押します。
####2-2. Homebrewがインストールされているか確認

```
% brew -v
```

以下のように、Homebrewのバージョン情報が表示されればOKです。
**下は入力結果です**

```
Homebrew 2.5.1 # 数字は異なる場合があります。
```

####2-3. Homebrewをアップデート
以下のコマンドで最新状態にします。

```
% brew update
```

####2-4. Homebrewの権限を変更
以下のコマンドで権限を変更

```
%  sudo chown -R `whoami`:admin /usr/local/bin
```
再度パスワードを入力し、コマンドが入力できるようになれば終了です。
作成したアプリケーションのルーティングの解説

![スクリーンショット 2021-03-03 午後1.20.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636843/1df62577-6a6f-1f94-0b23-70b13eb0bb6f.png)

作成したアプリケーションのルーティングを復習のため解説していこうと思います。

そもそもルーティングとは・・・Webアプリケーションを実行するためのリクエストを受け付ける場所です。ルーティングが起点になってどんなアクションを返すか、どのページを表示するかそれらの窓口になります。


では早速自分のルーティング解説に行きたいと思います。

## root 'static_pages#home'
・root・・・自分のアプリケーションの最初に出てくる画面をrootとして設定することができる。
ルートにはパスを選択する必要がないので次から書いている左にあるパスを指定するものがありません。
'static_pages#home'　この部分でstatic_pagesアクションし、homeコントローラーで処理が行われることを表しています。

## post  '/guest_sessions', to: 'guest_sessions#create'
・post・・・何か作成をしたりするためのアクション。postは投稿と言えるので"~を投稿しますよ"と覚えています。
'/guest_sessions'　ルート以下のパスを'/guest_sessions'　だよと指定して、to:は"方向を指し示したりするので"　'/guest_sessions'の時は'guest_sessions#create'　ここで処理するよみたいな感じです。

## get '/signup', to:'users#new'
・get・・・　表示するアクション。 getは取得するなので"取得したものを表示する"と覚えています。

## delete '/logout', to:'sessions#destroy'
delete・・・これは直感的に削除する時に使うものだとわかるようにしています。


## resources 
index, show, get, edit, update, new, create, deleteアクションの７つをまとめて作ります。

```
resources :posts do
  resource :favorite 
end 
``` 


```
        favorites         GET    /favorites(.:format)                                                                  favorites#index
        new_post_favorite GET    /posts/:post_id/favorite/new(.:format)                                                   favorites#new
       edit_post_favorite GET    /posts/:post_id/favorite/edit(.:format)                                                  favorites#edit
            post_favorite GET    /posts/:post_id/favorite(.:format)                                                       favorites#show
                          PATCH  /posts/:post_id/favorite(.:format)                                                       favorites#update
                          PUT    /posts/:post_id/favorite(.:format)                                                       favorites#update
                          DELETE /posts/:post_id/favorite(.:format)                                                       favorites#destroy
                          POST   /posts/:post_id/favorite(.:format)                                                       favorites#create
```

これらはネストしたルーティングです。

ネストについて、、、

https://qiita.com/kouhei_matuura/items/16b77a25cf53d7ff232a

postsのfavoriteでアクションを作るよ〜ってイメージで覚えています。
これらが生成されますが使っているのは3つだけなのでもっと良い書き方があるのかも知れません、変更していくと思います。

## member

resources :users で7つのアクションが作られるんですがそれ以外のアクションを作りたいとなった時にこのmemberを使います。これでusersのfollowingとfollowersアクションが作られました。

memberを使うのかcollectionを使うのかは
こちらがわかりやすいかなと思います。

https://qiita.com/hirokihello/items/fa82863ab10a3052d2ff


```
resources :users do
  member do
    get :following, :followers
  end
end
```

ちなみに書き方が違うだけでcollection doともかけると思います。

```
resource :posts do
  get :favorites, on: :collection
end
```


## Only
only・・・7つのアクションのうちアクションを指定する書き方です。パスは規定に沿って生成されます。
createとdestroyアクションを作るのですがネストしてpostのとした方がいいかもと思っています。
間違ってはいないし、動くけどあんまりよろしくないかもと今は思っていますかね。


```
resources :relationships, only:[:create, :destroy]
resources :comments, only: [:create, :destroy]
resources :notifications, only: :index
```


自分で作ったアプリのルーティングの解説をしました。
もし間違えがありましたら教えてください。