OmniAICreator/Qiita-1.07M huggingface dataset:
Python3 で 十字キーが入力された判定をとる方法

## はじめに
curses モジュールを使うことでキーの判定を取ることができます。それに依存しない方法を以下に書きます
https://docs.python.org/ja/3/library/curses.html#constants

## まえがき
自分用のメモです。愚直実装です。
やりたいことは十字キーなど特殊な文字が入力されたことを検知することです。

前提としてUnicode制御文字の知識があることが望ましいです。
[wikipedia](https://ja.wikipedia.org/wiki/%E5%88%B6%E5%BE%A1%E6%96%87%E5%AD%97)

## 詰まったところ
getchは入力を1文字ごとに取得します。しかし、矢印キーは3回文字分の入力がありました。 例えば上矢印は`27 91 65` とはいってきます。このままでは、矢印キーなどの特殊なキーを判定することができないばかりか、望まない入力を受け取ってしまいます。そこで、以下のように実装しました。


## ソース
getch 1文字の入力を受け取る関数
ord は文字をUnicodeに変換する関数、
chr はUnicodeを文字に変換する関数です。
自分用のデバッグも兼ねて、冗長なコードになっています。

```python
# inputの代わりに、1文字ずつ入力を受け取る関数を用意。
# try の中はWindows用、except 野中はLinux用
try:
    from msvcrt import getch
except ImportError:
    import sys
    import tty
    import termios
    def getch():
          
            fd = sys.stdin.fileno()
            old = termios.tcgetattr(fd)
            try:
                tty.setraw(fd)
                return sys.stdin.read(1)
            finally:
                termios.tcsetattr(fd, termios.TCSADRAIN, old)

# Unicode制御文字のエイリアス
EOT = 3
TAB = 9
ESC = 27

# メインループ
while True:
    key = ord(getch())
    if key == EOT:
        break
    elif key == TAB:
        print('keydown TAB')
    elif key == ESC:
        key = ord(getch())
        if key == ord('['):
            key = ord(getch())
            if key == ord('A'):
                print('keydown uparrow')
                continue
            elif key == ord('B'):
                print('keydown downarrow')
                continue
            elif key == ord('C'):
                print('keydown leftarrow')
                continue
            elif key == ord('D'):
                print('keydown rightarrow')
                continue
    else:
        message = f'keydown {chr(key)}'
        print(message)
```
## 実行した結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489653/38119dbb-194d-36e2-4b50-b15dda07fd8d.png)
きちんと判定が取れているのがわかります。

## 終わりに
今回はコードが冗長になるため実装しませんでしたが、特殊なキーを入力したときのUnicodeを見て、条件分岐で全列挙すれば、判定がとれます。この記事の類似コードはアプリケーションを自作するときに役に立つかもしれません。他にいい書き方を知っている人がいたら教えてください。

## 参考
- https://torina.top/detail/428/
- https://stackoverflow.com/questions/12175964/python-method-for-reading-keypress
【カイ二乗検定】観測度数を渡すと期待度数を返すGoogleスプレッドシート関数（GAS）

（注意：筆者は統計については素人レベルなので、この関数を利用した検定の正確性について保証することはできません）

ExcelやGoogleスプレッドシートではカイ二乗検定のためにCHISQ.TESTという関数がありますが、第1引数に観測度数の範囲、第2引数に期待度数の範囲を渡す必要があります。結果として、カイ二乗検定でのp値を返してくれます。

```
CHISQ.TEST(観測度数範囲, 期待度数範囲)
```

観測度数が分かれば期待度数も自明なのにわざわざ別々にデータを用意しなくてはいけないのが面倒くさかったので、観測度数から期待度数を返してくれるGoogleスプレッドシート関数をGoogle Apps Script(GAS)で作りました。備忘録として残しておきます。

```javascript
function getExpectedFreq(range) {
  /** 
   * 数値文字列の配列から合計値を計算するための内部関数。
   * 整数へのparseに失敗したらエラーを投げる
   */
  const sumStrArray = (arr) => (arr.reduce((prev, current) => {
    const num = parseInt(current);
      if (isNaN(num)) {
      throw `failed to parse string to int: ${current}`;
    } else {
      return prev + current;
    }
  }, 0));
  /* 整数の配列から合計値を計算するための内部関数 */
  const sumIntArray = (arr) => (arr.reduce((prev, current) => prev + current));

  /* スプレッドシートで渡された引数が配列だったら処理を続ける。配列ではなかったらエラーを返す */
  if (Array.isArray(range)) {
    /* 横（行）の周辺度数を計算する */
    let marginX;
    try {
      marginX = range.map(row => sumStrArray(row));
    } catch(e) {
      throw e;
    }
    
    /* ref. [JavaScriptで二次元配列の行列を転置するワンライナー](https://qiita.com/kznr_luk/items/790f1b154d1b6d4de398) */
    const transpose = a => a[0].map((_, c) => a.map(r => r[c]));
    
    /* 縦（列）の周辺度数を計算する。計算のために行列を転置しておく */
    const transposedRange = transpose(range);
    let marginY;
    try {
      marginY = transposedRange.map(row => sumStrArray(row));
    } catch(e) {
      throw e;
    }
    
    /* 期待度数を計算する */
    const sumY = sumIntArray(marginY);
    return marginX.map(x => marginY.map(y => x * y / sumY));
  } else {
    throw 'expected range input, but got cell input';
  }
}
```

こんな感じで使えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201031/3e3598e1-2855-89cd-821d-bbd6b0c93868.png)

# 注意点

2x2のクロス集計表では上手く動作していそうなのを確認しました。それ以上の多次元配列でも正しく動作するように実装したつもりですが、ちゃんと試していないので保証はできません。

また、期待度数表のチェックは怠らないようにしましょう。期待度数が少ないと、カイ二乗検定が有効ではないと考えられるケースがあります。

その基準については諸説あるようですが、そのうち一つを引用にて紹介しておきます。

> A.期待度数が１未満のセルがある
> B.期待度数が５未満のセルが、全体のセルの20%以上ある

出典：[独立性の検定―最もポピュラーなカイ二乗検定](https://bellcurve.jp/statistics/blog/14038.html)（統計WEB、2017年）

そして繰り返しになりますが、筆者は統計については素人レベルなので、この関数を利用した検定の正確性について保証することはできません。
（統計に詳しい方からのコメントをお待ちしています）


# 参考
* [CHISQ.TEST関数／CHITEST関数でカイ二乗検定を行う | Excel関数 | できるネット](https://dekiru.net/article/4588/)
* [JavaScriptで二次元配列の行列を転置するワンライナー](https://qiita.com/kznr_luk/items/790f1b154d1b6d4de398)
* [独立性の検定―最もポピュラーなカイ二乗検定 | ブログ | 統計WEB](https://bellcurve.jp/statistics/blog/14038.html)
jupyter-notebookの導入時不具合を一つ解決したのでメモ

　プログラミングほぼ初心者です。パイソン入門の為、jupyter-notebook(Ver6.03)を入れてコマンドプロンプトから起動してみると、エラーがおきました(下記)。調べてる中でなんとなく思いついた方法を試してみたら、うまくいったのでとりあえずのメモです。

★環境：
　Windows10(build:18363.720)
　anaconda(ver 1.7.2)、phython(ver 3.7.6)、jupyter-notebook(ver 6.0.3)


#エラー内容
```
User\HOGE\anaconda3\lib\site-packages\zmq\backend\cython\__init__.py", line 6, in <module>
    from . import (constants, error, message, context,
ImportError: DLL load failed: 指定されたモジュールが見つかりません。
```

全然進まないし、ウェブの動きもディレクトリを移動しない状態になり、色々調べていたら、Qiitaで記事を発見。

- [anacondaでnumpyやscipyのインポートに失敗してしまうバグについて](https://qiita.com/marshi/items/a0f80c5aa3c37b0025d6#_reference-ad9a74bec672fd834dc6)

　
　
同じバグではないですが、どうやらanaconda3\Library\binについて、環境変数Path内の優先度の問題で機能していないっぽい様子。。。もしかしたら、これもそうかもしれない・・・

消すのは怖かったので、パスをとおしてたユーザー環境変数のPATH内の順序を入れ替え、優先度を変えてみました。

#対策
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132088/6f8d8fcc-7d31-a813-5db8-f961f5b2ddcd.png)
※\anaconda3\Library\binを一番上にしました。
　
　
　
　
……そうしたら、なんとうまくインストールできるように！:relaxed:
　

　
　というわけで、確認は全然取ってないけど多分環境変数の競合でインストール障害が起きて多っぽいので、環境変数の順位を入れ替えたら大丈夫っぽい？？ということでした。



##その後
このまま、一番上にしてても大丈夫なのか…と心配に思い、シャットダウンをする前に、順位を戻しました。jupyter-notebookの方は軽く触ってですが、問題はなく動いてそうです。

下手な文章でしたが、以上です。m(__)m
AWS CLI v2をMacにインストールする

# はじめに
AWS CLIバージョン2をMacにインストールします。（バージョン1のときのように、pipの事前導入などが不要となりました）

# 事前準備
AWS CLIバージョン1が先に導入されている場合は、awsコマンドへのパスに注意が必要です。バージョン1をアンインストールするか、シンボリックリンクでの工夫が必要です。

# 手順
### AWS CLIのインストール
1. https://awscli.amazonaws.com/AWSCLIV2.pkg からインストーラーのダウンロード
2. インストーラー（pkgファイル）をダブルクリックして実行し、インストール手順に従ってインストールする
3. ターミナルを起動し、`$ which aws`でawsコマンドが実行できるかを確認する

### AWS CLIの構成
1. ホームディレクトリでconfigの起動 `$ aws configure`
2. アクセスキー、シークレットアクセスキー、リージョン名を入れる

```
$ aws configure
AWS Access Key ID [None]: xxxxxxxx
AWS Secret Access Key [None]: xxxxxxxxxxxxxxxx
Default region name [None]: ap-northeast-1
Default output format [None]: 
```
ホームディレクトリ直下に.awsというフォルダが作成され、その下に、configとcredentialsというファイルが作成される。

# アップグレード
再度インストーラをダウンロードして同じ手順で上書きインストールします。
CentOS 7からデフォルトのFirewalldでIPv6がブロックされる時の対処法

# 概要

Firewalldでserviceやportで通信を許可してもIPv4は通信できてIPv6何故か通信ができないってことがある。
原因はIPv6で利用するICMPv6パケット通信がFirewalldで破棄されているためであり、これを許可すれば通信できるようになる。

# 説明は必要ない人向け

以下のコマンドを一行ずつ入力する。

```Bash
firewall-cmd --permanent --direct --add-rule ipv6 filter INPUT 0 -p icmpv6 --icmpv6-type 128 -j DROP
firewall-cmd --permanent --direct --add-rule ipv6 filter INPUT 1 -p icmpv6 -j ACCEPT
```

permanentなのでreloadする。

```Bash
firewall-cmd --reload
```

# ちょっと詳しい説明

## 1行目

ICMPv6の中のType128 Echo RequestをDROP（破棄）する。
pingを許可する場合は入力する必要は無い。

## 2行目

ICMPv6の全ての通信をACCEPT（許可）する。

# 出典
[Firewalld blocks IPv6, ignores config](https://serverfault.com/questions/769374/firewalld-blocks-ipv6-ignores-config)
Pythonで音声の波形表示

# はじめに
音声の波形を表示するコードを書いた時のメモ。
librosaというライブラリのlibrosa.display.waveplotを使用するのが簡単だが，音声ファイルのデータ数が多い場合エラーが生じるため，素直にmatplotlib.pyplotを使用して表示する方法も記す。
# librosa.display.waveplotを使用する方法
最も簡単な方法。
## コード
```python
import librosa

def make_waveform_librosa(filename):
    y, sr = librosa.load(filename)
    librosa.display.waveplot(y, sr=sr)

make_waveform_librosa("test.mp3")
```
## 結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565938/f3fb56d6-b7f2-a043-1b58-cc69b9af39ef.png)
しかし，読み込む音声ファイルのデータ数が大きい場合，OverflowError: Exceeded cell block limitとなり，上手く波形が表示できないことがある。
# matplotlib.pyplotを使用する方法
matplotlibのバックエンドで動いているaggのchunksizeを変更することができるため，音声ファイルのデータ数が大きい場合にも対応することができる。
## コード
```python
import matplotlib.pyplot as plt
import matplotlib
import librosa

def make_waveform_pyplot(filename):
    y, sr = librosa.load(filename)
    totaltime = len(y)/sr
    time_array = np.arange(0, totaltime, 1/sr)
    mpl.rcParams['agg.path.chunksize'] = 100000
    fig, ax = plt.subplots()
    formatter = mpl.ticker.FuncFormatter(lambda s, x: time.strftime('%M:%S', time.gmtime(s)))
    ax.xaxis.set_major_formatter(formatter)
    ax.set_xlim(0, totaltime)
    ax.set_xlabel("Time")
    ax.plot(time_array, y)
    plt.show()

make_waveform_pyplot("test.mp3")
```
chunksizeは[ここ](https://matplotlib.org/xkcd/users/customizing.html)を参照すると以下のように書いてあったので，適当に100000としておきました。

```python
### Agg rendering
### Warning: experimental, 2008/10/10
#agg.path.chunksize : 0           # 0 to disable; values in the range
                                  # 10000 to 100000 can improve speed slightly
                                  # and prevent an Agg rendering failure
                                  # when plotting very large data sets,
                                  # especially if they are very gappy.
                                  # It may cause minor artifacts, though.
                                  # A value of 20000 is probably a good
                                  # starting point.
```
## 結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565938/b028fb57-3a24-f9d0-8fc0-f42fffdc04a0.png)
librosa.display.waveplotと同じものを出力することができた。

# おわりに
librosa.display.waveplotも内部でmatplotlibを使用しているので，同じようにchunksizeを弄れば表示できるようになるとは思いますが，直接ライブラリのコードを弄る必要があると思われます。
プログラム開発者格差の話が怖い。格下でもLGTMは重い。Qiitaを辞めなければいけないかもしれないのでポエムを詠む。

※ 本記事は **ポエム** です。紹介させていただいている記事の良し悪しを述べてはいません。

**[プログラム開発者格差の話をしよう](https://qiita.com/Rwf-9DH3/items/fe65756c0485f095cc98)** の記事が **怖い**

ニュース番組だと思っていたら、 **隠し撮りのドキュメンタリー映像** が流れていて、怖くなって夜寝れなくなるのに似ている。

別にニュース番組でドキュメンタリーを流してはいけない決まりはないが、
ニュース番組には **[HRT](https://help.qiita.com/ja/articles/qiita-community-guideline)** があるのかもしれない。

　

しかし、

**[エンジニア業界を少し外から眺めて](https://qiita.com/kishibashi3/items/87577190eee5e88311c9) の コメント欄の LGTM数** を見て愕然とした。

**LGTM** は **Looks Good To Me** の略であり、 **コードレビューをするときにも用いるワード** である。

**コーディングスタイルはチームによって違う** ため、 **自分ではLGTM** と思わなくても、
**LGTMが多ければ従うべき** だろう。

**議論をすることは大事** である。しかし、仕事では **一度結論が出たら仕事としてはそれに従うべき** である。
結論を出すために多数決は有効だし、どうしても納得できないのであれば、 **チームを抜ける** べきだ。

　
**[Qiitaの「いいね」が「LGTM」に変わります - Qiita Blog](https://blog.qiita.com/like-to-lgtm/)** にも


> 「いいね」の重み付けされた総量が「Contribution」として表現されることからもその意図は伝わるかと思います。

> Qiita運営としても、流れてきた記事に「いいね」するのではなく、しっかりその内容を読んで、その内容が少なくとも自分にとって良いものだと思ったときに「LGTM（Looks Good To Me）」と言ってもらった方が良いと考えました。

とある。

**いいね** だったら、**共感した** とか、 **考えさせられた** 人が多いんだなとスルーすることができた。

　
**LGTM** は **開発メンバの一員** として、 **チームのコードとして** 、 「LGTM（**L**ooks **G**ood **T**o **M**e）」なのだ。


それっぽく動いたことに、 **LGTM** するチームであれば、辞めるしかない。

　

　

　
つまり

 - LGTMは重い。投稿者だけではなく、LGTMする人にもHRTを大切にしてほしい。
 - LGTM以外のアクションのニーズ（応援や記事を広めたいなど）が多いと思う。Qiitaには、ほかの機能を用意するなどの対応をしてほしい。
 - たぶんQiitaは辞めない。運営の意図とは反するが、**LGTM** が、**いいね** として使われ続けてしまうのであれば、 **精神衛生上の理由で** 、**[LGTMを戻す](https://qiita.com/sapi_kawahara/items/4e05845e285ac087feb5)** ことを考えた方がいい。
 - この記事はポエム

## 2020/3/26 追記ポエム

**[高階関数を書いたら、中級者になれた気がした。を批判したら上級者になれた気がした。を格下目線から批判してみた。](https://qiita.com/mishio/items/0212c6f790f83f71cf2e)** を読んだら、 

**[某pay、不正アクセス事件についてまとめ](https://qiita.com/kanchan-1996/items/1ab5561d61f169cb05b4)** を思い出して怖くなった
Githubでのプログラム修正の流れ　その3

##はじめに
以下の記事の続きです。
[Githubでのプログラム修正の流れ　その1](https://qiita.com/ysda/items/7da00da7fe3d13b7ca6f)
[Githubでのプログラム修正の流れ　その2](https://qiita.com/ysda/items/61318db52b45da31eaf2)

##今回の記事に出てくる言葉
| 用語       |       意味 |
|:-----------------|:------------------
| リポジトリ             |ファイルやディレクトリの<br>変更履歴を保管しておくもの|
| ローカルリポジトリ        |自分のPC上にあるリポジトリ|
| リモートリポジトリ        |インターネット上に存在するリポジトリ<br>GitHubやbitbucket等|
| コミット        |ファイルの修正や追加をローカルリポジトリに<br>変更履歴として記録すること|
| ブランチ       　　 |変更履歴の流れを分岐して記録していく物。masterブランチという大元があり、そこからブランチ（枝）が分かれている、、、というイメージ。修正する機能ごとにブランチを作り、プログラム修正が完了したらmasterブランチに反映する。|
| プルリクエスト        |ローカルリポジトリで修正したコードに対して、レビュー依頼をすること|
| マージ        |ブランチでの修正内容ををmasterブランチに反映すること|

##ファイル修正
前回の記事まででブランチの作成はできていると思うので、早速ファイルを修正してみましょう。
こんな感じで「hello world」から「hello world!!!」にしてみます。
![スクリーンショット 2020-03-18 21.45.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429077/e4bf767c-061f-ac09-43fa-8339c17b5b54.png)
するとGitHubDesktop上に変更前と変更後の比較が表示されます。
![スクリーンショット 2020-03-19 21.53.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429077/7bd4c111-cec9-b95d-d482-1c46a61fcbaf.png)

コメントを記入してコミットボタンを押しましょう。
![スクリーンショット 2020-03-23 21.16.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429077/ef37f337-e47e-0e15-a392-3cfd2a43f7b6.png)

続いて、publish branchを押下してローカルリポジトリの内容をリモートリポジトリに反映します。
![スクリーンショット 2020-03-23 21.29.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429077/6dcc3213-fd45-e25f-92dc-044de7f984fa.png)

##プルリクエストを出す
Create Pull Requestを押下してプルリクエストを出しましょう。
![スクリーンショット 2020-03-23 21.48.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429077/338f3080-b958-9692-25d0-c51321d01bde.png)

するとブラウザでGitHubが開かれるはずなので、何をどのような目的で修正したのか記入してCreate pull request押下しましょう。これでプルリクエストは完了です。
![スクリーンショット 2020-03-23 21.56.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429077/58baaea8-e6e7-11d5-9719-d302ef235beb.png)

## レビュー
レビュアーから修正依頼がきたら、その都度対応しましょう。
今回は以下のような修正依頼が来たとします。
![90z1bO89YT1YJOT1585013423_1585013626.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429077/f84c0aab-38a8-13f9-c2e0-6b0027b38325.png)
修正内容を確認し、レビュアーからの指摘が無くなるまでファイルの修正→コミット→プルリクエストを繰り返します。

##マージ
指摘反映が完了したら、Merge pull requestボタン押下　→　Confirm meergeボタン押下でmasterブランチへの反映は完了です。
![スクリーンショット 2020-03-24 10.43.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429077/c5526a57-d96a-45d5-034d-19e6089607f9.png)
![WnrTsl7Ma9QhicV1585014382_1585014412.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429077/21acfbc5-337a-f658-a8c8-e309e50f32af.png)

##これで完了
以上がGitHubプログラム修正の流れとなります。他にもいろいろな機能があるので、Gitを使いこなして効率の良い開発を進めましょう！
Dockerを使ってAlpineでMatplotlibを日本語化する

こちらの[Dockerfile](https://github.com/moisutsu/NLP100/blob/fe965ea7bea979b3f03e70d7136cb42e0e29920c/c4/Dockerfile)を作成しました。

# はじめに

大学で自然言語処理の研究室に配属されることになったので[言語処理100本ノック](http://www.cl.ecei.tohoku.ac.jp/nlp100/)を進めています。その問題でmatplotlibを日本語化しなければならない問題があったので、最近勉強しているDockerを使って環境を構築してみました。

# 環境

- Docker 19.03.8

# Dockerfileについて

Dockerで環境構築するにあたって、

- ベースイメージをAlpineにする
- Anacondaを使用しない
- numpyもインストールする

ことを目標にしました。

pipでmatplotlibとnumpyをインストールする際に、ライブラリが足りずにエラーが出てしまったので、alpineのパッケージマネージャであるapkでbuild-baseとfreetype-devを追加しました。このうち、build-base内のlibstdc++とfreetype-devは実行時に利用されるため、削除しないようにしました。

また日本語に対応しているフォントとしてNotoSansCJKjpを入れました。そしてmatplotlibの設定ファイルでこのフォントを使用するようにし、キャッシュを削除しました。

またイメージサイズが小さくなる(らしい?)ので、RUNは一つにまとめてあります。

そして完成品が[こちら](https://github.com/moisutsu/NLP100/blob/fe965ea7bea979b3f03e70d7136cb42e0e29920c/c4/Dockerfile)になります。

# 最後に

Dockerはとても便利なのでこれからも使っていきたいです。
【Linux】同じアプリなのにDockにアイコンが2個表示されてしまう！

自分でdesktopファイルを書いて登録したアプリなどがこうなることがあります↓
![Screenshot from 2020-03-25 00-53-29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151137/3efc1ab5-84f7-13d2-341e-c32501f775f8.png)

# 対処法

やることとしては、このアプリのクラス名を取得し、そのクラス名をdesktopファイルに明記します。

## クラス名の取得

1. 調べたいアプリケーションを起動しておいてください。

2. このコマンドを叩きます

```
$ xprop WM_CLASS
```

3. するとコマンドが完了せずに待ちの状態に入りますので、この状態で該当のアプリケーションのウィンドウをクリックします

うまくいくと、↓のようにクラス名を出力します。

```
WM_CLASS(STRING) = "gravitdesigner", "GravitDesigner"
```

## desktopファイルに登録

対象アプリのdesktopファイルを開き、

```
$ sudo vi /usr/share/applications/gravit-designer.desktop
```

↓の行を追加します

```
StartupWMClass=GravitDesigner
```

`GravitDesigner` がさっき調べたクラス名になります。

---

以上で改善するはずです！

ちなみに、この[GravitDesigner](https://www.designer.io/en/)というデザインソフトは、Adobe Illustratorからの乗り換え先として使っています。おすすめです。
ユーザーの新規登録時に入力なしの初期値を設定する【Ruby on Rails】

### 目的
ユーザーの新規登録時に、直接入力させずにテーブルに初期値を保存させること。

### 使用する技術
- gem devise

# 実践
以下のテーブルが作成してあるとします。

|Column|Type|Options|
|------|----|-------|
|username|string|null: false, unique: true|
|email|string|null: false, unique: true|
|password|string|null: false|
|coin|integer|null: false|

今回は、ユーザー登録フォームで

- username
- email
- password

の３項目をのみを入力させます。
ここで、**coinカラムは入力させずに、初期値0としてテーブルに保存します。**


### 事前準備
すでに、gem deviseが導入され、コントローラとビューの作成が終了しているものとします。
（このような画面まで用意されている所からです）
<img width="729" alt="devise:registrations:new.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579117/781a1b9c-f520-3b64-921c-ba23a89829b1.png">

## deviseのカスタマイズ
ここからは、デバイスのカスタマイズを行っていきます。
初めにdeviseのコントローラを作成して編集できるようにします。

```
$  rails g devise:controllers users
```
`app/controller/users/`のフォルダにコントローラが作成されました。
このフォルダ内の`registrations_controller.rb`を使用していきます。


次に、ルーティングを一度確認しておきます。

```
$  rails routes

# 結果
Prefix                 Verb   URI Pattern                    Controller#Action
new_user_registration  GET    /users/sign_up(.:format)       devise/registrations#new
```
今のままでは、作成した`registrations_controller.rb`が呼び出されていない状態なので、これを呼び出す記述をします。

```ruby:config/routes.rb
Rails.application.routes.draw do
  devise_for :users, controllers: {
    registrations: 'users/registrations',
  }
end
```
devise導入時に自動的に記述された`devise_for :users`に続けて、このように記述します。
編集後、もう一度ルーティングを確認します。


```
$  rails routes

# 結果
Prefix                 Verb   URI Pattern                    Controller#Action
new_user_registration GET    /users/sign_up(.:format)       users/registrations#new
```

`devise/registrations#new → users/registrations#new`
に変わっていればOKです。

## コントローラに初期値を設定
コントローラにnewメソッドとcreateメソッドを定義していきます。

```ruby:registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
  
  # 省略

  def new
    @user = User.new
  end

  def create
    @user = User.new(sign_up_params)
    unless @user.valid?
      flash.now[:alert] = @user.errors.full_messages
      render "devise/registrations/new" and return
    end
    @user[:coin] = 0
    @user.save
    sign_in(:user, @user)
    redirect_to root_path
  end

  # 省略
```
`registrations_controller.rb`はコメントアウトで記述がされていて、`Devise::RegistrationsController`で最初からメソッドが定義されています。
カスタマイズするときは、コメントアウト部分を消してオーバーライド（上書き）していきます。

重要なのは、ここです。

```ruby
@user[:coin] = 0
```
`@user = User.new`の時点では`coin: nil`だったところに、0を代入します。
これで、coinカラムに0が入りました。あとはそのまま、データベースにレコードを登録 ＋ ログイン + root_pathにリダイレクトを行っています。

ちなみに補足しておくと、、

```ruby
unless @user.valid?
  flash.now[:alert] = @user.errors.full_messages
  render "devise/registrations/new" and return
end
```
ここは、バリデーションに引っ掛かったときにエラーメッセージを表示させて、登録フォームのページを返すということをしています。（これがない場合、登録されずにTOPページに遷移したりします）
##

### 最後に
ユーザーの新規登録の場合はdeviseをカスタマイズする必要がありましたが、
普通のテーブルであれば、new,createメソッドのどちらかに初期値を代入するだけで簡単に保存させられます。

### 参考
[Qiita 【オブジェクト生成時にインスタンス変数の初期値を設定する】
](https://qiita.com/kazuooooo/items/8cc92007c90497217b89)
今更ながらWPFに置き換えてみる（8）

#画面の右上下への吸着（というか移動）

画面の右上、右下にWindowを飛ばすボタンをテスト。

アイコン化→通常Windowへ復帰した場合、画面の上限、右端、下限に接している場合現状のtop,leftを固定せずに拡大方向を切り替えてどのように見えるかを確認してみた。

![TestApp3-2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/590512/9638315f-82ca-1f40-5535-86d7064341a8.gif)

Windowの位置、サイズについては直接this.left、this.topをセットするというのが一番単純な方法ですが、それだと最低でも2ステップの実行となってしまいトランジション中にがたつきが目立つので、Win32のSetWindowPosでまとめてセットするように変更。

Windowの位置変更は非常に速いが、サイズの変更は予想通り処理が重い。
位置変更トランジションは中間に１００ステップ入れていますがほとんど瞬間移動しているように見えます。
サイズの変更は３０ステップ程度でタイミング的に釣り合うイメージでした。

新たに出てきた問題点
・Windowの位置変更にDragMoveを利用しているが、ドラッグ中のスクリーン枠へのスナップがForms＋VBの時のように簡単にいかない（気がする）
OculusQuest のハンドトラッキングで摘んでVR空間を移動する

Update の中身はわずか１０行程度で、こんな感じで、空間を摘んで移動できるようになります。

![Moving.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506075/1660bfa8-0f4f-a4ea-b205-a677819a49f4.gif)

空中も自由自在ですね。さらっとご紹介。

# 解説
ほんと簡単です。

## まずはつまんでいる状態を検知します
こんな感じで、つまみ始めるとキューブが小さくなり、摘んだを検出するとキューブが緑色に変わるようにしました。

![PinchingDetection2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506075/e4c4200d-5875-5841-5edf-47ad1d58fd8f.gif)

### プログラム
```C#
using UnityEngine;

public class PinchDetection : MonoBehaviour
{
    [SerializeField] private OVRHand ovrHand;

    [SerializeField] private Transform cube;
    [SerializeField] private MeshRenderer cubeRenderer;

    [SerializeField] private Material on;  // キューブの色変更用
    [SerializeField] private Material off; // キューブの色変更用

    public bool IsPinching = false;

    void Update()
    {
        // つまみの強さを取得、０から１の間で変化し、１は完全に親指と人指し指がくっついている状態
        var strength = ovrHand.GetFingerPinchStrength(OVRHand.HandFinger.Index);
        // 5cm x つまみの強さを取得していて、消えないように 0.1cm は残るようにしています
        var scale = Mathf.Max(0.05f * (1 - strength), 0.01f);
        // 人差し指のピンチングの強さに応じて cube の scale を変更します
        cube.localScale = new Vector3(scale, scale, scale);
        
        // キューブが 2cm 未満になっていることを検出
        IsPinching = cube.localScale.x < 0.02f;
        // 検出したら、キューブの色を変えます
        cubeRenderer.materials = IsPinching ? new[] {on} : new[] {off};
    }
}

```

## そして、摘んでいるときに移動できるようにします
1フレーム前の手の位置と、現在の手の位置との差分を取得して、その変化量に応じて自分自身を移動させます。

```C#
using UnityEngine;

public class PinchingMover : MonoBehaviour
{
    [SerializeField] private GameObject me;
    [SerializeField] private GameObject hand;
    [SerializeField] private PinchDetection detection; // 上のプログラム

    private float speed = 20f; // 移動スピード、適当な値です
    private Vector3 previous;

    void Update()
    {
        // 摘んでいるときは
        if (detection.IsPinching)
        {
            // 1フレーム前の手の位置と、現在の手の位置との差分を移動量のベースに、speed を積算します
            var movement = (previous - hand.transform.localPosition) * speed;
            // 自分自身を移動させます
            me.transform.position += movement;
        }

        // Update の最後で、再び自分の手の位置を設定
        previous = hand.transform.localPosition;
    }
}
```

### 注意
* hand.transform.`local`Position にしないと、自分（me）と一緒に手（hand）が動くので、ぶっ飛んで死にます。
* previous は Start で初期化しておいた方がいいとか、細かいところは見やすさ重視で割愛しています。

## Unity の設定
### PinchingMover
![スクリーンショット 2020-03-25 0.47.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506075/3815084f-161f-e626-8bea-ce37d1c53351.png)

### PinchingDetection
Green16, Red16 とかは適当にMaterialを作って設定してもらえれば大丈夫です。
![スクリーンショット 2020-03-25 0.49.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506075/967acb1c-9277-1d1f-82c3-2e1b71a2b8a4.png)

# 備考
* 摘むの補足は、前に書いた [OculusQeust のハンドトラッキングの摘むを試しみた](https://qiita.com/matchyy/items/c7e0b5ddeff04b3a1275) を参照ください。
* 本当は指だけで移動できるようにしたかったり、ボルダリングみたいなのを考えていたりしていく中で、デバッグ用ならこれでいいかってなった結果の産物です。
【Linux】定義されていないmime typeを登録してアプリケーションに関連付ける

# 例:

`Qiita` というアプリケーションは、 `xxx.qiita` というプロジェクトファイルを保存します。

しかし、`*.qiita` という拡張子は登録されておらず、`Qiita`にも関連付けられていません。
`*.qiita` というファイルを `Qiita` で開けるように設定します。
![Screenshot from 2020-03-25 00-35-09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151137/ee1ef1a5-05fa-8783-5bc2-18b697b9e333.png)

# 拡張子の確認

まずは `mimetype` コマンドで拡張子が登録されていないことを確認します。

```bash
$ mimetype article.qiita 
article.qiita: application/gzip
```

登録されていない場合、 `text/plain` や `application/gzip` などと認識されます。

# 拡張子を定義

```
$ sudo vi /usr/share/mime/packages/freedesktop.org.xml
```

周りの項目を見ながらxmlを書きます。コメントとかは多分適当で大丈夫です。

```xml
  <mime-type type="application/qiita">
    <comment>Qiita file</comment>
    <comment xml:lang="ja">Qiita ファイル</comment>
    <acronym>Qiita</acronym>
    <expanded-acronym>Qiita file</expanded-acronym>
    <glob pattern="*.qiita"/>
  </mime-type>
```

mime databaseを更新します。

```
$ sudo update-mime-database /usr/share/mime
```

確認

```
$ mimetype article.qiita 
article.qiita: application/qiita
```

# アプリケーションに拡張子を関連付け

「Qiita」というアプリは「application/qiita」に対応してますよー、的な設定をします。

該当のdesktopファイルのMimeTypeに加筆します。なければ行を足してください。

```
$ sudo vi /usr/share/applications/qiita.desktop
```

```
...
MimeType=xxx/xxx;xxx/xxx;application/qiita;
...
```

再読込

```
$ update-desktop-database
```

`*.qiita` ファイルを `Qiita` で開けるようになっているはずです。
SQL 第2版 ゼロからはじめるデータベース操作とMacのpostgreSQLのインストール

##SQL 第2版 ゼロからはじめるデータベース操作

<img width="260" alt="スクリーンショット 2020-03-25 0.06.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547448/85365072-d542-6b28-3da3-4183e12621e6.png">

こちらの本を買ったのですが、インストールをミスってしまいかなり時間がかかってしまったので、これからmacで操作する人に向けて書きました。

とりあえず最初この本を読みながらインストールしました。
すると日本語を入力するとずっと???となってしまいました。
[こちら](https://teratail.com/questions/163297)の状況と一緒なのでリンクを貼ります。

私が初心者すぎるせいか、設定がものすごく苦手ということもあり、様々な解決策など見ても解決ができずにいました。

結論としてはまずインストールしたpostgreSQLを一度アンインストールしました。

そして[こちらのサイト](https://to-kei.net/db/postgre-mac-install/)を参考にインストールし直しました。


上記サイトの**PostgreSQLの起動**の部分では恐らく上手くいかないと思います。
恐らくPCを再起動すると上手く動くはずです。

そのあとはもう一度**PostgreSQLの起動**の部分から設定します。

そうするとターミナルで以下コードを打つとサーバーが起動するはずです。

```
$　postgres -D /usr/local/var/postgres
````

またターミナルをcommand+tなどで新しい別ウィンドを開き以下コードを打ちます。

```
$　psql -d postgres
````

そうすると以下のようになります。

```
$ psql -d postgres
psql (12.2)
Type "help" for help.

postgres=# 
```

この流れでインストールをしpostgresSQLを起動すると普通に日本語で入力することができました。
めでたしめでたしです。
高階関数の記事のタイトルが長いから、高階関数で処理してみた

## 概要

* 高階関数についての記事タイトルが引用を繰り返してたので、高階関数的に処理してみました。

## コード

```JavaScript
[
  '高階関数を書いたら、中級者になれた気がした。',
  '批判したら上級者になれた気がした。',
  '格下目線から批判してみた。',
  '高階関数でタイトル生成してみた。',
].reduce((accumulator, title) => accumulator + 'を' + title)

// "高階関数を書いたら、中級者になれた気がした。を批判したら上級者になれた気がした。を格下目線から批判してみた。を高階関数でタイトルを作ってみた。"
```

## 高階関数 reduce

* 高階関数 reduce は、第二引数を指定すると、最初の処理時に accumulator に指定されます。第二引数を省略すると、最初の要素が accumulator に指定されて、第二要素から処理がスタートします。

* 第二引数込みで書き換えると次のようになります。配列の要素が分散されるので、あまりよいコードではなくなると思います。

```JavaScript:第二要素込み。
[
  '批判したら上級者になれた気がした。',
  '格下目線から批判してみた。',
  '高階関数でタイトル生成してみた。',
].reduce(
  (accumulator, title) => accumulator + 'を' + title,
  '高階関数を書いたら、中級者になれた気がした。'
)

// "高階関数を書いたら、中級者になれた気がした。を批判したら上級者になれた気がした。を格下目線から批判してみた。を高階関数でタイトルを作ってみた。"
```

## 結論

* このケースなら `Join` を使った方が簡単ですね。

```JavaScript:join
[
  '高階関数を書いたら、中級者になれた気がした。',
  '批判したら上級者になれた気がした。',
  '格下目線から批判してみた。',
  '高階関数でタイトル生成してみた。',
].join('を')
```

## Tips

* 高階関数は、英語で higher-order functions です。

## 参考記事

* [高階関数を書いたら、中級者になれた気がした。](https://qiita.com/Yametaro/items/fe863978994861f36611)
* [高階関数を書いたら、中級者になれた気がした。を批判したら上級者になれた気がした。](https://qiita.com/elipmoc101/items/c34b38ddbbd9b52d0a4f)
* [高階関数を書いたら、中級者になれた気がした。を批判したら上級者になれた気がした。を格下目線から批判してみた。](https://qiita.com/mishio/items/0212c6f790f83f71cf2e)
【UE4】モーションに合わせて攻撃判定をつける方法【UnrealEngine】

弾丸やレーザーなど最初から当たり判定が存在している攻撃以外にも剣や拳など振り切ったタイミングで当たってほしい攻撃もあります。

攻撃用の当たり判定(Collision)をアニメーションに合わせ、有効化する事で指定したタイミングで当たる攻撃が作れます。


実装手順
-------------------------
####1.攻撃した時に出てきてほしい当たり判定を配置
![damagecoll.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/497331/58a0685e-3829-d670-7ecf-45b220b62a7a.png)

この作ったコリジョンにヒットした場合、敵は消える処理だったとしましょう。

####2.アニメーションにダメージ用の通知イベントを追加
![kenhutterutoki.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/497331/f0d7746a-2df8-74f5-537e-f87addb1d0f1.png)

当たり判定表示フラグを自前で作り
DamageActiveとDamageEndという通知イベントを作り、当たり判定が有効化してほしいフレームをこの通知イベントで挟みます。
![damagesyori.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/497331/789b090c-75f0-baac-40b7-1ed1a4803d17.png)
DamageActive で当たり判定表示フラグをtrueに
DamageEnd で当たり判定表示フラグをfalseに変える処理を作ります。

####3.毎フレーム呼ばれるTickで当たり判定表示フラグに合わせ攻撃用当たり判定の有効・無効を切り替える
![kirikae.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/497331/d15bb991-c39e-3de2-4c59-3136c7118632.png)


結果
-------------

![攻撃.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/497331/274a573e-f349-4822-db24-e178adc1ec53.gif)

瞬殺

パッと思いついた方法を共有しましたが、
もっと良い方法があればコメントなどで是非教えてください。
WSL2でカスタムカーネルを使う

___WSL2にてカスタムカーネルを使う方法を書きますた｡___

# Linux 5.xを使う
追記です｡
scoopを使っていて､Linux 5.x (next) を使いたいならこれを
(公式カーネルはもう既に5.10までにBumpされています。)

```shell:ifscoop
# If you may need
# scoop install git
scoop bucket add github-koumaza https://github.com/koumaza/bucket.git
scoop install wsl2-next
```

```powershell:overwrite-in-pwsh
Write-Output (
	"[WSL2]" + "`n" +
	"kernel=C:\\Users\\" + ${env:USERNAME} + "\\scoop\\apps\\wsl2-next\\current\\bzImage"
) > ${env:USERPROFILE}\.wslconfig
```

<details><summary>For scoop <code>.wslconfig</code></summary><div>

```ini:.wslconfig
[WSL2]
kernel=C:\\Users\\[USERNAME]\\scoop\\apps\\wsl2-next\\current\\bzImage
```
</div></details>

# カーネルのコンパイル (例)

[github - microsoft/WSL2-Linux-Kernel](https://github.com/microsoft/WSL2-Linux-Kernel/)

#### 依存関係
######Ubuntu
`build-essential flex bison libssl-dev libelf-dev`
######ArchLinux
`base-devel flex bison openssl libelf`

[ソース](https://github.com/microsoft/WSL2-Linux-Kernel/blob/linux-msft-wsl-4.19.y/README-Microsoft.WSL2)

#### ビルド

```shell:shell
 make KCONFIG_CONFIG=Microsoft/config-wsl
# or. AutoEnter
 yes '' | make KCONFIG_CONFIG=Microsoft/config-wsl
```

# Windowsでの設定

__~/.wslconfig__を弄ります｡
の前に！`uname -a`と`cat /proc/version`をしておきましょう｡

ホームパスに次のファイルを作ります｡
[USERNAME]を置き換えてください｡

```ini:.wslconfig
[WSL2]
kernel=C:\\Users\\[USERNAME]\\vmlinux
```
インスタンスを起動している場合は`wsl --shutdown`をします｡
vmlinuxの場所はもちろん自由です｡各自好きなところに｡
[Linux 5.x](https://github.com/nathanchance/WSL2-Linux-Kernel/releases)✌
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387170/eb22fad3-0d72-cdfa-42c6-cf7032f608f4.png)


WSL2でぜんぶできるね
Reinitialized existing Git repository in が出たときの対処法

## はじめに
ただの備忘録のうちのひとつ。将来のために、、、

## git init したときのやつ
```
$ git init 
Reinitialized existing Git repository in ~
```
## 結論：やることない
特にやることない。Reinitializedとか言うから「初期化して最初から⁉」とか思ってたけどそうではないらしい。

## 関係ないけど
名前とメールの確認もたまにしたくなる

```
$git config --global --list
user.name=hogehoge
user.email=hoge@gmail.com
```

###### 参考
https://qiita.com/ragingalpaca/items/ef247e459ff2e7759ba9
https://hacknote.jp/archives/15745/
VB6→C#化における、ラッピング戦略


コンバートしたソースを最大限利用する方法

プロジェクトの参照で、C# WinFormsプロジェクトの基本的な参照のみを残し、削除する
これにより、コンバート時に変換された、VB6互換部品のコードが全てエラーになる。
（詳細は、後日追記する）

SharpDevelopで新たに追加された、MyApplicationなどのStatic対応も全て使わないことにする。
参考にすることはある可能性はあるので、ファイル全体をコメントアウトしておく。

Using句のネームスペース設定中、Microsoft.VisualBasic 名前空間、Microsoft.VisualBasic.Compatibility.VB6 名前空間は参照を削除したことによって赤いアンダーラインが表示されるが、残しておく。この名前空間を利用し、エラーになっている部分を拾うことになる。

https://docs.microsoft.com/ja-jp/dotnet/api/microsoft.visualbasic.compatibility.vb6?view=netframework-4.8

https://docs.microsoft.com/ja-jp/dotnet/api/microsoft.visualbasic?view=netframework-4.8

一部、LenBやErr()など、上記の名前空間に属する関数などが省略された形で記述されているが、
一括変換又は、下記で記述するマイグレーションサポート用のクラスへ実装することにする。詳細は後述する。
簡単に説明すると、この関数らを含むフォームを継承したクラスを作り、全てのフォームはそれらを継承するようにする。
Class MigSupForm : Form
{
  LenB(){};
  Err(); 
}
Class FrmXXX : MigSupForm
{

}
Grid

AxMSFlexGrid
MSWinsockLib
axWinsck
ADODB

これらのOCX部品に関しても、Microsoft.VisualBasic 名前空間、Microsoft.VisualBasic.Compatibility.VB6 名前空間へ属する
関数として作ることにより、変換ソースを極力修正しないようにする。

名前空間を利用する目的としては、一行一行の手間を省くためである。これは、実際やっていただければ納得するはず。

ここまでは無難な作業である。なんでやるかは、
VB６関連ソースを一括に管理するため、
移行の土台に素早く乗らせるため、
リファクタリングを活用することで、もっと効率的な作業を進めるため。
。。。

型の曖昧さの問題は、演算子周りで起きており、キャストを施すのは、最終的に道ではあるが、全てを手作業するのは大変である。
この解決策として、演算子のオーバーロードを施す事はどうだろうか。
全ての形ではない問題が起きている型のみを作成することにする。

ジェネリックも応用できそう
https://ufcpp.net/study/csharp/sp2_generics.html

BOXING、UNBOXINGも応用できそう。
オブジェクト型には全てが入る。
using System;

class Test
{
    static void Main() {
        int i = 123;
        object o = i;          // Boxing
        int j = (int)o;        // Unboxing
    }
}

頻発する、Form を　Objectへ代入、ShortにIntを代入　は
VBSObject クラス、VBSShortクラスを作り、演算子を定義すればそうだろうか。


全体的にStaticとなっているので、最初は、SharpDevelop作成サポートクラスに似せた
静的サポートクラスを作成する。ここにMain関数も入れておく。

フォームのクラス名でそのまま利用などは、SharpDelelop作成クラスでの定義を利用するように変換されているので、
それに似せるような形をとる。


win32 C# 関数　
ちょっと変換が変なので、見直しが必要。
https://www.atmarkit.co.jp/ait/articles/0305/09/news004.html

ここで結構調べられる
https://www.pinvoke.net/index.aspx


配列　コントロール　C#
http://tki.main.jp/hata/indexer.html


このコンセプトのファイルは、DLLのプロジェクトにして、共通としてインポートするといいでしょう。


全体を早く見渡し、少しでも早く軌道に乗せたい。
Wordpress 作成したプラグインに設定項目を追加する方法

## プラグインに設定を追加して保存できるようにする

プラグインに設定項目（オプション）を追加するには以下のことを行う。

- メニューの作成
- 設定項目の登録
- 設定画面に表示するフォームを作成

```php
<?php
/*
Plugin Name: Test plugin
Description: A test plugin to demonstrate wordpress functionality
Author: Test Name
Version: 0.1
*/

// プラグインに設定ページを追加
add_action('admin_menu', 'test_plugin_setup_menu');

function test_plugin_setup_menu() {

	// メニューの作成
  add_menu_page(
    __( 'TestPlugin', 'textdomain' ), // ページタイトル
    'Test Plugin',  // メニュータイトル
    'manage_options', // Capabilities、メニューが含む機能？
    'test-plugin',  // メニューslug
    'test_setting_function',  // 設定画面で実行する関数
    'dashicons-chart-pie'  // メニューに表示するアイコン
  );

	// 設定の登録関数を呼び出し
	add_action( 'admin_init', 'register_test_plugin_settings' );
}

// 設定の登録関数
function register_test_plugin_settings() {
	// 設定項目を１つずつ追加、オプション名は取り出すときにも使う
	register_setting( 'test-plugin-settings-group', 'test_option_1' );
	register_setting( 'test-plugin-settings-group', 'test_option_2' );
	register_setting( 'test-plugin-settings-group', 'test_option_3' );
}

// 設定画面で実行する関数
function test_setting_function() {
?>
<div class="wrap">
<h1>プラグイン名</h1>

<!-- 設定項目のフォーム -->
<form method="post" action="options.php">
    <?php settings_fields( 'test-plugin-settings-group' ); ?>
    <?php do_settings_sections( 'test-plugin-settings-group' ); ?>
    <table class="form-table">
        <tr valign="top">
        <th scope="row">設定項目１</th>
        <td><input type="text" name="test_option_1" value="<?php echo esc_attr( get_option('test_option_1') ); ?>" /></td>
        </tr>
         
        <tr valign="top">
        <th scope="row">設定項目２</th>
        <td><input type="text" name="test_option_2" value="<?php echo esc_attr( get_option('test_option_2') ); ?>" /></td>
        </tr>
        
        <tr valign="top">
        <th scope="row">設定項目３</th>
        <td><input type="text" name="test_option_3" value="<?php echo esc_attr( get_option('test_option_3') ); ?>" /></td>
        </tr>
    </table>
    <!-- 保存ボタン -->
    <?php submit_button(); ?>

</form>
</div>
<?php }
```

## 設定したデータをテンプレートに表示する方法
オプションをテンプレートで表示するには、`get_option()`を使う。

パラメータには登録したオプション名を記入する。

```php
<?php echo esc_attr( get_option('test_option_1') ); ?>
```
curlコマンドでTrelloのリストのIDを取得する

シェル（curlコマンド）でTrelloのリストのIDを取得する方法を確認したのでメモ。

TrelloのAPIを利用してカードを投稿するためには、投稿先のリストのIDが必要となるが、このIDの値は事前にシェルなどで確認しておく必要がある。

## 取得してみる
- APIキーとAPIトークンを取得

[https://trello.com/app-key](https://trello.com/app-key)よりAPIキーとAPIトークンを取得する。

- 自分のユーザー名を取得

[https://trello.com](https://trello.com)でページ右上のアイコンより[プロフィールと公開範囲]をクリック
![image.png](https://image.docbase.io/uploads/59b51a75-6f98-40d5-bd82-c36c9ed3fbfc.png)

赤枠内の`@`の右側がユーザー名なので控える。
![image.png](https://image.docbase.io/uploads/a4cc8afa-3305-4f43-a93f-5beac33b28ed.png)

- ボードIDを取得

前述の手順で取得したAPIキー、APIトークン、ユーザー名を指定して、curlコマンドでボードID一覧を取得する。

```shell
$ key="<APIキー>"
$ token="<APIトークン>"
$ user_name="<ユーザーID>"

$ curl "https://trello.com/1/members/${user_name}/boards?key=${key}&token=${token}&fields=name" | jq .
```

こんな感じのJSONのリストが返ってくるので、カードを投稿したいリストが含まれるボードの`id`を控える。

```json
[
  {
    "name": "Board",
    "id": "XXXXXXXXXXXXXXX"
  },
  {
    "name": "task",
    "id": "YYYYYYYYYYYYYYY"
  },
  {
    "name": "trash",
    "id": "ZZZZZZZZZZZZZZZ"
  }
]
```

- リストIDを取得

先程控えたボードIDを指定して、curlコマンドでリストID一覧を取得する。

```shell
$ board_id="<ボードID>"
$ curl "https://trello.com/1/boards/${board_id}/lists?key=${key}&token=${token}&fields=name" | jq .
```

こんな感じのJSONのリストが返ってくるので、カードを投稿したいリストの`id`を控える。

```json
[
  {
    "id": "5e7a20719b46942f3b12d9ca",
    "name": "2020-03-25"
  },
  {
    "id": "5dea89fb416b532c9495f81a",
    "name": "Ready"
  },
  {
    "id": "5dfc9ec2fd1b113a0cb1fdbc",
    "name": "Waiting"
  }
]
```

## 参考
- http://blog.serverworks.co.jp/tech/2016/05/16/trello-api/
AIM Tech Round 5 (rated, Div. 1 + Div. 2) B. Unnatural Conditions

https://codeforces.com/contest/1028/problem/B

$f(a+b) = 1$に気が付けるか。

# 概要
- 10進数xを考えたとき、$f(x)$ は各桁の和である。つまり、$123$なら$1+2+3 = 6$ 
- $n, m$が与えられるこの時、以下を満たす$a,b$を答えよ
- $f(a) \geq n $ 
- $f(b) \geq n $ 
- $f(a+b) \lt m $ 

`制約: $1≤n,m≤1129$, aとbは2230桁以下`

# こう考える
この問題のポイントは、制約より$n=1129, m=1$が一番厳しい条件であることである。

$m=1$はとても厳しい制約であることが分かる。各桁のすべての和が1ということは、$10^n$しか許されない。つまり、$a=50, b=50$で$a+b=100$なら$f(a+b)=1$である。

結論として、これを満たす最適な$a,b$は例えば以下である。

```
999001
   999
```

などの9をk個, 0をn-1個, 最後に1をつけた2n桁のaと9がn個続くbは必ず$f(a+b) = 1$である。nは最大1129なので、$9 \times 126 = 1134$より、126桁の数字であればよい。

$f(a+b)=1$であればいいので、この制約であれば、例えば以下のようにしても良い。

```
5555555
4444445
```

# コード
入力を受け付けなくともよい。

```Python
s1 = "9"*126 + "0" * 125 + "1"
s2 = "9" * 126
print(s1, s2)
```
チーム開発 3/24

#メモです
商品出品機能のサーバーサイドを作っていく

画像を貼る際にすぐに画像が
プレビューできるようにする
複数画像を送信できるようにする

使うメソッド
fields_forは,file_fieldや collection_check_boxesなどと
同じくフォームのインプット要素を生成するフォームヘルパーです。
1つのリソースに対し紐づいた、
複数の別のリソースを同時に保存したい際に利用します。
例えば今回のような1投稿に対して複数の画像をつけるパターンや、
1投稿に対して複数のタグをつける時などにも利用できます。

```ruby
<%= form_for @product do |f| %>
  商品名<%= f.text_field :name %><br>
  価格<%= f.number_field :price %><br>
  <%= f.fields_for :images do |i| %>
    <%= i.file_field :src %><br>
  <% end %>
  <%= f.submit %>
<% end %>
```

accepts_nested_attributes_for
fields_forメソッドを利用する際に、
親モデルの中に書く必要があるメソッドです。
以下の例のように、引数として子モデルの名前を書きます。

```ruby
hoge.rb
class hoge
  has_many :images
  accepts_nested_attributes_for :images
end
```
accepts_nested_attributes_forメソッドのオプションとして、
引数に書くことができる記述です。このオプションをつけることで、
親のレコードが削除された場合に、関連付いている子のレコードも一緒に削除してくれます。
accepts_nested_attributes_for :images, allow_destroy: true


まとめ
1つのフォームで商品と商品画像を保存
①productモデルに子モデルをまとめて追加・更新するための記述を加える
②newアクションでproductモデルと、それにひも付くimageモデルのインスタンスを作成する
③ビューでfields_forを使うことで、@productに関連付いているimageの数(newなら1つ、editなら登録した枚数分)だけ入力欄が生成される
④最後に、コントローラでレコードを保存する処理を加える。ストロングパラメータの形が独特なので注意する。

画像を複数枚投稿できるようにjsでフォームを生成する
①画像投稿用のinputボタンに、フォームで画像を選択したタイミングのイベントをセットする。
②①のイベントが発生したら、新しい画像投稿フォームを生成する、というJavaScriptのメソッドを動かす
③生成した画像投稿フォームを画面に追加する

スプリントレビューのため一時停止
デプロイした後
トップページ背景画像が消えていたので修正
Background:url
が使えないため
image_tag
を利用さらに
Position:abusolute
で修正
＿＿＿＿＿＿＿＿＿＿＿＿
#調べたこと

imgタグにおけるalt
Altタグには、この画像はなんの画像かを
わかりやすくするのに記述するタグ
https://www.kanzaki.com/docs/html/htminfo-alt.html#formula
参考ページ
[Rails]指定したカラムが空白であるレコードを検索

指定したカラムが空白であるレコードを検索

```ruby:users_controller.rb
users = User.where("name =  \'\'")
```

逆に
指定したカラムが空白ではないレコードを検索

```ruby:users_controller.rb
users = User.where.not("name =  \'\'")
```

# 参考
https://qiita.com/DrqYuto/items/67df6755560bb2fcd32d
https://qiita.com/Sirloin/items/b14ab34415a1ebd8a9c5
PowerShellで再帰的にCSVファイルをマージする

# 複数CSVのマージ

## 全ファイル同一フォーマットでヘッダーありの例

```Invoke-MargeCSV.ps1
param (
    [parameter(mandatory=$true)][string]$Path
)
$heder = "ID","column1","column2","column3","column4","column5"
Get-ChildItem -Path $Path -Recurse -Filter "*.csv" | %{ Import-Csv -Path $_.FullName -Header $heder | Select-Object -Skip 1 } | Export-Csv -Encoding UTF8 -Path .\test.csv -NoClobber -NoTypeInformation
``` 

## 行別解説

### 1~3行目：探索対象のトップフォルダを指定

必須の引数として、再帰的に探索するトップのフォルダを指定できるようにしています。

```
param (
    [parameter(mandatory=$true)][string]$Path
)
```

`$Path` 変数にパスを直書きでもOK

```
$Path = "C:\Users\myUser\Desktop"
```

### 4行目：CSVのヘッダーを指定

ヘッダーを文字列配列として指定しています。
ヘッダーなしの場合は不要

```
$heder = "ID","column1","column2","column3","column4","column5"
```

### 5行目の1パイプ目の処理：再帰的に拡張子`.csv`のファイルを配列で取得

大文字小文字は区別されないため、`.csv` または `.CSV` いずれかを指定します。

```
Get-ChildItem -Path $Path -Recurse -Filter "*.csv" 
```

`.txt`を含めたくなったときは以下の様に指定する。
`-Filter` を `-Include` に変更しています。

```
Get-ChildItem -Path $Path -Recurse -Include "*.csv","*.txt" 
```
### 5行目の2パイプ目の処理：1ファイルずつCSVファイルの中身を読み込み

Get-ChildItem で取得したファイル名のフルパスと`$heder`で指定したヘッダーを利用し
CSVファイルの読み込みを行います。
(全てにヘッダー行が指定されている場合、`Select-Object -Skip 1 `で１行目(ヘッダー行)をスキップする。)

```
%{ Import-Csv -Path $_.FullName -Header $heder | Select-Object -Skip 1 }
```

### 5行目の3パイプ目の処理：CSVファイルの中身を書き込み

`-Encoding`で文字コードを指定
`-Path`で出力パスを指定
`-NoClobber`で上書きを禁止(誤って上書かないように)
`-NoTypeInformation`で不要なCSVの補足データが出力されないように指定

```
Export-Csv -Encoding UTF8 -Path .\test.csv -NoClobber -NoTypeInformation
```
apache環境でのPHP について

# はじめに
CakePHP3の勉強をするついでに、環境構築をする際にApache環境でPHPをどのように設定をするのかをまとめてみようと思います。
今まで、特に意識することなくwebに落ちているコマンド叩いて、開発環境を構築できていましたが、何を設定するべきなのか、どのように動いているのかをdockerで環境構築するにあたりまとめようと思います。

## 構成
- Webサーバ
 - Apache2
- 言語
 - php 

## 2つのPHP動作パターン
Apacheを動作させる方法は2パターンある

- モジュール版 
  - Apacheの１つの追加機能としてモジュール版がある
  - Webサーバーを動かすユーザー（root権限など）で動作する
  - WebサーバーのプロセスのなかでPHPを実行   
- CGI版
 - CGI（版のPHP）を動かす各ユーザーは、Webサーバー本体を動かすユーザーとは異なる
 - Webサーバーとは別のプロセスで実行
セキュリティ的にはCGIで処理速度ではモジュールが良いという話
同一Webサーバに別プロジェクトが存在するなどの場合はCGIを選ぶべきで、そうで無い場合はモジュールを選びましょうということでしょう。
なので、レンタルサーバで開発をする訳ではないので、モジュール版で開発環境を作ります。

## モジュール版PHPをインストール
```dockerfile:DockerFile
## Packageインストール
RUN apk add --update --no-cache php7 php7-apache2 

```

## httpd.confにモジュール記述
```config:httpd.conf
# Get information about the requests being processed by the server
## モジュール版PHP
LoadModule php7_module modules/mod_php7.so

## URLでファイル名を省略した場合の表示しようとする優先順位を設定します。
DirectoryIndex index.php index.html

<FilesMatch \.php$>
    SetHandler application/x-httpd-php
</FilesMatch>

# Uncomment the following to allow .phps files to be handled by the php source filter,
# and displayed as syntax-highlighted source code
#<FilesMatch "\.phps$">
#    SetHandler application/x-httpd-php-source
#</FilesMatch>
```
これでPHPをApacheのプロセスの中で実行できるようになります。
※phpをサーバにインストールすることで勝手に記述されたファイルができていた。

[Apacheの設定方法参考リンク](https://server-setting.info/centos/apache_install.html)
Adafruit Trinket M0 にシリアルポートを追加する

はじめに
-
　[Arduino Pro mini 互換ボード](http://akizukidenshi.com/catalog/g/gK-10347/)で作っていたプログラムが　CPU 処理能力、メモリ容量の両方が足りなくなったので [Adafruit Trinket M0](https://learn.adafruit.com/adafruit-trinket-m0-circuitpython-arduino/overview) に乗り換えた。  
  
　Arduino では [SoftwareSerial](https://www.arduino.cc/en/Reference/softwareSerial) を使っていたのだが Adafruit Trinket M0 では H/W Serial が使えるということだったので、いろいろ探したのだがピッタリのものが見つからない。 [Arduino Zero の](https://www.arduino.cc/en/Tutorial/SamdSercom)は何とか見つかり、[STM32 を使った Adafruit 向けの情報](https://learn.adafruit.com/using-atsamd21-sercom-to-add-more-spi-i2c-serial-ports/creating-a-new-serial)も見つかったのだがなかなかうまくいかず...。
  
　ということで苦労して動くようにしたのでメモ。  

サンプルソース
-
[github](https://github.com/kuma-hati-labo/Adafruit-Trinket-M0-Serial2-sample/blob/master/Adafruit-Trinket-M0-Serial2-sample.ino) にあるので、お急ぎの方はこちらを。

パラメータの定義とオブジェクトの宣言
-
```
#define PIN_SERIAL2_RX       (2ul) // PA09
#define PAD_SERIAL2_RX       (SERCOM_RX_PAD_1)
#define PIN_SERIAL2_TX       (0ul) // PA08
#define PAD_SERIAL2_TX       (UART_TX_PAD_0)

Uart Serial2( &sercom2, PIN_SERIAL2_RX, PIN_SERIAL2_TX, PAD_SERIAL2_RX, PAD_SERIAL2_TX ) ;
```
割り当てたのは Pin 0, 2。なぜか RX が入力なので要注意。他のピンへの割り当ても可能だが、かなり難解。どうしてもという場合は[こちら](https://cdn-learn.adafruit.com/downloads/pdf/using-atsamd21-sercom-to-add-more-spi-i2c-serial-ports.pdf)を参考に。

ポートをシリアルポートに割り当て
-
```
    Serial2.begin(115200);
    pinPeripheral(0, PIO_SERCOM_ALT);
    pinPeripheral(2, PIO_SERCOM_ALT);
```
　pinPeripheral() で、物理的なピンをSERCOM(CPU 内部のシリアル関連を制御するモジュール)に割り当てる。

割り込みハンドラの追加
-
```
void SERCOM2_Handler() {
  Serial2.IrqHandler();
}
```
　割り込み側ハンドラはユーザー側のコードで定義が必須。SerialEvent() は、使わない場合は定義しなくてもよいが、Adafruit M0 系にシリアルを追加する場合は割り込みハンドラの定義が必須。これがなくともコンパイラはエラーを吐かないが、プログラムが動かない。


終わりに
-
　コードにすると10行ほどだが、ここまでたどり着くのに半日かかってしまった...。
homebrewでnodeモジュールのダウングレード

homebrewでダウングレードしたnodeを使用する際に、詰まった部分を残します。

###環境
インストール済みのnodeバージョン：13.11.0
インストールしたいnodeバージョン：12.16.1

macOS:10.14.3


##nodeバージョン12系をインストール
バージョン指定の方法が12系の場合`@12`で最新の12系のバージョンがインストールできます。

```
$ brew install node@12
==> Downloading https://homebrew.bintray.com/bottles/node@12-12.16.1.mojave.bott
==> Downloading from https://akamai.bintray.com/3d/3dee3426e2ea8928d0724a801591a
######################################################################## 100.0%
==> Pouring node@12-12.16.1.mojave.bottle.tar.gz
==> Caveats
node@12 is keg-only, which means it was not symlinked into /usr/local,
because this is an alternate version of another formula.

If you need to have node@12 first in your PATH run:
  echo 'export PATH="/usr/local/opt/node@12/bin:$PATH"' >> ~/.bash_profile

For compilers to find node@12 you may need to set:
  export LDFLAGS="-L/usr/local/opt/node@12/lib"
  export CPPFLAGS="-I/usr/local/opt/node@12/include"

==> Summary
🍺  /usr/local/Cellar/node@12/12.16.1: 4,293 files, 57.8MB
```

12系のバージョンはインストールが完了しました。

しかし、13系のバージョンを残したままインストールすると複数のノードパッケージをインストールできますが、同時に使用できるようにすることはできません。
したがって、既存のパッケージ（ここでは13系）が入っている場合は最初にその紐付きを解除する必要があります。


##インストール済みのバージョンの紐付きを解除


以下のコマンドで現在紐付いているバージョンを解除できます。

```
$ brew unlink node
Unlinking /usr/local/Cellar/node/13.11.0... 0 symlinks removed
```

##使用したいバージョンを紐付ける

今回は12系のnodeバージョンを紐付けたいので以下のように設定します。

```
$ brew link node@12
Warning: node@12 is keg-only and must be linked with --force

If you need to have this software first in your PATH instead consider running:
  echo 'export PATH="/usr/local/opt/node@12/bin:$PATH"' >> ~/.bash_profile
```

紐付けを行なった際に`.bash_profile`のnodeのパスを設定してくださいと警告が出ているので、設定します。

```
$ echo 'export PATH="/usr/local/opt/node@12/bin:$PATH"' >> ~/.bash_profile
```

`.bash_profile`を念のため更新

```
$ source ~/.bash_profile
```

最後にnodeのバージョンを確認

```
$ node -v
v12.16.1
```

成功です。


---
余談ですが、今回バージョンを落とした理由は
`gatsby-cli v2.11.1`をインストールする際に、nodeモジュールが13.11.0の場合インストールに失敗してしまう事がきっかけでした。

ダウングレードにより、無事`gatsby-cli`の導入もできました。

```
$ gatsby --version
Gatsby CLI version: 2.11.1
```
[OCI] Autonomous Database) SQL Developer Webの接続ユーザの変更してみた。

OCI Autonomous Database(ADW/ATP)では、デフォルトでSQL Developer Webが構成されています。
Webコンソールから起動するSQL Developer Webは、ADMINユーザで接続するように構成されています。
ADMINユーザ以外のDatabaseユーザで接続する方法を試しました。	

### 参考情報
- [SQL Developer Webへのユーザー・アクセスの有効化](https://docs.oracle.com/cd/F25236_01/sdweb/about-sdw.html#GUID-63D265FC-7500-4F88-8870-1C60E0A286FF)

# Databaseユーザの作成
ADMINユーザでAutonomous Databaseに接続し
Databaseユーザを作成、必要な権限の付与（表領域Quataなど）

```
create user demo identified by <demo user password>;
grant connect,resource to demo;
ALTER USER demo QUOTA UNLIMITED ON DATA;
```

# ユーザー・アクセスの有効化
引き続きADMINユーザで次のコードを実行

```
begin    
  ords_admin.enable_schema(
    p_enabled => true,
    p_schema => 'DEMO', -- Actual name of the schema
    p_url_mapping_type => 'BASE_PATH',
    p_url_mapping_pattern => 'api', -- Alias used in the URL for access
    p_auto_rest_auth => true
  );

  commit;

end;
```

- p_schema => 接続するすべて大文字のデータベース・スキーマ名
- p_url_mapping_pattern => ユーザーがSQL Developer Webへのアクセスに使用するURLに表示されるスキーマ名の別名
  - スキーマ名自体は使用を避けることでスキーマ名が公開されない

# SQL Developer Webの起動とアクセスするURLの変更
1. WebコンソールからAutonomous Database の詳細から「ツール」をクリック
![image01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108635/a933d147-b569-499f-cfbf-1be7c2763a25.jpeg)

2. 「SQL Developer Webを開く」をクリック
![image02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108635/6988bc0e-7cdf-4539-0c53-e629baa61627.jpeg)

3. 表示されるURLの文字列の「admin」を p_url_mapping_pattern で指定した文字列に変更
![image03.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108635/e4c1cd5f-4ae3-05ee-23b2-5f9cbb16d936.jpeg)

4. p_schema で指定したデータベースユーザでログイン
![image04.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108635/af4dc58b-e141-6533-a5a9-3600908befba.jpeg)


5. 指定したユーザでログインされていることを確認
![image05.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108635/713fd177-585d-4a83-5faa-a875b90d289e.jpeg)


-- 
SQL Developer Webの接続ユーザの変更ができました。
Cテスト

```C:test.c
typedef struct
{
    int  cnt;
    long dat[12];
}can_mon_buf;

can_mon_buf mon_jstand[10];

void mon_buf_hold(int pat)
{
    int i;

    /* 初期化 */
    static bool inifinflg = FALSE;
    if (TRUE != inifinflg){
        memset((char*)&mon_jstand, 0x00, sizeof(mon_jstand));
        initfinflg = TRUE;
    }

    i = mon_jstand[pat].cnt;
    if (12 >= i){
        mon_jstand[pat].dat[i] = dat;
    }else{
        mon_jstand[pat].cnt++;
    }
}
```
【エラー】ターミナルにてOperation not permittedエラーの解消方法

# はじめに

現在のバージョン：
macOS Catalina 10.15.3

ターミナルにてDesktopに保存したプログラム（ファイル）を動かす為、Desktop配下で実行した際に下記エラーが発生しました。

`Operation not permitted`

# 原因
原因を調べるとmacOSをアップデートしてからセキュリティが強化されターミナルの権限に影響した模様。（macOS Mojaveから影響）

# 解消方法
ターミナルアプリにディスクフルアクセスの権限を付与する必要がありました。
下記、手順になります。

##### ①システム環境設定から「セキュリティとプライバシー」を選択<img width="666" alt="スクリーンショット 2020-03-24 23.39.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607914/fc6fa298-e39b-e106-c8fa-e7d815048d85.png">

#### ②プライバシーの中のフルディスクアクセスを選択し、鍵を解除後ターミナルにチェック<img width="669" alt="スクリーンショット<img width="666" alt="スクリーンショット 2020-03-24 23.56.17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607914/077efa7c-4812-1c5d-975b-f96c9c463db6.png">

上記対応後、ターミナルで再度実行すると解消しました。