OmniAICreator/Qiita-1.07M huggingface dataset:
Pandasによるデータ処理Tips

個人的忘備録も兼ね、Pandasによるデータ処理のTipsです。
ググっても引っかからなかったものを書き留めています。
どんどん追加していく予定です。
間違いや改善点等ありましたらお知らせいただけますと幸いです。

##まず見るべきはチートシート
和訳してくださった方に圧倒的感謝。
https://qiita.com/s_katagiri/items/4cd7dee37aae7a1e1fc0

##複数の変数に関数を適用し、返り値を別の変数に保存する。
例: x1の中に含まれる「＠」の個数をcnt_x1に入れる、というのをx2,x3,...についても行う。
x1→cnt_x1, ..., x13→cnt_x13


```python
migs = {'cnt_x1': 'x1', 'cnt_x2': 'x2', ...,  'cnt_x13': 'x13'}

for vars, mig in migs.items():
    df1[vars] = df1[mig].str.count('＠')
```

- keys(): 各要素のキーkeyに対してforループ処理
- values(): 各要素の値valueに対してforループ処理
- items(): 各要素のキーkeyと値valueに対してforループ処理

辞書を使用する。辞書のkeyとvalueの対応は以下のとおりである。
 {'key1': 'value1', 'key2': 'value2', 'key3': 'value3'}

##データフレームの列に対して1対1の変換を施す

```python
def income(x):
    if x == 1:
        return 100
    elif x == 2:
        return 300
    elif x == 3:
        return 500

df['x1'] = df['x1'].apply(income)

```

# 全カラムに対して関数適用
```python

for col in df:
    df.loc[:, col] = df.loc[:, col].apply(lambda x: 1 if x == 1 else 0) 
```



##postgresにクエリを投げてデータフレーム化（ヘッダも取得）旧

cur.execute()の中に'''で囲んだクエリを記述。
個人的には（Postgresの際は）PgAdminで動きを確かめてから記述。

```python
import psycopg2
import pandas as pd
conn = psycopg2.connect("host=hostname  user=username port=port dbname=dbname password=password")
# execute sql
cur = conn.cursor()
#スキーマ名.テーブル名
cur.execute('''
select *
from hoge
;''')
results = cur.fetchall()
#dfにしたい
df = pd.DataFrame(results, columns=[col.name for col in cur.description])
cur.close()
conn.close()
``` 

##postgresにクエリを投げてデータフレーム化（ヘッダも取得）新

withを使うとSQL実行中にエラー等起きても
データベースが固まったままにならない。

```python
import psycopg2
import pandas as pd
import pandas.io.sql as psql

def get_connection(server, db):
	return psycopg2.connect(host=server, port=5432, database=db, user="user", password='pass')

with get_connection(dbname, db) as conn:
	df = psql.read_sql(sql, conn)

``` 

##PostgreSQLにinsertする
conn.autocommit = True
が必要

```python
with get_connection() as conn:
    conn.autocommit = True
    with conn.cursor() as cur:
        cur.execute('INSERT INTO users (name) VALUES (%s)', ('foo',))
```



##空のファイルを作り、ファイル名に現段階のサンプル数を書き出して状況を把握する方法

上のpostgresにクエリを投げ、データフレーム化をするプログラムと組み合わせ、Windowsのタスクスケジューラで定期実行されるようにすると、毎日（毎週、毎時間など好きなスパン）のデータベース内のサンプルの状況を把握することができる。

```python
allcnt = len(df)

with open(r"./日付" + str(date) +  r"_計_" + str(allcnt) + r"_国内_" + str(domestic) + r"_海外_" + str(foreign) + r".txt","w"):pass
```

##id一覧のエクセルファイルを読み込んで、sqlのwhere句で操作する

```python

# shift-jis のCSVファイル
with open(in_file, 'r', encoding='CP932', errors='ignore') as csv_file:
# 行毎に読込
    for row in csv.reader(csv_file):
        id_list.append(row[1])


del id_list[0]
id_str = "'" + "','".join(id_list) + "'"

###pandasで作成
import pandas as pd
df = pd.read_excel(output_path + r'\\ID一覧.xlsx',dtype=object).dropna(subset = ['x1'])
id_list = []
id_list = df.x1.tolist()
id_str = "'" + "','".join(id_list) + "'"

sql = """
select * from hoge
where id in (
{0}
);
""".format(id_str)

#以下でpsycopg2で実行

```

##参考にさせていただいたページ
https://qiita.com/hoto17296/items/0ca1569d6fa54c7c4732
https://qiita.com/stokes/items/157f7ab737c5ded26832
https://qiita.com/knoguchi/items/3d5631505b3f08fa37cc
firebase hostingでアクセスログを確認する(Cloud Logging)

# 概要
firebase hostingのアクセスログがCloud Loggingを導入することで簡単に確認できるようになりました。
(しかもボタンポチポチするだけで簡単！！)

ひっそりと統合メニューに追加されており、気づいていない人もいると思うので共有です。


# できること

公式より
https://firebase.google.com/docs/hosting/web-request-logs-and-metrics

『FirebaseプロジェクトをCloud Loggingにリンクして、ホスティングサイトごとにウェブリクエストログを表示、検索、フィルタリングできます。これらのログは、Firebaseによって自動的に提供されるCDNからのものであるため、サイトへのすべてのリクエストと関連するリクエストデータがログに記録されます。』

ユーザエージェントやIP、http staus、CDNキャッシュhit、レスポンスタイム、リファラなどを確認できるようです。

# 導入手順
1. Hosting設定もしくはプロジェクト設定→「統合」からCloud Logginを見つけてポチポチ進めます
![スクリーンショット 2020-08-14 2.28.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263190/6102144d-ff25-c694-d039-7555b27849a7.png)
![スクリーンショット 2020-08-14 2.31.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263190/9fcbd53d-e335-1d1d-0223-f0d2fb0fb822.png)
![スクリーンショット 2020-08-14 2.32.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263190/71b21401-663f-a79a-e42d-e993c95bc5db.png)
![スクリーンショット 2020-08-14 2.32.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263190/63ea4181-7ebe-d1b1-17bc-3815778f647b.png)
![スクリーンショット 2020-08-14 2.32.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263190/56b3df68-6d25-0715-2c75-ef9198ae75f8.png)

2. 設定完了したら「Cloud Logginで表示」からconsoleへ飛びます
![スクリーンショット 2020-08-15 13.24.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263190/33264019-d1ac-03ef-ca95-67cec135690b.png)

3. consoleでアクセスログを確認することができます
![スクリーンショット 2020-08-15 13.39.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263190/1655199a-829a-b3f1-4265-58e937205034.png)

(`/wp-login.php`へのアクセスログがありますねぇ、、、)


# まとめ
firebase hostingでも簡単にアクセスログが取れるようになりました。
googleアナリティクスは入れているものの、アプリまで到達していないアクセスログは見れないものか、と気になっていました。

月50GBまでの転送量までは無料のようなので、とりあえず試してみてはいかがでしょうか。
Wordpressの画像をS3に移行する

この記事でできること

* Wordpressにアップロードしている画像をすべてS3に移行する
* 記事内の画像URLをS3に置き換える
* 今後アップロードする画像のパスをS3にする

この記事でできないこと

* メディアライブラリ内に表示される画像パスをS3に変更すること
* CDN配信

## Wordpressにアップロードしている画像をすべてS3に移行する

[こちらの記事](https://www.momosiri.info/wppi/export-media-library/)を参考に、Export Media Libraryというプラグインをインストールし、画像のZipファイルをダウンロードします。

ダウンロードしたZipファイルを解凍し、フォルダ名を「uploads」に変更します。

s3にアクセスし、「ドメイン名」のバケットを作成します。(例:qiita.com)

バケットの中に、「wp-content」というフォルダを作成します。

wp-contentフォルダに、先程ダウンロードした、「uploads」フォルダをアップロードします。この時、権限はパブリックにします。

これで、画像の移行は完了です。

## 記事内の画像URLをS3に置き換える

[こちらの記事](https://www.adminweb.jp/wordpress-plugin/operation/index27.html)を参考に、「Search regex」というプラグインをインストールします。

検索フォームに「https://ドメイン名(qiita.com)/wp-content/uploads」と入力し、置換フォームに「https://qiita.s3.ap-northeast-1.amazonaws.com/wp-content/uploads/」と入力します。(リージョンによってS3のURLが変わるので、S3上で画像を開いてみて、URLを確認してください。)

実行すると、記事やその他コンテンツのURLが一気に入れ替わります。

一括変更が怖い人は、試しに1つの記事内の画像のURLを手動で変更してみましょう。また、バックアップも取っておきましょう。

## 今後アップロードする画像のパスをS3にする

[こちらの記事](https://blog.yuichisato.net/wp-images-fast-with-aws-s3-cloudfront-wp-offload/)を参考に、「WP Offload Media Lite」をインストールします。

AWSでユーザを作り、アクセスキーを取得して、WP Offload Media Liteに登録すれば、今後アップロードされる画像がS3に保存されるようになります。

## できないことも不可能ではないはず

この記事では以下の2つのことはできないのですが、面倒でやってないだけなので、調べてみてください。

* メディアライブラリ内に表示される画像パスをS3に変更すること
* CDN配信

## 今後やりたいこと

* Wordpressの移行

画像をS3から配信するので、Wordpressの移行がやりやすくなりました。

wordpress to wordpressでもいいですし、静的サイトジェネレータへの移行も簡単です。

S3から配信すると、その分課金されますが、静的サイトジェネレータに移行して、レンタルサーバやEC2を止めれば実質安くなります。
Django Rest Frakework環境でAPIを作る時に入れておいたほうが良いライブラリ・vscode拡張等(初心者向け)

## 前提条件
python3前提

## 対象
フロントエンドがメインだけどDjango Rest FrameworkでなんとなくAPIを作ってみたい人
今までDjangoメインだったけどDjango Rest Frameworkに手を出したい人
Django Rest Framework環境で他の人がどんなライブラリを作っているか知りたい人

## PyPIライブラリ
### 優先度A ( 使わないとDXが大きく落ちる )
**flake8**
linter+formatterないと死ぬ

**autopep8**
pep8基準のオートフォマッターないと死ぬ

**drf-yasg**
Django Rest Frameworkで使っているシリアライザのリクエスト/レスポンスを元に
swaggerを自動生成するライブラリ。
必須。ドキュメントもしっかり読んでおいたほうがいい。
django-rest-swaggerは更新がされていないためこちらを推奨。
https://github.com/axnsan12/drf-yasg

**djangorestframework-camel-case**
スネークケースをAPI生成時にキャメルケースにしてくれるライブラリ。
フロントエンドでは通常キャメルケースを利用するので必須。

**FactoryBoy**
ランダムテストデータを作成するライブラリ。
テスト時に多用する。
必須。

**django-cors-headers**
CORS管理を簡単にしてくれるライブラリ。
必須。

**django-import-export**
管理画面上からCSV等の形式でデータのインポート/エクスポートが行えるようになる。

### 優先度B ( 環境によっては使ったほうがいい )
**django-admin-sortable**
管理画面上でモデルのソートができるようになるライブラリ

**django-ses**
DjangoでAmazon SESを簡単に送るためのライブラリ

**boto3**
AWS用SDK特にS3利用時に多用する

## 優先度C ( 好み )
**django-jet**
管理画面の見栄えを良くしてくれる。

# VSCode拡張
### 優先度A ( 使わないとDXが大きく落ちる )
**Python**
https://github.com/Microsoft/vscode-python
これがないと始まらない

### 優先度B ( 環境によっては使ったほうがいい )
**TabNine**
機械学習による補完ツール。
他の言語でも利用していますがPythonは特に相性が良いと思います。
herokuで使用頻度が多かったコマンド集


herokuは、無料でアプリを本番環境にデプロイできるツールです。
かなり手軽にデプロイできるので、AWSでデプロイを経験した後だと拍子抜けするかもしれません。

一方で、無料で使えるが故の注意点もあり、herokuでデプロイしたアプリは一定時間で停止します。その場合は再度アプリを使えば起動しますが、しばらく起動に時間がかかる点が注意です。

例えばLINE BOTをherokuでデプロイした場合、文章を送信してLineから最初の返信が来るまでに暫くタイムラグがあります。
体感としては大体20秒〜30秒くらいでした。

前置きが長くなりましたが、そんなherokuとデプロイを巡って頻繁に使用したコマンドが多々あるので、備忘録の意味を兼ねて下記に記載していきます。

※尚、herokuの環境構築は済んでいる前提です。それについては割愛します。
　間違い等ありましたらご指摘頂けると幸いです。

# ①herokuにログインする
```
$ heroku login
```
文字通りherokuサイトにログインするコマンドです。
ターミナルに入力後、エンターキーで実行します。
コマンドを入力すると下記が表示されるので、もう一回エンターキーを押します

```
heroku: Press any key to open up the browser to login or q to exit:
```

するとネットに繋がり画面が自動で表示されます。
![heroku1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638561/d36188db-2572-9d8b-2f8b-321eadad3888.png)
Log inの文字を押すとherokuサイトへのログインが完了し、その旨がターミナルにも記載されます。

### https://id.heroku.com/login
若しくは上記URLから直にログインも可能です。

# ②herokuにデプロイする
まずはheroku上にアプリを作成する為に下記コマンドを実行します。

```
$ heroku create <アプリ名>
```
上記コマンドを打つだけでheroku状にアプリが作成できます。
<>で囲んでいるアプリ名は任意で決めましょう。
※<>部分は入力する必要はありません。

以降はherokuサイト上でもアプリの管理が可能になります。

アプリ作成が完了したら、次がデプロイです。
下記３つのコマンドを順々に入力していく事でデプロイが完了します。
デプロイは多少時間がかかるので、お待ちください。
※railsユーザーとして記載しているので、各言語によっても違いはあるようです。

```
$ git add .
$ git commit -m "initial commit"
$ git push heroku master
```

これでデプロイが完了しました。

# ③ログの一覧表示
個人的に一番便利だと感じたコマンドです。

エラー原因を探る事や、herokuがどんな挙動をしているかがターミナルで一覧表示が可能です。
時間も表示されるので、いつ何が起きたかも分かります。

```
$ heroku logs
```

困った場合に使うと良いでしょう。

# ④環境変数を設定する場合
環境変数は外部に漏洩すると不味いトークンなどを厳重に管理する為に設定します。
下記はLINE BOTの環境変数を設定した場合の想定です。

私はcontorollerファイルに記載されている文言と入力コマンドを打ち間違えて、トークンが取得できないエラーにハマりました。

なので、スペルミスや記述ミスには十分注意しましょう。
エラーに沼った場合は、上記のheroku logsで原因を探しましょう。

```
$ heroku config:set LINE_BOT_CHANNEL_SECRET="[LINEのチャンネルシークレット]"
$ heroku config:set LINE_BOT_CHANNEL_TOKEN="[LINEのアクセストークン]"
```
環境変数は作成するものによって必要・不要があると思うので、適宜設定をして下さい。

# ⑤アプリの停止&再起動
作ったアプリの挙動がおかしい等の不調が起きた時に使うコマンドです。


####アプリの停止
```
$ heroku ps:scale web=1 
```
####アプリの再起動
```
$ heroku ps
```

# ⑥アプリの削除
不要なアプリはherokuサイト上から削除が可能です。
しかし、それだけだとgitのリモートには残ったままなので削除の作業としては不十分です。
その為、ターミナルから専用コマンドを入力してまとめて削除してしまうのが確実です。

```
$ heroku apps:destroy --app <アプリ名>
```
コマンドを入力したら、確認のためにもう一度アプリ名の入力を求められるので、改めてアプリ名を入力して処理を続行すればアプリの削除が完了です。
このコマンドを使えば、Heroku上のアプリもリモートリポジトリもまとめて削除が可能です。


### これ以外にもコマンドは当然存在していますが、今回の内容はログイン〜アプリ作成〜デプロイ〜削除に至る過程で使用する頻度が多かったコマンド達でした。
RHEL 8 での nginx のインストール


# 1.インストール環境

RHEL 8.2 を使用しました。
nginx 自体は、感覚的になんなくうろ覚えで導入できますが、1年ぶりくらいにやると周辺コマンドや、firewall の部分など忘れがちになるのでメモ書きです。

```
# cat /etc/redhat-release 
Red Hat Enterprise Linux release 8.2 (Ootpa)
#
```

# 2.hostname の設定

```
# ホスト名の設定
$ hostnamectl set-hostname myhost.example.com

# 設定の確認
$ hostnamectl status
```


# 3.nginx のインストール

```
$ yum install -y nginx  
```
もしくは yum のフォーク版であり後継である dnf を使って

```
$ dnf install -y nginx  
```


# 4.nginx の基本コマンド

systemctl で操作できます。
作業時のコピペ用に基本的なコマンドをリストしておきます。

```
# 起動
$ systemctl start nginx  

# 停止
$ systemctl stop nginx  

# 再起動
$ systemctl restart nginx  

# 状況を確認
$ systemctl status nginx  

# 自動起動を設定
$ systemctl enable nginx   

# 自動起動を解除
$ systemctl disable nginx   

# 自動起動設定確認
$ systemctl list-unit-files -t service | grep nginx
```

# 5.nginx の起動

yum でインストールしただけで、nginx はデフォルトページを使って起動できます。

```
# nginx の 起動
 systemctl start nginx  
```

これで後は、http://<ホスト名>/ 
にアクセスすれば稼働が確認出来ます。

```
# アクセスを確認
 $ curl -s http://localhost  | grep Welcome

Memo: 
-s で、silent モードにして、HTTP response だけの出力にして転送情報等を出さないように
grep Welcome で、Welcome の HTMLソース部分だけを表示（動いている事を確認できればいいので）
```

ただし、デフォルトのRHELの設定では Firewallに阻まれて、サーバー外からはページを見る事はできないはずです。


# 6.Firewall のポート開け
RHELのデフォルトの設定では Firewalld が稼働していて nginx の使用する 80/443 も閉じているため Firewallのポートを空けてあげる必要があります。

## 6.1.現在の設定の確認
現在の設定を確認します。

RHEL8を入れたばかりの素の状態であれば、ここは読み飛ばして「http/httpsの穴を開ける」に飛んでも大丈夫です。
Firewallの設定は、NIC(Network Interface Card) 毎に「Zone」というグループを作って管理されています。

```
# NIC 毎に割り当てられている firewall の Zone を確認する。 
$ firewall-cmd --get-active-zones
libvirt
  interfaces: virbr0     # これはdefault で動いている仮想 NIC。今回は関係無い。
public
  interfaces: ens192    # こちらが外に向かって生えている NIC. "public" という zone 名が割り当てられている事がわかる。

Memo:
NIC が2枚ある場合は、デフォルトでは両方とも public の zone に設定されていた。
```

とりあえず、設定が必要なのは「public」のゾーンであると記憶します。
次は「public」に設定されている「サービス」を確認します。

```
# public の firewall の service を確認する。
$ firewall-cmd --list-services --zone=public
cockpit dhcpv6-client ssh   # 「cockpit」「dhcpv6-client」「ssh」3つのサービスが登録されている。
```
見た目から何となく HTTP/HTTPS が Firewalld のルールに登録されてない事が感じられます。
http と https というサービス（事前定義されている名前が存在しています）を追加します。

## 6.2.http / https の穴を開ける

Firewall に http と https の穴を開けます。

```
# http と https を Firewalld に追加する
$ firewall-cmd  --add-service=http --zone=public 
$ firewall-cmd  --add-service=https --zone=public 

Memo:
-zone を指定しない場合は、[firewall-cmd --get-default-zone]で返ってくる default の zone に設定される。
 
# 新しい設定を永続化させます。
$ firewall-cmd --runtime-to-permanent
success
```
動画と画像投稿テスト

![スクリーンショット 2020-08-08 10.46.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/231044/c4da4d67-792e-c036-0de4-8179f5b1ba74.png)
<iframe width="560" height="315" src="https://www.youtube.com/embed/tDXy3S9vZU8" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
初めてVue.jsでプロジェクトを作る

# やり方

天才的な記事があるので [【Vue.js】爆速でSPAを作る](https://qiita.com/nagimaruxxx/items/8fc59a5ca05bb91bfe1f) 全部これにそってやるだけ

# 開発環境

- macOS Catalina Version 10.15.4
- Nodejs v14.7.0
- npm 6.14.7

# 各種インストール

```
curl -L git.io/nodebrew | perl - setup
nodebrew install latest

nodebrew use latest
node -v
v14.7.0

npm -v
6.14.7

npm install -g vue-cli
```

# プロジェクト作成

```bash
vue init webpack single_page_application

? Project name single_page_application
? Project description A Vue.js project
? Author masatonaka <masatonaka1989@gmail.com>
? Vue build standalone
? Install vue-router? Yes
? Use ESLint to lint your code? Yes
? Pick an ESLint preset Standard
? Set up unit tests Yes
? Pick a test runner jest
? Setup e2e tests with Nightwatch? Yes
? Should we run `npm install` for you after the project has been created? (recommended) n
pm

   vue-cli · Generated "single_page_application".
...
# Project initialization finished!
# ========================

To get started:

  cd single_page_application
  npm run dev

Documentation can be found at https://vuejs-templates.github.io/webpack
```

できた!!

Run

```
npm run dev
...
Your application is running here: http://localhost:8080
```
[Android、Java]２つの日付から経過年月日を求めるメソッド

#やりたいこと
２つの日付から経過年月日（〇年〇ヵ月〇日という具合）を求める。
例
　2020/08/01と2020/08/03　→　0年0ヵ月2日
　2020/08/01と2020/09/01　→　0年1ヵ月0日
　2020/08/01と2021/08/01　→　1年0ヵ月0日

---
#仕様
・From日付 > To日付はエラー（エラーコード：-1）を返す
・日付の書式は　yyyy/MM/dd のみ
・From日付、To日付はともにString型
・年、月、日はint[]で返却（0：年、1：月、2：日）

---
#実装
```Java
    public static int getDateDiff(String paraFromDate, String paraToDate, int[] paraDiffDay) {
        int     diffYear = 0 ;
        int     diffMonth = 0 ;
        int     diffDay = 0 ;

        // 起算日の日付を年、月、日に分解(From)
        int     from_year = parseInt(paraFromDate.substring(0,4)) ;
        int     from_month = parseInt(paraFromDate.substring(5,7)) ;
        int     from_day = parseInt(paraFromDate.substring(8,10)) ;

        // 基準日の日付を年、月、日に分解(To)
        int     to_year = parseInt(paraToDate.substring(0,4)) ;
        int     to_month = parseInt(paraToDate.substring(5,7)) ;
        int     to_day = parseInt(paraToDate.substring(8,10)) ;

        Calendar comp_from = Calendar.getInstance() ;
        comp_from.set(from_year, from_month - 1, from_day) ;

        Calendar comp_to = Calendar.getInstance() ;
        comp_to.set(to_year, to_month - 1, to_day) ;

        // 起算日 > 基準日の場合、エラーにする
        if(comp_from.compareTo(comp_to) > 0) {
            return -1;
        }

        // 年の差を取得する
        diffYear = to_year - from_year ;

        // 月を比較
        if(from_month > to_month) {
            // 起算日の月の方が大きい場合 = 年を跨ぐ
            to_month = to_month + 12 ;
            // 年をマイナスする
            // 同じ年であればfrom_monthの方が大きいことはあり得ないため、マイナスになることはない
            diffYear = diffYear - 1 ;
        }

        // 月の差を取得する
        diffMonth = to_month - from_month ;

        // 日を比較
        // 起算日(From)の方が大きい場合、月を跨いでいると判断
        if(from_day > to_day) {
            // 起算日の最大日数を加える
            to_day = to_day + comp_from.getActualMaximum(comp_from.DATE) ;
            // 月の差をマイナスする
            diffMonth = diffMonth - 1 ;
        }
        // 日の差を取得する
        diffDay = to_day - from_day ;

        // 引数に設定する
        paraDiffDay[0] = diffYear ;
        paraDiffDay[1] = diffMonth ;
        paraDiffDay[2] = diffDay ;

        return 0 ;

    }
```
---
呼び出し側

```Java
    String fromDate = '2020/08/20' ;
    String toDate = '2020/10/01' ;
    int diffDate[] = {0,0,0} ;
    if( getDateDiff(fromDate, toDate, diffDate) != 0 ) {
        // エラー
    }
    else {
        String keikaDate = diffDate[0] + "年" + diffDate[1] + "ヵ月" + diffDate[2] + "日" ;
    }
    
```

---
#問題点、課題
・エラーハンドリングがない
　→　引数の日付が yyyy/MM/dd の書式でない場合、Exception発生
　→　yyyy/MM/dd書式であっても存在しない日付の場合、挙動不正

---
#良かった点
・getActualMaximumを使ってその月の最大日数を取得した
　→　最初は
　　　1,3,5,7,8,10,12月は31日
　　　4、6、9、11月は30日
　　　2月はうるう年なら29日、そうでなければ28日としようとした。
　　　getActualMaximumの一文で解決。
【Rails5】順序の並べ替えをドラッグドロップで asts_as_list


#概要
項目の並び替えをドラッグドロップでやるやつです。

https://qiita.com/at-946/items/28cad21211b9305d6077
↑
こちらの記事をもうちょい簡略化して、
coffeeスクリプトが分からんのでJavaScriptにして、
好みでhamlにして、

動作確認までしたのでコードのメモ的な記事です。


#必要なもの
- gem 'acts_as_list'
- Sortable.js
- jQuery.js

`acts_as_list`は、レコードの順番を入れ替え処理するためのgemです。

Sortable.jsはドラッグドロップで順番を入れ替える描写をするためのJavaScriptです。
（jQueryを使わずに実装できる！という謳い文句あり）

jQueryはAjax処理を素のJavaScriptで上手く使えなかったので、めんどくさくなって入れました（妥協）

なのでSortable入れずjQueryの機能で入れ替え処理やるのも良いかもしれませんね。


#導入

##acts_as_list導入

```Gemfile
gem 'acts_as_list'
```

```
$ bundle install
```

```app/models/product.rb
class Product < ApplicationRecord
  acts_as_list
end
```

テーブルにpositionというinteger型カラムが無かったら追加する


##Sortable.js, jquery.min.js 導入

RailsにJavaScriptファイルを追加する時の手順

1. ファイルをapp/assets/javascripts/に配置する
2. config/initializers/assets.rbに定義？を追記する
3. 使用するページでのみ読み込む

↓

```
cd app/assets/javascripts/
wget https://raw.githubusercontent.com/SortableJS/Sortable/master/Sortable.min.js
wget https://code.jquery.com/jquery-3.5.1.min.js

mv jquery-3.5.1.min.js jquery.min.js
```
指定しやすいように一応リネームもしておく。

```config/initializers/assets.js
Rails.application.config.assets.precompile += %w( Sortable.min.js )
Rails.application.config.assets.precompile += %w( jquery.min.js )
```
反映のためRailsサーバを再起動


```app/views/products/index.html.haml
= javascript_include_tag 'Sortable.min.js'
= javascript_include_tag 'jquery.min.js'
```

ここまでが導入に必要なもの。


#ソースコード MVC + route
自分が今回動いたのを確認出来たものです。
見返す用でもあります😂


```app/models/product.rb
class Product < ApplicationRecord
  acts_as_list
end
```


```app/controllers/products_controller.rb
class ProductsController < ApplicationController

  def index
    @products = Product.all.order(:position)
  end

  def sort
    @product  = Product.find(params[:id].to_i)
    @product.insert_at(params[:to].to_i + 1) # SortableのnewInbexは0から始まるから
    head :ok
  end

end
```


```app/views/products/index.html.haml
= javascript_include_tag 'Sortable.min.js'
= javascript_include_tag 'jquery.min.js'

%ul#sortable_list

  - @products.each do |p|
    %li{ value: p.id }= p.position.to_s + " : " + p.name


:javascript

  var sortable = new Sortable(sortable_list, {
    animation: 150,
    delay: 100,
    onUpdate: function(evt) {
      return $.ajax({
        url: 'products/sort',
        type: 'get',
        data: { 
          id: evt.item.value, 
          to: evt.newIndex 
        }
      });
    }
  });
```


```config/routes.rb
Rails.application.routes.draw do
  mount RailsAdmin::Engine => '/admin', as: 'rails_admin'

  get 'products', to: 'products#index'
  get 'products/index'
  patch 'products/sort'
  get 'products/sort'

end
```


#Ajax送信で422エラーが出た問題

俺の指定がどこか悪かったのかもですが……、

Ajaxでの送信部分を「PATCH」にすると422エラーばっかりだったんですよね。
けど「GET」で試したら、解決しました。

うーん……？


#まとめ
割と最低限という感じで使える記事なんじゃないかと思います。

途中、JavaScriptでの値がどうなってるか……とかはonUpdateの中で
alert(evt.item.value);
とかをぶっこんで確認出来ました。
Ajax何度かやってるのに忘れてしまう……。

あと、もしかしたらHaml分からん……言う人も見てるかもですが、冗談じゃなく30分で8割理解できますよこの言語（？）
ヤバヤバ言語。
HTMLをPythonみたいに描ける……🤤って感じなので是非Haml使って下さい（謎ステマ）
ハムろう

終わり
Pythonでスクレイピング

Pythonでスクレイピングする必要があったので、メモしておきます。
Dockerで環境を整えて実施します。


```bash:構成
$ ls
README.md  docker-compose.yaml  scraping
$ ls scraping/
Dockerfile  requirements.txt  scrap.py  scraping.py
```

```yaml:docker-compose.yaml
version: '3.8'

services:
  scraping:
    build: ./scraping
```


```dockerfile:Dockerfile
FROM python:latest

COPY . /work
WORKDIR /work

RUN apt-get update

# beautiful soupをインストール
RUN pip install -U pip
RUN pip install -r requirements.txt

ENTRYPOINT ["python"]
CMD ["scrap.py"]
```

```txt:requirements.txt
bs4
requests
```

適当に h1 で取得

```python:scrap.py
import requests
from bs4 import BeautifulSoup

url = "https://www.yahoo.co.jp"
response = requests.get(url)

soup = BeautifulSoup(response.text,"html.parser")

titles = soup.find_all("h1")

for title in titles:
    print(title.text)
```


```bash:実行結果
$ docker-compose up --build
.
.
.
scraping_1  | Yahoo! JAPAN
scraping_1  | 検索
scraping_1  | JavaScriptの設定について
scraping_1  | 推奨ブラウザーについて
scraping_1  | お知らせ
scraping_1  | 主なサービス
scraping_1  | ニュース
scraping_1  | 主要 ニュース
scraping_1  | 天皇陛下「深い反省」今年も
scraping_1  | さびしい 戦地から届いた恋文
scraping_1  | 戦わず死者5000 見放された島
scraping_1  | 午後は災害級の暑さ 警戒を
scraping_1  | 元徴用工 文氏「日本と努力」
scraping_1  | ローソン 印紙購入横行の背景
scraping_1  | 速報交流試合 磐城vs.国士舘
scraping_1  | 履正社 一度も負けず夏終える
scraping_1  | 追悼式で黙とう
scraping_1  | 個人に関わる情報
scraping_1  | あなたのステータス
scraping_1  | 今日の日付
b-model_scraping_1 exited with code 0
```
laravel 登録したユーザー名をブラウザに表示させる方法

## 完成版

![スクリーンショット 2020-08-15 12.30.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613591/d00eaff1-187b-e567-f200-2c8420bbe7ee.png)

ユーザー登録画面で保存した名前を

![スクリーンショット 2020-08-15 13.17.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613591/90a24cd0-b115-a399-f7a6-caeabe136d70.png)


ログイン後にプラウザで表示させます

## 前提条件　
* ユーザー登録できる状態
* usersテーブルにnameがある状態(migratetionsファイルのusers.tableで確認できます）

```php:/migrations/2014_10_12_000000_create_users_table.php
public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->bigIncrements('id');
            
            $table->string('name');        //こちらです
            
            //中略
        });
    }

``````


## 作成
使用環境： Laravel framework 6.18.24 PHP7


```php:/views/index.blade.php
<h1>おかえりなさい　<?php $user = Auth::user(); ?>{{ $user->name }}</h1>
```

これでユーザー名が表示されます。
メディアクエリ〜ページ表示する画面サイズによってスタイルの設定を変える〜

- SCSSをいじっている際にこいつを知らなくて不覚にもｳﾝ時間も溶かしたのでメモる。
- 雰囲気で読んでやってください


# 背景とやりたいこと

- Railsのアプリケーション(SPAでない)を開発中のお話。
    - プレゼンテーション層はslim, scssファイルを使っている
- あるページにYouTuneの動画を埋め込む。これを、
    - `モバイル機器では、画面の横幅一杯`に表示したい
    - `タブレットとデスクトップでは幅520px`で表示したい。

# 解決策

## (1)UserAgentによってhtmlにタグを付け分ける(最初やろうとしてた)

- アクセスした機器のUserAgentに応じて、Railsのviewファイルをレンダリングする際にタグを動的に付与する
    - モバイル版では、以下のケースだとdivタグに`mobile`クラスが加わる
    - なお、「リクエスト元のUserAgentがどの端末であるかを識別するロジックをアプリケーションの内部に自前で定義している」ことが必要ある

```page.html.slim

// @user_agent.mobile?とで、アクセス者がモバイルかを識別する
div class="app-movie #{'mobile' if @user_agent.mobile?}"
  iframe src="https://www.youtube.com/embed/xxxxxxxx" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"" allowfullscreen
```

```page.scss
.app-movie {
  iframe {
    width: 100%;
  }
  &.mobile {
    iframe {
      width: 520px;
    }
  }
}
```



## CSSファイルの中でメディアクエリを使う(最終的にこっちを採用)


- 一発だった。


```page.html.slim
div class="app-movie"
  iframe src="https://www.youtube.com/embed/xxxxxxxx" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"" allowfullscreen
```

```page.scss

app-movie {
  iframe {
    // TO読者: 閾値の設定はこの記事を参考にしないでください
    @media screen and (max-width:767px) {
      width: 100%;
    }
    @media screen and (min-width:768px) and (max-width:979px) {
      width: 520px;
    }
    @media screen and (min-width:980px) {
      width: 520px;
    }
  }
}
```

- メディアクエリの使い方をもう少し細かく知りたい時は[こちら](https://qiita.com/knml/items/c94dc493571dd4127d43)を参照しよう。


# 補足

- 「widthじゃなくてmax-widthを520pxに設定したらいいのではないか」と思ったりもしたが、[iframeはデフォルトで幅300px, 高さ150pxが設定されており、スクリーンの横幅を広くして行っても、横幅が520pxにまで達することはない](https://stackoverflow.com/questions/5871668/default-width-height-of-an-iframe)ため、widthを設定した。
    - これも知らなかったため、結構時間を溶かしてしまった
WindowsにSelenium Serverを立てる

開発用にSelenium Serverをサクッと立てる方法です。
使用するのは、「npm」と「selenium-standalone」です。

# node.jsをインストールする
npmを同封しているnode.jsをインストールします。
http://nodejs.org/
インストール手順はココがわかりやすい
https://qiita.com/taiponrock/items/9001ae194571feb63a5e

# selenium-standaloneをインストール
[selenium-standalone](https://github.com/vvo/selenium-standalone)は、面倒なドライバーのダウンロードや設定を良きに計らってくれるNode.jsのライブラリです。

- コマンドラインからインストール

```bash
npm install selenium-standalone@latest -g
```
- ドライバーをダウンロード

```bash
selenium-standalone install
```

# Selenium Serverを起動する

```bash
> selenium-standalone start
```
- WSLからSelenium Serverを起動したい場合は、cmd.exe経由で起動する
 
```bash
cmd.exe /c selenium-standalone.cmd start
```
起動が成功している場合はこんなメッセージが表示されます。

```
13:15:11.500 INFO [GridLauncherV3.parse] - Selenium server version: 3.141.59, revision: e82be7d358
13:15:12.003 INFO [GridLauncherV3.lambda$buildLaunchers$3] - Launching a standalone Selenium Server on port 4444
2020-08-15 13:15:12.537:INFO::main: Logging initialized @2501ms to org.seleniumhq.jetty9.util.log.StdErrLog
13:15:13.961 INFO [WebDriverServlet.<init>] - Initialising WebDriverServlet
13:15:15.424 INFO [SeleniumServer.boot] - Selenium Server is up and running on port 4444
Selenium started
```
# Selenium Serverを簡単に起動できるようにする。
コマンドプロンプト(cmd.exe)を開く

```
> notepad hub.bat
```

hub.batの内容を以下の通りにして保存する。

```
cmd.exe /c selenium-standalone.cmd install
selenium-standalone.cmd start
```

# Selenium Serverが起動しているか確認する
Windowsならブラウザで http://localhost:4444  にアクセスする
![seleniumserver.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482013/5142a045-8554-5469-cbe9-0f9e24012990.png)

# WSLからアクセスできるか確認する

```bash
$ wget http://ホストOSのIP:4444 -O -
--2020-08-15 13:52:42--  http://ホストOSのIP:4444/
Connecting to ホストOSのIP:4444... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1672 (1.6K) [text/html]
Saving to: ‘STDOUT’
　　・
　　・
```
ホストOSのIPがわからない場合は、ipconfig.exeで調べられます。

```bash
$ ipconfig.exe
イーサネット アダプター vEthernet (WSL):
   接続固有の DNS サフィックス . . . . .:
   リンクローカル IPv6 アドレス. . . . .: XXXX::XXXX:XXXX:XXXX:XXXX
   IPv4 アドレス . . . . . . . . . . . .: XXX.XXX.XXX.XXX
   サブネット マスク . . . . . . . . . .: 255.255.240.0
   デフォルト ゲートウェイ . . . . . . .:
```
IPv4 アドレスのところが、ホストOSのIPです。
それでもアクセスできない場合はファイアウォールでブロックしているかもしれません。
toio.jsをWindowsで動かす


## 前置

こちらの記事を参考にUnityからtoio Cubeを連携したかったのですが、Windowsだとtoio.jsを動かすまでの手順が少し複雑になるようです
https://qiita.com/ito_ur_right/items/85062db988cfce14c4d7

なるべく簡単に実行環境を用意したいと探りつつ、サンプルを動かすところまで行けたのでメモを残したいと思います
環境依存となる部分があるかもしれませんので参考にされる場合はご注意ください

## node.js・yarn

node.jsとyarn、両方ともインストーラーをダウンロードして実行

## node.js
https://nodejs.org/ja/download/
node-v12.18.3-x64.msi

## yarn
https://classic.yarnpkg.com/ja/docs/install/#windows-stable
yarn-1.22.4.msi


## toio.js

toio.jsをZipでダウンロードして、作業環境となるディレクトリに展開

https://github.com/toio/toio.js

### インストールとビルド

toio.jsを展開したディレクトリでコマンド実行

```
yarn install 
yarn build
```

インストールとビルド時にエラーが出ましたが2回実施すると無事に完了しますので、とりあえず進めることにしました


## Zadig

Zadig Toolを使って汎用USBドライバーをインストールします

### Zadig Tool
https://zadig.akeo.ie/
zadig-2.5.exe

使用方法については以下のビデオ（1:48～2:42あたり）を参考にしました
https://youtu.be/mL9B8wuEdms?t=107

**注意**
Zadig Toolを使って汎用USBドライバーの適用を行うとWindows上でBluetoothとして認識されなくなります
node-bluetooth-hci-socketのREADMEではデバイスマネージャーよりロールバックが出来るとの記載がありますが、自分はそれではダメで~~ドライバの再インストールが必要でした~~

戻す手段は見つかっていません


### Bluetooth USBアダプタについて

Zadigを使用するには互換性のあるBluetooth 4.0/4.1 USBアダプタである必要があるようです。
詳しくはリンク先の一覧表をご確認ください
https://github.com/noble/node-bluetooth-hci-socket#windows

ちなみに自分の環境ではエレコムの LBT-UAN05C2 を使っています。
Windows10環境で使うなら良いのではないでしょうか（安いし）
https://www.amazon.co.jp/dp/B00J84V7OM/ref=cm_sw_r_tw_dp_x_Y-ynFbNXNE3MA

#### エレコムLBT-UAN05C2のドライバ

~~汎用USBドライバーを適用した後にドライバーを戻すのにドライバが必要となることがあります~~

~~以下は、エレコムLBT-UAN05C2をロールバックするのに使用したインストーラーのダウンロード先です~~
~~https://www.elecom.co.jp/support/download/network/bluetooth/lbt-uan05/?_ga=2.65248494.1331885594.1598415049-530739635.1598415049~~

ダメでした

##node-bluetooth-hci-socket

node-bluetooth-hci-socket(Node.jsのBluetooth HCIソケットバインディング)をZipでダウンロード、作業環境となるディレクトリに展開

https://github.com/noble/node-bluetooth-hci-socket#windows
node-bluetooth-hci-socket-master.zip


### インストール

bluetooth-hci-socketを展開したディレクトリでコマンド実行

```
npm install bluetooth-hci-socket
```

## サンプル実行

toio Cubeの電源を入れて、サンプル keyboard-control を実行

```
yarn example:keyboard-control
```

無事、toio Cubeをカーソルキーで操作できました
PYNQ > PL > IP: concat > 一つの入力(Slide SW)を一つの出力(RGBLED_R)につなげる

```txt:動作環境
Windows 10 Pro (v1909) 
PYNQ-Z1 (Digilent) (以下、PYNQと表記)
PYNQ v2.5 Image
Vivado v2019.1 (64-bit)
```

### 概要

- 一つの入力(Slide SW)を一つの出力(RGBLED_R)につなげたい
- concatを1bit input, 1bit outputで使うとできた

### Block Design

![コメント 2020-08-15 124558.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32870/3a18ef84-39f3-c893-d655-bac4d33510a0.png)

### Concat IP

Number of Portsを１に変更した。

![コメント 2020-08-15 124637.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32870/ecc7522c-09ba-ba6d-d535-635243063d6f.png)

### Constant IP

RGBLEDのGとBについてはConstant IPで固定。
Const Val=0としておく。

![コメント 2020-08-15 124927.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32870/3c5fff53-c691-d7ac-d9f6-c6a3fc5bfabf.png)

### 制約ファイル

Run Synthesisを実行後、I/O PortsにてSlide SWとRGBLEDのピンを指定する。
ZYNQ-Z1のプリセットファイル(`PYNQ-Z1_C.xdc`)にピンの記載があるので、それを参考にする


```txt:制約ファイル
set_property PACKAGE_PIN L15 [get_ports {RGBLED_B[0]}]
set_property IOSTANDARD LVCMOS18 [get_ports {RGBLED_B[0]}]
set_property PACKAGE_PIN G17 [get_ports {RGBLED_G[0]}]
set_property PACKAGE_PIN N15 [get_ports {RGBLED_R[0]}]
set_property IOSTANDARD LVCMOS18 [get_ports {RGBLED_G[0]}]
set_property IOSTANDARD LVCMOS18 [get_ports {RGBLED_R[0]}]

set_property PACKAGE_PIN M20 [get_ports {SlideSW[0]}]
set_property IOSTANDARD LVCMOS18 [get_ports {SlideSW[0]}]
```

### 動作確認

上記にてbitstreamを生成した。
.tclファイルと.bitファイルをZYNQ-Z1のフォルダ(`\\pynq\xilinx\jupyter_notebooks\base`)にコピーした (Explorerで`\\pynq`に接続してフォルダ選択）。

### Python

Jupyter Notebookにて下記を実行した。

```py
from pynq import Overlay

ol = Overlay("/home/xilinx/jupyter_notebooks/base/slideSW_RGBLed_200815.bit")
```

SlideSWをOFFの時
![IMG_1975.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32870/9c575a5c-794f-86a7-abbc-131987500204.jpeg)

SlideSWをONの時
![IMG_1976.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32870/d810dabe-bcc2-5856-06d6-f8e8ccb07324.jpeg)


### その他

- Concatの代わりにSliceを使おうともしたが、Sliceだと1bit inputは設定できなかった

### 補足

Slide SWのON/OFFによる処理の開始(PL)は別にConcat IPを使わないで、直接対象のIPのピンにMake Externalすればいいかな。
RGBLED_Rへの出力と、別のRTLのenableと結線するのはするかもしれない。
crossでOpenSSLを静的リンクしてビルドする

Rustをクロスコンパイルする際に利用する、[cross](https://github.com/rust-embedded/cross)というツールがあります。

crossには、target別にクロスコンパイル用のtoolchainを揃えたコンテナイメージが用意されており、cargoコマンドの代わりに、crossコマンドを使うことで、クロスコンパイル用のコンテナでビルドを行ってくれます。

クロスコンパイル用のtoolchainが予め導入されているといっても、必要なものが足りないということはありえます。その場合は、[カスタムしたdocker imageを利用する](https://github.com/rust-embedded/cross/blob/master/README.md#custom-docker-images)ことで、必要なファイルをコンテナイメージに追加してビルドに利用することができます。

現状、よく問題になっていると思われるのが、OpenSSL用のライブラリが足りずにコンパイルできない、ということです。crossは現在(2020/8)、v0.2.1ですが、2020/2以前のv0.1.16まではOpenSSLのライブラリがコンテナに含まれていました。[Remove OpenSSL](https://github.com/rust-embedded/cross/issues/229)を見ると、そもそもOpenSSLはcrossが本来サポートするスコープから外れているため、外そうということになったようです。

ただ、OpenSSLがビルドに必要なcrateは多かったようで、上記のissueにもいきなりビルドできなくなったんだけどどうしたらいいの？ という質問が多くあります。自分も以前はissue内で紹介されている、crossを以前のバージョンで使用する(cargo install --version 0.1.16 cross)で回避していたのですが、ビルド時にpythonが必要なcrateを使う必要があり、カスタムdocker imageの作成を行ってみたので、その際のメモを残しておきます。

### Cross.toml
カスタムdockerイメージを使う場合、Cross.tomlファイルに利用するイメージ名を指定しておきます。↓の例は自分のDocker Hubのイメージを指定していますが、ローカルのみで使う場合はタグがついていれば十分で、特にDocker Hubへpushする必要ありません。自分はtravis ciでのビルドでも利用するため、pushしています。

```Cross.toml
[target.x86_64-unknown-linux-gnu]
image = "k2da/hrkk-cross-linux-gnu:latest"
```

### イメージの作成
本題のイメージを作成します。targetはx86_64-unknown-linux-gnuです。

最初は「apt-get install libssl-dev」のみで試してビルド自体は通ったのですが、生成されたバイナリがubuntuで動かなかったため、静的リンクに変更してます。

```Dockerfile
FROM rustembedded/cross:x86_64-unknown-linux-gnu-0.2.1

RUN apt-get update && \
    apt-get install python --assume-yes

COPY openssl.sh /
RUN bash /openssl.sh linux-x86_64

ENV OPENSSL_DIR=/openssl \
    OPENSSL_INCLUDE_DIR=/openssl/include \
    OPENSSL_LIB_DIR=/openssl/lib \
    OPENSSL_STATIC=1
```

ベースとしてcrossの最新のイメージを使用。openssl.shは[crossの0.1.16で使用されていたスクリプト](https://github.com/rust-embedded/cross/blob/v0.1.16/docker/openssl.sh)をそのまま持ってきて、同じディレクトリに入れてあります。最後の環境変数は、静的リンクするために必要なもので、これも0.1.16のDockerfileを参考にしてます。

pythonは別の事情で入れてるだけなので、OpenSSLとは関係ありません。

dockerイメージをビルドして、tagをつけておきます。

```
# イメージビルドしてtagつける
docker build . -t k2da/hrkk-cross-linux-gnu:latest
```

### ビルドする

cargoではなく、crossを使用するだけです。イメージはCross.tomlで指定してあるので、コマンド自体は通常のcrossでのビルドと同じです。

```
cross build --release --target x86_64-unknown-linux-gnu
```

これでビルド成功して、自分のubuntu環境では動きました。
JavaScript オブジェクトの値で重複したものを削除する


### やりたいこと

以下のように、中身の値（ id や key など要素を一意に決めるものを想定しています）が重複しているオブジェクトがあった時、重複している部分だけ削除したオブジェクトを作りたい。

```id``` の ```aa``` が重複しているので、

```ruby:sample.js
const objectA = [ {id: aa, value: "banana”},
                  {id: bb, value: "apple"},
　　　　　　　　　　　{id: cc, value: "orange"},
                  {id: aa, value: "banana"},
                  {id: dd, value: "grape"} ];
```

こうしたい

```ruby:sample.js
const objectA = [ {id: aa, value: "banana”},
                  {id: bb, value: "apple"},
　　　　　　　　　　　{id: cc, value: "orange"},
                  {id: dd, value: "grape"} ];
```


### やりかた

以下のように、```filter``` と```findIndex```を用いてフィルタリングすることで、重複した値を持つ要素を削除したオブジェクトを作ることができます。```item.id```の```id```の部分は調べたいプロパティ名に適宜変えてやってみてください。

```ruby:sample.js

    const filteredObjectA = objectA.filter(
      (item, index, array) => {
        return (
          array.findIndex(nextItem => item.id === nextItem.id) ===
          index
        );
      }
    );
```
LocalDateとTimestampを変換する方法

`LocalDate`と`Timestamp`を変換するには間に`LocalDateTime`を挟んで変換していく。

- 参考
    - [Timestamp (Java Platform SE 8)](https://docs.oracle.com/javase/jp/8/docs/api/java/sql/Timestamp.html)
    - [LocalDate (Java Platform SE 8)](https://docs.oracle.com/javase/jp/8/docs/api/java/time/LocalDate.html)

# LocalDateをTimestampへ変換する方法

```java
/**
 * TimeStampで現在日時を取得する.
 * @return 現在日時.
 */
public Timestamp getTimestamp() {
    // LocalDateで現在日時.
    var localDate = LocalDate.now();
    // 日付の開始時のLocalDateTimeを作成.
    var localDateTime = localDate.atStartOfDay();
    // LocalDateTimeと同じ日付/時間値を持つTimestampを取得.
    var timestamp = Timestamp.valueOf(localDateTime);
    return timestamp;
}
```

# TimestampをLocalDateへ変換する方法
```java
/**
 * LocalDateで現在日を取得する.
 * @return 現在日.
 */
public LocalDate getLocalDate() {
    // Timestampで現在日時.
    var timestamp = new Timestamp(new Date().getTime());
    // TimestampをLocalDateTimeに変換
    var localDateTime = timestamp.toLocalDateTime();
    // この日付/時間のLocalDate部分を取得
    var localDate = localDateTime.toLocalDate();
    return localDate;
}
```
PHP Paiza 標準入力テンプレート

## Paiza

[Paiza](https://paiza.jp)はコーディングのスキルチェックが行えます。
問題では標準入力からパラメータを受け取りますが、毎回書くのも手間なのでどの問題でも共通して利用できるテンプレートを用意しました。

## Paiza標準入力テンプレート

単一行でも複数行でもDランク〜SランクまですべてのPaizaの問題で利用できます。また、ローカルで動作確認のやり方もご紹介します。

```php:example.php
<?php

$inputs = [];
while ($input = trim((string) fgets(STDIN))) {
    $inputs[] = explode(' ', $input);
}

var_dump($inputs);
```

## 使い方1

```
$ php example.php
```

![ScreenShot 2022-08-17 10.37.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52879/480dc1c6-56b0-4f38-1a71-a8f9ce243cbb.png)

ファイルを実行すると標準入力を受け付けます。
空Enterするとループから抜けます。

入力したデータは `$inputs` に配列で格納されてるので良い感じに使用してください。

## 使い方2

何度も動作確認したい時に標準入力を何度も行うのは手間がかかります。
何行にも渡りも入力データがある場合は入力ミスも発生しやすいです。

実行時にファイルを標準入力にリダイレクトすると簡単です。

```txt:stdin.txt
aaa bbb ccc
100 200 300 400 500
```

`stdin.txt` はただのテキストファイルです。

```shell-session
$ php example.php < stdin.txt
```

![ScreenShot 2022-08-17 10.58.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52879/b54106da-265f-3cf1-1b6d-b4d5a3c9454e.png)

### Dockerコマンド

```shell-session
$ docker run -i -v $(pwd):/data -w /data php:8.1 php example.php < stdin.txt
```

ローカルにphp環境作るのが面倒な人はdockerでphpコンテナを作るのが一番楽かなと思います。

### 標準出力テスト

```shell-session
$ diff <(docker run -i -v $(pwd):/data -w /data php:8.1 php c075.php < stdin.txt) <(cat stdout.txt)
```

標準出力が多い場合、1行1行目で確認するのは手間なので、diffで差分がないか確認すると良いです。

## 解説

### STDIN

`STDIN` は `standard input(標準入力)` の意味です。
ターミナルで入力した文字を標準入力としてPHPへ渡す形になります。

### fgets とは

第一引数に指定したファイルポインタから1行取得し、その文字列を返します。
https://www.php.net/manual/ja/function.fgets.php
`STDIN` という標準入力を表す定数を渡しているので、標準入力から1行取得します。
`fgets` した時に読み込みデータがない場合、 `false` が返るので `string` にキャストしてます。

### trim とは

第一引数に指定した文字列の先頭および末尾にある空白や改行を取り除き、その文字列を返します。
https://www.php.net/manual/ja/function.trim.php

改行のみの行を最終行と判定したいのですが、改行コードがあるとループから抜けることができないので、trimしてます。

## 参考記事

- [Paizaで使える標準入力の取得](https://qiita.com/one-kelvin/items/09068b8971c4da509cd3)
【Laravel + Vue】ファイルパスに .. を使いたくない【webpackConfig Alias】

#問題
階層が深いところから、上の呼び出すときに
`..`がたくさん連なったりしてわかりにくい

```js:App.vue
import Hoge from '../../../components/Hoge'
```

#解決方法
webpackConfigでエイリアスを設定する

```js:webpack.mix.js
mix.webpackConfig({
    resolve: {
        alias: {
            "@": path.resolve(__dirname, "resources/js")
        }
    }
});
```

これで`@/components/Hoge`とやれば
`/resources/js/components/Hoge`見たく展開される
ParseException: Unparseable dateとなった時の対応方法



# 事象 : f:convertDateTimeを使ったらエラーになった
- 環境
    - CentOS Linux release 7.8.2003 (Core)
    - Eclipse IDE for Enterprise Java Developers.Version: 2020-03 (4.15.0)
    - openjdk version "11.0.7" 2020-04-14 LTS
    - JSF 2.3.9


```bash
java.text.ParseException: Unparseable date: "sampleBean.timestamp"
    at java.base/java.text.DateFormat.parse(DateFormat.java:395)
    at javax.faces.convert.DateTimeConverter$FormatWrapper.parse(DateTimeConverter.java:489)
    at javax.faces.convert.DateTimeConverter$FormatWrapper.access$100(DateTimeConverter.java:470)
    at javax.faces.convert.DateTimeConverter.getAsObject(DateTimeConverter.java:437)
    at com.sun.faces.facelets.tag.jsf.ConverterTagHandlerDelegateImpl.applyAttachedObject(ConverterTagHandlerDelegateImpl.java:120)
    at javax.faces.view.facelets.FaceletsAttachedObjectHandler.applyAttachedObject(FaceletsAttachedObjectHandler.java:60)
    at com.sun.faces.facelets.tag.jsf.ConverterTagHandlerDelegateImpl.apply(ConverterTagHandlerDelegateImpl.java:53)
    at javax.faces.view.facelets.DelegatingMetaTagHandler.apply(DelegatingMetaTagHandler.java:111)
    at javax.faces.view.facelets.DelegatingMetaTagHandler.applyNextHandler(DelegatingMetaTagHandler.java:137)
    at com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.apply(ComponentTagHandlerDelegateImpl.java:179)
...省略...
```

## 原因 : h:outputTextのvalue属性を#{}で囲むのを忘れた
1. `f:convertDateTime`から([convertDateTime(JSF 2.2 View Declaration Language: JSP Variant)](https://docs.oracle.com/javaee/7/javaserver-faces-2-2/vdldocs-jsp/f/convertDateTime.html))
1. `javax.faces.convert.DateTimeConverter#getAsObject`が呼ばれて([DateTimeConverter | JavaServer Faces API (2.2)](https://faces.liferay.dev/doc/javax.faces-api/2.2/javadoc/index.html?javax/faces/convert/DateTimeConverter.html))
1. `javax.faces.convert.DateTimeConverter.FormatWrapper#parse`が呼ばれて([DateTimeConverter.FormatWrapper (Mojarra Implementation Javadoc (2.3))](https://javadoc.io/static/org.glassfish/javax.faces/2.3.0-m04/javax/faces/convert/DateTimeConverter.FormatWrapper.html#parse-java.lang.CharSequence-))
1. `java.text.DateFormat#parse`で`ParseException`になる
1. 理由には「 指定された文字列の先頭が解析できない場合。」とある([DateFormat (Java Platform SE 8)](https://docs.oracle.com/javase/jp/8/docs/api/java/text/DateFormat.html#parse-java.lang.String-))

バカっぽいけどよくやる自分がいる

```xml
    <h:outputText value="sampleBean.timestamp">
      <f:convertDateTime pattern="yyyy-MM-dd" timeZone="Japan"/>
    </h:outputText>
```

### 対応 : EL式はちゃんと#{}で囲む
```xml
    <h:outputText value="#{sampleBean.timestamp}">
      <f:convertDateTime pattern="yyyy-MM-dd" timeZone="Japan"/>
    </h:outputText>
```
Vtuberになって顔と腕を動かす

![movearm.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268835/fae74df0-c00e-7a14-7b22-3b56456db906.gif)

# やりたいこと
モーションキャプチャーとフェイストラッキングで3dモデルを動かして、WebRTCで配信するよ

# デモ
配信
https://mlivt.xbid.ne.jp/?model=0

# 動くとこ
顔の向き
腕上部
腕下部

# ライブラリ
## 外部のやつ
face-api.js
https://github.com/justadudewhohacks/face-api.js/
posenet
https://github.com/tensorflow/tfjs-models/tree/master/posenet

## 自作
Live.js
https://github.com/yusukem99/Live

# こまった
faceapi.jsはtensorflow2.0に対応してないよ
AWS EC2 AmazonLinux2 peclコマンドを使用できる様にする

# 目的

- AWSのEC2のインスタンスでpeclコマンドを実行できる様にする方法を紹介する。

# 実施環境

- ハードウェア環境

    | 項目 | 情報 |
    | --- | --- |
    | OS | macOS Catalina(10.15.5) |
    | ハードウェア | MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports) |
    | プロセッサ | 2 GHz クアッドコアIntel Core i5 |
    | メモリ | 32 GB 3733 MHz LPDDR4 |
    | グラフィックス | Intel Iris Plus Graphics 1536 MB |

- ソフトウェア環境(下記の環境をEC2に構築した)

    | 名前 | バージョン | 備考 |
    | --- | --- | --- |
    | PHP | 7.4.7 | こちらの方法で構築→[AWS EC2 AmazonLinux2 PHPをインストールする](https://qiita.com/miriwo/items/7d94303e7185e4118f52) |
    | composer | 1.10.7 | こちらの方法で構築→[AWS EC2 AmazonLinux2 composerをインストールする](https://qiita.com/miriwo/items/b25f9d4d74b7103f6ff6) |
    | MySQL | 8.0.20 for Linux | こちらの方法で構築→[AWS EC2 AmazonLinux2 MySQLを使えるようにする](https://qiita.com/miriwo/items/c0ba0ff17c329700fc9e) |
    | Apache | 2.4.43 | こちらの方法で構築→[AWS EC2 をMacで使ってみよう!](https://qiita.com/miriwo/items/a1ab84c098008e43d042) |
    | Laravel | 7.22.4 | こちらの方法で構築→[AWS EC2 AmazonLinux2だけでLaravelのアプリをデプロイする](https://qiita.com/miriwo/items/b39d1ac6289c54cc2cfd) |

# 前提条件

- 先に記載した各バージョンで環境構築が実施されていること。

# 前提情報

- 本説明で実行するコマンドは特に記載がない場合インスタンスにsshで接続して実行する物とする。

# 読後感

- AmazonLinux2インスタンス内でpeclコマンドを実行することができる。

# 詳細

1. 下記コマンドを実行してリポジトリを追加する。

    ```terminal
    $ sudo yum install http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
    ```
1. 下記コマンドを実行してパッケージをインストールする。

    ```terminal
    $ sudo yum --enablerepo=remi-php74 install php-pear
    ```
1. 下記コマンドを実行してコマンドの実行を確認する。

    ```terminal
    $ pecl
    ```

# 参考文献

- [https://www.php.net/manual/ja/install.pecl.pear.php](https://www.php.net/manual/ja/install.pecl.pear.php)
- [https://unskilled.site/pecl%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%99%E3%82%8B/](https://unskilled.site/pecl%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%99%E3%82%8B/)
- [https://weblabo.oscasierra.net/centos7-php72-install/](https://weblabo.oscasierra.net/centos7-php72-install/)
grbl_ESP32 WEB UI (wifi)

#WIFIからGRBLを制御
grbl_ESP32はESP3DというwebベースのGコード制御に対応している。(WEB UI)
USBでシリアル接続しなくてもコントロールが可能。

ESP3D
https://github.com/luc-github/ESP3D

###WEB UI設定
config.hの以下を設定
(自宅のwifiに繋げるとき)
　//Connect to your local AP with these credentials
　#define CONNECT_TO_SSID  "???????"
　#define SSID_PASSWORD  "??????"
(?????に自宅wifiのSSIDとパスワードを入力)

ファームを書き込んだArduino IDEのシリアルモニタで
$I を打つとIPが表示されるのでwebブラウザでそのIPを叩く。

下記表示が出る（ちゃんとつながっていれば）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664748/4aa7344f-bf5a-39d5-69a8-e8ec4a9bac4e.png)

Flash Filesystemの「Choose Files」をクリックして、
Aruduino\libraries\Grbl_Esp32\data\内の
index.html.gzを選択し「upload」ボタンを押す。

リロードすると下記画面になる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664748/c662baf6-177b-4aaf-1723-05c629e6eb66.png)

左下のSD FilesのウインドウにLaserGRBLなどで生成したGコードファイルをアップロードして動かす。
(ファイル名の右に再生ボタン)
右下のウインドウで直接コマンド制御することも可能。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664748/847a8f20-9eac-9550-4138-4dd9e31c1d17.png)
（128GBのマイクロSDカードは認識されなかった。32GBは問題なく動作することを確認）

パソコンが近くになくてもwifiさえつながっていればレーザー加工できるので大変便利。


ホーミング動作
https://youtu.be/k1f5RiOqayM

WEB UIからGコードを走らせた動画
https://youtu.be/nTk5zm0EwNQ
map処理を用いて、返り値が配列のfunctionを作る

## やりたい事
- map処理で返ってきた配列を、返り値として渡すfunction を作りたい


### Case 1
```sample.ts
const functionA = (test_data) => {
  return test_data.map((data, index)=>{
    // 何かしらの処理
    return {
      field: data,
      index: index
    }
  })
}

const main = () => {
  const array = functionA() //[{field: hoge, index: fuga},{~},{~}]が返り値
}
```
複数の値がある`test_data` をmap処理を用いて、一つ一つずつ処理していく。
それぞれの処理済み値をreturn するのはもちろん、map処理を行っている本体の処理もreturn する必要がある。


### Case 2 (非同期処理)
```sample2.ts
const functionB = async(test_data) => {
  const promises = test_data.map(async(data, index)=>{
    // await functionC() (何かしらの非同期処理)
    return {
      field: data,
      index: index
    }
  })
 return await Promise.all(promises)
}

const main = async() => {
  const data = await functionB()
}
```
map処理の中で重い非同期処理を行いたい場合は、`Promise.all`を用いるのが楽。
Gitで開発中のブランチにリモートブランチの変更を取り込む

# 環境
- AmazonLinux2
- Git

# 状況
1. ローカルのdevelopブランチから派生させたfeature/○○○ブランチで開発を行っている
2. リモートのdevelopブランチに他の人のプルリクがマージされる

# 手順
```
git checkout feature/○○○
git pull --rebase origin develop
```

### 変更を取り込んだ後に`git push origin feature/○○○`がrejectされた場合
```
git push -f origin feature/○○○
```
※他の人が同じfeature/○○○を利用していない場合のみ
[初心者向け]画面遷移できない！"class AppDelegate: UIResponder, UIApplicationDelegate"で起こったエラーの対処法

こんにちは。はじめまして。
最近iOSアプリ開発に向けてSwiftの学習を始めました。

画面遷移の学習中、今回のエラーが起こり長い時間悩まされていたので、
同じ悩みを持つ人が現れた時の一助となれるよう記事にしたいと思います。


#対象

・Xcode　ver 11.6前後から学び始めた学習者
・storyboardを使用している
・学習をスタートしてまだ１〜２時間程度（おそらく）


#起こるエラー
・画面遷移等で紐付けをしているがシミュレータを起動してもクラッシュしてしまう。
→その後下記の画面が表示される。
![スクリーンショット 2020-08-15 11.30.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691642/85171f18-a71c-d226-7ce7-08acb791dd28.png)




※一度紐付けしたものを削除して再度紐付けし直しても同じようにエラーになります。

#原因
一度削除もしくは変更した紐付けがキャッシュとしてまだ残っているため

#解決法
1.Main.storyboardの画面を開きます。
2.紐付け元のView Controllerを右クリックor二本指でタップなどで開きます。(下の画像でいうと、スマホ画面の上にある青く暗転している部分です。）
![スクリーンショット 2020-08-15 11.47.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691642/a2a14f18-4a77-bd00-d4ec-a9039f5e2342.png)
3.キャッシュが残っている部分は黄色の三角マークで警告が出ています。
→その左側にある"×"を押してキャッシュを削除。


![スクリーンショット 2020-08-15 11.48.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691642/2c8845e9-3a31-0887-ed6c-9c1408932e33.png)

以上を行なった後に再度紐付けをしてシミュレータを起動してみてください。



#まとめ
できるだけ初学者に向け、難しい言葉を使わない記事にしました。
同じ言葉を何度も使い、かえって読みにくくなっている部分もあると思います。
さらには自分の理解を至らない部分もあり、誤った箇所もあると思います。
今後も理解を深め、本記事についても加筆・修正を行なっていきたいと思います。

始めたばかりでたちまち前に進めず歯痒い思いをしている初学者の方への一助となれば幸いです。
[PHP]一番早い日時, 一番遅い日時を返すには？

# 結論

`min()`, `max()`を使えば良いです。

# コード

```PHP:sample.php
<?php

$oldest_datetime = new DateTimeImmutable('2020-08-15 09:00:00');
$datetime        = new DateTimeImmutable('2020-08-15 10:00:00');
$latest_datetime = new DateTimeImmutable('2040-08-15 11:00:00');

var_dump(min($oldest_datetime, $datetime, $latest_datetime));
var_dump(max($oldest_datetime, $datetime, $latest_datetime));

// 配列で渡してもOK
$datetimes = [ $oldest_datetime, $datetime, $latest_datetime ];

var_dump(min($datetimes));
var_dump(max($datetimes));
```

```Shell
$ php sample.php
object(DateTimeImmutable)#1 (3) {
  ["date"]=>
  string(26) "2020-08-15 09:00:00.000000"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(3) "UTC"
}
object(DateTimeImmutable)#3 (3) {
  ["date"]=>
  string(26) "2040-08-15 11:00:00.000000"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(3) "UTC"
}
object(DateTimeImmutable)#1 (3) {
  ["date"]=>
  string(26) "2020-08-15 09:00:00.000000"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(3) "UTC"
}
object(DateTimeImmutable)#3 (3) {
  ["date"]=>
  string(26) "2040-08-15 11:00:00.000000"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(3) "UTC"
}
```

# ポイント

- `min()`, `max()`なら誰でもある程度は挙動を知ってます。オレオレ関数をわざわざ作る必要はありません。
- `DateTimeImmutable`, `Datetime`クラスは比較演算子が使えます。なので`min()`, `max()`による早い/遅いの比較が可能です。エポック秒などの数字に変換させる必要はありません。

[min - PHP](https://www.php.net/manual/ja/function.min.php)