OmniAICreator/Qiita-1.07M huggingface dataset:
初心者がGitHubを使ってみた話

0. 初めに

初めまして。TBTで電装班でandroidアプリを作っているとうちゃんと申します。
先日初めてGitを使ったので備忘録としてその内容をまとめてみました。

2.Gitとは

A. バージョン管理を簡単にしてくれるアプリ
初心者の立場での感想ですが概ね間違ってはいないと思います。

3.Gitを使うメリット

Gitを使う理由は、３つのメリットがあるからです。

1.更新履歴を記録し、後で確認したり前の状態に戻したりできる
2.共同作業ができる
3.異なる保存場所を切り替えられる

4.実際に使ってみる

1.適当なフォルダに適当なhtmlファイルを作る
![スクリーンショット 2022-08-25 012357.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2808210/266138c2-d798-b916-035e-feff497da4d8.png)
 2.visualstudioを開きターミナル→新しいターミナルを開く。
![スクリーンショット 2022-08-25 012659.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2808210/7feba480-4f30-e998-d80a-8cb7ea5ec05c.png)
この画面が出ればオーケーです。その後3.~9.の手順で入力していきます。
 3. $ git init をターミナルに入力する
 4. $ git add README.md をターミナルに入力する。
 5. $ git remote add origin "Githubのレポジトリのパス" をターミナルに入力する。
 6. $ git checkout -b main をターミナルに入力する。
 7. $ git add . をターミナルに入力する。
 8. $ git commit -m 'First Commit' をターミナルに入力する。
 9. $ git push -u origin main をターミナルに入力する。
 10.
![スクリーンショット 2022-08-25 014610.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2808210/840082d9-bfbf-c835-0c31-6e160fe0ff08.png)

この画面が出たらGithubをリロードする。
![スクリーンショット 2022-08-25 013905.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2808210/71d8224a-d1f4-ddc4-54c8-e36e9c41c559.png)
＜code＞の部分がこのようになったら完成。

5.まとめ
　Gitはバージョン管理を簡単にし、後で確認したり前の状態に戻したりすることができる。便利！
MySQL：複合ユニークのカラムにNULLがあった場合

NULLのイメージを誤解していたので、備忘録として書きます。
### 概要
- MySQLで複合ユニーク制約をしているカラムにNULLが入っている場合、ユニークとならないと知った
    - NULL = NULL とはならないため

### 例

idとnameとageで複合ユニーク制約があっても、NULLが含まれる場合ユニークとならない

|  id  |  name  | age |
| ---- | ---- | ---- |
|  1  |  foo  | 20 |
|  2  |  bar  | 30 |
|  2  |   bar  | NULL |

### 教訓
- 複合ユニークに使うカラムはNOT NULLにする

参考
[「NULLがUNIQUE制約に縛られないことを利用する」のは、正当なNULLの使い方 - 極北データモデリング](https://tgk.hatenadiary.org/entry/20120913/1347506946)
> NULLは「値がある(が、システムはその値を知らない)状態」
ファイルアップロード機能をファイル選択ボタン非表示で行う方法

## 前提
・ ファイルアップロード機能を作りたい人
・ 「ファイルを選択」ボタンを表示させたくない人

## ファイルアップロード
通常ファイルアップロード機能を作る場合、「input type="file"」にすると思うが、それだとファイル選択が表示される。

![スクリーンショット 2022-08-23 21.45.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2601625/00c0dca9-709e-a930-2954-94a215dece57.png)

```html
<form method="POST" action="/upload" enctype='multipart/form-data'>
    <input type="file">
</form>
```

こういった「ファイルを選択」ボタンを出さないようにするにはどうすれば良いのだろうか。
![スクリーンショット 2022-08-23 21.47.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2601625/151ea35a-257f-1e9a-e36f-b34ae9d18267.png)

## 解決策
「input type="file"」を非表示にし、divタグなどでファイルアップロードをするエリアを用意(今回でいうと
スクショの写真追加のエリア)し、labelタグで囲うとlabel配下要素のイベントを紐付けることができます。
それにより「class="img-contents"」エリアを押下すれば、「ファイルを選択」ボタン押下時の挙動が起こります。

``` html
<label>
   <form method="POST" action="/upload" enctype='multipart/form-data'>
   <div class="img-contents">
     <img class="img">
     <span class="photo">写真追加</span>
   </div>
   <input type="file" name="img" hidden>
   </form>
</label>
```

``` css
.photo {
  color: #ddd;
  font-size: 20px;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translateY(-50%) translateX(-50%);
}

.img-contents {
  width: 600px;
  height: 400px;
  border: 1px dashed skyblue;
  position: relative;
}

.img {
  position: absolute;
  width: 600px;
  height: 400px;
}
```

labelで囲ったエリアで特定の要素を要素を押下した際、「input type="file"」を発火させたくない場合、「preventDefault()」使えば下記の場合、「class="btn"」押下後、eventを実行することを抑制できます。

```js
$(document).on("click", ".btn", function (event) {
  event.preventDefault();
}); 
```

以上、 「ファイルを選択」ボタンを表示させないでファイルアップロードする方法でした。
Androidで保険業界の単語帳を作る vol.2　~画面を作成する~

# オブジェクト構成
単語帳に最低限必要な機能といえば単語の一覧を表示することと、データを保存するデータベースの2点かなと思ってます。
いろいろ調べていたところ、まあうさブラザーズさんが書いている以下のブログの記事のオブジェクト構成がヒントになるんじゃないかと思ったので、こちらを参考にしながら開発していこうかなと思います。

https://www.ma-chanblog.com/2021/02/android-listview.html

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2803693/9b5cc170-ed04-6727-23e3-7d528564098b.png)

「テキスト画面」は今のところ作るつもりはないので、メイン画面とデータベースとそれをつないでいるオブジェクトを作成していこうかなと思います。

今のところどんな風に開発するか、まったく見当がついていませんw

# メイン画面を作成する
メイン画面を作ろうと思いますが、記事を読むとメイン画面も「メイン画面」のレイアウトと「1行分のレイアウト」の２つに分けられるらしい、、、なるほど。

まずは「メイン画面」のレイアウトから。記事でもそこまで難しいことはやっていないみたいで安心しました^^
「ConstraintLayout」というレイアウトが画面の下地となるようなレイアウトになります。
他のView（文字とかボタンとか）と相対的に画面上にViewを配置できるレイアウトです。
そこにListView(データを一覧として表示するレイアウト)を貼り付けます。
ソースコードがこちら↓
```XML:main_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ListView
        android:id="@+id/mainList"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
```
idがListViewの名前、widthやheightが幅と高さ、appから始まる部分が"相対的に"の部分で、下地となるConstraintLayoutの４つの辺（上、下、右、左)にListViewの４つの辺をくっつけています。
記事にはフローティングアクションボタンが作成されてますが、単語を追加したりする予定は今のとこないのでカット。
とりあえずメイン画面は完成しました！

# 1行のレイアウトを作成する
つづいてListViewに表示させる１行分のレイアウトを作成していきます。
記事のようにテキストとボタンを組み合わせた行の場合、こういう作り方をするのだと思うのですが、
今回は単語だけ乗ればとりあえずはいいかなと思ってます。ただ将来的にボタンを付けたりできるように今のうちに作っておきます。
```XML:row_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/word"
        android:layout_width="match_parent"
        android:layout_height="70dp"
        android:gravity="center_vertical"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:textSize="24sp"/>
</LinearLayout>
```
一行の下地となるのはLinerLayoutというレイアウト。
これは横もしくは縦にViewを配置するレイアウトになります。
テキストだけの１行なので本領発揮していない気もしますが、ボタンとか配置したい場合は横並びで配置します。XML上で文字を入れてみるとこんな感じ↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2803693/ecb32f75-cf49-f641-fe29-741fb9d8cd33.png)

とりあえず画面はこんな感じ。
次回はデータベースを作っていきます！
rhel9-CRB リポジトリの使い方

RHEL 9 で libtirpc-devel や rrdtool-devel パッケージをインストールしようとするも，パッケージが見つからない．
[RHEL 9 の採用における考慮事項](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/9/html-single/considerations_in_adopting_rhel_9/index)には rhel9-CRB とあり， rhel9-CRB とはなにかを調べたメモ．

CRB は CodeReady Builderの略でした．[公式マニュアル](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/9/html/package_manifest/codereadylinuxbuilder-repository)．拡張リポジトリ的な位置付けでしょうか．
subscription-manager で rhel9-CRB リポジトリを有効にすれば解決．

```
# subscription-manager repos --enable=codeready-builder-for-rhel-9-x86_64-rpms
リポジトリー 'codeready-builder-for-rhel-9-x86_64-rpms' は，このシステムに対して有効になりました．

# dnf info libtirpc-devel
サブスクリプション管理リポジトリーを更新しています．
Red Hat CodeReady Linux Builder for RHEL 9 x86_64 (RPMs)                                                        3.8 MB/s | 2.5 MB     00:00
利用可能なパッケージ
名前         : libtirpc-devel
バージョン   : 1.3.2
リリース     : 1.el9
Arch         : x86_64
サイズ       : 251 k
ソース       : libtirpc-1.3.2-1.el9.src.rpm
リポジトリー : @System
repo から    : codeready-builder-for-rhel-9-x86_64-rpms
```
見つかりました．
プログラマとオンライン会議


# 僕は会議では基本的に口を出したくなる。

我慢との戦いだ。言うべきことと言わざるべきことのバランスを考え続ける。言うべきタイミングと言わざるべきタイミングのバランスを考え続ける。なかなか難しい。

# 人間同士の会話には高度な知性が要求されるという。

グループでの会話ともなればなおさらだ。仕事の会議であればなおさらのなおさらだ。

# 相手の意図に想像をめぐらす。沈黙の意味にも想像をめぐらす。

AさんからBさんへの質問の後に長い沈黙がある。僕は口を挟んで何かの思いつきで会話を埋めてしまいたくなる。だけど我慢する。そうするとBさんからいずれ答えが出てくる。会話を遮らなくて良かったと思う。

# 皆よく沈黙を我慢しているなと思う。

日本人は会議では発言が苦手らしい。だからだろうか。発言しないことに慣れているのかもしれない。もしくは僕がただせっかちなだけで他の人の方が遥かに会議能力の知性が高いのかもしれない。どうやら後者のような気もする。

# 発言できるのは同時に1人までだ。

他5人のメンバーがいれば5人はその間沈黙することになる。どうしたって沈黙の量のほうが多い。会議とは発言の場ではなくむしろ沈黙の場だ。

# 時間は限られている。

会議に無限の時間は使えない。思うことを思う存分に話す時間はいつだって足りない。リアルタイムの試合だ。人同士の感情にも配慮する必要がある。滅多なことは言えない。話の流れを遮らないように音声ではなくチャットに書き込んでみたが返信がない。どうやらチャットは誰も見ていないようだ。

# 会議の最中に人は何を考えながら参加しているのだろうか。

僕のようにあれこれと思考がめぐり続けているのだろうか。それとも意外にもあっけらかんとしたものなのだろうか。会議中の人の心というものが知りたい。オンライン会議だと会話も間合いが分かりづらい。ビデオをオフにしているメンバーもいる。発言する人もいれば発言しない人もいる。

# こんな事を考え続けていると発言の機会を逃す恐れがある。

他の人の話が一段落したところでようやく自分の意見をまとめて話してみる。今だという瞬間に自分の発言を挟み込む。ほんの数秒を逃せばもう二度とチャンスはやってこない場合もある。自分が言おうと思っていたことを他の人が言って褒められた場合には悔しい。変な言葉をこぼして滑った場合はいたたまれない。いつだって人間の感情というものが関わってくる。

# オンライン会議は難しい。

2022年8月23日

<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# Twitter

https://twitter.com/YumaInaura

<!-- Update From Qiita API -->
Dockerfileは、本番用と開発用に二つ作ろう

## 開発環境と本番環境の違い
先日、RailsアプリをAWSにデプロイしました

早速デプロイしたアプリの修正を行おうとローカルで起動しようとしたら起動せず..


それもそのはず。開発環境ではdocker-composeを使ってDBを起動してましたが、本番環境ではRDSを使ってるので、docker-composeから削除してあったのです

いちいちコメントアウトしたりして書き換えることもできるでしょうが、どこを修正すべきかわからなくなったりしそうで怖いし、何より面倒ですよね

## 開発環境用docker-compose ファイルを作る
- 本番環境用ファイル＝`docker-compose-prod.yaml`
- 開発環境用ファイル＝`docker-compose-dev.yaml`

今回はすでにデプロイしてしまってるので、開発環境用のファイルだけ追加で作ることにします

## 起動方法
開発環境で起動する場合は
```
$ docker compose -f docker-compose-dev.yaml up -d
```
-fオプションでファイルを指定できるんですね

## Dockerfileも変更したい場合
- 本番環境＝`Dockerfile.prod`
- 開発環境＝`Dockerfile.dev`

ビルドするなら
```
$ docker build -f Dockerfile.dev
```
docker-composeで起動するなら
```
docker-compose-prod.yamlversion: '3'
services:
  app:
    build:
      context: .
      dockerfile: "Dockerfile.dev"
```
- context ･･･ Dockerfileの所在
- dockerfile ･･･ Dockerfileの名称

のふたつを記載してあげる

[Dockerfileを本番環境と開発環境で分けたいとき](https://abillyz.com/watanabe/studies/467)
DataGridViewの表データをエクセルファイルに出力する(C# WinForm)

DataGridViewの表データを、エクセルファイルに変換するプログラムを作成しました。

## デモプロジェクト
https://github.com/panda728/DataGridViewDump

2022/09/16追記：列の並び替えにも対応しました

Windwosフォーム画面イメージ
![image](https://user-images.githubusercontent.com/16958552/186148469-1d721265-357f-4f95-8ba7-0ed059f24e76.png)

エクセルファイル画面イメージ
![image](https://user-images.githubusercontent.com/16958552/186148816-5c4ac74e-59df-46fd-91c6-7446cfa830a1.png)

## 使用ライブラリ
https://github.com/panda728/FakeExcelSerializer

C#からエクセルファイルを出力するライブラリです。
ClosedXmlと比較して、3倍～8倍速いです。（100行程度の場合。10万行だと圧倒的な差がでます。）
ただし凝った装飾などは指定できません。（数値書式、日付書式のカスタマイズは可能）
ですので、お手軽にダンプ出力したい用途に向いています。

## コード
DumpExcelHelper.cs の拡張メソッドとしてToExcelFileが定義されています。
呼び出し方は以下になります。

~~~C#
dataGridView1.ToExcelFile(saveFileDialog1.FileName);
~~~

## DumpExcelHelper 処理内容
DataGridViewのDataGridViewRowの値を
シリアライズするクラスを用意します。
タイトル行生成とシリアライズの処理を記述します。

~~~C#

public void WriteTitle(ref ExcelSerializerWriter writer, DataGridViewRow value, ExcelSerializerOptions options, string name)
{
    var serializer = options.GetRequiredSerializer<string>();
    var cells = value.Cells.OfType<DataGridViewCell>()
        .OrderBy(c => c.OwningColumn.DisplayIndex);
    foreach (var cell in cells)
    {
        serializer.Serialize(ref writer, cell.OwningColumn.HeaderText, options);
    }
}

public void Serialize(ref ExcelSerializerWriter writer, DataGridViewRow value, ExcelSerializerOptions options)
{
    var serializer = options.GetRequiredSerializer<object>();
    var cells = value.Cells.OfType<DataGridViewCell>()
        .OrderBy(c => c.OwningColumn.DisplayIndex);
    foreach (var cell in cells)
    {
        serializer.Serialize(ref writer, cell.Value, options);
    }
}
~~~

クラスをプロバイダに登録します。
~~~C#
readonly IExcelSerializerProvider _dataGridViewExcelProvider
    = ExcelSerializerProvider.Create(
        new[] { new DataGridViewExcelSerializer() },
        new[] { ExcelSerializerProvider.Default });
~~~

準備が整ったのでメインの出力処理です。

シリアライザの設定クラスを用意して、ToFileメソッドを呼ぶとファイルが作成されます。
（フォルダ作成・削除の権限が必要です。内部で作業フォルダとファイルのZIP圧縮を行うため）

なお、今回はエクセルの1行目にタイトル行を表示したいのでHeaderTextを抽出します。

~~~C#
var newConfig = ExcelSerializerOptions.Default with
{
    Provider = _dataGridViewExcelProvider,
    CultureInfo = CultureInfo.CurrentCulture,
    HasHeaderRecord = hasHeaderRecord,
    HeaderTitles = headerTitles ?? Array.Empty<string>(),
    AutoFitColumns = autoFitColumns,
    NumberFormat = "#,##0.000;[Red]\\-#,##0.000",
};
ExcelSerializer.ToFile(value, fileName, newConfig);
~~~

C#側のデータ型に応じて、エクセルのほうも文字、数値、日付に対応します。
例えば、文字列型の場合は、エクセルでも文字扱いになりますので、前０があっても安心です。

![image](https://user-images.githubusercontent.com/16958552/186148816-5c4ac74e-59df-46fd-91c6-7446cfa830a1.png)


#### （付録）DataGridViewのデータ取得処理の概要
~~~C#
foreach (var row in dataGridView1.Rows.Cast<DataGridViewRow>())
{
    foreach (var c in row.Cells.OfType<DataGridViewCell>())
    {
        Debug.Write($"{c.Value},");
    }
    Debug.WriteLine("");
}
~~~


## シリアライザについて
IEnumerable<T>から型に応じた値を取得する処理は
CysharpさんのWebSerializerの方式を使用しています。

https://github.com/Cysharp/WebSerializer

拡張性もあり高速に動作する素晴らしい設計です。
database "データベース名" does not existの解決方法

# docker環境にてrails開発している最中にエラーが出る
途中gemを追加後新規にdatabaseを立ち上げlocalhost:3000に接続したところ
>FATAL:  database "データベース名" does not exist

とエラーが出てしまい接続が出来ない。
エラーを直読みするとdatabase"データベース名"が存在しないと言われている。

なぜ？
今までこんなエラー表示されていなかった為、調べながら解決してみる。
まず定義されているか確認にためdatabase.yml確認するとしっかり定義されている。

続いてコンテナアプリ内に入ります(下記実行)
~~~
docker compose exec アプリ名 bash
~~~

続いて、databaseが無いなら作成します
~~~
rails db:create
~~~

>Running via Spring preloader in process 56
Created database 'データベース名'

ん・・・できたっぽい？
ってことでもう一度localhost:3000に接続してみとちゃんと接続されました！

調べても案外初歩的なエラーの為、今回載せてみました。
参考になればと思います。
人事のおじさんプログラミングを学ぶ Day6「論理演算子」

書籍『確かな力が身につくJavaScript「超」入門 第2版』に沿って、
時間で異なるメッセージを表示する～論理演算子をやってみた。
![2022-08-23_vsc.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2783084/c2dc24e5-1e2d-0e45-6228-fdd824e3153d.jpeg)
    ![2022-08-23_web.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2783084/6c65d146-fad5-d8ea-ac3b-f30896af00d1.jpeg)
[git]操作時にdetected dubious ownership in repositoryが発生するようになった

# 初めに

gitのリポジトリを載せてている環境があり、
Ansibleで環境を新しくサーバを構築したところなぜかgitの操作が通らずに失敗するようになった。
問題となっているのがgitだったのでサーバの中に入り確認したところ、
各種操作で以下のエラーが確認された。

```
$ git pull
fatal: detected dubious ownership in repository at '/xxx/xxx'
To add an exception for this directory, call:

	git config --global --add safe.directory /xxx/xxx
```

以前同じ建て方をした環境では発生せずに新しく立てた環境のみ発生する事象であった。

# 原因

gitのバージョンが2.35.2以上で`safe.directory`パラメータの追加に関連する変更が起因だった。
https://git-scm.com/docs/git-config/2.35.2#Documentation/git-config.txt-safedirectory

成功している環境はgitのバージョンが`2.32.0`だが今回建てた環境は`2.37.1`でこのバージョンを跨いだため発生した。

なぜバージョンが違うのか後で確認したところアプリに直接関わるphp等のバージョンは固定していたが、
git等直接関わらない部分がインストールの指定の時に固定されていなかったので、
立てた時期の違いによってバージョンが異なってしまった。

# 対処方法

説明に記載の通りのコマンドを実行すれば解決する。
rootなど予期せぬユーザでgit pullをして新規ファイルの権限がrootで作成されてしまった...
ということがないようにめんどくさがって`--system`で設定しない方が無難だと個人的には思う。

対象の環境はAnsibleでの構築かつ該当ユーザはそのリポジトリ一つしか取り扱わなかったので、
以下をAnsible側に追記することで解決。

```yml
    - name: add safe directory
      git_config:
        name: safe.directory
        scope: global
        value: '/xxx/xxx' #リポジトリの配置先
```

gitのコマンド的には`--add`を使うことで既存の設定に追加する形でパスを追加できるようですが、
Ansible側で分割上複数箇所で設定したい場合は何が正解となるのかは不明。
(`--add`は既存のパラメータと同じ値が既にあっても追記する挙動のようです)

# そのほかの解決はあるか？(要確認)

> https://git-scm.com/docs/git-config/2.35.2#Documentation/git-config.txt-safedirectory
> By default, Git will refuse to even parse a Git config of a repository owned by someone else

記載を見る限り所有者が他の場合に発生するもののような記載が見当たる。
ただ今回.gitフォルダの権限を確認し所有者で実行していることは確認しているのになぜか発生している。

一応リポジトリを配置している一つ下のディレクトリの所有者が`root:root`であったため、
権限を試しに今回リポジトリを設置するユーザに変更してみたがこれでもNGであった。

特定の開発環境などであれば個別に`safe.directory`を配置すれば良いと思うが、
開発PC等複数のリポジトリを持つ場合はどうするのが正解となるのだろうか(そもそも発生するのか)。

一応`*`を指定することで全ディレクトリOKができる例がいくつか見つかったので、
開発PCでバージョンを上げて発生するのであれば最悪この対応をするか、
せめてリポジトリがまとめて配置してあるディレクトリは以下を指定するのがよさそうではある。


追記(同日)
手元の環境(macosx)でgitのバージョンを上げてみてgit操作をしてみたがこの事象は発生しなかった。
やはり権限等何かしらの要因がある可能性があるので解決可能ならそちらを解決するのが良いかもしれない。
docker exited(7)解決方法

# docker 起動時 exited(7)
docker環境にて開発しようとdocker立ち上げ後、
下記実行
~~~
docker compose exec アプリ名 bash
~~~
あれ？コンテナ内に入れないぞ・・・。

upした際には、エラーも発生せずに実行出来ている感じなのに

>service "アプリ名" is not running container #1

と表示されてしまいコマンド実行出来ない。

今まで出来ていたのになぜ・・・？
最近変更したところと言えばgemfileに新しいgemを追記したくらいのため、変更内容が反映されてないのかと思い一度buildしてみる。

~~~
docker compose build
~~~

その後もう一度立ち上げてみる。

~~~
docker compose up -d
~~~

無事runになり解決しました。
読み込みをしていなかっただけだったみたいです。
バリデーション(validate)かけたuseFormでvalueで値表示できない (mantineだけど通常のuseFormも同じかな？)

# 結論: form.setValuesを使う

~~~js
const editUserToForm = (recoilEditUser: RegisteredUsers) => {
    form.setValues({
      id: "5",
      name: "へのへのもへじ",
      age: "39",
      todo: "味噌がもうないから買いに行く",
      email: "todo@email.com",
    });
  };

~~~

## 上記に対してのuseForm

~~~js

import { useForm } from "@mantine/form";

export const useUserForm = () => {
  const form = useForm({
    initialValues: {
      id: "",
      name: "",
      age: "",
      todo: "",
      email: "",
     
    },

    validate: {
      name: (name_value) =>
        name_value.length < 1 ? "名前は必須入力です" : null,
      age: (age_value) =>
        age_value.length == 0
          ? null
          : /(^\d?\d{1}$)|(^1[0-4]{1}\d{1}$)|(^150$)/.test(age_value)
          ? null
          : "年齢は数字で150以下で入力してください",
      todo: (todo_value) =>
        todo_value.length < 1 ? "todoは必須入力です" : null,
      email: (mail_value) =>
        mail_value.length === 0
          ? null
          : /^\S+@\S+$/.test(mail_value)
          ? null
          : "メールアドレス形式で入力してください",
    },
  });

  return form;
};
~~~

## このuseFormのform
~~~js
 <form onSubmit={getFormUser}>
          <TextInput
            disabled
            label="id"
            placeholder="id"
            {...form.getInputProps("id")}
          />
          <TextInput
            label="名前"
            placeholder="Name"
            {...form.getInputProps("name")}
          />
          <TextInput
            mt="md"
            label="年齢"
            placeholder="年齢を入力してください"
            {...form.getInputProps("age")}
          />
          <TextInput
            mt="md"
            label="todo"
            placeholder="適当な文字"
            {...form.getInputProps("todo")}
          />
          <TextInput
            mt="md"
            label="Email"
            placeholder="your@email.com"
            {...form.getInputProps("email")}
          />
          <Button className="bg-black" type="submit">
            Submit
          </Button>
        </form>
~~~

## 反映されないパターン
バリデーションかけたuseFormだと「へのへのもへじ」は表示されない
~~~js
         <TextInput
            label="名前"
            value="へのへのもへじ"
            {...form.getInputProps("name")}
          />
~~~
## 反映されるパターン
バリデーションかけていないもの？`...form`を使っていなければvalueで動く
~~~js
          <TextInput
            value="へのへのもへじ"
            onChange={(event) => setValue(event.currentTarget.value)}
          />
~~~
・・・とりあえず実装重視だったので原因追求はあとです

参考
[ReactUIライブラリMantineのフォームAPIを使用する](https://dev.classmethod.jp/articles/mantine-form/)
#オブジェクトの移動

# :star2:オブジェクトの移動・ジャンプ:star2:   

# :bulb:成果:bulb:
<details>
  <summary>translate メソッド</summary>
・座標の数値を更新していく
・166,207
</details>

```
// マウスのクリックで移動(座標の更新)
// ---------------------------------------------------------  
    float speed = 0;
    void Start()
    {
        Application.targetFrameRate = 60;    
    }
    void Update()
    {
        if(Input.GetMouseButton(0))
        {
            this.speed = 0.2f;
        }        
        transform.Translate(this.speed,0,0);
    }
// ---------------------------------------------------------
```

<details>
  <summary>AddForceメソッド</summary>
Rigidbody2D コンポーネントのAddForceメソッドを利用する
P267
</details>

```
    Rigidbody2D rigid2D;
    float moveForce = 20.0f;

    void Start()
    {
        Application.targetFrameRate = 60;    
        this.rigid2D = GetComponent<Rigidbody2D>();
    }
    void Update()
    {
        if(Input.GetMouseButton(0))
        {
            this.rigid2D.AddForce(transform.right*this.moveForce);
        }        
    }
```
Python小技集 - #2 多次元リストの平坦化 (flatten)

こんにちは！beatbox4108です。
今日はPythonで多次元リストを平坦化 (flatten)する方法について説明していきます。

# まず平坦化とは?
平坦化とは、簡単に言えば、
```python3
[
    [0,1,2,3,4],
    [5,6,7,8,9],
    [10,11,12,13,14]
]
```
を
```python3
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14]
```
のようにネストされたリストのネストを外すような操作です。

このような操作を行う方法はいくつかあります。
# 1.sum関数を使う方法
pythonのsum関数には初期値が設定できるので、その初期値に`+`演算をする原理で合成してしまおうという魂胆です。
```python3
l=[[0,1],[2],[3,4,5]]
print(sum(l,[]))
```
```python3
[0,1,2,3,4,5]
```
:::note warn
第二引数にリストを設定するのを忘れないようにしましょう。
:::
# 2. itertools.chainを使う方法
`itertools.chain`の`from_iterable()`を使えば、リストだけでなく、イテレーターを返すイテレーターならすべて使えます。
ただ、戻り値もイテレーターなので、list()関数などで変換するのを忘れないようにしましょう。
```python3
from itertools import chain

l=[[0,1],[2],[3,4,5]]
print(list(chain.from_iterable(l)))
```
```python3
[0,1,2,3,4,5]
```
# 3.　リスト内包表記
```python3
l=[[0,1],[2],[3,4,5]]
print([e for e in i for i in l])
```
```python3
[0,1,2,3,4,5]
```
# 4. pandas.core.common.flattenを使う方法
```python3
from pandas.core.common import flatten

l=[[0,1],[2],[3,4,5]]
print(list(flatten(l)))
```
```python3
[0,1,2,3,4,5]
```
* * *
いかがだったでしょうか。なんかどれもこれも似たような感じでしたね...
ちなみにndarrayには元から関数が用意されています。優秀！
それでは、また次回もお楽しみに！
PowerAutomateの「選択」で string() が無視される

今回もPowerAutomateを使ってフローを構築・運用している過程で遭遇した問題のトラブルシューティングです。

# Problem

オブジェクトの配列に対して「選択」（Select）アクションを使用し、要素オブジェクトのプロパティの選択／変換を行うとき、`string()`関数が無視される。

例えば次のような配列があるとしましょう。この配列の要素オブジェクトには`foo`というプロパティがあり、文字列型だったり数値型だったりします：

```json
[
  {
    "foo": "123"
  },
  {
    "foo": "456"
  },
  {
    "foo": 789
  },
  {
    "foo": "012"
  }
]
```

ここで、プロパティ`foo`をすべて文字列型に変換するとします：

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/16afba3a-1ae8-a293-b8b8-dcf60f85002f.png)

「Map」欄の`fooString`に対応する値には 式`string(item()['foo'])`を指定します。

これを実行すると、結果は思いもかけないものになります：

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/e92e76c5-1be9-3f3e-9b78-64c97bde12eb.png)

```json
[
  {
    "fooString": "123"
  },
  {
    "fooString": "456"
  },
  {
    "fooString": 789
  },
  {
    "fooString": "012"
  }
]
```

つまり数値型から文字列型への変換が行われていません。。

おまけに「選択」アクションの「Switch Map to text mode」ボタンを押したり、フローの詳細画面に戻ったあと再度編集画面に遷移したりすると、式`string(item()['foo'])`は勝手に式`item()['foo']`に変換されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/c8e834ab-239b-27db-3045-fcf50037c73f.png)

原因は不明です。
PowerAutomateが自動的に行う式の最適化のバグだろうと推測していますが実際のところはわかりません。
ちなみにこの問題はオブジェクトの配列でのみ発生し、文字列型の配列では発生しません。

# Solution

対策として `string()`の代わりに`concat('', ...)`を使用します。
つまり `string(item()['foo'])`の代わりに `concat('', item()['foo'])`と記述します。
The selected AVD is currently running in the Emulator

流れはこちら。
① advファイルを検索、確認する
②　　advファイルを削除する

## ①advファイルを検索、確認する


    ls ~/.android/avd/


多分下記のような感じでadvとiniファイルが表示されます。

    Pixel_4a_API_32.avd     Pixel_4a_API_32.ini     Pixel_5_API_32.avd      Pixel_5_API_32.ini


## ②advファイルを削除する

今回はPixel_5_API_32を消したかったので、下記コマンドを実行しました。

    rm ~/.android/avd/Pixel_5_API_32.avd/*.lock

そうするとWipeしたり編集したりできます。

## まとめ

データを削除したいのになぜかできずにAndroid Studioを再起動したりEmuratorを強制終了したりめんどくさいなぁと思いつつやってたんですが調べたら割と簡単な方法あったので、忘備録がメインですが共有です。

どなたかの参考になれば幸いです。
SAA取得までの道のり

皆様こんにちは。
今回はSAAの認定を取得したので、それまでの道のりをお話しさせていただきます。

## はじめに
まず、自分がAWSを利用したり学習を始めたのが去年の9月からなので、AWS歴は約1年程度です。
クラウドサービスについてざっくりとした理解はあるものの、それがなんなのか説明しろと言われると口ごもるくらいのレベル感でした。

## 受験
CLFについては学習3ヶ月目で受験して一発合格だったので、そのままの勢いで7ヶ月目にSAA受験しました。
しかしあえなく撃沈。。。

点数についてはあと1~2問合っていれば合格という結果だったのですが、問題の手応えとしては全くわからないものもそこそこあったので、おそらく運によるところが大きかったのだと思います。
(*学習には[通称オレンジ本](https://www.amazon.co.jp/AWS%E8%AA%8D%E5%AE%9A%E8%B3%87%E6%A0%BC%E8%A9%A6%E9%A8%93%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88-AWS%E8%AA%8D%E5%AE%9A-%E3%82%BD%E3%83%AA%E3%83%A5%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%88-%E3%82%A2%E3%82%BD%E3%82%B7%E3%82%A8%E3%82%A4%E3%83%88-NRI%E3%83%8D%E3%83%83%E3%83%88%E3%82%B3%E3%83%A0%E6%A0%AA%E5%BC%8F%E4%BC%9A%E7%A4%BE/dp/479739739X)と[Udemyの問題集](https://www.udemy.com/share/101rfM3@7CaCsfrvzer2WpR_tAyXKjFnHJ8Ui-k8iQ60Gpr6PKu3Zz0wrQAZNB5LYosA3wOGBQ==/)を利用しました。)

ここで思ったのは、CLFは単語とその概要がざっくり分かれば受かるけど、SAAはアーキテクチャの読み書きがある程度できないと受からないなということです。

しかし、暗記が苦手な自分は順序立てて一から結びつけて理解しないとおぼえられない質で、問題をひたすら解き進めてもなかなか記憶が定着せず、時間が経つと一度解いた問題でも忘れてしまうというような状態でした。

## 学習
そこで自分の中でのブレイクスルーとなったのは下記サイトです。

Gatewayが多過ぎて何がなんなのかわからない？AWSのGateway全種類解説！ーその１、その2
https://blog.serverworks.co.jp/aws-gateways-1
https://blog.serverworks.co.jp/aws-gateways-2

それぞれなんかしらの入口または出口にっなっているということはざっくり理解していたのですが、実際の問題となると似たような単語がいっぱいでどれが正しいのかさっぱりでした。
しかし、上記のサイトではそれぞれ具体的な利用シーンを挙げて比較してあったので、自分でもすごく納得したのを覚えてます。

アーキテクチャの改善を問う問題ではこの付近の知識を問う問題が頻出しており、理解していくと65問の中に同じようなことを問う問題が何問か出てくることに気づきました。
1回目受験した時はそれがわからなかったので、そこまで問題を読み込めていなかったのでしょう・・・。

そして、社内でC02期限直前勉強会を開催していただいたこともあり今回無事に合格することができました。

## 最後に
とりあえず今言えることはC02の期限が今月末なので、現在学習している人は今月中に合格できるよう頑張ってくださいということです。
また、自分みたいに暗記が得意でないかたは問題をいっぱい解くよりひとつひとつの問題について、わかる人と議論しながら深く読み込んでいくのもありだと思います。

この記事がSAA受験されるかたの一助になると幸いです。
typescript 型通してmap()から要素を取得する　map()の~.idとか~.nameが欲しい時

# ‘DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>’ に割り当てることはできません。
## もともとのきっかけのエラー文
~~~
(property) edit_user_id: string | undefined
型 ‘{ children: string; onClick: (e: MouseEvent<HTMLElement, MouseEvent>) => Promise<void>; edit_user_id: string | undefined; }'
を
型 ‘DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>’ に割り当てることはできません。
  プロパティ ‘edit_user_id’ は型 ‘DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>’ に存在しません。
~~~


## 「data-」という形でカスタムデータ属性を作成してmapで使う
下記のような形で定義する
~~~js
const rows = props.data.map((item) => (
    <tr key={item.name}>
      <td>
        {/* data-edit_user_idがそれ　 edit_user_idだとエラーが出る*/}
        <button onClick={fetchEditUserId} data-edit_user_id={item.id}>
          編集
        </button>
      </td>
      <td>
      {/* data-delete_user_idがそれ　 delete_user_idだとエラーが出る*/}
        <button onClick={fetchDeleteUserId} data-delete_user_id={item.id}>
          削除
        </button>
      </td>
    </tr>
  ));
~~~

## 使う時は`e.currentTarget.getAttribute("data-edit_user_id")`とかする

~~~js
// 削除ボタン
   const fetchDeleteUserId = (e: React.MouseEvent<HTMLElement>) => {
    const id = e.currentTarget.getAttribute("data-delete_user_id");
    // nullの可能性を排除
    if (!id) {
      return;
    }
    // 取得したidを渡す
    deleteUser(id);
  };
~~~
や
~~~js
 const getUserById = useGetUser();
  // 編集ボタン
  const fetchEditUserId = async (e: React.MouseEvent<HTMLElement>) => {
    // ①押した変種ボタンからedit_user_idに格納されているidを取得
    const id = e.currentTarget.getAttribute("data-edit_user_id");
    if (!id) {
      return;
    }
    ~~~~~~他省略
~~~
みたいにする

以上
型通すのにかなり悩まされたのでメモを残す
`data-`でないとダメとかは、わかんないって・・・

参考
[data-*](https://developer.mozilla.org/ja/docs/Web/HTML/Global_attributes/data-*)
[【React/TypeScript】onClickなどのイベント処理で要素ごとに引数を渡したい場合](https://qiita.com/tobita0000/items/9cfa933324a3f6fe504d)
駆け出しプログラマのAtCoder日記　２日目

# はじめに
はじめまして、SLOTREと申します。
最近、pythonのお勉強をはじめたばかりの駆け出し君です。
作りたいものもあるけれど、まずは基礎力をつけるために・アルゴリズムを理解するためにAtcoderで勉強をはじめてみました。
ぜひ、こうしたら良いよ！ってアドバイスあれば教えていただけるとありがたいです。

# やってみた問題
人1～人iまでのリストが与えられて、注目する人P(リストの最後に加える)は人1の何世代前ですか？って問題。
人は3人、注目する人をPとすると、人1、人2、人3、Pのリストになって人1はPの3世代前だよ！って答えになる。
正直、この2行を理解するのに結構かかってしまった・・・
もしかして、プログラミング力より国語力高めないといけない・・・？ｗ

・問題文 [B - Ancestor](https://atcoder.jp/contests/abc263/tasks/abc263_b)
N 人の人がいます。N 人の人には人 1, 人 2,…, 人 N と番号がついています。
人 i(2≤i≤N) の親は人 Piです。
ここで、Pi <i が保証されます。
人 1 が人 N の何代前か求めてください。
（見づらい方は、リンク先を見てみてください）

# コード
```python3:Ancestor.py
import numpy as np

# ---定義部---
P = int(input()) #注目する人
number = input() #世代のリスト（人1～人i）
array = np.array(number.split(" "),dtype = np.int)
gen = np.append(array, P)
last = -1
top = 0
gen_ago = 0 #何世代前か
gen_now = gen[last]
target = gen[top] #人1

# ---処理部---
while gen_now != target:
  gen_now = gen[last]
  last -= 1
  gen_ago += 1
print(gen_ago - 1)
```

# 考え方
とりあえず、与えられたリストの末尾に注目する人Pをくっつけるみたいなのでつけました。
そこから、target(人1)にgen_nowが同値になるまでひたすらにループさせます。
そして、こうすると注目する人Pも1世代に含まれてしまうので、ー１した数を表示させてます。

# 感想
正直、問題で与えられる値を見ると全部1,2,3,4・・・と並んでいるので、P-1を表示させればいいんじゃないかと思いました。
ただ、それだと練習にならないので2,3,5,7・・・みたいに飛び飛びになる場合もあると考えてやってみました。
なんとなく、Pも含んだリストを作るのってもっと簡単になるんじゃないかな・・・？とも思いましたが、自分ではわからなかったのでこうなってます。

# 疑問点
```python3:定義部
import numpy as np

# ---定義部---
P = int(input()) #注目する人
number = input() #世代のリスト（人1～人i）
array = np.array(number.split(" "),dtype = np.int)
gen = np.append(array, P)
```
この部分なんですが、下記のようにすると、「'NoneType' object is not subscriptable」というエラーがでてしまいました。
```python3:エラー出る定義
# ---定義部---
P = int(input())
number = list(input())
gen = number.append(P)
```
僕の理解としては、リストが空っぽなのに、リストの最後をとってくる等の処理をしようとしているから、python君が空っぽのリストですよ・・・添え字なんかありませんよ・・・とエラーを出してくれているという理解です。
ただ、僕としてはlistに対してappendでPを最後につける処理をしているはずなのに、なぜNoneType型になってしまっているのかがわかりませんでした。
もし、お優しい有識者の方がいらっしゃれば解説していただけるとありがたいです。
Unityのアニメーターで、サイクルオフセットが使えない？

こんにちは、ユーゴです。
今回は、Unityでアニメーター(Animator)を使っていたときに起きた問題と解決策を紹介します。
ちなみにタイトルには「サイクルオフセットが使えない」とありますが、厳密には「欲しかったのがサイクルオフセットじゃない」です。

# やりたいこと
アニメーターで「アニメA → アニメB」に遷移する時、アニメBの冒頭数秒を切り取りたい。
また、「アニメAが10秒・アニメBが10秒」の時、アニメBの冒頭5秒(任意)を切り取って「アニメAが10秒・アニメBが5秒(任意)」にしたい
![img1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2607452/60fbf7b3-f83b-db28-64cc-cef03b97bd21.png)

# やったこと＆起きた問題
サイクルオフセットを使う(0~1の割合で指定。10秒なら0.5で5秒)。
しかし、上記の例だと、アニメBが10秒のまま変わらない。
![スクリーンショット 2022-08-23 19.58.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2607452/53e6f0bc-1fa3-946e-ef85-cd3a2f066de9.png)

# 原因
Cycle Offsetは、**開始と終了をずらす**。つまり、カットしたかった冒頭は、末尾に付け足される。
![img2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2607452/ffd73964-5408-3199-4fb0-d4a60bcab394.png)


# 解決策
Cycle Offsetではなく、「Transition Offset」を使う。同じく、0~1の割合で指定。
![スクリーンショット 2022-08-23 20.11.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2607452/2e2500d5-8bab-06dc-031c-a99ec6482d5f.png)

# ちなみに
私は、VRChatでアニメーターをいじっている時に遭遇した問題でした。アニメーター内部に遅延処理を入れたかったため、10秒ある空のアニメーションを用意し、望みの秒数だけそれを切り取って実装しようとしました。しかし、10秒という時間が変わらず、しかも空のアニメーションなので何が起きているのか分かリませんでした...
結局、別バージョンで別プロジェクトを立ち上げ、2Dにした上でオブジェクトを用意し実行しました。その結果、そもそもサイクルオフセットの使い方が違ったということでした...(T T)

# まとめ
いかがだったでしょうか。今回は、アニメーターでサイクルオフセットが使えないという問題の解決を紹介しました。厳密には「欲しかったのがサイクルオフセットじゃない」でしたが...
このように、初歩的なミス紹介から、かなりニッチで高度なテクニックまで幅広く扱っていく予定です。もし気に入っていただけましたら、LGTM&フォローの方よろしくお願いいたします。
Gmailがなかなか届かない時の対処法


# この記事の対象者
・Gmailの受信が遅いことがある人
**・Gmail以外のドメイン（○○○.jpなど）をGmailで受信している人**

# Gmailが来ない！
送られてきたはずのGmailが全然届かないこと、ありませんか？
メールとはいえ急いで返信しなければならない場面は結構あり、受信が遅れると非常に焦りますよね。
ブラウザを何度もリロードしたり、PCを再起動してみても残念ながら効果はありません。
この前は、「ワンタイムパスワード：○○○　　このパスワードを5分以内に入力してください」というメールが１時間後に届いてました。詰みです。

# 対処法
そんな困ったGmailですが、ちゃんと対処法が存在していました！

１．	Gmailの右上の歯車のアイコンをクリック
２．	「すべての設定を表示」をクリック
 ![画像1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2375098/ce4bb5ea-c0d8-4fa8-2905-5e6d0d3035b2.png)

３．「アカウントとインポート」タブをクリック
４．「他のアカウントのメールを確認」内の「メールを今すぐ確認する」をクリック
 ![画像2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2375098/0bec103b-26fd-d897-7203-096695cc9159.png)


**来ました！！**
 ![画像3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2375098/d7a4ce11-ce00-18e6-db96-382327034350.png)


５．受信トレイを確認する
受信トレイを確認すると、新規にメールを受信しているはずです。

# Gmail以外のメールが届く仕組み
メールが送信されると、まずは登録してある別のサーバー（エックスサーバー、さくらサーバーなど）にメールが届きます。Gmailはそれを定期的に確認しに行って、Gmailに持ってきてくれます。常に確認が行われているわけではないことがメールが遅れて届く原因だったわけですね。
そこで、手動で確認を行ってあげることですぐにメールを受け取ることができます。

# あとがき
いかがでしたでしょうか。この情報がGmailの受信の遅さに悩む人のお役に立てば幸いです。
WebMSXでARKファイルを解凍してみた

# はじめに
Lhaplusなどでarc(ark)ファイルを解凍できるが、色んなツールの使い方を記事化しておく。
環境：Windows 11

# ARKファイルの入手

http://www.pc88.gr.jp/softlib/index.php?action=list_file&anum=1&gnum=85

から CPMEMU.ARK をダウンロードする。

# UNARCの入手

https://www.chiark.greenend.org.uk/~jacobn/cpm/cpmfiles.html

から UNARC.COM を検索するとftpのurlが得られる。
ftp://ftp.mayn.de/pub/really_old_stuff/cpm/archive/starter-kit/unarc.com-z80

```
C:\Projects\etc\MSX>ftp
ftp> open ftp.mayn.de
filebus.gefoekom.org に接続しました。
220 GeFoeKom e.V. FTP Server
200 UTF8 set to on
ユーザー (filebus.gefoekom.org:(none)): anonymous
331 Anonymous login ok, send your complete email address as your password
パスワード:(なし)

(中略)

ftp> bin
200 Type set to I
ftp> get pub/really_old_stuff/cpm/archive/starter-kit/unarc.com-z80
200 PORT command successful
150 Opening BINARY mode data connection for pub/really_old_stuff/cpm/archive/starter-kit/unarc.com-z80 (4736 bytes)
226 Transfer complete
ftp: 4736 バイトが受信されました 0.08秒 59.20KB/秒。
ftp> bye
221 Goodbye.
```

unarc.com-z80をunarc.comにリネームする。

# WebMSXを使う

## MSX-DOS2の起動

https://webmsx.org/

- 右下の歯車アイコン[Settings]をクリックし[Select Machine]-[MSX turbo R Japan (NTSC)]を選択する。
- 左下のフロッピーアイコン[Drive A]をクリックし[Add Boot Disk]を選択する。
- 左下の電源アイコン[System Power]をクリックし[Reset]を選択する。

## ARKファイルの解凍

unarc.com と CPMEMU.ARK をWebMSXウィンドウの[Drive A]の[+ FILES]にドラッグ&ドロップする。

- 左下のフロッピーアイコン[Drive B]をクリックし[Add Blank Disk]を選択する。

```
mode 80
unarc cpmemu b:
```

![WMSX Screen.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257554/c1333c4b-b41c-17ab-3da7-182db4788efc.png)

- 左下のフロッピーアイコン[Drive B]をクリックし[Save Disk Image]を選択する。

ファイル名を webmsx.dsk とする。

# dskファイルの解凍

## DiskExplorerの場合

https://hp.vector.co.jp/authors/VA013937/editdisk/

webmsx.dsk を[plain image]として開く。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257554/68738887-b068-e34f-43f6-f29e9028deb5.png)

## DskToolの場合

https://www.msx.org/downloads/related/disk

のDskTool 1.12から dsktool.zip をダウンロードする。
DskTool.exe と webmsx.dsk を作業ディレクトリにコピーする。

```
C:\Projects\etc\MSX>dsktool e webmsx.dsk
DSK Tool v1.2
Copyright (C) 1998 by Ricardo Bittencourt
Updated 2010 by Tony Cruise
This file is under GNU GPL, read COPYING for details

extracting CPM.DOC
extracting CPM.MAP
extracting CPMB.COM
extracting CPME.COM
extracting CPMS.COM
extracting CPMX.COM
```
#衝突判定

# :star2:衝突判定:star2: &ensp;&ensp;P211
👉 オブジェクト同士が衝突した時に処理を行う仕組み

<br>
<br>

# :bulb:成果:bulb:
<details>
  <summary>⭕円の中心と半径の利用📐</summary>
P212<br>  
中心間の距離が，半径の和より小さければ衝突
</details>

<details>
  <summary>💪Physicsで衝突を検出🦾</summary>
・P294<br>
・Colliderコンポーネントをアタッチしたオブジェクト同士を衝突させる<br>
【オブジェクトの準備】<br>
物体① : Rigidbody + Collider<br>
物体② : Collider <br>

【メソッド】
P295
</details>

# ✨重要✨
衝突判定をするとき，物体はtranslateメソッドを使って移動させるのではなく
Physics を用いて移動させる。
現在地が取得(できたら|できなかったら)何かする

少し時間が経つと忘れすぎ問題

```js
    function hogehogefunc() {
      function success(position) {
       // todo
      }
      function error(error) {
       // todo
      }
      var watch_id = navigator.geolocation.watchPosition(success, error, {
        enableHighAccuracy: true
      });
    }
    
    hogehogefunc()
    
```

おまけ：これも調べず書きたい
```js
    if( window.matchMedia('(max-width: 767px)').matches ) { // スマホ幅以下だったら
      // 何かの処理
    } else { // スマホ幅以上だったら
      // 何かの処理
    }
```
import { ~ as ~ } の"as"とは何者なのか

はじめに
--
ポートフォリオのフロント側をTypeScript(react)で開発しているのですが、参考にしていた記事で出てきた"import { ~ as ~ }"の"as"はどういう意味なのかしっかり理解しておきたいと思ったので、調べたことを備忘録として残します。
(※import/exportの説明は割愛します）

asとはなんなのか
--
ものすごく簡単に結論だけ述べると、"as"を使うことで元のモジュール名を別名として使用することができるようになります。
MDNの下記の例が分かりやすかったので引用します。
~~~js
import {
  reallyReallyLongModuleExportName as shortName,
  anotherLongModuleName as short
} from '/modules/my-module.js';
~~~
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/import#%E3%82%A4%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%88%E3%81%99%E3%82%8B%E9%9A%9B%E3%81%AB%E8%A4%87%E6%95%B0%E3%81%AE%E3%82%A8%E3%82%AF%E3%82%B9%E3%83%9D%E3%83%BC%E3%83%88%E3%81%AE%E5%90%8D%E5%89%8D%E3%82%92%E5%A4%89%E3%81%88%E3%82%8B


モジュール名自体がが"as"を使用している理由を表していますね笑
可読性を上げるために使用している場合が多いのではないでしょうか？
~~~
reallyReallyLongModuleExportName（モジュールのエクスポート名が非常に長い）
~~~

import * asを使用する場合
--
~~~js
import * as 指定した名前 from 'パス';
~~~
「*」を使用することにより、「指定した名前」がパス先のファイルのモジュールからのexportを全て含めることになります。

下記では、meta-syntactic-variable.jsファイルからexportしたモジュール全てをmetaSyntacticという名前に含めています。

importしたmetaSyntacticを使い、元々exportで設定をしていたメソッドを使用するためには、[指定した名前.exportで設定したメソッド名]という順番で記述をすればOKです。

~~~./meta-syntactic-variable.js
function foo() {
  console.log(foo);
}

function bar() {
  console.log(bar);
}

export {foo, bar};
~~~

~~~js
import * as metaSyntactic from 'meta-syntactic-variable.js';

//"指定した名前.exportで設定した関数名"で使用できる

metaSyntactic.foo();
//=> foo
metaSyntactic.bar();
//=> bar
~~~

asが使えない場面
---
"export"ではなく、"export default"を使用している場合は"as"を使用することができません。（そもそもasを使う必要ないですもんね）

参考
--
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/import#%E4%BE%8B
サービスベースアーキテクチャ ドメインサービス間の通信は避けるべき について

ソフトウェアアーキテクチャの基礎 13章 サービスベースアーキテクチャ　で 「ドメインサービス間の通信は避けるべき」 と記載があったが、サービスベースアーキテクチャにおいてサービスまたいだデータが欲しくなったときにどういった落とし所があるか？を考えてみた。

# ドメインサービス間の通信は避けるべき

> データベースを分割する場合には、それぞれのデータベースが持つデータを他のドメインサービスが必要としていないことを確認する必要がある。そうすることで、ドメインサービス間の通信(サービスベースアーキテクチャでは絶対に避けるべきこと)やデータベース間のデータの重複を避けられる。

言及されている、避けるべきこと
- ドメインサービス間の通信
- データーベース間のデータの重複

## ケースで考える（参照系の共有）

1. なんかECっぽいサービス
![スクリーンショット 2022-08-23 18.42.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213002/824f40a8-c196-78cf-2ecb-1d380b36e485.png)

2. ユーザー情報と購買情報はそれぞれ独立してるから、DBも分割して良さそうと判断し分割
![スクリーンショット 2022-08-23 18.44.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213002/51f0565a-82ec-f524-3a17-ae7b2fc1b976.png)

3. 購買履歴の一覧表示機能が欲しくなる
購買サービスに作成
![スクリーンショット 2022-08-23 18.47.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213002/2ebd7389-fc79-8c83-728e-c544c3318cd3.png)

4. 購買履歴の一覧表示にユーザー情報も出したくなる
(リアルタイムで、オンラインで画面を見たいようなケースを考える)

- 購買サービスがユーザー情報を見るパターン
ドメインサービス間の通信はダメ => 購買サービスがユーザーデータを参照する
![スクリーンショット 2022-08-23 18.56.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213002/a1dea707-e041-7791-00cb-da112dab2e7a.png)
  - Pros: サービスを新しく増やさないで済む
  - Cons: せっかく分割したデータベースがまたサービスで共有される。

- 購買履歴の機能を独立させる
![スクリーンショット 2022-08-23 19.00.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213002/5a1b463e-e524-6511-8ed7-d3d39ae0e90e.png)
  - Pros: DBに対して更新操作を持つサービス(ここでは購買サービス)が他のデータベースを参照することは避けられる
  - Cons: 結局データベース共有されてる？ / サービスが乱立してサービスベースアーキテクチャから外れそう

- ファサードを挟む
![スクリーンショット 2022-08-23 19.15.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213002/251048fa-b831-4f1b-5616-3fe9b9df7d28.png)
  - Pros: 既存の機能を有効活用できそう
  - Cons: ファサードのコレジャナイ感

- データベースを再統合
なさそう
- サービスを再統合
なさそう

- まとめ
__参照操作だけならデータベース共有してもOK、ただし更新系はデータベースがサービスを共有しないように頑張る。が現実的な落としどころ？__
  - 購買サービスがユーザーDBのリードレプリカやミラーリングを参照する
  - 参照のみする購買履歴サービスを作成する

ただし、どのケースでもDB分割してる時点で、オンライン処理で2つのテーブルの結合は現実的なスピードではなさそう。絶対にオンラインでリアルタイム情報を一覧表示したい。みたいな要望があった時点でなかなか厳しくなる気もする。

## ケースで考える（参照系の共有その2）
- 前提
ユーザーサービス / ポイントサービス の2つにサービス、データベースが分割されている状態

- 追加要望
ユーザー情報画面に保持ポイントを表示したくなった場合。

=> この程度ならファサードで処理 または、ユーザーンターフェイスが別にリクエスト投げるなどでも良さそう

## ケースで考える（更新系の共有）
気になれば考える。
Android: Kotlin でファイルの MD5 を計算する

Android や JVM 環境の Kotlin でファイルの MD5 を計算する実装です。

# 前提

InputStream からデータを読み込み、JDK の `java.security` を利用して MD5 を計算する方針とします。

ファイルサイズがある程度大きい (1MB ~) 状況を想定し InputStream からの読み込みとしています。

# 実装

```kotlin
import java.io.InputStream
import java.security.DigestInputStream
import java.security.MessageDigest

...
val inputStream: InputStream = ... // File の inputStream など
val md5 = DigestInputStream(inputStream, MessageDigest.getInstance("MD5")).use { input ->
    val buffer = ByteArray(1024 * 1024) // buffer size は任意のサイズ (ここでは1MB)
    var read = 0
    while (read != -1) {
        // ファイル末尾まで読み込む
        read = input.read(buffer)
    }
    input.messageDigest.digest().joinToString("") { "%02x".format(it) }
}
// md5(例) => "fb0bf2b96b28cf776cd898e4098485e2"
```

# 解説

`java.security.MessageDigest` により MD5 を計算します。入力が InputStream の場合は `java.security.DigestInputStream` にデータを通すことで MD5 が計算されます。

https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/security/MessageDigest.html

https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/security/DigestInputStream.html

MessageDigest, DigestInputStream は Android でも利用可能です。

https://developer.android.com/reference/kotlin/java/security/MessageDigest

https://developer.android.com/reference/kotlin/java/security/DigestInputStream

[MessageDigest#digest()](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/security/MessageDigest.html#digest()) で計算した MD5 は ByteArray 形式であるため `"%02x".format(...)` により 16 進数文字列へ変換します。

# InputStream を使わない場合

InputStream ではなく ByteArray でデータを保持している場合は DigestInputStream を使わずに [MessageDigest#digest(input: ByteArray)](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/security/MessageDigest.html#digest(byte%5B%5D)) だけで計算可能です
TensorFlowでGPUを使えるようにする(docker編）

# dockerでもGPUが使える
Windowsではdocker上でGPUが使えないと思っていたので、しばらくDockerは避けていましたが普通に使えました。
すべて[ここ](https://www.tensorflow.org/install/docker)に書いてあることの翻訳に過ぎないのですが、備忘録として書き残します。

[githubレポジトリ](https://github.com/NVIDIA/nvidia-docker)に書いてあるように、ホストOSにもドライバをインストールする必要があるので、それぞれ下の記事を参照してください

[Windows](https://qiita.com/yusukem99/items/5c528e85cc8e9dd29694)
[Linux](https://qiita.com/yusukem99/items/d5871d4f325fad4c5f85)
# 起動例
dockerのバージョンで使用するフラグが変わるので注意してください。

```bash:docker>=19.03
$ docker run -it --rm --gpus all tensorflow/tensorflow:2.9.1-gpu /bin/bash
```
--gpus all


```bash:docker<19.03
$ docker run -it --rm --runtime=nvidia all tensorflow/tensorflow:2.9.1-gpu /bin/bash
```

--runtime=nvidia
piyopiyo.exで作ったLiveView感想投稿サイトの話

こんにちは、piyopiyo.ex共同運営者です。

イベント開催を何回か重ねるうちに、piyopiyo.exイベント参加者の感想を集約する何かがほしいなあと思い始め、
実際に感想投稿サイトをpiyopiyo.exで作れば面白いのでは？と考え、作業工程を5回のイベントに分割し、仕様策定から実装、デプロイをやってみました。

本記事では、各イベントで使った資料と成果物を紹介します。

## イベント一覧

* piyopiyo.ex #4 Phoenix環境構築〜Hello,world!
* piyopiyo.ex #5 感想投稿機能をLiveViewでつくろう！（要件定義＋mix phx.new + phx.gen.live）
* piyopiyo.ex #6 感想投稿機能をLiveViewでつくろう！（ワイヤーフレームに沿って実装しよう） 
* piyopiyo.ex #7 感想投稿サイトにスタイルをあてよう！（daisyUI、tailwind css）
* piyopiyo.ex #8 GitHubActionsでGigalixirにデプロイしよう！

## イベントを通して作成したpiyopiyo.ex感想投稿サイト

https://piyopiyoex-portal.gigalixirapp.com/

TODO: アイキャッチ画像の追加

## 各イベント内容と資料

### piyopiyo.ex #5 感想投稿機能をLiveViewでつくろう！（要件定義＋mix phx.new + phx.gen.live）

イベント中にGoogle Docで簡単な仕様書、ワイヤーフレームを作成しました。
（下記動画では17分頃から本編が始まります）

https://www.youtube.com/watch?v=m9-EGAGdZjk&t=11s

### piyopiyo.ex #6 感想投稿機能をLiveViewでつくろう！（ワイヤーフレームに沿って実装しよう） 

モブプロで実装してみる、という試みをしました。
モブプロのホストは共同運営者のymnさんに担当していただきました。

https://github.com/nako-9h-sleep/piyopiyoex_portal

### piyopiyo.ex #7 感想投稿サイトにスタイルをあてよう！（daisyUI、tailwind css）

Tailwind CSS、daisy UIを予めインストールしたコードを準備しておき、
モブプロで実装してみる、という試みをしました。

#### 記事

https://qiita.com/nako_sleep_9h/items/9cd2343d19abee7a59e9

#### PR
https://github.com/nako-9h-sleep/piyopiyoex_portal/pull/11/files
https://github.com/nako-9h-sleep/piyopiyoex_portal/pull/12/files

### piyopiyo.ex #8 GitHubActionsでGigalixirにデプロイしよう！

デプロイ回はモブプロはできないので、スライドを用意し、実際にデプロイする様子を見ていただきました。

https://speakerdeck.com/nako_sleep_9h/piyopiyo-dot-ex-number-8-github-actionsdegigalixirnidepuroisuru

### おまけ

@torifukukaiou さんの下記記事を参考に空コミットする実装をGitHub Actionsに追加しました。
Gigalixirを使う上で大切なことなのです。お察しください。

https://qiita.com/torifukukaiou/items/a2b51fb46299762d3ce9

## 感想

仕様書作成を含めてイベントで扱うのが初だったので、面白い試みでした。
また、イベントを通して好反応をいただけて大変うれしかったです。

## お知らせ：piyopiyo.exリニューアル中です！

初心者向けElixir/Phoenixコミュニティとしてイベントを開催していましたが、
さらに入門しやすい内容になるようリニューアル中です。

![F68D9CCA-3890-4B08-BA3B-64BB21AD0B05_1_102_o.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109744/45d55f64-0917-a1a3-d698-52e8dba5c090.png)
[Houdini学習2日目]作業外のオブジェクトの表示方法

## 作業外のオブジェクトの表示
※前提：複数あるオブジェクトのうち、どれかの中に入っていること 

**Show All Objects**
![選択中以外の物体1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2797498/a3277c81-1b10-0e0d-3804-39a5fb00e897.png)

**Ghost Other Objects**
![選択中以外の物体2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2797498/d147c0d4-0af7-f66e-9c50-238dd63005d3.png)

**Hide Other Objects**
![選択中以外の物体3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2797498/223c18b7-a6fb-06c7-e6f3-643a263ef7ca.png)
Next.js x Express x Socket.IO でリアルタイムなじゃんけんアプリをつくってみた✌️

# きっかけ

- リモートワークで雑用を気軽に押し付けたい！
- 現実のじゃんけんみたいにリモートでも臨場感を持って盛り上がりたい！

というわけで、Socket.IO を使ってリアルタイムなじゃんけんアプリを作ってみました :v:

:::note
この記事は、つくった Web アプリの構成などの概要をまとめたものです
ソースコードの解説は行っていないのであらかじめご了承ください 🙏
:::

# つくったもの

https://janken-pon.vercel.app/

![janken-pon-demo-heavy.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266244/00fbbfd6-d5de-fb48-4e5c-e59a4f278be2.gif)

~~グーナーの皆さん怒らないでください~~

## GitHub Repository

https://github.com/Nag729/janken-pon

https://github.com/Nag729/janken-pon-backend

# 構成

- 言語はフロントエンド、バックエンドともに **[TypeScript](https://www.typescriptlang.org/)** です
- WebSocket の双方向通信は **[Socket.IO](https://socket.io/)** によって実現しています
- フロントエンドは **[Next.js](https://nextjs.org/)** で、UI ライブラリとして **[Chakra UI](https://chakra-ui.com/)** を採用しました
- バックエンドは Socket.IO のサンプルが豊富だった **[Express](https://expressjs.com/ja/)** を採用しました

![janken-pon-architecture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266244/7ff11858-0d0b-f3d2-0b10-b0139f1b02fb.png)

:::note
Express は [Next.js - Custom Server](https://nextjs.org/docs/advanced-features/custom-server) として立てることも考えましたが、Custom Server は Vercel にデプロイできないということだったので今回はスタンドアロンにしました
:::

# 苦労したこと

簡単にですが、開発で苦労したポイントを書いておきます

## :one: Socket.IO の新しい情報が少ない問題

Socket.IO の実装に関する情報を調べてみると、2014~2016 年くらいの記事が上位に出てくることが多く、「この情報いまも信じていいのかな？ :thinking: 」と不安になりました

例えば、部屋ごとにじゃんけんの部屋を作る方法を知りたいとき、

1. 実現のためにどういう選択肢があるか？
2. [Rooms](https://socket.io/docs/v3/rooms/) と [Namespaces](https://socket.io/docs/v3/namespaces/) のどっちが適しているか？
3. どう実装するのがいいか？

といった情報を調べていくのに公式ドキュメントだけでは理解しきれず、色んなサイトを巡ることになりました

:::note warn
WebSocket の知見がないこともあり日本語の情報を中心に探したので、英語が読める人なら苦労しないかもしれません
:::

Socket.IO の実装は気が向いたら別記事でまとめようかなと思いますが、もし今すぐ「実装を見たい」という場合はバックエンドの [main.ts](https://github.com/Nag729/janken-pon-backend/blob/master/src/main.ts#L61) を見てみてください

## :two: Heroku に Express デプロイしたらレスポンスが遅い問題

最初はバックエンドを Heroku にデプロイしてみたのですが、想像していた以上にレスポンスが遅かったです
一例として、シンプルな POST に2秒以上かかっていました

Heroku の無料プランでは Region を変更できないので、この機会に [AWS App Runner](https://aws.amazon.com/jp/apprunner/) を東京リージョンで試してみたところ、無事にレスポンスが改善されました :tada:
（こちらも有料ですが、支払いを AWS にまとめられるのが魅力でした）

:bulb: AWS App Runner へのデプロイでは、↓の記事を参考にさせていただきました

https://zenn.dev/ibaraki/articles/7b781553eb7a74

:::note
AWS App Runner をつかってみて:
:ok_woman: 設定ファイルの追加なしでコンソールからデプロイできるのが楽ちん
:no_good: Heroku や Vercel と比べてデプロイの時間が長い
:::

# ふりかえり

ひとまず公開まで辿り着けてよかったです :tada:
**つくりたいモチベーションが明確だったので、機能スコープを絞れた** のが勝因かなと思います

Socket.IO は最初動かすまで少し苦労しましたが、軌道に乗ってからは割とスムーズでした
ただ、ちゃんとテストをすればまだ大量の `// TODO` が積み上がると思います :sweat:

あとは、簡単ですが初めて SEO 対策をしてみたので、知らないことばかりで学びになりました
実際にユーザーに使ってもらってこそ価値を生み出せると思うので、これからも **「つくったものをいかにユーザーに届けていくか？」** という視点は大切にしていきたいです :blush:
MySQLの-bash: mysqld: command not foundエラー（GPGキーのエラー）


先日、久しぶりに何も考えずにLinuxサーバーにMysqlを入れて、
```terminal
mysqld --version
```

をしたら

```terminal
mysqld: command not found
```

になりまして、


仕方なくメッセージをさかのぼって原因を探していくと、途中で
```terminal
The GPG keys listed for the "MySQL 5.7 Community Server" repository are already installed but they are not correct for this package.
Check that the correct key URLs are configured for this repository.
```

を発見！

新しいGPSキーをインストールしてなんとかなりました。

```
sudo rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022
```




ーーーーーーーーーーーーーーーーーーーーーーーーーー

参考


https://blog.katsubemakito.net/mysql/mysql-update-error-gpg



https://hi3103.net/notes/web/1068
ログの出し方あれこれ

printデバッグはダサいとはいうものの、プロダクション環境でもログは出てる。Webサーバーにいたってはすべての通信をログに出してる。

ログにはinfoログとエラーログがある

### まずダメな例から

- エラーがあったらメール
    - どうせメールだらけになる
    - メールフィルタつけて結局みなくなる
- エラーがあったらSlack 
    - どうせSlackの通知だらけになる
    - どうせ定期的にSlackをみるのなら、エラー通知じゃなくていい

### 一般的だけど悩ましい方式
 
- syslogに出す
    - 他のミドルウェアがやってることではある。ログのローテもOSがやってくれる
    - だけど開発環境でsyslogに吐き出すのって結構ハードル高い
    - そもそも「syslogってどこに出るの？」って知らない人も多い
- logファイルに書き出す
    - これはありだけど、自前ログのローテーションってめんどい
    - 別々のサーバーで動いてるとログ集めるの大変
- loggerみたいなログ出力ライブラリを使う
    - そのloggerがどこに吐き出すのがいいのかという話
    - ファイルにした時点であとで集めるやローテーションが面倒
- Fluentdみたいなログアグリゲーターを使う
    - とても真っ当
    - だけど開発環境でちょっとしたinfoログを見るためだけに、みんなの環境にFluentdインストールするのハードル高い
    - 集計がメインの機能で、デバッグ観点やエラー通知という感じじゃない

### 楽ちんさを優先するとこれ

- 標準出力に吐き出す
    - まさにprintデバッグ
    - tmuxで起動してるのなら、サーバーにログインしてtmuxアタッチするだけで直近のログがみれる。リアルタイムにも観れるという嬉しさがある
- データベースに書き出す
    - 標準出力に書き出すのに比べると手間がかかるけど、どうせほとんどのシステムはDBと繋がってるので新しいミドルウェアを導入してるわけではない
    - insertが多すぎてDBの容量がきになるかもしれないけど、どうせlogなんだから一週間くらいで削除すればいい
    - レコードの削除は負荷がかかるので、パーティション単位でTruncateすれば負荷はほとんどない
    - データはリアルタイムに集まってるので、「直近10分のエラー件数が100件超えたら強めのアラートを送る」みたいな使い方ができる
    - 集計できるから日時でグループ化して処理のペースなんてなのもみれる


ということで標準出力とDBという「ログのために新たなミドルウェアを入れない」というのがおすすめ。

ちなみにちゃんとしたミドルウェアのログはログローテーションのタイミングで、ログファイルを一度閉じて開き直すという仕組みをちゃんと作り込んでる。そこまで作り込まない人のために、loglotateは「コピーしてファイルサイズをゼロにする」というcopytruncate 機能がある。この方式ならただファイルをオープンしっぱなしでログを書き出すだけのシンプルな仕組みでもログローテができる（がみんなが知ってるわけではない）。
【Linux】指定ディレクトリ配下にあるファイルの拡張子の一覧および数を表示する

## 概要
指定ディレクトリ配下にあるファイルの拡張子の一覧および数を表示するコマンドを記載する

## コマンド
`find <検索するディレクトリ> -type f -print | sed -e 's/^.*\///' | grep '\.' | sed -e 's/^.*\.//' | sort | uniq -c | sort -nr`

カレントディレクトリ配下全てを検索する場合は以下のように指定する。
```
$ find ./ -type f -print | sed -e 's/^.*\///' | grep '\.' | sed -e 's/^.*\.//' | sort | uniq -c | sort -nr
     82 py
     28 png
     25 html
     15 yml
     15 json
     11 txt
      8 sh
      8 js
      7 jpg
      6 md
      5 ini
      4 yaml
      3 gitignore
      3 dockerignore
      3 conf
      2 tmpl
      2 css
      1 tar
      1 pem
      1 pdf
      1 go
      1 env
      1 cfg
      1 bin
```
StableDiffusionを動かせるサーバーを立てた話

ちょっと前に、こんな→https://qiita.com/tanreinama/items/89a7c9c29cf60618bd0b
デモサーバーを立てて、テキスト→イラスト生成のデモンストレーションを動かしました。

そしたらその直後にMidjourneyが出てきて全てをさらってゆきました・・・

悔しいのでデモンストレーションにStableDiffusionを使うオプションも入れて、StableDiffusionを実行出来るようにしておきました。
公式のデモページがあるのであえて・・・ではありますが。日本語でOKです。

![タイトルなし.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/595605/8b37829c-25d9-62ce-e182-d90a0fcc300e.png)

てかStableDiffusion凄いな。他人の褌で恥ずかしいですが。