OmniAICreator/Qiita-1.07M huggingface dataset:
[Python]YWTの日報をOutlookメールで自動作成してみた



# 概要
毎日YWTの日報メールを作るのがだるい...
メールのテンプレート作成をしても、件名に今日の日付を毎回打たなきゃいけない...
PythonでOutlookのメールを自動作成できないか試してみた記事になります。
初めての投稿のため、色々とおかしいところがありますがそこはスルーで...

**YWTについては[こちら](https://www.kikakulabo.com/tpl-ywt/#:~:text=YWT%E3%81%A8%E3%81%AF%E3%80%81%E3%80%8CY%EF%BC%9A,%E3%81%AE%E6%B5%81%E3%82%8C%E3%81%AF%E5%90%8C%E3%81%98%E3%81%A7%E3%81%99%E3%80%82)**

# やりたいこと
1. 日報メールのYWTテンプレートを自動作成したい
2. 件名に今日の日付をいれたい
3. 昨日の日報メールのTの＜次にやること＞を今日の日報メールのYの＜やったこと＞にする

3については昨日のTを今日のYに書くことが多いので、
必要にしている人は自分以外にいるのか微妙...

# コード
```Python
import win32com.client
import datetime
import re


# 昨日の日報メールの本文を取得する
today = datetime.datetime.now()
object = win32com.client.Dispatch("Outlook.Application")
ns = object.GetNamespace("MAPI")
folder = ns.GetDefaultFolder(6) # 6はOutlookの受信トレイフォルダを表している

days_cnt = 1
flag = False # 昨日の日報メールが見つかったらTrue、見つからなかったらFalse
# 昨日の日報を探す
while flag == False:
    yesterday = today - datetime.timedelta(days=days_cnt)
    yesterday_sub ="日報[{}月{}日]".format(yesterday.month,yesterday.day)
    for i in reversed(folder.Items):
        if yesterday_sub in i.Subject:
            text = i.Body # 昨日の日報メールの本文を入れる
            flag = True # 昨日の日報メールが見つかったのでTrue
            break
    days_cnt += 1 # 日付の日報メールが見つからなかったら、その日付の昨日にする
        
    
# ＜次にやること＞の内容を抜き出す
result = re.findall('＜次にやること＞[^＜]+',text)
b = result[0].replace('＜次にやること＞', '')
# 「・～～～」の内容を抜き出す
result2 = re.findall('・.+\r\n',b)
sentence = ""
for i in result2:
    sentence += i


# メール送信
object = win32com.client.Dispatch("Outlook.Application")
mail = object.CreateItem(0) 
mail.BodyFormat = 1

# 宛先の設定　To,CC,Bcc
mail.To = "yyy@vvv.com" # 自分のメールアドレス
# mail.cc = "yyy@vvv.com"
# mail.Bcc = "yyy@vvv.com"

mail.Subject = "日報[{}月{}日]".format(today.month,today.day) # メールの件名

# メールの本文
mail.Body = """\
お疲れ様です。
日報を送ります。

＜やったこと＞
"""+sentence+"""\
    
＜わかったこと＞

＜次にやること＞

以上です
"""

mail.Display(True) # 作成したメールの表示

# mail.Send() # メール送信
```

# 結果
#### 昨日の日報メールはこちら
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/763295/548d7e26-886b-a2ac-54d2-fbdfc1c43eb7.png" width=90%>
#### 今日の日報を自動作成
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/763295/859363fa-d070-fddf-24fa-10f1171e285b.png" width=90%>

**赤線は自分のメールアドレスです**

# まとめ
OutlookのメールをPythonで自動作成できた。
これで日報メールを作る手間が少し省ける！

時間が合ったらリファクタリングをしたい！
TeamsやMattermostで日報をYWTで提出することがあるので、この２つでも自動作成してみたい。

# 参考
[メールのテンプレート作成](https://www.crie.co.jp/chokotech/detail/282/)
[PythonでOutlookのメール送信](https://qiita.com/watyanabe164/items/e1c21af0127497b74b2a)
【pyxel】「failed to initialize SDL Audio in 'Audio'」の解決法

pyxelをインストールし、とりあえずサンプルプログラムを実行……しようと思ったら

```
pyxel error: failed to initialize SDL Audio in 'Audio'
```
というpyxel errorが発生しました。無事解決できたので、同じエラーで困っている人のために解決法を書いておきます。

#解決法
デスクトップPCにイヤホンを刺したら解決しました。音声出力デバイスが１つも無いせいで上記のエラーが発生していたようです。

僕のデスクトップPCにはスピーカーが接続されておらず、音楽を聞く時だけイヤホンを刺す使い方をしていたので、このエラーが出たときには音声出力デバイスがなにも接続されておらず……。
例えBGMを聞かない場合でも、pyxelで作ったゲームを起動するときには音声出力デバイスがつながっている必要があるみたいです。
GitHubでフォーク元の変化を取り込む

GitHubで共同開発をしていると、フォークしてから作業をするという形で作業することが多くなるかと思います。

その際、フォーク元のリポジトリに差分が生じてしまうと```git pull```では差分を取り込むことができません。

そこで今回はフォーク元の差分を自身のリポジトリに反映させる方法を書きます。

# 手順
まずは正しくupstream先が登録されているか確認します。

```
$ git remote -v
origin	git@github:private/hoge.git (fetch)
origin	git@github:private/hoge.git (push)
upstream	git@github:work/hoge.git (fetch)
upstream	git@github:work/hoge.git (push)
```

もしupstream先を登録できていない場合は下記コマンドで登録します。

```
$ git remote add upstream git@github:work/hoge.git
```

後はupstream先の最新をfetchで追いかけて自身のリポジトリにマージします。

```
$ git fetch upstream
$ git merge upstream/master
```

意外と調べてもピンポイントで記事が出てこなかったので書きました。
Ruby 2.7.2 がリリースされ、今後は非推奨な警告はデフォルトでは出なくなる

[ブログ記事](https://secret-garden.hatenablog.com/entry/2020/10/06/162055)からの転載です。

先日 Ruby 2.7.2 がリリースされました。

* [Ruby 2.7.2 リリース](https://www.ruby-lang.org/ja/news/2020/10/02/ruby-2-7-2-released/)

このリリースで[先日お伝えした『非推奨な警告がデフォルトでは出なくなる』](https://secret-garden.hatenablog.com/entry/2020/09/27/192210)ようになりました。
なので、今後は非推奨な機能が削除されるといきなりアプリケーションが動作しなくなる可能性があります。
このような問題を回避するために今後は以下のようにして『明示的に非推奨な警告が出力されるようする』ことで安全に開発する事ができます。

* `-w` や `-W:deprecated` を付けて Ruby を実行す
* コード上に `Warning[:deprecated] = true` を追記する


## 参照

* [[Feature #17000] 2.7.2 turns off deprecation warnings by default](https://bugs.ruby-lang.org/issues/17000)
* [[Feature #16345] Don't emit deprecation warnings by default.](https://bugs.ruby-lang.org/issues/16345)
EC2インスタンス起動後に必要なセキュリティ設定


EC2 に SSH でログインした後、最低限必要な設定をまとめます。

## ユーザ設定

### ユーザ追加、パスワード設定

```
# ユーザ追加とパスワード設定
sudo useradd hogehoge
sudo passwd hogehoge
```

### wheel グループに追加

# 作成したユーザのディレクトリを確認

```
# wheelグループに追加
sudo usermod -aG wheel hogehoge

# wheelに所属しているユーザーの確認
less /etc/group | grep wheel
```

### 公開鍵設定

```
# 公開鍵のコピーとパーミッション設定
sudo cp -R ~/.ssh/ /home/hogehoge/.ssh
sudo chown -R hogehoge:hogehoge /home/hogehoge/.ssh
sudo chmod -R go-rwx /home/hogehoge/.ssh
```

## SSH 設定

### ec2-user へ直接 ssh を禁止

```
sudo echo "DenyUsers ec2-user" >> /etc/ssh/sshd_config
sudo systemctl restart sshd
```

### SSH ポート変更

```
sudo vi /etc/ssh/sshd_config

# デフォルトListen Portを修正
# Port 22
Port 12345
```

sshd を再起動しておきます

```
sudo systemctl restart sshd
```

**※指定したポートは AWS の Security Group で開けておいてください**

## セキュリティパッチの自動実行設定

賛否両論ありますが yum update を定期的に実行してくれる設定をします。

```
sudo yum install yum-cron

# 設定ファイルのバックアップ
sudo cp /etc/yum/yum-cron.conf /etc/yum/yum-cron.conf.backup

# sed コマンドで書き換え
sudo sed -i "s/^update_cmd.*$/update_cmd = security/g" /etc/yum/yum-cron.conf
sudo sed -i "s/^apply_updates.*$/apply_updates = yes/g" /etc/yum/yum-cron.conf

# yum-cronの起動と自動起動の設定
# 起動
sudo systemctl start yum-cron

# 自動起動の設定
sudo systemctl enable yum-cron

# ステータスの確認
systemctl status yum-cron
```

## タイムゾーンの変更

```
timedatectl status
sudo timedatectl set-timezone Asia/Tokyo
```
Automatorでシェルスクリプトまとめ【更新版】

###Pythonをターミナルから実行できるが、Automatorで正常に実行できない

参考サイト：https://teratail.com/questions/279608


```エラー文:エラー文
アクション“シェルスクリプトを実行”でエラーが起きました: “Traceback (most recent call last):
  File "goods.py", line 4, in <module>
    import chromedriver_binary 
ModuleNotFoundError: No module named 'chromedriver_binary'”
```

実行している環境が違う為エラーが表示される

```/bin/zsh:/bin/zsh
which python3　👈　ここでpython3の場所を特定
>> /usr/local/bin/python3　👈　結果をpython3のところに置き換える
```

```Automator:Aotomator
/usr/local/bin/python3 helloworld.py
```

これで無事実行できました。
Google Colabの制限を突破する話

# 忙しい人向け

<b>GoogleColabがreCAPTCHAを搭載したぽいのでこの記事の手法は完璧ではなくなりました。</b>


・Google　Colabの90分問題をどうにかするよ
・自動リロードはできないからコンソールからJavascriptで直接"再接続"を押すよ



```javascript
function ClickConnect(){
    console.log("更新")
    document.querySelector("#top-toolbar > colab-connect-button").shadowRoot.querySelector("#connect").click()
    document.querySelector("#top-toolbar > colab-connect-button").shadowRoot.querySelector("#connect").click()
}
setInterval(ClickConnect,3600*1000)
```


# Google Colabの制限とは
google colaboratory、通称Google Colabでは無料でGPUが使えるなどの豊富なメリットがありますが、その代償としていくつかの制限が設けられてます。GPUのリソース制限、未操作90分による接続切れ、12時間の連続運転による接続切れ。

今回はそのうちの未操作90分による接続切れ、いわゆる90分問題をどうにかします

# 過去にできたこと
「自動リロードによるページの再読み込み→自動接続」による接続切れ回避を前まではできるようになってましたが、現在は変更の破棄をするかどうか聞かれるダイアログにより行えなくなりました。
![Colab90-0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/557059/b62ca35d-39a7-85b3-734b-7302f721b4e8.png)


ちなみに同じようにリロードするとでてくるダイアログにあるチェックボックスにチェックを入れても無意味なようです。
![Colab90-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/557059/0823af4a-8b9c-7c50-e709-82d2e59c19b3.png)

ローカル上のスクリプト経由による自動リロードについては未検証です。

# 今回やること
なので今回は別の手法としてページ上でなにかしらの作業を定期的にさせるようなスクリプトを置きます。

実行中のセルに影響が出なければ問題はないはずですが、万が一ネットワークの不調などで接続が切れてしまった時のために右上の再接続ボタンを押すようにします。
![Colab90-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/557059/f5f9e527-0c9e-c545-239f-3c622743eddf.png)

コードは上記の通り。あとはブラウザのコンソールを立ち上げ（やり方はブラウザごとに違うので各自検索をお願いします）、コードを入力すれば完了です。

60分間に一回ボタンを押し、コンソール上のログに”更新”と出力します。

ちなみに、普段は再接続ではなく接続済みとなってるはずなので問題が起きなければアクティブなセッションの一覧が定期的に表示されるはずです。

# 自動リロードが通らない原因
どうやらセルのログが更新されるたびにページに変更が発生するようで、それをブラウザ側がありがた迷惑に確認してくるのが原因のようです。

# 参考元
https://qiita.com/enmaru/items/2770df602dd7778d4ce6
https://qiita.com/Gimina_Graph/items/4bdf3e3c3658eeb0eba8
https://flat-kids.net/2020/07/28/google-colab-%E3%82%BB%E3%83%83%E3%82%B7%E3%83%A7%E3%83%B3%E5%88%87%E3%82%8C%E3%82%92%E9%98%B2%E6%AD%A2%E3%81%99%E3%82%8B/

# 追記
冒頭のコードを変更しました。
変更点
・引っ張ってくる要素をGoogleColab側に合わせて変更しました
・二回押すことで画面上はほとんど変化がないようにしました（上手くいってるかわかりません）
Pythonによる正規表現操作

# はじめに
Pythonで正規表現を扱いたいときの操作をよく忘れるので、よく検索するものをメモ。よく検索するものが増えたら追記していきます。
網羅された情報を見たいなら[公式ドキュメント](https://docs.python.org/ja/3/library/re.html)へ。
reのインポートを忘れずに。正規表現の文法については[こちら](https://qiita.com/)でメモを残しているので参考までに。
# 概要
紹介している関数のまとめ。
ここでは、patternは任意の正規表現オブジェクトを、matchは任意のマッチオブジェクトを表す。

| 関数 | 内容 |
| ---- | ---- |
| re.compile(r"正規表現")| 正規表現オブジェクトの生成|
| pattern.search(文字列)| 文字列内でpatternに一致した最初のマッチオブジェクト|
| pattern.finditer(文字列)| 文字列内でpatternに一致した全てのマッチオブジェクトのイテレータ|
| match.start( ) | 検索結果の文字列内での開始インデックス|
| match.end( ) | 検索結果の文字列内での終了インデックス|
| match[0] | 検索結果の文字列|
# 文字列の検索(1つ)
例えば、文字列`私はPython初心者Aです`に「アルファベットの大文字」が入っているかどうかを知りたいとき。

```search_exam_1.py
import re
string = "私はPython初心者Aです" #文字列の定義
pattern = re.compile(r"[A-Z]") #正規表現パターンの定義
result = pattern.search(string) #検索

print(result)
print(result.start())
print(result.end())
```
```text
<re.Match object; span=(2, 3), match='P'>
2
3
```
正規表現を使うときは、それが正規表現であると認識してもらうための処理が必要。その処理が`re.compile()`である。なお、`re.search(r"[A-Z]",string)`で3、4行目をまとめると、テキストが複数ある時に毎回正規表現オブジェクトを生成することになってしまう。
また、正規表現内に\\(円記号)があった場合などにそれを正しく認識してもらうために、`r" "`で文字列を囲む必要がある。こうすると中の文字列がrawであるとPythonに認識される。詳しくは[公式ドキュメント](https://docs.python.org/ja/3/library/re.html)冒頭を参照。

`result`に返ってきたオブジェクトはマッチオブジェクトといって、検索文字列の中で最初にヒットしたものの情報を持っている。`start()`と`end()`のメソッドでそれぞれ開始と終了のインデックスを取得できるのが便利。
# 文字列の検索(複数)
文字列`私はPython初心者Aです`に入っている「アルファベットの大文字」を**全て**取得したいとき。


```search_exam_2.py
import re
string = "私はPython初心者Aです" #文字列の定義
pattern = re.compile("[A-Z]") #正規表現パターンの定義
results = pattern.finditer(string) #文字列の検索

for result in results: #検索結果のイテレータ(results)をresultに入れる
    print(result[0]) #マッチオブジェクトのアイテム
    print(result.start(), result.end())
```

```text
P
2 3
A
11 12
```

`finditer`で文字列を検索すると、マッチオブジェクトのイテレータが返ってくるので、一つずつfor文で展開する。複数検索はこのようにして実現される。
result[0]は何かというと、マッチオブジェクト内のグループの0番目にアクセスするという操作。複数個の文字列を検索すれば、マッチオブジェクトの内のグループは複数個になる。

# まとめ
ここでは、patternは任意の正規表現オブジェクトを、matchは任意のマッチオブジェクトを表す。

| 関数 | 内容 |
| ---- | ---- |
| re.compile(r"正規表現")| 正規表現オブジェクトの生成|
| pattern.search(文字列)| 文字列内でpatternに一致した最初のマッチオブジェクト|
| pattern.finditer(文字列)| 文字列内でpatternに一致した全てのマッチオブジェクトのイテレータ|
| match.start( ) | 検索結果の文字列内での開始インデックス|
| match.end( ) | 検索結果の文字列内での終了インデックス|
| match[0] | 検索結果の文字列|
今のところは、`search`と`finditer`関連を記載。今後また追記していきます。
アクション内でrenderを使わずにバリデーションエラーや入力していた内容を前ページに反映する方法

#はじめに
フォーム内容を送信する際、バリデーションに引っ掛かったら
`render`メソッドで新規投稿画面をレンダリングして
そこでエラーなり入力していた内容なりを表示すると学習した方が多いはず

しかし、`render`メソッドが使えない時はどうしますか？
実は制作中のポートフォリオにGoogleMapAPIを使用しているのですが
`render`でページをレンダリングするとなぜかMAPが表示しなくなる不具合が発生...

仕様を変えれば解決できる問題だったのですが、変えたくなかったので
`render`を使わずに上記の動きを実現する方法を紹介します。

#通常renderを使った場合
例として`tasks_controller.rb`に
新規投稿ページのアクション`new`と、
新規投稿内容を保存するアクション`create`があるとします。

```ruby:tasks_controller.rb

def create
  @task = Task.new(task_params)
  if @task.save
    redirect_to @task, notice: 'タスクを保存しました。'
  else
    render :new
  end
end

```

`@task.save`が失敗し`else`以下の`render :new`が実行され、
新規投稿ページがレンダリングされます。
あとはもうご存知のとおり、viewのほうで`@task.errors.full_messages`を活用してく感じですね。


#renderを使わない場合

`redirect_to`で再アクセスをするという形をとり、
エラー文や入力内容はアクション内で`flash`に格納してしまいます。

```ruby:tasks_controller.rb

def create
  @task = Task.new(task_params)
  if @task.save
    redirect_to @task, notice: 'タスクを保存しました。'
  else
    flash[:error_msgs] = @task.errors.full_messages
    flash[:tmp_body] = @task.body
    redirect_to new_task_url
  end
end
```

`flash[:error_msgs]`にはエラー文を、
`flash[:tmp_body]`には文章内容を、それぞれ格納しておきます。

あとはアクセス先のviewで、flashの値を活用してすればOKです。
以上！
macOS Catalinaで Xcode 12.0.1をインストールした


**動作環境**
``` MacBook Air(11-inch, Early 2015)
OS : macOS Catalina
OS バージョン : 10.15.7(19H2)
Xcode バージョン : 12.0.1
``` 

**結論**
・macOS Catalinaをインストールしておく
・AppleのDeveloperページからインストールする
・ハードディスクの容量不足に注意する

**①**
XcodeをMacBook Airにインストール
(https://apps.apple.com/jp/app/xcode/id497799835?mt=12)
しようとすると、

` Xcodeは“Macintosh HD”にはインストールできません。macOSバージョン10.15.4以降が必要です。` 
とエラーが表示され、インストールに失敗した。

**②**
```macOS Catalina```(https://support.apple.com/ja-jp/HT201475)
をダウンロードしてからインストールする必要があったので(https://discussionsjapan.apple.com/thread/251756763)

```macOS Catalina```をインストールして、Xcodeのインストールを再度実行すると、
Xcodeのインストールが始まったが、終わる気配なし。

**③**
App Storeからではなく、AppleのDeveloperページ(https://developer.apple.com/downloads/index.action?name=Xcode)
からインストールする方法があったので(https://fukatsu.tech/install-xcode#Developer)

Xcode ``` 12.0.1.xip```をダウンロードし、アーカイブユーティリティで展開しようとすると、ハードディスクの容量不足のエラーが表示され、xipファイルを解凍できず、インストールに失敗した。

**④**
ストレージの空き容量を増やし、(```Apple メニュー  ``` >```「この Mac について」```>```「ストレージ」```>```「管理...」```)
再起動した上で再度アーカイブユーティリティで展開すると、無事解凍でき、インストールに成功した。
Gitのデフォルトブランチをmasterからmainに変更する方法

# はじめに
GitHubのデフォルトブランチがmasterからmainに変更されました。
理由等は以下の記事を参考にしてもらえるとmainに変更された理由がわかります。

[GitHub、これから作成するリポジトリのデフォルトブランチ名が「main」に。「master」から「main」へ変更 － Publickey](https://www.publickey1.jp/blog/20/githubmainmastermain.html)

これに準じて、ローカルリポジトリもmasterからmainに変更することで、煩わしい状態が減ります。
例えば、masterのままでいると、同じ役割を果たすmasterのブランチとmainのブランチが2つ共存する形になり結局削除する手順が必要になってしまいます。

この手順を続けるのはかなり面倒くさいです。ですが、ローカルリポジトリのデフォルトブランチをmasterからmainに変更することで、上記のような煩わしさはなくなります。

以下で、デフォルトブランチをmasterからmainに変更する方法を載せます。

# ローカルリポジトリのデフォルトブランチをmasterからmainに変更する方法
変更するにあたって行う手順は2つだけです。

- Gitのバージョンをアップデートする
- git configでデフォルトのブランチを変更する

## Gitのバージョンをアップデートする

**最新にする前に、Gitのバージョンを確認してください。**
Gitのバージョンを確認したい場合、以下をコマンドプロンプト等で打ち込むことで確認することが可能です。

```
$ git --version
```

Gitのバージョンが **2.28.0** 以降でしたらコマンドでデフォルトのブランチ名を変更できるため、バージョンをアップデートする必要はありません。次に進んでください。

逆にバージョンが上記のバージョンよりも低い場合は、更新する必要があるので、アップデートをしてください。

### Macユーザーの場合
Homebrew等を使用してアップデート等する必要があるので、以下の記事等を参考にしてアップデートしてください。

- [最新の Git を Mac にインストールする手順 - Qiita](https://qiita.com/normalsalt/items/f200ba50363ebfd46df0)
- [macOS git を update したメモ - Qiita](https://qiita.com/MochiMochiChip/items/d91c12e40cd0de84b804)

### Windowsユーザーの場合
GitBashやコマンドプロンプト等を用いて以下のコマンドを打ち込むことでアップデートが可能です。

```
$ git update-git-for-windows
```

筆者は、以下の記事を参考にアップデートすることができました。

[【Git】インストール済みのGitをアップデートする【Windows環境】 | かずさプログラマーの雑記帳](https://kazusa-pg.com/installed-git-update/)

# git configでデフォルトのブランチを変更する
以下のコマンドを打ってもらえるとデフォルトのブランチ名を変更できます。

```
$ git config --global init.defaultBranch main
```

これでデフォルトブランチの変更が完了です。

実際にローカルリポジトリを作成してステージングしてコミットした後に `git branch` で確認すると、作成されたブランチが`main`に変更されています。

# （補足）作成したmasterブランチをmainに変更する方法
```
$ git branch -m master main
```
すでにブランチを作ってしまった場合はこのコマンドを打つことで変更可能です。

# 参考記事
[Highlights from Git 2.28 - The GitHub Blog](https://github.blog/2020-07-27-highlights-from-git-2-28/)
template_c配下ファイル削除

## 背景
現在開発中のプロジェクトがfuelphpで開発。
テンプレートを更新した際にブラウザに変更が反映されなかった。

## 原因
teplate_c配下viewのキャッシュが生成されるので、変更が反映されない場合はtemplate_c配下のファイルを削除してみるとよい。
template_c配下のファイルを削除したあとブラウザを読み込むと新しくキャッシュファイルが生成される。

参考:http://co-co-wa.com/smarty-tpl-templates_c-permission/
【その２】wicked_pdfで日本語が表示されない場合の対処法

[【その1】wicked_pdfで履歴書を作成するまで](https://qiita.com/michiru-miyagawa/items/a5c87896b1e1c52cb63c)の続きで、【その２】wicked_pdfで日本語が表示されない場合の対処法について書いていきたいと思います。

## ハマったポイント

### 日本語の文字化け

wicked_pdfを使用すると日本語が文字化けし、表示されないという問題がありました。
Docker開発環境の場合、Dockerfileに`fonts-ipafont`をインストールすることで解決できます。
そうでない場合は、下記のコマンドでIPAフォントのインストールをする必要があります。
※ Linux に日本語が入っていないためフォントのインストールが必要

```
$ yum install -y ipa-gothic-fonts
$ yum install -y ipa-mincho-fonts
```

### 明朝体の表示
`font-family`を`serif`にしてしまうとAndroidでは明朝体で表示されません。Webフォントを設定することでAndroidからでも明朝体で表示することができます。


```sass:app/assets/stylesheets/application.sass 
@import url('https://fonts.googleapis.com/css?family=Noto+Serif+JP&display=swap&subset=japanese')
```

```sass:app/assets/stylesheets/pdf.sass
.resume__content
  font-family: 'Noto Serif JP', serif
```

```haml:app/views/layouts/pdf_template.html.haml
%html
  %head
    -#%meta{:content => "text/html; charset=UTF-8", "http-equiv" => "Content-Type"}/
    %meta{:charset => "utf-8"}/
    %meta{ name: 'viewport', content: 'width=device-width, initial-scale=1.0' }
    %meta{ name: 'x-apple-disable-message-reformatting' }
    = wicked_pdf_stylesheet_link_tag 'pdf'
    = stylesheet_link_tag "https://fonts.googleapis.com/css?family=Noto+Serif+JP&display=swap&subset=japanese"
// ↑↑上記を追加
```

レイアウトを諸々整えると、以下のようにPDFで出力可能。
しっかり明朝体での出力もできています。
![スクリーンショット 2020-10-06 18.49.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/623708/7183e338-cd6c-1d4e-cb95-b5af9b5906f2.png)
VirtualBoxでホストOSとゲストOSのマウントに失敗した

# 出力されたエラー
```
Failed to mount folders in Linux guest. This is usually because
the "vboxsf" file system is not available. Please verify that
the guest additions are properly installed in the guest and
can work properly. The command attempted was:

mount -t vboxsf -o uid=`id -u vagrant`,gid=`getent group vagrant | cut -d: -f3`,dmode=777,fmode=666 vagrant /vagrant
mount -t vboxsf -o uid=`id -u vagrant`,gid=`id -g vagrant`,dmode=777,fmode=666 vagrant /vagrant

The error output from the last command was:

/sbin/mount.vboxsf: mounting failed with the error: No such device
```

# 原因
自分の環境の VirtualBox のバージョンと Box にインストールされている Guest Addition のバージョンが違ったから

# 解決方法
vagrant-vbguest のプラグインをいれておく。

# vagrant-vbguestとは
自分の環境の VirtualBox のバージョンと Box にインストールされている Guest Addition のバージョンが違う場合に、VirtualBox のバージョンに合わせて最新化してくれるもの

# コマンド
```
// vagrant-vbguest のプラグインを入れて
$ vagrant plugin install vagrant-vbguest

// 仮想マシンを再起動
$ vagrant reload
```
VagrantでCent OSの仮想サーバをたてる

## Vagrantとは
仮想マシンの簡単な構築や、どこでも同じ環境を再現できるように仮想マシンを管理するためのコマンドラインツール

## 手順
Windows(64bit)環境にインストールする手順
### 1. VirtualBoxとVagrantをインストール
以下のURLからそれぞれインストーラーをDLしてインストール。
 - Vagrant
https://www.vagrantup.com/downloads.html
- VirtualBox
https://www.virtualbox.org/wiki/Downloads

インストールしたらPCを再起動し、コマンドプロンプトでバージョン確認

```
>vagrant -v
Vagrant 2.1.2
```

### 2. つくりたいBoxを検索
https://app.vagrantup.com/boxes/search でインストールするBoxファイルを検索。
たとえばCentOSなら「bento/centos-7.3」とか。

### 3. Vagrantを初期化
まず専用のフォルダを作る

```
mkdir centos7
```

Vagrantを初期化

```
# このコマンドは「2. つくりたいBoxを検索」で確認できる
vagrant init bento/centos-7.3
```
→centos7フォルダにVagrantfileが作成されたらOK。

### 4. Vagrantfileを編集
```
～
config.vm.box = "bento/centos-6.7"
# ↑ここはvagrant init時に指定したBox名が設定されている
～
config.vm.network "private_network", ip: "192.168.33.10"
# ↑ここのコメントアウトを外し、好きなIPアドレスにする
～
```
### 4. 仮想マシンを起動
```
vagrant up
```

### 5. 仮想マシンにログイン
RloginなどのSSHクライアントからログインする。

- 接続先ホスト名
Vagrantfileに書いてあるIPアドレス（192.168.33.10）

- ポート
22番
- ユーザー名/パスワード
vagrant / vagrant
root / vagrant
使用したメソッドまとめてみた

アプリ制作の際、使用したメソッドを忘れないように都度追加していこうと思います。

● order
orderメソッドとは、レコードを並び替える事ができるメソッドです。
.order(id: "DESC")のように記述すると、idをDESC(降順)で並び替えるという意味になります。
DESC（降順）の逆はASC(昇順)です。orderメソッドを使用しないデフォルトでは、ASCになっています。

メモの順番を降順にする場合。
![orderメソッド.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/702625/56011576-2d90-86dc-727b-3df13e0bbd2e.png)

これで、メモを降順で表示できるようになりました。

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
●floorメソッド
小数点を消し整数にする
ex.
Math.floor

●ceil
切り上げ

●include?メソッド
include?メソッドは指定した要素が、配列または文字列に含まれているかを判定するメソッドです。
![include?メソッド.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/702625/12c1307e-b01a-cf18-e234-b74891747d93.png)
DynamoDBをローカルで構築し、AWS CLIコマンドを使っていじるまで

実施環境はWindowsのPC内にVagrantで立てたCentOSの仮想マシンです。


## Javaがなかったので入れる
```
[root@localhost ~]# yum install java-1.8.0-openjdk
[root@localhost ~]# java -version
openjdk version "1.8.0_181"
OpenJDK Runtime Environment (build 1.8.0_181-b13)
OpenJDK 64-Bit Server VM (build 25.181-b13, mixed mode)
```

## dynamodb-localをダウンロード
```
[vagrant@localhost ~]$ sudo su -
[root@localhost ~]# wget http://dynamodb-local.s3-website-us-west-2.amazonaws.com/dynamodb_local_latest.tar.gz

100%[========================================================================================================================================>] 16,884,788  3.26MB/s   in 4.9s   

2018-09-12 06:52:31 (3.26 MB/s) - ‘dynamodb_local_latest.tar.gz’ saved [16884788/16884788]
```
## 展開
```
[root@localhost ~]# tar zxvf dynamodb_local_latest.tar.gz
```
## 起動
```
[root@localhost ~]# java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar -sharedDb
Initializing DynamoDB Local with the following configuration:
Port:   8000
InMemory:       false
DbPath: null
SharedDb:       true
shouldDelayTransientStatuses:   false
CorsParams:     *
```
停止するときはCtrt + cで
## AWSCLIを入れる
公式ページを参考に
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/awscli-install-linux.html

### まずpython-pipを使えるようにする
```
[root@localhost~]# yum install python-setuptools -y
[root@localhost~]# easy_install pip
```
### AWS CLIをインストール
```
[root@localhost ~]# pip install awscli
[root@localhost ~]# aws --version
aws-cli/1.16.12 Python/2.7.5 Linux/3.10.0-514.26.2.el7.x86_64 botocore/1.12.2
```

## AWS CLIを使ってDynamoDBをいじる
### aws configureを設定

```
[root@localhost ~]# aws configure
AWS Access Key ID [None]: ＜アクセスキーID＞
AWS Secret Access Key [None]: ＜シークレットアクセスキー＞
Default region name [None]: ap-northeast-1 // なんとなく東京に
Default output format [None]: json
```
アクセスキーIDとシークレットアクセスキーは一度AWSのコンソールから発行してもらったものを設定したけど
ローカルで動かす場合はダミーでよかった。
むしろ本当のアクセスキーを設定したので```「--endpoint-url http://192.168.33.11:8000」```を付けなかった場合、
ローカルのDynamoDBではなくAWS上のDynamoDBにアクセスしてしまった( ´△｀)

### テーブル一覧
```
[root@localhost ~]# aws dynamodb list-tables --endpoint-url http://192.168.33.11:8000
{
    "TableNames": []
}
```
endpoint-urlは接続先ホスト名。
今回はVagrantで立てた仮想マシン内で実行するためVagrantfileに書いてあるIPアドレス（192.168.33.10）を指定した。
UnityAndroidでExportしたprojectをステップ実行



# 環境１
OS : win10 pro
Unity5.6
AndroidStudio2.3.2

OS : win10 pro
Unity2019
AndroidStudio4

# 手順
・Unity　C#プラグインメソッドを呼び出す。pluginは消す。
・UnityでExportする。
・AndroidStudioでそれを開く。
・AndroidStudioで、C#で呼び出したプラグインメソッドと同じIFのメソッドを作成する。

# 確認

Java層でブレークポイント停止するのを確認した。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555658/0fba47f2-cc67-5597-4b4a-ac9b37fb7a9f.png)

AndroidJavaObjectの引数は　JavaクラスへのFULLPATH　/ TestMainがクラス名
Unity/Assert/Plugins/Android以下は空にしてEXPORTする。

c#

```

	string PluginPackageClass = "com.ore.test.TestMain";
	AndroidJavaObject mImageLoader = null;

	public void init_lib()
	{
		m_text.text = "init_lib";
		try
		{
			mImageLoader = new AndroidJavaObject(PluginPackageClass);
			if (mImageLoader != null)
			{
				int t_no = mImageLoader.CallStatic<int>("getNo");
				m_text.text = t_no.ToString();
            }
            else
            {
				m_text.text = "null";

			}

		}
		catch(Exception e)
        {
			Debug.Log(e.ToString());
			m_text.text = "ex a";
		}
	}

```

# ExportしたJava

Android4で開いて、PluginPackageClass を作成する。これに合わせたコードを書いていき、動作確認できたら、その部分をLibにして
Unity/Assert/Plugins/Androidにもっていく。

```

package com.ore.test;

public class TestMain {
    static int m_no = 0;
    public static int getNo(){
        if ( m_no == 0) {
            return 44;
        }else{
            return 22;
        }

    }

    public  int getNo2(){
        return 44;
    }
}


```
SonarQubeのDockerContainerをUpdateした話

# はじめに
[SonarQubeをDockerContainerにしてみた話](https://qiita.com/awakuwaku/items/05c230bf7380fe29a69d) の `SonarQube` のその後の話です。


# 経緯
ある開発のお手伝いをしたのですがオンプレミス環境でかなり古いバージョンの `SonarQube` を利用していて微妙な状態でした。
個人的に2年近く前にSonarQubeのDockerContainer化をしていたので、最新のバージョンにして提供しましたのでその際の備忘です。


# 実施したこと
- SonarQube Ver 7.4 を SonarQube Ver 8.4.2に変更
- SonarQube用のDBを MySQL から PostgreSQL  Ver 13.0 に変更（[End of Life of MySQL Support](https://community.sonarsource.com/t/end-of-life-of-mysql-support/8667) ）
- docker-composeファイルを Ver 3 に変更


## SonarQube Ver 7.4 を SonarQube Ver 8.4.2に変更
利用するContaner Imageを `sonarqube:8.4.2-community` に変更するだけの簡単な作業です。

```yaml
  # SonarQube Server
  sonarqube-server:
    container_name: sonarqube-server
    image: sonarqube:8.4.2-community
```


## SonarQube用のDBを MySQL から PostgreSQL  Ver 13.0 に変更
[End of Life of MySQL Support](https://community.sonarsource.com/t/end-of-life-of-mysql-support/8667) の通り、最新の `SonarQube` ではMySQLがサポートされないためPostgreSQLに乗り換えます。

利用するContaner Imageを `postgres:13.0-alpine` に変更し、[公式ガイド](https://hub.docker.com/_/postgres)を参考に `volumes` と `environment` を変更します。
合わせてcontainer_nameなどもわかりやすいものに変更します。

```yaml
  # SonarQube Server用Database
  postgres-sonarqube:
    container_name: postgres-sonarqube
    image: postgres:13.0-alpine
    volumes:
      - "./data/postgresql/init:/docker-entrypoint-initdb.d"
      - "./data/postgresql/db:/var/lib/postgresql"
    ports:
      - "5432:5432"
    networks:
      - sonarqube-server-network
    environment:
      - POSTGRES_USER=sonar
      - POSTGRES_PASSWORD=sonar
      - POSTGRES_DB=sonar
```

また、 `SonarQube` ContanerのDB接続情報(`environment`)も変更します。

```yaml
  # SonarQube Server
  sonarqube-server:
    container_name: sonarqube-server
    image: sonarqube:8.4.2-community
    command: -Dsonar.web.context=/sonarqube
    links:
      - postgres-sonarqube:postgres
    volumes:
      - ./data/sonarqube/extensions/plugin:/opt/sonarqube/extensions/plugins
    ports:
      - "9000:9000"
      - "9092:9092"
    networks:
      - sonarqube-server-network
    environment:
      - SONARQUBE_JDBC_USERNAME=sonar
      - SONARQUBE_JDBC_PASSWORD=sonar
      - "SONARQUBE_JDBC_URL=jdbc:postgresql://postgres-sonarqube:5432/sonar"
```


## docker-composeファイルを Ver 3 に変更
今はVer3が主流なので、docker-composeファイルのversionsも `3` に変更します。

```yaml
version: '3'
services:
```


## 動作確認
ここまで対応したら、以下のコマンドで動作確認をして作業終了です。

```shell
docker-compose up --force-recreate sonarqube-server
```


# 感想
データ移行は考慮しないバージョンアップ作業が主なので簡単でした。
改めてDocker Container化しておくとこの辺は簡単で良いと感じました。
これでしばらくは頑張れそうですね。

本記事の対応は以下のgithubリポジトリに公開していますので興味ありましたら参考にしてください。
https://github.com/awakuwaku/sonar-qube-docker


# 参考
- https://hub.docker.com/_/sonarqube/
【laravel-admin】【grid】Custom Actions Class

##gridの\Encore\Admin\Grid\Displayers\ActionsをoverrideしてCustomActionsを作る

```CustomActions.php
namespace App\Admin\Controllers;

use Encore\Admin\Admin;

class CustomActions extends \Encore\Admin\Grid\Displayers\Actions
{
    protected $actions = ['edit'];
    protected function renderEdit()
    {
        if(false !== strpos($_SERVER["REQUEST_URI"], env('ADMIN_ROUTE_PREFIX', 'admin')."/auth")){
            return <<<EOT
<a href="{$this->getResource()}/{$this->getRouteKey()}/edit" class="{$this->grid->getGridRowName()}-edit">
    <i class="fa fa-edit"></i>
</a>
EOT;
        }else{
            $this->setupEditScript();
            return <<<EOT
<a href="{$this->getResource()}/" class="{$this->grid->getGridRowName()}-edit btn btn-xs btn-default">
    <i class="fa fa-edit"></i> 編集
</a>
EOT;
        }
    }
    protected function setupEditScript()
    {
        $trans = [
            'delete_confirm' => trans('admin.delete_confirm'),
            'confirm'        => trans('admin.confirm'),
            'cancel'         => trans('admin.cancel'),
        ];

        $script = <<<SCRIPT

$('.{$this->grid->getGridRowName()}-edit').click(function (e) {
    var id = $(this).closest('tr').find('.column-ID').text();
    id = $.trim(id);
    var currentHref = $(this).attr('href');
    var newHref = currentHref + id + '/edit';
    window.location.href= newHref;
});

SCRIPT;

        Admin::script($script);
    }
}
```

```bootstrap.php
Encore\Admin\Grid\Column::define('__actions__', \App\Admin\Controllers\CustomActions::class);
```

gridの編集ボタン&それをクリックしたときの挙動を変えたかった時に対応しました。

`\Encore\Admin\Grid\Displayers\Actions`をoverrideした`CustomActions`クラスを作って、`bootstrap.php`に上記を追記します。
LaravelにてDBから取得した画像をツイートする方法

##はじめに
今回は認証済みでアクセス情報も取得している前提で進めますので、
まだの方は先にそちらを完了させて下さい！

php.7.0
Laravel 7

##本文

```
 composer require abraham/twitteroauth //twitteroauthをインストール
```


```TweetController.php
 use Abraham\TwitterOAuth\TwitterOAuth;//先程インストールしたのをuse
 public function index(Request $request)
    {
        $api_key = //apiキーをセット;
        $secret_Key = //シークレットキーをセット;
        $access_token = //アクセストークンをセット;
        $access_token_secret = //アクセストークンシークレットをセット;

        //インスタンスを作成
        $twitter = new TwitterOAuth($api_key, $secret_Key, $access_token, $access_token_secret);

        //ここは適宜画像を取得してください
        $user = App\Models\User::inRandomOrder()->first();
        
        //画像の内容を読み込む
        $post_image = file_get_contents($user->image_path);

        //ローカルの画像フォルダまでのパスを指定し、そこにtweet.jpgという名前で先程読み込んだ画像をセット
        file_put_contents(public_path() . "/images/tweet.jpg", $post_image, FILE_APPEND);

        //画像をアップロード
        $user_image = $twitter->upload('media/upload', ['media' => public_path() . "/images/tweet.jpg"]);

        $twitter->post("statuses/update", [
            //ツイート本文
            "status" =>
                $user->name . PHP_EOL .
                $user->text . PHP_EOL .
                '#ハッシュタグも指定できる'. PHP_EOL,

            'media_ids' => implode(',', [
                $user_image->media_id_string
            ])
        ]);
    }

```
Webpack の Linux 最大監視数の問題

## 課題

`webpack` 使うと、ファイル数が多い場合、このようなエラーが出ます。

```sh
Error: ENOSPC: System limit for number of file watchers reached
```

## 解決策
環境変数を追加したら、解決します。

```sh
export CHOKIDAR_USEPOLLING=1
```
JSONを整形する Emacsパッケージ

WebAPIを利用していると、電文で利用しているJSONデータの構造を確認したいことが良くあります。
私のメインエディターのEmacsで便利なパッケージはないかなと、探したところ良さげなツール(json-refomat)がありましたので、紹介します。

## 前提条件
- Emacs 23以上

## 導入方法

1. パッケージを導入します
```M-x package-install RET json-reformat```

2. init.elを修正する
インストールした json-reformat パッケージを参照するように init.el に以下の行を追加します。
`(require 'json-reformat)`

## 使い方

変換する対象を選択して、以下のコマンドを入力する。
`M-x json-reformat-region`

### 変換前
```
{"name":"mkyong.com","messages":["msg 1","msg 2","msg 3"],"age":100}
```

### 変換後
```
{
    "age": 100,
    "messages": [
        "msg 1",
        "msg 2",
        "msg 3"
    ],
    "name": "mkyong.com"
}
```
AWS Client VPNの承認ルールに複数のADグループを設定する場合の注意点

AWSにはAWS Client VPNというマネージドのVPNサービスがあり、OpenVPN ベースのVPN クライアントを使用すれば、VPN接続を簡単に実施することができます。

その中で、Active Directory認証と相互認証（証明書）を使用して認証することができるのですが、
Active Directory認証を使用した際に通常のネットワークの使用とは異なる部分がありました。

#Active Directory認証をする際の注意点

※動作としては以下のトラブルシュート
https://docs.aws.amazon.com/ja_jp/vpn/latest/clientvpn-admin/troubleshooting.html#ad-group-auth-rules

例えば、ひとつのClientVPNにおなじディレクトリに所属する2つのADグループと承認ルールを設定していたとします。

|  ADグループ名  |  承認ルール |
| ---- | ---- |
|  test1  |  10.0.0.0/16  |
|  test2  |  10.0.0.0/16  |

上記のADグループ”test1”に"10.0.1.0/24"を追加したとします。

|  ADグループ名  |  承認ルール |
| ---- | ---- |
|  test1  |  10.0.0.0/16 |
|  test1  |  10.0.1.0/24 | 
|  test2  |  10.0.0.0/16 |

その場合、"test2"のADグループに含まれるユーザは10.0.0.0/16に含まれるはずの10.0.1.0/24にはアクセスできなくなります。
※test1のADグループに紐づいている10.0.1.0/24への承認ルールが先に評価されてしまって、test2のユーザがアクセスしようとする際は10.0.1.0/24への通信が拒否されてしまう仕様のようです。

なので、test2のADグループに所属するユーザが10.0.1.0/24にアクセスさせたい場合は以下のように設定する必要があります。

|  ADグループ名  |  承認ルール |
| ---- | ---- |
|  test1  |  10.0.0.0/16 |
|  test1  |  10.0.1.0/24 | 
|  test2  |  10.0.0.0/16 |
|  test2  |  10.0.1.0/24 |

#結論
ClientVPNに複数のADグループを設定する場合は、同じClientVPNに設定されているADグループに承認ルールの追加が通信に影響を及ぼさないかの確認が必要そうです。

細かく通信を制御させたい場合は、ClientVPNエンドポイントをユーザごとに分けることも検討したほうがよさそうです。
Winodowsメモ帳でGrepするbat(再アップ)

Windowsのメモ帳しか使えない環境で、log確認等をすることが多かったので
batファイルを作ってみた。

ほんとエディターツールってすばらしいよね。。。

#zipファイル
<p><a href="https://github.com/yyoshizu/Grepbat/releases/download/bat/Grep.zip"download="https://github.com/yyoshizu/Grepbat/releases/download/bat/Grep.zip">zipファイルをダウンロード</a></p>

#使い方
①Greplist.txtと本batファイル準備する。

②Greplist.txtへGrepしたいワードを入れる。

③①のファイルをGrepしたいファイルの階層に格納する。
　※サブフォルダにも対応しているので上位フォルダへ格納もOK

④Grep.batを実行する。
　※Grepしたいファイルの拡張子を入力する。
　　例：.txtの場合⇒txt　 .logの場合⇒log

⑤Grep結果のファイルがデスクトップへ出力される。
　


#出力イメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475419/0d7a7add-132f-9f3f-0779-9672e0192736.png)

※内容説明
　・starttime：実行した時間
　・Grep keyword：Greplistに記載している検索キーワード
　・該当のファイル名：行数：行内容
　・endtime：終了した時間




#ソースコード
```ruby:Grep.bat
echo off


rem ▼デスクトップへ[日付.log]でログの生成
set fname=%USERPROFILE%\Desktop\%date:~0,4%%date:~5,2%%date:~8,2%.log

:Start
set /p filetype="Grep対象ファイルの拡張子を入力して下さい[拡張子を入力]："

echo 対象拡張子：.%filetype% 
:Select
set /p Check="以上の設定でGrepを始めます。よろしいですか？...[Y/N] "

if /i %Check%==Y Goto:GREP
if /i %Check%==YES Goto:GREP
if /i %Check%==N Goto:Start
if /i %Check%==NO Goto:Start

:GREP
echo starttime %date% %time% >> %fname%
echo; >> %fname%
echo Grep keyword >> %fname%
findstr -g:Greplist.txt Greplist.txt >> %fname%
echo; >> %fname%
echo; >> %fname%
findstr -i -s -n  -g:Greplist.txt *.%filetype% >> %fname%
echo; >> %fname%
echo endtime %date% %time% >> %fname%
echo; >> %fname%
echo; >> %fname%
pause

```

#更新(2021/3/12)
拡張子設定後の確認ステップ追加[.拡張子]形式で表示。
出力結果の画像および内容について追記。
zip形式でダウンロード可能にしました。
raspberryPiとjulius（音声認識）を使用する。①マイク編

#関連記事
[raspberryPiとjulus（音声認識）を使用する。①マイク編](https://qiita.com/chiapis2/items/347a9b422706c2d8ebe2)
[raspberryPiでjulius（音声認識）を使用する。②インストール編](https://qiita.com/chiapis2/items/7ec1b0b21ee4fef4e8f0)
[raspberryPiとJulius(音声認識)を使用する。③辞書作成編](https://qiita.com/chiapis2/items/f0bd2ccb0f04d18d8a98)
[raspberryPiとJulius（音声認識）を使用する。④Lチカ編](https://qiita.com/chiapis2/items/a2ed64414c9e49b6cb42)
[raspberryPiとJulius（音声認識）を使用する。⑤i2cキャラクタディスプレイ編](https://qiita.com/chiapis2/items/8e02bb591fb7a02274aa)
<h1>使用するもの</h1>
Raspberry Pi 3 Model B+
USBマイク（サンワサプライ USBマイクロホン 単一指向性 直挿し型 MM-MCU02BK）

<h1>マイクの設定</h1>

ラズパイのUSBポートにマイクを接続し、マイクが認識されていることを確認する。

```
$lsusb
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504329/67f6fb5f-ad92-a39a-9f03-22407ecb1dd4.png)

一番上のC-Mediaがマイクで、認識されていることが分かる。

<h2>マイクの優先度を上げる</h2>
オーディオモジュールの優先度を確認する。

```
$ cat /proc/asound/modules
　0 snd_bcm2835
　1 snd_usb_audio
```
初めは０が内蔵オーディオモジュール、１がUSBマイクになっているので、優先度を書き換える。

```
$ sudo nano /etc/modprobe.d/alsa-base.conf
```
開いたエディタに次のコードを書き込む。

```
options snd slots=snd_audio,snd_bcm2835
options snd_usb_audio index=0
options snd_bcm2835 index=1
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504329/6eea896b-b6a9-7fc2-5296-dbbbf07f00bf.png)
ctrl+Xで終了し、再起動する。

```
$ reboot
```
起動したら再度優先度を確認し、０がUSBオーディオモジュール、１が内蔵オーディオモジュールになっていれば成功。

```
$lsusb
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504329/4c582344-b42b-7712-d5b2-64e8242ae385.png)


<h2>サウンドドライバのインストール</h2>
aptitudeをインストールしてからALSAのサウンドドライバをインストールする。raspberryPi3B+にはsnd-pcm-ossモジュールは入っていないらしい。

```
sudo apt-get install aptitude
sudo apt-get install osspd-alsa
sudo aptitude install libasound2-dev
```
マイクのサウンドカード番号を確認する。

```
$ arecord -l
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504329/8bd7d038-fd75-ebae-aca1-7e8c9d47e4a5.png)
常に同じ設定を使用できるように環境変数を設定する。

```
$ sudo nano ~/.profile
```

開いたエディタの一番上でも一番下でも、書いてあるコードを邪魔しない場所に次のコードを追加する。

```
export ALSADEV=hw:0,0
```

ctrl+Xで終了し、再起動する。

```
$ reboot
```

<h1>マイクの設定は完了</h1>
次はJuliusのインストール編へ
[raspberryPiでjulius（音声認識）を使用する。②インストール編](https://qiita.com/chiapis2/items/7ec1b0b21ee4fef4e8f0)


<h1>参考</h1>
[Raspberry pi3B+でjuliusを動かせるようになるまでの覚書き(2019.3.10現在)](https://qiita.com/todateman/items/9c0e291e7b378a3c559b)
[ラズパイ2日目①：ラズパイにマイクを接続する](https://kihara0223.hatenablog.com/entry/2020/01/02/140738)
Flask(クライアント)からHasuraにgraphqlクエリを投げる

インターン中なぜかハマってしまったので、今後みなさんがハマらないように書き留めておきます。

#結論
gqlを使いましょう。
https://pypi.org/project/gql/

#なぜハマったのか
ReactやVueだとapolloっていう超有名なqraphqlライブラリがあって、これで簡単にできる。
apolloはflaskでも使えるのかなーと思いきや、使えないみたい。
じゃあどうすればいいかって考えた時にエンドポイントわかってるてるし、普通にPOSTすればいいだろうと。
ただ、パラメーターの構造はどう書くんだ、、、
ということでドキュメントを漁ってみても全然書かれてない。
文字列にして渡してみてもうまくいかない。
結局gqlを見つけて彼に頼りました。

#クエリの参考
変数を使いたい場合には三つのポイントに注意

- .format()で変数を入れる
- 変数に使わない{}は{{}}二重にする
- 変数を""で囲ってあげる



```app.py
transport=RequestsHTTPTransport(
        url='http://localhost:8080/v1/graphql',
        use_json=True,
        headers={
            "Content-type": "application/json",
        },
    )
client = Client(transport=transport, fetch_schema_from_transport=True)
query = gql(
        """
            mutation insert_single_hoge {{
                insert_hoge_one(
                    object: {{
                        name: "{name}",
                        address: "{address}",
                    }}
                ) {{
                    id
                }}
            }}
        """.format(
                name=name,
                address=address
            )
)
result = client.execute(query)
```
PHPでもコンストラクタに限り、シグニチャーの違うオーバーライドができる！！

# タイトル変更しました
ご指摘いただき、勘違いが分かりましたので、タイトルを以下の通り変更させてもらいました。

**PHPでも他のオブジェクト指向で言うオーバーロードができる！！（ただしコンストラクに限る）**
↓
**PHPでもコンストラクタに限り、シグニチャーの違うオーバーライドができる！！**

# 概要
表題の通りですが、PHPでもコンストラクタに限り引数のシグニチャが異なるオーバーライド（他のオブジェクト指向で言うオーバーロード）ができるというのをマニュアルで確認したというだけのお話です。
PHPではオーバーロードができないという記事をよく見かけるのですが、コンストラクタだけは例外ということが明記されている記事を見かけなかったので（マニュアルにあるから当たり前！？）、残しておこうかと。

[2020-10-06追記]
ご指摘によりオーバーロードはできないことが分かりましたので、以下の記事は、「PHPでもコンストラクタに限り、シグニチャーの違うオーバーライドができる！！」という内容になります。
@error_401 さんありがとうございます！

# Manual
[PHP Manual(extends)](https://www.php.net/manual/ja/language.oop5.basic.php#language.oop5.basic.extends)

# サンプルコード
```<?php

class Base
{
        protected $a;
        public function __construct(int $a)
        {
                $this->a = $a;
        }

        public function test(string $a)
        {
                echo sprintf('class Base(%s)', $a) . PHP_EOL;
        }
}

class A extends Base
{
        protected $a;
        protected $b;
        public function __construct(string $a, int $b)
        {
                $this->a = $a;
                $this->b = $b;
                parent::__construct($b);
        }

        public function test(int $a)
        {
                echo sprintf('class A(%d)', $a) . PHP_EOL;
        }
}


$base = new Base(10);
$base->test(10);
$base->test('xxx');

$a = new A('aaa', 10);
$a->test(10);
//$a->test('xxx');
```
このコードを実行すると、以下のE_WARNINGレベルのエラーが発生しますが、コンストクタについては何もエラーが発生していないことから、コンストラクタのオーバーライドは例外で、正常にオーバーライド~~（オーバーロード）~~可能なことが分かります。

```
Warning: Declaration of A::test(int $a) should be compatible with Base::test(string $a) in /var/www/wonder/test_overload.php on line 32
```

# 更なる疑問
ここで気になるのが、コンストラクタ以外のメソッドもWARNINGなので、実行自体は止まらず、オーバーライドできているような挙動となることです。

```
//$a->test('xxx');
```
のコメントアウトを外すと、以下のエラーが発生することからもオーバーライドして、引数の型が変更できているように見えます。

```
Fatal error: Uncaught TypeError: Argument 1 passed to A::test() must be of the type int, string given, called in /var/www/wonder/test_overload.php on line 41 and defined in /var/www/wonder/test_overload.php on line 28
```

# まとめ
以上、新たな疑問は発生しましたが、マニュアル及びE_WARNINGレベルのエラーの発生より、

- PHPでは引数のシグニチャーが異なるオーバーライド~~（オーバーロード）~~は基本的に不可
- ただしコンストラクタのみオーバーライド~~（オーバーロード）~~可能

ということが分かりました。
ゲームを作りながら学ぶ！JavaScript レベルアップ講座 part2

こんにちは、[Yui](https://twitter.com/yui_active)です。

今回は[前回](https://qiita.com/Yui_active/items/473c1a02bc97ab50708b)に引き続き[JavaScript道場](https://x-hack.connpass.com/event/196255/?utm_campaign=event_publish_to_series_watcher&utm_source=notifications&utm_medium=email&utm_content=detail_btn)で学んだオブジェクト指向について解説をしていきます。

# オブジェクト指向とは

まずJavaScriptにおける「オブジェクト」は、```名前と値をもつプロパティを格納する入れ物```にすぎません。つまり、```オブジェクト＝データの入れ物```です。

それでは「オブジェクト指向」とは何かというと、簡単にいうと``` 「ソフトウェアで扱う事柄について、データと操作(メソッド)をまとめて１つのオブジェクトとして捉えること」 ```を指します。

(オブジェクト指向の説明には色々な切り口があリ専門家の間でも微妙に食い違いますが、ここは共通しているはずです)

例えば、AさんとBさんの「歯を磨く動作」をプログラミングするとして考えると、以下の動作はAさん、Bさん関係なく共通のものですよね。

* 歯ブラシを手に取る
* 歯磨き粉をつける
* 歯ブラシを口に入れる
* 歯ブラシを口の中で動かす
* 歯ブラシを口から出す
* うがいをする

JavaScriptで言うなら一つ一つの動作は```関数```として表すことができますが、共通で使う関数が複数あるならまとめておいたほうが楽ですよね。

それをまとめて書けるというのが「オブジェクト指向プログラミング」の一つの利点です。コードを共通化することで、同じようなコードを何度も書く必要がなくなります。

注意点としては、**同じコードだからといって何でも共通化すれば良いというわけではない**ので、そこは気をつけてください。

# 実際にオブジェクト指向プログラミングで書いてみよう

それでは実際にオブジェクト指向で書いてみましょう。（コードは[MDN](https://developer.mozilla.org/ja/docs/Learn/JavaScript/Objects/Object-oriented_JS)からの引用です）

例えばAとBの人物を用意して、```Hi! I'm 〇〇.```とアラートを出すだけの簡単なプログラムを書いてみます。

```js
var personA = {
  name: 'Bob',
  greeting: function() {
    alert('Hi! I\'m ' + this.name + '.');
  }
}

var personB = {
  name: 'Sarah',
  greeting: function() {
    alert('Hi! I\'m ' + this.name + '.');
  }
}

```
この状態で```personA.greeting()```と入力すれば、```Hi! I'm Bob.```というアラートが出るという簡単なプログラムです。

ただ、これ2人だけならこのままでも良いかもしれませんが、100人、200人となると毎回この共通の部分をコピペするのはあまり好ましくないですよね。

そこで共通の部分を**オブジェクト指向**で書いてみます。

```js

function Person(name) {
  this.name = name;
  this.greeting = function() {
    alert('Hi! I\'m ' + this.name + '.');
  };
}

let personA = new Person('Bob');
let personB = new Person('Sarah');
```

上記のように簡単に書くことができました。それぞれの`greeting`メソッドは、自分自身の`name`プロパティを内部で使っています。

このようにすることで今後人物を追加する際は`let 〇〇 = new Person('name')`とすれば良いだけなので非常に簡単ですね。

ちなみに今回は簡単な例だったのですが、これから作るゲームではオブジェクト指向で書かないとコードがかなり冗長になってしまいます。小規模なコードだとイマイチ便利さが伝わりづらいですが、今後より実践的なプログラミングを学んでいけば、よりオブジェクト指向の便利さを理解できるかと思います。

また、今回さらっと書いた上記のコードに中に```this```がありますが、これがわからない人も多いのではないでしょうか？
thisは慣れれば感覚的に使えるのですが、JavaScriptで書く上では欠かせないものになるので、次回はthisとは何かについて解説をしていきたいと思います。

最後までお読みいただきありがとうございました。
【laravel-admin】【controller】javascript

##laravel-adminのController側でjavascriptを使う

ちょっとしたjavascriptのためにいちいちファイルを作って、とかviewを変更して、とかが大変な時は以下の方法でcontroller側にjavascriptを書いてページに埋め込むことができます。
viewの一部を変更したいけどviewには手を加えたくない...という場合などに便利です。


```SampleController.php
use Encore\Admin\Admin;

class SampleController extends AdminController
{
    /**
     * sample
     */
    public function sample(Content $content)
    {
        $script = <<<SCRIPT
$('.breadcrumb li:first').remove();
$('.breadcrumb .active').html('<i class="fa fa-home"></i>メニュー');
$('.navbar-custom-menu').find('.pull-left').html('');
$('.main-footer').find('strong').html('');
SCRIPT;
        Admin::script($script);
        Admin::style('.form-control {margin-top: 10px;}');
        return $content
        ->title('メニュー')
        ->description('メニューです。')
　　　　　->row('メニュー1')
        ->row('メニュー2')
        ->row('メニュー3');
    }
}
```

1行目→パンくずリストの1つ目を削除
2行目→自身がいる位置を現在地として表示
3行目→ユーザー設定のボタンを削除
4行目→フッターの文字を削除
こっちはcss→`Admin::style('.form-control {margin-top: 10px;}');`

参考：[Laravel admin | CSS / JavaScript](https://laravel-admin.org/docs/en/frontend)
unityのARFoundationでアプリ作ったのに、実機だとカメラが真っ黒になってしまう時の改善策

unityのARFoundationでARのアプリをエラーなく作ったのに、iosやAndroidで実機で立ち上げると、カメラが真っ黒で映らない！！時の改善方法をご紹介します。

#改善策
* **「camera usage description」** を設定していない

Edit→project settings→Player→iosまたはAndroidを選択(実機の環境)
→camera usage descriptionの欄に

**Camera required for AR**

というように記入してビルド
iosの場合はこれでXcodeの内のinfo.plistにPrivacy - Camera Usage Description が自動的にセットされます。

![スクリーンショット 2020-10-06 17.02.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704869/13c3af7c-d20f-e92b-f345-dde814670140.png)



* **XR Plug-in Management の Plug-in Providers を設定(私はこれで解決)**

Edit→project settings→XR Plug-in Management→iosまたはAndroidを選択(実機の環境)→ARKitまたはARCoreにチェックを入れる。

![スクリーンショット 2020-10-06 17.01.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704869/682c996b-1322-fd73-880d-d41e44f3efe1.png)

[XR Plug-in Management](https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@4.0/manual/index.html)はこちらに記載があります。


* **バージョンを最新版にアップデート**

Unity、ARFoundation,ios,Android,xcode,ARKit,ARCoreなどなどアップデート
ちなみXcodeのアップデートは容量と時間が必要なのでご注意を笑

#どこにもエラーがないのに、、
全て設定したのにカメラが動かないとなると、解決策はここら辺だと思います。
ARにおいてカメラはマストなので、しっかりと解決して実機で確認できらいいですね。
RDS（Postgres）からデータをdumpしてローカルDBに投入する

# 環境

- RDS Postgres
- Amazon Linux 2（※dumpを取得する環境として）

# 手順

※ `pg_dump:aborting because of server version mismatch` というエラーが出た場合は、後述の手順を実施。

### dump の取得

以下をサーバ（ここでは Amazon Linux 2 を想定）にログインして実行。

```
$ /usr/pgsql-9.6/bin/pg_dump -U <user> -h <db_url> -p 5432 <db_name> -f <dump_file>

// 以下、例。
$ /usr/pgsql-9.6/bin/pg_dump -U root -h foo.cbvedzbhutma.ap-northeast-1.rds.amazonaws.com -p 5432 your_db_name_comes_here -f foo_dump.sql
```

### scp でローカルにコピー

以下をローカルホストで実行。
作業後不要になった dump ファイルは適時削除する。

```
scp -i ~/.ssh/xxx <user>@<server_address>:<path_to_dump_file> <path_to_dump_file_on_local>
```

### ローカルDB にデータを投入する

```
psql -U <user> -h localhost -d <db_name> -p 5432 -f <path_to_dump_file_on_local>
```

# トラブルシューティング

### pg_dump:aborting because of server version mismatch が出た場合

※バージョン 9.6 用ですが、他のバージョン用に適時読み替えてください。

```
$ sudo yum install https://download.postgresql.org/pub/repos/yum/9.6/redhat/rhel-7-x86_64/postgresql96-libs-9.6.12-1PGDG.rhel7.x86_64.rpm

$ sudo yum install https://download.postgresql.org/pub/repos/yum/9.6/redhat/rhel-7-x86_64/postgresql96-9.6.12-1PGDG.rhel7.x86_64.rpm
```
LaravelからVueコンポーネントへのデータ受け渡し

Laravelで作成したアプリのデータを非同期通信したいと思って、Vueを使い始めた。
なかなか、理解が悪く先にすすんでいないが、とりあえずいつものごとく備忘録を書いていく。

### やりたいこと
初期のみDBにあるデータをLaravelで静的に受け取って、
その後はVueで作成したコンポーネントを使用しながら、非同期通信でデータを操作する。

### 詰まった箇所
Laravelでデータの処理してから、どのようにして、Vueコンポーネントに渡していいかわからなかった。
Vueコンポーネント同士の親子でのデータ受け渡しについては記事をよく見かけたが、ララベルとVue間でのデータ受け渡しについては、調べてもよくわからなかった。理解が悪いだけかもしれないが。。。

### 結論
色々やってみて、以下の通りでうまく行った。

1. Laravelのコントローラで、app.jsが読まれているBladeテンプレート（これが親となる）へDBからデータ値を送る。
2. 上記Bladeテンプレート内の、Bodyタグ内の最下部にscriptタグを配置。その中に、コントローラから送られたDB値を格納する。例えば、DBから$data_hogeを受け取っているとしたら、`<script>let dataHoge = @json($data_hoge)</script>`と書く。@jsonとしているのはphpのデータをjson形式にしないと、vueで使えないので。
3. app.jsの、Vueインスタンスの中に、dataオプションを記述し、データを受け取る。
4. app.jsが読まれたBlade内で使われるVueコンポーネントは、子コンポーネント（Blade-app.jsが親）になる。Blade内に書いた、Vueコンポーネントタグ内に、v-bind:オプション値として、子コンポーネントに渡す準備をする。そして、子コンポーネント内では、それをpropsで受ける。子コンポーネント内でデータを動的に変更するには、dataプロパティにつけ直して、自由に使う（propsはそのまま使ってはいけない）。
4. 子コンポーネントから、親（Blade）に値を返したいときは、$emitでイベント発火して、値を受け取る。


考え方は、LaravelBlade-app.jsが親、Bladeに書かれたコンポーネントが子になる。
文章にしてみると、単にVueやJavaScriptの理解が浅いだけな気がしてきた。

後で、もうちょっと加筆するかも。
Scssでリファクタリングやメンテナンス性を意識した記述

CSSのアニメーションを学んでいる中で、Scssの記述方法についてリファクタリングやメンテナンス性を意識して書く際に、色々と便利だなぁと思ったことがあったので自分の備忘録も含めて記事を書きました。

### よく使うカラーの値などを変数化

```scss
$spColor: rgb(0,0,0);
//$の後に名前を付けて、変数化

.sample-div {
    background-color: $spColor;
    //上で設定した rgb(0,0,0)が、background-colorに適用される
}
```

例えばボタンなど、各ページで共通して使う色を変数化せずにScss内で書いてしまうと、もし色を変えたくなった場合に全てを一個一個変えていかなければいけません。
しかし、変数化しておくことで $spColor の値を変更するだけで変数が記述されている箇所全てに適用させることができます。
共通して使う値は変数化しておくことで、コードが読みやすくなりますしメンテナンス性も上がります。

### ネストさせて書く場合に親要素の名前を & で置き換えられる

```scss
$spColor: rgb(0,0,0);

.parent {
    position: relative;
    background-color: $spColor;

    & .child {
        position: absolute;
    }

}
```

これを、コンパイルすると

```css
.parent {
  position: relative;
  background-color: black;
}

.parent .child {
  position: absolute;
}
```
上記を見ると、`&`で記述した部分が親要素(.parent)に変化してコンパイルされています。
ネストして記述する場合には、`&`を用いることで読みやすく、かついちいち書く手間が減ります。

### 他のクラスと同じ内容を1行で適用できる
既に他のクラスで記述した内容をもう一度使いたい場合は`@extend`を用いることで適用できます。

```scss

.bg-img {
    background-image: url(images/image-1.jpg);
    background-repeat: no-repeat;
    background-position: center;
    background-size: cover;
}


.copy-img {
    @extend .bg-img;
}
```
仮に、`.bg-img`の内容を`.copy-img`にそのまま適用させたい場合は`@extend`にクラス名を記述することで適用できます。


### Scssでfor文が使える
同じ処理を連続する要素に対して繰り返し行う場合に、Scssでもfor文が使えます。

```scss

@for $i from 1 through 9 {
    &:nth-child(#{$i}) {
        animation-delay: $i * 0.04s;
    }
}
```
書き方としては、`@for` の後に
`$i` : 繰り返しのカウンタが入ります。 (上記の例:1, 2, 3...9)
`from` : カウンタをスタートさせる数字を指定します。
`through`: カウンタを終了させる数字を指定します。

`through`ですが、`to`も同様に使えます。
しかし、それぞれに違いがあり
`through`は指定した数字を含んだ回数で繰り返し処理を行いますので
上記の場合は、1から9までの合計9回の処理となりますが
`to`の場合は指定した数字を繰り返し処理の回数に含みません。

```scss

@for $i from 1 to 9 {
    &:nth-child(#{$i}) {
        animation-delay: $i * 0.04s;
    }
}
```

なので、上記のように`to`を記述した場合は1から8までの合計8回の処理実行となります。


### eachを使って条件に合わせた処理を実行できる
クラス名に合わせた処理を実行したい場合などに使えます。

書き方は`@each`の後に `$key, $value in $pattern`と記述します。
そして、`$pattern`の中にキーとバリュー値を組み合わせて記述することで条件に合わせた処理が実行できます。

```html
<div class="sample up"></div>
```
↑HTML

```scss

$pattern:(
    "up": translateY(6px),
    "down": translateY(-6px),
    "left": translateX(40px),
    "right": translateX(-40px),);
    // $key: $value となる

@each $key,$value in $pattern {
    .sample.#{$key} {
        & .item {
            transform: $value;
        }
    }
}
```
↑scss

上記の例でいきますと、HTML側で`sample`と`up`がマルチクラスで記述されていた場合
一番上の`$pattern`にある1つ目の`$key`である`up`のvalue値`translateY(6px)`
が
`@each`処理内の下から4行目`transform: $value`に適用される流れとなっています。

### 終わりに
Ruby on RailsでWebアプリケーションを製作したのですが、画面に動きがないフロントエンドだったためユーザーを楽しませられるアニメーションなどを実装できるようにCSSを再度勉強したところScssの記述方法で勉強になるところがありましたので今回、記事を書かせて頂きました。
初めての記事投稿なので、読みにくい点や間違っている点などございましたらコメントにて教えて頂けると幸いです。