OmniAICreator/Qiita-1.07M huggingface dataset:
【Vue.js】Vue.jsとcssアニメーションで作るスライドショー

`Vue.js`と`CSS`を用いてスライドショーを実装するメモです。
##目的
![スライド画像.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346455/850acc31-c749-0caa-bf1c-8d5a5954ad80.gif)
上記のようなシンプルなスライドショーを実装します。

##実装
###テンプレート

```vue:Imageslide.vue
<template>
  <div>
    <transition-group tag="ul" class="images">
      <li
        v-for="(image, index) in demoimages"
        v-show="currentImage == index + 1"
        :key="index"
      >
        <img :src="image.image" alt="" />
      </li>
    </transition-group>
  </div>
</template>
```
画像を`v-for`でリストして`v-show`で表示を切り替えています。
`v-show`は`v-if`とは違い、DOMを消したり追加したりはせず、`display:none`を付与して要素を非表示にします。そのため非表示の画像をもう一度表示する場合も、再度画像が読み込まれるわけではありません。

###スクリプト

```vue:Imageslide.vue
<script>
export default {
  data() {
    return {
      currentImage: 1,
    }
  },
  computed: {
    demoimages() {
      return [
        { image: '/images/1.jpg' },
        { image: '/images/2.jpg' },
        { image: '/images/3.jpg' },
      ]
    },
  },
  watch: {
    currentImage() {
      this.autoSlide()
    },
  },
  mounted() {
    this.autoSlide()
  },
  methods: {
    async autoSlide() {
      const wait = (ms) =>
        new Promise((resolve) => setTimeout(() => resolve(), ms))
      await wait(2000)
      if (this.currentImage > this.images.length - 1) {
        this.currentImage = 1
      } else {
        this.currentImage++
      }
    },
  },
}
</script>
```
表示されている画像のインデックスを示す`currentImage`をウォッチして`autoSlide()`を実行しています。currentImageが画像のリストを超えた場合に初期化することで無限ループになります。

###スタイル

```vue:Imageslide.vue
<style lang="scss" scoped>
.images {
  width: 100%;
  height: 100%;
  padding: 0;
  margin: 0;
  position: relative;
  li {
    width: 100%;
    height: 100%;
    max-height: 627px;
    position: absolute;
    top: 0;
    left: 0;
  }
}
img {
  width: 100%;
  height: 100%;
  max-height: 627px;
  margin: auto;
  z-index: 2;
}
.v-enter-active,
.v-leave-active {
  transition: opacity 0.5s;
}

.v-enter,
.v-leave-to {
  opacity: 0;
}
</style>
```
リストの親要素に`position:relative`を指定し、子要素に`position:absolute top:0 left:0`を指定することで同じ位置に画像を重ねることができます。
`.v-enter-active,.v-leave-active,.v-enter,.v-leave-to`は`transition`によってVueから自動的に付与されるクラスです。
##まとめ
Vue.jsとCSSを使用したスライドショーの実装方法について簡単に説明してみました。私はこのように実装しましたが、おそらく別の方法もあるかと思います。いろいろ試してみてください！
一時表領域（Temp表領域）についての私的まとめ

#一時表領域（Temp表領域）とは
一時セグメントと呼ばれる作業用のディスク領域を格納する表領域のこと。
ソート処理などで、処理に必要な一時的な作業領域がメモリ上に確保出来なかった場合に一時セグメントが割り当てられる。

DBCAでデータベースを作成すると、デフォルトで「TEMP」という名の表領域が作成される

以下で表領域の使用率を確認。この環境では容量が20480KB(=約20MB）。

```
SQL> SELECT dt.file_name, dt.tablespace_name,
  2  to_char(dt.bytes / 1024, '99999990.000') file_kbytes,
  3  to_char(t.bytes_cached / 1024, '99999990.000') used_kbytes,
  4  to_char(t.bytes_cached / dt.bytes * 100, '990.00') || '%' capacity
  5  FROM sys.dba_temp_files dt, v$temp_extent_pool t, v$tempfile v
  6  WHERE t.file_id(+)= dt.file_id AND dt.file_id = v.file#;

FILE_NAME                                TABLESPACE FILE_KBYTES     USED_KBYTE CAPACITY
---------------------------------------- ---------- -------------- ---------- ----------
C:\APP\AIMER\ORADATA\ORA12201\TEMP01.DBF TEMP     　 20480.000       13312.000   65.00%
                                                                               
```

#一時ファイル
一時表領域は、一時ファイル（一時データファイル）という特殊なデータファイルで構成される。v$tempfileで確認可能

```
SQL> col name for a40
SQL> select name,bytes,status from v$tempfile;

NAME                                          BYTES STATUS
---------------------------------------- ---------- --------------
C:\APP\AIMER\ORADATA\ORA12201\TEMP01.DBF   20971520 ONLINE
```


#一時表領域の拡張
一時ファイルを拡張することで、一時表領域の容量の拡張が可能。
ALTER DATABASE TEMPFILE文を利用する

```
SQL> alter database tempfile 'C:\APP\AIMER\ORADATA\ORA12201\TEMP01.DBF' resize 30M;

データベースが変更されました。

SQL>  select name,bytes,status from v$tempfile;

NAME                                          BYTES STATUS
---------------------------------------- ---------- --------------
C:\APP\AIMER\ORADATA\ORA12201\TEMP01.DBF   31457280 ONLINE

```

#一時ファイルのサイズ上限
一時ファイルのサイズには、データブロックのサイズなどに応じたサイズの上限がある。
たとえばsmallfile表領域を使用しており、データブロックが8KBの場合、
一時ファイルのサイズは約32GBが上限となる。

上限を超えた値を指定すると、エラーになる。

```
SQL> alter database tempfile 'C:\APP\AIMER\ORADATA\ORA12201\TEMP01.DBF' resize 40G;
alter database tempfile 'C:\APP\AIMER\ORADATA\ORA12201\TEMP01.DBF' resize 40G
*
行1でエラーが発生しました。:
ORA-01144: ファイル・サイズ(5242880ブロック)が最大値4194303ブロックを超えています。

```

・Oracle® Databaseリファレンス
12c リリース1 (12.1)　A.2 物理データベースの制限
https://docs.oracle.com/cd/E57425_01/121/REFRN/GUID-939CB455-783E-458A-A2E8-81172B990FE9.htm

#一時表領域の追加
CREATE TEMPORARY TABLESPACE文で、一時表領域の追加が可能（CREATE TABLESPACEシステム権限が必要）。
このとき、一時ファイルも新規作成される。

```

SQL> CREATE TEMPORARY TABLESPACE temptest TEMPFILE 'C:\APP\AIMER\ORADATA\ORA12201\TEMPTEST.DBF'
  2  size 20M reuse EXTENT MANAGEMENT LOCAL;

表領域が作成されました。

SQL>  select name,bytes,status from v$tempfile;

NAME                                          BYTES STATUS
---------------------------------------- 　---------- --------------
C:\APP\AIMER\ORADATA\ORA12201\TEMP01.DBF  　 31457280 ONLINE
C:\APP\AIMER\ORADATA\ORA12201\TEMPTEST.DBF   20971520 ONLINE

```

・Oracle® Database管理者ガイド
12cリリース1 (12.1)
13.2.6.2 ローカル管理の一時表領域の作成
https://docs.oracle.com/cd/E57425_01/121/ADMIN/tspaces.htm#GUID-03CCF8D4-9DAA-451A-B9F8-836F8262B43D
v-bind:keyは並び替えるためのものじゃない

#結論

v-bind:keyはそれぞれの要素に一意なキーを与えるだけ。並べ替えはしません。
並べ替えるなら関数使って新しく作りましょう。

#例
お恥ずかしいことに、下記のようにキーに数字を与えると自動で並べ替えられると思っていました。

```vuejs

<span v-for="num in [3, 2, 1]" :key="num">
    {{ num }}
</span>

<!-- 期待したのは出力はこっち--> 
<!-- 1 2 3 -->

<!-- 実際の出力は以下になる -->
<!-- 3 2 1 -->
```
具体的な並び替え方は以下が参考になりました。
[Vue.jsのv-forでの並び順を指定したキーの値順にしたり、昇順、降順を切り替えたりする](https://www.virment.com/how-to-create-computed-v-for/)

#まとめ
keyは一意に定めるものでそれ単体で並び替えに使えるものではありません。並び替えるならcomputedプロパティなどを使って並び替えたデータを用意しましょう。

私のように変な勘違いを起こした方が路頭に迷わないためにここに残しておきます。
「HourGuard作業時間管理ソフト」をインストールしてみました。アンインストールしました。

「ストップウォッチ」アプリの代わりに、「ストップ時刻ウォッチ」（ワンクリックで時刻履歴登録）アプリを、探していたら、たどりつきました。
①おすすめの時刻履歴アプリを教えて下さい。（win版、スマホ版）
②おすすめのボイスレコーダーアプリを教えて下さい。（スマホ版）
③おすすめの時間管理ソフトを教えて下さい。（win版、スマホ版）
よろしくお願いします。



###ホームページ(NCH Software)
https://www.nchsoftware.com/timesheet/jp/index.html
###(設定)タスクの開始/停止用ホットキーを使ってみようと思います。
http://help.nchsoftware.com/help/jp/hourguard/win/shortcut.html
オプション>その他>ホットキー>現在のタスクの開始/停止用ホットキー>設定　Ctrl+/ 
###(感想)
「HourGuard作業時間管理ソフト」の窓が、常に最前面に表示されます。


#2020-11-27追加
###以下のため、無料お試し版をアンインストールしました。
(参考)Vector 新着ソフトレビュー 「HourGuard」 - 簡単な操作で作業の開始・終了時刻を記録。報告書の作成にも対応した作業時間管理ソフト
https://www.vector.co.jp/magazine/softnews/170221/n1702211_reviewer.html
「
フリーソフト版は従業員5人以下の企業で、非営利目的の用途にのみ利用することが可能。
起動時には利用規約に関するメッセージが毎回表示される。
」
jpg画像で白背景を透過

最近、twitter界隈で有名な、小林さん（@pulpxstyle）

先日投稿したツイートがかなりバズってました。

そのツイートがこちら
https://twitter.com/pulpxstyle/status/1329575674458238977?s=20

これを知ったとき、控えめに言って神かと思いました。

「Photoshopで加工した写真を背景透過で使いたいけどpngじゃないとできない！」
「でも、pngだと容量が重くて表示スピードが遅くなる、、、」


この課題を見事に解決してくれましたね。

※白いもの写真には注意です。一緒に透過する可能性があります。
色の濃い写真ならOKです。


一応、参考のソースコードがこちら。

```
<style>
  .photo_wrap{
    background-image: url("../sky.jpg");
    mix-blend-mode: multiply;
   }
</style>
```


```
  <div class="photo_wrap">
    <img src="picture.jpg" alt="白背景の写真">
  </div>
```

参考：https://twitter.com/pulpxstyle/status/1329575674458238977?s=20
create-react-app typescriptテンプレート指定時エラーの対処法

最新のcreate-react-appでtypescriptを指定した場合、下記エラーが発生するため私がとった対応策です

`npx create-react-app <プロジェクト名> --template typescript` 
でプロジェクト作成後 npm start すると下記エラー↓

TypeError: Cannot assign to read only property 'jsx' of object '<Object>'
＊エラー文以下省略

対応策
①srcフォルダ内にあるpackage.jsonのreact-scriptsとtypescriptのバージョンを下記内容に書き換える。
"react-scripts": "4.0.0-next.98",
"typescript": "^4.1.0",

②node_modules & package-lock.jsonを削除

③npm install 

④npm start

私はこれで対処できました！
2つのディレクトリの内容を比較するPythonスクリプト

# 動機

デジタルカメラやアクションカムなどの記録メディアを(USBメモリ,SDカードなど)のデータを別の大容量の外付けSSDにコピーして蓄積していたが、外付けSSDの残量が少なくなってきた。外付けSSDの中には重複したデータがあるようなので削除したい。重複したファイルが発生したのは、

  - 外付けSSDにコピーしたあとに、記録メディアのコピー元のファイルを消去する前に追記したのちに、再度バックアップしてしまった。
  - バックアップ作業を行ったOS環境の違いによりファイル名の大文字/小文字が変わってしまったことがあり、その際バックアップ作業済みなのかか未作業なのか誤解して2回バックアップしてしまった

といったことが原因のようだ。大文字小文字を区別せず、2つのディレクトリの内容の過不足をチェックするのは手間なので、スクリプトを書くことにした。

# ファイル置き場

  - https://github.com/nanigashi-uji/cmp_dirtree/
  - https://gitlab.com/nanigashi_uji/cmp_dirtree/

# 実行例

比較したい2つのディレクトリを引数にして実行すると、サブディレクトリごとに、ファイル、ディレクトリ、シンボリックリンク毎に
タイムスタンプとファイルサイズを比較する。同じサイズのファイルには、``filecmp.cmp(..., shallow=False)``関数で比較する。
比較の結果を示す下記の記号をファイル名の前につけて表示する。

   - 比較対象に同名のファイルがある場合には、タイムスタンプ(mtime)を表す記号(`>`,`=`,`<`)と内容の比較結果の記号(`++`,`--`,`!=`,`==`, `  `, `!!`)を結合した3バイト
  
たとえば、`===`は「タイムスタンプも内容も同じ」、`>++`は「比較対象のディレクトリにある同名ファイルよりも新しくサイズも大きい」、`=!=`は、「比較対象のディレクトリにある同名ファイルとタイムスタンプもファイルサイズも同じだが、中身(データ)は違う」という意味となる。シンボリックリンクの場合には、'=(空白2文字)'は「タイムスタンプもリンク先のパスも同じ」、'=!!'は「タイムスタンプは同じだがリンク先のパスが違う」という記号になる。

```tcsh:実行例
% ./cmp_dirtree ./data0 ./data1
### ========================================
1: ./data0
2: ./data1
### ========================================
###-----------------< M4ROOT >--------------------
1: ./data0/M4ROOT
2: ./data1/M4ROOT
### Sub directories: ---
1:  =++ : 2019/02/09 12:43:35 :          952 : CLIP
2:  =-- : 2019/02/09 12:43:35 :          476 : CLIP
1:  === : 2019/02/09 12:43:35 :           68 : GENERAL
2:  === : 2019/02/09 12:43:35 :           68 : GENERAL
(途中略)
### File lists: ---
1:  >== : 2019/11/05 03:47:45 :         6148 : .DS_Store
2:  <== : 2019/11/05 01:10:13 :         6148 : .DS_Store
1:  >++ : 2019/11/02 19:09:34 :         5122 : MEDIAPRO.XML
2:  <-- : 2019/07/01 19:07:35 :         2595 : MEDIAPRO.XML
1:  >== : 2019/11/02 19:09:34 :            7 : STATUS.BIN
2:  <== : 2019/07/01 19:07:35 :            7 : STATUS.BIN
###-----------------< M4ROOT/CLIP >--------------------
1: ./data0/M4ROOT/CLIP
2: ./data1/M4ROOT/CLIP
### File lists: ---
1:  === : 2019/02/09 14:53:23 :   1878686635 : C0001.MP4
2:  === : 2019/02/09 14:53:23 :   1878686635 : C0001.MP4
1:  === : 2019/02/09 14:53:23 :         2008 : C0001M01.XML
2:  === : 2019/02/09 14:53:23 :         2008 : C0001M01.XML
(途中略)
1:  === : 2019/07/01 19:07:35 :   7627022896 : C0006.MP4
2:  === : 2019/07/01 19:07:35 :   7627022896 : C0006.MP4
1:  === : 2019/07/01 19:07:35 :         2009 : C0006M01.XML
2:  === : 2019/07/01 19:07:35 :         2009 : C0006M01.XML
1:      : 2019/07/28 14:15:53 :  15709053750 : C0007.MP4
2: !    : ~~
1:      : 2019/07/28 14:15:53 :         2008 : C0007M01.XML
2: !    : ~~
(以下略)
```
比較するディレクトリ、ファイル数が多い場合には、` ./cmp_dirtree ./data0 ./data1 | grep -e ' .== ' `といった方法でフィルタすると、容易に重複するファイルを見つけられるようになった。
.bakを再帰的につけるバックアップスクリプト

```shell
bak() (
	for file in "$@"; do
		bakfile="$file"'.bak'
		if [ -e "$bakfile" ]; then
			echo 'already exists: '"$bakfile"
			bak "$bakfile"
		fi
		cp "$file" "$bakfile"
	done
)
```
を `~/.bashrc` などに追記すると、

```:fileA
This is A.
```
に対して

```shell
$ ls
fileA
$ bak fileA
$ ls
fileA fileA.bak
$ echo 'This is A!' > fileA # fileAの中身を This is A! に上書き
$ bak fileA
already exists: fileA.bak
$ ls
fileA fileA.bak fileA.bak.bak
```

とするとき、それぞれのファイルの中身は、

|fileA |fileA.bak|fileA.bak.bak|
|:-:|:-:|:-:|
|This is A!|This is A!|This is A.|

という調子で、より古いファイルに `.bak` がどんどんつきます。
【Rubyによるデザインパターン】コマンドパターンのメモ

#【Rubyによるデザインパターン】コマンドパターンのメモ

プログラムの設計力向上のため『Rubyによるデザインパターン』を読んでおり、気になるデザインパターンを、1つずつまとめています。

今回は、コマンドパターンについてまとめました。

## デザインパターン記事一覧
[【Rubyによるデザインパターン】テンプレートメソッドパターンのメモ - Qiita] (https://qiita.com/yuki_0920/items/07382034dfb65f0a13a0)
[【Rubyによるデザインパターン】ファクトリーメソッドパターンのメモ - Qiita](https://qiita.com/yuki_0920/items/324c5536bf4e3d085f33)
[【Rubyによるデザインパターン】ストラテジーパターンのメモ - Qiita](https://qiita.com/yuki_0920/items/87dc056952f71b88a287)
[【Rubyによるデザインパターン】コマンドパターンのメモ - Qiita](https://qiita.com/yuki_0920/items/46545085309877012201) <- 本記事
[【Rubyによるデザインパターン】オブザーバーパターンのメモ - Qiita](https://qiita.com/yuki_0920/items/64c7010844265e9e4bd2)
[【Rubyによるデザインパターン】シングルトンパターンのメモ - Qiita](https://qiita.com/yuki_0920/items/fc0b235e9956ffc6b76a)

## コマンドパターンについて
特定の動作を実行するオブジェクト(コマンドオブジェクト)を定義し、そのオブジェクトを経由して動作を実行するパターンです。

複雑なロジックを分離したいときに使えるリファクタリングのテクニックとしても有用です。
分離後にはロジックをさらに分割する、変数名を修正するなどのさらなる改善が容易になり、コードの見通しが良くできることが特徴です。


## サンプルコード
私はジム通いしているのですが、その趣味にちなんで、ジムの月あたりの維持費用を計算するプログラムを考えます。

簡易的に、維持費用は家賃と設備コストだけと仮定しています。
また、設備コストは設備のグレードから算出しています。

まずはコマンドパターン適用前からです。

```rb
class Gym
  def initialize(estate, equipment)
    @estate = estate
    @equipment = equipment
  end

  def calculate_maintenance_cost
    equipment_cost =
      case @equipment[:grade]
      when 'small'
        10
      when 'middle'
        50
      when 'high'
        100
      end

    @estate[:rent] + equipment_cost
  end
end
```

実行時はこのとおりです。
不動産(estate)や設備(equipment)は本来はクラス化したほうが良いのでしょうが、簡易的にハッシュで定義します。

```rb
estate = { name: 'サンプル不動産ビルディング', rent: 30 }
equipment = { name: 'ベンチプレスマシーン', grade: 'middle'}
gym = Gym.new(estate, equipment)
puts gym.calculate_maintenance_cost
# 80
```

現状では Gym に 1つのメソッドしか定義されていないので、見通しが悪いわけではありませんが、通常モデルにはビジネスロジックが集約され複雑化することが往々にしてあるかと思います。

そこで、 `calculate_maintenance_cost` 内のロジックにコマンドパターンを適用しオブジェクト化します。

```rb
class Gym
  def initialize(estate, equipment)
    @estate = estate
    @equipment = equipment
  end

  def calculate_maintenance_cost
    MaintenanceCostCalculater.new(@estate[:rent], @equipment[:grade]).execute
  end
end

class MaintenanceCostCalculater
  def initialize(rent, equipment_grade)
    @rent = rent
    @equipment_grade = equipment_grade
  end

  def execute
    equipment_cost =
    case @equipment_grade
    when 'small'
      10
    when 'middle'
      50
    when 'high'
      100
    end

    @rent + equipment_cost
  end
end
```

```rb
estate = { name: 'サンプル不動産ビルディング', rent: 30 }
equipment = { name: 'ベンチプレスマシーン', grade: 'middle'}
gym = Gym.new(estate, equipment)
puts gym.calculate_maintenance_cost
# 80
```

`calculate_maintenance_cost` の内容を MaintenanceCostCalculater のオブジェクトを通して実行するように修正しました。

MaintenanceCostCalculater は維持費用計算に必要な値のみを属性として持つため、シンプルなクラスです。

## コマンドオブジェクトのメソッド名
『リファクタリング 第2版』によると、コマンドオブジェクトは、 execute や call, run といったメソッド名をつけるケースが多いようです。

これを知った私は、確かに業務上でこれらのメソッド名を見かける機会多く、実は普段から触れていたアプリケーションがコマンドパターンに倣っているケースが多かったのだと気づきました。

みなさんの携わっているアプリケーションでも、これらのメソッド名が使用されていた場合、もしかしたらコマンドパターンが適用されているかもしれません。

## おわりに
コマンドパターンは特定の動作だけを担うオブジェクトを構築するパターンでした。
複雑なロジックのリファクタリングに有用なため、使いこなせるようになりたいです。
時々使いたいのにすぐ忘れてしまうエクセルのショートカットキー、アクセスキーまとめ

個人的メモです。時々追加します。

アクセスキーとは、Altを押した時に出てくるアルファベットを入力することで操作を実行できる機能のことです。

下記の表のうち、"+"は同時押し、"->"は次に押すキー、となります。

| やりたいこと | 操作 | 補足 |
| ---- | ---- | ---- |
| セルの値だけ貼り付け | Ctrl + Alt + V -> V |  |
| コメント全表示/非表示切り替え | Alt + V -> C | Office365では"メモ"という |
| 行全体選択 | Shift + Space | 半角英数字入力モードで |
| 列全体選択 | Ctrl + Space | 半角英数字入力モードで |
| 行挿入 | Ctrl + Shift + ; | 行全選択状態で |
| 行削除 | Ctrl + "-" | 行全選択状態で |
| 目盛線の非表示 | Alt -> W -> V -> G |  |
Python  Jupyter Lab (Notebook) でメモリリーク?

## 環境

- Kaggle Docker Python v86  
https://console.cloud.google.com/gcr/images/kaggle-images/GLOBAL/python

## 現象

Jupyter Labを使っていて、変数を定義したのちdelしてgc.collect()してもメモリが解放されない。

### 再現手順

1つのセルの中に以下のようなコードを書いて実行する。

``` python
import numpy as np
import pandas as pd
import psutil
print(psutil.Process().memory_info().rss / 1024**2)
df = pd.DataFrame(np.arange(50000000).reshape(-1,5))
df.head()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269702/980d3150-5849-b776-dcd1-d000cb6dd30d.png)

最後にdf.head() としていることに注意。

次のセルで

``` python
print(psutil.Process().memory_info().rss / 1024**2)
del df
print(psutil.Process().memory_info().rss / 1024**2)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269702/6a802610-7f0f-9a10-4b57-a8d100e02cb2.png)

メモリの状況はすぐに表示されないので念のためさらに次のセルでも確認

``` python
print(psutil.Process().memory_info().rss / 1024**2)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269702/e0393424-0052-7e9c-93be-48ee8acc8057.png)

※ちなみに引き続いてgc.collect()しても同じ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269702/14ea7800-1866-9710-4846-c0d2b6bec9e1.png)

## 原因

pandas.DataFrame の問題かと思ったが、そうではない。
「セル」の最後にJupyter Labの機能による出力表示を行うと、それ以後他のセルでdelしても解放されないようだ。

## 解決策

セルの最後でdf.head()しない。表示したければprintする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269702/7e33c664-7ff8-c19a-7c22-3f12bcd76653.png)

## コメント

- 地味に不安要素になる部分・挙動だけれど、きちんとJupyter 入門すると注意されていることなのだろうか（知らない）。
- 手元で調査して確認できたが、gc対象とならない理由はjupyterの画面表示機能に参照が保持されるか何かだろうか。IPythonに原因があるらしい。検索語をJupyter memory leakとすれば https://github.com/jupyter/notebook/issues/3713 が出てきて、この先に説明があるらしい（見てない）。
- 検索語をpandas memory leak とすると https://stackoverflow.com/questions/14224068/memory-leak-using-pandas-dataframe などが出てきて、迷い続ける（迷った）。
[Rails]hidden_fieldとhidden_field_tagの違いについて！[初心者]

#どういう時に使用するの？
``form_with``や``form_for``を利用して、ユーザーに何かを打ち込んでもらい、送信してもらいたい時に便利なメソッドです。

例えば、AmazonのようなECサイトで、ショッピングカートの商品を購入するとき。
ユーザーからすると、「確定ボタン」だけ押したいのに、再度``username``や``address``を打たなければならないのは面倒ですよね。
また、パラメーターを経由したいけれども、ユーザー側にその情報を隠しておきたい時などにも使えます。

#使い方
````ruby:hidden_field
hidden_field :値の取得時に使用する名前(シンボル), :value => 実際に渡す値
              #第一引数→name属性                        #第二引数→value属性
````

アクションで``hidden_field``で渡されたパラメータを受け取ることが出来ます。
ここで、controllerに記述する際に、フォームフィールドに紐づく値となっている為、記述方法は
``params[:モデル名][:渡したname属性]``
という形になるので、注意が必要です。

````ruby:hidden_field_tag
hidden_field_tag :渡したいパラメータの値, 実際に渡す値
````

#それぞれの使用タイミング
``hidden_field``
form_withやform_forで渡すインスタンスがある場合(もしくはそれらのヘルパーを使っている場合)。

``hidden_field_tag``
一個だけパラメータを他のアクションへ単体で渡したい時に、独立して使用。
【SFDC】権限に関するメモ（ロール、階層を使用したアクセス許可）

＜権限の勉強をしたのでメモ＞

前提
・ロールは、管理職と営業員の2階層
・利用者は2名。上司花子さん、部下太郎さん
・オブジェクトは2つで、参照関係
・オブジェクトは非公開、所有者ベースの制御
・プロファイルは、以下の通り。
　　（１）取引先→作成、編集、参照にチェック
　　（１）テスト→作成、編集、参照にチェック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/90fc859d-5867-0a1c-bfa5-c98aa2cdf172.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/8ef9078c-3c3d-3e5e-053c-7c9dadc517d8.png)

＜テスト①＞
・テストオブジェクトの「階層を使用したアクセス許可」はON
（１）花子が取引先と、それに紐づくテストを作成
（２）太郎が取引先と、それに紐づくテストを作成
↓見え方
・花子は（１）（２）どれも見える。
・太郎は（２）のみ見える。

＜テスト②＞
・テストオブジェクトの「階層を使用したアクセス許可」はOFF
（１）花子が取引先と、それに紐づくテストを作成
（２）太郎が取引先と、それに紐づくテストを作成
↓見え方
・花子は（１）と、（２）の取引先のみ見える。
　　→階層使用したアクセス許可をOffとしたため、テストオブジェクトがロールに従わない。
・太郎は（２）のみ見える。
CircleCIのジョブ結果をSlackに通知する

## 背景

CircleCIのジョブ結果をSlackに通知する方法が変更になったので、その方法を記載する。

## 本題

旧バージョンでは、コンソール画面からWebhookURLに値を設定するのみだったが、現在は *Orbs* を利用するようになった。必要最低限の結果を受け取るための設定を以下に記述する。少々手間だが、 *post-steps* を利用して、ジョブ実行後のステップに差し込む。

```yaml:./circleci/config.yml
version: 2.1 # post-stepsの利用のため2.1が必須

orbs:
  slack: circleci/slack@3.4.2

commands:
  notify_status:
    steps:
      - slack/status
      # カスタマイズ箇所は https://circleci.com/developer/orbs/orb/circleci/slack?version=3.4.2#commands-status から参照できる。

jobs:
 <job_name>:

workflows:
  version: 2
  workflow_name:
    jobs:
      - <job_name>:
          post-steps:
            - notify_status
```

## バージョン

2020/11/20現在では `circleci/slack@4.1.1` が最新。3.4.2との差分の注目点はテンプレートのカスタマイズ性だと思われる。[custom-message-template](https://github.com/CircleCI-Public/slack-orb/tree/v4.1.1#custom-message-template)より、 Slackのビルダーキットで作ることができる。（調査背景・用途としては、ジョブの結果とコンソールへのURLさえ分かれば良かったので、実際には使っていない。）

## 課題

旧方法で通知設定しているプロジェクトを編集する方法について見つけられなかった。

## 参考

- [Using-Slack-Integrations-with-CircleCI](https://support.circleci.com/hc/en-us/articles/360044674612-Using-Slack-Integrations-with-CircleCI)
- [CircleCIの新UIでのslack連携](https://christina04.hatenablog.com/entry/slack-integration-with-circleci-new-ui)
- [orbs/circleci/slack](https://circleci.com/developer/orbs/orb/circleci/slack)
Flaskで簡易的なドット絵ジェネレータを作る

# 完成形
以下のような感じ。
![スクリーンショット 2020-11-21 7.03.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/289055/e6886b0b-14c2-c300-3240-64e9313f244d.png)
https://flaskandheroku.herokuapp.com/

# 仕様

- トップ画面にはランダム生成されたドット絵が表示されている
- 「ランダム生成」ボタンを押下するとランダムでドット絵が表示される
- ドット絵は画像ではなく文字の「■(四角)」で構成されている
- 文字を画像へ変換する技術は実装していない
- Twitterシェアボタンを配置

# 作ろうと思った経緯
- Flaskを勉強中なので、簡単な成果物を作ってみたくなった
- 以下のようなドット絵を描くのが趣味なので、自動で生成できるようなツールを作ってみたくなった
![スクリーンショット 2020-11-21 7.14.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/289055/132899aa-040d-fb57-15e4-b36b3aba5f29.png)
https://akihanari.github.io/gif-amabie/



# 使用言語やフレームワークなど
- HTML5
- CSS3
- Bootstrap
- Python
- Flask
- Heroku



# ファイル構成
- templates
 - layout.html
 - index.hrml
- app.py
- Procfile
- requirements.txt

# 仕組み（コード）
シンプルです。

```
# app.py

@app.route('/')
def dot_gene():
    numbers = [[random.randrange(4) for i in range(8)] for j in range(8)]
    return render_template("index.html", numbers = numbers)
```

まずは@app.route('/')に、二重ループの関数を作成します。
今回は8×8のドットを作るのですが、各ドットの色が白か黒かを決めるため、
0〜3のランダムな数値を生成します。
例えばこんな感じになっています

```
11230032
31231000
30023111
12213303
01202010
32111320
01322031
00011203
```
次に、index.htmlの中で処理を行います。

```
# index.html
{% extends "layout.html" %}
      {% block content %}
        <h1>Pixel art generator</h1>
        <div class="spaces">
          {% for number in numbers %}
            {% for num in number %}
                {% if num == 0 %}
                  <font color="#000000">■</font>
                {% elif num == 1%}
                  <font color="#ededed">■</font>
                {% elif num == 2%}
                  <font color="#ededed">■</font>
                {% else %}
                  <font color="#ededed">■</font>
                {% endif %}
              {% endfor %}
              <br>
          {% endfor %}
       </div>
        .
        .
        .
{% endblock %}
```
~~コードが非常に汚くて大変申し訳ないのですが~~
作成した二重ループの数字と「■」、白か黒かを関連付けます。
今回は数字が0の時のみ黒に、それ以外の数字の場合は白（っぽい）色に変換します。
![スクリーンショット 2020-11-21 8.22.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/289055/d42ccca7-ca0e-8ae1-5cc7-69e9f4807be4.png)
そうするとこのようなドット絵が表示される訳です。


# 改善点
- スマートフォン表示だとドット絵が若干崩れてしまう
- 生成されたドット絵を画像に変換して保存できるようにしたい
- もっとドット絵らしいドット絵を生成されるようにしたい
![smartphone.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/289055/9b8ebd0f-c087-cd9a-a075-2867d66ab5b0.png)

# 参考
[paiza Flask入門編1:PythonでWebアプリケーションを作ろう ](https://paiza.jp/works/flask/primer)
VC++でCSVファイルをSQLで検索してみた

#はじめに
CSVファイル用のODBCドライバが32bit版の環境を想定する。

#環境
- Windows 10 Home (64bit)
- Visual Studio Community 2019

C++ によるデスクトップ開発
最新の v142 ビルド ツール用 C++ ATL (x86 および x64)
オプションにチェックが入っていること。

#手順
##ODBCドライバの確認
スタートメニューをクリックし、odbcと打ち込むと「ODBC Data Sources (32-bit)」が現れるので起動する。

[ドライバー]タブを選択し、一覧の中に
`Microsoft Text Driver (*.txt; *.csv)`
があることを確認する。

##プロジェクトの作成
プロジェクト テンプレート：空のプロジェクト [C++]
プロジェクト名：adotest

```adotest.cpp
#import "C:\Program Files (x86)\Common Files\System\ado\msado15.dll" \
    rename("EOF", "EndOfFile")
using namespace ADODB;

int main()
{
        HRESULT hr = CoInitialize(nullptr);

        _ConnectionPtr cn("ADODB.Connection");
        hr = cn->Open("Driver={Microsoft Text Driver (*.txt; *.csv)}; ReadOnly=1;",
                "", "", 0);

        _RecordsetPtr rs("ADODB.Recordset");
        //_RecordsetPtr rs;
        //hr = rs.CreateInstance(__uuidof(Recordset));

        hr = rs->Open("select name from [test.csv] where id=2",
                cn.GetInterfacePtr(), adOpenForwardOnly, adLockReadOnly, adCmdText);
        //rs = cn->Execute("select name from [test.csv] where id=2",
        //        nullptr, adCmdText);

        for (; !rs->EndOfFile; rs->MoveNext()) {
                _variant_t v = rs->GetCollect("name");
                printf("%S\n", v.bstrVal);
        }

        hr = rs->Close();
        hr = cn->Close();
        CoUninitialize();
}
```

エディタに警告が出る場合は[プロジェクト]→[ソリューションの再スキャン]してみる。

##データの用意
プロジェクトのディレクトリなど実行時のカレントディレクトリに置く。

```schema.ini
[test.csv]
ColNameHeader=False
Format=TabDelimited
MaxScanRows=25
CharacterSet=OEM
Col1=id Byte
Col2=name Text
```

```test.csv
1	tako
2	ika
3	manbo
2	geso
```
Doma入門 - ログライブラリにSLF4Jを使う

## はじめに

DomaはJavaの標準ライブラリ以外に依存しないことをコンセプトに謳っているので、デフォルトのログライブラリとしてJUL（java.util.logging）を使っています。ただ残念なことにJULは使いにくいということでとても不人気ですね。

この記事では、ログライブラリをJULから[SLF4J](http://www.slf4j.org/)に切り替える方法を説明します。

Domaのバージョンは現時点で最新の2.44.3を想定して説明します。
Domaの他の機能については、[Doma入門](https://qiita.com/nakamura-to/items/deaff05ba530317f3cf8)もお読みください。

## Domaのログの仕組み

Domaの実行時のログ出力は、`org.seasar.doma.jdbc.JdbcLogger`インタフェースを介して行われます。

doma-core.jarには、`org.seasar.doma.jdbc.UtilLoggingJdbcLogger`というJULを利用する実装クラスが含まれており、Domaを単体で利用する場合はこの`UtilLoggingJdbcLogger`が使われます。

他のログライブラリを使うには、別の既存実装を利用するか自前で独自実装を作成する必要があります。

## DomaのSLF4J対応

doma-slf4j.jarに、SLF4Jを使う`org.seasar.doma.jdbc.Slf4jJdbcLogger`という実装クラスがあります。JULからSLF4Jに切り替えるには`UtilLoggingJdbcLogger`の代わりに`Slf4jJdbcLogger`を使うようにすればOKです。

これら2つの実装クラスの違いですが、利用するログライブラリが異なることに加えてデフォルトのログレベルが異なります。`UtilLoggingJdbcLogger`経由で出力されるデフォルトのログレベルはINFOですが、`Slf4jJdbcLogger`のデフォルトのログレベルはDEBUGとなっています。

`Slf4jJdbcLogger`を使うにはMavenやGradleではdoma-core.jarと同じバージョンのdoma-slf4j.jarへの依存が必要です。SLF4Jにバインディングさせて他のログライブラリ（logbackなど）を使う場合は、そちらの依存設定も忘れずに。

利用例は[getting-started](https://github.com/domaframework/getting-started)を参照ください。

## Spring Bootを使う場合

Spring Bootを使っている場合でも、`Slf4jJdbcLogger`を使えさえすればログライブラリをSLF4Jに切り替えられます。

[doma-spring-boot](https://github.com/domaframework/doma-spring-boot) 1.5.0以上使っている場合、この切り替えはとても簡単でapplication.propertiesに下記のように記載するだけです。

```java:application.prpoperties
doma.jdbc-logger=SLF4J
```

なお、ログが出力されるようにするには、doma-spring-bootの利用の有無にかかわらず、Spring Bootのお作法にしたがって下記のようにログカテゴリの指定をしてください。

```java:application.prpoperties
logging.level.org.seasar.doma=DEBUG
```

## Quarkusを使う場合

Doma向けのQuarkusのExtensionである[quarkiverse-doma](https://github.com/quarkiverse/quarkiverse-doma)を使うのが簡単です。
このライブラリはデフォルトでSLF4Jを使います。

ログ出力をするには、Quarkusのお作法にしたがって次のように記載するだけです。

```java:application.prpoperties
quarkus.log.category."org.seasar.doma".level=DEBUG
```

## おわりに

DomaでログライブラリをSLF4Jに切り替える方法を説明しました。

SLF4J向けの実装を作ったのはつい最近（Doma 2.43.0から）ですが、もっと前から対応してもよかったですね。

ところで、最近ZulipというチャットサービスにDoma専用のルームを開設しました。もしDomaに関して質問などあればこのチャットルームでお気軽にどうぞ。

- https://domaframework.zulipchat.com/

## 参考情報

- [SLF4J support](https://doma.readthedocs.io/en/latest/slf4j-support/)
Mac:Thunderboltケーブル利用時の各種転送速度比較

# ２台のMacをThunderboldケーブルでつなぎ複数の転送方法の速度を比較
[Thunderboltケーブル](https://www.apple.com/jp/shop/product/MD862ZM/A/apple-thunderboltケーブル05m?fnode=91bddce0c04005e0089578b2f0d30ef9bce7a29d5c0c9923685331f39891efbbf1eb523b5409ec0a10c1c42818a7e9b461e1d2830f4e2eaf3fb002a732e181a8ccc4aa4457123ccb81c116ba4651698d05c625e34c6f913c36b81ba09ffa7348)を使って２台のMacを接続し、各種方法でデータ転送した時の速度を比較した。

## 使用したMac
- Mac mini (2014)
- MacbookAir 13inch (2017)

## 転送方法１（ネットワーク）
Thuderboltケーブルを用いて２台のMacをつなげると、自動的にLinklocalアドレス（169.254.xxx.yyy/16）が割り当てられる。システム環境設定のネットワークを参照。
![Thunderbolt.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/a6dcb2ac-5684-e890-fb96-bd51b59aaf54.png)
なお、MacではマルチキャストDNS（Bonjour）により、IPアドレスだけではなく、同じくシステム環境設定の共有で設定された「名前」で認識される（接続可能）。
![共有.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/cb0600f2-9544-de46-9ec0-6b5e701a121f.png)
ここでは、Vienna.localを使ってこのMacにアクセスすることができる。例えば、「ssh namae@Vienna.local」のような指定で、sshによるログインが可能となる。

次に、転送系プロトコルを設定する。下記、「ファイル共有」（SMB利用）と「リモートログイン」（scp利用）とにチェックをつける。
![ファイル共有＆リモートログイン.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/217f6ec7-4bf9-6db1-71a9-8a425d681ab6.png)
「ファイル共有」では、詳細でプロトコルとしてAFPを指定可能。
![共有SMB／AFP.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/4604f530-22ae-09f0-149e-81d5fa7b4c60.png)
（今回は、AFP接続がうまくできず、、、断念。）

## 転送方法２（外部ディスク）
Macには以前からターゲットディスクモードが存在し、片方のMacをもう一方のMacの外部ディスクとして扱うことが、Thuderboltケーブルを用いて実現できる（以前はFirewireケーブルが使われていた）。システム環境設定内の起動ディスクにて、ターゲットディスクモードとして起動する。
![ターゲットディスウ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/2a9b508d-5468-120a-0c2d-2a1ca0cfc8bd.png)


## 転送方法
4GBの空ファイルをddコマンドで作成し、scpコマンドやcpコマンド（SMBおよび外部ディスク）で転送する。また、timeコマンドにより転送時間を計測。下記はその例である。

```
$ dd if=/dev/zero of=./File4G bs=1048576 count=4096
$ time scp File4G namae@Vienna.local:tmp
Password:
File4G                                                                              100% 4096MB 120.9MB/s   00:33    

real	0m38.878s
user	0m24.910s
sys		0m11.585s

```

```
$ time cp File4G /Volumes/namae/tmp

real	0m22.727s
user	0m0.013s
sys		0m5.384s
```

## 結果＆考察
下記表の数値の単位は秒。

|   |scp(ssh)|SMB|外部ディスク|
|---|---|---|---|
|１回目|38.878  |21.433  |18.328 |
|２回目|40.078  |17.760  |18.037 |
|３回目|39.297  |21.365  |17.719 |
|４回目|38.381  |18.298  |17.272 |
|５回目|40.076  |22.727  |17.891 |
|**平均**　|**_39.342_**  |**_20.317_**  |**_17.849_** |

当たり前ではあるが、外部ディスクとして転送したときが最も早く、IPプロトコル（scpおよびSMB利用時）利用時のオーバーヘッドが見られる。特にscpの場合、セキュア転送でさらにオーバーヘッドがある。
VBAのVariant型の基本

# Variant型とは
VBAのVariant型は、データ型を宣言しない変数に使用するデータ型です。
Variant型の変数には、全てのデータ型を入れることができます。

# Variant型の変数には異なる型のデータを代入できる
以下の例のように、最初に変数aには数値型を代入し、次に文字列型を代入しています。このように、Variant型の変数は最初に入れたデータ型に関わらず、どのようなデータ型でも代入できます。

```vb
Option Explicit

Sub Sample()

Dim a As Variant
a = 1

'VarTypeは指定した変数のデータ型を返す関数
MsgBox VarType(a)   '2を表示。2はInteger（整数型）を表す

a = "AAA"
MsgBox VarType(a)   '8を表示。8はString（文字列型）を表す

End Sub
```

# Variant型の変数には配列を代入できる
Variant型以外の場合、配列は「変数名()」で宣言し、値を代入します。

```vb
Option Explicit

Sub Sample()

Dim list(3) As String
list(0) = "東京"
list(1) = "大阪"
list(2) = "福岡"
Range("A1").Value = list(0)
Range("A2").Value = list(1)
Range("A3").Value = list(2)

End Sub
'A1セル：東京
'B1セル：大阪
'C1セル：福岡
```
Variant型の場合、配列を「変数名()」で宣言する方法と、「変数名()」を使わずに宣言する方法があります。後者の場合、後続処理でArray関数を使用します。

```vb
Option Explicit

Sub Sample()

Dim list As Variant
list = Array("東京", "大阪", "福岡")
Range("A1").Value = list(0)
Range("A2").Value = list(1)
Range("A3").Value = list(2)

End Sub

'A1セル：東京
'B1セル：大阪
'C1セル：福岡
```

# Variant型の変数は連想配列を代入できる
連想配列とは、列と行を持っている配列のことです。
Variatn型の変数を使えば、ひとつの変数に複数範囲のセルの値をまるごと代入できます。

```vb
Option Explicit

Sub Sample()
Dim list As Variant
list = Range("A1:C3")
Range("A10:C12").Value = list

End Sub
```

もともとは以下の状態です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262601/9283aacd-cfb2-9187-43cc-042a3913baee.png)

VBAを実行すると、Variant型の変数listに入れた値が、A10～C12に代入されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262601/73176e07-9104-4dc4-9270-bffed3add144.png)
辞書の値を属性参照するメモ(車輪の再開発)

# AttrDictの方が便利だけど、ちょっと使いたいのにインストールしたくない人向け(22/10/16更新)

## 値の参照だけしたいとき
### 定義
```python
class Dict(dict):__getattr__=dict.__getitem__
```

要素の追加もできるように__setattr__を追加したバージョン。
```python
class Dict(dict):
    __getattr__ = dict.__getitem__
    __setattr__ = dict.__setitem__
```

### 使用時
```python
a = Dict(a=0, b=Dict(c=1, d=2))
(a.a, a.b.c, a["a"], a["b"]["c"])
```

## 値も設定したい
### 定義
```python
class Dict(dict):__getattr__=dict.__getitem__;__setattr__=dict.__setitem__
```
一行で書く必要はないけど。

### 使用時
```python
a = Dict()
a.b = Dict()
a.b.c = True
a.b.d = True
a.b["c"] = False
a.b.d = False
print(a)
```


## pickleで使いたいとき
### 定義
```python
class Dict(dict):
    __getattr__ = dict.__getitem__
    __setattr__ = dict.__setitem__
    
    def __getstate__(self):
        return self.__dict__.copy()

    def __setstate__(self, state):
        self.__dict__.update(state)
```
```__getstate__, __setstate__```をpickle対策のため追加

### 使用時
```python
import pickle
a = Dict(a=0, b=Dict(c=1, d=2))
a.b.e = False
(a, (a.a, a.b.c, a["a"], a["b"]["c"]), pickle.loads(pickle.dumps(a)))
```




## 番外編
式で書いてみる。特に意味はない。

```python
globals().update({"Dict": type("Dict", (dict,), dict(__getattr__=dict.__getitem__, __setattr__=dict.__setitem__))}); a=Dict(a=1, b=Dict(c=2, d=3)); a.b.e=4; a
```
Shopifyのコンバージョン率を上げる方法

eコマースビジネスの所有者として、あなたはおそらくあなたのオンラインストアに訪問者を引き付けるために必要な努力と財源の量を知っています。

この[記事](https://whidegroup.com/blog/shopify-conversion-optimization/)では、コンバージョンを殺す最も燃えているウェブサイトのデザインの問題に関する重要な情報を見つけるでしょう。また、Shopifyストアでコンバージョン率の最適化に使用されるベストプラクティスについても説明します。この記事で集中する主な質問は、Shopifyのコンバージョン率を上げる方法です。

最初のステップは、現在顧客の行動に影響を与え、eコマースビジネスの成功を妨げる要因を特定することです。

1ナビゲーションが悪い

ナビゲーションは、Shopifyのコンバージョン率の最適化の観点から考慮すべき最大のオンラインストア設計の問題点の1つです。ほとんどの場合、ナビゲーションは、何千もの製品を販売する大規模なオンラインストアにとって実際の問題になります。

ウェブサイトの訪問者が壮大な検索を行わずに探しているものを見つける機会がない場合、Shopifyストアは販売されません。すべてのオンラインストアに共通のソリューションはありませんが、役立ついくつかの推奨事項があります。

ドロップダウンメニューを構成する

シンプルで明確なカタログ構造は、私たちが強調する最も重要な推奨事項です。組織化が重要です–すべての製品をメインカテゴリとサブカテゴリに分割することが不可欠です。また、すべての商品は、顧客が3回のクリック以下で目的の商品に到達できるように、ネストの第3レベルよりも深く配置しないでください。

これは、構造化されたドロップダウンメニューの優れた例です。

![how to increase the Shopify conversion rate](https://whidegroup.com/wp-content/uploads/shopify-conversion-optimization-img-1.webp)

カテゴリブロックを正しく配置する

人々はリストの最初と最後に最も注意を払う傾向があります。

アクセントを付ける

顧客の目を通してあなたのウェブサイトを見て、すべてのCTA（行動を促すフレーズ）ボタンが明白であることを確認してください。

可視検索

ウェブサイトを検索する機能は、オンラインストア、特に幅広い品揃えのストアにとって必須の機能です。訪問者が必要なものを正確に知ってWebサイトにアクセスする場合は、ナビゲーションメニュー全体をクリックしなくても、探しているものを簡単に見つけることができる方法があることを確認してください。

特性でフィルタリング

ユーザーは、サイズ、素材、希望の色などの属性を指定できます。このオプションにより、カスタマージャーニーが大幅に短縮され、注文フェーズにすばやく進むことができます。

2CTAなし

CTAボタンは、オンラインストアで使用する最も重要な戦術の1つです。すべてのeコマースストアの所有者の目標は、できるだけ多くの訪問者がCTAをクリックするようにすることです。ウェブサイトのデザインのその段階で、CTAを含めるのを忘れた場合、またはページの背景から目立たせなかった場合は、訪問者にCTAが表示されない可能性があります。最悪のシナリオ？ウェブサイトにアクセスし、カタログをスクロールしてから離れると、よりわかりやすい設定で別のサイトで購入する可能性があるため、ストアからの購入を忘れてしまう可能性があります。これを回避するには、商品ページに「今すぐ購入」、「カートに追加」などの対照的なボタンが必要です。

3チェックアウトの問題

ストアに紛らわしいショッピングカートとチェックアウトがある場合、これはShopifyのコンバージョン最適化のために対処するもう1つのポイントです。

これは、ショッピングカートのボタンのデザインが貧弱な例です。
![how to increase the Shopify conversion rate](https://whidegroup.com/wp-content/uploads/shopify-conversion-optimization-img-4.webp)
sabre/dav

## dockerで動かす場合

```
docker run -it --rm \
 -p 80:80 \
  atifsyedali/docker-sabre-dav
```

http://127.0.0.1/ にアクセスし、フォルダを作成し、
Explorerで http://127.0.0.1/ にアクセスすると表示される。

試しに `/folder1/にほんご.txt`を作成すると以下に保存される。

* /var/www/files/folder1/にほんご.txt


![aa.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/2efabb09-ed1c-8304-ca12-6fecbbbaba73.png)


## composerでインストールする場合

* https://sabre.io/dav/install/

```sh
composer require sabre/dav
# データの保存場所
mkdir -p /home/share/webdav/
chmod 700 /home/share/webdav/
# lockファイル用
mkdir data
```

## 利用方法

```php:/webdav/server.php
<?php
use Sabre\DAV;

require 'vendor/autoload.php';

// データ保管場所の設定。DocumentRootは避ける
$rootDirectory = new DAV\FS\Directory('/home/share/webdav/');
$server = new DAV\Server($rootDirectory);

// このスクリプトのURI
$server->setBaseUri('/webdav/server.php');

$lockBackend = new DAV\Locks\Backend\File('data/locks');
$lockPlugin = new DAV\Locks\Plugin($lockBackend);
$server->addPlugin($lockPlugin);

$server->addPlugin(new DAV\Browser\Plugin());

$server->exec();
```

## アクセス

explorerで `https://ドメイン名/webdav/server.php` にアクセスすると
`/home/share/webdav/`が読み書きできることを確認。

## 認証

後で書く

* https://sabre.io/dav/authentication/
BigQuery Scriptingでsleep

BigQuery Scriptingで処理を書いている途中で、少しだけ待ち時間を挟みたいことがたまにあります。
そんな時用のsleep処理をprocedureとして書いてみました。

```sql
CREATE OR REPLACE PROCEDURE `<プロジェクト名>.<データセット名>.sleep`(IN sec INT64)
BEGIN
  DECLARE now TIMESTAMP DEFAULT CURRENT_TIMESTAMP();
  DECLARE finish TIMESTAMP DEFAULT TIMESTAMP_ADD(CURRENT_TIMESTAMP(), INTERVAL sec SECOND);

  WHILE now < finish DO
    SET now = CURRENT_TIMESTAMP();
  END WHILE;
END;
```
Windows版ZOOM専用リモコンをM5StickC(無印)でさらに作りこんでみた。

#前回よりも、より良いZOOMリモコンを求めて
[前回はこちら](https://qiita.com/kai00/items/144298038f17831a5c59)を作ってみたが、自分はZOOMユーザーでWebEXを使わないし、マイクのミュート＆ミュート解除とビデオのオン/オフが使いたかったので、コードをさらに書き換えてみた。

##改善したい点
・ビデオのオン/オフ
・バッテリー寿命の延命
・バッテリーが切れそうになったら表示する
以上の自分の要望に応えるために以下のコードに改良した。改良点はコード内のコメントを参照ください。

```
#include <M5StickC.h>
#include <BleKeyboard.h>


BleKeyboard bleKeyboard;

enum ConfSystem {
  mic = 0,
  video,
  vaps
} conf;
int n_conf = 2;
bool on_air;

void setup() {
  M5.begin();
  bleKeyboard.begin();
  
  M5.Lcd.setRotation(3); // BtnA is left side to LCD
  
  //Make display daker
  M5.Axp.ScreenBreath( 8 );
  setCpuFrequencyMhz(80);

  // default
  conf = mic;
  on_air = true;
  update_display();
}

void loop() {
  M5.update();
  
  if(M5.BtnA.wasPressed()){
    if(bleKeyboard.isConnected()){
      on_air = !on_air;
      if(conf==mic){
        send_mute_mic();
      }
      else if(conf==video){
          send_off_video();
      }
    }
    else {
      Serial.println("BLE is not connected");
    }
    update_display();
  }

  if(M5.BtnB.wasPressed()){
    conf = ConfSystem((conf+1) % n_conf);
    update_display();
  }

  if(M5.Axp.GetWarningLeve() == 1){
    M5.Lcd.drawString("LowBattery",0,0);
    delay(10);
  }else{
  //Get Voltage of internal battery
    String vaps = String(M5.Axp.GetAPSVoltage())+ "V";
    M5.Lcd.drawString(vaps,0,0);
    delay(100);
  }
}

void update_display(){
  if(on_air){
    show_onair();
  }
  else {
    show_inmute();
  }
}

void show_onair(){
  M5.Lcd.fillScreen(TFT_RED);
  M5.Lcd.setTextColor(TFT_WHITE, TFT_RED);
  M5.Lcd.setTextSize(3);
  M5.Lcd.setTextDatum(MC_DATUM);
  M5.Lcd.drawString("ON AIR",80,40);

  M5.Lcd.setTextSize(2);
  M5.Lcd.setTextDatum(BR_DATUM);
  if(conf==mic){
    M5.Lcd.drawString("Mic",158,78);
  }
  else if (conf==video){
    M5.Lcd.drawString("Video", 158,78);  
  }
}

void show_inmute(){
  M5.Lcd.fillScreen(TFT_DARKGREY);
  M5.Lcd.setTextColor(TFT_WHITE, TFT_DARKGREY);
  M5.Lcd.setTextSize(3);
  M5.Lcd.setTextDatum(MC_DATUM);
  M5.Lcd.drawString("Muted...",80,40);

  M5.Lcd.setTextSize(2);
  M5.Lcd.setTextDatum(BR_DATUM);
  if(conf==mic){
    M5.Lcd.drawString("Mic",158,78);
  }
  else if (conf==video){
    M5.Lcd.drawString("Video", 158,78);  
  }
}

void send_mute_mic(){
  // https://support.zoom.us/hc/en-us/articles/205683899-Hot-Keys-and-Keyboard-Shortcuts-for-Zoom
  bleKeyboard.press(KEY_LEFT_ALT);
  bleKeyboard.press('a');
  delay(100);
  bleKeyboard.releaseAll();
}

void send_off_video(){
  // https://www.cisco.com/c/en/us/td/docs/collaboration/CWMS/2_5/b_manage_meetings/b_manage_meetings_chapter_0100.html
  M5.Lcd.drawString("Muted...",80,40);
  bleKeyboard.press(KEY_LEFT_ALT);
  bleKeyboard.press('v');
  delay(100);
  bleKeyboard.releaseAll();
}
```
OpenCV4.5 で改良されたテキスト検出について調査中

OpenCV4.5 の[リリースノート](https://github.com/opencv/opencv/wiki/ChangeLog#version450)には、文字認識が改良されたことが書いてある。

さらに、リリースノートをたどると、この改変のPRにたどり着ける。
https://github.com/opencv/opencv/pull/17675

最近は、このPRの説明が詳しくて、どのように追加・改変の機能がよくなったのかをわかりやすくまとめている。

英数字についても文字認識は、これまでにもだいぶ進んできていたが、手書き文字についても性能が向上してきている。

文字認識は、次の２段階からなる。
- 文字が写っている領域を検出する。(text detection)
- その領域に写っている文字の１字１字を特定する。(text recognition)
- （さらには、単独の文字認識で区別しにくい文字を、辞書を使って特定する。）


このOpenCVの実装は、上記のPRを読めばわかるように、文字を確定するまでのものになっている。


```
$ cd opencv/samples/dnn
$ opencv/samples/dnn$ python text_detection.py -h
usage: text_detection.py [-h] [--input INPUT] --model MODEL [--ocr OCR]
                         [--width WIDTH] [--height HEIGHT] [--thr THR]
                         [--nms NMS]

Use this script to run TensorFlow implementation
(https://github.com/argman/EAST) of EAST: An Efficient and Accurate Scene Text
Detector (https://arxiv.org/abs/1704.03155v2)The OCR model can be obtained
from converting the pretrained CRNN model to .onnx format from the github
repository https://github.com/meijieru/crnn.pytorchOr you can download trained
OCR model directly from https://drive.google.com/drive/folders/1cTbQ3nuZG-
EKWak6emD_s8_hHXWz7lAr?usp=sharing

optional arguments:
  -h, --help            show this help message and exit
  --input INPUT         Path to input image or video file. Skip this argument
                        to capture frames from a camera.
  --model MODEL, -m MODEL
                        Path to a binary .pb file contains trained detector
                        network.
  --ocr OCR             Path to a binary .pb or .onnx file contains trained
                        recognition network
  --width WIDTH         Preprocess input image by resizing to a specific
                        width. It should be multiple by 32.
  --height HEIGHT       Preprocess input image by resizing to a specific
                        height. It should be multiple by 32.
  --thr THR             Confidence threshold.
  --nms NMS             Non-maximum suppression threshold.

```

英文でよければ、次の解説記事がある。

[OpenCV Text Detection (EAST text detector)]
(https://www.pyimagesearch.com/2018/08/20/opencv-text-detection-east-text-detector/)


qiita [OpenCVをPythonで文字の場所をレシートから取得する]
(https://qiita.com/ChibaDai/items/875d767d260151974c89)

---
OpenVinoの場合

https://docs.openvinotoolkit.org/latest/omz_models_intel_text_detection_0003_description_text_detection_0003.html

https://docs.openvinotoolkit.org/latest/text_recognition.html


手書きの日本語を認識している！

https://docs.openvinotoolkit.org/latest/omz_models_intel_handwritten_japanese_recognition_0001_description_handwritten_japanese_recognition_0001.html

![](https://docs.openvinotoolkit.org/latest/test.png)
ノーパソにインストールされた Ubunt 20.04 のサーバを閉じてもサスペンドしないように設定する

## デフォルトだとサスペンドする設定になってるので、変える

```diff:/etc/systemd/logind.conf
- #HandleLidSwitch=suspend
+ HandleLidSwitch=ignore
```

## 設定の更新分の反映

`systemctl restart systemd-logind`
SAPIで湯婆婆を実装してみる

# 前置き
巷では湯婆婆の実装が流行っているそうですね。
私も真似してみようと思いましたが、有名どころのプログラミング言語は粗方実装され尽くしているように思います。

なので少し趣向を変えて、テキストではなく音声で湯婆婆を再現してみたいと思います。

# コード
```VBScript:湯婆婆.vbs
Option Explicit

Dim sapi
Set sapi = CreateObject("SAPI.SpVoice")

sapi.Speak "契約書だよ。そこに名前を書きな。"

Dim name
name = InputBox("契約書")

If Len(name) = 0 Then
	Wscript.Arguments(-1)
End If

sapi.Speak ("フン。" & name & "というのかい。贅沢な名だねぇ。")

Dim newName
Randomize
newName = Mid(name, Int(Len(name) * Rnd + 1), 1)

sapi.Speak ("今からお前の名前は" & newName & "だ。いいかい、" & newName & "だよ。分かったら返事をするんだ、" & newName & "!!")

Set sapi = Nothing
```

WindowsのSAPI (Speech APIの略で、サピと読みます) を使用し、VBSで実装しました。

# 解説
まずはSAPIを呼び出すためのオブジェクトを生成します。
生成以降、Speakメソッドで音声が出力できるようになります。

```
Dim sapi
Set sapi = CreateObject("SAPI.SpVoice")

sapi.Speak "契約書だよ。そこに名前を書きな。"
```

次に、契約書を入力するためのボックスを表示します。

```
Dim name
name = InputBox("契約書")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501246/9719bcfe-c91a-1d4e-37d2-92ae5a04aaf6.png)

そして入力後、未記入の場合にクラッシュする必要があるため、わざとエラーを引き起こすようにしています。

```
If Len(name) = 0 Then
	Wscript.Arguments(-1)
End If
```

記入されている場合はランダムで文字を１つ選び、後は名前を奪って完了です。
※乱数取得前にRandomizeを実行しておかないと、続けて実行したときに同じ乱数が返ってきてしまいます。

```
sapi.Speak ("フン。" & name & "というのかい。贅沢な名だねぇ。")

Dim newName
Randomize
newName = Mid(name, Int(Len(name) * Rnd + 1), 1)

sapi.Speak ("今からお前の名前は" & newName & "だ。いいかい、" & newName & "だよ。分かったら返事をするんだ、" & newName & "!!")
```

# 感想
SAPIで湯婆婆を実装してみる、ということでSAPI婆を実装してみました。
使ってみて良いなと思ったのは、名前を入力した時と１文字だけ抜き取った時とで漢字の読みが変わることです。例えば、千尋は"チヒロ"と読み、千は"セン"と読み上げてくれます。
また難点はやはり、棒読みになってしまい緊張感に欠けることですね。最後に"!!"を付けても感情を込めてくれないので、劇中の情景とはギャップが生まれます。
Ansibleとは何か

　Ansibleはオープンソースの構成管理とOSやソフトウェアなどの設定作業を自動化するツールであり、主にLinuxやWindowsなどの管理に利用されている。

　クラウド環境やコンテナ環境でも管理可能なモジュールは提供されているが、Ansibleは基本的には管理者が手動で実行・管理していたOSコマンドやOS上の設定ファイルを自動で管理する。本稿ではこの機能を中心に説明していく。

　Ansibleとは、OSのターミナルから実行するコマンドのことであり（以下、「Ansibleコマンド」と呼ぶ）、Ansibleコマンドが導入されているサーバーを本稿では「Ansibleサーバー」と呼ぶ。

　AnsibleサーバーでAnsibleコマンドを実行すると、Ansibleサーバーから被管理サーバーへアクセスして各種設定を行う。

　被管理サーバーへのアクセスと設定の反映には、対象がLinuxサーバーの場合はSSHプロトコルとPythonを、Windowsの場合はWinRM（Windows Remote Manager：Windowsリモート管理）プロトコルを使用する。被管理サーバー側に、Ansibleのクライアントを導入する必要はない。

　このクライアントの導入不要という点はAnsibleの大きなメリットの１つであり、そのため被管理サーバーを作成してから直ちにAnsibleでのセットアップが可能となる。

　Ansibleにはいくつかコマンドが存在するが、Ansibleによる構成管理というと、ansible-playbookコマンドを実行する形が一般的である。

　ansible-playbookコマンドを実行する際には、PlaybookファイルとInventoryファイルが必要である。Playbookファイルは、被管理サーバーに対して設定する内容を記述したテキストファイル（YAMLフォーマット）で、パッケージ管理、ユーザー管理、ファイルやディレクトリ操作、サービス操作など、さまざまな設定が可能である。

　一方、Inventoryファイルは被管理サーバーの接続情報を定義するテキストファイルで、主に被管理サーバーのホスト名やIPアドレスのリストを記載するほか、被管理サーバーにアクセスする際に使用するユーザーID、パスワードやSSH鍵、被管理サーバーに導入されているPythonのパス、といった情報を記載することもある。

　Ansibleコマンドの実行イメージは、以下のとおりである。

```
$ ansible-playbook -i Inventoryファイルパス Playbookファイルパス　
```

　デフォルトでは、ansible-playbookコマンドを実行したユーザーIDとSSH鍵で被管理サーバーにSSH接続して、Playbookを実行する。

　異なるユーザーIDとSSH鍵でSSH接続する場合は、-uや–private-keyオプションなどを使用し、被管理サーバーがWindowsである場合はInventoryファイルにユーザーIDやパスワードを記述する。
[メモ]Jupyter Notebook上で仮想環境を動かす[ImportError: win32apiというモジュールはありません]

## 前書き
PyGameで色々やりたいなと思い立ったのが昨日のこと。今日はとりあえず仮想環境を作ってJupyterNotebook上でアレコレ試せるようにしたいなと思って作成作業をしていましたが、少しはまってしまいました。

ここではその症状と対処法をメモ書き程度に残しておきます。同じ症状が起きている方はあまり居ないようですが、参考になれば幸いです。

### 環境
Windows 10
Python 3.8
conda 4.9.0


### 前提
[Jupyterで複数カーネルを簡単に選択するための設定](https://qiita.com/tomochiii/items/8b937f15c79a0c3eae0e)で紹介されている内容は終わっているものとします。

### 症状と対処法
カーネルの設定も終わったぞ、と思って早速仮想環境に入り、そこからJupyterNotebookを起動すると、何やらkernel errorが。

メッセージを読んでみると、"win32apiがimport出来ないんだけど"という旨のお話。

いくつか記事をあたって見ると、以下のようなサイトが。
[ImportError：win32apiというモジュールはありません](https://www.it-swarm-ja.tech/ja/python/importerror%EF%BC%9Awin32api%E3%81%A8%E3%81%84%E3%81%86%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB%E3%81%AF%E3%81%82%E3%82%8A%E3%81%BE%E3%81%9B%E3%82%93/1043946510/)

Pypiwin32は古いらしいので、代わりにpywin32をpipでインストールしましたが、それでも動きません。さらに読み進めてみると、

>pywin32 github に従って実行する必要があります

とのお言葉が。早速[github](https://github.com/mhammond/pywin32)を見に行ってみると、

>Note that if you want to use pywin32 for "system wide" features, such as registering COM objects or implementing Windows Services, then you must run the following command from an elevated command prompt:

```
python Scripts/pywin32_postinstall.py -install
```

半分くらいはわかっていませんが、システムワイド（横断的？）に使いたい場合はWindowsサービスに登録しなければならないようなので、Scripts置き場（私の場合はAnaconda3ファイルの直下）に行き、指定されたコマンドを実行すると、ようやく動きました。

### 雑考察
以前に同じくJupyterNotebookを使える仮想環境を作成しましたが、その時にこのような沼にはまった覚えはありません。

おそらくですが、その時のPythonのバージョンが3.6だか3.5だったのに対し、今回はPygame側から指定されて3.8を仮想環境作成時にインストールしたのが原因なのかもしれません。

### まとめ
集合知に感謝。
vagrant + VirtualBoxでVERR_INTNET_FLT_IF_NOT_FOUNDが出たのを解消したメモ

## 概要
VERR_INTNET_FLT_IF_NOT_FOUNDが出てVirtualboxが起動できなくなった。
ホスティングアダプタの再起動で直った。

## 現象
`vagrant up`をしたところ以下のようなエラーが発生。

```
==> default: Booting VM...
There was an error while executing `VBoxManage`, a CLI used by Vagrant
for controlling VirtualBox. The command and stderr is shown below.

Command: ["startvm", "87e1b4f5-9363-4430-9eb9-36c684d306ab", "--type", "headless"]

Stderr: VBoxManage.exe: error: Failed to open/create the internal network 'HostInterfaceNetworking-VirtualBox Host-Only Ethernet Adapter #13' (VERR_INTNET_FLT_IF_NOT_FOUND).
VBoxManage.exe: error: Failed to attach the network LUN (VERR_INTNET_FLT_IF_NOT_FOUND)
VBoxManage.exe: error: Details: code E_FAIL (0x80004005), component ConsoleWrap, interface IConsole
```

## 環境
* Windows10 Home バージョン20H2(OS ビルド 19042.610)
* VirtualBox 6.1.16 r140961 (Qt5.6.2)
* Vagrant 2.2.10

## 対応
[VirtualBoxでminikubeやvagrantが起動しなくなった場合の対処（VERR_INTNET_FLT_IF_NOT_FOUND)][*1]に記述の手順をなぞる。

#### 操作ログ
「windowsキー」+「xキー」で開いたメニューから「ネットワーク接続」を選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99876/a01b0d05-e10b-9ae7-6009-6d563f310364.png)

「アダプターのオプションを変更する」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99876/a9fad814-95b0-3651-4c46-660f1b2c276e.png)

「プロパティ」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99876/d7cacdae-255e-4cfe-5f4f-a8ea8ccbbd75.png)

「インターネット プロトコルバージョン6(TCP/IPv6)」のチェックを外す
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99876/3e6dfd11-27ea-a7ac-fd2b-3d27d1d52cc3.png)


#### 操作ログ
一度、エラーが出ていたネットワークを「無効にする」から無効にし、その後「有効にする」を押して有効にする。
有効にした後はネットワーク設定を開きなおさないと無効と表示されたままだった。おそらく表示が更新されていないだけ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99876/aad13093-2ff0-abc3-7a82-40b4f31745d4.png)

## 参考
[VirtualBoxでminikubeやvagrantが起動しなくなった場合の対処（VERR_INTNET_FLT_IF_NOT_FOUND)][*1]

[*1]:https://qiita.com/tmiki/items/563bf3450977fcd965cc
関数の呼び出し[Javascript]

#Javascript ~関数の呼び出し~
関数を定義しただけでは、その中の処理は実行されない。図のように、関数を定義した際に使用した定数名を用いて、「定数名()」と書くことで関数の中の処理を実行できる
![46e36760d965e0fe3fadf99676883857.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/725167/ef2701f1-56c1-69b6-da31-db97332b7103.png)
![6c9e37b2b045ca7f070adb4c6ae2ae5e.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/725167/fa468d92-a621-3e4f-bd08-01ceb2ed6097.png)
##引数を受け取る関数の定義
(引数名) =>」と括弧の中に引数名を書くことで引数を受け取ることができる
![1529043476847.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/725167/016c2428-ecb7-5f11-1c6e-1d822dde49b7.png)
![1529044955793.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/725167/87f6d449-7d4e-a99b-1433-43bb4c72b9bc.png)
#以上！