OmniAICreator/Qiita-1.07M huggingface dataset:
オブジェクトの配列をハッシュテーブルに詰め替えると扱いやすくなる場合

○○パターンみたいなかっこいい名前が付いていたら教えて下さい。

例えば、配列になったオブジェクトから特定のオブジェクトを取り出してプロパティの値を確認したいとします。

```powershell
$status = Get-Service | Where-Object { $_.Name -match "w3svc"  } | Foreach-Object { $_.Status }
```

サービスの稼動確認をするために時々書きます。

ただ、この書き方は無駄が多いような気がしてきて、以下のような変遷を遂げます。

```powershell
# 最後のForeachは冗長すぎると思って削ったり
$status = Get-Service | Where-Object { $_.Name -match "w3svc"  } | Select-Object -ExpandProperty Status

# そもそも最初から絞ってみたり
$status = Get-Service -Name "w3svc" | Select-Object -ExpandProperty Status

# もっと短くできると思ったり
$status = (Get-Service -Name "w3svc").Status

# でもやっぱり複数サービスの確認がしたいのでまとめて出してみたり
Get-Service | Foreach-Object {
    switch($_.Name){
        "w3svc" { echo $_.Status }
        "....." { echo $_.Status }
        "....." { echo $_.Status }
    }
}
```

この辺りまでやると、手書きが面倒になるので最初の書き方に戻ります。

この無意味なループを解消するために、以下のような書き方をします。

```powershell
$svc = @{} # 初期化
Get-Service | Foreach-Object { $svc[$_.Name] = $_ } # 一意になるプロパティをキーにする
$svc["w3svc"].Status
$svc["....."].Status
$svc["....."].Status
```

`Get-Service` を何度も呼び出すこともなく、ループ（パイプ）の数も少なく、記述量も少なくて機械と脳と指に優しいです。`Get-Service`をローカルで呼び出す場合はそれほど問題にはならないかもしれませんが、ネットワーク越しに一覧を取る系のコマンドが先頭に来る場合などは、覚えておくと良いのではないかと思います。
Django MySQLにマイグレーションでWARNINGS

DjangoでMySQLにマイグレーションすると以下の警告が出た。

```
WARNINGS:
?: (mysql.W002) MySQL Strict Mode is not set for database connection 'default'
        HINT: MySQL's Strict Mode fixes many data integrity problems in MySQL, such as data truncation upon insertion, by escalating warnings into errors. It is strongly recommended you activate it. See: https://docs.djangoproject.com/en/3.1/ref/databases/#mysql-sql-mode
```

調べると settings.pyにOPTIONSを追加することで解決。

```
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'my_db',
        'OPTIONS': {
            'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
        },
    }
}
```


参考
https://qiita.com/hayato1130/items/27093d62d786ca0abc14
https://django-mysql.readthedocs.io/en/latest/checks.html
Vue.js+Axiosでリクエストをキャンセル(中断)する

## 概要
ボタンを押すことによって非同期通信が行われる様な場合、
ボタンの連打によって複数回数実行されると最後に実行されるリクエスト到達まで遅くなってしまう。
この場合はv-modelによってボタンの活性制御をすれば良いが事情があってできない場合はaxiosのキャンセルトークン利用して、
最後にボタンが押された際の非同期通信処理のみ実行するようにする。

(実際に使用した箇所としてFullCalendar-vueで月を変更するとその月の情報のみを非同期通信で取得するロジックの場合
月の変更ボタンを連打されてしまうと上記の問題が発生するのでキャンセルトークンを使用しました
これに関してはもっといい方法があるかも)

下記の例ではcreateUserメソッドが複数回連続して呼び出される前提

## CancelTokenを使用して以前のリクエストを中断する

\<script>直下

```js:test.vue
const axios = require("axios");
const CancelToken = axios.CancelToken;
let cancel;
```


methods部分


```js:test.vue
createUser(){
    if (cancel) {
        console.log("Cancel!!!");
        cancel();
    }

    axios
        .post("/api/users", {
            id: 5,
            name: "John",
        }, {
            cancelToken: new CancelToken(function executor(c) {
                cancel = c;
            }),
        })
        .then((response) => {
            console.log(response.data);
        })
}
```

#### やり方はもう1つあるがスマートに書けるのでこの記述方法を採用した
#### 詳しくは[公式のGitHub](https://github.com/axios/axios)参照
僕の選んだvsコードでシュパパッとメモるための拡張機能

# 結論：実現したこと＆拡張機能
- メモに画像を入れたい
    - `Paste Image`
- メモを見返すときに楽にしたい
    - 目次が欲しい
        - `Auto Markdown TOC`
    - 自動でプレビュー開きたい
        - `Auto-Open Markdown Preview`

こんな感じにできました：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237551/0088d465-4ee0-75db-3371-0d3697749d3c.png)


# 想定ケース（僕の場合）
- pythonのコーディングなどでvsコードをよく使っており、その流れで適当なメモもvsコード(.md)で書いてる
- 画像挿入ができなかったので、キャプチャした画像を残すときはコンフルつかっててめんどくさかった
- 個人用のメモなので多少汚くてもよく、linterなどの校正は興味ない
- Markdown All in One的な拡張入れたけど、イマイチ上手くいかないな（このあたりで多少苦労したのでQiitaに残しておこうと思いました）

## 環境
OS
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237551/834b8c1b-d19a-8a80-ba0b-1919072a8a58.png)

Visual Studio Code
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237551/8a0b33c9-0fb0-8087-48ca-9e46ae4114a0.png)

# 使い方
## 下記3つの拡張機能をインストール
`Paste Image`
`Auto Markdown TOC`
`Auto-Open Markdown Preview`
like_this:
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237551/c0523808-e9e0-3b4a-e83e-b75c02162637.png)

## 他のマークダウン絡みの拡張機能は一旦無効に
（再起動を求められたらやってね）
like_this:
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237551/8881dc4f-b5fa-fcd0-7c25-cbbe25870d01.png)


## 適当に.mdファイル作る
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237551/a75384f8-35fb-c686-c95d-8c1198414d3c.png)

## .mdファイル開く->自動でプレビュー表示
自動でプレビューが表示されれば、`Auto-Open Markdown Preview`は役目を果たしています！
like_this: 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237551/69e08034-3b92-6e3d-3ef2-c0089998a92e.png)
(ちなみに手動プレビューはcmd+shift+V)

## 適当に.mdに中身作る
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237551/f800d773-e98f-e0a7-0aec-e86df00d55b4.png)

## 目次を挿入
`右クリック`で`Auto Markdown TOC: Insert/Update`
右クリックメニューにこれが現れるのは`Auto Markdown TOC`拡張を入れてるからです！
like_this:
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237551/b3120c71-e0fe-672e-2062-a885744483a1.png)

こんな感じで目次が表示されます:
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237551/88137dc1-fcb9-bb11-76aa-065f58c8ee40.png)

## クリップボードから画像を挿入
macだと`cmd+shift+control+4`で指定範囲キャプチャできます。
それを貼り付けるには`cmd+option+V`です（これは`Paste Image`拡張機能の力です！）

こんな感じになります：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237551/0088d465-4ee0-75db-3371-0d3697749d3c.png)

個人用のメモとしては十分じゃないでしょうか！
vscodeと拡張機能を作ってくれた方々に大感謝です！

おわり
【React Typescript】useEffectを複数の引数で発火させる方法

React Typescriptで新規プロダクト開発中、複数の管理するステートが変更されたタイミングで、1つのuseEffectを発火させたい場合があったんだけど日本語の記事を探してもなかなか見つからなかったからメモ。まあ1つのステートごとに同じuseEffectを書いてそれを複数用意すれば動くだろうけど、そんなんは俺の上司のPRレビューで通用しないことを知っている怒られる前に策を打つのだ

##  結論

以下のように書けば、今回やりたいuseEffectを複数の引数で発火させるができる
複数の引数で発火とは複数のステートが変更されたタイミングで発火を意味しているよん

```index.tsx
function HukusuuHakka() {

  const [aaa, setAaa] = useState(0)
  const [bbb, setBbb] = useState(0)
  const [ccc, setCcc] = useState(0)


  useEffect(() => {
    console.log("@@@@@@@@@@@@@@@@ 発火🔥 @@@@@@@@@@＠@@@@@@@")
  }, [aaa, bbb, ccc])


  return (
    <div>
      {aaa} {bbb} {ccc}
      <br />
      <button onClick={() => setAaa(aaa + 1)}>aaa + 1</button>
      <button onClick={() => setBbb(bbb + 1)}>bbb + 1</button>
      <button onClick={() => setCcc(ccc + 1)}>ccc + 1</button>
    </div>
  );
}

```

https://ja.reactjs.org/docs/hooks-effect.html
https://ja.reactjs.org/docs/hooks-reference.html
https://tech-1natsu.hatenablog.com/entry/2019/02/14/214816
https://stackoverflow.com/questions/55067202/what-if-i-add-multiple-dependency-in-reacts-useeffect-second-parameter
【laravel】社内案件管理システムを作成しました

# 投稿一覧ページ

```ruby:show.blade.php
@extends('layout')

@section('content')

    <div class="contentsArea">
      <nav style="--bs-breadcrumb-divider: '>';" aria-label="breadcrumb">
        <ul class="breadcrumb">
          <li class="breadcrumb-item"><a href={{route('index')}}>TOP</a></li>
          <li class="breadcrumb-item active" aria-current="page">受注案件一覧</li>
        </ul>
      </nav>
      <section class="section">
        <h2 class="heading02">受注案件一覧</h2>

        @include('search')
        <div class="table-scroll">
          <table class="table-bordered table-hover table-01 mt-5">
            <thead>
              <tr>
                <th>計上日</th>
                <th>発注元営業部門</th>
                <th>営業</th>
                <th>クライアント名</th>
                <th>案件名</th>
                <th>作成者</th>
                <th>金額</th>
                <th>状態</th>
                <th></th>
              </tr>
            </thead>
            <tbody>
              @foreach ($projectlist as $projectlist)
              <tr>
                <td class="ta-center">{{ $projectlist->accounting_date->format('Y/m/d') }}</td>
                <td class="ta-center">{{ $projectlist->department_name }}</td>
                <td class="ta-center">{{ $projectlist->sales_name }}</td>
                <td class="ta-center">{{ $projectlist->client_name }}</td>
                <td class="ta-center">{{ $projectlist->project_name }}</td>
                <td class="ta-center">{{ $projectlist->author_name }}</td>
                <td class="ta-right">{{ number_format($projectlist->price) }}</td>
                <td class="ta-center">{{ $projectlist->status }}</td>
                <td><a href={{ route('projectlist.detail', ['id' =>  $projectlist->id]) }} class="btn-02-s">詳細</a></td>
              </tr>
              @endforeach
            </tbody>
          </table>
        </div>
      </section>
    </div>

@endsection
```
GooglePlayアプリ申請でRejectされた時にやったこと（2021年）

Androidアプリを作った！早速GooglePlayで公開しよう！
と思って申請してからというもの、合計6回ほどRejectを繰り返し、のべ2ヶ月ほどかかってしまいました
これからアプリを作る方の参考になればと思います

# 今回リリースしたアプリ
* 年齢制限なし、広告なし、アプリ内課金なし
* バックグラウンド位置情報、アクティビティにアクセスする
* 配布対象は日本のみ

というアプリで申請してみました
アプリが使う機能が多くなるほどRejectされやすくなるだろうなとは思います

# Reject理由
一連の流れでRejectされたのは下記３つの要因です
特に**位置情報のバックグラウンド取得に絡めてRejectされることがほとんど**でした
最近では厳しくなってるんでしょうね

### Unclear feature description
バックグラウンドで位置情報にアクセスが必要な機能を特定できなかった

### Prominent disclosure not found
目立つ開示が見つからなかった

### Invalid privacy policy
プライバシーポリシーが無効である

# Rejectに対してやったこと
### 位置情報にアクセスする妥当性を説明する
位置情報はユーザのプライバシーに関わる情報として、特に注意されています
アプリ内でデバイスの位置情報にアクセスする場合には、申請時にしっかり説明する必要があります
説明するところはこちら、「機密情報に関わるアプリの権限」です

![スクリーンショット 2021-02-23 13.18.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/924658/2172affb-e1d6-acbc-6553-93f813a0bc93.png)

この中で下記の３点が必要です
* アプリの目的　（〜500文字）
* 位置情報へアクセスする必要があるアプリの機能　（〜500文字）
* 位置情報にアクセスしている様子を記録した動画　（〜30秒）

私の場合、Reject前は非常に簡素な説明（各100文字程度）だったため指摘されたようです
それぞれ400字以上かけてガッツリ説明することにしました
特に下記の観点で説明することが重要なのかなと推測しています

* なぜアプリに位置情報が必要なのか
* なぜバックグラウンドで位置情報を取得する必要があるのか
    * バックグラウンドではない場合、何が困るのか

動画に関しては、後述のランタイム開示を実装したら忘れずに反映しましょう

### 権限リクエストの直前に説明画面を表示する
[Googleの個人・機密情報ポリシー](https://support.google.com/googleplay/android-developer/answer/10144311?visit_id=637488178116865516-3459747432&rd=1#personal-sensitive)によると、いくつか要件が指示されています

* アプリ内の通常使用時に表示すること。メニューや設定画面から移動する必要がある場所はダメ
* 掲載場所をプライバシーポリシーや利用規約の中のみとしないこと
* 個人情報や機密情報の収集に関係のない開示の中に掲載しないこと

ということで、位置情報やアクティビティといったデバイス情報にアクセスする直前に、説明画面を表示することにしました

![ab23292f-797c-4e1b-b00b-2dfe3ad773bc-1920x2742r.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/924658/f1ec40b0-ad3e-79f3-c12d-1c22992bd53c.png)![29ebd29c-bde8-48e9-be7f-87097bceb098.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/924658/040f946e-ad19-6f5c-1384-09cf533e194a.png)

使う時に、使う権限だけ、ユーザにわかりやすく説明しなさい、ということですね

### プライバシーポリシーをしっかり作る、遵守する
こちらが一番クセモノで、Reject文だけだと修正箇所がわからないことがあります
かなり手当たり次第に実施しました

**プライバシーポリシーをしっかり作る**

* URL, タイトル, 見出し, 内容でプライバシーポリシーであることが明らかにする
    * **「プライバシーポリシー的な内容を含む利用規約」ではダメ**でした
    * [利用規約とは分けた方が法律的にも良さそうです](https://www.cloudsign.jp/media/20200212-privacypolicy-doui/)
* アプリ内で表示するときに、アイテム名やアクションバータイトルを「プライバシーポリシー」にする
* プライバシーポリシーの内容で、デバイスから取得する情報、目的について明記する

**アプリ説明文で位置情報を使うことが推測できるようにする**

GooglePlay上のアプリの説明文を充実させました
ユーザにとって、**アプリが位置情報やアクティビティを使うことが合理的に推測できること**が必要であると解釈しました

# それでもわからなければ...
実はReject意義申し立てフォームで問い合わせるとヒントをもらえることがあります
私の場合、「手は尽くしたんだけどぶっちゃけわからない。ヒントちょうだい（意訳）」的な文章を送りました
すると翌日に一つだけ理由を教えてもらえました

どうしてもわからなければやってみるものアリかと思います
シンプルカレンダーでカレンダーを入れました。(Gem)

#簡単なカレンダー作りたい
今回、オリジナルアプリで下記のようなカレンダーを作成しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1122715/c2976fff-d1ed-edce-2003-e14365fb9ee2.png)
これはsimple_calendarというGemを利用しています。

どんな風に作ったか思い出しを含め投稿します。
間違い等あるかもしれませんが宜しくです。

#バージョン
- Ruby 2.6.5
- Rails 6.0.0
- Bootstrap導入済み

#流れ
①

```ruby
#Gemfileに記載
gem 'simple_calendar', '~> 2.0'
```
####記載後bundle installをする。

②
rails g にてコントローラーの作成。
※ルーティングを忘れずに。

③
rails g にてモデルの作成。

④
今回は投稿した日時を表示させたいので、マイグレーションファイルに記載。
t.datetime :daytime,null: false
が重要です。

```ruby
class CreateMuscles < ActiveRecord::Migration[6.0]
  def change
    create_table :muscles do |t|
      t.string :title,          null: false
      t.text :explain,          null: false
      t.integer :part_id,       null: false
      t.integer :difficult_id,  null: false
      t.datetime :daytime,      null: false
      t.references :user,       foreign_key: true
      t.timestamps
    end
  end
end
```

その後rails db:migrateを実行！

⑤コントローラーの中身を編集する。（私のものはわかりずらいので割愛）
⑥ビューの編集。

```ruby
<h1 class="training-title">MYカレンダー</h1>
<div class="calendar">
  <%= week_calendar events: @muscles do |date, muscles| %>
    <%= date.day %>
    <% muscles.each do |muscle| %>
      <div>
        <%= link_to muscle.title, muscle %>
      </div>
    <% end %>
  <% end %>
</div>
```
今回は一週間分を表示させたかったので

```ruby
<%= week_calendar events: @muscles do |date, muscles| %>
```
の部分がweek_calendarになってます。
ちなみにmonth_calenderなら一月分です。

見た目の編集のため、以下を実行

```
$ rails g simple_calendar:views
```
最後application.cssに下記を記入。

```
 *= require simple_calendar ＃ここに追加
 *= require_tree .
 *= require_self
 */
```

ほぼ参考の方と同じですが、復習を兼ねて書かせていただきました。

#参考
導入までは、こちらの方を参考にしました！
https://qiita.com/isaatsu0131/items/ad1d0a6130fe4fd339d0
SQLメモ

小数点以下のまるめ関数挙動をまとめておく。自分用メモ


### まとめている関数
- round（数値, 桁数）<br>
数値を指定した桁数で四捨五入して返す（桁数入力の無い場合は、整数になる）
- trunc（数値, 桁数）<br>
数値を指定した桁数で切り捨てて返す（桁数入力の無い場合は、整数になる）
- floor（数値）<br>
指定した数値の切り捨て整数値を返す
- ceil（数値）<br>
指定した数値の切り上げ整数値を返す

### 実際にやってみる
```SQL
round(10.5)    # 11.0
round(-10.5)   # -11.0
trunc(10.5)    # 10.0
trunc(-10.5)   # -10.0
floor(10.5)    # 10.0
floor(-10.5)   # -11.0
ceil(10.5)     # 11.0
ceil(-10.5)    # -10.0
```

桁数はどこまで表示するかを表す。１が小数点第一位、０が整数部分一桁目、−１が整数部分二桁目。
つまり1の場合は、小数点第二位までを端数として操作し、小数点第一位までを表示する。
これを前提にroundとtruncの挙動を比べてみる。
### roundの挙動を確認
```SQL
round(156.753,3)   # 156.753
round(156.753,2)   # 156.75
round(156.753,1)   # 156.8
round(156.753,0)   # 157.0
round(156.753,-1)  # 160.0
round(156.753,-2)  # 200.0
round(156.753,-3)  # 0.0
```

### truncの挙動を確認
```SQL
trunc(156.753,3)   # 156.752
trunc(156.753,2)   # 156.75
trunc(156.753,1)   # 156.7
trunc(156.753,0)   # 156.0
trunc(156.753,-1)  # 140.0
trunc(156.753,-2)  # 100.0
trunc(156.753,-3)  # 0.0
```

### 数直線上の挙動でまとめてみる
- round（数値, 桁数）<br>
絶対値の大きい方に動く
- trunc（数値, 桁数）<br>
絶対値の小さい方の動く
- floor（数値）<br>
数値の小さい方に動く
- ceil（数値）<br>
数値の大きい方に動く


ごちゃつくと計算を繰り返しているうちに数値が合わなくなるので注意が必要です。
Extra Reducerを理解してなかった話

Extra ReducerをcreateAsyncActionの付き添いレベルで想定していたが、domainを跨いでactionによるStoreの更新を行える。

ログアウトや、cacheのアップデート(apiのresponseがnestedで他のデータに影響する場合(user.oragnizationとか))の場合は影響範囲をdomain単位で記載できる。

変更による改修コストは確かにあがりそうだけど、importから終える+createAsyncThunkで大量のdispatchを呼ばなくてすむので、コードの集約生が上がりそう。

ちゃんと解説を読むべきだった。。。
[createSlice](https://redux-toolkit.js.org/api/createSlice)

```store-sample.ts
const Logout = createAction('[CORE] LOGOUT')

const userSlice = createSlice({
    name: "user",
    reducers: {
       clear: () => initialState
    },
    extraReducers: builder => {
        builder.addCase(Logout, (state, action) => {
              console.log("call because of logout") // 呼ばれる
              userSlice.caseReducer.clear(state, action)
        }).addDeXXXX
    }
})

const companySlice = createSlice({
    name: "company",
    reducers: {
       clear: () => initialState
    },
    extraReducers: builder => {
        builder.addCase(Logout, (state, action) => {
              console.log("call because of logout") // 呼ばれる
              userSlice.caseReducer.clear(state, action)
        }).addDeXXXX
    }
})
```

```contaienr.tsx
const App: FC<Props> = props => {
    return (
        <button onClick={() => {useDispatch(Logout())}} >logout</button>
    )
}
```
CloudWatchとは

## 勉強前イメージ

サーバの状況とかが監視出来るサービス
ちょっとしたことなら設定したことあるけど、エージェントとかもあるとかないとか？？

## 調査

### CloudWatchとは

AWSで稼働している各サービスを監視するモニタリングサービスです。
CloudWatchを使用することでまとめて監視することが一つのプラットフォームで出来るようになります。

### CloudWatch のメリット

- 単一のプラットフォームで可視化することが出来る
	- アプリケーションもインフラも
- モニタリングが簡単
	- デフォルトのメトリックスがあるのでこちらを利用することで簡単に監視が始められます
- アラートが鳴る
	- 定義していたり、機械学習に基づいてアラームが設定されている
- 長期間履歴を見ることが出来る
	- 最大15ヶ月過去のデータを見ることが出来る

### CloudWatch の機能

機能としては以下の5つがあります。
それぞれ紹介していきます。

- CloudWatch

AWSで使っているリソースの稼働状況を監視します。
EC2のCPUやメモリ状況なども監視ができ、追加でインストールなどの作業は必要ありません。
よく使う監視項目(メトリクス)は標準で準備されていますが、
準備されていないものは `CloudWatch Logs` をインストールすることで取得できます

- CloudWatch Dashboard

AWSのリソースやログなど統合的に可視化出来ます。
ダッシュボードはカスタマイズ出来るので必要な情報のみを絞って表示させることが可能です。

- CloudWatch Alarm

監視する監視項目(メトリクス)がしきい値を超えた場合に、アラートなどを実施することが出来ます。

- CloudWatch Logs

CloudWatch Logsのエージェンhントをサーバにインストールすることで
準備されていないアプリケーションや項目を監視対象に出来ます。
`CloudWatch Logs Insights` を使用することで分析も可能になります。

- CloudWatch Events

リソースの変更を示すシステムのイベントを取得し、イベントに応じたアクションをスケジューリングしたりなど
自動化することが出来ます。

## 勉強後イメージ

CloudWatch Logs と CloudWatch Events は初めて知った。
標準で取れないものは、zabbix-agent的な感じで取得するイメージっぽい

## 参考

- [【運用管理】 AWSの監視ツール「CloudWatch」で何ができるの？](https://www.bit-drive.ne.jp/managed-cloud/column/column_06.html)
- [Amazon CloudWatch](https://aws.amazon.com/jp/cloudwatch/)
- [AWS上のサービスを監視する「Amazon CloudWatch」の実力は？](https://business.ntt-east.co.jp/content/cloudsolution/column-42.html)
python 多次元配列を1次元配列に変換する

[前回まで](https://qiita.com/kirin123kirin/items/1082d3c1564b745dcb4f)分割キーボードを作っていたが完成しやっと手になじんできた。

# 2次元以上の配列を1次元のリストへ

```python
# 配列返すバージョン
def flatten(x, notype=(str, bytes, bytearray), _recur=False):
    if _recur is False and isinstance(x, notype) or not hasattr(x, "__iter__"):
        return [x]
    return [z for y in x for z in (flatten(y, _recur=True)
              if y is not None and hasattr(y, "__iter__") and not isinstance(y, notype) else (y,))]

# generatorバージョン
def iterflatten(x, notype=(str, bytes, bytearray), _recur=False):
    if _recur is False and isinstance(x, notype) or not hasattr(x, "__iter__"):
        yield x
    yield from (z for y in x for z in (flatten(y, _recur=True)
              if y is not None and hasattr(y, "__iter__") and not isinstance(y, notype) else (y,)))

```

どんなにネストが深かろうと、1次元配列を返す。
追記 more_itertoolsにcollapseという関数があることを知った。

```python

from more_itertools import collapse
>>> list(collapse([1,2,[3,4,[5,6,[7]]]]))
[1, 2, 3, 4, 5, 6, 7]

```

```python
>>> flatten([1,2,[3,4,[5,6,[7]]]])
[1, 2, 3, 4, 5, 6, 7]

>>> flatten([1,2])
[1, 2]

# iterableならなんでも回して返す
>>> flatten([1,2,[range(3)]])
[1, 2, 0, 1, 2]

>>> flatten("1,2")
["1,2"]

>>> flatten(None)
[None]

>>> flatten([])
[]

_2d_10000 = [[0, 1, 2]] * 10000

>>> %%timeit
... sum(_2d_10000, [])
466 ms ± 81.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

import itertools

>>> %%timeit
... list(itertools.chain.from_iterable(_2d_10000))
356 µs ± 5.44 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

>>> %%timeit
... flatten(_2d_10000)
9.79 ms ± 31.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
# 2次元配列ならitertoolsのfrom_iterableより遅いが、sumより速く、3次元配列以上に対応できる汎用性優位



# 追記 3次元以上
>>> _3nest_10000 = [1,2,[3,4,[5,6,[7]]]] * 10000
>>> from more_itertools import collapse
>>> %%timeit
list(collapse(_3nest_10000))
74.5 ms ± 233 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

>>> %%timeit
flatten(_3nest_10000)
27.7 ms ± 29.3 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

```
アプリの音量設定、デジベル？パスカル？

##あらすじ
大抵の音声再生ライブラリは音量を音圧で指定するが、音の単位には音圧レベルってのもあるけど、どっち基準がいいのだろうか・・・

内容的にはトリビア的な物でそんなに製作活動に参考にはならないかもしれませんがご理解ください。

##音の感じ方

音の単位には、「音圧を表すPa」と「音圧レベルを表すDB」が存在します。

人間が聞ける音の大きさの範囲は20μPa〜20Paぐらい、最小と最大で音の大きさは100万倍！
音の強さは音圧が倍になると４倍になるので、最小と最大の音の強さは1兆倍！

こういう風に桁数が多いと音の強さが何倍になったかとかを表現するのが分かりにくいので「dB SPL」が使われています。

db splは基準である、20uPaの音に対して音の強さが10の何乗であるかで表します
20uPaの音なら0[db SPL]、20Paの音は130[db SPL]となります

##音圧指定の音声ライブラリで素直に実装した場合
音量50%と音量100%で音圧は２倍差になるので、音の強さは４倍になります。
これは約+12[db]程変化する事になります

音量50%を音量1%にすると音圧は1/50なので、音の強さは1/2500になります。
これは約-68[db]程変化する事になります

デシベルでの変化は5倍以上差が出るんだ！

##音の強さが変化するエンジンで素直に実装した場合
音の強さが50→100で2倍なので、約6[db]変化
音の強さが50→1で1/50なので、約-34[db]変化
という感じ

つまりどっちにしても音を大きくする方がdbの変化の範囲が小さい
なので音を小さくするのに比べて音を大きくする方は調整範囲が狭いけど微調整が効くって事になりやすいはず

##最大音量と最低音量で初期音量からのDBの変化量を同じにするには？
せっかくなのでDBの変化量で調整して、大きくする方と小さくする方で調整範囲を同じにしてみましょう？

50%の音量を1として、100%をxのn乗倍、xのn乗分の1になるようにすれば、同じになりますね！

例えば0~256の範囲で音量指定するライブラリだと、最低音量が1、最大音量が256、初期音量を16にすれば良いと言う事になります
音の強さは256倍変化するので、上下に約48デシベルの設定範囲になる

##一目盛り動かした時のdb変化量を一定にするには？
音量をnの目盛り乗にすると1目盛りあたりのDB変化量が一定になります。
例えば0~256の範囲で音量指定するライブラリだと、1~9の範囲設定で、最小は2の0乗で1、5で2の4乗の16、最大の9で2の8乗で256にする

##個人的な感想
これまでは音量設定値に比例した音量にしてたのを、一個上の段落の方法で実装してみました
前は目盛りを変化させても音の変化が分かりにくい範囲があったけど、どこで目盛りを上げ下げしても音量の変化が常にあるので良くなったような印象
（この感想には、個人差があります）
（Webで確認出来るサンプルアプリ等は用意していない）

##まとめ
DB基準とPa基準の音量設定どっちが良いのかは結局良く分かりませんでした、どっちが良いんでしょうね。
統計的に優位なアンケートを取れたらデータ下さい。

そもそも音量設定に求められるのは？
・最大でも音が小さすぎない
・最小でも音が大きすぎない
・初期音量設定がうるさすぎて不快にならない
・初期音量が小さすぎて音がなっている事に気づかれない事が無い
の４点だと思います

・初期設定音量が最大or最小になっていて、音を大きくする or 小さくする事が出来ない
・他のソフトの初期設定音量と比較して極端に音が大きかったり小さい（特に大きい方は良くない）
・目盛り数が少なすぎて微調整が効かない、マスターボリューム × BGM or SEボリュームが望ましい。

みたいなわりと見かけるので、その辺りを改善すれば十分なんじゃないかな
音量設定なんかに拘るより別の所に力を入れた方が良いな？

参考にしました
https://info.shimamura.co.jp/digital/knowledge/2014/03/21161
M5Stackリレーユニットでオンオフ制御してみた


最近開発中のプロジェクトで、クラウドの情報によって、リアル世界内の電源をオンオフする必要が出てきたので、M5Stackを使ったリレー制御を卓上扇風機で試してみました。

M5Stack専用のリレーユニットを使えば、半田付け不要、複雑な配線不要、簡単なビジュアルプログラムでリレー制御ができます。

##やったこと
M5StackのボタンAを押すと扇風機がまわり、ボタンBを押すと扇風機が止まります。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">M5Stack専用のリレーユニットで試しに卓上扇風機のリレー制御をやってみた。半田付け不要、複雑な配線不要、簡単なビジュアルプログラムでリレー制御ができる。 <a href="https://twitter.com/hashtag/M5Stack?src=hash&amp;ref_src=twsrc%5Etfw">#M5Stack</a> <a href="https://twitter.com/hashtag/protoout?src=hash&amp;ref_src=twsrc%5Etfw">#protoout</a> <a href="https://t.co/OdjWg1eEwL">pic.twitter.com/OdjWg1eEwL</a></p>&mdash; たつや (@tatsuya1970) <a href="https://twitter.com/tatsuya1970/status/1363492529543532547?ref_src=twsrc%5Etfw">February 21, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

##必要なもの
- [M5Stack Gray](https://www.switch-science.com/catalog/3648/)<br>
※このケースのように通信をしない場合は M5Stack Basicでもいいです。
- [M5Stack ミニリレーユニット](https://www.switch-science.com/catalog/4054/)
- オンオフを制御するもの<br>※今回のケースは市販の卓上扇風機をちょっと分解しました。

##システム構成

![プレゼンテーション1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/291592/b21ea6c2-fe17-491d-fed5-a0f012519781.jpeg)

リレーユニットの COM と ON に線を繋げます。
配線は、ただそれだけ。


##UIFlow
以下の画像のように、まずUnitsにRELAYを追加します。
あとは、画像のとおりです。

[![Image from Gyazo](https://i.gyazo.com/29b3329db4ae868fc13d92054b969a73.png)](https://gyazo.com/29b3329db4ae868fc13d92054b969a73)

あと、理由は分からないのですが、
RELAYのportは、 私の場合、A(21,22,VG）を選んだら動きました。
[![Image from Gyazo](https://i.gyazo.com/4fb5c901c101b58654ffee4372300b0e.png)](https://gyazo.com/4fb5c901c101b58654ffee4372300b0e)

##その他
リレーにどうやって線を繋げるのか途方にくれて、数日開発が進みませんでしたが、詳しい人に聞いたら一瞬で解決しました。
ネジを緩めるだけです。

![153651690_3756871951027978_937765310058189040_o.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/291592/ef45cf1f-8a31-e96d-c124-b670e286f570.jpeg)


独学で電子工作やってると、こんなしょうもないことで、よくつまづきます。

<BR><BR>
关于排序在NLU中的地位

排序在自然语言处理中是一个基本问题。我记得谷歌T5的论文里就有对比过填空（BERT）和顺序修复，两者训练通用模型的效果，当时我好像看到顺序修复效果是比填空好的，所以才一直忘不掉。

如今重新提起排序是因为这是老师给我提供的一个候选研究方向。

最近谷歌的openAI CLIP给人极大的冲击。我认为模型效果如此之好的根本原因是loss函数真正贴合了人类想要模型做的事情——理解图片&自然语言。最为Loss函数受苦的机器学习领域是强化学习——恰恰是openAI专攻的领域。我甚至怀疑openAI是不是用某种强化学习设置来探索了最优的loss函数，然后把这个结果给拿出来发表，而把本质的东西（发现这个loss定义的方法）藏了起来。

总而言之。我们作NLP的，仍然在为探索NLU（自然语言理解）最优的loss苦苦挣扎。而排序Loss，正是其中的一员。

排序Loss（以同一个句子中的单词排序为例）得以生效，是基于这样一个常识： 唯有理解了句意，我们才能够将句中词语正确排序。想想英语考试中的短语排序吧，那就是最好的例子。

单词排序可以用于训练句子embedding，句子排序可以用于训练段落embedding。

### Deep Attentive Sentence Ordering Network

今天看了这篇2018年的ACL论文。比起老师几年前的论文当然是好上很多，但是老实说，没有什么新意。 

![Screenshot from 2021-02-23 13-07-06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227568/f1f83549-c4a0-c309-ab40-db8356e97ec4.png)

观察模型结构，我们可以看到他比起prtNet的唯一不同是，中间用了多层selfattention。我们知道自注意层是自带multi-head的，这可以成为性能差异的要因之一。然后，他们选择排除一切position embedding之类的机制来抹消错误位置对模型产生的恶性影响。

这就是全部了。虽然模型结构比起老师之前论文里的SVM要好上很多，研究主题毫无新意，你知道我这样一个只读过不超过50篇论文的人，接手这样一个研究时，首先想到的就是这样的改进。

### 接下来的研究方向

虽然我作为云玩家可以指点江山，可是一轮到做研究就菜的像条狗，至今已经失败了三个研究：  
1. prtNet用于主题分割，就是segbot的那个想法，虽然segbot的手动记忆方案显得更加tricky
2. 唬人的沙漏模型用于主题分割
3. 日语段落分割先行研究的追实验

接下来我的想法是做日语的句子&段落排序。如果你问我为什么选择日语，原因是我不敢再眼高手低。我至今一篇论文都还没有发过。虽然我有上ACL的壮志，却已经遭到了屡屡挫折。

至于方法，我是打算先在训练集上训练个句子级别的VAE——多头自注意作为encoder，LSTM作为decoder，每次输出一个单词——用来做句子embedding，顺便可以开拓一下日语VAE的领域，然后将decoder去掉，接上MLP作为分类器作为段落划分，又或者接上LSTM作为顺序器用于排序。Decoder可以多种多样，但是VAE作为encoder是矢志不移，因为我已经被句子同构深深吸引了，而这在日语领域似乎还是一片处女地。

而至于VAE怎么训练就是另一个问题了，我可以用类似BERT的填空，也可以用排序，都是可以的。
祝日なのでバーチャル空間で寿司打をする

## やったこと
Oculusアプリの[Virtual Desktop](https://www.oculus.com/experiences/quest/2017050365004772/?locale=ja_JP)を使用し、VR空間上のPC画面でみんな大好き [寿司打](http://typingx0.net/sushida/play.html) をやりました

## 寿司打とは
エンジニアは寿司打より生まれ、寿司打に還ると言われています

正しい情報はこちらをご覧ください
http://typingx0.net/sushida/

## 使ったもの
- Oculus Quest2
- MacBook(macOS Big Sur 11.2)
- Virtual Desktop, Virtual Desktop Streamer

## セットアップ
こちらの記事を参考にさせていただいています
https://note.com/ohbashunsuke/n/n45222684c046

### Oculus側
アプリストアから、Virtual Desktopをインストールします
(2021.2.23時点では1,990円でした)

インストール直後にアプリを開いた状態の画面です
**No computer found**と表示されますが、PC側での設定をこのあと実施しますので問題ありません
<img width="500px" alt="VirtualDesktop.Android-20210223-121258.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463957/fe2fee5c-7a68-2c17-4d94-863fda970d85.png">


### MacBook側
Virtual DesktopのWebサイト([https://www.vrdesktop.net/](https://www.vrdesktop.net/))からMacクライアントソフトをダウンロード、インストールします
参考記事内ではDiscord経由で取得されていますが、確認時直接ダウンロードが可能となっていました
<img width="500px" alt="www.vrdesktop.net_.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463957/2f389182-352e-12ad-c004-09afe64f5254.png">

インストールされたVirtual Desktop Streamerを開くと次のような画面が表示されます
Oculus Username に自分のユーザー名を入力してSave
ユーザー名は`No computer found`の画面にも表示されますので、同じものを入力します
<img width="500px" alt="screenshot 2021-02-23 12.10.26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463957/c247dbc8-2cb9-1f7a-8cc6-5b4fc2ce18ba.png">

### 設定完了〜接続
設定が完了したら、Oculus側で一度アプリを再起動します
クライアントの情報が表示され、自動で接続が開始し・・・
<img width="500px" alt="VirtualDesktop.Android-20210223-120711.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463957/d8455c58-8a69-0ca9-8553-50bbc6f3effb.png">

<img width="500px" alt="screenshot 2021-02-23 11.56.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463957/02e85076-63c8-1391-4292-1847334b7448.png">
きました！！！！！！

<img width="500px" alt="screenshot 2021-02-23 11.57.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463957/d6536af5-abec-50ff-3649-766d9c7f4ac4.png">

こんな景色のいい場所で寿司打ができるなんてエンジニア冥利に尽きますね

## 寿司打る
早速、本題の寿司打を開始します

![ezgif-6-c755eb6dab35.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463957/9e78db1d-9316-5faf-fdab-9226950797ac.gif)
正直もっとカクカクするんだろうなと思っていましたが、ミラーリングの遅延はほとんど気になりませんでした（すごい）
これで日々のルーティーンである寿司打にも一層身が入りそうです

## 最後に
キーボードまではVR空間に持っていけず、タイピングは物理キーボードを用いて行いました

ゆくゆくはバーチャルキーボードの使用感も向上し、完全VRで寿司打ができる日が来るのでしょうか
考えただけで興奮しますね


おわり
【完全初心者向け】求人情報を一括で自動的に取得する方法公開！

元記事：https://www.octoparse.jp/blog/a-complete-guide-to-web-scraping-job-postings/

2020年以来、新型コロナウイルス感染症の感染拡大による景気低迷によって悪化に転じました。総務省が12月25日発表した11月の労働力調査によると、完全失業率は2.9%になりました。一方、厚生労働省が発表した8月の有効求人倍率は8カ月連続の低下となりました。

つまり、同倍率は仕事を探す人1人に対し、何件の求人があるかを示します。企業からの有効求人は前月から0.9%増えたものの、働く意欲のある有効求職者が4.7%増えました。統計によると、現在は求人に対して、求職者の数が上回っている状態です。

市場競争がますます激しくなっている不景気の中では、まだまだチャンスが残っています。そのチャンスは一歩先に有益な情報を手に入れた会社や人たちにあります。

![求人情報収集.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262932/2aa68f03-7606-39a9-39c1-c8c7a1f301ae.png)

**企業側にとって**、早めに求人情報を手に入れることは、
・仕事の傾向や労働市場に合わせて自社事業をを分析・調整できる
・競合他社の動向を追跡・分析できる
・営業リストを整理・作成できる
.......

**個人側にとって**、早めに求人情報を手に入れることは、
・仕事の傾向や労働市場を分析できる
・目指すべき方向を調整できる
・就職チャンスをつかめる
.......

だが、データ収集はそんなに簡単にできることではないですね。特に、初心者にとっては短時間内での実現がさらなる不可能です。それではどのように求人情報を取得すればよいでしょうか。

これからこの記事で**3つの取得方法を紹介し、さらにそのメリットとデメリット**も一緒にご参考いただければと思います。

 

#方法一：自分でクローラーをセットアップする#
簡単に言うと、ご自力でデータを取得する[**Webスクレイピング**](https://www.octoparse.jp/)を作るということです。本記事ではプログラムを作る詳細を紹介しません。もしご興味があれば、こちらの記事をご参考いただきます。

**参考記事：**[**【Pythonクローラー入門】クローリング スクレイピング方法 総まとめ**](https://www.sejuku.net/blog/69383)

 

**メリット：**
1) クローリングプロセスを完全にコントロールことができる
2) コミュニケーションの手間が少なく、迅速な対応が可能

**デメリット：**
1) 専門知識を勉強する時間が必要
　Webスクレイピングは、高いレベルな技術が必要とする独特なプロセスであり、特に人気のあるWebサイトのいくつかからスクレイピングする必要がある場合や、定期的にデータを大量に抽出する必要がある場合です。
2) 配置・運用・保守の技術力が必要
　Webサイトのレイアウトやコードが更新するたびに、常にクローラーを動かすようなメンテナンス時間と技術力が必要です。

 

#方法二：[**データ代行収集サービス（DaaS）**](https://service.octoparse.com/ja-jp/data-service)を依頼する#
いわゆるお金を払ってデータ取得の作業を他の企業や個人などに依頼するということです。「餅は餅屋」という通り、何事においても、その道の専門家に任せるのが一番ですね。
一般的には、依頼する時にサイト数、それからサイトのHTML構造や取得するデータ量などによって料金が異なってきます。


**メリット：**
1) IT専門知識を学習する時間を省く
2) 事務負担及び収集時に発生するリスクを軽減
　高度なセキュリティ環境であるデータセンター内にて、効率的かつ安全、正確にデータの収集を行うことができます。

**デメリット：**
1) 料金が比較的に高くなる
2) 依頼先とのコミュニケーションに時間がかかる
3) 依頼先にサイトの取得可能性を検証してもらい、発注してから納品までのセットアップ時間が長い

 

#方法三： Webスクレイピングツールを使う#
 

多くの人はまだ知らないと思いますが、実際にテクノロジーの進歩により、Webスクレイピングを自動化してくれるツールもあります。
完全な素人でも使えるような[**Webスクレイピングツール**](https://www.octoparse.jp/)はWebページのHTML構造を自動的に識別したり、必要なデータを自由に選択したり、自由にカスタマイズすることなどの機能が備えていています。もしご興味があれば、こちらの記事を見てみてください。

参考記事：[**無料で使えるスクレイピングツール9選**](https://qiita.com/Octoparse_Japan/items/ebeb6002503fb138a4a0)

 

**メリット：**
1) コストが低い
2) 初心者にやさしい
3) 自由な時間に取得可能
4) カスタマイズ自由度が高い
5) 高度なカスタマイズが可能
6) 低メンテナンスコスト

**デメリット：**
1) プログラム作成ほどではないけど、操作設定を慣れる時間が必要
2) ベンダーさんのサーバー不安定による故障がよくある

 

前では求人情報を取得する3つの方法を紹介しましたが、これからは無料WebスクレイピングツールのOctoparseを使って、Indeedから「東京 エンジニア」の下記求人情報をスクレイピングできました。

Octoparseを[**インストール**](https://www.octoparse.jp/Download)してからの操作設定の詳細はここで紹介しませんので、興味のある方はこちらの[**チュートリアル**](https://helpcenter.octoparse.jp/hc/ja/articles/360015592500-Indeed%E3%81%8B%E3%82%89%E6%B1%82%E4%BA%BA%E6%83%85%E5%A0%B1%E3%82%92%E3%82%B9%E3%82%AF%E3%83%AC%E3%82%A4%E3%83%94%E3%83%B3%E3%82%B0%E3%81%99%E3%82%8B)を参考してください。
![octoparse_indeed.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262932/c93043be-45fa-eefe-1f5d-f3363bf822b1.png)
 

**参考記事：**
[ゼロからWebクローラーを構築する方法](https://www.octoparse.jp/blog/how-to-build-a-web-crawler-from-scratch-a-guide-for-beginners/)
[売上予測に役たつ！企業メールアドレスを取得するツール10選](https://www.octoparse.jp/blog/3-web-crawling-tools-for-extracting-web-data/)
Dockerを利用してnginxをrailsプロジェクトへの導入手順をまとめてみました

railsのアプリケーションサーバpumaではなく、nginxをウエブサーバーとして、導入してみましたので、メモとして、導入手順をここに残しておきました。

#nginx ウェブサーバーの導入手順
##railsのDockerfileを修正
　※puma.sockを配置するディレクトリを作成（socketsとはnginxとの通信用）
　RUN mkdir -p tmp/sockets
##nginx用のフォルダを新規作成
　./containers/nginx/
##nginx用のDockerfileと設定ファイルを格納
　./containers/nginx/Dockerfile
　./containers/nginx/nginx.conf
##docker-compose.ymlファイルを修正
　　railsとnginx通信用のフォルダをマウント
　　nginx起動用のサービスを追加

```docker:Dockerfile
　 app
      build: .
      volumes:
        - .:/webapp
        #nginxとpuma間の通信では、ボリュームズのマウントが必要
        - tmp-data:/webapp/tmp
      command: rails s
      depends_on:
        - db
    web:
      build:
        context: containers/nginx
      volumes:
        #nginxとpuma間の通信では、ボリュームズのマウントが必要
        - tmp-data:/webapp/tmp
        - ./containers/nginx/log:/var/log/nginx/
      ports:
        - 80:80
      depends_on:
        - app
       
```

##puma.rbを修正
###pumaのhttp機能ではなく、nginxを使用する理由
puma+railsのみで稼働する場合、大量なアクセスが来る場合、システム全体のパフォマンスが大幅に落ちる可能性があるその代わりに、nginxはCで作成されたため、処理性能が高く、使用メモリが少ない特徴で、
　・ビジネスロジックなどの動的処理が必要ない静的処理をnginxで対応、
　・ビジネスロジックが必要な動的処理をpuma+railsでrailsで対応
という組み合わせで、システム全体のパフォマンスを高めることが可能
Djangoの動的モデルに関するリファレンス


Djangoで動的モデルを扱う方法に関するリファレンス。
Djangoで扱うデータベースは、モデルクラスとして予め定義しておかなければならない。
しかし、例えば「アンケートの回答結果」を「行：個票、列：設問番号」で保存するような場合、事前には個票数も設問数も確定できず、動的モデルが必要となる。

## 動的モデルの実装

### Djangoフレームワークで動的モデルを使用する
https://jpcloud.net/q/veughlxn

### Dynamic models（公式のWiki）
https://code.djangoproject.com/wiki/DynamicModels

### ↑その日本語解説
https://cream-worker.blog.jp/archives/1076337096.html

### Djangoでスキーマに動的にテーブル作成、動的にModel生成
https://qiita.com/kimisyo/items/aae530d2ce1a49692d94


### StackOverflow：
https://stackoverflow.com/questions/31835362/using-dynamic-models-in-django-framework
Dockerを利用してのrails6.0.3.4開発環境の構築手順をまとめてみました

Dockerを利用してのrails6.0.3.4開発環境を構築してみましたので、構築手順をメモとして、ここに残しておきます。

#Dockerを利用してのrails6.0.3.4開発環境の構築手順

・mkdir circle_test：プロジェクトフォルダを作成
・cd circle_test：プロジェクト
・Dockerfile、Docker-compose、Gemfile、Gemfile.lockをフォルダに格納
・docker-compose build：railsをインストール
・docker-compose run web rails new . --force --database=postgresql --skip-bundle：・・railsアプリケーションをセットアップ
・exit：コンテナへの接続を切断
・docker-compose build：railsの関連gemを再インストール
・docker-compose run web rails g scaffold procudct name:string price:string：サンプルコードを作成

```ruby:config/database.yml

  development:
    host: db
    user: postgres
    port: 5432
    password: postgres
  test:
    host: db
    user: postgres
    port: 5432
    password: postgres
```

・docker-compose run app rails db:create：データベースを作成
・docker-compose run app rails db:migrate：テーブルを作成
・docker-compose run app rails webpacker:install 
・docker-compose run app rails webpacker:compile
・routes.rbにroot 'products#index'を追加
・rails s -b 0.0.0.0：railsを起動(-b 0.0.0.0を指定しないとブラウザからアクセスできない)
ブラウザでhttp://localhost:0000をアクセス
bit全探索で沼った！！



bit全探索で沼ったのでそもそものpythonでのbit演算子周りの知識をまとめた自分用の備忘録です。
##bit全探索のお気持ち表明
####bit全探索のテンプレ

```python
for i in range(2**N):
    for j in range(N):
        if (i>>j) & 1:
```

まずはpythonでbit全探索をするときの基本となるこの形の意味を簡単にまとめる。

**そもそもbit全探索のお気持ちは、 $N$ 個あるYes,Noの選択肢の取り得るすべてのパターン$2^N$通りを全て探索したいということ。**



考え方をステップごとに細分化します。

**ステップ１（一行目）：**
$2^N$パターンのそれぞれの状態に、その状態を表す番号として10進数表記で $0$ から $2^N-1$ をふる。
 
**ステップ２（二行目）：**
それを2進数表記にすると全部で $N$ 桁なので（$N$個の選択しに対して）、

**ステップ３（三行目）：**
それぞれの桁が $0$ か $1$ か（選択しないか選択するか）を順に調べていく。

って感じでしょうか。

**つまるところ、選ぶか選ばないかの状態を、2進数表記のそれぞれの桁が $0$ か $1$ かで紐付けて表現することにより、各ビットが $0$ か $1$ かの判別を繰り返すだけですべての状態の評価ができるということです。**

例えば、「○×クイズを3問解いたとき、解答として考え得る組み合わせを調べる」、という場合は以下の表のようになりますね。

この $2^3$ 通りのパターンをすべて調べるには $3$ bit分を調べればよいとわかりますね。当たり前です。

| 10進数表記 | 2進数表記 | 紐付けられた状態 |
|:-:|:-:|:-:|
|   0|   000|   xxx|
|   1|   001|   xxo|
|   2|   010|   xox|
|   3|   011|   xoo|
|   4|   100|   oxx|
|   5|   101|   oxo|
|   6|   110|   oox|
|   7|   111|   ooo|



bit全探索のお気持ちはここまで。次はbitの扱いについて触れていきます。

##bit演算子のお気持ち表明
組み込み関数の`bin()`を使うことで2進数表記にすることができます。
解説していくのは`>>`と`&`です。

<br />
###論理積`&`のお気持ち
`&`は論理積といわれ、`bin()`で2進数表記の文字列に変換した結果を出力します。

比較する値のビット数が等しいときは、そのまま自然な出力です。

```python
> bin(5)    #'0b101'
> bin(6)    #'0b110'
> bin(5&6)  #'0b100'
> 5&6       #4
```

<br />
一方、ビット数が異なるときは短い方のビットまでの論理積が出力されます。
###**ここがミソ！**

```python
> bin(1)    #'0b1'
> 5&1       #1
> 6&1       #0
```
$5→101, 6→110$ であるので $1$ ビット目はそれぞれ $1,0$ です。
**つまり、 $1$ との論理積をとることで、任意の２進数表記の値の $1$ ビット目が $0$ か $1$ かを判別できるということですね！**

<br />
###右ビットシフト`>>`のお気持ち
`>>`は右ビットシフトと呼ばれています。動作は以下の通り。


```python 
> bin(5)    #'0b101'
> bin(5>>1) #'0b10'
```

出力を見ての通りで、右に $1$ ビットシフトしているのがわかります。
**何がうれしいかというと、 $1$ との論理積をとったときに今度は次のビットが $0$ か $1$ かの判別ができるということですね。**
`&`と組み合わせることで一つずつビットをずらしながら調べることができますね。


##辞任表明
畢竟、冒頭のコードの、

```python
for i in range(2**N):
    for j in range(N):
        if (i>>j) & 1:
```
というのは、判定するビットを右に一つずつずらして全てのビットに対して順に $1$ との論理積をとることで、そのビットが立っているのか立っていないのかを判別していたのです。

繰り返しになりますが、bit全探索のうまみは一対一対応で各状態を $0$ と $1$ の表記で表せることであり、かつbit演算子を使えば簡単に全パターンを評価できるということです。
【Qiita】Markdownどう書く？【初投稿】


![WindowsOSInfo](https://img.shields.io/badge/WinOS-Windows--10--10.0.19041--SP0-brightgreen) ![PythonVer](https://img.shields.io/badge/PythonVer.-3.8.3-brightgreen)

#初投稿
MarkDown記法の学習とテストです。
[@shizumaさんの記事](https://qiita.com/shizuma/items/8616bbe3ebe8ab0b6ca1)を参考に書きます。

## コードハイライト
私はPythonを使っているため、Pythonの例を示します。

```python:hello.py
print('hello world')
```

'\`\`\`'でコードを囲みます。頭の'\`\`\`の直ぐ後にpythonと書き、ファイル名を表示したければ続けて:_file_name_.pyと書きます。


## 引用
各行に対し一つの'>'を書くだけだそうです。
>つまり、一つの'>'でこのように表示され、
>>二つの'>'でこのように表示されます。

## 文字の修飾
イタリックは'\_'または'\*'で文字を囲むそうです。
_このとおり_
太字は'\_\_'または'\**'で囲むそうです。
__このとおり__

## 役物のエスケープ
'\\'でエスケープできます。たとえば、上の「文字の修飾」では、文中において'\_'や'\*'などの役物が表示されています。役物をエスケープでエスケープさせているから表示されているのです。

## リスト

数字とピリオドでリスト表示されるはずですが、されないようです。（あるいは、これで表示されたことになっているのかな？）

 1. リスト
 2. リスト
 3. リスト

'\*''\+''\-'はちゃんと機能するようです。

 * List
  + List
  - List

リスト表示させるブロックは、その前後に空行を挿入する必要があるそうです。テーブルに対しても同様に空行が必要だそうです。

## テーブル
二行目がポイントだそうで、二行目の'\:'の位置で調整するそうです。以下ではすべて中央揃えにします。

|*|2|3|
|:---:|:---:|:---:|
|4|8|12|
|5|10|15|

## 「この記事はどのように記述されてるんだろうか？」
Qiitaの記事で参考にしたいものがあれば、その記事のURLの最後に.mdをつけるとMarkDownで見れます。

## 謝辞
[@shizuma](https://qiita.com/shizuma)さん、大変参考になりました。ありがとうございました。
actでUnable to resolve v1: reference not foundが出たときの解決方法

act実行時に少し詰まってしまったので備忘録として残しておきます。

#現象
[pronto-rubocop](https://github.com/prontolabs/pronto-rubocop)のGitHub Actionsを、actのDry runで実行したところ、ruby/setup-rubyのv1を見つけられないエラーが発生しました。

```
> act pull_request -P ubuntu-latest=nektos/act-environments-ubuntu:18.04 -n
・・・略・・・
*DRYRUN* [Checks/unit_tests-43] ⭐  Run ruby/setup-ruby@v1
*DRYRUN* [Checks/unit_tests-43]   ☁  git clone 'https://github.com/ruby/setup-ruby' # ref=v1
*DRYRUN* [Checks/unit_tests-43] Unable to resolve v1: reference not found
*DRYRUN* [Checks/unit_tests-43]   ❌  Failure - ruby/setup-ruby@v1
Error: reference not found
```

# 調査
actのissueに類似現象が記載されていました。
[Unable to resolve v1: reference not found #311](https://github.com/nektos/act/issues/311)
このissueをたどっていくと、気になるコメントを見つけました。
>The issue occurs if v1, v2 refs are branches, not tags. But yes, it's very annoying and needs to be fixed.

v1やv2がタグになく、ブランチにあるとこの問題が発生するようです。
[ruby/setup-ruby](https://github.com/ruby/setup-ruy)を確認してみると、ブランチにはv1がありますが、タグにはv1はなくv1.0.0がある状態でした。
ブランチ: https://github.com/ruby/setup-ruby/branches
タグ: https://github.com/ruby/setup-ruby/releases/tag/v1.0.0

なお、この問題はすでにPull Request([Fix "reference not found" error #433](https://github.com/nektos/act/pull/433))が作成され、マージ済みとなっていました。この変更では、まずタグに該当バージョンがないか探し、なければブランチで該当バージョンを探す処理となっているようです。

リリースバージョンは[v0.2.19](https://github.com/nektos/act/releases/tag/v0.2.19)となっており、私が使っているバージョンを確認すると`0.2.16`だったので、今回の問題の原因はこのことだったようです。

# 対応
actはbrewで入れたので、`brew upgrade`を行いactのバージョンアップを行いました。
楽天証券サイトにPythonとSeleniumを使ってログインする

楽天証券のサイトにPythonとSelenium使ってログインする方法を解説します。

※2021/02/23時点の情報です

## 環境
- Windows 10
- Python 3.8
- Selenium 3.141.0

## 全体の処理の流れと注意点
全体の処理の流れについては、下記記事に詳しく書いたのでこちらもあわせて確認してみてください。楽天銀行の例になっていますが、処理の流れは同じです。

https://qiita.com/yoshi2045/items/2fff5bf5f0fa763f7104

また、下記記事では他サイトのサンプル一覧と注意点を解説しているのでこちらも参考にしてみてください。

https://qiita.com/yoshi2045/items/a58a7fbebcb9faad3e15

## サンプルコード全文

```python
#
# 楽天証券サイトへログインしてデータを取得する
#

import json
from selenium.webdriver import Firefox, FirefoxOptions
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec

# 設定ファイルからログイン情報を取得
login_info = json.load(open("login_info.json", "r", encoding="utf-8"))

# ログインサイト名
site_name = "sec_rakuten"

# ログイン画面URL
url_login = login_info[site_name]["url"]

# ユーザー名とパスワードの指定
USER = login_info[site_name]["id"]
PASS = login_info[site_name]["pass"]

# Firefoxのヘッドレスモードを有効にする
options = FirefoxOptions()
options.add_argument('--headless')

# Firefoxを起動する
browser = Firefox(options=options)

# ログイン画面取得
browser.get(url_login)

# 入力
e = browser.find_element_by_id("form-login-id")
e.clear()
e.send_keys(USER)
e = browser.find_element_by_id("form-login-pass")
e.clear()
e.send_keys(PASS)

# ログイン
frm = browser.find_element_by_name("loginform")
frm.submit()

# ページロード完了まで待機
WebDriverWait(browser, 10).until(
    ec.presence_of_element_located((By.ID, "asset_total_possess_btn"))
)

# ログインできたか確認（画面キャプチャ取る）browser.save_screenshot("../screenshot/sec_rakuten/home.png")

browser.quit()
```


## ログイン情報設定ファイル
サイトURLやログイン情報（IDやパスワード）は、JSON形式のファイルに保持するようにしています。以下のサンプルでは楽天銀行と楽天証券の2サイトの情報と設定しています。

"id", "pass"の値を書き換えればそのまま使えるはずです。

なお、このファイルだけは絶対に漏洩しないよう、管理方法に注意しましょう！

```json:login_info.json
{
  "bank_rakuten": {
    "id": "1234567890",
    "pass": "password",
    "url": "https://fes.rakuten-bank.co.jp/MS/main/RbS?CurrentPageID=START&&COMMAND=LOGIN"
  },
  "sec_rakuten": {
    "id": "1234567890",
    "pass": "password",
    "url": "https://www.rakuten-sec.co.jp/ITS/V_ACT_Login.html"
  }
}
```
【jquery,js】URL・大きさを指定してウィンドウを開く [disabledプロパティ,value,confirm,open,switch,elementsプロパティ] [js06_20210223] 

####  <font color='orange'>処理の概要</font>
URLを指定して任意の大きさで新しいウィンドウを開く

##### 処理のフロー：
　(1)入力された値（リンク、幅、高さ）が入力されているかをチェックする
　(2)入力された値（リンク、幅、高さ）を取得する
　(3)ポップアップメッセージを出力する
　(4)Yesが選択されたら新しいウィンドウを開く

####  <font color='orange'>画面イメージ</font>

#####画像１
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647299/3f92cd57-97b2-cbee-53fb-bdfe60ead47f.png" width="500px">

#####画像２
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647299/94be1cf7-5e40-8e2f-02db-e7e2863989e4.png" width="600px">


####  <font color='orange'>ソースコード</font>
```html:index.html
    <body onload="init()">
        <form name="form1">
            <p>
                <input type="button" name="btnOpen" value="Open" onclick="openWindow()">
                <input type="button" name="btnClose" value="Close" onclick="closeWindow()">
            </p>
            <p>URL:<input type="text" name="txtUrl"></p>
            <p>幅:<input type="text" name="txtWidth"></p>
            <p>高さ:<input type="text" name="txtHeight"></p>
        </form>
    </body>
```

```javascript:main.js
function init(){
    document.form1.txtUrl.value = "http://www.ank.co.jp";
    document.form1.txtWidth.value = "600";
    document.form1.txtHeight.value = "480";
    document.form1.btnClose.disabled = "true";
}

function openWindow(){
    var errMsg = errorCheck();
    
    if (errMsg !=""){
        alert(errMsg + "が入力されていません");
        return;
    }

    var url = document.form1.txtUrl.value;
    var width = document.form1.txtWidth.value;
    var height = document.form1.txtHeight.value;

    if (confirm("新しいウィンドウを開いてもよいですか？")){
        mywin = window.open(url,"","width=" + width + ",height=" + height);
        document.form1.btnClose.disabled = false;
    }
}

function closeWindow(){
    mywin.close();
    document.form1.btnClose.disabled = true;
}

function errorCheck(){
    var errMsg = "";

    for(i=0; i<document.form1.length; i++){
        if(document.form1.elements[i].type == "text" 
        && document.form1.elements[i].value == ""){
            switch(document.form1.elements[i].name){
                case "txtUrl":
                    errMsg += "[URL]";
                    break;
                case "txtWidth":
                    errMsg += "[幅]";
                    break;
                case "txtHeight":
                    errMsg += "[高さ]";
                    break;
            }
        }   
    }
    return errMsg;
};
```



####  <font color='orange'>ポイント</font>
html：
(1)各ボタンにメソッドを紐付ける
js：
(1)値を取得するまえに入力チェックを行う（errorCheckメソッド）
(2)window.openメソッドの第一引数は、「url」、このほかオプションの設定が出来る
(3)openされたら、closeボタンオブジェクトを有効化する。
(4)form1のオブジェクトを「form1.elements[i]」で配列として取得し、switchに渡して制御する

####  <font color='orange'>参考資料</font>
JavaScript(仕事の現場でサッと使える！デザイン教科書)　p74
cliとphp-fpmでPHPのバージョンが異なるときのcomposer require方法

# TL;DR
php-fpmで使用されてるのと同じPHPバージョンを使用して`php composer.phar require`を実行する。

```bash
$ php7.2 composer.phar require abraham/twitteroauth
```

#環境説明
今回の環境では、cliはPHP8.0が使用されていて、

```bash
$ php --version
PHP 8.0.2 (cli) (built: Feb 14 2021 14:21:15) ( NTS )
Copyright (c) The PHP Group
Zend Engine v4.0.2, Copyright (c) Zend Technologies
    with Zend OPcache v8.0.2, Copyright (c), by Zend Technologies
```

php-fpmではPHP7.2が使用されていた
![スクリーンショット 2021-02-23 11.03.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156669/ba773c48-dc5b-e826-a0e7-1b8b05aa0294.png)

そのため、composerがインストール時に参照するphpバージョン(cli: PHP8.0)と、サーバがPHPを実行するときに使用するphpバージョン(php-fpm: PHP7.2)が異なってしまい、互換性の問題が発生した。

# 設定方法
## 1. composerのインストール
現在(2021/2/23)最新版の`composer v2.0.9`と`PHP7.2`の組み合わせではサポート外というエラー(`Composer detected issues in your platform: Your Composer dependencies require a PHP version ">= 7.3.0".`)が出たので、[Composer本体のバージョンを1系に固定化する](https://qiita.com/ucan-lab/items/5a48f1a3c7a4c358223e)を参考に、`composer v1.10.20`をインストールした。
(`composer v1.10.20`と`PHP7.2`の組み合わせではエラーは発生しなかった。)

```bash
$ curl -sS https://getcomposer.org/installer | php -- --version=1.10.20
```

## 2. composer.pharでライブラリをインストール
composerがインストールできたら以下のコマンドでライブラリをインストールできるが、

```bash
$ php composer.phar require abraham/twitteroauth
```

先程も書いたように、cliとphp-fpmで使用するPHPのバージョンが異なっているのでこれでは問題が起きる。

それを回避するにはcliとphp-fpmで同じPHPのバージョンを使用する。今回の環境ではphp-fpmはPHP7.2が使用されているのでcliでもPHP7.2を使用する。

```bash
$ php7.2 composer.phar require abraham/twitteroauth
```

あとは通常通り`require_once "vendor/autoload.php";`でライブラリを使用できる

```PHP
<?php
require_once "vendor/autoload.php";
use Abraham\TwitterOAuth\TwitterOAuth;

$connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET, $access_token, $access_token_secret);
$content = $connection->get("account/verify_credentials");
```
初学者がDockerを使ってDjangoアプリをgunicorn上で動作させる

# 概要
Dockerを使ってDjangoアプリをgunicorn上で動作させたいと思います。話を簡単にするため、Djangoアプリは作成せず、ロケットが飛ぶ例の画面を表示させるだけにしたいと思います。

何分にも初学者ですので間違っている部分もあると思いますが、よろしくお願いします。m(_ _)m

# Dockerfileを作成する
```
# python3をベースにする
FROM python:3

WORKDIR  /code
COPY requirements.txt /code/
RUN pip install -r requirements.txt
```

# requirements.txtを作成する
```
Django==2.2.6
gunicorn
```

# docker-compose.ymlを作成する
```
version: '3'

services:
  web:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: django
    ports:
      - '8000:8000'
    volumes:
      - '.:/code'
    tty: true
    stdin_open: true
```

# docker imageをビルドして、コンテナを立てる
```
$ docker-compose up -d
```

# コンテナの中に入る
```
$ docker-compose exec web bash
```

# Djangoプロジェクトを作成する
```
$ django-admin startproject conf .
```

# 一旦、開発用サーバーを起動してみる
```
$ python manage.py runserver 0.0.0.0:8000
```
ブラウザを開き、localhost:8000にアクセスします。ロケットが飛んでいればOKです。
![スクリーンショット 2021-02-23 11.43.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689015/bdaefb94-41fb-ae09-8525-500f01d7055a.png)

ターミナルに戻ってCtrl+cを押下し、開発用サーバーを停止させる。

# gunicorn上でDjangoアプリを動作させる
開発用サーバー上で動くことが確認できたので、今度はgunicorn上で動作させたいと思います。

```
$ gunicorn --bind 0.0.0.0:8000 conf.wsgi:application
```
ブラウザを開き、localhost:8000にアクセスします。ロケットが飛んでいればOKです。見た目は開発用サーバーと同じですが、gunicorn上でDjangoアプリが動作しているはずです。

![スクリーンショット 2021-02-23 11.43.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689015/bdaefb94-41fb-ae09-8525-500f01d7055a.png)
python文字コード推測

[前回まで](https://qiita.com/kirin123kirin/items/1082d3c1564b745dcb4f)分割キーボードを作っていたが完成しやっと手になじんできた。

# バイトデータから文字コードを推測する

[nkf](https://pypi.org/project/nkf/)か[chardet](https://pypi.org/project/chardet/)のライブラリが必要。

chardetはちょっと遅い気がするが、判別可能な文字コード種別が豊富
nkfはちょっと速い気がするが、判別可能な文字コード種別が少ない。
日本語文字コードしか扱わないという前提ならばnkfの方が吉？。

## nkfを利用する場合

```python
import nkf
def getencoding(dat:bytes):
    if b"\0" in dat:
        return None
    enc = nkf.guess(dat).lower()
    if enc and enc == "shift_jis":
        return "cp932"
    elif enc == "binary":
        return None
    else:
        return enc
```

## chardetを利用する場合
```python
import chardet
def getencoding(dat:bytes):
    return chardet.detect(dat)["encoding"]

```

## 使い方

```python

>>> getencoding("これは何？".encode("utf-8"))
'utf-8'

>>> getencoding("これは何？".encode("sjis"))
'cp932'

>>> getencoding("これは何？".encode("euc-jp"))
'euc-jp'

>>> getencoding("Какво е какво?".encode("cp1251"))
'windows-1251' # chardetベースのgetencodingのみ判別できた

```

## 活用例
文字コード不明のテキストファイルがある場合、
バイナリモードで読み込んでgetencodingに渡せば推測文字コードが得られる。
どこまで正確なのかはよくわからないが、、、

```python
>>> fname = "/tmp/eucjp.txt"
>>> with open(fname, "rb") as f
...    enc = getencoding(f.read())
...    print(enc)
'euc-jp'

```

1Kバイトでも読めば十分なデータであればf.read(1024)としても良いだろう。

```py
# discovery.py
import sys
from glob import glob

for a in sys.argv[1:]:
    for fname in glob(a):
        with open(fname, "rb") as f:

            LT = f.readline()[-2:]

            if LT == "\r\n":
                print("改行コード:CRLF")
            elif LT[-1] == "\r":
                print("改行コード:CR")
            elif LT[-1] == "\n":
                print("改行コード:LF")
            else:
                print("改行コード:不明")

            f.seek(0)
            print("文字コード:" + getencoding(f.read(1024)))

```


数百MB~数GBのテキストファイルの文字コードと改行コードを調べたいため僕は以下のように回す


```bash
$ python discovery.py /tmp/*.txt /tmp/*.csv
```
Input関連まとめ

<b>1,Input.GetAxisとInput.GetAxisRawの違いとは？</b>

・Input.GetAxisはfloat型で-1から1までの値を返す。

・Input.GetAxisRawも同様にfloat型で値を返すが、常に-1,0,1いずれかの値をとる。

 入力後なめらかに値を変化させたい>>GetAxis,
 決まった値を常にとってほしい>>GetAxisRaw

<b>2,Input.MousePositionについて</b>