OmniAICreator/Qiita-1.07M huggingface dataset:
PHPのパフォーマンスチューニング（メモ化）

## はじめに
Laravelはよくパフォーマンスが悪いと言われますが、コードの書き方やLaravelの使い方次第で大幅にパフォーマンスは改善することが可能です。
本日はパフォーマンスチューニングの手法の一つであるメモ化について記事にしたいと思います。

## 動作確認環境
- PHP 8.0
- Laravel 8.0

※下位環境でも動作する場合がございます

## パフォーマンスについて

一番遅い：データベースから値を取得
遅い：外部キャッシュ（Redis、Memcacheなど）から値を取得
速い：データキャッシュとしてのapcuから値を取得
一番速い：メモ化して値を取得

保存箇所へのアクセスが遠いほど、パフォーマンス劣化が発生します。

## メモ化とは
> メモ化（英: Memoization）とは、プログラムの高速化のための最適化技法の一種であり、サブルーチン呼び出しの結果を後で再利用するために保持し、そのサブルーチン（関数）の呼び出し毎の再計算を防ぐ手法

Wikipediaには上記のようにあります。
噛み砕くと、処理の返り値を変数に保存しておき、それを再利用することで同じ計算を省略して処理速度を向上させる手法です。

## Laravelでメモ化が使われている箇所
Laravelでは、Illuminate\Support\Strなどで実際に使われています。
以下は、引数で渡された値を先頭大文字の英字（通称アッパーキャメルケース）に変換してくれるメソッドです。
一度目の呼び出しと同じ引数が渡された場合は、すでにメモ化しているので、変換処理をはさまずに値が返ります。

```php
/**
 * The cache of studly-cased words.
 *
 * @var array
 */
protected static $studlyCache = [];

/**
 * Convert a value to studly caps case.
 *
 * @param  string  $value
 * @return string
 */
public static function studly($value)
{
    $key = $value;

    if (isset(static::$studlyCache[$key])) {
        return static::$studlyCache[$key];
    }

    $value = ucwords(str_replace(['-', '_'], ' ', $value));

    return static::$studlyCache[$key] = str_replace(' ', '', $value);
}
```

## クロージャーを使ったメモ化
Laravelの\Illuminate\Cache\Repository::rememberをメモ化用に改変

```php
/**
 * @var array
 */
protected $localCache = [];

/**
 * Memoization sample
 *
 * @param  string  $cacheKey
 * @return mixed
 */
public function localCache(string $cacheKey)
{
    return $this->rememberLocal($cacheKey, function () {
        // メモ化したい処理
        // 引数のcacheKeyが同じであれば一度目しか重い処理は通りません
    });
}

/**
 * Get an item from the cache, or execute the given Closure and store the result.
 *
 * @param  string  $key
 * @param  \Closure  $callback
 * @return mixed
 */
private function rememberLocal(string $key, Closure $callback)
{
    $value = $this->get($key);

    if ($value !== null) {
        return $value;
    }

    $this->put($key, $value = $callback());

    return $value;
}

/**
 * Retrieve an item from the local cache by key.
 *
 * @param  string  $key
 * @return mixed
 */
private function get(string $key)
{
    return $this->localCache[$key] ?? null;
}

/**
 * Store an item in the local cache.
 *
 * @param  string  $key
 * @param  mixed  $value
 */
private function put(string $key, $value): void
{
    $this->localCache[$key] = $value;
}
```

## 編集後記
パフォーマンスチューニングについて勉強した時に一番最初に学んだメモ化について記事にしました。

どこまでパフォーマンスチューニングするかはケースバイケースだとは思いますが、私の場合DBへのアクセスするのは最終手段という中で育ってきたので、メモ化は積極的に使うようにしています。
1回の通信で同じ重い処理を2度以上する可能性がある場合にはまずはメモ化の検討をオススメします。

## Laravelのパフォーマンスチューニングに関する記事
https://laravel-news.com/performance-checklist

https://qiita.com/ProjectEuropa/items/e68567f3cd5b0cf31d90
terraformバージョンを0.12.29→0.15.3へアップグレードする方法

## 環境
- tfevnいれてる

## アップグレード方法
- 0.12系から一気に0.15系へアップグレードすることはできないみたい
- 0.12→0.13→0.14→0.15と順を追っていく必要がある

## v0.12.29→v0.13.7

### 現在
.terraform-version


```.terraform-version
0.12.29
```

### 変更する
.terraform-version


```.terraform-version
0.13.7
```

### providerの箇所
- 0.12系の書き方に住居

```provider.tf
provider "aws" {
  region  = var.region
  version = "= 3.1"
  profile = "vamdemic"
}

terraform {
  backend "s3" {
    bucket  = "vamdemic-terraform"
    region  = "ap-northeast-1"
    profile = "terraformer"
    key     = "terraform/terraform.tfstate"
    encrypt = true
  }
}
```

### upgrade実行

```
rm -fr .terraform
terraform init -upgrade
```
### planして、リソースの差分などが出たら手動で直す

```
terraform plan
```

## v0.13.7→0.14.11

.terraform-version

```.terraform-version
0.14.11
```

### upgrade実行

```
terraform init -upgrade
```

エラー発生

```
Warning: Version constraints inside provider configuration blocks are deprecated

  on main.tf line 3, in provider "aws":
   3:   version = "= 3.1"

Terraform 0.13 and earlier allowed provider version constraints inside the
provider configuration block, but that is now deprecated and will be removed
in a future version of Terraform. To silence this warning, move the provider
version constraint into the required_providers block.


Error: Invalid legacy provider address

This configuration or its associated state refers to the unqualified provider
"aws".

You must complete the Terraform 0.13 upgrade process before upgrading to later
versions.
```

### 文法が変わっているので書き換えてあげる

```provider.tf
provider "aws" {
  region  = local.region
  profile = "vamdemic"
}

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "= 3.36.0"
    }
  }
  backend "s3" {
    bucket  = "vamdemic-terraform"
    region  = "ap-northeast-1"
    profile = "terraformer"
    key     = "terraform/terraform.tfstate"
    encrypt = true
  }
}
```

### providerを書き換える
URLというか名称が変わっているらしいので

```
terraform state replace-provider registry.terraform.io/-/aws hashicorp/aws 
```

### 再度upgrade実行

```
terraform init -upgrade
```

### planして、リソースの差分などが出たら手動で直す

```
terraform plan
```

## v0.14.11→v0.15.3

.terraform-version

```.terraform-version
0.15.3
```

### upgrade実行

```
terraform init -upgrade
```

### planして、リソースの差分などが出たら手動で直す

```
terraform plan
```
sarのディスク情報をMackerelへメトリクス投稿する

★はじめに
sarの情報をMackerelに飛ばしたいなぁとおもったけど
ちょうどいいやり方が見つからないので自分で考えた

★参考
sadfを使ってjson形式でデータを取得する
https://miyakawataku.hatenablog.com/entry/20140202/1391330618

jsonデータを読み込む
https://qiita.com/kikuchiTakuya/items/53990fca06fb9ba1d8a7

pythonつかってカスタムメトリックをとばす
https://qiita.com/yhidetoshi/items/f0b20353714e3f1bd2f4

python上でコマンド実行
https://qiita.com/tdrk/items/9b23ad6a58ac4032bb3b

sarの項目の説明
https://tech-lab.sios.jp/archives/15817


★できました！
個人的に気を付けたポイントは↓↓（改善の余地がありすぎて泣ける…）
・sarの情報をjsonでとってくるためにsadfをつかったところ。
・それをpythonつかってうまいことjsonからデータ抜いてきたところ。
・うまいことutilの情報だけ抜くにあたっては泥臭くpythonを実行してどうやってとってくるかを確認した
・実行環境がCentOS7だったからかデフォルトで用意されていたpythonはpython2だったのでpython3の書き方にならないように気を付けた。

```:/opt/mackerel/getDiskInfo.py
#!/usr/bin/python
import subprocess
import json
import os
import time
import sys
from random import randint
from collections import defaultdict

def mkr_prepare():
    if (os.environ.get('MACKEREL_AGENT_PLUGIN_META') == '1'):
        metrics = [
            {
                            'name':'util',
                            'label':'util'
                    }
        ]
        meta['graphs']['sysstat.disk'] = {
                        'label': 'sysstat-disk',
                        'unit': 'float',
                        'metrics': metrics
        }
        print(json.dumps(meta))
        sys.exit(0)

if __name__ == '__main__':

    mkr_prepare()

    try:
        res = subprocess.check_output(['sadf','-T','-j','--','-d','1','1'])
        res_json = json.loads(res)
    except:
        print "Error."

    util_percent = res_json['sysstat']['hosts'][0]['statistics'][0]['disk'][0]['util-percent']

    print('\t'.join(['sysstat.disk.util', str(util_percent), str(time.time())]))
```

★試し実行

```
# python getDiskInfo.py
```

★config更新

```
# vi /etc/mackerel-agent/mackerel-agent.conf
```

![Image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416263/98f881f7-cbdc-64a0-b1be-ba233076a08f.png)

★結果がコチラ

![Image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416263/6368f8b4-cd04-8ed8-b8c6-529747805cc3.png)

★おわりに
次はもうちょっと気の利いたマカレル監視のアイデアを投稿できるようにしておこうと思いました。。。
Matplotlib定量比較-ヒストグラム

## ヒストグラムとは

ヒストグラムは変数の全体的分布を示すものです。
ヒストグラムを見て、どんな数値が多いか、少ないか、偏りがあるかないかを読み解きます。

ヒストグラムのX軸は階級（データを区切った空間）、Y軸は度数（データの数量）を表します。

## 簡単なヒストグラム

```python
import matplotlib.pyplot as plt

fig, ax = plt.subplots()
ax.hist(data01['colName'])
ax.hist(data02['colName'])

ax.set_xlabel('Data')
ax.set_ylabel('Frequency')

plt.show()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260307/a4ec4aef-31ff-c6fa-bd4e-52050396118e.png)

## 常用オプション

* label : 凡例のラベル（凡例を表示するためplt.legend()との併用が必要）
* bins : ビンの数またはビンの境界 例：bin=5 or bin=[100, 150, 200, 250, 300]
* histtype : ヒストグラムの種類 stepは透明

```python
import matplotlib.pyplot as plt

fig, ax = plt.subplots()

ax.hist(data01['colName'], label='Data01', bins=5, histtype='step')
ax.hist(data02['colName'], label='Data02', bins=5, histtype='step')

ax.set_xlabel("Data")
ax.set_ylabel("Frequency")

ax.legend()
plt.show()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260307/c64538a5-6165-8435-efe6-40abdc3a67fa.png)
[OutSystems]Associate Reactive Developerのサンプル問題について解説 1/4(#1-#5)

Associateは入門レベルの試験で、この試験の合格が他の試験の受験資格にもなっています。
Reactiveとついている通り、Reactive Web App開発の基礎的な知識を問われる試験。

試験問題は、
https://www.outsystems.com/learn/certifications/
の、「Associate Reactive Developer (OutSystems 11)」項目のリンク「Exam Details」でダウンロードできる資料から。解凍したら、Japaneseフォルダにあるファイル「Associate Reactive Developer Sample Exam - JP.pdf」を開いてください。

Associate Reactive Developerのサンプル問題について解説 1/4(#1-#5)
[Associate Reactive Developerのサンプル問題について解説 2/4(#6-#10)](https://qiita.com/jyunji_watanabe/items/95fc314f04c06d98449d)
[Associate Reactive Developerのサンプル問題について解説 3/4(#11-#15)](https://qiita.com/jyunji_watanabe/items/4452e8cabab795726cb0)
[Associate Reactive Developerのサンプル問題について解説 4/4(#16-#20)](https://qiita.com/jyunji_watanabe/items/1c7d603b5e66d0aa305a)

#1 データリレーション（多対多）
一般的なRDBの設計の知識で回答できる内容。

Entity間でリレーションを持つには、参照をする側のEntityに、参照される側のEntity Identifier型の属性を追加します。

上記の方法では参照する側：される側で多:1の関係になります。
Entity同士に多対多の関係を持つには、中間Entityを作り、双方のEntityのIdentifier型の属性を持たせればいいです。

つまり、この場合は、中間EntityにOrder Identifier型の属性とProduct Identifier型の属性を持たせます。
この場合1つのOrder（注文）中に複数のProduct（製品）が含まれ、1つのProductは複数のOrderに登場するという関係が表せる。

よって、このことを説明しているA（Order Identifier 型および Product Identifier 型の2つのアトリビュートを含む3つ目のエンティティを作成する。）が正解。

#2 エンティティとデータ型（識別子）
[エンティティ](https://success.outsystems.com/ja-jp/Documentation/11/Developing_an_Application/Use_Data/Data_Modeling/Entities)に記載されています。

エンティティ識別子は主キーのこと。
OutSystemsでは主キーは1属性限定です。複合キーは持てない（別途UniqueなIndexを作成することは可能）。

各選択肢を見ていきます。
A：×。デフォルトではLong Integerですが、変更可能です。
B：×。同じくデフォルトでは自動採番（属性のIs AutoNumber=Yes）ですが、オフにできます。
C：○
D：×。型や名前を変更することができます。

というわけで正解はC。

#3 Aggregate（Group By）
問題の図を見ると

- ShippingState：Group Of ...という記述があるので、これはGroup Byが効いている
- Count：Count of ...という記述があるので、この属性には、Group Byでまとめられたレコード数を返る

よって、Group Byがされているため、Aggregate返る属性は集計に使った2属性のみ。
選択肢A（2つの集約されたアトリビュート(ShippingStateおよびCount)。）が該当します。

なお、AggregateにGroup Byを適用する手順は、[グループ化されたデータから値を計算する](https://success.outsystems.com/ja-jp/Documentation/11/Developing_an_Application/Use_Data/Query_Data/Calculate_Values_from_Grouped_Data)にあります。

#4 Aggregate (JOIN)
図を見ると、

- OrderとEmployeeが「With or Without」で
- OrderとPriority/OrderStatusが「Only With」で

結合されています。
With or Without：結合の左側のEntityの全レコードを取得し、結合できるときだけ、右側のEntityをくっつけて返す（左外部結合）
Only With：左側のEntityのレコードと右側のEntityのレコードで結合できたレコードだけを返す（内部結合）

よって条件を読み替えると

- Employeeがあるかどうかに関わらず（0レコード以上と読み替えられる）
- Priorityがあり
- OrderStatusがある

Orderレコードを返すことになります。
これに合致するのは選択肢D（Priorityがあり、Employeeが0人以上のOrderを返す。）ですね。
一応各選択肢を見ると
A：EmployeeがあるOrderのみを返す、の部分が間違い。With or Withoutなので、なくてもよい
B：Order.StatusでOrderStatus.IdをOnly Withで結合しているため、StatusがないOrderは返りません
C：Employeeはなくてもよいので、Employeeがない＝0人の場合もOrderが返るため、「Employeeが1人以上の」の部分が間違い

#5 Aggregate (Group By)
「PriorityごとのOrderの数を返す」なので、

- （Priorityごとの）Priorityを一意に特定できる列にGroup Byする
- （Orderの数を返す）Orderの列にCountをつける

が必要です。
選択肢Bが該当しますね。
Ｍackerel公式のDice.rbをDice.pyで書き起こしてグラフ化する

★はじめに
マカレル公式で紹介してくれるメトリクスの投稿はruby製なのでそのままだとちょっと…と思っていたら
python風にアレンジして見事成功しているサイトがあったのでそれを参考にしたらうまくいったので記念に残す。

★お手本
https://sky-joker.tech/2017/04/23/mackerel%E3%81%A7%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0%E3%83%A1%E3%83%88%E3%83%AA%E3%83%83%E3%82%AF%E3%82%92%E6%8A%95%E7%A8%BF%E3%81%97%E3%81%A6%E3%81%BF%E3%81%9F/

★手順
①python3のインストール ←なくても作れる（CentOS7はpython2がデフォルトで入っているから）
②dice.pyの作成
③エージェント修正
④グラフを確認

★①python3のインストール
[python使ってMackerelのメトリクスを投稿する（いろいろがんばるも失敗…）]の末尾に書いたのでそれを見て－

★②dice.pyの作成
↓↓のコードはpython2でもうごく。

・/opt/mackerel/dice.py

```
#!/usr/bin/python
import json
import os
import time
import sys
from random import randint
from collections import defaultdict

def multi_dimension_dict(dimension, callable_obj=int):
    nodes = defaultdict(callable_obj)
    for i in range(dimension-1):
        p = nodes.copy()
        nodes = defaultdict(lambda : defaultdict(p.default_factory))
    return nodes

if(os.environ.get('MACKEREL_AGENT_PLUGIN_META') == '1'):
    meta = multi_dimension_dict(2)
    metrics = [{'name':'d6','label':'Die(d6)'},{'name':'d20','label':'Die(20)'}]
    meta['graphs']['super.pdice'] = {'label': 'My pDice', 'unit': 'integer', 'metrics': metrics}
    print('# mackerel-agent-plugin')
    print(json.dumps(meta))
    sys.exit(0)

print('\t'.join(['super.pdice.d6', str(randint(1,6)), str(time.time())]))
print('\t'.join(['super.pdice.d20', str(randint(1,20)), str(time.time())]))
```

動作確認。

```
# python /opt/mackerel/dice.py
```

mackerel-agentではTSV形式で表示してることがわかる。

![Image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416263/6c909b5a-0f1d-15d2-7b8e-d081a6d718d3.png)


dice.pyできたら

```
# chmod +x dice.py　←これはしなくてもいい。
```

![Image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416263/019ee668-1341-daaf-d8fd-0d5d37193c70.png)


★③エージェント修正

```
# vi /etc/mackerel-agent/mackerel-agent.conf
```

![Image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416263/c7fdd0a4-d2e1-1988-0986-a0f041ab8848.png)


mackerel-agentのコンフィグチェック

```
# mackerel-agent configtest
```

![Image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416263/0ebc6457-51da-7bca-74cd-36553294df4d.png)


mackerel-agent再起動

```
# systemctl restart mackerel-agent.service
```

★④グラフを確認
できてるーーー、しかもやりたかったこと全部できてるーー

![Image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416263/db4db0ad-ab25-9344-0596-093b07f173ba.png)


～おしまい～
【Rust】３種類のメモリ空間

[Tour of Rust](https://tourofrust.com/00_ja.html)を進めていての備忘録。
Rustでは、データを保持するためメモリ空間をに3種類持つ。

##1. データメモリ
固定長もしくは スタティック (例: プログラムのライフサイクルで常に存在するもの)なデータ。 
プログラム内の文字列(例: ‘Hello World’)のキャラクタは読み取りにしか使えないため、この領域に入る。 コンパイラはこうしたデータに対してチューニングをしており、メモリ上の位置はすでに知られていてかつ固定であるため、非常に速く使うことができる。
    
##2. スタックメモリ
関数内で宣言された変数。 
関数が呼び出されている間は、メモリ上の位置は変更されることがないため、コンパイラからするとチューニングができるので、スタックメモリも非常に速くデータにアクセスできる。

##3. ヒープメモリ
プログラムの実行時に作られるデータ。 
このメモリにあるデータは追加、移動、削除、サイズの調節などの操作が許されている。
動的であるため、遅いと思われがちだが、これによりメモリの使い方に柔軟性を生み出すことができる。

- アロケーション(allocation) = データをヒープメモリに入れること
- ディアロケーション(deallocation) = データをヒープメモリから削除すること
Google Natural Language API利用時のクレデンシャルを文字列で指定したい

## 目的と経緯

- AWS Lambdaで [Cloud Natural Language](https://cloud.google.com/natural-language) を[Python用SDK](https://github.com/googleapis/python-language) で操作することが目的です
- [Getting started with authentication](https://cloud.google.com/docs/authentication/getting-started) によると環境変数 `GOOGLE_APPLICATION_CREDENTIALS` へサービスアカウントJSONファイルパスを指定すれば良いと書いてあり、当然その通りにすれば動作しました
- この方法はファイルを読み込む前提であり、AWS LambdaやGoogle以外のコンテナ系環境で実行する場合は実行環境内にファイルを設置する必要があります
- デプロイファイルセットにAPIアクセス用のクレデンシャルファイルを含めるのは少し躊躇するところです
- 今回はAWSなので パラメータストア(AWS Systems Manager)へクレデンシャル内容を保持し、実行時に取得することにしました
- パラメータストアから取得した時点で文字列は変数に保持できているので、それをそのまま使ってくれよ、というのが自然かなと思うのですが現時点のSDK(version2.0.0)にはそのインターフェイスは用意されていないようです
- パラメータストアから取得した内容（JSON文字列）をテンポラリファイルへ書き出し、そのパスを環境変数 `GOOGLE_APPLICATION_CREDENTIALS` へセットしてSDK利用する、という方法でも動作すると思いましたが、それもいかにも無駄かなと感じます
    - ※用意されたインターフェイスに従うという意味では間違いとは思っていません
- そこで、ファイルを介さずに直接クレデンシャルJSONを利用する方法としたので、メモと何かの参考になればと記録します


## コード


### クライアントオブジェクトを取得する

- google.oauth2.service_account.Credentialsのクラスメソッド `from_service_account_info()` を引っ張り出し、クレデンシャルをロードしています
- 要は `LanguageServiceClient()` のcredentialsパラメータを指定すれば良いのです。指定内容が本記事で言いたいことすべてです

 
```python
from google.cloud.language_v1 import LanguageServiceClient
from google.oauth2.service_account import Credentials

def get_language_client(credential: dict) -> LanguageServiceClient:
    return LanguageServiceClient(
        credentials=Credentials.from_service_account_info(credential))
```

## 利用例

### 実行コード

```python
import json
from google.cloud import language_v1

# 省略しますがサービスアカウントJSONファイルの内容そのままをセット（実際はパラメータストアなどから取得する想定）
credential_json = '{\n  "type": "service_account",\n  "project_id": "...",\n  ....'

# 作成したメソッドでクライアントオブジェクトを取得
client = get_language_client(json.loads(credential_json))

# エンティティ分析を呼び出して動作を確認
text = '東京の夏は暑い'
response = client.analyze_entities(
    document=language_v1.Document(
        content=text,
        type_=language_v1.Document.Type.PLAIN_TEXT),
    encoding_type=language_v1.EncodingType.UTF8)
for entity in response.entities:
    print('{}\n{}\n{}\n{}\n'.format(
        '='*20,
        entity.name,
        entity.type_.name,
        entity.metadata))
```

### 実行結果

```
====================
東京
LOCATION
{'wikipedia_url': 'https://de.wikipedia.org/wiki/Tokio', 'mid': '/g/12lnhn10f'}

====================
夏
OTHER
{}
```


## 最後に

現時点でv2.0.0がリリースされていますが、未リリースのgithubコード上ではメソッド追加されているようです
このバージョンがリリースされれば `LanguageServiceClient.from_service_account_info(key_dict)` を使えるようになると思われます

https://github.com/googleapis/python-language/blob/master/google/cloud/language_v1/services/language_service/client.py#L113

※見返したところ、冒頭の「目的と経緯」が長いポエム状態でした。夜中に書いたのですみません。
DockerでLinux に wxPythonをインストールする

これして
```
sudo apt install libsdl2-2.0-0 libsdl2-dev
```

これする
```
pip install -U -f https://extras.wxpython.org/wxPython4/extras/linux/gtk3/ubuntu-20.04 wxPython
```

※ubuntuのバージョンは要確認

## だけでは動かなかった

これをトライしてみる

https://www.pixelstech.net/article/1599647177-Problem-and-Solution-for-Installing-wxPython-on-Ubuntu-20-04
pandasのdataframeで和暦を西暦に変換する

# はじめに
巷には未だに和暦のcsvデータが溢れています。
和暦のcsvデータをreadして、いい感じに西暦なdataframeにしたいと思っている人への備忘です。
（parserを修正しました）

# 結論

### 整形前

```csv:input.csv
"年月日","メモ"
R03.05.15,"メモ1"
R03.06.04,"メモ2"
```

### 整形後

```
        date memo
0 2021-05-15  メモ1
1 2021-06-04  メモ2
```

### コード

```python
import pandas as pd
from datetime import datetime


def read_wareki_csv(csv_filename):
    df = pd.read_csv(csv_filename, header=None, names=['date', 'memo'], skiprows=1, parse_dates=[0], date_parser=wareki_parser)
    return df


def wareki_parser(date):
    wareki = {
            "R":2018,
            "H":1988
            }
    date = str(int(date[1:3])+wareki[date[0]])+date[3:9]
    dt = datetime.strptime(date, '%Y.%m.%d')

    return dt


if __name__ == '__main__':
    df = read_wareki_csv("./input.csv")
    print(df)
```


# 解説
## read_csv

```python
def read_wareki_csv(csv_filename):
    df = pd.read_csv(csv_filename, header=None, names=['date', 'memo'], skiprows=1, parse_dates=[0], date_parser=wareki_parser)
    return df
```

pandasのread_csvには、便利なオプションとして、指定のcolumnをdatetime型で読み込む`parse_dates`と、`parse_dates`で指定したcolumnを処理するparserを指定する`date_parser`があります。

`parse_dates`にはlistとかdictとかを指定しましょう。ここを`parse_dates=0`とかにすると、`TypeError: Only booleans, lists, and dictionaries are accepted for the 'parse_dates' parameter`と怒られます。

`date_parser`には自作関数を指定します。この自作関数の中で和暦→西暦変換を書いてあげましょう。
今回は、令和と平成の両方に対応する感じでやります。

## parser（修正）
当初、`datetime.strptime(date, 'R%y.%m.%d')`という感じで年の下2桁をそのまま読み込んでから年数を加算する方式で書いていましたが、閏年でエラーとなるとご指摘をいただいたため、普通に文字列操作でやることにしました。。そりゃそうですよね・・・。

```python
def wareki_parser(date):
    wareki = {
            "R":2018,
            "H":1988
            }
    date = str(int(date[1:3])+wareki[date[0]])+date[3:9]
    dt = datetime.strptime(date, '%Y.%m.%d')
    return dt
```

なお、今回は令和と平成のみにしましたが、同様に昭和等も対応可能です。
皆様、素敵な和暦データ処理をお楽しみください。
グラフを描画してExcelに貼り付ける

```python:
import tkinter as tk 
import tkinter.filedialog as fl 
import tkinter.messagebox as mb 
import matplotlib.pyplot as plt
import openpyxl as px
import os
import pandas as pd

root = tk.Tk()

#ファイルダイアログを表示するディレクトリ
INI_DIR = "D:/Python/Hello"

#GUIのボタンを押した時の処理
def get(*args):
    #CSVファイルを選択する ※複数選択可
    filetype = [('excel file', '*.xlsx'), ("csv file",".csv"), ('excel file', '*.xls')]
    path_list = fl.askopenfilenames(initialdir=INI_DIR,
                                    filetypes=filetype,
                                    title="select file")

    #保存用Excelファイル名を指定する
    typ = [("Excel", ".xlsx")]
    savefile = fl.asksaveasfilename(title="保存ファイル名を指定",
                                    filetypes=typ,
                                    initialdir=INI_DIR)

    #書き込み＆グラフ描画用のExcelを新規作成
    wb = px.Workbook()

    #Excel内に新しいシートを作成してファイル名をつける
    wb.create_sheet(index=0, title='グラフ')
    ws = wb['グラフ']
    #自動で作成される不要なシートであるSheetを削除
    wb.remove(wb['Sheet'])

    # 読み取った複数のCSVファイルを1つのExcelファイルにまとめる
    for i, path in enumerate(path_list):
        read_data = pd.read_excel(path, skiprows=1)

        #データ数、系列数を変数に格納
        data_num, series_num = read_data.shape

        #ファイル名をシート名に設定
        filename = os.path.basename(path)
        basename = os.path.splitext(filename)[0]

        #x軸とするデータ
        x_values = read_data.iloc[:,0]

        #グラフの作成
        fig = plt.figure()
        ax = fig.add_subplot(1,1,1)
        #カラーマップを定義
        cmap = plt.get_cmap("tab10")
        for j in range(1, series_num):
            #y軸とするデータ
            y_values = read_data.iloc[:,j]
            ax.plot(x_values, y_values, label=basename, color=cmap(j))
  
        #グラフを保存
        image_file_path = os.path.dirname(savefile)+"\\"+basename+".png"
        plt.savefig(image_file_path)

        #グラフのメモリ解放
        plt.clf()
        plt.close()

        # 画像を貼り付ける位置をExcel形式で表す(列のアルファベット+行の番号)
        inColLetter = px.utils.get_column_letter(1) #エクセルの1列目（A列）を指定
        inCellLetter = inColLetter + str(28*(i)+1) #各ファイルのデータのグラフを28行間隔で貼り付ける

        # グラフの画像読み出し
        img = px.drawing.image.Image(image_file_path)

        #シートにグラフを追加
        ws.add_image(img, inCellLetter)

    #Excelデータを保存
    wb.save(savefile + ".xlsx")

    #処理が完了したことをユーザーに知らせる
    mb.showinfo("確認","Excelファイルの作成が完了しました")
    message["text"] = "処理が完了しました"

message = tk.Label(root,text="ファイルを選択してください", width=30)
message.grid(row=0, column=0)

button = tk.Button(text="開く", command=get)
button.grid(row=0, column=1)

root.mainloop()
```
nuxt.jsを立ち上げた

#nuxt.jsの環境構築

```
$ npx create-nuxt-app nuxt-app
```


ですぐ環構築ができた！
＊node.jsが入っている前提。

##次にTailwind CSSを導入してみた。

```
$npx tailwindcss init
```
でtailwind.config.jsを作成。

```
purge: [
    './components/**/*.{vue,js}',
    './layouts/**/*.vue',
    './pages/**/*.vue',
    './plugins/**/*.{js,ts}',
    './nuxt.config.{js,ts}',
  ],
```
tailwind.config.jsに上記を記載。

そしてassetsの中にcss/tailwind.cssを作成し下記を記述.


```
@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';
```

これでもう一度$npm run devしたらTailwindが使えた！！
技術メモ：Lightningコンポーネント（Aura）のクイックアクションのキャンセルボタン非表示

# ヘッダとキャンセルボタンが表示されている
開発者コンソールに自動作成の場合、クイックアクションに追加して、ヘッダとキャンセルボタンが表示されている
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/0f1c6f8b-0df6-a65f-b283-d9eb4fdfdc96.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/fe7cd831-1c87-46c2-df4a-7ad206056507.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/61833633-63ff-67fd-d183-c6e60d798176.png)

## 回避方法
lightningQuickAction⇒lightningQuickActionWithoutHeaderに変更
```<aura:component implements="force:lightningQuickActionWithoutHeader">```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424429/1a005d07-e4ad-a6a7-d958-a14815a7b67e.png)
Facebook Graph API をJava(RestFb)で実行する

# はじめに

社内で提供しているWebAppがFacebookGraphAPIを利用していた。  
FacebookGraphAPIにはバージョンの概念があって、3ヶ月周期ぐらいでバージョンが上がっていく。  
利用期日が迫ったタイミングでFacebook周りの実装をリファクタリングした。
その際にAPIクライアントを [restfb](https://restfb.com/) を利用するようにした。

# restfb

Java製のFacebookGraphAPI用のAPIクライアント。
月次リリースを行なっているようで、更新頻度高め。(2021年06月現在

初期導入したバージョンは `2.25.0`　。
その後、保守で `3.15.0` まで引き上げた。

利用するにあたりの利点としては、APIから返却されるjsonをマッピングするレスポンスクラスが用意されていること。

## 導入方法

下記らへんを参考に実装した。

- [restfb-examples(サンプルコード)](https://github.com/restfb/restfb-examples)
- [cookbook](https://restfb.com/cookbook/)
- [documentation](https://restfb.com/documentation/)

## ライブラリアップデート

2.X系から3.X系にあげたが、大きく変更があった箇所は記憶にない。。。

# おわりに

書き味やコードサンプルは特に記載しませんが、
公式リファレンスが整頓されすぎて、導入の敷居はすごく低いです。

JavaアプリケーションでFacebook連携する際は、restfbの導入を検討して欲しいです。
RailsでインポートするCSVにBOMをつけたら列名に一致するカラムの値を取り出せなくなった

気づけば簡単な話なのですが、RailsでCSVインポート機能を作っている時にサンプルCSVがもしエクセルで開いても文字化けしないようにとBOMをつけたら、読み込む時に一致するカラムの値を取り出せなくなったので記録しておこうと思います。

## TL;DR
BOMがついている時にCSVの値をカラム名で指定してしまうと列名の最初の文字にBOM(ZERO WIDTH NO-BREAK SPACE, 文字コード65279)が入ってしまい、読み込む際に列名を指定しても適切に取得できなくなります。
見えないので最初の文字を`String#ord`メソッドなどで比較しないと気づきにくいです。
解決方法は追記に書いてあります。


## 本文

下記がBOMをつけてダウンロードするようにしたサンプルCSVの`application_controller.rb`
です。
他のコントローラでこのコントローラを継承して、rowsメソッドを実装する形になります。

```ruby:controllers/admin/csv/sample/application_controller.rb
class Admin::Csv::Sample::ApplicationController < Admin::Csv::ApplicationController
  def show
    respond_to do |format|
      format.csv do
        send_data create_csv,
                  type: :csv,
                  filename: "sample_#{controller_name}.csv"
      end
    end
  end

  protected
  # 子のコントローラでオーバーライドを強制
  def rows
    raise NotImplementedError.new("You must implement #{self.class}##{__method__}")
  end

  def create_csv
    bom = %w[EF BB BF].map { |e| e.hex.chr }.join
    CSV.generate(bom) do |csv|
      rows.each do |row|
        csv << row
      end
    end
  end
end

```


下記は例として`sports_controller.rb`

```ruby:controllers/admin/csv/sample/sports_controller.rb
class Admin::Csv::Sample::SportsController < Admin::Csv::Sample::ApplicationController
  private

  def rows
    [
      ["name"],
      ["バスケットボール"],
    ]
  end
end
```

このようにしてダウンロードしたCSVをモデルに記述したメソッドでインポートしようとします。

```ruby:models/sport.rb
class Sport < ApplicationRecord
  class << self
    def import(file)
      CSV.foreach(file.path, headers: true) do |row|
        record = find_by(id: row["id"]) || new
        record.attributes = row.to_hash.slice(*updatable_attributes)
        record.save
      end
    end

    def updatable_attributes
      ["name"]
    end
  end
end
```


```ruby:controllers/admin/csv/sports_controller.rb
class Admin::Csv::SportsController < Admin::Csv::ApplicationController
  def new
  end

  def create
    Sport.import(params[:file])
    flash[:notice] = t('action.imported')
    redirect_to admin_sports_url
  end
end
```

着目すべきは以下の行です。

```ruby
record.attributes = row.to_hash.slice(*updatable_attributes)
```

ここではモデルのインスタンスの各フィールドに許可された値を挿入しています。
`sport.rb`で許可された値は`name`のみなので、`{'name': 'バスケットボール'}`のような値が入るはずですが、BOMがついていると`row.to_hash`で返ってくるkeyの部分がBOM付きの`name`となり`updatable_attributes`の`name`という文字列と一致しません。

これによってCSVインポートしても値が更新されないという現象が発生してしまいます。
しかもぱっと見は同じ文字列に見えるのでなかなか気づきにくいです。
これを解決するにはsampleのCSVにBOMをつけないか、列名ではなく列の順序などで値を取得するなどの方法が考えられるかと思います。
BOM付きのCSVをインポートする場合はお気をつけください。


## 追記
@mcfishさんのご指摘によりCSVクラスの特異メソッド`foreach`の引数`encoding`にBOMを考慮した`'BOM|UTF-8'`を設定すればBOM付きのCSVでも問題なくインポートできました。
ご指摘頂きありがとうございます。

```ruby
CSV.foreach(file.path, headers: true, endoging: 'BOM|UTF-8') do |row|
```
Linux パーミッション権限について

#パーミッション権限の確認と変更
だいぶ慣れてきたが、ふと分からなくなることがあるので書き留めておく。

##パーミッション権限の確認

```
$ls -l
```

上記コマンドを押すと以下のような一覧が出てくる。

```
-rwxr--r--  1 user group      9  12月 31 00:00 hoge.txt
drwxr-xr-x  6 user group      1  12月 31 00:00 ダウンロード
```

##読み解き方

最初の１文字目はファイル種別を示している。
`-	ファイル`
`d	ディレクトリ`
`l	シンボリックリンク`

※**シンボリックリンク**
fileA シンボリックリンクＡ　があるとする。
シンボリックリンクAにアクセスするとfileAが開く。
シンボリックリンクAを消してもfileAは消えない。
windowsでいうところのショートカットみたいなもの。

2文字目から4文字目はファイルの所有者に対する権限を表し、
5文字目から7文字目はファイルの所有グループに対する権限を表し、
8文字目から10文字目はその他に対する権限を表す。

先ほどのものをもう一度表示すると

```
-rwxr--r--  1 user group      9  12月 31 00:00 hoge.txt
drwxr-xr-x  6 user group      1  12月 31 00:00 ダウンロード
```

`-rwxr--r--`は、
「ファイル種別」が「ファイル」
「所有者」は「読み取り」と「書き込み」と「実行」の権限を持ち
「所有グループ」は「読み取り」の権限を持ち
「その他」に「読み取り」の権限があることを示している。

`drwxr-xr-x`は、
「ファイル種別」が「ディレクトリ」であり、
「所有者」に「読み取り」と「書き込み」と「実行」の権限があり、
「所有グループ」に「読み取り」と「実行」の権限があり、
「その他」に「読み取り」と「実行」の権限があることを示している。

ちなみにそれぞれ
`所有者（Owner）	ファイル/ディレクトリの所有者、本人のこと`
`所有グループ（Group）	同じサーバーを利用できるユーザ全体`
`その他（Other）	その他全て、第三者のこと`
を指してます

#権限の変更
パーミッションの権限変更にはchmodコマンドを使う。

```
chmod 数字（それぞれの足し算） 対象ファイル名
```

| 数字 | A | 権限 |
|:-----------|------------:|:------------:|
|4| r      | 読み取り         |
| 2     | w   | 書き込み      |
|1       | x     | 実行       |


ここでいう実行ってのはそのファイル、プログラムを動かしていいかどうかって事です。

```
$chmod 777hoge.txt
-$ ls -l
-rwxrwxrwx  1 user group      9  1月 1 00:00 hoge.txt
```

777だと全員OKってことですね

```
$ chmod 764 hoge.txt
$ ls -l
-rwxrw-r--  1 user group      9  1月 1 00:00 hoge.txt
```

それぞれ数字の7が最大数と考えて足算して考えれば良いわけですね。
↓アルファベットでもできる



```
chmod g+x <ファイルorディレクトリ>
```


「g+x」は、g（グループ）に x（実行権限）を +（加える）という意味になる
逆に権限をなくす場合は、「g-x」とすれば良い、
既存のものに変更を加えたりするときはこっちにが使いやすい！

#所有者の変更
`chown`　を使う

```
chown <[所有者]or[所有者:グループ]> <ファイルorディレクトリ>
```

dataフォルダの所有者をsatouに変更する

```
chown satou data
dataフォルダの所有者をsatouにグループをstaffにする
```

chown satou:staff data

それぞれ
**ディレクトリごと権限を変更したい場合**
-Rをつければ良い！
index.html.erbに全ての投稿を表示させる方法 Rails

ホロライブの桃鈴ねねさんが大好きです。
なので、Webページに全てのアーカイブを表示したいと思います。
※あらかじめテーブルに全てのアーカイブ情報を取得してます。

```app/controllers/archive_controller.rb
class ArchiveController < ApplicationController
  def index
    @archive = Archive.all
  end
end
```

これで@archiveにあらかじめarchivesテーブルに登録しておいた情報を格納します。

```app/views/archive/index.html.erb
<%= render partial: "archive" , collection: @archive %>
```

renderメソッドを使うことで、@archiveというインスタンス変数を_archive.html.erbでも使用できます。
更にオプションでcollectionを使用することで、@archiveに格納されている全ての情報を使用できます。

```app/views/archive/_archive.html.erb
<div class="card">
  <%= link_to "#{archive.archiveurl}" do %>
    <%= image_tag (archive.archiveimg) %>
  <% end %>
</div>
```
この辺のビューは調整が必要ですが、簡単にやればこんな感じ。
archiveimgにはサムネイルの画像URLが格納されています。
archiveurlには動画のURLが格納されています。

ポイントはrenderメソッドを使用することと、collectionというオプションを使用すること、partialを使用することで、一つのファイルの記述量を減らすことが出来ます。
とりあえずこれで、動画情報を全て表示する、という目標が達成できました。
【Bootstamp】複数の設問にラジオボタンで回答いただく場合の注意点

# はじめに
<!-- 発端や概要を記載 -->

今回は下記の画像のように、
ひとつのページで複数の設問にラジオボタンで答えていただくページを作成する際に
Bootstrapのラジオボタンを使用する場合の注意点について記述させていただきます。
![_Users_nishimotokenta_program_Work,LiveShift_%E3%83%A6%E3%83%BC%E3%82%B5%E3%82%99%E3%83%BC%E7%99%BB%E9%8C%B2%E3%81%AE%E3%83%92%E3%82%99%E3%83%A5%E3%83%BC_test.html (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1623096/8be3b4be-a0cf-e6a0-adb7-5ddbff6a7196.png)




Bootstrapのラジオボタンは下記URLへ飛んでいだたければ使用できます！
（ https://getbootstrap.jp/docs/5.0/forms/checks-radios/ ）

また、Bootstrapの使い方についてご不明な方は、
別の記事をご覧いらだければと思います。


# 開発環境
Bootstamp バージョン５
Ruby on Rails バージョン2.6.5

<!-- 各チャプター -->
# ラジオボタンのはめ込み
Bootstrapのラジオボタンのページを飛んでいただき、下記の記述をラジオボタンもはめ込みたいところに記述します。
（ ラジオボタンのURL : https://getbootstrap.jp/docs/5.0/forms/checks-radios/ ）

```html
<div class="form-check">
  <input class="form-check-input" type="radio" name="flexRadioDefault" id="flexRadioDefault1">
  <label class="form-check-label" for="flexRadioDefault1">
    Default radio
  </label>
</div>
<div class="form-check">
  <input class="form-check-input" type="radio" name="flexRadioDefault" id="flexRadioDefault2" checked>
  <label class="form-check-label" for="flexRadioDefault2">
    Default checked radio
  </label>
</div>
```

これでこのようなラジオボタン設置が可能です。
![Default checkbox.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1623096/c51a31ef-b9bf-3cc5-314c-4812b1e47510.png)


# ラジオボタンをひとつのページで複数設定する場合

先程のコードを記述することでラジオボタンの設置は可能です。
ですが、ひとつにページで複数のラジオボタンを設置する場合は、
そのまま二つ目以降をそのまま記述してしまうと問題が発生します。

その問題とは、1ページで選択できるラジオボタンがひとつだけになってしまうという状況が起こります。
例）下記画像の場合、、、
設問１で回答Dと答え、設問２で回答Bを選択したとき、
設問１の回答Dの回答は消えてしまい、設問２の回答のみが残ってしまいます。

![_Users_nishimotokenta_program_Work,LiveShift_%E3%83%A6%E3%83%BC%E3%82%B5%E3%82%99%E3%83%BC%E7%99%BB%E9%8C%B2%E3%81%AE%E3%83%92%E3%82%99%E3%83%A5%E3%83%BC_test.html (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1623096/8be3b4be-a0cf-e6a0-adb7-5ddbff6a7196.png)


# 問題を解決する方法
こちらの問題を解決する方法は、２つ目以降のラジオボタンを設置する際に、
``<input>タグのname属性の名前を変更します！
``


```html
設問１
<div class="form-check">
  <input class="form-check-input" type="radio" name="flexRadioDefault" id="flexRadioDefault1">
  <label class="form-check-label" for="flexRadioDefault1">
    Default radio
  </label>
</div>
<div class="form-check">
  <input class="form-check-input" type="radio" name="flexRadioDefault" id="flexRadioDefault2" checked>
  <label class="form-check-label" for="flexRadioDefault2">
    Default checked radio
  </label>
</div>

設問２では

<div class="form-check">
  <input class="form-check-input" type="radio" name="flexRadioDefault-1" ※ここを変える id="flexRadioDefault1">
  <label class="form-check-label" for="flexRadioDefault1">
    Default radio
  </label>
</div>
<div class="form-check">
  <input class="form-check-input" type="radio" name="flexRadioDefault-1" ※ここを変える　id="flexRadioDefault2" checked>
  <label class="form-check-label" for="flexRadioDefault2">
    Default checked radio
  </label>
</div>
```

こうすることで、設問の数だけラジオボタンを選択することが可能となります！
rails6 でwebpackerを使ってBootstrapが導入できなかった時にやったこと


ターミナル上で下記コマンドを入力
Bootstrapが関係しているパッケージがpopper　ｖ２のため？

現状このコマンドで解決できる程度の理解しかないので、
コメントで教えていただけるとありがたいです。


<pre>yarn remove popper.js 
yarn add @popperjs/core</pre>
https://qiita.com/kazutosato/items/d47b7705ee545de4cb1a
【Swift】MoyaでエンドポイントのURLを取得する

# どういうことか

例えばAPIを叩いてみたはいいけど `404` が返ってくるとかで検証したい。
叩く場所は任意。

```swift
provider.request(.articles) { (result) in
    switch result {
    
    case .success(let response):
        print("コレ", response.request?.url)

// 以下略
```

おわり(´・ω・｀)
gitでマージ出来ない


There isn’t anything to compare.とかerror: failed to push some refsとか出る。
私の場合、AWSで使っていたリポジトリから、herokuに移したくて、commitの履歴が違うよ～と言われていた模様。


これであっているか分からないけど出来た。

```condole:コンソール
git checkout hoge
git branch master hoge -f   
git checkout master
git push origin master -f
```

hogeは何かしらのブランチ名。
Wio Terminalで静的コンフィギュレーションしたTOPPERS/ASPを動かす

# はじめに

[Wio Terminal](https://wiki.seeedstudio.com/jp/Wio-Terminal-Getting-Started/)用のTOPPERS/ASPカーネルターゲット依存部を作成した。
TOPPERSプロジェクトの[Contributed Software](http://dev.toppers.jp/svn/contrib/asp_wio_terminal/)で公開している。

このターゲット依存部は既に[ここ](https://github.com/exshonda/Arduino_TOPPERS_ASP)で公開されているが、
今回は静的コンフィギュレーションに対応させたものである。

組込みは静的コンフィギュレーションでないと落ち着かない、という方のためになれば幸いである。

# 開発環境

- Mac OS Catalina
- arm-none-eabi-gcc 9.2.1
- Wio Terminal
- USBシリアル変換器

# ビルド手順
## ファイルのダウンロードと展開

TOPPERSのリリースパッケージは簡易、個別とあり、今回はすべて個別のパッケージを使用する。
以下4つをダウンロードして1つのディレクトリにまとめる。

- [TOPPERS/ASP ターゲット非依存部 1.9.3](https://toppers.jp/download.cgi/asp-1.9.3.tar.gz)
- [TOPPERS/ASP Coretex-M4 ターゲット依存部 1.9.7](https://toppers.jp/download.cgi/asp_arch_arm_m4_gcc-1.9.7.tar.gz)
- [TOPPERS/ASP Wio Terminal ターゲット依存部](http://dev.toppers.jp/svn/contrib/asp_wio_terminal/)
- [TOPPERS新世代カーネル用コンフィギュレータ 1.9.5](https://toppers.jp/download.cgi/cfg-osx-static-1_9_5.tar.gz)

    Macバイナリがあるのが1つ前のバージョンだった。

```sh
% tar xvf asp-1.9.3.tar.gz
% tar xvf asp_arch_arm_m4_gcc-1.9.7.tar.gz
% tar xvf cfg-osx-static-1_9_5.tar.gz
% mkdir -p asp/cfg/cfg
% mv cfg asp/cfg/cfg
% cd asp/target
% svn co http://dev.toppers.jp/svn/contrib/asp_wio_terminal/trunk/target/samd51_gcc
```
## configure

sample1のプロジェクトを作る。aspのトップ階層に移動して、

```sh
% mkdir sample1
% cf sample1
% ../configure -T samd51_gcc
configure: Generating Makefile from ../sample/Makefile.
configure: Generating sample1.c from ../sample/sample1.c.
configure: Generating sample1.h from ../sample/sample1.h.
configure: Generating sample1.cfg from ../sample/sample1.cfg.
```

## Makefileの編集

出力形式をbinにするためにMakefileを少し編集する。
217行目と218行目を修正。

```makefile
#
#  ターゲットファイル（複数を同時に選択してはならない）
#
#all: $(OBJFILE)
all: $(OBJNAME).bin
#all: $(OBJNAME).srec
```


## ビルド

依存関係を構築する。cfgは安全でないと言われるが、Macの設定で許可する。

```sh
% make depend
```

ビルドする。

```sh
make
```

# 書き込み

書き込みにはRust環境で使えるhf2を使っている。
bossacなど他のコマンドでも差し支えない。

```
% hf2 flash -f asp.bin -a 0x4000
no vid/pid provided..
found Ok(Some("Seeed Studio")) Ok(Some("Wio Terminal"))
Success
```

# シリアルでつなぐ

シリアルの設定は115200bps、パリティなし、8bit、ストップビット1bit。
少し化けているのは現在調査中。

![スクリーンショット 2021-06-10 22.56.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1593056/69bf8c81-14ef-b21a-aa11-f03d8aa7b133.png)
C#・自分用のメモ書き

C#の標準入力を受け取り、その文字列を配列に格納する方法を探すのに時間がかかっているので備忘録として記す

```csharp
using System;
class Program
{
    static void Main()
    {
        var line = Console.ReadLine();

        char[] line1 = line.ToCharArray();
        foreach (char a in line1)
        {
            Console.WriteLine(a);
        }

    }
}
```

標準入力で文字列を受け取った後にToCharArray()メソッドを用いてchar型の1次元配列に変換してる

foreach文にて１要素ずつ表示しているだけ。


てか、Javaだとfor文でforeach書くからC#にforeach文あるの感動



因みに、区切り文字があれば、Split('区切り文字')を用いてstring[]配列に格納もできる
Xboxコントローラをラズパイ4にワイヤレス接続したときの苦労話

## Xboxコントローラをラズパイ4にワイヤレス接続したときの苦労話

ネットで検索してみると、同じ悩みで困っている人たちを見かけ、対策方法も出回っているのになぜか同じ方法で解決しなかったので、自分のやった対策手順をメモ書きしておく

## 実行環境

- [Raspberry Pi 4 Model B/4GB](https://jp.rs-online.com/web/generalDisplay.html?id=raspberrypi)

    - カーネル：5.10.17-v7l+
    - BlueZ: 5.50
    
- [Xbox ワイヤレス コントローラー](https://www.xbox.com/ja-JP/accessories/controllers/xbox-wireless-controller)

## 現象

### 現象1: BluetoothからXbox Controllerが見えない

Xboxコントローラをペアリングモードにしてもラズパイ上から確認できない。
※以下の状態
![Animation1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171097/eead4055-4f24-17f6-21a6-70551aad10a1.gif)

### 対策１: `xpadneo`をインストールする

[xpadneo](https://github.com/atar-axis/xpadneo)をインストールする

```bash
$ sudo apt-get install dkms raspberrypi-kernel-headers
$ git clone https://github.com/atar-axis/xpadneo
$ cd xpadneo
$ sudo ./install.sh
$ sudo modprob hid-xpadneo
$ sudo reboot
```

その後、再起動すると表示されるようになる

### 現象2: ペアリングしてみたらBluezが停止する

ペアリングを行った後、Xboxコントローラを接続しようとBluetoothアイコンをクリックしても何も反応しなくなる

### 対策2: `Bluez`をアップデートする

[www.bluez.org](http://www.bluez.org/)から最新のリリースを確認してインストールする
※今回は5.58を使用する

```bash
$ wget http://www.kernel.org/pub/linux/bluetooth/bluez-5.58.tar.xz
$ tar xvf bluez-5.58.tar.xz
$ cd bluez-5.58
# 必要パッケージをインストールする
$ sudo apt install libglib2.0-dev libdbus-1-dev libical-dev libudev-dev libreadline-dev
$ ./configure --prefix=/usr --mandir=/usr/share/man --sysconfdir=/etc --localstatedir=/var --enable-experimental
$ make -j4
$ sudo make install
$ sudo reboot
```

対策2を実行後、対策1をもう一度実行する。

### 現象3: 接続できない、接続・切断を繰り返す

ペアリング後、コントローラと接続できない。

### 対策3-1: bluetoothの設定を変更する

Bluetoothのプライバシー設定を`Device`に変更する

```bash
$ sudo gedit /etc/bluetooth/main.conf
###############################
[General]
#Privacy = off
 ↓
Privacy = device
###############################
```

### 対策3-2: Xboxコントローラのファームウェアをアップデートする

XboxコントローラをUSBで手近なWindows 10 PCに接続する。

![PXL_20210610_134617920.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171097/b1beda02-eb7f-1bf0-7842-18a0d62e1bce.jpeg)

Xboxアクセサリを起動して、アップデートが必要ならアップデートする。

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171097/aedcb965-e535-4b7b-0ea6-a9923daf1571.png)


## 参考リンク

- [Ubuntu20.04でxboxのコントローラー(1914 SeriesX 2020年版)を無線(BLE)で使う](https://asukiaaa.blogspot.com/2021/01/xbox-controller-1916-on-ubuntu.html)
- [Raspberry PiにBluetoothでワイヤレス・ゲームパッドを接続するには](https://denor.jp/raspberry-pi%E3%81%ABbluetooth%E3%81%A7%E3%83%AF%E3%82%A4%E3%83%A4%E3%83%AC%E3%82%B9%E3%83%BB%E3%82%B2%E3%83%BC%E3%83%A0%E3%83%91%E3%83%83%E3%83%89%E3%82%92%E6%8E%A5%E7%B6%9A%E3%81%99%E3%82%8B#Raspberry_PiXboxOneBluetooth)
- [Updating BlueZ on Raspberry Pi (from 5.43 to 5.50)](https://scribles.net/updating-bluez-on-raspberry-pi-from-5-43-to-5-50/)
RLoginのダウンロード先（2021年6月現在）

RLoginの本家サイトに繋がらず、RLoginがダウンロード出来ないって人が結構いたので、
備忘のため記載しておきます。

以下のGithubのページ内の
**Windows XP以降、実行プログラム(32bit) rlogin_x32.zip**
**Windows 7以降、実行プログラム(64bit) rlogin_x64.zip**
のうち自分のPCに対応している方をダウンロードして解凍後、
**rlogin.exe**を適当な場所に置いて実行してください

https://github.com/kmiya-culti/RLogin/releases/
Linux メモ sftpコマンドでアップロード・ダウンロード

Linux に関するメモ。
ファイル転送について`scp`でも同様のことができるが、こちらは脆弱性があるとのことで非推奨となっているので、`sftp`を使った。

windows10 Powershell にて動作確認。

ログイン

```
PS C:\WINDOWS\system32> sftp -i C:\Users\username\Downloads\sample.pem ec2-user@123.456.789.0
```

ローカルへダウンロード

```
sftp> get test.txt C:\Users\username\Downloads
Fetching /home/ec2-user/test.txt to C:/Users/username/Downloads/test.txt
/home/ec2-user/test.txt                                                  38%   62MB 367.0KB/s   04:40 ETA
```

ローカルからアップロード

```
sftp> put C:\Users\username\Downloads\test.txt /home/ec2-user/dir/
Uploading C:/Users/username/Downloads/test.txt to /home/ec2-user/dir/test.txt
C:/Users/username/Downloads/test.txt                                             100% 1350    26.1KB/s   00:00
```

# 参考記事

https://webkaru.net/linux/sftp-command/

https://security.sios.com/vulnerability/openssh-security-vulnerability-20190115.html
Sandy Bridge おじさんの新しい自作PC計画

自宅で使用する、そこそこの仕様で多目的のデスクトップPCを自作したいと思った時の備忘録。趣味用途ではあるが、ゲームは含まない。動画編集は、少し行うかもしれない。　主たるOSは、Linux や BSD　だが、一応、Windows 10 も動くようにしておきたい。

####1. ケース
自室で使用する場合は、静音性を重視したい。最近話題になるケースは、fractal design define R5 というケース。￥12,000くらい。HDD/SSDを複数台数設置したり、ハードウェアを交換したり、いろいろいじりたいのであれば、作業空間の広いタワータイプが良いと思う。配線の取り回しは意外と手間がかかる。

####2. 電源
約650W、￥10,000〜20,000 を目処に探す。Seasonic あたり。 日本製コンデンサーとかが採択のキーワードになる。

ケース(オンオフスイッチが気になる。)と電源は、自作PCを長期間稼働させたいのであれば軽視しないこと。

####3. MPU
何のために使用するのか？で左右されるが、そこそこの性能が欲しいのであれば、メーカーの主力製品の一世代前で、価格低下気味のMPUが狙いめ。価格ドットコムで売れ筋のMPUを探す。
この記事を書いている時点(2021年6月)であれば、INTEL Comet Lake(14nmノード) Core i5 あたり。￥20,000～￥30,000を目安とする。

####4. マザーボード
上記のMPUに合致するマザーボードを探す。MPUのソケット形状が合致すること。
過去実績では、10年以上稼働しているGigabyte製が最も長寿命であった。これも「日本製コンデンサー」という殺し文句で決めた。タワーケースであれば、作業性や冷却を考慮し、ATX かつ 壊れやすい Wi-fi 機能なし。RAIDも不要だろう。￥20,000以下で入手可能なもの。

####5. メモリー
自宅用途であれば、16GBもあれば、OK。MPUとマザーボードで自動的にマッチする仕様が決まる。Samsung, SK hynix あたりから選んでおく。
動画編集とかが主たる目的の場合は、もっと搭載したほうが良いかも知れない。￥10,000 〜￥20,000

###6. ドライブ等
壊れない限りは、使えるハードウェアを使い回す。SSDであれば、256GBもあれば足りるし、HDDであれば、1TBなんて使い切れない。両者とも価格が下がっており、在庫が確保されているかのほうが懸念事項。データ保管は、別途NAS中に保管する。

###7. ディスプライ、キーボード、マウス
過去の機材を使いまわす。

ということで、買い替えるなら、こうだろうなあと考えていたのだが、現状のデスクトップPCがなかなか壊れない。いわゆる、Sandy Bridge おじさん仕様である。
マザーボード：Gigabyte GA-Z68X-UD3H-B3 2012年に購入し、UEFIには対応していない。
MPU: Core i7-2700K @3.5GHz
ケースは、1997年頃に購入したケースをいまだに使用。

で、最近、以下の部材を購入して、使用延長が決定した。

https://www.amazon.co.jp/gp/product/B00GOF0YOW/ref=ppx_yo_dt_b_asin_title_o01_s00?ie=UTF8&psc=1

これのおかげで、起動用USBスティックをケースの裏側まで挿しにいかなくてもよくなった。なぜ、もっと早く購入しなかったのか。

https://www.amazon.co.jp/gp/product/B08FDDM4W6/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1

最年長さんの 1TB 3.5インチHDD の引退部屋。使用する必要のない場合は、前面のスイッチを入れなければ良いだけ。これで HDD は引退。データが必要な場合のみ、起動時にスイッチオンにしておく。

以上
Railsのビューの基本中の基本

Railsにおいて、ビューの基本は

app/assets/layouts/application.html.erb

を経由するということ。

逆に言えば、application.html.erbに記述していないと、仮にcontrollerとそれに対応するviewを作っても何も表示されません。

そのため、最低限、application.html.erbには下記の記述が必要です。

```app/assets/layouts/application.html.erb
<%= yield %>
```

これを記述しておけば、各controllerに対応するviewを書いておけばそれぞれ呼び出されます。

これだけだと流石に、無駄が多いので、各種ビューを見て重複する部分はapplication.html.erbにまとめておけば良いと思います。
（例えばheadタグ要素とか。）
ListViewの全項目を(ちょっとだけ)高速に選択する


参考にした記事
[ListBoxの全項目を高速に選択する - Qiita](https://qiita.com/mifumi323/items/071be4cd87998ce267f9)

```c#:テストコード
private void listView1_KeyDown(object sender, KeyEventArgs e)
{
    if (e.KeyCode == Keys.A && e.Control)
    {
        foreach (ListViewItem item in listView1.Items)
        {
            item.Selected = true;
        }
    }
    if (e.KeyCode == Keys.Q && e.Control)
    {
        if (0 < listView1.Items.Count)
        {
            listView1.Items[0].Selected = true;
            SendKeys.SendWait("{HOME}+{END}");
        }
    }
}
```

元のコードは`SendKeys.SendWait("{HOME}+{END}");`のみだったが、ListViewで途中を選択した状態から始めると最初のほうが選択されなかったので、最初の1個だけ`Selected`で選択するようにした。

体感的には、SendKeyのほうがわずかに早い。といっても、数百くらいなら体感差は無く、1万くらいになると差が出てくる感じ。古いPCなので、最近のPCならもっと差は縮まるかも。

アイテムが大量にある場合、foreach Selectedでは、キーを押してからGUIが変わるのに少し待ち時間があるが、SendKeyの場合は、キーを押したら瞬時に最初の1個が選択されて、それから少し遅れてすべてが選択されるので、視覚的に操作が開始されたことがわかりやすいSendKeyのほうが使い勝手は良さそう。

foreach Selectedでは、すべてを選択した際に、スクロール位置は変化しない。SendKeyの場合は、最初に一番上までスクロールし、続いて一番下までスクロールする。このあたりの見た目の動きは好みで分かれそう。

// DLLを叩くと素早く一気に選択できるらしいんだけど、コード量が一気に増えるのと、今のところは数百から最大でも2万弱までの見込みなので、今回は未確認
switch文について

# switch文について

## switch文とは?

Javaには条件分岐処理というシステムがあります。

代表的な文として「if-else文」があります。

今回は、もう一つの条件分岐処理の「switch文」について説明致します。

## switch文の構造

以下のコードをご覧ください。

```
switch(式){

    case 定数1: //式の結果が定数1と一致したとき、以下の処理が行われる。
     処理文1;

    case 定数2: //式の結果が定数2と一致したとき、以下の処理が行われる。
    処理文2;

    default: //上記どのcaseにも一致しなかったとき、以下の処理文が実行される。

    defaultの処理文;
}

```

switch文は、**式を評価した結果**と**case**で指定した定数とを比較し、
一致した場合にそのcase以降に記述した処理文を実行します。

## switch文のデータ型

switch文の式の評価は、データ型として

・char
・byte
・short
・int(およびそのラッパークラス)
・enum
・String

のいずれかの値である必要があります。

それ以外の型が指定されると**コンパイルエラー**となります。
また、式の評価がnullの場合、コンパイルは成功しますが、**実行時にNullPointerException例外**が
発生します。

## break文

case文で式を評価しtrueになった場合、case以下の処理が全て行われてしまいます。

もしswitch文を抜けたい場合はbreak文を記述します。


```
case 定数1: 
    処理文1;
    break;

case 定数2: 
    処理文2;

```

このコードの場合、もし「case 定数1」でtrueになった場合、処理文1が実行され、「case 定数2」の式は
評価されず、switch文を抜ける流れとなります。

まとめ
・switch文は、式を評価した結果とcaseで指定した定数とを比較し、
一致した場合にそのcase以降に記述した処理文を実行する。
・switch文の式の評価は、データ型として【char,byte,short,intおよびそのラッパークラス),enum,String】
のいずれかの値である必要がある。
・switch文を抜けたい場合はbreak文を記述する。
whichコマンドで見たいものが見れない時は...!!

# まえがき
何をすれば良いのか結果だけ見たい方は一番最後の[PATHだけ表示したいよ](https://qiita.com/drafts/c6c202981b084f4522d4/edit#path%E3%81%A0%E3%81%91%E8%A1%A8%E7%A4%BA%E3%81%97%E3%81%9F%E3%81%84%E3%82%88)を見ていただければ幸いです。

# whichコマンドとは
コマンドのディレクトリがどこにあるのかを知るために使用します。
僕は普段、pythonをメインに使用するので例として下記のようにやると、

```Terminal 
$ which pipenv

/usr/local/bin/pipenv
```

このようになると思います。
ですが**pipnev**と合わせて使う**pyenv**でやってみると、

```Terminal
$ which pyenv

pyenv () {
	local command
	command="${1:-}" 
	if [ "$#" -gt 0 ]
	then
		shift
	fi
	case "$command" in
		(rehash | shell) eval "$(pyenv "sh-$command" "$@")" ;;
		(*) command pyenv "$command" "$@" ;;
	esac
}
```

おやおや、**pipenv**のときように**PATH**のみが現れませんね。
さらにさらに**nodenv**においてもやってみると、

```Terminal
$ which nodenv

nodenv () {
	local command
	command="${1:-}" 
	if [ "$#" -gt 0 ]
	then
		shift
	fi
	case "$command" in
		(rehash | shell) eval "$(nodenv "sh-$command" "$@")" ;;
		(*) command nodenv "$command" "$@" ;;
	esac
}
```

**pyenv**と同じ感じになりましたね。

# whereコマンドとの違い
上記で述べた**where**コマンドと比較してみると、

```Terminal
$ where nodenv

nodenv () {
	local command
	command="${1:-}" 
	if [ "$#" -gt 0 ]
	then
		shift
	fi
	case "$command" in
		(rehash | shell) eval "$(nodenv "sh-$command" "$@")" ;;
		(*) command nodenv "$command" "$@" ;;
	esac
}
/usr/local/bin/nodenv
```

おっと、**which**コマンドでも見れた部分がありますね。どうやら**which**コマンドは**where**コマンドで表示される**最初の部分**が表示されるという違いがあるようです。

# PATHだけ表示したいよ
毎回**where**コマンドで確認するのもいいですが欲しい情報以外も表示されてしまい少しわかりづらくなってしまいます。ここで使うのが**type**コマンドです。
試しにやってみると、

```Termianl 
$ type pipenv

pipenv is /usr/local/bin/pipenv
```

```Terminal
$ type pyenv

pyenv is a shell function from /Users/gabe/.zshrc
pyenv is /usr/local/bin/pyenv
```

```Terminal
$ type nodenv

nodenv is a shell function from /Users/gabe/.zshrc
nodenv is /usr/local/bin/nodenv
```

このように表示されます。しかも、ユーザーも設定している場合、それがどこに記載されているかも表示してくれます。
なので、**where**コマンドを使用するよりも**type**コマンドを利用した方が都合が良い時が多いかもしれませんね！
【論文紹介】New Thermal Taste Actuation Technology for Future Multisensory Virtual Reality and Internet

#論文紹介
論文：New Thermal Taste Actuation Technology for Future Multisensory Virtual Reality and Internet
著者：Kasun Karunanayaka, Nurafiqah Johari, Surina Hariri, Hanis Camelia, Kevin Stanley Bielawski,
and Adrian David Cheok, Member, IEEE
https://openaccess.city.ac.uk/id/eprint/19433/1/New%20Thermal%20taste%20actuation%20technology%20for%20future%20Multisensory%20Virtual%20Reality%20and%20internet.pdf

#どんなもの
　舌の表面の温度を変化させるThermal Taste Machineを用いて、温度によって味覚がどのように変化するのかの研究。

→舌を急速に加熱すると、甘み、脂肪感（油感）、電気的な味、温感が感じられ、金属的な味の感度が低下する。舌を冷やすと、ミント味、快感、冷たさを感じる。
舌の温度上昇が速いほど、より強い甘さを感じる。しかし、長く舌を加熱すると、辛さ、しびれ、不快感などの感覚になる。
舌を温めると、冷やす場合やオフの場合に比べて、金属味の感覚が減少。
温熱甘味器は，溶液の甘さと濃さの両方の評価に影響を与える。


#先行研究と比較してすごいところ
　化学薬品を使うことなく、長期的に利用できる。 
　甘味などの基本的な味の感覚を作り出すことだけでなく、味に関連しない感覚も作り出すことができる。これを確認するために温熱味覚装置のThermal Tasye Machineを作った。
　<font color="gray">今までの研究では、主に甘味の感覚を誘導することが多かったが、この論文では温熱味覚を味覚と非味覚を用いて温熱味覚を表現する。</font>


#技術や手法のキモ
　短時間で舌の表面の温度を変化させることのできるThermal Taste Machineを用いた。(加熱中は25℃~40℃、冷却中は25℃~10℃)

　銀板に密着させたペルチェモジュールを使用して、電流を流すと片側が冷たく反対側が温かくなる。(電流の流れる方向を変えると加熱側と冷却側を入れ替えられる。)

#検証方法
　Thermal Taste Machineのユーザ評価を3種類行った。
①熱による味覚の特徴
②温熱味覚装置がスクロースによって生じる甘味の強さを変えることができるか
③温度上昇の違いが熱的甘味感覚を変化させるか
　25℃から40℃の加熱と25℃から10℃の冷却を用いて舌の表面を刺激した。(最初に蒸留水で口をすすぎ、熱味覚装置の銀板を舌の上に置く。そして、実験者はランダムに設定された刺激（スイッチオフ、加熱、冷却のいずれか）で温熱味覚装置を作動させた。)
　刺激した後、参加者に舌に感じた感覚を20種類の感覚を用意した強度記録シートを使って評価してもらう。
　一元配置分散分析を使ってスイッチオフ、加熱、冷却の3つの異なる刺激感の平均値を比較した。

温熱味覚装置とショ糖液を用いて実験を行った。(温熱味覚装置で舌を刺激することで，甘味に対する感度も高まるかどうかを調べるため)
　溶液を1から10までの3つの視覚的アナログスケール(強度、価数、甘さ)で評価してもらう。
　甘さ、好きさ、強さの評価は、on／offおよび溶液（水、甘さ控えめ、甘さ強め）を因子とする2×3分散型統計分析(ATS)により分析。有意な主効果は，ペアワイズ・ウィルコクソン符号付き順位検定によってさらに分析。

#議論
　刺激の速さの違いで甘味がどのように影響が出るかの実験の被験者が6人は少なすぎるのでは？
　舌の上に金属板を置くのではなくて、スプーンやフォークにくっつけるほうがいいのでは？

#気になった論文
　Virtual Sweet: Simulating Sweet Sensation Using Thermal Stimulation on the Tip of the Tongue