OmniAICreator/Qiita-1.07M huggingface dataset:
log warnへスタックトレース出力

やりたかったものはタイトル通りだった。
e.printStackTrace()から出力されているものを、Stringに変換して使いたい時に呼ばれるように。。したかった。
## 解決
方法は本当に簡単で

```java
log.warn("### メッセージ後、スタックトレース出力されたらいいな", e);

結果)
2021-11-18 10:52:19.409 [] [] ERROR ### メッセージ後、スタックトレース出力されたらいいな
java.lang.NullPointerException: null
原因発生地だらだら
```
# 時間かかった理由
検索をHow do I get e printStackTrace as string?にした。
結果)
https://www.baeldung.com/java-stacktrace-to-string#:~:text=The%20function%20printStackTrace()%20of,printStackTrace(pw)%3B
https://stackoverflow.com/questions/1149703/how-can-i-convert-a-stack-trace-to-a-string

二種類の方ほが出る。。
#### 1) Throwableを理由する
ただ本番でJunitを使うのが気持ち悪かった

```java
import org.junit.internal.Throwables;



log.warn("メッセージ後、スタックトレース出力されたらいいな。 message={}",
e.getMessage());
Throwables.getStacktrace(e));
```

#### 2) exception eの中に一旦値はあるから値を全部出力する
ながいいいいい

```java
catch (Exception e) {
StringBuilder sb = new StringBuilder();
for (StackTraceElement st : e.getStackTrace()) {
　sb.append(st).append("\r\n");
}
　log.warn("### メッセージ後、スタックトレース出力されたらいいな message={}",
　sb.toString());
}

```

どっちみち同じだったけど。。。方法１が簡単だからそれでやろうかと思ったら、
指摘もらった。。。ガンさん。。java ドキュメントにこのメソッドありますけど。。使わない理由ってあります？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209211/edfb67e9-f502-90f1-6505-0901184ad0b8.png)

(はずかしい( ﾉД`)ｼｸｼｸ…)
紛らわしかった理由が。。e = e.toString()で出ちゃうかなと思って、やってみたら
java.lang.NullPointerException: null しか出なかったので止めました。。。
だが↑のメソッドを使ったらe= throwable中身でスタックトレース出力に向かう処理があるらしいです。。。
ｈ。。。あ。。

とにかく、勉強になりましった！

# e.getMessage vs e.toString vs e.printStackTrace = ↑のwarn(string, throwable)
e.getMessage : エラー原因のみ

e.toString: エラーのException種類＋原因

e.printStackTrace：エラー発生した経由すべて(の場合上記の~.getStackTraceする必要がある)


level種類
http://www.slf4j.org/api/org/apache/log4j/Level.html
loggerは。。関数。。どうかjava ドキュメントを読むようになればいいな。。
http://www.slf4j.org/api/org/slf4j/Logger.html
Windows上のWSL2でCentOSのDockerコンテナを動かす

SurfaceGO2上でCentOSを動かすようにしたのでメモ。
入れる前に2021年11月時点の最新にWindowsUpdateしておいた。

# WSL2
とりあえずWSL2が動作するようにする。
昔と違って色々やらななくても
`wsl --install`
で普通にWSL2とUbuntuが入った。
念のため`wsl --set-default-version 2`はしておいた。

CentOSを動かす方法としては大きく次の形がありそう。

* 仮想環境を構築して、CentOSを入れる
* WSL2で直接CentOSを適用する
* WSL2で入れたUbuntuに対して、DockerでCentOSを入れる
* Docker for Windowe（WSL2）でCentOSを動かす

最初はWSL2で直接入れようと思っていたが、Dockerパターンの方がよい気がしたので、Ubuntu＋Dockerにする。

# Docker
[このあたり](https://www.techceed-inc.com/engineer_blog/6671/)が参考

apt-getする。

```
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
sudo usermod -aG docker $USER
```

ここまででDocker本体のインストールが完了。
`docker -v`
で確認可能。

CentOSのイメージを取得
`docker pull centos:centos7`
確認は
`docker images`
でCentOSのイメージがあればOK

Dockerサービスを起動する。
`sudo service docker start`

実際にイメージを開始する。
`docker run -it -d --name centos7 centos:centos7`
が、後で80番ポートとかでアクセスする場合は-pオプションでポート開けておく。
`docker run -it -d -p 80:80 --name centos7 centos:centos7`のような感じ。（１敗）
一応あとからiptablesとかで解放できないこともないらしい。

あとは普通に`dockdr ps`で確認して、
`docker exec -it centos7 bash`
で中に入ってコマンド実行が可能。

使い終わったら
`docker stop centos7`
`docker rm centos7`
で削除したら綺麗になる。

何かをインストールして継続して使いたいのではなく、
一時的に立ち上げてテストしたい、といった用途ならこれがよさそう。
（インストールする場合はDockerイメージ作ればいける）

# centOS

先ほどのdocker execで中に入った後にサーバを構築する場合、
CentOSなので
`yum install nginx`
のようにyumでインストールするのだが、リポジトリが設定されていないので
/etc/yum.repos.d/nginx.repoファイルを追加する。

```
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=0
enabled=1
```

最近だと普段はVSCodeをGUI上で使うので、正直viやemacsの使い方をマスターするつもりは学生時代からない。
のでこういう時は[nanoエディタ](https://news.mynavi.jp/article/liunx_win-23/)を使う。最初からは入っていないので
`yum install nano`
でインストールして`nano /etc/yum.repos.d/nginx.repo`で開いてコピペ、保存。
これでnginxのインストールができるようになった。

起動は`systemctl start nginx`で行うのが一般的だと思われるが、
Dockerだとそのままでは実行できないので`/usr/sbin/nginx`で直接実行。
`curl http://localhost`でDocker内からは接続出来る事を確認。

Windowsからもlocalhostで接続出来た。
CentOS向けのソフトウェアをテストする際にはこれでいける。

必要があれば作ったコンテナからイメージに変換しておくことで、いつでも立ち上げられる。
[ここ](https://pointsandlines.jp/server-infra/docker/docker-beginner-3)にやり方。
`docker commit centos7 centos7-nginx`
のようにCommitする。
IoTデバイスとは何か、IoTアーキテクチャにおけるIoTデバイスの役割とは何か。

[IoTデバイス](https://www.ioctrl.com/post/iot-devices-internet-of-things-iot-projects)とは、ネットワークに接続された物理的なデバイスまたはオブジェクト（「モノ」）であり、影響を与える要因を可視化、分析、処理するためのデータを転送します。
IoTデバイスには、制約のあるデバイスもあれば、ローカルでデータを処理し、IoTプラットフォームへのデータ転送量が少ない本格的な[Linuxゲートウェイ](https://www.ioctrl.com/post/mqttdesk-mqtt-client-to-mqtt-broker)もあります。

IoTデバイスの接続性は、ユースケースや現実のIoTアプリケーションに依存し、[IoTアプリケーション](https://www.ioctrl.com/post/iot-devices-internet-of-things-iot-projects)で使用する[IoTプロトコル](https://www.ioctrl.com/post/mqtt-message-queuing-telemetry-transport)を決定します。
MQTTプロトコル、HTTP Rest、LORA、COAP、Websocket、TCP/TLS、Cellular、Sub-Ghz、その他多くのIoTプロトコルが、アプリケーションとその範囲、データ転送、その他のパラメータに応じて選択できます。

IoTデバイスを安全に監視し、他のMQTTクライアントにデータを転送するために、MqttDesk [MQTTクライアント](https://www.ioctrl.com/post/mqttdesk-windows-mqtt-client)が重要な役割を果たしているのはこの部分です。

以上がIoTデバイスの基本的な考え方です。詳しくは以下のブログをご覧ください。

https://www.ioctrl.com/post/iot-devices-internet-of-things-iot-projects
ModuleNotFoundError: No module named 'tqdm.auto'

`ModuleNotFoundError: No module named 'tqdm.auto'`のようなエラーが出る

```
$ python3 learning.py 
Traceback (most recent call last):
  File "learning.py", line 7, in <module>
    import optuna
  File "/home/ubuntu/.local/lib/python3.6/site-packages/optuna/__init__.py", line 8, in <module>
    from optuna import importance
  File "/home/ubuntu/.local/lib/python3.6/site-packages/optuna/importance/__init__.py", line 6, in <module>
    from optuna.importance._base import BaseImportanceEvaluator
  File "/home/ubuntu/.local/lib/python3.6/site-packages/optuna/importance/_base.py", line 9, in <module>
    from optuna.samplers import intersection_search_space
  File "/home/ubuntu/.local/lib/python3.6/site-packages/optuna/samplers/__init__.py", line 1, in <module>
    from optuna.samplers._base import BaseSampler
  File "/home/ubuntu/.local/lib/python3.6/site-packages/optuna/samplers/_base.py", line 8, in <module>
    from optuna.study import Study
  File "/home/ubuntu/.local/lib/python3.6/site-packages/optuna/study/__init__.py", line 4, in <module>
    from optuna.study.study import BaseStudy
  File "/home/ubuntu/.local/lib/python3.6/site-packages/optuna/study/study.py", line 27, in <module>
    from optuna.study._optimize import _check_and_convert_to_values
  File "/home/ubuntu/.local/lib/python3.6/site-packages/optuna/study/_optimize.py", line 29, in <module>
    from optuna import progress_bar as pbar_module
  File "/home/ubuntu/.local/lib/python3.6/site-packages/optuna/progress_bar.py", line 5, in <module>
    from tqdm.auto import tqdm
ModuleNotFoundError: No module named 'tqdm.auto'
```

以下で解決

```
$ pip3 install -U tqdm
Defaulting to user installation because normal site-packages is not writeable
Collecting tqdm
  Downloading tqdm-4.62.3-py2.py3-none-any.whl (76 kB)
     |████████████████████████████████| 76 kB 11.1 MB/s 
Installing collected packages: tqdm
  Attempting uninstall: tqdm
    Found existing installation: tqdm 4.19.9
    Uninstalling tqdm-4.19.9:
      Successfully uninstalled tqdm-4.19.9
```

# 参考
[https://github.com/nteract/papermill/issues/287](https://github.com/nteract/papermill/issues/287)
特定の単語がツイートされたらGoogleスプレッドシートに記載されるようにする

ヒヤリ・ハットをデジタル化しヒヤリ・ハットの報告と共有を活性化することで医療介護現場における同じミスの繰り返しや重大事故を減らせるのではないかと考えています。
仕組みを作ることと、その仕組みを広げる方策についても検討中なのですが、まずはヒヤリ・ハットについての情報を集めようと思い、特定の単語がツイートされたらGoogleスプレッドシートに記載されるようにするというaplletをIFTTTで作りました。

https://ifttt.com/home

IFTTTを用いて新しいappletを作ります。

Ifを「New tweet from search」として、Thenを「Add row to spreadsheet」とするのがベース。
Ifの中で、「Search for」の部分に検索したい単語を入れるのですが、「ヒヤリハット」と入れるか「ヒヤリ・ハット」と入れるか悩んだ結果、「ヒヤリ」といれることに。
![スクリーンショット 2021-11-17 23.13.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2051906/b7b2278a-0c5c-a034-aafc-7d0dc9bc356c.png)

これでしばらく運用してみたところ、1日130件ほどが記載されるようになりました。

しかし、よく見たら「ヒヤリハット」や「ヒヤリ・ハット」が含まれるツイートは含まれていない様子。
そこで並行して、「ヒヤリハット」を「Search for」の部分に入れたappletを走らせたところ、「ヒヤリ」のものと別で本文に「ヒヤリハット」と含まれるツイートが記載されるようになりました。

そこで、"ヒヤリハット""ヒヤリ・ハット""ヒヤリ"と、それぞれの単語を""で囲い、まとめて「Search for」の中に記載することに（appletのこの画面には一単語しか表示されないようです）。
![スクリーンショット 2021-11-17 23.13.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2051906/bb8cf4c0-f019-65c3-7279-e896b16d3b18.png)

これで、関連しそうな単語を自動で引っ張って来れるようになりました。

単語の書き方で検索の仕方が変わることについては、こちらの記事が参考になります。

https://gukouhikkoshi.com/lifehack20180909/

ちなみに、この取り組みを行う中で気付いたツイートがこちら。

https://twitter.com/Trialanderror_v/status/1460379822304403459?s=20

建築現場も重大事故が命に直結することからヒヤリ・ハット報告が注目されており、戸田建設さんがヒヤリ・ハットのアプリを作ったとのこと。
私が医療介護現場で行おうと考えている取り組みであり、とても興味深い。

「気になるツイートを自動で集めてくれるなんて、便利な仕組みだ！」と感動し、複数の同僚にこの仕組みについて話をしましたが、「Twitterしてないです」「そこまでして追いかけたい情報がない」と、いまいちの反応で自分との温度差が著しく少し恥ずかしい思いをしました、、

引き続き情報を集めていきます。
NCMBのFlutter SDKをnullsafety対応するために行ったこと

Flutter 2.12.0以降に対応させる際にはnullsafetyになっている必要があります。自動マイグレーションも用意されているのですが、実行してみるとテストも通らない状態になってしまったので、手作業で対応させました。

主に行った内容は次のとおりです。

## 初期化されないクラス変数をオプショナルに

Flutter SDKでは、NCMBの初期化をおこなった際に、NCMBインスタンスをクラス変数に適用しています。

```dart
class NCMB {
  String? applicationKey;
  String? clientKey;
  String? sessionToken;
  String version = '2.0.0';
  
  NCMB(String applicationKey, String clientKey) {
    this.applicationKey = applicationKey;
    this.clientKey = clientKey;
    NCMBUser.ncmb = this;
    NCMBObject.ncmb = this;
    NCMBInstallation.ncmb = this;
    NCMBFile.ncmb = this;
    NCMBQuery.ncmb = this;
    NCMBRequest.ncmb = this;
    NCMBRole.ncmb = this;
    NCMBPush.ncmb = this;
  }
}
```

この時の `NCMBUser.ncmb` の ncmb は null の場合があるので（普通に初期化をしている限りは発生しないのですが）、オプショナルにしています。各クラス、一通り修正しています。

```dart
part of ncmb;

class NCMBUser extends NCMBObject {
  static NCMB? ncmb; // ← ?を追加
}
```

## 複数の型が返ってくる場合の対応

APIリクエストした際にデータストア（NCMBObject）、ファイルストア（NCMBFile）、ユーザ（NCMBUser）、グループ（NCMBRole）など、異なる型のクラスが返ってくる可能性があります。Dartではレスポンスの型に複数持たせられないそうなので、受け取り側で指定する必要があります（実はできるとかだったら嬉しいのですが）。

そのため取得部分ではとりあえずListで返しています。

```dart
Future<List> fetchAll() async {
	try {
		var r = new NCMBRequest();
		List ary = await r.get(_name, _queries);
		List results = [];
		ary.forEach((item) {
			var obj;
			switch (_name) {
				case 'files':
					obj = new NCMBFile();
					break;
				case 'users':
					obj = new NCMBUser();
					break;
				case 'roles':
					obj = new NCMBRole(item['roleName']);
					break;
				case 'installations':
					obj = new NCMBInstallation();
					break;
				case 'push':
					obj = new NCMBPush();
					break;
				default:
					obj = new NCMBObject(_name);
					break;
			}
			obj.sets(item);
			results.add(obj);
		});
		return results;
	} catch (e) {
		throw e;
	}
}
```

受け取り側はList<dynamic>として受け取っています。

```dart
var users = await role1.fetchUser();
```

そして for で回す時に型を指定しています。元々Future.forEachを使っていたのですが、型指定周りでエラーが出るために変更しています。

```dart
for (NCMBUser u in users) {
	await u.delete();
}
```

forEachを使う場合は次のようになります。

```dart
var items = await query.fetchAll();
items.forEach((o) async {
	await o.delete();
});
```

## 必要な場所に ! を付ける

nullがくる場合には?をつけますが、確実に入っている場所に ! をつけていきました。

```dart
Map<String, String> headers = {
	"X-NCMB-Application-Key": NCMBRequest.ncmb!.applicationKey!,
	"X-NCMB-Timestamp": time.toIso8601String(),
	"X-NCMB-Signature": signature
};
```

## 依存パッケージのアップデート

これはたぶん自動でできるはず。以下のコマンドで古い依存パッケージをリストアップ。

```
flutter pub outdated --mode=null-safety
```

そしてアップデート。

```
flutter pub upgrade --null-safety 
```

## マイグレートコマンドで確認

`dart migrate` を実行して、足りない部分を確認しながら修正していきます。Web画面で一気にまとめて自動修正したら、その後動作しなくなりました…。やはり見ながら修正した方が良さそうです。

## 結果

修正をおこなった結果 NCMB SDK 2.0.6 から Null safety になりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/ffd6af6a-d7ef-9aff-cf9c-3665e1167d5c.png)


ぜひFlutterでNCMBをご利用ください！

[ncmb | Dart Package](https://pub.dev/packages/ncmb)
pandas dataframeから行番号・列番号を削除する

#方法
```sample.py
df.to_csv(index=False,header=False)
```

#備考
dataframeのまま行番号・列番号を削除する方法が見つからなかった。しかし、これらを削除したいと思うときはcsvに出力したいときが想定される。なのでこれで困らない。
iOS 15 Safari モーダル処理時にスクロール固定のために従来のやり方をするとおかしくなる件

##現象

モーダル表示される時に普段はoverflow hiddenして、スクロールさせない様にしてますが、iOSはoverflow hiddenしてもスクロールされるためbodyにfixedし、ずれた分のScrollTopからの位置をあてて対応してました。

ところがiOS１５にてその対応を行っているページで不具合が発生しました。

どうやらbodyにfixedすることでiOSで新たに追加された機能（タブバー）のせいなのかわかりませんが、bottomの基準位置が見た目とズレちゃうみたいなんですよね。

これがどういう状況で起こるかというと、下記に該当している場合です。

1.ページ下部にナビゲーションをfixedで置いている。（bottom: 0;など。）
２.modalなどの処理でbodyまたはhtmlにfixedしている時。

modalを開いてbody fixedしてスクロールを固定させると既に置いているページ下部のナビゲーションがタブバーの高さ分？隙間が出ちゃいます。

##対処法
とりあえずコードを。

```javascript
class Ios15ModalHack {
  constructor() {
    this.init();
    this.load();
    this.resize();
  }
  init() {
    const styleTag = document.createElement('style');
    styleTag.innerText = "html.is-locked,html.is-locked body {height: calc(var(--window-inner-height) - 1px);overflow: hidden;box-sizing: border-box;}"
    document.getElementsByTagName('head')[0].insertAdjacentElement('beforeend', styleTag);
  }
  syncHeight() {
    document.documentElement.style.setProperty (
      "--window-inner-height",
      `${window.innerHeight}px`
    );
  }
  load() {
    window.addEventListener('load', () => {
      this.syncHeight();
    });
  }
  resize() {
    window.addEventListener('resize', () => {
      this.syncHeight();
    })
  }
}
const App = new Ios15ModalHack();

```

headに必要なstyleをjs側で挿入して、
モーダル発火時にそのクラス(　html.is-locked　)をつけることで謎の隙間を防止します。
fixedは使いません。

内容としてはモーダル展開時にスクロール量が内部的にあると起こる？らしいので
発火時にはwindow.innerHeightでhtmlのheightを固定してしまおうという内容です。
CSS側で

height: calc(var(--window-inner-height) - 1px);

と謎の1pxを引いてますが、これが無いと展開時に垂直スクロールでタブバーの誤動作が起きて不具合が起きるそうです。


iOS15は他にも不具合ありそうなので注意が必要ですね...。

下記参考させていただきました。
https://pqina.nl/blog/how-to-prevent-scrolling-the-page-on-ios-safari/
ディリクレ分布から乱数を取得する

### ベータ分布の定義

確率密度関数が
<br>

```math
f(x) = Beta(x|a,b)= Cx^{a-1}(1-x)^{b-1} (0 \le x \le 1)
```

<br>
であるような一変量の確率分布。

### ディリクレ分布の定義

確率密度関数が
<br>

```math
f(x_1,...,x_{n-1}, x_n)= Dir(x_1,...,x_n|\alpha_1,...,\alpha_{n-1}) = Cx^{\alpha_{1}-1}\cdots x_n^{\alpha_n -1} (x_1,...,x_n \ge 0), 
```

<br>
であるような多変量の確率分布をディリクレ分布と呼ぶ。ただし、$C$は正規化定数($x_1 + ...+x_n = 1$にするためにかけるもの）・$\alpha$はパラメータである。

### ディリクレ分布の解釈

ベータ分布（コイントスにおいて表が出る確率の予測の分布）を多次元に拡張したもの。つまり、ディリクレ分布において、$n=2$の場合（単変量）を考えると、

```math
f(x_1,1-x_1) = Cx_1^{\alpha_1 -1}(1 - x_1)^{\alpha_2 -1}, x_2 = 1 - x_1
```

となりベータ分布の確率密度関数となる。

### ディリクレ分布をサイコロの目の出やすさの分布と捉える

サイコロを何度も投げて各目の出やすさを推し量るイメージを持つ。三面サイコロで考える場合、確率密度関数は

<br>

```math
f(x_1,x_2,x_3) = Dir(X | \alpha) = Cx_1^{\alpha_1-1}x_2^{\alpha_2-1}x_3^{\alpha_3 -1}
```
<br>
となる。$X = (x_1,x_2,x_3)$は各目の出る確率を、$\alpha = (\alpha_1, \alpha_2, \alpha_3)$は各目の実際に出た回数+1を表している。$X = (x_1,x_2,x_3)$の組み合わせは無限にあるが、実際の観測値（パラメータ）により、あり得そうな出やすさの組み合わせとそうでないものが出てくる。直感的には、各組合せの候補がどれくらい統計的に有力なのかを表したものとして$Dir(X|\alpha)$を捉えることができる。

### scipyとnumpyを用いてPDFを計算および乱数を取得

```Python
from scipy.stats import dirichlet

#三面サイコロを30回振って各目が10回ずつ出た場合

```python
from scipy.stats import dirichlet

print(dirichlet.pdf(x=(0.333, 0.333,0.334), alpha = (11,11,11)))
print(dirichlet.pdf(x=(0.25, 0.25,0.50), alpha = (11,11,11)))

26.744346275061304
4.890833353429621

import numpy as np

#3次元ディリクレ分布から二次元配列を作成
a = np.random.dirichlet(alpha = (11,11,11), size =3)
a

array([[0.31927048, 0.40265028, 0.27807924],
       [0.45294397, 0.20323626, 0.34381977],
       [0.21744933, 0.43121254, 0.35133813]])
```

実測値から各目の出やすさの組み合わせとして$[0.33,0.33,0.34]$あたりが最も高い確率密度を取ることが予想でき、実際に外れ値的な各目の出やすさは確認されなかった。
After Effects パスのトリミング　シェイプ

#■パスのトリミング
シェイプの追加項目にパスのトリミングがある。(コンテンツの右に追加がある。)
■デフォルト
開始0
終了100
オフセット0
線が表示されている割合。
全て表示

###▼開始
時計回りに数値が存在。
10
20
と数値を上げるほどに右回りに消えていく。


###▼終了
半時計回りに数値が存在。
10
20
と数値を上げるほどに左回りに消えていく。

###▼オフセット
開始点の変更が可能。

参考サイト
https://www.curioscene.com/simple-logo-using-trim-path/
【javascript】prototypeの継承

# prototypeの継承
以下のような、prototypeを持つコンストラクタがあったとする。

```js

function Person(name, age) {
  this.name = name;
  this.age = age;
}

Person.prototype.hello = function() {
  console.log('hello ' + this.name);
}

```
新たに、japaneseというコンストラクタを用意したい。

```js
function Person(name, age) {
  this.name = name;
  this.age = age;
}

Person.prototype.hello = function() {
  console.log('hello ' + this.name);
}

function Japanese(name, age){
  this.name = name;
  this.age = age;
}

Japanese.prototype.hello = function() {
  console.log('hello ' + this.name);
}

```
同じ内容を記述しているので、冗長であり、メンテナンス性が悪い。



# 継承

Perosnのprototypeを継承すれば楽。

```js
function Person(name, age) {
  this.name = name;
  this.age = age;
}

Person.prototype.hello = function() {
  console.log('hello ' + this.name);
}

function Japanese(name, age){
  this.name = name;
  this.age = age;
}

// からのオブジェクトを用意し、Person.prototypeを作成している。
Japanese.prototype = Object.create(Person.prototype)

```


継承ができている。

![スクリーンショット 2021-11-18 16.33.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378066/577477f5-dfb9-7c21-7553-17030d38439d.png)

## callメソッドを使用してコンストラクタ内部も継承する。

```js
function Person(name, age) {
  this.name = name;
  this.age = age;
}

Person.prototype.hello = function() {
  console.log('hello ' + this.name);
}

function Japanese(name, age){
  Person.call(this. name, age)
}
//call(第一引数:japaneseコンストラクタのthisをPersonに渡している。
// 第二引数：japaneseコンストラクタのnameをPersonに渡している。
//第三引数：japaneseコンストラクタのageをPersonに渡している。

Japanese.prototype = Object.create(Person.prototype)

const takashi = new Japanese('takashi', 23)
console.log(takashi) >> Japanese {name: 'takashi', age: 23}
takashi.hello() >> hello takashi

```

# prototypeの上書き

```js
function Person(name, age) {
  this.name = name;
  this.age = age;
}

Person.prototype.hello = function() {
  console.log('hello ' + this.name);
}

//Japaneseコンストラクタにgenderを拡張することができる。
function Japanese(name, age, gender){
  Person.call(this, name, age)
  this.gender = gender;
}

Japanese.prototype = Object.create(Person.prototype)

//Japanse.protorypeは独立して作成できるので、byeメソッドを拡張している。
Japanese.prototype.bye = function() {
  console.log('こんにちは ' + this.name);
}

const takashi = new Japanese('takashi', 23, '男性')
console.log(takashi)
takashi.hello()
takashi.bye()
```
python テキスト操作編+αその１　-初心者メモ

テキストを呼び出す方法

二つある。
一つは    {}.format(引数)
フォーマットを用いたやり方

もう一つは   f'{引数}
fストリングスを用いた方法




```
name = '和夫'
birthplace = 'アメリカ'


'私は{}です。出身は{}です。'.format(name,birthplace)


f'私は{name}です。出身は{birthplace}です。'
```
出力
'私は和夫です。出身はアメリカです。'
'私は和夫です。出身はアメリカです。'







改行の表示
改行\nはprint()の中に入れることで、jupyterやcolaboでも改行されて表示される。

```
print('そこに痺れる。\n憧れる')

```
出力
そこに痺れる。
憧れる





整数型、16進数、浮動小数点での表示

```
print("10進数 = %d,16進数 = %x, 10進浮動小数点=%f"  % (16,16,16))
```
出力結果
10進数 = 16,16進数 = 10, 10進浮動小数点=16.000000


文字を大文字にするまたは小文字にする

```
'hello'.upper()

'WOrlD'.lower()
```
'HELLO'
'world'



テキストの分割　.split('')


```
message = "こんにちは\n私は和夫です"
messages=message.split('\n')
messages
```

['こんにちは', '私は和夫です']

リストに入ったテキストの結合　'結合間に入れるテキスト'.join(messages)

```
'  '.join(messages)
```

'こんにちは  私は和夫です'

テキストの入れ替え .replace()

```
message = '今日は晴れですね'
message.replace('晴れ','雨')

```
'今日は雨ですね'

テキストが何文字目か.find('')する

```
message = '今日はとても夜空がきれいだ'
message.find('夜空')
```

テキスト操作その１はこんなもんで終わります。
Solr内部のそうだったのか メモ

いつもSolrのコードを調べては忘れ、調べては忘れているので、とりあえずここ見ると過去に調べたことはまとまってるよっていうメモ。
※ それ間違ってるよというものがあればご指摘ください。


# fqとfilter cacheについて

fqはfilter cacheが有効になっている場合、それぞれのfqパラメータで独立に検索を行う。
それぞれのfqパラメータで検索し、それぞれのパラメータごとでfilter cacheにドキュメントの集合を保存している。

そしてfqたちで積集合を取り、最後にqパラメータのクエリと積集合を取る。
(fqでマッチするドキュメントが少ないものを起点に積集合は取ってくれる)

なのでSQLのwhereの感覚で 「他のfqの条件で絞られるから問題ない」 **とはならない**

おそらくキャッシュヒット率を上げるためにこうなっている。
なので、よくセットで指定しているfqは、一つのクエリパラメータにまとめたほうが早くなる（はず）


ちなみに

```
fq={!cache=false}key1:val1
```
このように、明示的に`cache=false`とすることで、qとマージされて検索することができる。
その時は、qを**MUST**、fqを**FILTER**とした`BooleanQuery`として検索される。



# fqとPostFilterについて

SolrはJavaで書かれているので、fqやqで指定したクエリは何らかのクラスのインスタンスになるが、fqのQueryには`PostFilter interface` を実装したQueryを指定することができる。

PostFilterを実装しているのは、 `{!frange}` や、`{!collapse}` などのクエリである。

こいつらは何かというと、その名の通りフィルタの後に実行されるクエリのクラス。
そしてfrangeやcollapseのようなクエリを指定すると、たとえfilter cacheが有効になっていても内部でcacheを切ってクエリを実行する。
そのため、newSearcherなどでcache warmingしようと思っていても、collapseはキャッシュされないので意味がない。


またfqでは、`{!cache=false}`のようにキャッシュを使用しないことを明示的に指定できるが、同時に`cost`パラメータも指定することができる。

https://solr.apache.org/guide/8_3/common-query-parameters.html#cache-parameter

```:使用例
fq={!cache=false cost=100}key1:val1
```

そしてcostが100以下の場合、costが100以下のPostFilterのみでcost順にソートされ、順に評価される。
ただし気をつける必要があるのが、1つ目のfqで検索されたドキュメントに対して2つ目のfqで検索されるのではなく、あるドキュメントに対して、一致するまで順番にfqを見るという点。
これは、キャッシュ対象としないfqをcost順にソートした後、一つのQueryクラスに変換しているためである。

上述のfrangeやcollapseは、内部でcostが100に設定されているので、ドキュメントに対してPostFilterが順に適用される。

こういった仕組みにより、重い処理をフィルタした後の少ないドキュメント数に対して実行できるようになっている。


# collapseの仕組み

collapseは、PostFilterを実装していて、PostFilterはこのようなメソッドを持っている必要がある。
`public DelegatingCollector getFilterCollector(IndexSearcher indexSearcher)` 

戻り値のDelegatingCollectorは、別のCollectorに処理を委譲できるCollectorのクラス。
このクラスは、処理が終わったときに呼ばれる`void finish()`を持っている。

collapseでは、以下のような流れで処理される。

1. `collect()`が呼ばれる
1. 内部で持ってるMap(DynamicMap)にputする(同じキーなら一つにまとめられる)
1. `finish()`が呼ばれると、Mapを順に見て、それで後続のcollectorの`collect()`を呼ぶ

Mapに入れるかどうか(collapseでまとめるものの代表とするか）は、GroupHeadSelectorによって判断される。

個人的には、Mapで実現っていう割とイメージ通りでびっくりした。


## expandの仕組み

collapseしたものを、expandできる。

expandは、`ExpandComponent`として実装されていて、Componentをまたぐときは、検索結果がdocList(ドキュメントIDの一覧)としてしか取得できない。
そのため、collapseに指定したフィールドで再度検索して実現されている。

# collapseとスコア計算の順序

collapseは、ローカルパラメータとして、主に以下のようなものを受け取ることができる。

| ローカルパラメータ | 説明 |
| --- | --- |
| `field` | collapseの対象となるフィールド |
| `min` or `max` | 指定されたフィールド or 関数クエリの`最小値`か`最大値`を代表とする |
| `sort` | 指定されたソートの文字列に従って代表を選択する |

collapseは実行されると、ドキュメントが`まとめられる = 減る` ので、スコア計算が重い処理を行う場合、collapseの実行後に行って欲しい。

実態としては

- collapseの`min` `max` `sort`でscoreを使う場合は代表選択にスコア計算が必要なので、計算される
- collapseの実行タイミングはfqのフィルタの後なので、スコア計算される場合でもフィルタされた後にスコア計算される。
- collapseの代表選択にスコア計算が不要で、全体の中でスコアが必要（`fl` or `sort`にscoreが指定されている)ならば、Mapに保存されている値を更新する必要があるときにスコアを計算する（最終的に代表となるドキュメントのスコアが残るように）
- collectorが複数個 chainされているとき、何回もスコア計算が走らないように、ScoreAndDocクラスのオブジェクトをMapに保存しておいて、`finish()`内で次の`collect()`を呼んだときに、Mapから保存してあるスコアが取得できるように`setScorer(dummy)`しておく
docker-pyを用いてDockerコンテナ内で外部ファイルを実行する方法

## 実行環境
 - Ubuntu-20.04.2
 - Python 3.8.10

```
$ python3 -V
Python 3.8.10
```

 - ライブラリ: docker-py

Docker Engine API用のPythonライブラリです。


## DockerコンテナをPythonプログラムで操作する
Pythonにはdocker-pyというライブラリがあるためPythonプログラムを用いてdockerコンテナを操作できる。

### インストール方法
pipを使用してインストールできる。

```
$ pip3 install docker
```

### 使用方法
実行するためdockerデーモンと通信する。

```test.py
import docker
cli = docker.from_env()
```

試しにPythonのコンテナを立ててみる。

```test.py
import docker

cli = docker.from_env()

cont_image = "python:3.9-alpine"
cont_run = cli.containers.run(image=cont_image, detach=True, tty=True, command=["/bin/sh"])
```

実行してみる。

```
$ sudo python3 test.py
$ docker ps
CONTAINER ID   IMAGE                                           COMMAND                  CREATED              STATUS              PORTS      NAMES
3f968c5c3194   python:3.9-alpine                               "/bin/sh"                About a minute ago   Up About a minute              recursing_chandrasekhar
```

無事Pythonプログラムを用いてコンテナを立てられた。

## 立てたコンテナでPythonプログラムを実行する
大まかな方法を説明すると、test.pyでtest2.pyの内容を読み取り、test2.pyの全文をコンテナに送ることによりプログラムをコンテナにコピーすることなく実行する。

### コンテナ内で実行するPythonプログラムを用意する
試しにコンテナ内でFlaskというライブラリをインストールするプログラムを作成する。

```test2.py
import subprocess

install_flask = subprocess.check_output(["pip", "install", "flask"]).decode('utf-8')
print(install_flask)
```

### test2.pyをtest.pyで立てたコンテナで実行する
test2.pyを実行するプログラム作成

```test.py
import docker

cli = docker.from_env()

cont_image = "python:3.9-alpine"
cont_run = cli.containers.run(image=cont_image, detach=True, tty=True, command=["/bin/sh"])

with open("./test2.py") as f:
    code = f.read()

exec_run = cont_run.exec_run(["sh", "-c", f"cat<<EOF | python\n{code}\nEOF"]).output.decode("utf-8")
print(exec_run)
```

test.py実行結果

```
$ sudo python3 test.py 
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
WARNING: You are using pip version 21.2.4; however, version 21.3.1 is available.
You should consider upgrading via the '/usr/local/bin/python -m pip install --upgrade pip' command.
Collecting flask
  Downloading Flask-2.0.2-py3-none-any.whl (95 kB)
Collecting itsdangerous>=2.0
  Downloading itsdangerous-2.0.1-py3-none-any.whl (18 kB)
Collecting Werkzeug>=2.0
  Downloading Werkzeug-2.0.2-py3-none-any.whl (288 kB)
Collecting Jinja2>=3.0
  Downloading Jinja2-3.0.3-py3-none-any.whl (133 kB)
Collecting click>=7.1.2
  Downloading click-8.0.3-py3-none-any.whl (97 kB)
Collecting MarkupSafe>=2.0
  Downloading MarkupSafe-2.0.1-cp39-cp39-musllinux_1_1_x86_64.whl (30 kB)
Installing collected packages: MarkupSafe, Werkzeug, Jinja2, itsdangerous, click, flask
Successfully installed Jinja2-3.0.3 MarkupSafe-2.0.1 Werkzeug-2.0.2 click-8.0.3 flask-2.0.2 itsdangerous-2.0.1
```

この方法を用いることでコンテナにファイルをコピーすることなくコンテナでPythonファイルを実行することができる。

## 最後に
docker-pyを使えるようになるとシェルスクリプトを使わずにdockerの操作を自動化できるので結構便利です！
皆さんぜひ使ってみてください！！
MLKitで顔のパーツのポジションを取るには（Android）

まず公式サイトを貼ります：

https://developers.google.com/ml-kit/vision/face-detection/android#1.-configure-the-face-detector

setLandmarkModeに入ります：

https://developers.google.com/android/reference/com/google/mlkit/vision/face/FaceDetectorOptions.Builder#setLandmarkMode(int)

二択しかないのでパーツを取りたい時には以下の設定にしてください：

```
// 特徴を取るかどうか
.setLandmarkMode(FaceDetectorOptions.LANDMARK_MODE_ALL)
```
これをオンにすることで、全部の顔のパーツが読み取れるようになる。

その後

例えば左目のｘポジションを取りたい時に以下のコードを

```
x = face.getLandmark(FaceLandmark.LEFT_EYE).getPosition().x;
// ちなみにface.getLandmark（）.getPosition()のリターンタイプはPointFというタイプです。
```
【保存版!】コーディングテスト「track」の標準入力の対処法(Python)

#はじめに
コーディングテスト「track」の標準入力が少し独特で、アルゴリズム書く前にそっちに躓いてしまいました。なので、データの取得の仕方を解説します。

#例題
※問題文は必要な部分のみ抽出しています

ある数字列が与えられたとき、最小の数と最大の数をスペース間隔で表示し、数字列を小さい順に並べるプログラムを実装してください。

**入出力例**
標準入力

```
3
3 1 5
```
標準出力

```
1   5
135
```




**入力ルール**
標準入力は以下のフォーマットに従って渡されます

```
n
a1 a2 a3 ...
```
・nは数字の要素数
・a1,a2,a3...は0以上の整数


**標準入力の取得方法**
**main.py**内で定義されている**main**という関数から**lines**の名前で取得できます。

#コードの解説
デフォルトでコード部分は既に以下が書かれていると思います。

```python
def main(lines):
    # このコードは標準入力と標準出力を用いたサンプルコードです。
    # このコードは好きなように編集・削除してもらって構いません。
    # ---
    # This is a sample code to use stdin and stdout.
    # Edit and remove this code as you like.
    for i, v in enumerate(lines):
        print("line[{0}]: {1}".format(i, v))

if __name__ == '__main__':
    lines = []
    for l in sys.stdin:
        lines.append(l.rstrip('\r\n'))
    main(lines)     
```
これでデバックを実行すると以下が表示されます

```
line[0]: 3

line[1]: 3 1 5
```
for文でやっているように、入力の**lines**の1行目が**n** , 2行目が**a1 a2 a3**ということですね。

#実装方法
とりあえず入力データを取得する部分だけ実装してみます。
**コード**

```python
def main(lines):
    # このコードは標準入力と標準出力を用いたサンプルコードです。
    # このコードは好きなように編集・削除してもらって構いません。
    # ---
    # This is a sample code to use stdin and stdout.
    # Edit and remove this code as you like.
    for i, v in enumerate(lines):
        #print("line[{0}]: {1}".format(i, v))
        if(i==0): #1行目は数字の要素数 n
            n = v
        elif(i==1):
          a = list(map(int, v.split(" "))) #1行目じゃない(2行目)の時は数字のリストを取得
    print(n)
    print(a) 


if __name__ == '__main__':
    lines = []
    for l in sys.stdin:
        lines.append(l.rstrip('\r\n'))
    main(lines)     
```

**入力例**

```
3
3 1 5
```

**出力例**

```
3
[3, 1, 5]
```
コードの解説をします。
for文で**1行目(i=0)**の時は、数字の要素数なので**n**に代入します
**2行目(i=1)**の時は数字の要素をlistで取得しています。また2行目の部分はスペースで空いているので、**v.split(" ")**でスペース区切りしています。
**出力例**を見てもらうと、1行目は数字の数、2行目はリストが取得出来ています。

この**list(map(int, v.split(" ")))**の部分は以下を参考にしました。

https://qiita.com/jamjamjam/items/e066b8c7bc85487c0785


**解答**


```python
import sys

def main(lines):
    # このコードは標準入力と標準出力を用いたサンプルコードです。
    # このコードは好きなように編集・削除してもらって構いません。
    # ---
    # This is a sample code to use stdin and stdout.
    # Edit and remove this code as you like.
    for i, v in enumerate(lines):
        #print("line[{0}]: {1}".format(i, v))
        if(i==0): #1行目は数字の要素数 n
            n = v
        elif(i==1):
            a = list(map(int, v.split(" "))) #1行目じゃない(2行目)の時は数字のリストを取得
    #print(n)
    #print(a)
    la = list(sorted(a)) #リストの要素を小さい順に並びかえ
    print(la[0]," ",la[len(a)-1]) #1番小さい0番目と1番大きいlen(a)-1番目をスペース空けて表示
    for j in la:
        print(j,end="") #全ての要素を詰めて表示

                
if __name__ == '__main__':
    lines = []
    for l in sys.stdin:
        lines.append(l.rstrip('\r\n'))
    main(lines)
```

**出力**

```
1   5
135
```

アルゴリズムについてはコメントを見てください。

#コツ
デフォルトで実装されてる

```python
for i, v in enumerate(lines):
```
を利用するのがポイントです！
Git 用語解説！ 〜GitとGithubの違いってなんだ？〜

##基礎用語の確認
駆け出しのエンジニアです。プログラミングを学習していて、当然の様に出る専門用語や略語。それを理解したつもりにならないために確認として今回の記事を書くことにしました。

##バージョン管理
コードを書くファイルの変更履歴を管理することをバージョン管理と言います。(変更履歴のことをバージョンと呼んでいる)

バグが発生した時期やバグによる影響度を明確化するためにバージョン管理を行います。これをすることでサービス開発時の生産性が大きく上がります。

##リポジトリ
バージョン管理をするときに管理されるファイルをリポジトリと言います。
このリポジトリの中に入っているファイルを変更したときにcommit(ファイルの変更の差分をローカルのリポジトリに保存)することでバージョン管理を行えます。

##「分散型」と「集中型」
ちなみにバージョン管理には「分散型」と「集中型」の二つの方法があります。
分散型というのは開発者それぞれの個人のPC内に存在するローカルリポジトリにcommitしてからリモートリポジトリ（インターネット上にある唯一つの共有リポジトリ）にpush（リモートリポジトリにcommitした差分を追加すること）します。
分散型のメリットとしては
①ネット上のリポジトリにアクセスしなくても開発が行えるためオフラインでも仕事ができる
②ローカルリポジトリ内で他の開発者に影響を与えずに色々試したりできる
ことです。

分散型のバージョン管理サービス例: Github

一方、集中型のというのはリモートリポジトリに直接、複数人の開発者がアクセスしながら、開発を行うことです。なのでローカルリポジトリという概念が存在せず、commit = リモートリポジトリの反映を意味しています。
集中型のメリットとしては
①エンジニア側が大量のファイルを保存する必要がない
です。

集中型のバージョン管理サービス例: Subversion

ちなみに現在のほとんどの開発は分散型の手法で行われています。


##GitとGithubの違い
次はGitとGithubの違いについてです。私は最初、全く同じ物だと解釈していました。
Gitはバージョン管理をするためのツールの呼称です。そして、Githubは"Git"を利用したWebサービスの名前でPull Requestなどの開発者にとって使いやすい機能も追加されています。簡単にいうとGithubはGitの上位互換みたいなものです。

##まとめ
今回はgitの基本的な知識の解説を書いていきました。初心者エンジニアのバージョン管理の理解のお役に立てば幸いです。
windowsでマルチPHPを実現する

###PHPをダウンロードし、任意のディレクトリにダウンロード
https://windows.php.net/downloads/releases/archives/

ここでは`/c/php/php-7.1.17-nts-Win32-VC14-x64`

###環境変数に下記を追加

``` C:\php ```

###PHPのエイリアスを作成

####git-bash用
```vi /c/php/php```

```PHP
#!/usr/bin/bash
"/c/php/php-7.1.17-nts-Win32-VC14-x64/php.exe" $*
```

#### cmd用

```vi /c/php/php.bat```

```PHP
@echo off
"C:\php\php-7.1.17-nts-Win32-VC14-x64/php.exe" %*

```

```vi ~/.bash_profile```

```PHP
#alias php='/c/php/php-7.3.31-nts-Win32-VC15-x64/php'
alias php='/c/php/php-7.1.17-nts-Win32-VC14-x64/php'
```

#### git-bash反映

```PHP
. ~/.bash_profile
```

### バージョン確認
```PHP
$ php -v
PHP 7.1.17 (cli) (built: Apr 25 2018 02:18:57) ( NTS MSVC14 (Visual C++ 2015) x64 )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2018 Zend Technologies
```
【javascript】プロトタイプチェーン

# プロトタイプチェーンとは
プロトタイプの多重形成をプロトタイプチェーンという。


# Case1

```js

//Personというコンストラクタ関数を用意
function Person(name, age) {
  this.name = name;
  this.age = age;
   }
}

//prototypeを使用して、Person, Objectにそれぞれhelloメソッドを作成している。
Person.prototype.hello = function() {
   console.log('Person: hello ' + this.name);
 }

Object.prototype.hello = function(){
  console.log('Object: hello' + this.name);
}

// Personコンストラクタをnewしてbob変数に代入
const bob = new Person('Bob', 18);

// bob.hello()を実行している。
bob.hello();

>> Person: hello Bob
// ここで出力されるのは当然Person.prototype.helloになる。

```

# case2
case1と基本は同じだが、Person.prototypeをコメントアウトするとbob.hello()は実行されるのか？

```js
function Person(name, age) {
  this.name = name;
  this.age = age;

}

Object.prototype.hello = function(){
  console.log('Object: hello' + this.name);
}
// Person.prototype.hello = function() {
//    console.log('Person: hello ' + this.name);
//  }

const bob = new Person('Bob', 18);
bob.hello();

//Object.prototypeが実行された。
>>> Object: hello
```

# ここまでのまとめ
prototypeは階層構造となっている。
最初はnew されたPersonコンストラクタを探すが、ない場合は抽象度が高いObjectのhelloを探しにいく挙動となっている。
このようにネストされているprototypeをプロトタイプチェーンと呼ぶ

![スクリーンショット 2021-11-18 16.08.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378066/6254b6bc-44ca-f728-f8c1-02fe779cfdda.png)
【Python3】「ModuleNotFoundError」の対応

#はじめに
Webスクレイピングをやろうとして、WebDriverや beautifulsoupなどモジュールはインポートできてるのに、seleniumやbs4が認識されず、「ModuleNotFoundError」が発生してました。
結論としてデフォルトパスが通ってなかっただけなのですが、すごく遠回りして「sys.path.append()」でパスを追加するなど非エンジニアの私としては難しかったので、一番簡単だった方法を記載します。
※Windows10環境

・システムのプロパティから「環境変数」をクリックします。
![qiita1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2265307/ad57b515-3143-50a5-5e40-2db3d0248fca.png)

・ユーザの環境変数に新規で「変数名」をPYTHONPATHで「ModuleNotFoundError」となるライブラリのパスを「変数値」に指定。
（パスは「pip show selenium」などのコマンドで表示）
![qiita2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2265307/cf75fe44-7327-017e-9217-e4f591adca6d.png)


・vscodeでデバッグしているため、vscodeを再起動




これで、認識されるようになりました。

>@maechさんのページを参考にさせて頂きました
>>[Python内のデフォルトパスを通す方法（Windows, Linux）](https://qiita.com/maech/items/72559402556eb2af73ad)
CSSの基本的な書き方

# CSSとは
***CSS***とは、Cascading Style Sheetsの略で、HTMLで書かれた文書構造に、色やレイアウトなど見た目を整えるための言語。

# CSSの基本的な書き方
CSSの基本的な書き方は、「***セレクタ***」「***プロパティ***」「***値***」から構成される。
■ ***セレクタ***：スタイルを適用する対象を指定する。
■ ***プロパティ***：適用するスタイルの種類を指定する。
■ ***値***：スタイルの具体的な数値やキーワードを指定する。

```css:基本書式
<セレクタ> {
    <プロパティ>: <値>;
}
```

例として具体的には以下のように書ける。

```css:例
/* p要素の色とフォントサイズを設定する */
p {
    color: green;
    font-size: 1em;
}

/* ページ全体の背景色を設定する */
body {
    background-color: red;
}
```

# CSSをHTMLに適用する方法
外部のCSSファイルをHTMLに読み込むためにはHTMLに以下を記述する。

```css:
/* 「sample.css」を読み込む場合 */

<link rel="stylesheet" href="sample.css" />
```
Lalavel｜save()とupdate()の違い

lalavelで投稿データの「更新」はsave()と　update()が使えうことが分かった。

でも、どんな違いがあるのか気になったので確認してみた。

結論を言うと...

:::note info
save()は、更新データがない場合「updated_at」を更新しない。
update()は、更新データがない場合でも「updated_at」を更新する。
:::


## save()を使った場合

コントローラーのupdateメソッドは以下のとおり

```php:controller.php
public function update(PostRequest $request, $id)

...処理...

//入力値をセット
$post->title=$request->title;
$post->body=$request->body;
  
//更新      
$post->save(); 
```


実際のテーブルの中身を見てみよう。

これが最初のテーブルの中身
![スクリーンショット 2021-11-18 15.25.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2192496/f78ab3b4-9f4b-858f-fbd4-5aa6d2f9ec27.png)

何も変更しないで「更新」ボタン押した時、「updated_at」は**更新せず**。
![スクリーンショット 2021-11-18 15.25.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2192496/91bc0c38-9c0b-0d02-6596-8d620e1b4bf2.png)

タイトルとか本文を変更し「更新」ボタン押した時には、「updated_at」を**更新した**。
![スクリーンショット 2021-11-18 15.25.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2192496/c7e05842-45e9-cde8-18fe-6b78f55a561c.png)


## update()を使った場合

コントローラーのupdateメソッドは以下のとおり

```php:controller.php
public function update(PostRequest $request, $id)

...処理...

Post::where('id',$id)->update([
  'title'=>$request->title,
  'body'=>$request->body
]);
```

実際のテーブルの中身を見てみよう。

これが最初のテーブルの中身
![スクリーンショット 2021-11-18 15.28.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2192496/4eb8e03d-ebaa-be7c-5d31-e62aa4e671e7.png)

何も変更しないで「更新」ボタン押した時、「updated_at」は**更新した**。
![スクリーンショット 2021-11-18 15.28.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2192496/4f0833b7-f8b9-85a1-8fb5-72df537773d1.png)

タイトルとか本文を変更し「更新」ボタン押した時にも、「updated_at」を**更新した**。
![スクリーンショット 2021-11-18 15.29.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2192496/5913bd11-0015-ce7e-92a0-4a0d022be541.png)
redux-toolkitのstoreをローカルストレージに保存する方法

開発を進めていく中でredux-toolkitのstoreに保存されているものをlocalStorageにも保存する処理が必要になったので、その方法を記載していく。

redux-localstoreage-simpleを利用することで簡単に実装することができた。

##1.インストールする

`npm install redux-localstorage-simple`

##2.store.tsを編集する

```store.ts
import { configureStore } from '@reduxjs/toolkit';
import authReducer from "../features/auth/authSlice";
import { save, load } from 'redux-localstorage-simple'; //追記

export const store = configureStore({
  reducer: {
    auth: authReducer,
  },
// 下記を追記
  preloadedState: load(),
  middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(save()),
});
```

以上で、storeの変更が行われた際に自動的にローカルストレージに保存されるようになる。
Qiitaの記事を書こう、簡単な使い方。

#前置き
MarkDown記法の最低限の使い方を説明します。これであなたもQiitaマスター！

#見出しを作る

　#の数によって見出しが変わります。

```
#見出し1
##見出し2
```

#見出し1
##見出し2



#リストを作る

リストは-を使います。

```
- list1
- list2
- list3
```

- list1
- list2
- list3

#コードを載せる

コードは「```」で囲う。

```
>```
>print("Hello world");
>```
```

```
print("Hello world");
```

#リンク

```
[リンクへ飛ぶ](http://www.google.com/)
```
[リンクへ飛ぶ](http://www.google.com/)

#始めよう。Qiita!
あとは書きたいことを文章にするだけ。
SPSS ModelerのヒストグラムノードをPythonで書き換える

SPSS ModelerのヒストグラムノードをPythonのmatplotlibやpandasのplotで書き換えてみます。

#0．データ
サンプルで利用するデータは以下です
M_CD: マシンコード
UP_TIIME: 起動時間
POWER: 電力
TEMP: 温度
PRESSURE：圧力フラグ
ERR_CD: エラーコード

各マシンコードごとに起動時間にそって電力や温度の変化、圧力スイッチ、そしてエラーがあればそれが時系列に記録されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/1e739d26-7c0f-3f6d-7c91-9934e64ba6c3.png)



#1m．③ヒストグラム。Modeler版
POWERでヒストグラムを作り、ERR_CDで色分けしてみます。
ヒストグラムノードでフィールドにPOWER、オーバーレイの色にERR_CDを設定し、実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/f00c2515-d4eb-ec8d-a690-accf9204cd6e.png)
ERR_CDで色分けされたヒストグラムができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/b53467d7-6b64-833d-9e95-8f67abca43ff.png)

#1p．③ヒストグラム。matplotlib版
matplotlibで、ERR_CDでグループ化したヒストグラムを書くには1回のプロットで行えるのですが、あらかじめ各ERR_CDごとにデータを分割しておく必要があります。

powersという配列に各ERR_CDごとにSeriesデータをいれるので初期化しておきます。
また、errsにエラーコードのリストを入れておきます。sort_values (ascending=False)は、Modelerのヒストグラムと同じように、上からERR_CDが0,101,202,303の順に積み上げるためです。デフォルトでは下から積みあがるのでERR_CD=0が一番下になります。Modelerと同じ順序にこだわらなければ、sort_values(ascending=False) は不要です。

```python
powers=[]
errs=df['ERR_CD'].cat.categories.sort_values (ascending=False)
```
ERR_CDの0,101,202,303でループさせ、df.queryをつかって各ERR_CDで絞りこんだSeriesオブジェクトをpowers配列に追加していきます。

```python
for i,err_cd in enumerate(errs):
    powers.append(df.query('ERR_CD=={0}'.format(err_cd))['POWER'])
```
plt.histでERR_CDの0,101,202,303のSeriesオブジェクトの配列であるpowersをあたえ、stacked=Trueを指定します。bins=25でModelerのデフォルトと同じビン数にしています。
labelは文字列型しか受け付けないので.astype('str')で変換しています。

```python
plt.hist(powers,bins=25, stacked=True,label=errs.astype('str'))
plt.legend()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/29c953e2-a59a-187d-61d8-afe68be7c378.png)

pandasのplotメソッドをつかって同じことをやろうとしたのですが、うまく積み上げる方法を思いつけませんでした。


* 参考: matplotlib でヒストグラムを描く – Python でデータサイエンス

https://pythondatascience.plavox.info/matplotlib/%E3%83%92%E3%82%B9%E3%83%88%E3%82%B0%E3%83%A9%E3%83%A0

#2. サンプル
サンプルは以下に置きました。

ストリーム
https://github.com/hkwd/200611Modeler2Python/blob/mastergraph/graph.str?raw=true
notebook
https://github.com/hkwd/200611Modeler2Python/blob/master/graph/graph.ipynb
データ
https://raw.githubusercontent.com/hkwd/200611Modeler2Python/master/data/Cond5n_e.csv

■テスト環境
Modeler 18.3
Windows 10 64bit
Python 3.8.5
pandas 1.0.5

#3. 参考情報
ヒストグラムの「作図」タブ - IBM Documentation

https://www.ibm.com/docs/ja/spss-modeler/18.3.0?topic=node-histogram-plot-tab
apache が夜中に異常終了(seg fault or similar nasty error detected)

# 環境

CentOS 7.6
httpd-2.4.6-93

# 現象

apache が夜中３時ごろに、以下のログ出力して異常終了しました。

```
[Fri Xxx XX 03:XX:XX.XXXXXX 2021] [core:notice] [pid 133248] AH00060: seg fault or similar nasty error detected in the parent process
```

でもそのまま start コマンド投入したら正常起動しました。

# 原因

原因は おそらく apache の[バグ](https://bugzilla.redhat.com/show_bug.cgi?id=1376835)です。
バージョンによりますが、reload(graceful) で再起動を繰り返すと、
再起動の何回目かに、今回のように落ちます。
セマフォだかミューテックスだか（ごめん よく知らないの）がｍａｘに達するみたい。

で、再起動しているのはログローテーションの
`/etc/logrotate.d/httpd`
です。
この設定ファイルの中に、再起動の記述があります。

しかもウチでは、デフォルトの weekly から daily に修正していました。
毎日 reload(graceful) で再起動して、最初の稼働から約１年半後に落ちました :dizzy_face:

# 対応

設定ファイルを以下のように修正しました。
再起動部分を消して、copytruncate を追記しました。

```bash
# 修正前
/var/log/httpd/*log {
    daily
    rotate 14
    missingok
    notifempty
    sharedscripts
    delaycompress
    postrotate
        /bin/systemctl reload httpd.service > /dev/null 2>/dev/null || true
    endscript
}
```

```bash
# 修正後
/var/log/httpd/*log {
    daily
    rotate 14
    missingok
    notifempty
    delaycompress
    copytruncate
}
```

これで何かが溜まって異常終了することはありません。
（ただ手動で何百回も reload(graceful) したら同様に落ちます。）

**2024/06/19 追記（今さらですが）**
reload(graceful) でなく、restart すると溜まってるものがリセットされる？ようなので、定期的な restart で異常終了を回避できるかもしれません（試しては無い）

# その他

redhat では修正版があるようですが、CentOS7 では無いみたい？
CentOS7 で修正した旨の記事が見当たらない・・・

# 参考

https://bugzilla.redhat.com/show_bug.cgi?id=1376835
https://access.redhat.com/solutions/2626601
https://bugs.centos.org/view.php?id=15286
CloudFlareを通したApacheでIPアドレスを復元する

#環境
Ubuntu 20.04.3
Apache 2.4.41

#テスト環境の作成
```php
<?php
$ip = $_SERVER['REMOTE_ADDR'];
$host = gethostbyaddr($ip);

echo 'IP:'.$ip.'<br>HOST:'.$host;
```
このファイルをサーバー上に配置することで、IPアドレスを確認することができます。
セットアップしてすぐの状態ではリモートIPは表示されず、CloudFlareのIPが表示されてしまうので、今回はこれを修正していきます。

#なおしていく！！
参考

https://support.cloudflare.com/hc/ja/articles/200170786-%E3%82%AA%E3%83%AA%E3%82%B8%E3%83%8A%E3%83%AB%E8%A8%AA%E5%95%8F%E8%80%85%E3%81%AEIP%E3%82%92%E5%BE%A9%E5%85%83%E3%81%99%E3%82%8B-mod-cloudflare%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6-%E8%A8%AA%E5%95%8F%E8%80%85%E3%81%AEIP%E3%82%A2%E3%83%89%E3%83%AC%E3%82%B9%E3%82%92%E8%A8%98%E9%8C%B2%E3%81%99%E3%82%8B-

参考サイトと違うのは３つ目のコマンドにsudoがあるだけです。
##ひたすらコマンドを実行
```shell-session
 $ sudo apt-get install apache2-dev libtool git

 $ git clone https://github.com/cloudflare/mod_cloudflare.git; cd mod_cloudflare

 $ sudo apxs -a -i -c mod_cloudflare.c

 $ sudo apachectl restart; apache2ctl -M|grep cloudflare

=> cloudflare_module (shared)
```
最後の表示があれば成功です。
[React] Attempted import error: 'Switch' is not exported from 'react-router-dom'. 

## 起きたこと

`react-router-dom`をインストールし`Switch`を使ってルーティングしたら以下のエラーが起きた。

## エラー内容

```terminal
Attempted import error: 'Switch' is not exported from 'react-router-dom'.
```

## 調査と原因
調べてみるとReact Routerのv6では`Switch`が`Routes`に置き換わるらしい

### 参考

https://remix.run/blog/react-router-v6

## 対処法
特に何も考えず`react-router-dom`をインストールしていたのでversionを指定して再度インストールで解決。

```
npm install react-router-dom@5
```
Swift system Imageの一覧

# Swift ImageのsystemNameの一覧を確認する方法
##1. コードで書く例

SwiftUI
```import Swift UI
Image(systemName: "xxxx")
```

Storyboard
```import UIkit
UIImage(systemname: "xxx")
```

例） "xxx" = "magnifyingglass"
![スクリーンショット 2021-11-18 14.32.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453718/1aad10c0-5308-6477-6a43-fae3f09b6943.png)


## 2. 一覧の取得にはAppleの公式サイトより「sf-symbols」というアプリをインストールする
![スクリーンショット 2021-11-18 14.35.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453718/f4de64ae-dbda-46c2-515e-2f941ee9a425.png)

##3. 起動時の画面
![スクリーンショット 2021-11-18 14.35.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453718/b241c3f2-7ca0-53f9-93f5-c5d2f465e977.png)

##4. 検索してみた
![スクリーンショット 2021-11-18 14.35.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453718/78826535-0c73-f61c-ad58-dae93537f865.png)
Github Action内でPrivate SubmoduleをPrivate Repositoryからチェックアウトする

社内で扱うGithubのPrivate Repositoryで、別の社内Private Repositoryをsubmoduleをチェックアウトするときのメモ

# 問題
単純にPrivate Repositoryから、別のPrivate RepositoryをSubmoduleとして登録するだけだと、Github Action内でチェックアウトしてもURLが見つからずエラーになる

https://github.com/actions/checkout/issues/287

上のissueでも言及されている

# 参考
次の記事に書かれていることを行った

https://qiita.com/u_nation/items/8ff79a9831c05f3f1d1d

https://stackoverflow.com/questions/57612428/cloning-private-github-repository-within-organisation-in-actions

https://zenn.dev/tokiya_horikawa/articles/215637f23c8407

# 解決策
今回、submoduleはsshで取り込んでいたため(`git@~~`)、ssh方式で取り込むことにした。また参考にしたページでも触れられているように、tokenを用いる方法も存在する。セキュリティの観点などから、今回はssh鍵を作成する方法をとることにした。

## 1. ssh鍵の作成
まず自分のローカルPCでsshの鍵を作成する。コマンドは次の通りである。

```sh
$ ssh-keygen -t rsa -C ""
```

https://atmarkit.itmedia.co.jp/ait/articles/1908/02/news015.html

ただしこの時、パスワードは指定しない(指定しても良いかもしれないが、Github Action側で処理を行う必要があると考えられる)。

`-t`で鍵の種類を指定することができる(デフォルトでもRSAだが指定した)。`-C`でコメントを指定することができる。`-C`を指定しない場合、自分のローカルPCの名前が入るため、何も入れたくない場合は上記のように`""`を指定するのがよい。

注意点として、デフォルトでは鍵の名前が`$HOME/.ssh/id_rsa`であり、既に存在する場合は上書きされるため、必要ならば別ディレクトリに保存する必要がある。

## 2. 鍵の登録
いま、手元に秘密鍵`id_rsa`と公開鍵`id_rsa.pub`があるとする。行うことは、
- 秘密鍵`id_rsa`をPrivate Repository(submoduleを登録してあるRepository)に置く
- 公開鍵`id_rsa.pub`をSubmoduleのPrivate Repositoryに置く
ことである。

まず秘密鍵をPrivate RepositotyのSetting -> Secrets -> Repository secretsに置く。このSecretの名前を`SSH_KEY`と呼ぶことにする。

次に公開鍵をSubmoduleとして登録したPrivate RepositoryのSetting -> Deploy Keysに置く。 

注意点は秘密鍵を登録する際、

```
-----BEGIN OPENSSH PRIVATE KEY-----
body
-----END OPENSSH PRIVATE KEY-----
```

と、ヘッダーとフッターにあたる`-----BEGIN OPENSSH PRIVATE KEY-----`と`-----END OPENSSH PRIVATE KEY-----`を含める必要があることである。

## 3. workflowのyamlに記述
Github Actionを利用するためには、`.github/workflow`内のYAMLファイルを記述する必要がある。Submoduleをcheckoutするために、jobに次のように記述する。

```yaml
    - uses: actions/checkout@v2
    - name: ssh setting
      env:
        TOKEN: ${{ secrets.SSH_KEY }}
      run: |
          mkdir -p $HOME/.ssh/
          echo -e "$TOKEN" > $HOME/.ssh/id_rsa
          chmod 600 $HOME/.ssh/id_rsa
    - name: Checkout 
      shell: bash
      run: |
          git submodule sync --recursive
          git submodule update --init --force --recursive
```

まず秘密鍵を`env`にて指定している。ここでの名前は、秘密鍵の名前(secretsに登録したときの名前)にする必要がある。この秘密鍵をホームディレクトリの`.ssh`ディレクトリの下にコピーし、読み取り権限を与えている。これでprivate repositoryからもってきたsubmoduleをcheckoutすることができる。
【続・パパ必見】おつかい上手になるためのアプリ（追加機能）　#ノーコード  #LINE

##「おつかいアプリ」にお知らせ機能を追加##

「おつかいアプリ」に機能を追加してみました！
<font color="Red">**LINEからGoogleスプレッドシートのリンク（おつかい指令）が定期的に飛んできます**</font>:joy:

<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2122173/de51f40b-0bbc-75ff-7d31-7dc655a1299c.png">


##パパ逃げる##
そもそも「おつかいアプリ」というのは僕が先日作った、パパスキル向上アイテムです。

https://qiita.com/TAKA_xedge/items/d3bc95a1bb1006d5e0f4

簡潔に言うと、<font color="Red">**おつかいで買ってきてほしいものをあらかじめLINEに投稿しておくと、それがGoogleスプレッドシートに反映されて、お買い物チェックシートとして使える**</font>といったものです。

基本的にパシる側が情報を格納していく仕様で、パシられる側はチェックシートを開くためだけに操作します。

で、使ってみてわかったんですが、<font color="Red">**パシられる側（僕）はこのアプリを開きたくありません。笑**</font>

すると、スプレッドシート開かないのでミッションを達成することができません。笑

なので、今度は<font color="Red">**パシられる側が定期的におつかいリストを参照するような仕組み**</font>を外出しで考えました。

##追加機能はノーコードで##

IFTTTを使用しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2122173/396bf34f-b98e-1e4b-679f-8b3fb944c379.png)

If This　 ：　Date&Time
Then That ：　LINE

会社からの帰宅途中に通知が来てほしかったので、トリガーはLocation（隣の駅）を指定しようと考えていましたが、会社に行くときにも通知が来てしまうので、時間トリガーに変更しました。

これで、パパの隷属スキルはさらに高まりました。問題解決です:v:←

兎にも角にも、<font color="Red">**一部の機能だけをノーコードで実装する**</font>ってとてもアリだなって思いました:ok_woman: