OmniAICreator/Qiita-1.07M huggingface dataset:
SFSymbolsが潰れて表示されるとき

SFSymbolsがこのように潰れて表示されてしまうときはどうするのか(UIKit)、メモしておきます。

![スクリーンショット 2021-11-19 12.28.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/505421/cbe7840a-04d2-ad0e-ebcf-6cd6f27c1f8c.png)


```swift
private func createImage(parentView: UIView, imageName: String) {
        let imageView = UIImageView()
        imageView.image = UIImage(systemName: imageName)
        imageView.frame = CGRect(x: 10, y: 12, width: 40, height: 40)
        parentView.addSubview(imageView)
}
```

## 対処法

設定を追加するだけでした

```swift
imageView.contentMode = .scaleAspectFit
```

![スクリーンショット 2021-11-19 12.28.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/505421/f7c57979-b8ab-5072-8364-0581656cf9dd.png)

SFSymbols特有のことかと思って調べると、意外とどうしたらいいのかわからなかったのですが、単純にUIImageViewの問題でした。

### おまけ

今回とは直接関係ありませんでしたが、SFSymbolsについてはこの記事がわかりやすかったです。

https://www.avanderlee.com/swift/sf-symbols-guide/
秒単位で結果が正しいかを判定したいPHPのテストコードを実装する際に気を付けること

## テスト内容
指定したデータが、仮の現在日時である「2021/11/19 12:00:00」より1秒前か、同じか、1秒後かどうかで処理内容が変わるかどうかを見るテストがあったとして、
テストコードにその日時の1秒前とか1秒後の日時を用意して引数に渡してあげれば、
うまくいくことがほとんどだと思うが、環境によってはそれが保証されない。

ごくごく普通というか平均的なスペックがあれば実行の速度的に1秒もかからんだろ～って思っていたが、それは確率論になってしまって、どんなに低い確率でも環境によって結果が異なってしまうようなテストはあまり良くないらしい。

そもそも、12:59:59みたいなときに実行したら、テスト対象メソッド実行後には時間変わってる可能性は高い。

## 解決方法
現在日時を、モック化するように固定させてしまえばいい。
以下のようにsetTestNow()を使うことで、現在日時を固定にすることができる。なので、2099年とかにしても、その値になる。

```php:anime-suko.php
// Carbonで得られる現在日時を以下で固定
Carbon::setTestNow(new Carbon('2021/11/19 12:00:00'));
```

なので、以下のように実際に現在日時を取得しようとしたら、いつ実行しても上記のsetTestNow()で指定した日時が得られることになる。

```php:anime-suko.php
$now = new Carbon('now');
```

## 注意点
Carbonには、CarbonImmutableというものもあって、同じようにインスタンスを作ってできるが、もしCarbonに対してだけsetTestNow()をしたとしたら、CarbonImmutableにはその固定が反映されないので注意。それぞれ別物として扱う。

```php:anime-suko.php
Carbon::setTestNow(new Carbon('2099/11/19 12:00:00'));
$now = new CarbonImmutable('now');//2099年になってなくてリアルな現在日時となる。
```

## 感想
モックとかこういう仮で固定するより、リアルな現在日時を使って直接メソッド呼んでうまくいったほうがよりリアルで良くね！？って思っていたが、
低い確率でもたまーに失敗するテストは論外というのは自分もそう思ってきた。
もちろんやらないよりはちゃんとやったほうが確実なので、今後もやります。
【Gatsby.js】「Firebase deploy error」と「Error: Input file contains unsupported image format」

## 概要

- GatsbyをFirebaseでbuildした時にエラーが出る。
 
```
error "gatsby-plugin-manifest" threw an error while running the onPostBootstrap lifecycle:

Input file contains unsupported image format

Error:Input file contains unsupported image format
```

## やったこと: 失敗

こちらの記事を参考にさせていただき、パッケージのバージョンを最新のものにアップグレードしました。

https://qiita.com/sotono/items/678c32f2820a40b27688

```
    "gatsby-plugin-manifest": "^2.4.24"　→　"^4.1.0",
    "gatsby-plugin-sharp": "^2.6.28"　→ "^4.1.0",
```

そうすると、別のエラーが出ました。

```
warning url-loader@1.1.2: Invalid bin field for "url-loader".
error gatsby-plugin-manifest@4.1.0: The engine "node" is incompatible with this module. Expected version ">=14.15.0". Got "12.22.7"
error Found incompatible module.
```

使ってるnodeの相性が悪い、あといま使ってるnodeのversionは"12.22.7"だ、と指摘されましたが、Vscodeのnvm-lsでチェックするしてみると、v15.8.0だよーと教えてくれたので、 ちょっと何言ってるのかわかりませんでした。

## やったこと: 成功

以下の3つのパッケージをダウングレードすると、Firebase deployが成功しました。

```
    "gatsby-plugin-manifest": "^2.12.1",
    "gatsby-plugin-sharp": "^2.14.4",
    "gatsby-transformer-sharp": "^2.12.1",
```
すべて最新のバージョンにすればいいわけではなくて、相性があることを学びました。

以上です。
ansible, moleculeが動作しなくなった際に行った回復手順の備忘

#ansible, moleculeが動作しなくなった際に行った回復手順の備忘

個人の環境なので厳密な管理をしていないのだが、ある日ansible, moleculeが動作しないことに気づいた。

```
$ molecule list 
Traceback (most recent call last):
  File "/home/hogehoge/.local/bin/molecule", line 5, in <module>
    from molecule.__main__ import main
ModuleNotFoundError: No module named 'molecule'

$ ansible --version
Traceback (most recent call last):
  File "/home/hogehoge/.local/bin/ansible", line 34, in <module>
    from ansible import context
ModuleNotFoundError: No module named 'ansible'
```

#環境

Fedora Linux 35 (Workstation Edition)

以下によりmolecule, ansibleを導入しているが、導入時はもっとfedoraのバージョンが低かったはず。

```
$ python3 -m pip install --user "molecule[lint]"
$ python3 -m pip install --user "molecule[docker]"
```

#いろいろ試行

```
$ python3 -m pip uninstall --user "molecule[lint]"
$ sudo dnf remove ansible
$ sudo dnf install ansible
```
など
他にも色々行っている可能性あり


#最終的に回復した手順

--user付き導入だったので、できるだけremoveした後、~/.local をどかして再導入

```
$ cd
$ mv .local .local.bk
$ python3 -m pip install --user "molecule[lint]"
$ python3 -m pip install --user "molecule[docker]"
$ python3 -m pip install --user ansible 

$ ansible --version
ansible [core 2.11.6] 
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/hogehoge/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/hogehoge/.local/lib/python3.10/site-packages/ansible
  ansible collection location = /home/hogehoge/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/hogehoge/.local/bin/ansible
  python version = 3.10.0 (default, Oct  4 2021, 00:00:00) [GCC 11.2.1 20210728 (Red Hat 11.2.1-1)]
  jinja version = 3.0.1
  libyaml = False

$ molecule --version
molecule 3.5.2 using python 3.10 
    ansible:2.11.6
    delegated:3.5.2 from molecule
    docker:1.1.0 from molecule_docker requiring collections: community.docker>=1.9.1
```

とりあえず一安心
Windows 11でASTERIA Warpを試してみた

Windows 11へのアップデート通知がようやく我がPCにもやってきました。早速アップデートしてみたのでWindows 11でASTERIA Warpを使ってみた感想を。

# 環境
* Windows 11 21H2 ビルド 22000.318
* ASTERIA Warp Server,ASTERIA Warp Flow Designer: 2016 
* Oracle JDK 1.8.0_311

ちなみにポイントはOracle JDKの1.8.0_311。このバージョンからWindows 11を正式にサポートしているようです。
https://www.oracle.com/java/technologies/javase/products-doc-jdk8-jre8-certconfig.html

# 起動してみた
早速起動してみました。Windows 11ではスタートメニューも微妙に違うので戸惑いますね。サービス起動ならなんてことないとは思いますが。

Windows 10ならスタートメニュー開くとだらだらとリストが出ますが、Windows 11だと一旦こんな画面になります。この「すべてのアプリ」を開きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41603/8ca8cc84-5e7b-e8ef-ead4-f76dcd5106f4.png)

そうするといつものスタートメニューのようにアルファベット順に並んでますのでASTERIA Warpを探しましょう。ありましたね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41603/ad45abaa-cfa5-773d-6c94-99f5b71672da.png)

毎回探すのは面倒なので右クリックして「スタートにピン留めする」でピン留めしておきましょう。すると次からは探さなくて住みます。起動後にタスクバーにピンドメするのも一つの手ですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41603/62fe00dd-4da4-e8ee-9ad1-9adb778b0245.png)

さてサーバーを起動してみましょう。難なく起動できました。コンソールウィンドウが少しモダンでいいですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41603/21b03b2f-73cf-f420-1dfc-82a0d3851164.png)

デザイナーも開いてみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41603/4f22b19a-9967-43cb-a482-899208ed87f7.png)

いつものデザイナーです。ウィンドウの角が丸くなったりフレームの色が変わっただけでいつもよりちょっとモダンな感じもしますね。

というわけで、Windows 11でASTERIA Warpを使ってみました。簡単にフローなどを使ってみましたが特に大きな問題はなさそうですね。

ただ、ASTERIA Warpは2106でも正式にWindows 11をサポートしていないのでASTERIA Warpが正式に検証を終えてサポートされるのを待ちましょうね。ご利用は自己責任でお願いします。
uninitialized constant Rack::Protection

## 概要

Railsアプリの開発でSidekiqを使う場面があると思います。
その際にハマった問題についてまとめていきます。

### 敬意

[sidekiq web interface show Forbidden when I try delete or post operations. · Issue #1289 · mperham/sidekiq](https://github.com/mperham/sidekiq/issues/1289#issuecomment-415714146)に紹介されている方法でRackを用いて特定のドメインのみsidekiqを扱えるように設定をした際にこの問題が起きました。

### エラー内容

sidekiqを`v6.0.x`を使って、先ほどのいるとタイトルのエラーが発生します。

```ruby:config/routes.rb
require 'sidekiq/web'

Sidekiq::Web.set :session_secret, Rails.application.secrets[:secret_key_base]
Sidekiq::Web.set :sessions, Rails.application.config.session_options
Sidekiq::Web.class_eval do
  use Rack::Protection, origin_whitelist: ['https://your.domain'] # resolve Rack Protection HttpOrigin
end
```

```ruby:Gemfile
gem 'sidekiq', '~> 6.0.7'
```

```bash
# 例えばRailsを起動すると
$ rails s

Exiting
Traceback (most recent call last):
...
/home/web/config/routes.rb:8:in `block (2 levels) in <main>': uninitialized constant Rack::Protection (NameError)
```

## 原因

2年前の対応により`v6.1.0`以降から`rack-protection`の依存を無くした対応が入ったため。

- [Vendor rack-protection/authenticity_token middleware by seuros · Pull Request #4588 · mperham/sidekiq](https://github.com/mperham/sidekiq/pull/4588)
- [Vendor rack-protection/authenticity_token middleware (#4588) · mperham/sidekiq@111d9d5](https://github.com/mperham/sidekiq/commit/111d9d536967579557c522bdca7b388226b17bc4)


## 対策

```yml:Gemfile
# 追記
gem 'rack-protection'
```

## まとめ

滅多に起きたいことかもですが、古いアプリで使っていた設定を新規アプリで同じように設定して使おうとした際にバージョン指定していないとこのエラーにハマるかと。（てかハマった笑）
Railsのエラーメッセージの階層、インデントの書き方

##やりたいこと
・ja.ymlファイルを編集してエラーメッセージを日本語化したい。
・カラム名は日本語に変更できたので、エラーメッセージのkeyを編集して
　完全な日本語にしたい


##エラー内容
・I18n::InvalidLocaleData in Topics#new
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2301963/204a35a5-d708-edd6-a50c-b13a99245415.png)





##原因
・ja.ymlファイルのインデントがあっていない
・そもそもファイルが読み込めていない
ちなみにこの段階でのymlファイルはこんな感じ
```

```
ja:
  activerecord:
    models:
      user:
    attributes:
      user:
        name: 名前
        email: メールアドレス
        user_area: 勤務地
        user_job: 役職
        school_year: 学年
        password: パスワード
      topic:
        images: 画像または動画
        description: 本文
  errors:
    messages:
      extension_whitelist_error: "%{extension}ファイルのアップロードは許可されていません。"
```
##解決策
###1インデントを修正してみる
ymlファイルはスペース一つ間違っているだけでも読み込んでくれないデリケートなものなので、コメントアウトで消すのではなくしっかりと消しましょう。
１９行目が怪しいので消してみます。すると…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2301963/9ca16185-af52-b533-f116-f6702b275787.png)

またもやエラー。しかし、内容が変わってる。
expected end of...
あ。ダブルクオーテーションで囲ってなかった。。
単なるスペルミス。

```
    extension_whitelist_error: "%{extension}ファイルのアップロードは許可されていません。"
```
上記のように修正。

すると、エラーは改善されました。そして実際に投稿画面でこのメッセージが表示されるかテストしてみる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2301963/90c926d7-995e-f046-b8c2-edd9ef3c6a16.png)

おかしいっすね。

ただ、このエラー文を見てみると、
```
画像または動画translation missing: ja.errors.messages.extension_whitelist_error
```
とあります。
これは、ja → errors → messages → extension_whitelist_error
の階層になっていないので翻訳データが見つかりませんよと言っている。


```
ja:
  activerecord:
    models:
      user:
    attributes:
      user:
        name: 名前
        email: メールアドレス
        user_area: 勤務地
        user_job: 役職
        school_year: 学年
        password: パスワード
      topic:
        images: 画像または動画
        description: 本文
    errors:
      messages:
        extension_whitelist_error: "%{extension}ファイルのアップロードは許可されていません。"
```
この表記だとactiverecord:の中にerror:が入ってしまっている。


なのでインデントを修正。

```
ja:
  activerecord:
    models:
      user:
    attributes:
      user:
        name: 名前
        email: メールアドレス
        user_area: 勤務地
        user_job: 役職
        school_year: 学年
        password: パスワード
      topic:
        images: 画像または動画
        description: 本文
  errors:
    messages:
      extension_whitelist_error: "%{extension}ファイルのアップロードは許可されていません。"

```
分かりづらいかもしれませんが、errors:以下の3行のインデントを1つ上げました。

もう一度テスト
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2301963/258bb95d-cb45-29f5-6797-97a48629df79.png)

上手くいきました！
M5StickCでeCO2と換気扇（など）を連動してみる

M5StackでCO2モニターを作ってみた話をしたところ、[【集中力UP】NETATMO+IFTTT+SwitchBotでCO2濃度を監視+自動換気する方法](http://touchlab.jp/2019/02/carbon_dioxide_monitoring_and_ventilation/)という記事を紹介いただきました。
手元で余らせているM5StickCでも似たことができないかな、ということでやってみました。

## 準備するもの

- [M5StickC（本体のみ） - スイッチサイエンス](https://www.switch-science.com/catalog/6350/) ¥2,398
- [TVOC/eCO2 ガスセンサユニット（SGP30） - スイッチサイエンス](https://www.switch-science.com/catalog/6619/) ¥1,562
- [M5Stack用赤外線送受信ユニット - スイッチサイエンス](https://www.switch-science.com/catalog/5699/) ¥528
- [GROVE - 4ピン-ジャンパメスケーブル (5本セット) - スイッチサイエンス](https://www.switch-science.com/catalog/1048/) ¥550
- [1×16 両方長いピンヘッダ - スイッチサイエンス](https://www.switch-science.com/catalog/1938/)
- [Amazon | オーム電機 電機器具専用 リモコンコンセント [品番]07-8251 OCR-05W 白 | オーム電機 | ペンダントライト](https://www.amazon.co.jp/gp/product/B01ABMGGQ8/ref=ppx_yo_dt_b_asin_title_o02_s00?ie=UTF8&psc=1) ¥1,936


累計 ¥7,056

あと、ピンヘッダーを切るのに必要なので持っていないようならニッパーを。
[Amazon | エンジニア マイクロニッパー ESD 静電気対策 120㎜ NS-04 | 小型ニッパ](https://www.amazon.co.jp/%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2-ENGINEER-NS-04-%E3%83%9E%E3%82%A4%E3%82%AF%E3%83%AD%E3%83%8B%E3%83%83%E3%83%91%E3%83%BC/dp/B000TGJSWG/ref=sr_1_6?keywords=%E3%83%8B%E3%83%83%E3%83%91%E3%83%BC&qid=1637288877&sr=8-6)


## 接続

TVOC/eCO2ガスセンサユニットは付属のコネクタで HY2.0-4P（GROVE）に接続。

赤外線送受信ユニットは、GROVE 4ピン-ジャンパメスケーブル に両方長いピンヘッダを差して

GND -> GND
5V -> 5V
OUT -> G26
IN -> G36

に接続。

リモコンコンセントを換気扇のコンセントに接続する。

## できたもの


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8961/d8615a8f-d4e0-4ea0-990f-777ac1cd94ee.png)

## Arduion IDEのコード

eCO2が500を境に電源を制御するようになっています。値は実際に使って見て調整予定です。

```c++
#include "Adafruit_SGP30.h"
#include <M5StickC.h>
#include <Arduino.h>
#include <IRremoteESP8266.h>
#include <IRsend.h>

Adafruit_SGP30 sgp;
int i = 15;
long last_millis = 0;

const uint16_t kIrLed = 26;
IRsend irsend(kIrLed);
// on
uint16_t onRawData[19] = {2578, 2664,  816, 876,  838, 850,  840, 1890,  840, 1892,  840, 1890,  842, 1892,  816, 876,  836, 852,  812};  // UNKNOWN 8F0C8B3A
//off
uint16_t offRawData[19] = {2554, 2688,  816, 878,  812, 1916,  840, 850,  812, 876,  814, 1918,  814, 876,  812, 1918,  840, 1890,  838};  // UNKNOWN D410BC59


void setup() {
  M5.begin();
  irsend.begin();

  Serial.begin(115200);
  delay(1000);

  Wire.begin(32, 33); // M5StickC

  if (!sgp.begin()) {
    Serial.println("Sensor not found");
    while (1);
  }
  M5.Lcd.setRotation(3);
  M5.Axp.ScreenBreath(12);
  M5.Lcd.setTextColor(WHITE, BLACK);
}

void loop() {
  M5.update();
  if (! sgp.IAQmeasure()) {
    Serial.println("Measurement failed");
    return;
  }
  Serial.println("TVOC " + String(sgp.TVOC));
  Serial.println("eCO2 " + String(sgp.eCO2));

  if (sgp.eCO2 > 500) {
   Serial.println("eCO2 over 500 ");
   irsend.sendRaw(onRawData, 19, 38);  // Send a raw data capture at 38kHz.    
  }
  if (sgp.eCO2 <= 500) {
   Serial.println("eCO2 under 500 "); 
    irsend.sendRaw(offRawData, 19, 38);  // Send a raw data capture at 38kHz.    
  }


  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setCursor(0, 0, 2);
  M5.Lcd.print("eCO2");
  M5.Lcd.setCursor(0, 30, 4);
  M5.Lcd.print(sgp.eCO2);
  M5.Lcd.print("ppm");
  delay(1000);
}

```
「自己満足の仕事」から脱却した話

##前書き
今日読んだ致知出版社[『1日1話、読めば心が熱くなる365人の仕事の教科書』][1]の一節。
新津春子さんという、清掃業のプロフェッショナルである方の記事に感銘した話である。
史上最年少で全国優勝した掃除の腕前らしい。
感銘したのは、その「視座の高さ」、「努力」、「プロとしての誇り」。
そして、自分のシゴトと重ね合わせ、自分自身、「自己満足」なシゴトをしていないか？と考えさせられた話であります。
皆さんにも共感するところがあるんじゃないかと思って、書いてみます。

[1]:https://www.amazon.co.jp/1%E6%97%A51%E8%A9%B1%E3%80%81%E8%AA%AD%E3%82%81%E3%81%B0%E5%BF%83%E3%81%8C%E7%86%B1%E3%81%8F%E3%81%AA%E3%82%8B365%E4%BA%BA%E3%81%AE%E4%BB%95%E4%BA%8B%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8-%E8%97%A4%E5%B0%BE%E7%A7%80%E6%98%AD/dp/4800912474

##本題　【7月27日】 断ったらプロじゃない<br> 　新津春子 日本空港テクノ所属環境マイスター

新津春子。羽田空港で清掃の仕事に携わり、ビルの清掃の全国大会で史上最年少で優勝した経歴を持つ。
中国残留孤児。掃除のプロとしての視座の高さにより、NHK「プロフェッショナル」にも出演した。著作や講演活動も行っている。
1970年生まれ。御年今年で51歳。

この記事は2016年の雑誌「致知」インタビュー記事。本の一部がネットにも掲載されていたので参考に付す。
本の前半部分はネットには掲載されていなかったが、その前半部分に感銘を受けた。
新津が清掃の全国大会の予選で「二位」の結果となったときに納得いかず、所属会社の常務に愚痴った話。
そして、その時の常務のコトバが、その後の新津を覚醒させた話。

>『入社から三年経った時、私は全国ビルクリーニング技能競技会に会社の代表として出場することになりました。全国大会の前に予選大会があって、私としては百％出し尽くしたんですけど、二位だったんです。その結果に納得がいかなくて、常務に「何がいけないの？」ってぶつけると、ひと言「気持ちを込めていない」って。
　私が「どうやって気持ちを込めるの？」と聞くと、「急ぐあまり道具を使ったらポンポン投げるように置いているでしょう。それが気持ちがないってことだよ。道具を作った人が見たらどう思う？」
　もう返す言葉がありませんでした。
　そこから全国大会までの二か月間、私は道具や物も人だと思って、使ったら「ありがとう」って言いながら置くようにしていきました。ただ、常務は「自分で考えろ」という感じで細かいことは教えてくれない。
　「気持ちを込めるにはどうしたらいいか」って毎日考えていました。ある日、お客様の動きをずっと見ていると、答えが分かったんですよ。』

新津は、空港を利用する人々は、それぞれの年齢層や職業など多種多様であり、それぞれのタイプによって動きが違うことに気づいた。

>『ということは、例えば同じテーブルを使うにしても汚れる場所、汚れ方はそれぞれ違ってくる。そうやって考えていくと、子供が使うとこう汚れるのか、ご年配の方の場合はこうだ、ということが分かってきて、使う人の事を見据えて掃除のやり方を工夫できるようになったんですよ。』

結果、見事全国大会で日本一を獲得する事ができたという。

>**『それからですね、自己満足の清掃ではなく、お客様のためにする清掃に転換したのは。「気持ちを込める」という自分に欠けていたものに気づいてから、清掃技術の向上だけに留まらず、もっともっと自分を高めていこうという意識に拍車がかかりました。一つずつ目標を立てて、努力して、達成して、また新たな目標を立てる。その喜びがやみつきになって、いつしか清掃の仕事が自分の居場所だと感じるようになりました。』**

上記の新津のコトバは心に響いた。
皆さんも『清掃』の部分を、皆さんがされている『仕事』に置き換えてみてください。

新津が常務のコトバから得た気づき。
それは、
**『自己満足の仕事からの脱却』**である。**『自己満足の清掃ではなく、お客様のためにする清掃に転換した』のだ。**
それは、
**『自分の仕事』の技術の向上だけに留まらず、『もっともっと自分を高めていこうという意識に拍車がかかる』のだ。**
それは、
**『一つずつ目標を立てて、努力して、達成して、また新たな目標を立てる。
　その喜びがやみつきになって、いつしか〇〇の仕事が自分の居場所だと感じるようにな』るのだ。**

新津は締めくくる。

>『私たち空港の清掃員はお客様からいろんなことを頼まれるんです。だから、清掃とは関係ないことであっても、お客様から言われたことは断らないで全部やっていく。
　そういうことは意識しています。
　断ること自体が自分には許せないというか、断ったらプロじゃないと思うんですよね。もちろん私にはできないようなことも中にはあるわけですから、
　それを断らないでやるためにはどうすればいいかって考えて、やっぱり日々プラスアルファの努力を積み重ねる。
　あと、清掃に関しては、赤ちゃんが床でハイハイしても大丈夫なくらい綺麗にしようって心掛けているんです。
　心を込めなければ綺麗にはできませんし、そこは妥協せずにやっています。どんな仕事でも心を込めてベストを尽くす。そうすることで、お客様は喜んでくれると思うの。』

新津さん、スーパーカッコよい、プロフェッショナルであった。僕は、敬意を表するッ！

（参考）

https://report.jobtalk.jp/interview/detail/id=395

https://think-out.jp/key-person/haruko-niitsu-1.html

https://www.chichi.co.jp/web/20181203niitsu/#
LaravelでカスタムAnnotationを定義

今回、LaravelにてCSVの１行分を表すクラス（DTO的な）を定義する必要があって、CSVの１行を出力するために、列の出力順をプロパティごとに設定したなぁとおもったので、そのやり方をメモ。

Reference URL:
https://www.doctrine-project.org/projects/doctrine-annotations/en/1.13/index.html


## Define Annotation class.

``` PHP
namespace App\Annotations;

/**
 * @Annotation
 */
class Order
{
    public int $value;
    public function __construct(array $values)
    {
        $this->value = $values['value'];
    }
}
```

## Put annotation on the properties.

``` PHP
namespace App\Services\CsvRows;

use App\Annotations\Order;

class MemberPersonalInfoRow 
{
  /** @Order(1) */
  public string $id;

  /** @Order(2) */
  public string $name;

  /** @Order(3) */
  public string $phone_number;

  /** @Order(4) */
  public string $address;
}
```

## Retrieve the annotation by property.

``` php
$reflectionClass  = new \ReflectionClass(MemberPersonalInfoRow::class);
$annotationReader = app(AnnotationReader::class);
foreach ($reflectionClass->getProperties() as $property) {
    $order = $annotationReader->getPropertyAnnotation($property, Order::class);
    if (is_null($order)) {
        continue;
    }
    /** @var $order Order */
    var_dump(
        $property->getName(),
        $order->value
    );
}
```
Android TextViewリンク多言語対応するときの色々


# はじめに
androidのTextViewリンク化（多言語）について、自分が下記のものを調べたけど、
うまく行けなかったので、色々を試して、簡単に共有します。


<!-- 各チャプター -->
<a id="#問題点"></a>
# 問題点
TextView内の多言語リンクうまく表示できないこと

resourcesファイル

```
<resources xmlns:tools="http://schemas.android.com/tools">
   <string name="link_text">Here is <a href="http://www.google.com">google</a> page </string>
</resources>
```

xmlファイル

```
<TextView
                    android:id="@+id/link_text"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:autoLink="web"
                    android:linksClickable="true"
                    android:gravity="center"
                    android:textSize="18sp" />
```

fragmentファイル

```
val linkText = binding.linkText
        linkText.isClickable = true
        linkText.movementMethod = LinkMovementMethod.getInstance()
        val infoText =
            rootContext.getString(R.string.link_text)
        linkText.text =
            Html.fromHtml(infoText, HtmlCompat.FROM_HTML_MODE_COMPACT)
```
結果下記の図

![スクリーンショット 2021-11-19 11.13.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2008594/7243b810-6d62-1f47-424a-a39cee9b0c17.png)


googleのリンク化されない

<a id="#解決方法"></a>
# 解決方法

xmlファイルの
```android:autoLink="web"
android:linksClickable="true"
```
この二つが要らない。

注意点として：
HTML文字列は、バックエンドまたはリソースファイルから取得できます。
テキストをリソース文字列として配置する場合は、必ずCDATAタグを追加してください。

例：
``<string name="your_text">normal text & <![CDATA[<a href="http://www.google.com">link text</a>]]>.....</string>```

```
<TextView
                    android:id="@+id/link_text"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:autoLink="web"
                    android:linksClickable="true"
                    android:gravity="center"
                    android:textSize="18sp" />
```

今回の例

```
  <string name="link_text">Here is <![CDATA[<a href="http://www.google.com">google</a>]]> page </string>
```

![スクリーンショット 2021-11-19 11.20.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2008594/078f02c2-526b-3df8-f946-c80d184f1ec7.png)


HtmlCompatすごく使いやすいものと思いますので、引き続きこの記事で更新する予定です。

<a id="#reference"></a>
# 参考文献
- [HtmlCompatの説明](https://developer.android.com/reference/androidx/core/text/HtmlCompat)
エッジコンピューティングを実現するCouchbase Mobile紹介：Sync Gateway間レプリケーション

## 概要

Sync Gatewayは、Sync Gateway間レプリケーション(Inter-Sync Gateway)機能を提供します。これによって、異なるデータセンターにある複数のCouchbase Serverクラスター間の同期を行うことができます。

Couchbase Serverのクロスデータセンターレプリケーション（XDCR）も同様に、Couchbase　Serverクラスター間でデータを同期する機能を提供します。 一方、Sync Gateway間レプリケーション機能は、Couchbase Mobileを使ったモバイル/エッジコンピューティング構成用に設計されています。


## ユースケース

### クラウドとエッジの同期
このケースでは、複数のエッジクラスターがクラウド（または中央データセンター）のクラスターと同期します。各エッジは、クラウドデータセンターへのネットワーク接続なしで自律的に動作できます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176567/6aa68315-a6c3-1640-2538-9df45ba8abc6.png)

### エッジとエッジの同期
このケースでは、アクティブなSync Gatewayノードを含む地理的に離れたエッジクラスターが、同期されます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176567/912ade8d-75dd-6541-16a6-5a553227e158.png)


## 特性

### 環境

Sync Gateway間レプリケーション構成には、ローカルCouchbase Serverデータベースが含まれます。

### プロトコル
Sync Gateway間レプリケーションは、WebSocketに基づいています。これは、Couchbase Liteクライアントでのレプリケーションに使用されるものとまったく同じプロトコルです。

WebSocket接続の双方向で永続的な性質は、変更イベントを常に待機して同期するモバイル/エッジアプリケーションに最適です。

### 同期方式
下記の３通りの同期方式を選択可能です。

- プッシュ
- プル
- プッシュアンドプル

### レプリケーションの種類
レプリケーションの種類は次のいずれかです。

- 永続的な(persistent)レプリケーション: Sync Gatewayノードの再起動後も存続し、自動的に実行を継続します。これらは、のいずれかで実行するように構成できます。また、次の2つのモードを選択することができます。
 -  continuous: すべてのドキュメントの同期が完了した後、待機します。
 -  one-shot: すべてのドキュメントの同期が完了したら後、停止ステータスになります。
- アドホックレプリケーション: アドホックレプリケーションは一時的なものであり、レプリケーションの期間のみ存在します。以下の要件を実現する方法を提供します：
 - 1回限りのレプリケーション実行（たとえば、トラブルシューティング時）
 - オンデマンドレプリケーション実行。たとえば、レプリケーションの定期実行を、スケジュールされた自動スクリプトによって、アドホックレプリケーションとして構成できます。


## その他


Sync Gateway間レプリケーション機能には、Couchbase Liteアプリケーションとの（通常の）レプリケーション同様、以下のような機能が存在します。


- デルタ同期
- 通信セキュリティ（暗号化・認証）
- アクセス制御
- ネットワーク障害からの回復
- 高可用性
- 競合解決


## 参考情報

https://docs.couchbase.com/sync-gateway/current/sync-inter-syncgateway-overview.html
ElixirでEnumを使わずEnumする

https://qiita.com/advent-calendar/2021/elixir

本記事は[「Elixir Advent Calendar 2021」](https://qiita.com/advent-calendar/2021/elixir)の1日目です。

[Elixir] のリモートもくもく会[autoracex](https://autoracex.connpass.com/)でいつもお世話になっているオーサムさん（@torifukukaiou）の横の１日目がぽっかり空いていたので空気を読まずに頂戴いたしました

皆さん[Elixir]を楽しんでますか

僕は今年ほぼ毎日、趣味の[Elixir]に没頭しました
各種Elixirコミュニティの主催者様に感謝です
（[Elixir.JPのslackはこちら](https://join.slack.com/t/elixirjp/shared_invite/zt-ae8m5bad-WW69GH1w4iuafm1tKNgd~w)）

[Elixir]によるIoT開発フレームワーク[Nerves]と[ラズパイ]にも取り組み、ありがたいことに[Nerves]コアチームの[フランクさん]と[コラボする機会](https://github.com/nerves-project/nerves_motd)も頂きました

さて、今日はその[フランクさん]と[Elixir]/[Nerves]プロジェクトに取り組んで学んだことをひとつ取り上げます

[`Enum`]を使わない「Enum」です

あるときに、フランクさんと取り組んでいたプロジェクトでIPアドレスのリストを表示する機能を実装していました

例えば、以下のように、データを加工する必要があるとします（addrとnetmaskのペアだけ取り出す）

```elixir
# Input
[
  flags: [:up, :broadcast, :running, :multicast],
  addr: {10, 0, 0, 202},
  netmask: {255, 255, 255, 0},
  broadaddr: {10, 0, 0, 202},
  addr: {65152, 0, 0, 0, 47655, 60415, 65227, 8746},
  netmask: {65535, 65535, 65535, 65535, 0, 0, 0, 0},
  hwaddr: [184, 39, 235, 203, 34, 42]
]

# Output
[
  {{10, 0, 0, 202}, {255, 255, 255, 0}},
  {{65152, 0, 0, 0, 47655, 60415, 65227, 8746}, {65535, 65535, 65535, 65535, 0, 0, 0, 0}}
]
```

皆さんはどのようにデータを加工するでしょうか？

僕は、例えばこんな感じで[`Enum`]モジュールの関数を組み合わせて、「完璧に関数プログラミングをしているつもり」になっていました

```elixir
def extract_ifaddr_addresses1(kv_pairs) do
  kv_pairs
  |> Enum.filter(fn {k, _v} -> k in [:addr, :netmask] end)
  |> Enum.map(fn {_k, v} -> v end)
  |> Enum.chunk_every(2)
  |> Enum.map(&List.to_tuple/1)
end
```

機能的には問題なく[イゴ](https://www.google.com/search?q=%E3%81%84%E3%81%94%E3%81%8F%E6%84%8F%E5%91%B3)いていたのですが、プルリクエストを[フランクさん]に見てもらってもなかなかOKがもらえません
当初、何に引っかかっているのか謎でしたが、[フランクさん]の代案を見せてもらって納得しました

```elixir
def extract_ifaddr_addresses2(kv_pairs, acc \\ [])

def extract_ifaddr_addresses2([], acc), do: Enum.reverse(acc)

def extract_ifaddr_addresses2([{:addr, addr}, {:netmask, netmask} | rest], acc) do
  extract_ifaddr_addresses2(rest, [{addr, netmask} | acc])
end

def extract_ifaddr_addresses2([_other | rest], acc) do
  extract_ifaddr_addresses2(rest, acc)
end
```

更にもう一歩踏み込んで[`Enum`]モジュールがなくても関数とパターンマッチだけで「Enum」できるんですね　（厳密には一箇所`Enum.reverse/1`が登場しますが）
目からウロコです
かっこいい

実際のコードは[こちら](https://github.com/nerves-project/nerves_motd/blob/fdb22134f8093e19159297b5d0b49ae8890429df/lib/nerves_motd/utils.ex)

[フランクさん]曰く「[Erlang]ではこれが普通だよ」ってことでした

どのスタイルが良いか、書きやすいか、読みやすいかは人それぞれで、状況にもよるとは思いますが、こういう考え方があるんだと個人的には衝撃的でした

[Elixir]に触れているとこのような新鮮な発見が多々あり、どんどん[Elixir]にハマっていきます

今日は[「NervesJP Advent Calendar 2021」](https://qiita.com/advent-calendar/2021/nervesjp)にも参加したので、もしよろしければ御覧ください

明日は@torifukukaiouさんの[「【Elixir】B - FizzBuzz Sum問題をEnum.map/2 |> Enum.filter/2 |> Enum.sum/1, Enum.reduce/3 を使って解く」](https://qiita.com/advent-calendar/2021/elixir)です
引き続き[`Enum`]の話になりそうですね

[Erlang]: https://www.erlang.org/
[Elixir]: https://elixir-lang.org/
[Nerves]: https://hexdocs.pm/nerves/getting-started.html
[フランクさん]: https://twitter.com/fhunleth
[`Enum`]: https://hexdocs.pm/elixir/Enum.html
[ラズパイ]: https://www.raspberrypi.com/products/
JavaScriptを基本からまとめてみた【18】【Reactを使うために知っておきたいJavaScriptの基本①】

##まずは概念を理解して、それから手を動かして学ぶ。

##モダンJavaScriptとは

- 明確な定義はないが以下あたりを指すことが常
- React、Vue、Angular、Riot等の仮装DOMを用いるライブラリ/フレームワークを使用

- npm/yarn等のパッケージマネージャーを使用<br>➡︎ 内部ではNode.jsが動いてくれる<br>依存関係が勝手に解決してくる<br>import先が明示的に分かれる<br>世界的に公開されているパッケージコマンドを１つで利用可能<br>チーム内での共有も簡単に
- 主にES2015(ES6)以降の記法を使用<br>※ES5=ES2014、ES6=ES2015
- webpack等のモジュールバンドラーを使用
- Babel等のトランスパイラを使用

##DOMとは

- Document Object Modelの略
- HTMLなどを解釈し木構造で表現したもの

##仮想DOMとは

- JavaScriptのオブジェクトで仮想的に作られたDOM

➡︎ いきなりDOMを操作せず、JS上で仮想DOMを操作し差分を出してからDOMに反映


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939638/99b151f7-b56e-1451-e948-a43996cc48c8.png)

##モジュールバンドラーとは

#####複数のjs(css/image)ファイルを１つにまとめるためのもの

##トランスパイラとは

#####新しいJavaScriptの気泡を古い記法に変換してくれる

##SPA (Single Page Application) とは

- モダンJavaScirptはSPAが基本
- HTMLは１つのみでJavaScirptで画面を置き換える

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939638/f0d94387-f3a6-a94c-3dc0-6340158ebc96.png)

##SPA (Single Page Application) のメリット

- ページ遷移毎のチラつきがなくなる
- 表示速度のアップによるユーザー体験向上
- コンポーネント分割が容易になることでの開発効率アップ


##参考サイト
[モダンJavaScriptの基礎から始める挫折しないためのReact入門]
(https://www.udemy.com/course/modern_javascipt_react_beginner/learn/lecture/22032604#overview)
C# から Python へ JSON の受け渡し

C#からPythonへJSON文字列を送り、少し編集してC#側に戻すサンプル。
Pythonにあまり詳しくないC#経験者向けに書いています。

# 環境

- Windows10 64bit
- Visual Studio 2022
- .Net6.0
- Newtonsoft.Json
- Python 3.6.8

# C#側

標準入出力を介してやり取りする形になります。

```c#:Program.cs
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Diagnostics;

// Pythonファイルのパス
string pythonFile = "Program.py";

// Python側に渡すJSON
JObject inputJObj = JObject.Parse(@"{
  'CPU': 'Intel',
  'Drives': [
    'DVD read/writer',
    '500 gigabyte hard drive'
  ]
}
");

var process = new Process
{
    StartInfo = new ProcessStartInfo("python.exe")
    {
        UseShellExecute = false,
        RedirectStandardOutput = true,
        Arguments =
            pythonFile +
            " " +
            JsonConvert.SerializeObject(inputJObj)
                .Replace("\"", "\\\"\"") // 「"」を「\""」にエスケープする
    }
};

process.Start();
StreamReader streamReader = process.StandardOutput;
string? pythonStdOut = streamReader.ReadLine();
process.WaitForExit();
process.Close();

if (pythonStdOut != null)
{
    JObject outputJObj = JObject.Parse(pythonStdOut);
    Console.WriteLine(outputJObj);
}
else
{
    Console.WriteLine("pythonから値が返ってきませんでした");
}
```

JSONを引数で渡す場合は「"」を「\""」にエスケープしないと
Python側に「"」が一切ないjson文字列が送られてしまい`json.decoder.JSONDecodeError`になってしまいます。

# Python側

していることは"Memory"キーを追加するだけです。

```Program.py
import sys
import json

arg = sys.argv[1]
inputObj = json.loads(arg)
inputObj["Memory"] = "16 GB" # "Memory"キーを追加するだけ
print(json.dumps(inputObj, ensure_ascii=False))
```

sys.argv[1]でjson文字列を受け取ります。
sys.argv[0]には自ファイル名が入っています。

# 実行

DebugフォルダにPythonファイルが存在しないため、エラーになります。

```
python.exe: can't open file 'Program.py': [Errno 2] No such file or directory
```

プロジェクトのプロパティから、ビルド後のイベントとして
Pythonファイルのコピーを登録します。

```powershell
copy Program.py bin\Debug\net6.0\Program.py
```

これでちゃんと動きます。

```
{
  "CPU": "Intel",
  "Drives": [
    "DVD read/writer",
    "500 gigabyte hard drive"
  ],
  "Memory": "16 GB"
}
```

# 補足

- C#側でSystem.ComponentModel.Win32Exceptionが出た

```
System.ComponentModel.Win32Exception
  HResult=0x80004005
  Message=An error occurred trying to start process 'python.exe' with working directory 'D:\C#\CSharp-Python\CSharp-Python\bin\Debug\net6.0'. 指定されたファイルが見つかりません。
  Source=System.Diagnostics.Process
  スタック トレース:
   場所 System.Diagnostics.Process.StartWithCreateProcess(ProcessStartInfo startInfo)
   場所 System.Diagnostics.Process.Start()
   場所 Program.<Main>$(String[] args) (D:\C#\CSharp-Python\CSharp-Python\Program.cs):行 126
```

Pythonがインストールされていないか、Pathが通っていないと思われます。
> Pythonインストーラの最後に「PATHに追加する」のチェックがあるので要チェックです。初期値が未チェックなので分かりにくいです。

バージョン表示がされればOKです。

```bash
python -V
# "Python 3.x.x" が表示されればOK
```

- Python側でModuleNotFoundErrorが出た

```
Traceback (most recent call last):
  File "Program.py", line 4, in <module>
    import psycopg2
ModuleNotFoundError: No module named 'psycopg2'
```

この例だと「psycopg2モジュールが見つかりません」ということなのでインストールすればOKです。

```bash
python -m pip install psycopg2
```

---

こういうのもありました。
https://github.com/pythonnet/pythonnet
IBMCloud CitrixNetscaler SSL証明書更新の影響

##以前の検証結果について
https://qiita.com/khoshina/items/a67eb2421351425fcee7

以前上記の記事で検証レベルでは影響が見られなかった。

##本番環境での影響
念の為、Citrixに確認してみると、<font color="Red">更新に伴い１マイクロ秒の停止が発生</font>するとのこと
業務影響があるのかないのかと聞かれると、***<font color="Red">業務影響あり</font>***が正しいかな。
PixiJSの文字にフィルターをかけたい

# はじめに
[PixiJS](https://pixijs.com/)で文字にフィルターをかけたかったのですが、色々詰まったのでまとめます。
公式でなんとかならないかな～

# 簡単にかけてみる
[CrossHatchFilter](https://filters.pixijs.download/main/docs/PIXI.filters.CrossHatchFilter.html)を文字にかけてみる。
<p class="codepen" data-height="300" data-default-tab="js,result" data-slug-hash="GRvzamK" data-user="nomber1910" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/nomber1910/pen/GRvzamK">
  pixi def filter</a> by 暁の流星 (<a href="https://codepen.io/nomber1910">@nomber1910</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>
文字以外にもかかってしまう...
というのも、[Text](https://pixijs.download/dev/docs/PIXI.Text.html)は[Sprite](https://pixijs.download/dev/docs/PIXI.Sprite.html)が親であり、filter自体は[DisplayObject](https://pixijs.download/dev/docs/PIXI.DisplayObject.html)にかかっているため、このような表示になってしまうらしい。
<br/>
glslで青のフィルターをかけてあげても
<p class="codepen" data-height="300" data-default-tab="js,result" data-slug-hash="MWvLdOO" data-user="nomber1910" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/nomber1910/pen/MWvLdOO">
  pixi text green</a> by 暁の流星 (<a href="https://codepen.io/nomber1910">@nomber1910</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>
背景が赤なので、青と赤が合わさってピンクになる。

# 対処法
背景は、glslで受け取るtexture2Dの中のalpha値は0なので、それを用いてフィルターをかける。
<p class="codepen" data-height="300" data-default-tab="js,result" data-slug-hash="poPPmvy" data-user="nomber1910" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/nomber1910/pen/poPPmvy">
  Untitled</a> by 暁の流星 (<a href="https://codepen.io/nomber1910">@nomber1910</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>
といっても、フィルターがかかる範囲は左右が文字ギリギリなので少し変に見える。
filterAreaをかけたらいい感じになるかもしれない。
何回やっても何回やってもカレンダーオブジェクトが取得できないYO編

備忘録として記録

カレンダー絡みのコード書く時に「日本の祝日」とか取りたいなとかあって
グーグル先生で検索して出てくるよくあるコード

例えばこんな感じのね

```
function hoge() {
  const id = "ja.japanese#holiday@group.v.calendar.google.com";
  const cal = CalendarApp.getCalendarById(id);
  console.log(cal)
}
```

ログ見るとカレンダーが~~**ヌルヌル**さん~~NULLですよ
~~もうね、アホかと。馬鹿かと。
他人様が書いたコードのコピペが何故動かんのかと！
問いたい、問い詰めたい。小一時間問い詰めたい。~~

**あー、なんでやねん**:confounded:とかいうてると
ふと思い出す。
あー、権限設定ダイアログ出たけど
こっちにも設定せんとあかんやんと！

というわけで下記の内容を追加ですよ

```AppleScript.json
//前略
  "oauthScopes": [
    "https://www.googleapis.com/auth/calendar.readonly"
  ]
//後略
```

やったぜ！父ちゃん。
明日もホームランや！
無事取得！
嗚呼、感無量、僥倖、至福、圧倒的達成

検索に出てきたサンプル達に圧倒的感謝を捧げつつ、
頼むから設定も一緒に入れといて頂きたいと切に希望するものであります。
Unity初心者 誰でも簡単「衝突判定」

参考

https://yttm-work.jp/unity/unity_0006.html

### Colliderの設定
Edit Colider を押下したらColliderを可視化できるので、
見ながらCenterやSizeで調整していきます。
・Is Trigger：衝突判定の時はOFF。重なり判定の時はTRUEでいきましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1548088/68229067-a054-9586-2060-985e0f77c6c5.png)

### rigidbodyの設定
衝突させるオブジェクトのどちらかに必要。
普通は、衝突しに行く側かな。
・Is Kinematic：基本false。これをtrueにすると物理が働かなくなるので衝突っぽくなりません。OnTrigger（重なり判定）で使えます。
・Collision Detection：衝突スピードにたいしてどこまで精密に判定できるかの選択肢です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1548088/dd79a09e-0a21-3a30-1cb8-8cda8218b4cd.png)

## 関数
### 当たった瞬間呼び出される　OnCollisionEnter

```
	void OnCollisionEnter(Collision other)
	{
		Debug.Log (other.gameObject.name + "Enter");
	}
```
### 当たってる間呼び出される  OnCollisionStay

```
	void OnCollisionStay(Collision other)
	{
		Debug.Log (other.gameObject.name + "Stay");
	}
```

### 注意事項
よく空のオブジェクトにスクリプトをつけてそこから他のオブジェクトに対する処理を書くことがありますが、
その場合OnCollision系のメソッドは呼び出されないため注意が必要です。
OnCollision系のメソッドは、Colliderがアタッチしてあるオブジェクトにスクリプトを関連付けることで発火します。

### 子の衝突判定がしたい
親にRigidbodyをつけていると、子のColliderの衝突検知もされるようです。
全く空の親だとダメなので、ぜひ試してみてください。
いろんなドキュメント・チートシート


# CSS系
## [TailwindCSSドキュメント](https://tailwindcss.com/docs)
TailwindCSSの公式ドキュメント

## [TailwindCSSチートシート](https://nerdcave.com/tailwind-cheat-sheet)
TailwindCSSのチートシート
結構ドキュメントがつよいと思うけど、あったら便利かも
『css 効かない！！』って人がやるべきこと

# はじめに
プログラミングする上で誤字脱字をするのは、仕方のないことです。
ただ、それをしてしまうとコードが正しく読まれなくなります。

自分自身、凡ミスで作業が止まってしまうことが多いのでメモとして書かせていただきます。

今回は、cssがうまくいかない時に何が原因なのか、あるある5選！！

# 1 .(ドット)がない

```css
main {
 間違ったcssの記述
}
```

これ意外と気づかないんですよ。
{}はエラー出てくれるんですけど、これ出ないんですよね。

### 正しい書き方！！！

```css
.main {
 正しいcssの記述
}
```

# 2 全角スペースを使ってる

```css
.main {
  padding:　10px;
 間違ったcssの記述(伝われ)
}
```

多分伝わりませんね。
プログラムは半角でしましょう

### 正しい書き方！！！

```css
.main {
  padding: 10px;
 正しいcssの記述（伝わらん）
}
```

# 3 セミコロン、{}(カッコ)が抜けている

```css
.main {
  padding:　10px
 間違ったcssの記述

```

これは絶対に読みこれません。
絶対にエラーが出るのですぐ直しましょう。


### 正しい書き方！！！

```css
.main {
  padding: 10px;
 正しいcssの記述
}
```

# 4 親要素、子要素の理解が浅い。

根本的な技術力の問題です。
例えば、こんな感じ。
極端かもしれませんが箱の中の文字を横にしたいのに2番目みたいにできない！
って場合です。
親子関係はしっかり図にしてみるといいかもしれませんね。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="VwzgNGd" data-user="_yuki0302_" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/_yuki0302_/pen/VwzgNGd">
  Qiitaの投稿(css4番)</a> by ユウキ (<a href="https://codepen.io/_yuki0302_">@_yuki0302_</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

# 5 CSSの指定がかぶっている

指定されたCSSの要素がかぶっている場合、決まっている優先度に従いCSSが解釈されます。
基本的にCSSやHTMLはブラウザが上から順番に読み込んでいくので、指定がかぶっている場合は下部に記述されているものにどんどんスタイルが上書きされていく特徴があります。

```css
1番目
.sanple {
  margin: 500px;
  width: 400px;
}

2番目
.sanple {
  margin: 300px;
  width: 200px;
}
```

この場合、2番目の記述に上書きされます。
cssの記述が無駄に多くなるだけなので消しましょう。

#　終わりに
よくある間違いを5個挙げました！
簡単なミスですがわからないことあるので、ぜひこの記事をご活用ください！
【Swift】UIImagePickerControllerで簡単カメラ連携

# やりたいこと
カメラで写真を撮影して、その写真をアプリ内で使いたい。

# 環境
- Xcode 13.1
- Swift 5

# 準備
カメラを使う際は、info.plist の Camera Usage Description を定義しておく必要があります。
![スクリーンショット 2021-11-18 18.53.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367596/35a9133d-388d-875d-9a22-acdd472ad7df.png)

# 処理概要
1. カメラのアクセス権限確認
1. UIImagePickerController のインスタンス生成、カメラ起動
1. Delegateで撮影した写真を受け取る

# ソースコード

```swift:SampleViewController.swift
class SampleViewController: UIViewController {
    /// ボタンタップでカメラを起動する
    @IBAction private func startCamera() {
        // 1. カメラのアクセス権限確認
        self.confirmCameraAuthorizationStatus { isAuthorized in
            if isAuthorized {
                let sourceType = UIImagePickerController.SourceType.camera
                guard UIImagePickerController.isSourceTypeAvailable(sourceType) else {
                    return
                }
            
                // 2. UIImagePickerController のインスタンス生成、カメラ起動
                let cameraPicker = UIImagePickerController()
                cameraPicker.sourceType = sourceType
                cameraPicker.delegate = self
                self.present(cameraPicker, animated: true, completion: nil)
            }
        }
    }

    /// カメラの利用許可確認
    private func confirmCameraAuthorizationStatus(result: @escaping (Bool) -> Void) {
        // カメラの利用が許可されているか確認
        switch AVCaptureDevice.authorizationStatus(for: .video) {
        case .authorized:
            result(true)
        case .notDetermined:
            AVCaptureDevice.requestAccess(for: .video) { isGranted in
                DispatchQueue.main.async {
                    result(isGranted)
                }
            }
        case .denied, .restricted:
            result(false)
        @unknown default:
            result(false)
        }
    }
}

extension SampleViewController: UIImagePickerControllerDelegate {
    // 3. Delegateで撮影した写真を受け取る
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        guard let pickedImage = info[.originalImage] as? UIImage else {
            print("写真取得失敗")
            picker.dismiss(animated: true, completion: nil)
            return
        }
        
        picker.dismiss(animated: true, completion: nil)
        // pickedImageを使って何か処理をする
    }
}

extension SampleViewController: UINavigationControllerDelegate {    
}

```
NEM NIS1 ノード (java版) バージョンアップ手順 - 2021.11

:::note alert
手順に問題がありましたので修正しました。バックアップは、コピーではなく移動、をさせないとまずかったです。そうしないと ~/package/nis/ 配下にバージョン0.6.99のソースと0.6.100のソースが同居しちゃってました。お詫びして訂正ですm(__)m
:::

本手順は以下の手順の続きです。

- https://qiita.com/curupo/items/3d36642c9a19953e8a82

バージョンアップがときどき発生します。

- https://github.com/NemProject/nem.core

以下、ホームディレクトリにブロックチェーンデータが配置されるnemディレクトリと自身の設定ファイルなどが配置されているpackageディレクトリがある想定での手順になります。

ノードを停止

```
$ curl localhost:7890/node/info
$ curl localhost:7890/shutdown
```

削除

```
$ ls ~/nem/nis.lock
$ rm ~/nem/nis.lock
```

バックアップ（移動させる）

```
$ mv ~/package ~/package.backup.YYYYMMDD
```

最新バージョンのファイル名を確認

```
https://bob.nem.ninja/
```
nis-0.x.xxx.tgz というファイルが置いてあるので確認。


ダウンロード

```
$ cd ~/
$ curl -o nis1.tgz https://bob.nem.ninja/nis-0.x.xxx.tgz
```

解凍

```
$ tar -xzvf nis1.tgz
```

必要な設定箇所を確認する

```
$ vim ~/package/nis/config-user.properties
----
nem.host = <ホスト名>
nis.bootName = <ノードリスト上のノード名>
nis.unlockedLimit = <ハーベスト接続人数の上限値>
----
```

実行シェルを修正（環境に合わせて適宜）

```
$ vim ~/package/nix.runNis.sh
----
-java -Xms1G -Xmx4G -cp ".:./*:../libs/*" org.nem.deploy.CommonStarter
+nohup java -Xms4G -Xmx8G -cp ".:./*:../libs/*" org.nem.deploy.CommonStarter &
----
```

実行権限の付与

```
$ cd ~/package
$ chmod +x nix.runNis.sh
```

起動

```
$ ./nix.runNis.sh
```

ブロック高を確認

```
$ curl localhost:7890/chain/height
```

ノード情報を確認

```
$ curl localhost:7890/node/info
⇒{"timeStamp":210132872,"error":"Service Unavailable","message":"NIS_ILLEGAL_STATE_LOADING_CHAIN","status":503}

NIS_ILLEGAL_STATE_LOADING_CHAIN とありますが、ブロック高が最新まで追いつくと消えました。
もし追いついてもメッセージが変わらなければノードをさらから作り直したほうが良いと思われます。
```

ノードのヘルスチェック

```
$ curl localhost:7890/heartbeat
```

参考にさせていただきました。
https://zenn.dev/y_matsuoka/scraps/cc585a8da4b130

ノード構築者が集うSlack

- https://tanuson.slack.com/
Twitterの「プロモーションする」を消す

## こいつを消す
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33329/f7d28dd1-d7f1-1044-50bb-72e3ddcbfdd3.png)


Chrome拡張機能を使用します。

ディレクトリ構造

```
./twitter_promotion_remove/
├── manifest.json
└── twitter
    ├── script.js
    └── style.css
```

```manifest.json
{
  "name": "twitter-promotion-remove",
  "author": "Noriaki Oshita",
  "description": "remove twitter promotion.",
  "version": "1.0.0",
  "manifest_version": 2,
  "web_accessible_resources": ["*"],
  "permissions": ["storage"],
  "content_scripts": [
    {
    "matches": ["https://twitter.com/*"],
    "css": ["twitter/style.css"],"js": ["twitter/script.js"]
    }
  ]
}
```

```style.css
a.css-4rbku5.css-18t94o4.css-1dbjc4n.r-1niwhzg.r-sdzlij.r-1phboty.r-rs99b7.r-1loqt21.r-1s2bzr4.r-2yi16.r-1qi8awa.r-1ny4l3l.r-ymttw5.r-o7ynqc.r-6416eg.r-lrvibr {
    display: none;
}

a.css-4rbku5.css-18t94o4.css-1dbjc4n.r-42olwf.r-sdzlij.r-1phboty.r-rs99b7.r-1loqt21.r-c8eef1.r-2yi16.r-1qi8awa.r-1ny4l3l.r-ymttw5.r-o7ynqc.r-6416eg.r-lrvibr {
    display: none;
}
```

```script.js
// 空です
```


作ったディレクトリをchrome://extensions/にドラッグアンドドロップすれば適用されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33329/4fcfb390-bb51-5dce-7c70-9f95ad6375dd.png)


##ソースコード
https://github.com/oshita-n/twitter_promotion_remove

## 参考
https://hira.page/blog/201809_chrome-stylize
[Drupal]カスタムフィールドフォーマッターの作り方

## フィールドフォーマッターとは
こちらをご参照ください

https://qiita.com/863/items/9b9c8dbbd5b72ce5cee8

## 今回作りたいフォーマッター
- フィールド値に関係なく「Hello World!」と表示する
- ノードのすべてのプレーンテキストフィールドに適用できる

## 作り方と使い方

### ファイルを作成
- カスタムモジュールに`src/Plugin/Field/FieldFormatter`というディレクトリを作成
- 上記のディレクトリ下に下記の内容で`HelloWorldFormatter.php`を作成
- `drush cr`

```php
<?php

namespace Drupal\my_module\Plugin\Field\FieldFormatter;

use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FormatterBase;

/**
 * 常にHello Worldと表示するフォーマッター.
 *
 * @FieldFormatter(
 *   id = "hello_world",
 *   label = "Hello World",
 *   field_types = {
 *     "string"
 *   }
 * )
 */
class HelloWorldFormatter extends FormatterBase {

  /**
   * {@inheritdoc}
   */
  public function viewElements(FieldItemListInterface $items, $langcode) {
    return ['#plain_text' => 'Hello World!'];
  }

  /**
   * {@inheritdoc}
   */
  public static function isApplicable(FieldDefinitionInterface $field_definition) {
    if ($field_definition->getTargetEntityTypeId() !== 'node') {
      return FALSE;
    }

    return TRUE;
  }

}

```
### コンテンツタイプの表示設定で選択
今回はノードのプレーンテキストフィールドでのみHello Worldフォーマッターが選択可になります。
![スクリーンショット 2021-11-19 8.22.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253501/2d0f8c51-d597-6cf3-e225-fc8b68aa165a.png)

### ノードを表示
フォーマッターによってフォーマットされた内容が表示されます。
![スクリーンショット 2021-11-19 8.24.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253501/20d43a62-f00e-86f3-4930-fcb3d6692b7f.png)



## 解説
以下、コードの内容を解説していきます。

### アノテーションでメタ情報を定義
まず、Drupalの他のプラグインと同様に、アノテーションでこのプラグインのメタ情報を定義します。

```php
/**
 * 常にHello Worldと表示するフォーマッター.
 *
 * @FieldFormatter(
 *   id = "hello_world", // フォーマッターのID
 *   label = "Hello World",　// フォーマッターのラベル
 *   field_types = {
 *     "string"　// フォーマッターを適用するフィールドタイプのID
 *   }
 * )
 */
```
今回はプレーンテキストにのみフォーマッターを適用したいので、対象となるフィールドタイプのIDにはプレーンテキストの`string`を記入しています。

#### plain_textじゃないんかいと思ったそこのあなた
フィールドタイプのIDはこちらでチェック
[FieldTypes, FieldWidgets and FieldFormatters](https://www.drupal.org/docs/drupal-apis/entity-api/fieldtypes-fieldwidgets-and-fieldformatters#comment-14298594)


### どのように表示するかを定義
`viewElements()`でレンダリング配列を返すことでどのような内容をレンダリングするかを決めます。

```
  /**
   * {@inheritdoc}
   */
  public function viewElements(FieldItemListInterface $items, $langcode) {
    return ['#plain_text' => 'Hello World!'];
  }
```
今回は単純に`Hello World!`と表示するだけですが、引数の`items`を利用すれば様々な値を取り出すことができます。

```php
    $items[0]->getEntity()); // ノードを取得
    $items[0]->getFieldDefinition());　// フィールド定義を取得
    $items[0]->getValue()['value']); // フィールド値を取得
```

### フォーマッターを適用する条件を定義
`isApplicable()`ではフィールドタイプ以外の適用条件を定義しています。今回はノードにしか適用できないようにしています。

```php
  /**
   * {@inheritdoc}
   */
  public static function isApplicable(FieldDefinitionInterface $field_definition) {
    if ($field_definition->getTargetEntityTypeId() !== 'node') {
      return FALSE;
    }

    return TRUE;
  }

```
これにより他のエンティティタイプでプレーンテキストのフォーマッターの設定を開いてもHello Worldフォーマッターは表示されなくなります。
kaggleでチームを組むためのTIPS

　私はkaggleをしているのですが（といってもまだContributor）、私の経験からチームで参戦する方法についてご紹介します。


## 1. 知人、友人と参加する
　もっとも一般的な方法。この場合は、初期段階からチームで参戦することになります。
　ちなみに私の場合、いっしょにやる仲間が見つからなかった（悲しい）ので、後述の方法を使っています。私は、2と3を経験しています。


## 2. チーム募集のディスカッションスレッドを活用する
　私のような境遇の人がいますので、コンペティションの初期段階でこうした募集用のスレッドが立っています。
そのスレッド内で、「誰かわたしといっしょにkaggleやんない？」（もちろん英語）と投稿します。もしくはそうした投稿に対して、返信をします。それで、相手が了承すればチーム成立です。どちらかにチームマージのリクエストを送り、送られた側がアクセプトします。ちなみに、送った側がリーダー、送られた側がメンバーです。
　スレッドがない場合ですが、積極的にスレッドを立てることをおすすめします。周りのkagglerから感謝されてupvoteされること間違いないでしょう。ただし、既にスレッドがある場合にそれをやると、迷惑になりますし、upvote集めとみなされて、叩かれ（downvote）されます。voteがマイナスのスレッドは割とよく見かけます。
チームビルディング用スレッドに限らず、ディスカッションルームにスレッドを立てる前に同じ内容の投稿をしていないか確認しましょう。これは、マナーであるとともに、意図せず自分の評価を下げないための護身術でもあります。

## 3. コンペティションの途中で声をかける/かけてもらう
　Notebookを公開したり、データセットを作ったり、ディスカッションで積極的にコメントしたり、スレッドを立てたりすると、必然的に周囲のkagglerの目に付きます。重要なのは、継続することです。継続することで、私はこのコンペティションを継続しますよという意思表示にもなります。また当たり前ですが、投稿の内容は評価（upvote）されるような内容でなければなりません。kaggle masterのような素晴らしい内容である必要はありません。kaggleに参加するのは、ビギナーから熟練者までが参加しているカオスな戦場です。自分の頭で考えて、真摯に課題に向き合った内容ならば、同じような課題を抱える参加者からは評価を得られます。
　私の場合、ディスカッションには基本的にはupvoteする側に回っていたのですが、自分のためには発信する側に回らねばと思い投稿を短期間に行ったところ、効果はすぐに現れました。2日間のうちにupvoteをいくつかもらいました。単純にupvoteされれば良いわけではないのですが、ディスカッションの場合1upvoteでブロンズメダルが1個もらえます。コードを公開するのはちょっと、、、という方はまずは、ディスカッションのスレッド内でコメントしてみたり、慣れてきたらスレッドを自ら立ち上げて見ましょう。よほど適当に書かない限り、downvoteはされないです。upvoteされなくても痛くも痒くもないので、勇気を出して積極的に発信してみましょう。なお、ブロンズメダルを50個集めるとディスカッションエキスパートになります。こうした称号を目標にしてみるのもkaggleを継続するモチベーションになるかと思います。
　私が声を掛けられたのは、ディスカッションに投稿をはじめて数日後のことでした。インドの学生からいっしょに組まないかということでした。インドの人とつながりができるのも、グローバルなプラットフォームであるkaggleならではだと思います。私は迷わずokしました。彼曰く、私に声を掛けたのは（表向きには）投稿の内容から知見や経験があると判断して一緒に組みたいということでした。これはこれで事実なのですが、裏事情として、一緒にチームを組んでるメンバーが忙しくて活動が進まなくて困っていたというのが本当の理由だということも明かしてくれました。正直に事情を話してくれるのも好印象でした。異国の人とチーミングするのは抵抗があるかと思います。もちろん私も無警戒にアクセプトはしません。決め手はkaggleの個人プロフィールです。そのページでは獲得したメダルや戦績が確認できるだけでなく、Linkdinや所属についての情報を載せることが可能です。前述のインド人学生は、学生にも関わらずLinkdinアカウント保有者であり、かつ内容も充実していたので、信用できると判断しました。
　最後に1点、チームが合流する際それまでのスコアはどうなるのかということです。実は、私のほうが合流元のチームよりスコアが高かったので、スコアを落とされるんじゃないかと思ったんですが、そうはなりませんでした。どうやら、合流前のメンバー・チームのうちスコアの高い方が採用されるようです。最も簡単にスコア上げ（順位上げ）できる方法なので、そうした目的で活用してみるのもありかもしれません。ただ、上位者or経験者の人が下位者or経験が浅い人と組むことは、あまり想定できないので、地道に実績を上げてからコンタクトした方が良いかと思います。