OmniAICreator/Qiita-1.07M huggingface dataset:
FlutterでStateError (Bad state: field does not exist within the DocumentSnapshotPlatform)に出会った（初心者）

# はじめに
こちらはFlutter超初心者がサンプル脳死タイピングの末に数時間を無駄にしたという、
とっても怖い実体験から次なる犠牲者（未来の自分）を救済するための覚書です。
大したことは書いていません。

## 起こったこと
ネット上に落ちてるチュートリアル的な記事を読みながら写経（ほぼ脳死）をしていたとき、
Firestoreからデータを取ってくる処理を実行したところで
```
StateError (Bad state: field does not exist within the DocumentSnapshotPlatform)
```
って言われた。

## 解決策
数時間ググっても何もわからず、ふとコードとFirestoreのコンソールとを見比べてみた。
すると、、、

``` main.dart
  return ListView(
    children: docs.map((doc) {
      if (doc == null) {
        return const Card(
          child: Text('No posts'),
        );
      }
    
      var email = doc['email'];
      var text = doc['text']; <- ここ
    
      return Card(
        child: ListTile(
          title: Text(text),
          subtitle: Text(email),
          trailing: email == user?.email
              ? IconButton(
                  icon: const Icon(Icons.delete),
                  onPressed: () async {
                    db.doc(doc.id).delete();
                  },
                )
              : null,
        ),
      );
}).toList());
```

### Firestoreのスクショ
![スクリーンショット 2022-08-21 22.28.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663352/8743f26e-a7db-9969-82ff-1b935a335ea4.png)

んんっ？？？message????

ということで、textなんて名前のフィールドは存在せず、それを取ってくるなんてできるはず無いわけで、、、
結論、確認はしっかりしましょうというお話でした。
その後、書き込みと読み込みの処理でフィールドの名前を統一したら何事もなかったかのように普通に動きました。

## なぜこんなことが起きたのか？
実はサンプルの写経中に、「こんなことはできるのかな？」とか思いつきで追加機能を考えて、
それをまた脳死で写して、ということをしていました。
結果、単に文字列を保存する名前に「message」と「text」の２つが混在しているのに気づかず、動作させて初めてバグに気が付いたのです。
こんなしょうもないミスで数時間も無駄にした人もいるらしいので皆さんは気をつけるようにしましょう！
Installing SAP NetWeaver Developer Edition on an Ubuntu desktop VM

この記事を参考した英語記事への[リンク](https://blogs.sap.com/2018/04/05/installing-sap-netweaver-developer-edition-on-an-ubuntu-desktop-vm-the-non-concise-guide/)

- 事前準備
  1. 最新版の「VMware Workstation Player無償評価版」をダウンロードする。([リンク](https://www.vmware.com/jp/products/workstation-player/workstation-player-evaluation.html))
  1. 「Ubuntu 18.04 LTS」のisoイメージをダウンロードする。([リンク](http://www.ftp.ne.jp/Linux/packages/ubuntu/releases-cd/bionic/ubuntu-18.04.6-desktop-amd64.iso))
  1. 最新版のABAPをダウンロードする。([リンク](https://developers.sap.com/trials-downloads.html))　現時点の最新版は7.52 SP04です。SAPのユーザーを持っていない場合無料で登録必要です。
- Ubuntuをインストール後の設定。(下記のコマンドを実行する）
    1. sudo apt install csh
    1. sudo apt install libaio1
    1. sudo apt install uuid
    1. sudo systemctl start uuidd
    1. ip addr show
    1. sudo nano /etc/hosts
    1. sudo reboot now
    1. sudo systemctl start uuidd
    1. systemctl status uuidd
- ABAPをインストールする。
    1. ダウンロードしたABAPのrarファイルを7zipで解凍する。(TD752SP04part01.rarのみ)
    1. 最新のライセンスファイル「SYBASE_ASE_TestDrive.lic」を「/mnt/hgfs/unpack_path/server/TAR/x86_64」にコピーする
    1. windowsとlinuxの共有フォルダを設定する
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551056/06ffb46b-38ed-aee9-d3c5-e4c3643c5313.png)
    1. sudo -i
    1. chmod +x install.sh
    1. ./install.sh （下記イメージのようなメッセージが出たらインストール成功しました）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551056/e30f4f96-3be5-5d42-7ac3-b9df80b84a5b.png)
- NPLを設定する。
    1. su -l npladm
    1. sapcontrol -nr 00 -function GetProcessList
- 「SAP GUI For Windows」をインストールする([リンク](https://developers.sap.com/trials-downloads.html))
- Connection情報を設定する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551056/d9c5fd21-70e1-7ac5-79b1-102956a4555d.png)
- 下記のデフォルトユーザーでログインできる（デフォルトパスワード：Down1oad）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551056/ebaa213d-52ca-e0e4-6831-c4ffb1cf0b89.png)
- Ubuntu再起動後サービスの起動と終了方法
    1. su -l npladm
    1. startsap ALL
    1. stopsap ALL
DjangoでBootstrapを導入する

# 1. はじめに
今回はDjangoにBootstapを導入する方法を紹介します。
また、Bootstap導入後に前回の「[DjangoのWebアプリケーションにユーザ認証を追加する(django-allauth)](https://qiita.com/t-shirayama/items/11d022d78ea3c5623c80)」で作成したログイン画面に適用していきます。

# 2. django-bootstrap5をインストール
pipでdjango-bootstrap5をインストールします。
```
pip install django-bootstrap5
```

# 3. settings.pyの変更
settings.pyのINSTALLED_APPSにdjango_bootstrap5を追加します。
```
INSTALLED_APPS = [
    ...
    'django_bootstrap5', # 追加
]
```

# 4. テンプレートに適用
テンプレートの先頭行に下記のコードを追加します。
```
{% load django_bootstrap5 %}
```

テンプレートのヘッダに下記のコードを追加します。
```
<head>
    ...
    {% bootstrap_css %}
    {% bootstrap_javascript %}
</head>
```

これでBootstrapの導入は完了になります。

# 5. django-allauthのテンプレートをカスタマイズ
django-allauthのテンプレートファイルをカスタマイズするにはdjango-allauthのテンプレートファイルを自身のtemplatesの下にコピーして編集します。
django-allauthの場所はpip showコマンドで確認できます。Locationに記載されているのがインストールされているパスになります。
```
$ pip show django-allauth
Name: django-allauth
Version: 0.51.0
Summary: Integrated set of Django applications addressing authentication, registration, account management as well as 3rd party (social) account authentication.
Home-page: http://www.intenct.nl/projects/django-allauth/
Author: Raymond Penners
Author-email: raymond.penners@intenct.nl
License: UNKNOWN
Location: /home/vagrant/.local/lib/python3.8/site-packages
Requires: requests-oauthlib, Django, requests, python3-openid, pyjwt
Required-by:
```

# 6. Bootstrap適用後の画面
Bootstrapを適用し、django-allauthのテンプレートをカスタマイズした結果は以下のようになります。

ログイン画面
![after1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2641338/7307a136-16c3-c700-dde3-f98a6da8056b.png)

ユーザ登録画面
![after2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2641338/dd46f082-50cd-fa92-538f-99da83c20587.png)

パスワード再設定画面
![after3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2641338/60fdbb1e-ed2e-3d4f-a3c9-8081cfe74e7b.png)

# 7. おわりに
今回はDjangoにBootstrapを導入し、デザインを改良しました。
今後もDjangoについて勉強した内容を投稿していきたいと思います。
Amazonの注文履歴を集計するメモ

## 概要
Amazonの注文履歴から、注文金額合計などを集計したかった。
ので、ささっとデータの確認をした方法をメモ。

### 使ったツール
- Chrome拡張「アマゾン注文履歴フィルタ」
- Tableau（集計できればなんでもいいが万能なので）
- Chrome Dev ToolsのConsole＋JavaScript（集計の検算に利用）

## Chrome拡張「アマゾン注文履歴フィルタ」をインストールする
### ダウンロードURL

※「注文履歴を見る」の項目でも触れるが、参考サイトにもリンクがあるので、リンク切れの場合はそちらを見るかググるかする。

https://chrome.google.com/webstore/detail/%E3%82%A2%E3%83%9E%E3%82%BE%E3%83%B3%E6%B3%A8%E6%96%87%E5%B1%A5%E6%AD%B4%E3%83%95%E3%82%A3%E3%83%AB%E3%82%BF/jaikhcpoplnhinlglnkmihfdlbamhgig?hl=ja


### 引っかかりポイント
#### 拡張機能はそれなりに更新されているので、疑う余地低し
拡張機能の更新日付は2022/8月現時点で2022/5月だった。
この後のフローでうまくいかない理由は拡張機能の更新が追いついていないからと思ったが、使い方が悪いだけだった。
疑ってごめんなさい。

## Amazon（JP）の注文履歴を見る
### 詳しい手順は参考サイトを確認
https://mono-stream.com/amazon-purchase-history

### 引っかかりポイント
#### 注文履歴の初期状態だとChrome拡張が動かない（？）
注文履歴を見る時、初期状態では
**「過去3ヶ月に確定された○件の注文」**
という日付のフィルタがかかっている。
この状態ではChrome拡張「アマゾン注文履歴フィルタ」はうまく動かないようなので、日付のフィルタは
**「2022年に確定された○件の注文」**
のような、年単位のフィルタに書き換える必要がある模様。
※数年前に使った時はこのハマりポイントはなかった気がした。

#### 抽出時に表示される謎の「Partial Order Error」
結論、月別の集計に影響は出ていなかったので問題なかったが、下記の状況でエラーメッセージが発生。
2022年の抽出では特に問題なかったものの、2021年の抽出をした際、
*Partial Order Error* 
なるエラーと、
*Download error list*
なるボタンが表示された。
部分的にちゃんとダウンロードできていない？と思ったため、
Chrome拡張「アマゾン注文履歴フィルタ」でダウンロードしたCSVファイルを集計した値と、
画面に表示される内容をJavaScriptで集計した値をそれぞれ月別に求め、検算することに。
※注文履歴が多かったり、特殊な履歴（例えばAudibleの月額サブスクリプション）など、
　元からAmazonにはなかった履歴、かつまだChrome拡張が対応していない場合に起きる？かと思いました。
　ちゃんと検証していないので、わかるかたいたら教えてください。

## TableauでCSVを可視化
### 年別にダウンロードしたCSVにユニオンとして接続
今回ダウンロードしたのはデジタルコンテンツ以外なので、以下のようなファイルネームになりました。
`amazon-order_non-digital_2021.csv`
ので、Tableauでユニオンを作る時は、以下のワイルドカードで指定します。
`amazon-order_non-digital_*.csv`

### 引っかかりポイント
ディメンション「商品名」でフィルタする点。
データの内容が下記のようになっているので若干注意。

* 注文番号1つに対して複数の行が作成される
* 商品名には以下のような値が入る
    * `（注文全体）` ： 商品の合計金額（割引やポイント・ギフト券による決済額の減少分を考慮していない）
    * `（クレジットカードへの請求）` ： クレジットカードに請求される金額
    * `（割引）` ： 割引額（注文合計フィールドにはマイナスの値が入る）
    * `Amazonギフト券` ： アマゾンギフト券での支払い金額（注文合計フィールドにはマイナスの値が入る）
    * ...etc.
* `注文合計` フィールドには、`（注文全体）` 、`（割引）` 、`Amazonギフト券` などの行で値が入る

→　つまり、`注文合計` フィールドで計算するなら、`（注文全体）` だけに絞り込めば良い、と思っていたら間違いだった。
　　正しくは、`（注文全体）` に加えて、`（割引）` 、`Amazonギフト券` などのマイナスの値が入るものも勘案してフィルタをかける必要があった。


### Tableauで月別の棒グラフを作成
Tableauを使ったのは単純に手元にあってフィルタとか集計とか万能だからです。
もう一つの理由は、注文番号1つに対して複数行に分かれるデータが出てきたので、LODとか計算するならTableauに任せたいな、と思ったためです。
※すいません、Tableau操作の解説は省きます。。。

月別の値が簡単に出せるはずなので、このデータが信頼できるか、実際の注文履歴画面に出てくるものを集計して付き合わせたくなります。


## JavaScriptで簡易的な関数を実行して検算
### Chrome拡張表示される月別の注文履歴を集計

やっつけですが下記のようなコードを書いて検算。

```.js
let valueElements = Array.from(document.getElementsByClassName('a-column a-span2 yohtmlc-order-total'));
let valueNumbers = [];
valueElements.forEach(function(el){
    valueNumbers.push(el.getElementsByClassName('a-row a-size-base')[0].innerText.replace(/(￥|,|\s)/gm,''))
});
let total =  valueNumbers.reduce(function(sum, value){
  return sum + Number(value);
}, 0);
console.log(total);
```

CSVで出力されるものを月別で集計したなら、注文履歴を月別で表示させ、上記スクリプトで出てくる合計金額を割り出すのみです。

## 結論： Chrome拡張を信じてよし。
ただし計算するフィールドは要チェック。
Hyper-Vの仮想マシンでバックアップ取得時にエラーが発生した時の対処について

# 背景

Hyper-V上の仮想マシンバックアップを、商用バックアップツールを使ってバックアップを取得しようとしたが、エラーが出て失敗。
その時の対処と得た教訓についてメモを残しておく。

# 先に結果

バックアップ取得対象がサポート切れの古いWindows Serverという事もあり、ベンダーサポートに問い合わせを出しても全然レスポンスがなく、
社内でヘルプ記事を出してあっさり解決。バックアップが取得可能となった。
ベンダーサポートはこういう場合、あてにならないと身に染みて実感。。。

会社の上司曰く、バックアップツールが何を使っているかというより、仮想マシンのバックアップエラーは、
どのツールを使っていても大体ベースの仕組みは一緒なので、どういうエラーが出ているか、
仮想マシンのバックアップがどういう仕組みを使って取得されているかをまず考慮する必要があるとの事だった。
(VMwareの仮想マシンだったらスナップショット、Hyper-Vの仮想マシンだったらチェックポイントを基本使っている等、
どのバックアップツールを使っていても、大体依存する仕組みがあるという事を念頭に置く必要がある)


# バックアップ失敗時に出力されたエラー

> VMバックアップのチェックポイントを取得できませんでした。
> エラーメッセージ
> ['<仮想マシン名>'に対するチェックポイント操作が失敗しました。
> (仮想マシンID xxxxxx-xxxx-xxxx-xxxxxxxx)'<仮想マシン名>'に対するチェックポイント操作が取り消されました。
> (仮想マシンID xxxxxx-xxxx-xxxx-xxxxxxxx)'<仮想マシン名>'はチェックポイント操作を開始できませんでした：
> 要素が見つかりません。(0x80070490)。(仮想マシンID xxxxxx-xxxx-xxxx-xxxxxxxx)

今回の対処で必要だったキーワードは以下2つ。
* Hyper-V
* エラーメッセージ中のエラーコード(0x80070490)

この2つを元に検索して出てきた記事がこちら。↓

[Hyper-V Backup Error: Could not initiate a checkpoint operation: Element not found. (0x80070490).](https://backupchain.com/i/hyper-v-backup-error-could-not-initiate-a-checkpoint-operation-element-not-found-0x80070490)

いや、表題からしてまんまだった。。。
最初にバックアップ失敗が発生して自分で調べた時、バックアップツールの名前を入れて検索して、どうもうまくこの記事が
引っかからなかったっぽい。
検索結果から見落としていた可能性も否めない。。。(-_-;)

# バックアップ失敗のその後

上記リンク先のページを見た後にバックアップ対象の仮想マシンをコピーして検証機を作成、検証機に上記参照先の対処を適用したところ、見事にバックアップ取得成功！
本番機にも適用して、現在は無事バックアップ取得が出来ている。

このバックアップ失敗の原因、対象のHyper-V仮想マシンのOSが古い場合に発生するHyper-Vのバグのようで、そもそもサポート切れの古いOSなんぞさっさと更新しろよ！というMicrosoftの意向なのか、ずっとバグは解消されず放置されている様子。
まあ本来は古いOSは更新しないと、ですよね。。。
でもお客さんにそう言えない身としては、何とかバックアップ取得を成功させないと！と試行錯誤。
まあ、何とかなって良かった。

# 今回の教訓

* エラーコードは大事にしよう
* 使用ツールにこだわり過ぎず、基本に立ち返ろう(今回の場合、仮想マシンのバックアップの仕組みを考慮)
Markdownで打ち消し線を引く

### 背景
Markdownで打ち消し線を引きたいことがよくあるのですが、毎回調べるので記録に残しておきます。

### 方法

「~」（チルダ）2本で打ち消したい部分を囲みます。

```
~~打ち消されるところー！！~~
```

のようにすると、

~~打ち消されるところー！！~~

と表示されます。


### 終わりに

誰かの役に立つことがあれば幸いです。
GROWIのユーザーページを削除する

# はじめに
一人で試験運用するにあたってtestuserとかaaとか意味不明な名前で作った大量のユーザーページが、ユーザー削除後もページツリーの/user/以下に残り続け、管理者権限をもってしても削除のボタンを見つけられなかった。
そこで今回は仕方なく、mongodbから直接ユーザーページを削除する事とした。
当然、正規の削除方法ではないため、問題が発生した場合に当方では責任を負う事ができないので、システムバックアップのうえ自己責任で実行すること。

GROWI上からユーザーページを削除する方法があったら教えてください。助けてください。

# 環境
* Growi: v5.1.0
* mongodb: v4.4
* [docker-compose](https://github.com/weseek/growi-docker-compose)による構築

# 方法
* mongoイメージ（v5.1.0ではgrowi_mongo_1という名前）のbashを起動
```shell:shell
sudo docker exec -it growi_mongo_1 /bin/bash
```
* mongoにアクセス
```shell:mongoコンテナshell
mongo
```
* growidbに切り替え
```shell:mongodb
use growi;
```
* 削除したいユーザーページを検索
```shell:mongodb
db.pages.find( { path : { $regex : '^/user/testusername' } }, { path : 1 } );
```
* 表示内容に相違がなければ削除
```shell:mongodb
db.pages.remove( { path : { $regex : '^/user/testusername' } }, { path : 1 } );
```
* 削除したページ数に応じて/userのdescendantCount（ページツリーに書かれている子孫のカウント数）を減らした値を追記
```shell:mongodb
db.pages.find( { path : { $regex : '^/user$' } } , { descendantCount : 1 } )
db.pages.update( { path : { $regex : '^/user$' } } , { $set : { descendantCount : newCountValue } } )
```



# ユーザーページの検索コマンドについて
正規表現で『/user/testusername』から始まる(^←この記号)ページを検索している

# 終わりに
最初に書いたように、正式なやり方ではないと思うので自己責任でお願いします。

前回から紆余曲折がありラズパイ4BでGROWIを運用するの諦めました。
2万くらいでミニPC買いました。（どうせラズパイとSDとケースと…と揃えるとそこそこの値段かかること思えば大差ない出費な気がします）
記憶にある範囲でなんともならなかったのはElasticsearchの検索機能でした。
一つ試す度にビルドに時間がかかるラズパイで試す事ではないな、という理由で諦めました。
この[ミニPC](https://www.amazon.co.jp/gp/product/B07XYLSNZH)を2万円弱で買ったのですが、ラズパイと比べるとGROWIのビルドが瞬間で終わるので、ストレスフリーです。
（ただし、標準で入っていたWindowsは11に上げたせいか滅茶苦茶遅かったです。Debianは神）

ついでに所内のTerastationと同じUPSに繋いでNUTの設定したり、時折死ぬVPNの代わりにSSHを外向けに発信したりするようにしました。
（事務所に割り当てられたIP次第でVPN接続できない事がある様子なんですが、そういう事ってあるんですかね…。SSHはVPNダメでも行けました。L2でなにかプロバイダが考え事をしている？）

現状は概ね満足のいく状態で運用できているつもりですが、GROWIのlsxはPukiwikiのlsxと違ってincludeオプションがないようなので、この辺を改造したいなあなどと考え中…。
manifestでキャッシュ参照しがちなのか、bundle.jsを適当に書き換えて反映させるためにシークレットウィンドウを開くのが面倒くさい…。
そもそもbundle.jsを書き換えるのが間違っている…。
トランスパイルよく分からない…。

乱文失礼しました。
【Android】時間を表示するView『AnalogClock』

# はじめに
前回は　デジタル時計を表示する『TextClock』を記事にしました。
よければそちらも見てください　→[【Android】時間を表示するView『TextClock』
](https://qiita.com/Tsubasa12/items/443db0ce5d89667a25bf)

今回は　アナログ時計を表示する『AnalogClock』を紹介します。

# AnalogClock
使い方としては　先述したTextClockの記事に書いてあるのと同じで
AnalogClockクラスか　LayoutにAnalogClockタグを追加して用います。

AnalogClockではデジタル時計のように時計の型式を変えることはできませんが、
AnalogClockでは時計の見た目を変更することができます。

xml側で
android:dial属性で, 時計の文字盤の画像
android:hand_minute属性で, 時計の長針の画像
android:hand_hour属性で, 時計の短針の画像
をそれぞれ指定することができます。

また、AnalogClockはAPI level 23で非推奨となり、今後のサポートはないみたいです。
早朝出勤のすすめ

コロナの影響もあり、自社でも時差出勤が認められるようになりました。  
以前より早朝出勤を心掛けていたのですが、時差出勤制度の適用により、退社時間を早めることで、最近は、ほぼ毎日17時退社を実現できるようになりました。  
改めて早朝出勤のメリットを纏めてみたいと思います。

## メリット

### 始業前時間を自由に使える

早朝のオフィス、誰もいない時間帯は、邪魔も入らず非常に快適です。
1日の計画立案や、集中して考えたいことは大体この時間に終わらせてしまいます。
やはり、早い時間帯の方が疲れもなく、頭の中がクリアな状態で、集中できると実感しています。
作業計画立案には、もっぱら、`Microsoft ToDo`を使用しています。`Wunderlist`時代から非常にお世話になっています。  

### 満員電車を避けられる

コロナ禍の中、リモートワークや時差出勤、各社様々な取り組みを行っていますが、それでも通勤時間帯はやはり人が多いです。通常の勤務時間帯だと、まず電車で座ることができません。    
時間を早め、6時台前半に自宅を出発することにより、ほぼ100%座って通勤できています。    
毎日のことですので、余計な体力は使わない方が良いです。暑い日等は、特に体力の消耗具合が違います。  

### 良いサイクルが身につく

「早く起きる為に、早く寝る。その為には、早く家に帰る。その為には、早く仕事を終わらせる。その為には、効率良く仕事をする。その為には、積極的に知識を吸収する。、、、」  
サイクルの起点は人それぞれだと思いますが、自分はこれで上手く回っているように感じています。　　 
日の出の様子を見ていると、つくづく、人間は日の出とともに起き、日の入りとともに眠る、このリズムが基本であると実感させられます。  

## デメリット

あまり感じていません。  
強いてあげれば、夜寝る時間が早くなり、プロ野球の試合が長引いた時に、結果を見ずに寝てしまうことくらいでしょうか。   
元々お酒も飲まない為、「飲みに行けなくて残念」ということもありません。  

## まとめ

時差出勤により、時間に追われることなく、心の余裕を生み出すことが出来てきたと感じています。   
余裕が有れば、これまでにやりたくてもやれなかったことにチャレンジしてみようという気力が湧いてきます。  
人生100年時代と言われ久しいですが、仕事だけではなく、色々な新しいことに目を向け、そこで得た知識、経験を仕事にも活かし、「効率 + 業績向上」で、これからも良いサイクルを回し続けたいと考えます。
Android Studioの動作が快適になった設定

# Android Studioの動作が快適になった設定

## はじめに

カーソル移動・文字打ち込みで画面が数秒硬直し仕事にならなかったので調査しました。
私の社用PCで効果があったので備忘録がてら記載しておきます。

## UseParallelGCを有効にする

Android Developerにも記載されている方法です。
以下の設定をgradle.propertiesに追記するだけです。
```
org.gradle.jvmargs=-XX:+UseParallelGC
```

## 参考元
- Android Developer - ビルド速度を最適化する
https://developer.android.com/studio/build/optimize-your-build?hl=ja
PHPの制御構造について

## 自己紹介

はじめまして、日本システム開発株式会社の藤井といいます。
業務でPHPを触ることが多く、勉強してみようと思ってドキュメントを読み、役立ちそうな内容を記事にまとめています。
記事の内容は大体[php.net](https://www.php.net/manual/ja/)に書いてありますが、ドキュメントを読むのが面倒くさいと思った方は、
ぜひこの記事を役立ててください。

## 概要

PHPの制御構造について、ちょっとしたテクニックを紹介しています。

## do-while

do-whileはループ構造であり、breakが使えます。
かつ、絶対に1回は実行されるため、条件によって後の処理を実行しない
といった使い方が可能です。

```php
<?php
$name = "hoge";
do {
    if ($name === "") {
        echo "Hello 名無し";
        break;
    }
    if (mb_strlen($name) > 100) {
        break;
    }

    echo "Hello " . $name;
} while (0);
?>
```

## for

for (式1; 式2; 式3)
式1はループ開始時に無条件で実行、
式2は繰り返しの開始時に実行され、
式3は繰り返しの後に実行されます。

各式では、「,」区切りで複数の式を記述でき、
逆に空にすることもできます。

簡単な例として、

```php
<?php
for (; ; ) {
    echo "piyo";
}
?>
```

上のスクリプトは無限に実行されます。

「,」区切りでは、

```php
<?php
$hoge = ['h', 'o', 'g', 'e'];

for ($i = 0, $size = count($hoge); $i < $size; $i++) {
    echo $hoge[$i];
}
?>
```

上のスクリプトのように、countをループ開始時のみで実行し、パフォーマンスを向上させることができます。

## foreach

foreachは配列内部のポインタと関係なく動きます。
ポインタを変更することもありません。  
([next](https://www.php.net/manual/ja/function.next.php)などポインタを操作し、値を取得する関数があります。配列の最後の要素を取得する[end](https://www.php.net/manual/ja/function.end.php)は結構便利だと思います)

```php
<?php
$samples = ["hoge", "fuga", "piyo"];
echo next($samples) . PHP_EOL;

foreach ($samples as $idx => $sample) {
    echo $sample;
    if ($idx !== count($samples) - 1)
        echo ",";
    else
        echo PHP_EOL;
}
echo current($samples);
?>
```

## break, continue

ループ構造(for, foreach, while, do-while, switch)の中でのみ使えます。
switch内でcontinueを使用することができますが、breakと同じ挙動で誤解を招きやすい記述のため、推奨されていません。
break, continueには引数を与えることができ、引数の数だけ直近のループ構造から外にでます。
引数のデフォルトは1です。

```php
<?php
for ($i = 0; $i < 10; $i++) {
    echo $i . PHP_EOL;
    for ($j = $i * 10; $j < $i * 10 + 10; $j++) {
        if ($j == $i * 10 + 2)
            break;
        if ($i == 2)
            break 2;
        echo $j . ",";
    }
    echo PHP_EOL . PHP_EOL;
}
?>
```

```plaintext
上のスクリプトの出力結果
0
0,1,

1
10,11,

2
```

内側のforは+0-1までで、終了し、
外側のforは+0-2までで、終了します。

## まとめ

- do-whileはループ以外の使い道がある
- forはパフォーマンスアップなどちょっとした工夫が可能。
- foreachは内部ポインターとは別で動作する。
- break, continueには引数を与えられる。
PostgreSQL 初期設定メモ

# 前提
```
$ sw_vers
ProductName:	macOS
ProductVersion:	12.3.1
BuildVersion:	21E258
```

# インストール
```
$ brew install postgresql
$ brew search postgresql
$ brew install postgresql@10

# バージョン確認
$ postgres --version
```


# 起動・停止
```
$ brew services start postgresql
$ brew services stop postgresql

# 確認
$ brew services list
```


# ターミナル接続
```
$ psql -d テーブル名
$ psql -d テーブル名 -U ユーザ名

# デフォルトのテーブルに接続
$ psql -d postgres
```

# ロール操作
```
# 一覧の表示
> \du ;

# 作成
> create role ロール名 with 権限1 権限2 ... password '***';
```


# DB操作
```
# 一覧の表示
> \l ;

# 作成
> create database DB名 -O ロール名 ;
※ 文字セットや照合順序を指定する場合は、オプションを要確認

# 選択
> \c DB名 ;
```


# テーブル操作
```
# テーブル一覧の表示
> \dt ;

# テーブル構造の表示
> \d テーブル名 ;
```


# 外部ファイル実行
```
> \i ファイル名 ;
```

# 参考
* よく使うコマンド
    * https://qiita.com/H-A-L/items/fe8cb0e0ee0041ff3ceb
* DB作成
    * https://www.dbonline.jp/postgresql/database/index2.html
* ロール作成
    * https://www.dbonline.jp/postgresql/role/index2.html
[Rails]HerokuでRedis+Sidekiqを使用したActive Jobを実行させる

### 前提
記事を書いている私は現役のエンジニアではなくエンジニアを目指して学習中の者です。
よって、気をつけてはいますが記述内容には誤った内容が含まれている危険性があります。
その為この記事は参考程度に読んで頂き詳しい内容は公式の記述を参考にすることをおすすめします。

### この記事で実装すること
Redis+Sidekiqを使ってactive jobを実装してそれをHeroku環境で実装する手順を説明します。
ローカル環境では既に実装している前提で進めるのでローカルでの実装方法が気になる方は以下の記事を参考にして下さい。

[Sidekiqってどんなキック？](https://dev.icare.jpn.com/dev_cat/sidekiq/)
[【Rails7】Redis+Sidekiq+Active Jobで指定した日時に非同期処理を行う](https://zenn.dev/yoiyoicho/articles/03863702867eb0)

### 使用技術
Ruby 3.1.2
Rails 6.1.6
Redis
sidekiq


### 実装手順
### 1, herokuにredisを追加する
対象のアプリにRedisが既に準備されていないかを確認する

```ruby
#どのアプリもredisを設定していなければ何も表示されない
$ heroku addons | grep heroku-redis
```

なかった場合はHerokuのCLIコマンドで追加すします。
```ruby
#-a の部分を自分のアプリ名にして実行
$ heroku addons:create heroku-redis:hobby-dev -a web-album
```

ログに出てくる``heroku addons:info ~~~``を実行すると作成状況を教えてくれます。
構築は数分あれば完了します。


### 2, Procfileの作成

Procfileは起動時にアプリで実行するコマンドを指定するものでアプリのwebサーバーなどを定義できるらしいです。
procfileはルートディレクトリに設置するのでこんな形で新しくファイルを作成します。

[![Image from Gyazo](https://i.gyazo.com/65d5f97eceb1b5095eb0b29468c13b5e.png)](https://gyazo.com/65d5f97eceb1b5095eb0b29468c13b5e)

ファイルの中身を以下のように編集します。
```ruby
web: bin/rails server -p $PORT -e $RAILS_ENV
worker: bundle exec sidekiq
```
ファイルの中身は`<process type>: <command>`の形で書きます。
commandの部分でdynoで実行する必要のあるコマンドを指定します。ここではsidekiqの起動を指示しています。
ファイルの記述が終わったら編集内容をcommitしてherokuにpushします。

### 3, worker dynoを作成する
最後に以下のコマンドを実行します。
```ruby
heroku ps:scale web=1 worker=1
```
以上で本番環境でもactive jobが使えるようになっているはずです！


初学者なので何か間違った記述があった場合はご指摘頂けると助かります！
ガラケーからスマホへ連絡先を移行する方法(SDカード使用)

# 背景
SDカードを使ってガラケーから連絡先を移行しようとしたが、SDカードのデータインポートが正常に出来なかった。
インポート時にエラーは発生しなかったが、インポート件数が「0件」となり、実際スマホの連絡先を見ても
データは空っぽで、取説通りにいかず。
結局Googleアカウントを使って何とかインポートに成功。
折角なのでメモとして残しておくこととする。

# 前提
* ガラケーでSDカードを使って連絡先がエクスポート出来る事。
* スマホはAndroid。
※iphoneでも同様な事が出来そうだが、試していないので不明。
* Googleアカウントが無い場合は作っておく。
ちなみにガラケー、スマホ共にAUだった。

# 手順
1. ガラケーから連絡先をSDカードへエクスポートする。
※ぱっと見、SDカードが使えなさそうなガラケーが多いが、昔のガラケーはバッテリーを取り外して
　SDカードを挿入出来るものも結構あるので、取説を見て確認する。

1. カードリーダー等でPCからSDカードにエクスポートした連絡先ファイルを確認する。
この時エクスポートしたファイルを確認すると、jsonファイル(Contacts1.json)だった。

1. 適当なツールを使って、jsonファイルをCSVファイルへ変換する。
念の為元ファイルはコピーして取っておくほうが無難。
(うまくいかなかった時の保険として)

1. PCでGoogleアカウントの連絡先をエクスポートする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214030/e42de908-20b5-7caf-8996-374a7f9e3f0f.png)

1. jsonファイルから変換したCSVファイルと、手順4でエクスポートしたGoogleアカウントの連絡先CSVファイルを開く。

1. Googleアカウントの連絡先CSVファイルに、ガラケーからエクスポート・変換したCSVファイルの中身だけを張り付ける。
この時フォーマットはGoogleアカウントの連絡先CSVファイルに合わせる事。
沢山の項目があるが、「Group Membership」は必須項目っぽい。
一意性はなくても良さそうなので、「* myContacts」を全部の連絡先にとりあえず適用。
ガラケー側で電話番号が2つ登録がある場合、以下の項目を列ごとコピーして2番目の電話番号用として追加する。
＜連絡先の電話番号用列＞
    * 追加前フォーマット
Phone 1 - Type
Phone 1 - Value
    * 2つ目の電話番号用列を追加した後のフォーマット
Phone 1 - Type
Phone 1 - Value
Phone 2 - Type　←　★追加
Phone 2 - Value　←　★追加

電話番号を格納する際、上記の「Type」列は必須のようなので、いったん全部「Mobile」で登録。
連絡先が無事インポート出来た後、スマホの連絡先で必要に応じて変更する事とする。

1. 編集したGoogleアカウントの連絡先CSVファイルを保存、連絡先からインポートする。

1. スマホの連絡先アプリを開いて、ガラケーから移植した連絡先が見える事を確認する。
反映されない場合は、連絡先アプリのデータ参照先を「Googleアカウント」に変更する。

以上！

# 感想

ちょっと時間はかかったが、今まで何も気にせず使っていた連絡先アプリについても少しは考えるようになり、
勉強になって良かったと思う。
Qiitaで記事を書く際に参考にしているサイト

数式などのMathJax記法をコピペで使える
https://easy-copy-mathjax.nakaken88.com/

数式の書き方
https://qiita.com/sukapontan/items/bbff92339aca1158233f#%E6%95%B0%E5%BC%8F%E3%82%A8%E3%83%AA%E3%82%A2%EF%BC%91%E8%A1%8C

ディラック記法の書き方
https://qiita.com/yyu/items/c140fbbd1236fe25cc7a

Tex記法の書き方
https://qiita.com/ttabata/items/92a4a72b042e6a2dbbad

Markdown記法の書き方
https://qiita.com/shizuma/items/8616bbe3ebe8ab0b6ca1
Microsoft.Web.WebView2 ダークモード・ライトモード（prefers-color-scheme）を固定する

* Windowsでダークテーマを使用している
* WebViewが埋め込まれたWpfアプリケーションはダークモード未対応
* WebViewで参照するページがダークモードに対応した状態
 
このような状況で統一感を維持するため、固定する必要があったので、以下メモ。


WebView2で`PreferredColorScheme`を固定します。

```c#
// webView: Microsoft.Web.WebView2.Wpf.WebView2
 webView.CoreWebView2.Profile.PreferredColorScheme 
    = Microsoft.Web.WebView2.Core.CoreWebView2PreferredColorScheme.Light; // or Dark
```

CoreWebView2が初期化されるタイミングがWebView2インスタンスと異なるようなので、CoreWebView2InitializationCompletedイベント等、CoreWebView2インスタンスが参照できるタイミングで指定する必要があります。


---

書いてるときに使用したバージョン
Microsoft.Web.WebView2
1.0.1293.44
[Unity] クリックしたUIのuv座標(coodinate)を調べる

UI,例えばImageのクリックを受け取るようにするには、[Add Component]-[Event Trigger]を追加するのが便利です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/787d3971-bd79-a403-11e2-9b42bb3e0503.png)
例えば上記のようにPoiner Clickを追加すると、クリック時の情報BaseEventDataを引数に持った関数を呼び出すことができます。
あとは呼び出した関数の中で

```
public void OnPointerClick(BaseEventData e)
{
    RectTransform rt = transform as RectTransform;
    Vector2 lp;
    if(RectTransformUtility.ScreenPointToLocalPointInRectangle(rt, (e as PointerEventData).position, null, out lp))
    {
        Vector2 cood = lp / rt.rect.size + rt.pivot;
        Debug.Log("cood:" + cood);
    }
}
```
のようにすればuv座標(左下を(0,0),右上を(1,1)とした座標系)が返ってきます。
※Canvasの指定をScreenOverlay-cameraにしている場合は、上記nullのところにカメラを入れてあげる必要があります。

また、「指定したUIのcoodinate離れたところに別のUI(ポインターなど)を置きたい」という場合は

```
    Vector2 ofs = (rt.rect.size * (cood - rt.pivot)) *rt.lossyScale;
    pointerUI.position = rt.position + new Vector3(ofs.x, ofs.y, 0f);
```
のようにします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/b15ab660-f38a-8996-1393-ba234dde702c.png)
AndroidStidioファイル内のコード置換方法(Mac)

今回はxmlなのでViewのidの名前を変更するときなど、ConstraintLayoutを使用しているとViewのidを複数箇所に記載している事などがあるので、その場合に便利だったりします。


# ファイル内のコード置換方法
`command + F`でまず、検索を表示させます。
ここにリネーム前文字を入力します。

`command + R`でリネーム後の文字を入力します。

Replaceを押すと置換されます。
Replace Allはファイル内全て置換されます。

![スクリーンショット 2022-08-21 19.24.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274615/c97cdd19-3266-b2de-afc8-fb7b077f0bd1.png)
このスクリーンショットの場合androidがappに置換されます

以上です。
今昔秀歌百撰  2012, 市川 浩 編<エンジニア夏休み企画>【読書感想文】

エンジニア夏休み企画  【読書感想文】
https://qiita.com/official-events/6d31965c499a69377c0b

【読書感想文】に焦点を当てたのは良い企画だと思った。

 <この項は書きかけです。順次追記します。>

人生で影響を受けた本100冊。
https://qiita.com/kaizen_nagoya/items/16af53acbb147a94172e

に掲載した本のうち、「新人プログラマ応援」企画で「私の推薦書３３冊」として３３冊紹介した。

新人プログラマ応援　私の推薦書３３冊
https://qiita.com/kaizen_nagoya/items/98c62f051dbdb4f8aca2

残りの６７冊から、順に過去の読書感想を引用し、新たな読書感想文を追記する。

# 28. 今昔秀歌百撰 
2012, [市川 浩](https://ja.wikipedia.org/wiki/市川浩), 谷田貝 常夫, [桶谷 秀昭](https://ja.wikipedia.org/wiki/桶谷秀昭)
<img width="200" alt="27923.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51423/96d9fe26-870e-d984-9ea3-a636654ac80c.png">
https://www.amazon.co.jp/dp/4990531221/
https://bookmeter.com/books/8165711
https://booklog.jp/item/1/4990531221

>すべての漢字を電子的に表現するための事業、文字鏡研究会でお世話になった方々が中心に制作された、短歌撰集、研究冊子。平成２４年にいただいてから、ネットで広報活動を始める。ちょうど、今昔文字鏡の広報活動をさせていただいたのと同じ。2015年の春から、大量に短歌を作成し始めるにあたって、広報活動および未掲載資料の作成を再開。

今昔秀歌百撰　全項目索引（一覧）
https://researchmap.jp/blogs/blog_entries/view/81777/f691323917cc4ea12caf0b03b34c8ea0

# 文字鏡フォント。
追悼　古家 時雄。日本語（２）
https://qiita.com/kaizen_nagoya/items/64c2ff25271ea8ebf2b0

リンクがResearchmap 2.0になってから切れたままになっていました。ごめんなさい。UIの改良と言いながら、古いURLを全部リンク切れにするUIって一体なんだろうと不思議に思いました。　

文字鏡フォントは、漢字を使った東アジアの文献のすべての電子化を可能にするための事業でした。　

ネットでは一部の人たちは、文字鏡フォントをあたかも自分たちが作ったかのように宣伝したり、ある人たちは、有償で販売することに文句をつけてきました。

努力して積み重ねてきたことを、よく事情をしらべて、文字鏡フォントの勝手にサイトを作ったら、その資料を引き継いで、公式ページを作ってくださいました。　

市場をよく調べ、市場の動向を把握して、責任持って行動すれば、権利者の方から、暖かい言葉をかけてくださることが分かるかもしれません。　

文字鏡フォントを作った成果の一つとして作られたのが、今昔秀歌百撰 です。　

私が短歌を始めたのは、この書籍の広報をかってにしながら、許諾を得て、非公式に活動をしているなかで、自分も短歌を作っていれば、短歌を作っている人たちへの宣伝は容易だということがわかったからです。　

結果として、計画者の１日、味噌が好きという２冊の歌集を、文学フリマで販売させていただきました。計画者の1日では、二桁販売実績をいただき、感謝の念に絶えません。味噌が好きは、熊本地震復興を訴え、九州の関係者から、お褒めの言葉をいただきました。

どんな発行物も１人の人に評価されれば十分です。　場合によっては、１０年後に一人の人に評価されるのでもよい。

「人生で影響を受けた本100冊」に28冊足す計画（13冊）

https://qiita.com/kaizen_nagoya/items/3ae6633725df77261df8

# 箱庭プロジェクト


箱庭もくもく会 #10 日時：2022/09/14(水) 17:30-19:30

https://hakoniwa.connpass.com/event/258129/

この項目は、箱庭プロジェクトを市場分析の対象として、原則的には、箱庭プロジェクトの外部から分析し、外部から箱庭の広告宣伝のための戦略会議を仮想した結果、仮想「箱庭もくもく会」を開催してみることを企画するものである。　
一切の内容は、箱庭プロジェクト、Athrill, TOPPERSとは無関係である。　
一(いち)参加データアナリストの、個人的なつぶやきです。

箱庭は、ありとあらゆるものの模擬試験を行うための基盤を提供しようとしているように見えます。　

日本のプロジェクトであれば、そのうち、ありとあらゆる日本語の文字が、システムの中で使えるようにする可能性があります。　

心無い人たちの、さまざまないやがらせなどにより、文字鏡フォントは、現在封印されたような状態になっています。オープンソースプロジェクトだけが、この眠れるフォントを掘り起こす力を得るかもしれないと思っています。

 ＜この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。＞

# 文書履歴(document history)
ver. 0.01 初稿 　20220821
LarevelのcreateメソッドによってDBへレコードを挿入する際の外部キーの自動取得

## createメソッド
- MVCモデルのM(Model)クラスから呼び出すことができるメソッド。
- 引数に連想配列を渡すことで、紐づけているDBのテーブルにデータを追加することができる.
- 同様にデータを追加することができるsaveメソッドもあるが、こちらはインスタンスを引数とすることに注意。
- リレーションを定義している場合、createメソッドとsaveメソッドともに外部キーには主テーブルの主キーを自動的に格納するようになっている。

```php:create method
// 掲示板アプリを想定して、投稿者を格納するテーブルをPost,投稿コメントを格納するテーブルをCommentsとする。
// また、PostとCommentsには一対多のリレーションを定義しているとする。
// Commentsテーブルにはpost_idカラムがあり、外部キーとする。参照先はPostテーブルのidとする。

$post = Post::find(1); // Postテーブルの主キーが1のレコードのインスタンスが$postに格納される。
$post->comments()->create([ // PostとCommentsにリレーションが定義されているため、自動でpost_idを1としてレコードを作成する。
    comments = 'A new comment.';
]);
```
- リレーションを定義して、親モデルから子モデルにアクセスする場合、Laravel公式ドキュメントによると外部キーは次のように想定されます。
>Eloquentは、Commentモデルに対する外部キーを自動的に決めることを心に留めてください。規約によりEloquentは、自分自身のモデル名の「スネークケース」に_idのサフィックスをつけた名前と想定します。ですから今回の例でEloquentは、Commentモデルの外部キーをpost_idであると想定します。
- また、子モデルから親モデルにアクセスする場合、次のようにして親モデルを探します。
>前の例でEloquentはCommentモデルのpost_idと一致するidのPostモデルを見つけようとします。Eloquentはリレーションメソッドの名前として、_に続けて主キーのカラム名をサフィックスとして付けた名前をデフォルトの外部キーとします。
## 参考文献
- [Laravel公式ドキュメント（日本語）](https://readouble.com/laravel/6.x/ja/eloquent-relationships.html#one-to-many)
【Swift】レイアウトの優先順位を設定

# 問題点
|理想|現状|
|:-:|:-:|
|![Simulator Screen Shot - iPhone 12 - 2022-08-20 at 18.25.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/00259665-2ab9-c1b9-dcc0-f3cb47b72a12.png)|![185735903-6b37eec7-3af5-40b5-9c80-fe385d70bc92.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/43f0f612-34b8-9c73-bf20-e05954878c01.png)|

タイトルの方が優先的に表示されてしまい、「INSTALL」ボタンが潰れてしまう。

# 現在のレイアウト
![スクリーンショット 2022-08-20 21.59.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/e57b2947-ce22-101d-383e-5735e34290b3.png)
![スクリーンショット 2022-08-20 22.00.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/ac0dbe10-69c0-b86e-2273-bcfb63cf2dd6.png)
![スクリーンショット 2022-08-20 22.00.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/45374a5e-4a95-7a93-09df-908f90d3c20b.png)

# 解決方法
優先したい方の「Content Compression Resistance Priority」を優先しない方より上にする
![スクリーンショット 2022-08-20 22.01.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/8dc1cfa2-0e85-3ed1-318a-698ef5c683c5.png)

# おわり
固定サイズしか方法はないと思ってたのですがこんなに便利な方法があるとは思いませんでした。
DockerでVite(React)のサーバーが立ち上がっているのにアクセスできない

# はじめに

この記事は2022年8月にまとめていた「細かいつまずいたことをメモしておく(8月編)をそれぞれ投稿した内容になります
解決方法が最新でない可能性もありますのでご了承ください

# 問題

Dockerでviteプロジェクトのサーバーを起動して以下のログが出ているがアクセスできない

```
react  |   VITE v3.0.4  ready in 309 ms
react  | 
react  |   ➜  Local:   http://localhost:5173/
````

docker-compose.ymlでは以下の設定を行っている

```yml:docker-compose.yml
    ports:
      - "5173:5173"
```

# 解決方法

`vite.config.js`を修正する

```js:vite.config.js
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
  server: {
    host: true
  }
})
```

`server`を追加したところアクセスできるようになった

```
react  |   VITE v3.0.4  ready in 288 ms
react  | 
react  |   ➜  Local:   http://localhost:5173/
react  |   ➜  Network: http://172.31.0.2:5173/
```

# 参考

https://zenn.dev/tasuya/articles/158209072d3715
csvファイルをpandasのread_csv()で読み込む際にヘッダーがずれてしまう

# はじめに
csv形式のファイルをpandasの`read_csv()`で読み込んだ際にヘッダーがずれてしまうことがあったため、その対策例を紹介します

# どんなことが起きるか(現象)
下記のようなcsvファイル(sample.csv)を`read_csv()`で読み込んだ際にヘッダーがずれることがあります。
sample.csv は1行目はヘッダー、2行目以降はデータとなるようなcsvファイルです。
データの末尾に「,」(カンマ)　が入ってしまっています。

```:sample.csv
path
hoge\hoge.txt,
```

sample.csvを下記のhoge.pyで読み込むと・・・
```python:hoge.py
import pandas as pd
df = pd.read_csv('sample.csv')
print(df)
```

下記の出力結果となってしまいます。データの方にNaNが入ってしまってますね。
```:出力結果
               path
hoge\hoge.txt   NaN
```

下記の出力結果となるのが理想です。
```:理想の出力結果
            path
0  hoge\hoge.txt
```


# なぜずれるか(原因)
上記の場合は、データの方にのみ末尾に不要な「,」(カンマ)が入ったことが原因です。
不要なセパレータが入り、ヘッダーとデータでセパレータの数が異なる場合にずれることがあると思われます。


（また、上記の場合はExcelで確認したのですが、ヘッダーが特にずれることなく、また末尾のカンマも消してくれるので問題ないように見えてしまいます。私はそれでハマりました・・・）




# 対策例
pythonで「sample.csv」を処理し、末尾の不要なセパレータを削除した「sample_out.csv」を出力する例を示します。


## 対策例1 (末尾の不要なセパレータを削除する)

末尾の改行を削除→末尾の,を削除→改行を追加　を行うことで末尾にある不要なセパレータを削除する方法です。

```python
with open('sample.csv') as f:
    lines = f.readlines()
    lines=[x.rstrip() for x in lines]
    lines=[x.rstrip(',') for x in lines]
    lines=[x+'\n' for x in lines]
#ファイルに出力
with open('sample_out.csv', 'w') as fw:
    fw.writelines(lines)
```

## 対策例2　(pandasのshift()を使用してヘッダーをずらす)

pandasには、データを行・列方向にずらす`shift()`メソッドがあるのでそれを使う方法です。

https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.shift.html

```python
df = pd.read_csv('sample.csv')
df.reset_index(inplace=True)
df = df.shift(axis=1)
df.drop('index', axis=1, inplace=True)
df.to_csv("sample_out.csv", index=False)
```
最終行で`to_csv()`で出力していますが、dfをそのまま処理することが可能です。

# 動作環境
下記のバージョンで動作確認しました
- Python: 3.7.9
- pandas: 1.2.3

# まとめ
csv形式のファイルをpandasの`read_csv()`で読み込んだ際にヘッダーがずれてしまうことがあったため、pythonで動作する2種類の対策例を紹介しました。

# リンク集
セパレータが特殊な場合でもヘッダーがずれることがあるみたいなので、下記もご参考に！

https://qiita.com/yoshikee/items/94716e907225eb65c0cc
XAML 学習ノート

# XAMLとXML
XAMLは、ソフトウェアの表示画面などを記述するためのXMLベースのマークアップ言語なので、基本的にXMLを理解すれば、XAMLは理解できる。

# MainWindow.xaml
Visual StudioでWPFアプリケーションのプロジェクトを新規作成すると、MainWindow.xamlとMainWindow.xaml.csは以下のようになっている。（Titleの内容は若干変えている）
```C#:MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace CashRegisterApplication
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }
}
```

```xml:MainWindow.xaml
<Window x:Class="CashRegisterApplication.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:CashRegisterApplication"
        mc:Ignorable="d"
        Title="MainWindow" Height="700" Width="800">
    <Grid>
    </Grid>
</Window>
```

xamlの方の説明をしていく。
1行目の「x:Class」は、そのxamlコードの表すクラス名を表し、C#コードの部分クラスと対応させている。
そのためC#のコードのクラスにはpartialという記載があるので、ここで部分クラスであるMainWindowと対応しているのがわかる。

2～6行目は名前空間を定義している。
名前空間に関してはxmlの以下の説明がわかりやすかった。
（https://www.kanzaki.com/docs/sw/names.html）

7行目は、接頭辞”d”をアプリ実行時に無視するような設定をしている。

## Grid
MainWindow.xamlの9行目のGridは、行と列を定義して画面レイアウトを構成する。

参考サイト：
https://anderson02.com/cs/wpf/wpf-3/

# 参考サイト
https://biotech-lab.org/articles/8442

https://biotech-lab.org/articles/8454
Hyper-VのDefault Switchでインターネットにつながらない時の対処法

# 症状
Default SwitchでゲストOSからインターネットに接続できない。

外部のスイッチを作っての解決策はたくさんネット上にあるのですが、
Default Switchのままで何とかならないのかなと、
ググっていたら、簡単な方法で解決できたの共有(簡単に訳しただけ汗)。

# 環境
## ホスト環境
OS　Windows10　21H2
ネットワーク物理デバイス 無線LAN　1つのみ

## ゲスト環境
Windows11　開発環境(クイック作成で使えるアレ)

# 解決策
物理デバイスの自動メトリックのチェックをオフにし、
インターフェースのメトリックの値を1にする。
参考としたサイトには無線と有線が混在する場合、無線を1、優先を2に設定する例がある。

# 手順
　1. ネットワークの接続からホストOSの物理デバイスのプロパティを開く
　2.インターネットプロトコルバージョンv4のプロパティを開く
　3.詳細設定を開く
　4.自動メトリックをチェックオフ
　5.インターフェースメトリックに1を設定
　6.ホストOSを再起動
　　→自分の場合はホストOSを再起動しないとゲストからインターネットに接続できませんでした。

# 参考
[Hyper-V Default Switch No Internet (Fixed)]( 
https://internet-access-guide.com/hyper-v-default-switch-no-internet/)
HI-TECH Cを使ってみた

# はじめに
環境：Windows 11

## 参考
CPM.EXE for Win32 で HI-TECH C を使う
http://hp.vector.co.jp/authors/VA000084/HI-TECH_C.html

HI-TECH C for CP/M Fan WIKI(JP)
http://hi-tech.msx.click/

MSX C Magazine HI-TECH C部屋 HI-TECH Cを256倍(!?)使うドキュメント
http://tatsu.life.coocan.jp/TMR/MSX-HCTECH.html

MSX(Z80)のセルフコンパイラ
https://www.nabeta.tk/msx/selfcc.html
HI-TECH C CP/M版

# HI-TECH Cの入手
http://web.archive.org/web/20040414090318/http://www.htsoft.com/software/cpm/index.html
若しくは
http://www.retroarchive.org/cpm/cdrom/SIMTEL/HITECH-C/
から Z80V309.EXE をダウンロードする。
自己解凍ファイルで64bitでは解凍できない。
MS-DOS Player若しくは拡張子をlzhにしてExplzhなどで解凍する。

適当なディレクトリに配置する（例：C:\etc\HI-TECH_C）

# CP/Mエミュレータの入手
CP/M program EXEcutor for Win32
https://www.vector.co.jp/soft/win95/util/se378130.html
から cpm32_04.zip をダウンロードする。

適当なディレクトリに配置する（例：C:\etc\cpm32_04）

# コンパイル
適当な作業ディレクトリを用意する（例：C:\Projects\etc\HI-TECH_C）

```dev.bat
@echo off
path %path%;C:\etc\cpm32_04
set cpmpath=C:\etc\HI-TECH_C
cmd
```

```hello.c
#include <stdio.h>
main()
{
	printf("hello, HI-TECH C\n");
}
```

環境変数を設定したバッチファイルでコマンドプロンプトを起動。
コンパイルして実行。

```
C:\Projects\etc\HI-TECH_C>cpm c hello.c
 COMPILER (CP/M-80) V3.09
Copyright (C) 1984-87 HI-TECH SOFTWARE

C:\Projects\etc\HI-TECH_C>cpm hello
hello, HI-TECH C

C:\Projects\etc\HI-TECH_C>
```

# asciiart

``` asciiart.c
/*
cpm c asciiart.c -LF
*/

#include <stdio.h>

main()
{
	int i, x, y;
	float a, b, ca, cb, t;

	for (y = -12; y <= 12; y++) {
		for (x = -39; x <= 39; x++) {
			ca = x * 0.0458;
			cb = y * 0.08333;
			a = ca;
			b = cb;
			for (i = 0; i <=15; i++) {
				t = a * a - b * b + ca;
				b = 2 * a * b + cb;
				a = t;
				if ((a * a + b * b) > 4) {
					break;
				}
			}
			putch("0123456789ABCDEF "[i]);
		}
		putch('\n');
	}
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257554/6bff3f91-76ab-5e0f-120f-9b010dd3dab5.png)

WebMSX/MSX-DOS2などでも実行可能。
![WMSX Screen.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257554/c7c1bb86-30e4-cb36-8947-52e23d4b3e0f.png)
FlutterでListTileの文字のデフォルトのフォントサイズを変更する

ListTileクラスの文字のデフォルトのフォントサイズを変更したい。

https://api.flutter.dev/flutter/dart-html/Text-class.html

ListTitleクラスでつかTextクラスのフォントサイズはTextThemaクラスのsubtitle1プロパティで設定されておりsizeは16だ。
なぜsubtitle1のプロパティなのかはドキュメントを探しても見当たらないのでわかる人がいたら教えてほしい。

https://api.flutter.dev/flutter/material/TextTheme-class.html

よってTextクラスのデフォルトのフォントサイズを変えるには以下のように記載する。

```dart
textTheme: TextTheme(
  subtitle1: TextStyle(fontSize: 180.0),
),
```

コードの全体も記載する。

```dart
import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  static const String _title = 'Flutter Code Sample';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        textTheme: TextTheme(
          subtitle1: TextStyle(fontSize: 180.0),
        ),
      ),
      title: _title,
      home: Scaffold(
        appBar: AppBar(title: const Text(_title)),
        body: const Center(
          child: MyStatefulWidget(),
        ),
      ),
    );
  }
}

class MyStatefulWidget extends StatefulWidget {
  const MyStatefulWidget({Key? key}) : super(key: key);

  @override
  State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  bool _lights = false;

  @override
  Widget build(BuildContext context) {
    return Column(children: [
      ListTile(title: Text("ListTitle"), leading: Icon(Icons.ac_unit)),
    ]);
  }
}


```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2458996/c89c7eb8-1b40-dc9c-c863-840d2c685e76.png)
create-react-app でTailwind CSS を使う

## 環境
- OS: Window 10
- Node.js: v16.16.0

## 手順
- create-react-app でプロジェクトを作成する
```terminal
npx create-react-app my-app
cd my-app
```

- Tailwind CSS と依存関係のモジュールをインストールする
    - PostCSS とは、JSプラグインでスタイルを変換するためのツール
    - Autoprefixer とは、ベンダープレフィックスを自動で付けるツール
```terminal
npm install -D tailwindcss postcss autoprefixer
```

- initコマンドを実行してtailwind.config.js とpostcss.config.js を生成する
    - tailwind.config.js はTailwind CSS の設定ファイル
    - postcss.config.js はPostCSS の設定ファイル
```terminal
npx tailwindcss init -p
```

```tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [],
  theme: {
    extend: {},
  },
  plugins: [],
}
```

```postcss.config.js
module.exports = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
}
```

- tailwind.config.js を修正する
    - src以下の、すべてのテンプレートファイルのパスを追加する
```diff_javascript:tailwind.config.js
/** @type {import('tailwindcss').Config} */ 
module.exports = {
  content: [
+    "./src/**/*.{js,jsx,ts,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}
```


- CSSにTailwindのディレクティブを追加する
```index.css
@tailwind base;
@tailwind components;
@tailwind utilities;
```

## 動作確認
- プロジェクトを実行
```
npm start
```

- プロジェクトでTailwind CSSを使ってみる
```jsx:App.js
import React from 'react';
import './index.css';

function App() {
  return (
    <div>
      <h1 className="text-3xl font-bold underline">Hello, Tailwind CSS!</h1>
    </div>
  );
}

export default App;
```

こんなかんじで、フォントサイズと字の太さ、下線が適用されました～
![tailwind.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2667439/68351269-69c4-d481-ea63-8bf1876eb5da.png)

## 参考文献
https://tailwindcss.com/docs/guides/create-react-app

https://github.com/postcss/postcss

https://github.com/postcss/autoprefixer
Userモデル、usersテーブル作成とバリデーション【10日目】

# 概要
- Userモデルを作成
- usersテーブルを作成
- TDDでバリデーション

# 1. モデルとマイグレーションファイルの作成
- `rails g model user`でモデルを作成
- 自動的にマイグレーションファイルが生成される
# 2.マイグレーションファイルの編集
- マイグレーションファイルの中身を編集
# 2. テーブル作成
- `rails db:create`でusersテーブルを作成
# 3. モデルの編集
- rspecでテストを書いてfailedを確認
- モデルにvalidation書く
- テストが通るか確認

# その他
- bcryptをgemでインストール
- has_secure_passwordでパスワードをハッシュ化
- パスワードのカラム名はpassword_digestへ
- 一意性（uniqueness）のバリデーションはDBレベルでも行う

# 参考
- [Ruby on Rails チュートリアル](https://railstutorial.jp/chapters/modeling_users?version=6.0)
【Cシェル備忘録】連続したスペースを含むテキストの扱い

# はじめに
連続したスペースを含むテキストファイルを編集するシェルスクリプトを作成する必要が生じた際に、初心者の私が苦肉の策を講じたサンプルコードを掲載したいと思います。

# 実現したかったこと
各行の桁数が決まっているテキストファイル（以下の例では10桁）を読み込み、特定の桁を置換したファイルを出力する。(便宜上、半角スペースを「-」で表示)
【例】
```input.txt
a--bb---cc
```
　このテキストを
```output.txt
a--xx---cc
```
　に修正（先頭から4,5桁目をbbからxxに置換）。

# サンプルコード
あれこれ試す中で、編集時に連続したスペースが1つに集約されたり、あいまいな範囲指定だとエラーが表示されたりしました。最終的に連続したスペースで区切られた文字列を切り出し、置換して再度つなげる際にスペースを再現する荒技で対処しました。
```sample.csh
#!/bin/csh

set readStr = "`sed -n 1p input.txt`"   #テキストファイルの1行目を代入

set outStr1 = `echo "${readStr}" | cut -c 1`   #1桁目「a」を代入
set outStr2 = "xx"   #置換用
set outStr3 = `echo "${readStr}" | cut -c 9-10`   #9,10桁目「cc」を代入

set space1 = "`printf "%2s"`"   #2連続スペースを用意
set space2 = "`printf "%3s"`"   #3連続スペースを用意

#文字列とスペースを連結
echo "${outStr1}${space1}${outStr2}${space2}${outStr3}" >> output.txt
```

# おわりに
シェルスクリプトの中でCシェルを採用したのは配列が使用できるためで、実際には今回の処理の中の一部も配列を用いましたが、連続したスペースを配列の要素とするとうまくいかなかったため、上記のようなスクリプトになりました。

似たような処理の実現でお困りの方の手助けとなれば幸いです。
WSL上でヒープ領域と格闘していた話

# 環境
Ubuntu 20.04 LTS (Focal Fossa) on WSL
g++ (Ubuntu 9.3.0-10ubuntu2) 9.3.0


# 前書き
ふと思い立ってWSL上でプログラムを久々に書き出したが、　`Segmentation fault (core dumped)`
原因は実行コードに対してヒープ領域が足りていないからだと思われる。
実際はもっとしょうもないところでミスをしているのだが、後学と自戒のために残しておく。

# 調査開始　ulimits編
[プログラムのスタックサイズを変更する](https://www.hiraku.ro/tdiary/tb.rb/20081216)
すぐにヒットしたのはこちらのサイト
しかしWSL上ではulimitの挙動が違う

```
$ ulimit -s
> 8192
```
試しに8192より大きなサイズを指定してみると
`-bash: ulimit: stack size: cannot modify limit: Invalid argument`
失敗。

ulimitsの数値はログイン時に決まっているらしく、設定ファイルは `/etc/security/limits.conf` 
設定方法も当該ファイルに書かれているのでそのように記述して再起動するも失敗。

あれこれ調べた結果これでうまくいきました、最後尾参照
https://github.com/microsoft/WSL/issues/633
どうやら、WSL上ではulimitsがうまく動作しない（？）ようで、issueがこのほかにも挙がっていました
[WSL2 の Ubuntu18 で ulimit open file を変更したい](https://bayashi.net/diary/2020/0730)

これでstack sizeは変更され、問題ないかなといったところで　`Segmentation fault (core dumped)`

# 調査開始　WSL編
詰まったので原点回帰、セグフォは本当にメモリの問題なのか？
コアダンプを確認しようとするも、出ない。
https://github.com/microsoft/WSL/issues/1262
WSL上ではコアダンプが出ないらしい。しかしスレッド末尾の会話を見る限り、WSL2上では動いていそう。

ん？
`wsl --list --verbose`
```
  NAME      STATE           VERSION
* Ubuntu    Stopped         1
```

はい。

https://www.kagoya.jp/howto/it-glossary/develop/wsl2_linux/
WSL2を入れるにあたって参考にしたサイト。ここで手順をミスって、Storeのバージョン付きのWSLのインストールに失敗してしまい、バージョンなしのUbuntuを選んだのが問題だったようだ。
一回すべてを消して再度手順をやり直して成功。

`Ubuntu-22.04    Running         2`

ulimit -s も問題なく行え、問題のプログラムも走った。

# 結論
環境のセットアップはちゃんとやりましょうね、という当たり前の話に落ち着いた。

# 余談
gccの-Wlオプションとは何ぞや？と思い調べたやつ
リンカ用オプションというところまではすぐ出てくるが、じゃあそのオプションはどこから確認できるんだ？
[What is the OPTION in the GCC's option "-Wl,OPTION"?](https://stackoverflow.com/questions/1258998/what-is-the-option-in-the-gccs-option-wl-option)
という記事をStackOverFlowで見つけたのでペタリ
http://sourceware.org/binutils/docs-2.16/ld/Options.html#:~:text=of%20the%20linker%5D-,%2D%2Dstack%20reserve,-%2D%2Dstack%20reserve%2C
こっちはオプションへのリンク
1983年40年前ステージ電飾制御

### パソコンで初めて、電飾制御を行いました。 
![1938EPSON.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378482/fe05928b-3c86-5c68-a95d-391d85507cbd.jpeg)
### ８ビットのハンドヘルドコンピュータＨＣ－２０を使いました。
・コンサートで数百本の蛍光燈を制御し、点滅させるだけの時は、ＣＰＵは使いませんでした。その後、音響のＶＵメータや時計を床電飾で表現するために。ハンドアッセンブラに記憶装置は、ミニカセットテープです。テクニカルリハーサルまでにバグがぬけず散々迷惑をかけ、音響さんにもノイズ発生器を作っているようなものですから、迷惑をかけました。オペレータスタッフには、カセットテープ トラブルフで毎回プログラムの読み込み時ヒヤ汗をかかせました。
### パターンの確認はサーマルプリンターでした!

その後ＨＣ－４０でＣＰ／Ｍベースのプログラムができソフトの開発も楽になり、何とＲＯＭディスクまで搭載し、カセットテープの恐怖から開放されました。
### おわりに、
今思うとそのころの私は毎日がチャレンジで、とにかく新しい方法ばかり考えていました。
こんなほとんど学生気分のぬけない、私に寛大に付き合っていただいた、
そのころの関係スタッフに心からお礼を言いたい気持ちです。

懐かしい　＜昨晩お会いしましょう＞　ここから参加　
https://yuming.okitsune.com/bio/tour/81_82.html
https://yuming.okitsune.com/bio/tour/83_84.html
https://yuming.okitsune.com/bio/index.html
https://yuming.okitsune.com/
https://news.1242.com/article/148735

### 　追記　2023　11/5
最初は　昨晩お会いしましょう
1981年    12月17日  浜松市民会館　スタートでした　25歳誕生日前日でした。
（　私は1956年　12月18日浜松市で生まれ、その後信州で育ちました　）
1983年   REINCARNATION   7月 6日 ツアー初日の武道館公演。
HC-40のバグが抜けずリハーサルですべて、動きませんでした。
一週間　移動時のみの睡眠でした。動いたのは本番当日朝5時でした。
（　動いたときは　さんざん　泣きました！！　）
しかし、さすがに、皆さんにご迷惑かけましたので、
そのツアーが私の最後のユーミンのお仕事でした。
https://yuming.okitsune.com/bio/tour/83_84.html
（　双方リンクになりました　）

yuming.okitsune.com　製作者さんから、お聞きしたことですが、
”　93年ごろの雑誌でユーミンが電飾フロアについてしたコメントで、
「本番直前まで動かなかったのが直前でピタッと直った。
その時はもう心から"ミラクル！"って叫びたかった」って書いてます。”

はい、トラブルがあったからこそ、覚えていただいていたと思います。💦
OSPFとダイクストラ法

# はじめに
ルーティングプロトコルである`OSPF`と、最短経路を求めるアルゴリズムである`ダイクストラ法`との関係について備忘録を残しておきます。


# そもそも`OSPF`とは
`OSPF`はOpen Shortest Path Firstの略で、自立システム（Autonomous System）と呼ばれる地域ネットワークやプロバイダ内部のどのホストなのかを認識するIGP（Interior Gateway Protocol）で利用されるプロトコルのこと。リンク状態型（Link-State）の経路制御アルゴリズムを利用している。

代表的な経路制御アルゴリズムは以下の2つである。

|  | 距離ベクトル型 | リンク状態型 |
|-----------|------------|:------------|
| 概要       | 距離と方向によって目的のネットワークやホストの位置を決定する方法 | ルーターがネットワーク全体の接続状態を確認して経路制御表を作成する方法 |
| 詳細 | ルーター間でネットワークの向きと距離に関する情報が交換され、この向きと距離の情報から経路制御表（ルーティングテーブル）を作成する。通過するルーターの数が距離（メトリック）の値として使われる。処理が比較的簡単である反面、向きと距離の情報しかないため、ネットワークの構造が複雑になると、経路制御情報が安定するまでに時間がかかる、経路にループが生じやすくなる、といった問題がある。 | ネットワークの構造はどのルーターにとっても同じであるため、全てのルーターが同じ情報をもつことになる。このため、各ルーターが経路制御情報を他のルーターと同期させれば経路制御を安定させることができ、ネットワークが複雑になっても各ルーターは正しい経路制御情報を持つことができ、安定した経路制御を行うことができる。その反面、 ネットワークトポロジーから経路制御表を求める計算には高いCPU能力と多くのメモリ資源が必要になる。このため、`OSPF`ではネットワークをエリアに分割できるようになっており、経路制御情報を減らせるような工夫がされている。|
| 主なプロトコル | RIP, EGP | IS-IS, `OSPF`|

距離ベクトル型のRIPでは、通過するルーターの数が最も少ない方向を経路に設定するが、リンク状態型の`OSPF`では、各リンクに重み（コスト）を付けることができ、この重みの合計値が最も少ない方向を経路に設定する。

# そもそも`ダイクストラ法`とは
`ダイクストラ法`は構造化プログラミングを提唱したダイクストラという偉い人が考えた、グラフにおける2点間の最短経路を求めるアルゴリズムのこと。
似たようなアルゴリズムにベルマン・フォード法があり、これは負の重みが許容される場合の2点間の最短距離を求めるアルゴリズムであり、グラフの辺の重みが全て非負である場合には、より高速な`ダイクストラ法`が利用される。
Pythonでこのアルゴリズムを実装すると以下のようになる。

```dijkstra.py
import heapq

# 辺情報を表す構造体
class edge:
    def __init__(self, end, leng):
        self.end = end      # 辺の終点
        self.leng = leng    # 辺の重み

INF = 10**9 # 初期化で使う十分大きな数

# 入力を受け取る
N, M = map(int, input().split())
G = [[] for _ in range(N)]  # G[i]：頂点 i を始点とする辺情報を格納する
for i in range(M):
    u, v, w = map(int, input().split())
    G[u].append(edge(v, w))

dist = [INF for _ in range(N)]  # dist[i]：頂点 0 から頂点 i への暫定的な経路長
dist[0] = 0
done = [False for _ in range(N)]    # done[i]：頂点 i の最短距離が確定しているか

hq = [] # (仮の最短距離、頂点番号) を管理するヒープ
heapq.heapify(hq)

# ヒープに最初の時点における情報を入れておく
for v in range(N):
    heapq.heappush(hq, (dist[v], v))

while len(hq) > 0:
    # ヒープの先頭要素を取り出す (v は頂点番号、d は 0 → v の仮の最短距離)
    [d, v] = heapq.heappop(hq)
    # 頂点 v の最短距離がすでに確定しているなら、何もしない
    if done[v]: continue

    # 頂点 v を始点とする辺 e について、更新を行う
    for e in G[v]:
        if dist[e.end] > dist[v] + e.leng:
            # 距離の更新がある場合には、ヒープに更新後の情報を入れる
            dist[e.end] = dist[v] + e.leng
            heapq.heappush(hq, (dist[e.end], e.end))
    # 頂点 v の最短距離を確定させる
    done[v] = True

# 答えを出力する
for i in range(N):
    print(dist[i])
```

# `OSPF`と`ダイクストラ法`との関係性
1. ネットワークLSA（Network Link State Advertisement, ネットワークにどのルーターが接続されているかを表す、ネットワークを中心に作成した情報）やルーターLSA（Router Link State Advertisement, ルーターにどのネットワークが接続されているかを表す、ルーターを中心に作成した情報）を`OSPF`によってルーター間で交換し、各ルーターは、ネットワークの構造を表すリンク状態データベース（Link State Database）を作成する。
1. ルーターは自分のリンク状態DBを完成させると、ネットワーク内の各ルーターまでの経路をすべて抽出し、経由するリンクの総コストを計算する。そして最も総コストの小さな経路を、そのルーターへの最短経路であると判断し、これを繰り返して最短パスツリーを構築する。これが`ダイクストラ法`である。

# 参考文献
https://www.ohmsha.co.jp/book/9784274224478/

https://algo-method.com/tasks/993/editorial

https://www.amazon.co.jp/dp/B09C3TPQYV

以上、ルーティングプロトコルの`OSPF`とアルゴリズムの`ダイクストラ法`との関係性に関する備忘録でした。
TCP備忘録

最近ネットワークに関する授業を閲覧しています。
そこで学んだTCPについて備忘録を残した記事です。
## TCPとは？
トランスポート層に該当するプロトコルで信頼性がある転送を保証
→信頼性とは「パケットのロスがない」、「送ったパケットが順番通りに受信される」ということ
## TCPの特徴
### コネクションマネジメント
TCPでは相手とコネクションを設立してから通信を開始
「Three Way Handshake」でコネクションを設立する
#### Three Way Handshake
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727545/5554927a-a15f-d565-5e7f-bea4f1119f9c.png)
>ACKとは
肯定応答（こうていおうとう、英: acknowledgement, ACK）は、テレタイプ端末で使われる制御文字であり、受信側が送信側に対して正しく受信したことを知らせるために送る。
[ウィキペディア](https://ja.wikipedia.org/wiki/%E8%82%AF%E5%AE%9A%E5%BF%9C%E7%AD%94)
1. サーバさん、コネクションを開始したいですけど、よろしいですか？
→相手とコネクションをしたい旨を伝えるために「SYN」を送信
2. いいですよ。準備OKでーす。
→受け取った「SYNbit」に「SYNACK」で返事
3. ご返信ありがとうございます！(では送りますね。)
→受け取った「SYNACK」に「ACK」で返事。この段階からデータを送信する場合もある。
### Flow Control
送信側がデータを送る速度より受信側の処理速度が遅いため、
送信側は受信側のバッファの様子を見ながらデータを送る。
もし、受信側のバッファが0だったら送信を停止する。
しかし、受信側のバッファに余裕ができたかを確認するため、
送信側はデータが0なセグメントを送り続ける。
で、「バッファに余裕あるよ」というACKが来たらデータの送信を再開する。
### 輻輳制御(Congestion Conrol)
ネットワークはみんなのもの。みんなが送りたいデータを存分に送信したら、ネットワークが処理できる範囲を超え
結局みんなが使えなくなる。
そのために輻輳制御をしよう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727545/a7a1c1c5-795f-c219-5e21-05faaddfcc6c.png)
[イメージの参照元](https://www.researchgate.net/figure/TCP-Slow-Start-and-Congestion-Avoidance-phase_fig1_256868797)
①Slow start：送信を開始した時点にはネットワークの状況が分からないため、ゆっくりデータを送信。
で、いい感じだと思ったら送る量を2乗ずつ増やす。
②ある瞬間になったら送信量をゆっくり増加させる。
③パケットの流失などネットワークに問題があったのが分からば、今まで送ってきたデータ量を急激に減らす。
(そうしないと、みんながネットワークを使えないから)
④また①からやり直す。