OmniAICreator/Qiita-1.07M huggingface dataset:
Trelloのアバター（アイコン）を漢字の名前にする方法がわかりずらかった。

### Trelloのアバター（アイコン）を漢字の名前にする方法。

こんにちわ。
Trelloのプロフィールの名前を漢字にしたらアバターも漢字2文字になるのかと思い変更したけど、人みたいなシルエットになって漢字の名前にならなかった :sweat_smile:
結局は漢字にすることが出来たけど、わかりずらかったので記事にしてみました。


#### まずは、Trelloの右上 〇 のアバターをクリック:zap:

プルダウンの __設定__ をクリック:zap:


![スクリーンショット 2023-01-11 201503.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2708892/8c32f067-d984-b18f-5b8d-b2b3d146ba22.jpeg)
遷移後の設定画面の上側にある、__Atlassianアカウントに移動__ をクリック:zap:

![スクリーンショット 2023-01-11 202922.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2708892/cf428858-8860-715a-b279-27ab534c526a.jpeg)
遷移後の画面左の __プロファイルとその公開範囲__ をクリック:zap:

![スクリーンショット 2023-01-11 204320.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2708892/b6b79b8f-855b-085d-0cc7-50f75abcfee0.jpeg)

 〇 のアバターをクリック:zap:
![スクリーンショット 2023-01-11 204206.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2708892/a9e82dfd-a799-96f1-dc2d-0b2ec9a4a793.jpeg)
プルダウンの __初期アバターを作成__ をクリック:zap:

![スクリーンショット 2023-01-11 204540.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2708892/290d39af-e48b-2a68-eb40-a66308d57da8.jpeg)
initialsのインプットに、 __ひらがな 漢字を最大4文字__　入力して __Update__ をクリック:zap:
するとアバターとして表示が出来ます。

以上、十例炉男からでした。嘘です。:smile:
2022/10/25主にITとかセキュリティの記事

重要インフラのランサム被害、4分の1は医療関連分野 - 米政府が注意喚起
https://www.security-next.com/140807

脆弱性DB「JVN iPedia」の3Q登録数、前四半期から倍増
https://www.security-next.com/140763

ソフトウェアをアップデートしなければいけない4つの理由(10/23)
https://news.mynavi.jp/techplus/article/20221023-2484804/

ランサムウェア攻撃でドイツの新聞印刷システムが停止(10/23)
https://news.mynavi.jp/techplus/article/20221023-2486833/

ランサムウェアの危機対応を準備している組織はわずか30%(10/21)
https://forbesjapan.com/articles/detail/51180

サイバー攻撃、２４％の企業が「１年以内に被害」回答　ウクライナ侵攻直後からは大幅減(10/23)
https://news.yahoo.co.jp/articles/4c01685779351d830f2b097f09dc951583ad32b2

【国際】サイバー攻撃対応者の心理的プレッシャー増大。疲弊への対策必要。IBM調査(10/23)
https://sustainablejapan.jp/2022/10/23/ibm-cybersecurity/78356

Windowsアップデートに偽装、完全に検出不能なPowerShellバックドアを発見(10/21)
https://news.mynavi.jp/techplus/article/20221021-2485873/

オンラインツールで全校生徒の成績丸見え　富山の中学教員が共有ミス(10/21)
https://www.asahi.com/articles/ASQBP4TBZQBPPISC001.html

一部生徒のPCから閲覧可能で7人が見る…中学校の全校生徒の成績等の個人情報 学外への流出は確認されず(10/21)
https://news.yahoo.co.jp/articles/3dc142c0c7a757d068000926cb98c5edeb4f2bc2

全４４７人の成績を誤って共有　八尾中、生徒２５人　閲覧可能に(10/22)
https://www.hokkoku.co.jp/articles/-/887056

L2ソリューション「StarkNet」とは？特徴や使い方を徹底解説！(10/21)
https://crypto-times.jp/l2-starknet/

「URSNIF」マルウェアの極めて危険な亜種が登場--「Emotet」に似た形態(10/21)
https://news.yahoo.co.jp/articles/bfb742d3ada553702e4b004c05c5151e39c3466b

Windows 11 Home／ProをMicrosoftアカウントではなくローカルアカウントで設定する裏技(10/21)
https://atmarkit.itmedia.co.jp/ait/articles/2210/21/news023.html

システム要件を満たさないPCでWindows 11「22H2」をアップデートしてみた！(10/23)
https://gunosy.com/articles/eRcvR

LinkedInに掲載の約60万人のApple社員、半数が偽物だった(10/23)
https://iphone-mania.jp/news-497833/

4館で貸し出し再開　那覇図書館　「情報源」利用者喜び(10/23)
https://ryukyushimpo.jp/news/entry-1604036.html

一味違う働き方　若手エンジニアの実像(10/24)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/020600014/101700129/

Windows並みの便利なデスクトップでLinuxを使いこなそう(10/24)
https://xtech.nikkei.com/atcl/nxt/column/18/02205/092800001/

「ノウハウは流出してもよい」　デジタル人材育成に必要な視点(10/24)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/020600007/101300124/

Azure上にデータレイク構築　「3度目の正直」で現場浸透へ(10/24)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/020600004/101400115/

Trusted Web(10/24)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/020600009/101800126/
docker-compose + Raspberry Pi ＋nginx + Flaskで現在接続しているWi-FiのSSIDを取得するときの備忘録



# 概要
docker-compose + Raspberry Pi ＋nginx + Flaskで、現在接続しているWi-FiのSSIDを取得しようと思った時に結構詰まったので、やり方を残しておく。


# ファイル構成
```
.
├── docker-compose.yml
├── nginx
│   └── default.conf
└── web
    ├── app.py
    ├── Dockerfile
    ├── requirements.txt
    └── templates
        └── index.html
```

# docker-compose.yml
### ここで`wpa_supplicant.conf`のボリュームを作成しておく！！！！！！！！！！
```yml
version: "3"
services:
  nginx:
    image: nginx:latest
    container_name: nginx
    ports:
      - "82:80"
    volumes:
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
    networks:
      - nginx_network

  web:
    build: ./web
    container_name: web
    ports:
      - 5002:5000
    volumes:
      - /etc/wpa_supplicant/wpa_supplicant.conf:/etc/wpa_supplicant/wpa_supplicant.conf
    networks:
      - nginx_network

networks:
  nginx_network:
    driver: bridge
```

# default.conf
```conf
server {
    listen       80;
    server_name  localhost;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

}
```
# Dockerfile
```Dockerfile
# Python3.7を使用
FROM python:3.7

# 作業ディレクトリを指定
WORKDIR /app

# カレントディレクトリのファイルをDockerコンテナの｢/app｣ ディレクトリにコピー
ADD . /app

# インストール
RUN pip install -r requirements.txt

# 外部に公開するポートを指定
EXPOSE 5000

# コンテナの実行コマンドを指定
CMD ["python", "app.py"]
```
# requirements.txt
```text
Flask
sqlalchemy
flask-sqlalchemy
```
# index.html
```html
<!DOCTYPE html>
<html lang="jp">
<head>
    <meta charset="UTF-8">
    <title>SSIDの表示</title>
</head>
<body>
    <div>
        <table>
            <tbody>
                <p>＜現在の状態＞</p>
                <tr>
                    <li>接続中WiFiのSSID： {{wifissid}}</li>
                </tr><br>
            </tbody>
        </table>
    </div>
</body>
</html>
```

# app.py
```python
from flask import Flask
from flask import render_template
import re


app = Flask(__name__)

@app.route('/',methods=['POST','GET'])
def wifissid():
    reg = re.compile('(?<=")[^")]+(?=")')

    with open('/etc/wpa_supplicant/wpa_supplicant.conf', 'r',encoding='UTF-8') as f:
        lines = f.read().splitlines()
        m = re.search(reg,lines[4])
        ssid = m.group()

        return render_template('index.html', wifissid = ssid)


if __name__ == '__main__':
    app.run(host='0.0.0.0',port=5000,debug=True)
```

# docker-composeで実行する
```
test@raspberrypi:~/server/flask $ docker-compose up -d
Creating network "flask_nginx_network" with driver "bridge"
Creating nginx ... done
Creating web   ... done
```
# docker-compose でステータスを確認する
```
test@raspberrypi:~/server/flask $ docker ps
CONTAINER ID   IMAGE             COMMAND                  CREATED          STATUS         PORTS                    NAMES
15f15f4d4042   flask_web   "python app.py"          2 minutes ago    Up 2 minutes   0.0.0.0:5002->5000/tcp         web
96a20fe360ce   nginx:latest      "/docker-entrypoint.…"   59 minutes ago   Up 7 minutes   0.0.0.0:82->80/tcp       nginx
```

# ブラウザで確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2684448/bc3b0012-7525-be8f-4e1b-0f712d702f32.png)
Arduino core for the ESP32を使っていてrst:0x8 (TG1WDT_SYS_RESET)による再起動が繰り返される時

ある関数を呼ぶ時だけ起こる場合は、スタックサイズが足りていない可能性があります。

標準のスタックサイズは8kバイトですが、SET_LOOP_TASK_STACK_SIZE()を使うと増やすことができ、これで解消できました。

通常はスタックオーバフローが発生していると、デバッグ出力で「\*\*\*ERROR\*\*\* A stack overflow in task loopTask has been detected.」のように検知されますが、大きく足りない場合には検出されないことがあるようです。

あまり無いケースのようですので、日本語情報として、投稿しました。

# 参考情報
* [ESP32ライブラリのサンプルスケッチ](https://github.com/espressif/arduino-esp32/blob/master/libraries/ESP32/examples/ArduinoStackSize/ArduinoStackSize.ino)
* [ESP32 Stack configuration (reloaded)](https://community.platformio.org/t/esp32-stack-configuration-reloaded/20994)
* [System Reset after touch pin interrupt](https://community.platformio.org/t/system-reset-after-touch-pin-interrupt/24130)

# 環境
* Arduino core for the ESP32 (ESP32 Arduino 2.0.4 based on ESP-IDF 4.4.1)
タグ検索機能　select(プルダウン)で実装してみた

タグ検索機能をプルダウンで実装したいとの声があったので
実装してみました！
タグ機能自体の実装に関しては、以下の記事を参考に進めていますので
DB周りの実装は以下の記事を参考にしていただけると幸いです🙇

https://qiita.com/MandoNarin/items/5a5610a40c66f77d6c10

# 目次
本記事は以下の流れで進みます！
1. [form_tagの実装](#formtagでの見た目実装)
1. [検索機能の実装](#検索機能の実装)

# form_tagでの見た目実装
## タグ機能を1つ実装した場合の検索機能
```erb:posts/index.html.erb
<%= form_tag({controller:"posts",action:"index"}, method: :get) do %>
        <%= select_tag :tag_search, options_from_collection_for_select(@tag, "id","name") %>
        <%= submit_tag "検索する" %>
<% end %>
```
`options_from_collection_for_select`の細かい説明は、
以前のこの記事↓にて行っているので、気になる人はみてみてください〜✨

https://qiita.com/yuuki-h/items/d88c52c22ae738dafc64#%E5%85%A5%E5%8A%9B%E3%83%95%E3%82%A3%E3%83%BC%E3%83%AB%E3%83%89%E3%82%92select%E3%81%A7%E5%AE%9F%E8%A3%85

## タグ機能を複数実装した場合の検索機能
先ほどの`select_tag`が増えるだけです！
(裏側の`controller`の処理も増えます)
```erb:posts/index.html.erb
<%= form_tag({controller:"posts",action:"index"}, method: :get) do %>
        <%= select_tag :size_search, options_from_collection_for_select(@size, "id","name") %>
        <%= select_tag :tag_search, options_from_collection_for_select(@tag, "id","name") %>
        <%= submit_tag "検索する" %>
<% end %>
```

# 検索機能の実装
基本的には、以下のフローで実装しています！
1. selectで必要なカラムをTagのテーブルから取得
1. paramsでURLから情報を取得
1. `find_by`を使ってレコードを取得&間接的に`posts`を取得

## タグ機能を実装した場合の検索機能
```rb:posts_controller.rb
    def index
        @tag = Tag.select("name", "id")
        tag_search = params[:tag_search]
        if tag_search != nil
            @posts = Tag.find_by(id: tag_search).posts
        else
            @posts = Post.all
        end
    end
```

## タグ機能を複数実装した場合の検索機能
```rb:posts_controller.rb
    def index
        @size = SizeTag.select("name", "id")
        @tag = Tag.select("name", "id")
        size_search = params[:size_search]
        tag_search = params[:tag_search]
        if size_search != nil && tag_search != nil
            size_posts = SizeTag.find_by(id: size_search).posts
            @posts = Tag.find_by(id: tag_search).posts & size_posts
        elsif size_search != nil
            @posts = SizeTag.find_by(id: size_search).posts
        elsif tag_search != nil
            @posts = Tag.find_by(id: tag_search).posts
        else
            @posts = Post.all
        end
    end
```

### 処理の流れと説明
まず、`select`でテーブルの中の特定のカラムのみ取得しています。
次に、`params`でURLから情報を取得します。

条件分岐としては、以下の４つです。
1. 複数の検索フォームが空でない場合（両方とも検索したい場合）
1. 1つの検索フォームのみ（片方のみ検索したい場合）
1. 同上
1. 検索フォームの値が空の場合

8行目の`@posts = Tag.find_by(id: tag_search).posts & size_posts`では
SizeTagのIDが一致するレコードかつ、TagのIDが一致するレコードを取得しています。


# 参考文献
https://railsdoc.com/page/options_for_select

https://qiita.com/MandoNarin/items/5a5610a40c66f77d6c10

https://qiita.com/zaqisuke/items/39e18a36d96d314b97af
IT用語辞典

## はじめに
前回の初投稿から時間が経ってしまいました。最低週1ペースで書きたいと思っているので反省...。今回は最近調べたIT用語について纏めました。


## IPアドレス
>PCやスマホなどのネットワーク上の機器に割り当てあられるインターネット上の住所みたいなもの。ページの閲覧、メールの送受信を行う場合、データの送信元や送信先を識別しなくてはいけないが、この識別に使われる番号がIPアドレスである。


## グローバルIPアドレス
>全世界で通用するアドレスで、世界中どこからでもデータ送受信の際に送り間違えのないよう、世界にただひとつ、インターネットに接続する際に割り振られるIPアドレス。


## プライベートIPアドレス(ローカルIPアドレス)
>自宅や会社など特定のネットワークの範囲内で用いられるIPアドレスのこと。


## WEBサーバー
>WEBブラウザからのリクエストに応じて静的画面や画像などのホームページのデータを Web ブラウザーに提供するサーバーのこと。


## ドメイン
>インターネット上の住所のようなもの。ホームページのURLの一部。
**図の挿入**


## SSH
>Secure Shell(セキュアシェル)の略称。リモートコンピュータと通信するためのプロトコルまたはソフトウェアのこと。SSHを使用することで認証部分を含めネットワーク上の通信がすべて暗号化されるため、安全に通信することができる。


## 公開鍵／秘密鍵
>公開鍵とは、通信を暗号化するときに使うキーのこと。
秘密鍵とは、対になる公開鍵で暗号化された通信を復号するために使うキーのこと。公開鍵と秘密鍵を使って暗号化するのを「公開鍵暗号方式」という。


## Cookie
>サイトを閲覧したときに、訪問者が訪れたサイトや入力データ、利用環境などの**ユーザー情報**が記録されたファイルのこと。同じサイトを訪れた際に、情報を再入力せずにログインできるなどのメリットがある。


## キャッシュ
>閲覧した**ウェブページ情報**を一時的に保存する仕組み（その一時的なデータそのもの）のこと。よく閲覧するページの表示スピードが上がるというメリットがある。


## SESSION
>接続してから切断するまでの一連の通信のこと。
一連のセッションにはSESSIONIDというものが割り当てられる。
そのSESSIONIDをサーバーが保持することにより、アクセスしたユーザーの情報と照らし合わせ、どのユーザーか判別することができる。それにより、リクエストをしたユーザーに適切なレスポンスを返すことが可能。


## HTTPメソッド
>HTTPメソッドは、クライアントが行いたい処理をサーバに伝えるという役割。(データを送って！データを削除して！etc...)


## UI
>User Interface(ユーザーインターフェイス)の略称。ユーザーとの接点を意味しており、Webサイトのボタン配置やデザインなどビジュアルに関することは全てに当てはまる。


## UX
>User Experience(ユーザーエクスペリエンス)の略称。ユーザーがモノやサービスを通して得られる経験や体験のこと。


## クラウド
>クラウド・コンピューティングのこと。ユーザーがハードウェアやソフトウェアを購入、利用しなくても、インターネットを通じて受けたいサービスを必要な時にどこからでも利用できる形態のこと。


## SaaS
>Software as a Service(サービスとしてのソフトウェア)の略称。
インターネット経由でユーザーがアクセスすることによって利用できるソフトウェアのこと。

例：Slack、Zoom、Google カレンダー、etc.


## PaaS
>Platform as a Service(サービスとしてのプラットフォーム)の略称。
インターネット経由で特定のソフトウェアを動作させるためのプラットフォームを提供するサービスのこと。

例：AWS、GCP、etc.


## IaaS
>Infrastructure as a Service(サービスとしてのインフラストラクチャー)の略称。システムの稼働に不可欠なサーバーやネットワークなどのインフラをインターネット経由で提供するサービスのこと。

例：AWS、Azure IaaS、etc.


## 最後に
IT用語多すぎる！！なんとなくで頭に入れています。(笑)
公開鍵/秘密鍵での認証方法とかは実際に作成してみないと理解できなさそうです。
Azureの管理ツールについて



●Azureポータル

●Azure Mobile App

●Azure　CLI

・az　基本的なコマンドの確認
・az version Azure CLIのバージョン確認
・az upgrade 更新
・az login Azureへの接続
・az storage account create -n <ストレージアカウント名>　-g <リソースグループ名>　-l <リージョン名(英語)>　ストレージアカウントを作成する
・az vm restart -g <リソースグループ名>　-n <仮想マシン名>　特定の仮想マシンを再起動する
・az find “<特定のキーワード>”　キーワードからコマンドを探す
・az find “storage”　storageというキーワードからコマンドを探す
・az storage —help　az storageのヘルプの確認(詳細な情報・使用できるサブコマンドの知覧が表示される)

●Azure PowerShell
使用するには、事前にPowerShellの管理ツールとモジュールのインストールが必要。

・Install-Module Az　　Azure PowerShellモジュールのインストール
・Import-Module Az　　Azure PowerShellモジュールのバージョン確認
・Get-Module Az　　　Azure PowerShellモジュールのバージョン確認
・Update-Module Az　　モジュールの更新

■Azure PowerShellの接続Azureへの接続を行い認証を受ける必要がある。
・Connect-AzAccount　azureへの接続

■Azure PowerShellでのリソースの操作
・New-AzStorageAccount -Name <ストレージアカウント名>　-ResourceGroupName <リソースグループ名> -Location <リージョン名(英語)>　-SkuName <レプリケーションオプション>　ストレージアカウントを作成する
・Restart-AzVM - ResourceGroupName <リソースグループ名>　-Name <仮想マシン名>　特定の仮想マシンを再起動する
・Get-Command -Name *任意の文字列*　特定の文字列を含むコマンドレットを探す
・New-AzStorageAccount -?　New-AzStorageAccountのヘルプの確認
・Get-Help New-AzStorageAccount -Examples　New-AzStorageAccountの実行例の確認

●Azure Cloud Shell
「Bash」と「PowerShell」が用意されている。起動時だけでなく使用中いつでも切り替え可能。

■Azure Cloud Shellを使用するメリット
Azure CLIyaAzure PowerShellモジュールの事前インストールが不要。
セキュアプロトコルと認証プロトコル

# セキュアプロトコル
### SSL(Secure Socket Layer)/TLS(Transport Layer Security)
```WebブラウザとWebサーバ間で認証と暗号化通信を行う```トランスポート層のプロトコル。
相手方のサーバから電子証明書を受け取り、なりすましでないことを証明するできたら、公開鍵暗号方式を使って、共通鍵を送る。
SSLをベースにしたものがTLSでSSL3.0以降のバージョンはTSLになる。

#### SSL/TLSの概要
相手の特定（認証）や暗号鍵の交換、情報の暗号化に使う各アルゴリズム（処理方法）を複数から選べるようになっています。
そのうちどのアルゴリズムを使うかは、通信最初の段階でサーバーとクライアントが相談し合って、お互いが共通に対応できるものを選択します。これを```ネゴシエーション``と言います。
最強の暗号と少し弱い暗号をがあり、サーバーかブラウザのどちらか一方が、少し弱い暗号にしか対応していない場合は、少し弱い暗号を使って通信することになる点に留意する必要がある。

https://www.sbcr.jp/product/4797386677/

#### HTTPS(HTTP over SSL/TLS)
SSLを用い、```WebサーバとWebブラウザ間の通信を暗号化して行う技術```。
HTMLファイルの転送プロトコルであるHTTPは平文でデータをやり取りするため、Webブラウザ上での決済などではHTTPSが利用される。
HTTPSの使用中はWebブラウザのアドレス欄に「https://」と表示される。

* HTTPのリクエストやレスポンスの内容は暗号化される。
* 誰かが盗聴しても内容を知ることができない。
* 通信内容を改ざんが行われても検出することができる。
* 接続先のWebサーバーが本物かどうかを検証することができる。

https://www.sbcr.jp/product/4797386677/

### IPsec(Security Architecture For Internet Protocol)
IP層で安全に通信を行うための技術の総称で、```IPパケットの暗号化```、```カプセル化```、```ユーザ認証```などの機能がある。IPv6から標準でサポートされてる。

### S/MIME
公開鍵暗号方式を用い、```メールを暗号化して送受信する電子メールの標準方式。```
送信側と受信側の両方のメールソフトが、S/MIMEに対応している必要がある。

### PGP(Pretty Good Privacy)
公開鍵暗号方式を用いて、```メールやファイルを暗号化するための仕組み及びプロトコル```。
デジタル署名を使い、改ざんを検出する機能を持つ。

# 認証プロトコル
### SMTP-AUTH(SMTP Authentication)
SMTP-AUTHは、メール送信に使うSMTPプロトコルに、```ユーザ認証機能を追加```したもの。
RFC 2554としてIETFにより文書化されている（現RFC 4954)

#### RFC ２５５４とは？
プロトコルの名前のようだ。

https://www.wdic.org/w/WDIC/SMTP%20AUTH
#### IETFとは？
IETFは、インターネット技術の標準化を推進する任意団体です。 コンピュータシステムを相互接続するため、 共通の技術仕様策定を議論するグループから発展したものです。

https://www.nic.ad.jp/ja/basics/terms/ietf.html

### SPF(Sender Policy Framework)
SMTPを利用したメール送受信において、```送信者のドメイン偽装を防ぎ、正当性を検出する仕組み```。
電子メールを受信したメールサーバが、送信元のメールアドレスのドメインのDNSサーバからメールサーバのIPアドレスを取得し、```SMTP接続元のサーバのIPアドレスと比較```することで正規サーバからメールであることを検証する。

### APOP(Authenticated POP)
メール受信に用いられるPOP３において```認証時にパスワードの暗号化```を行う方式。

### POP3S(POP3 over SSL/TLS)
SSL/TLSを用いて```伝送路そのものを暗号化```する。
ID、パスワード、メッセージ本文が暗号化されるので、盗聴リスクが低くなる。

### DKIM(DomainKeys Identified Mail)
受信したメールが```正当な送信者からのメールで改ざんされていないこと```を検証できる送信ドメイン認証技術。送信時に秘密鍵で生成した署名をメールヘッダに添付する。
* DKIM (DomainKeys Identified Mail)は、 電子メールにおける送信ドメイン認証技術の一つであり、 メールを送信する際に送信元が電子署名を行い、 受信者がそれを検証することで、 送信者のなりすましやメールの改ざんを検知できるようにするものです。
出典 https://www.nic.ad.jp/ja/basics/terms/dkim.html

# 出典
https://gihyo.jp/book/2022/978-4-297-12375-8

https://www.sbcr.jp/product/4797386677/
【BigQuery】スケジュールクエリ用パラメータ@run_dateを日本標準時(JST)で利用する

BigQueryの『スケジュールされたクエリ』(以降、スケジュールクエリ)という機能を使うと、プログラムを書かなくてもクエリを定期的に実行し、テーブルを更新することができます。

そのスケジュールクエリに設定したクエリ内で使える専用のパラメータに @run_date というDATE型のパラメータがあり、`where dt = date_add(@run_date,interval -1 day)` のような形で多用していました。

しかし、@run_date はUTC(世界標準時)の日付がデフォルトであり、日本時間で9:00AMより前にスケジュールを設定すると、@run_dateが前日になってしまうという問題がありました。

この@run_dateを日本の日付に直さなければならない場面に直面し、なんとなく答えが出たので書いておきます。

@run_dateというパラメータに関するGoogleの公式ドキュメントはこちら。

https://cloud.google.com/bigquery/docs/scheduling-queries?hl=ja#query_string

## @run_dateをJSTに変換するのは不可能


@run_dateというパラメータは[DATE型](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types?hl=ja#date_type)なのですが、そもそもDATE型(日付型)のデータ型にタイムゾーンの概念はありません。なので、UTCの日付が入っていても、それをJSTに変換することは不可能なのです。

であれば、タイムゾーンを持つTIMESTAMP型のパラメータを用いて、それをDATE関数でJSTに変換しながらDATE型にすると@run_dateをJSTに直すのと同じことになります。

そして、BigQueryにはスケジュールクエリで使える @run_timeというTIMESTAMP型のパラメータが存在します。

なので、
```sql
DATE(@run_time,'Asia/Tokyo')
```

とすれば良さそうです。
配列の中のオブジェクト中の配列を重複がないように、二次元配列から一次元配列として取得する

## やりたいこと
このtagsを
```
const customers = [
  {
    lastName: '2f8',
    tags: ['VIP', 'male'],
  },
  {
    email: 'a@gmail.com',
    tags: ['VIP', 'male'],
  },
  {
    email: 'c@gmail.com',
    tags: ['VIP', 'female'],
  },
];
```
↓
重複のないような一次元配列にしたい

```
['VIP', 'male','female']
```

## 解決方法
```
const customers = [
  {
    lastName: '2f8',
    tags: ['VIP', 'male'],
  },
  {
    email: 'a@gmail.com',
    tags: ['VIP', 'male'],
  },
  {
    email: 'c@gmail.com',
    tags: ['VIP', 'female'],
  },
];

const array = customers.map((el) => el.tags.map((el) => el));
const flatArray = [].concat(...array);
const noDoubleArray = Array.from(new Set(flatArray));
```

https://stackblitz.com/edit/typescript-pusapr?file=index.ts
タスク管理ツールをReact + ASP.Coreで作る 04一覧リストに表示するデータとDB構造の検討

[前回](https://qiita.com/mosuma/items/b6140751f5148efc9e42)の続きです

### ガイド
全体Index：[タスク管理ツールをReact + ASP.Coreで作る - Index](https://qiita.com/mosuma/items/88e40dc44e7bff1a54d8)

## 次に作っていく流れの検討

前回までで、テンプレートに含まれているwebapiのデータをクライアントサイドに表示することができるようになりました。

クライアントからサーバーに問い合わせてデータを取得し、表示するという基本的なフローが出来たので、サーバーサイドでタスクの一覧情報を返すAPIを作ることが出来ればクライアントで一覧表を表示することが出来そうです。

ですので、次のステップとしてはタスクの一覧表を表示する機能を作っていくことにしたいと思います。

## 画面とテーブルの検討
元々作っていた画面イメージはこんな感じです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2664470/29b3faff-c9cf-608b-d464-c5ec9a7a981a.png)

最終的にやりたいことに対して、今書いている絵もかなり限定的な内容ではあるのですが、それでもこれを一気に作るのは結構大変そうなので、まずは一覧画面を作っていこうというのが意図です。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2664470/c5d0b18a-18b9-a0d8-cf7f-43c4c214f2f1.png)

はい、まずはこの画面を目指しましょう。
最初は意図したデータが表示されればスタイル・レイアウトなども問わないものとします。


## テーブル設計

テーブル設計は表示する情報を元に↓のように検討しました。(()内は型です)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2664470/74d8f2c2-2d94-fb92-2ea3-b4d79c582efe.png)

Noは、DBの値ではなく、表示するときの行番号なのでDB側では持ちません。
各カラムの名称は、UIでの表示名をそのまま使うと微妙に何のことかわからなくなりそうなものもあるので、意味が分かりやすいように変えてあります。

今回はここまでです。
[次回](https://qiita.com/mosuma/items/246624b5075d92ac528d)から、実際にテーブルを構築していきます
VueでlocalStorageを監視して特定のキーの結果に応じて動作できる様にする

# はじめに
前回、`vuex-persistedstate`を利用して画面リロードでもログイン状態を保持できる様になったおかげで、ログイン状態の場合には画面を表示し、未ログイン状態の場合にはログイン画面へリダイレクト処理させることができました。

https://qiita.com/fakefurcoronet/items/aeef6b354cadce4494f2

しかしここで新たな課題が発生します。

なんと別タブで画面表示した場合に、一方のタブでログアウトされたらもう一方のタブでもログイン画面へリダイレクトさせたいと言うのです。
調べてもなかなか別タブで変更されたstateやlocalStorageの値をwatchする方法が見つかりません。

さて、どうしよう…

# StorageEventを使用する
Web Storage APIには、Storageオブジェクトが変更されるたびに発生するStorageEventが存在します。

https://developer.mozilla.org/ja/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API#storageevent_%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%A6%E3%82%B9%E3%83%88%E3%83%AC%E3%83%BC%E3%82%B8%E3%81%AE%E5%A4%89%E6%9B%B4%E3%81%AB%E5%8F%8D%E5%BF%9C%E3%81%99%E3%82%8B

このStorageEventを検知するためにイベントリスナを定義するサンプルコードがありました。

```event.js
window.addEventListener('storage', function(e) {
  document.querySelector('.my-key').textContent = e.key;
  document.querySelector('.my-old').textContent = e.oldValue;
  document.querySelector('.my-new').textContent = e.newValue;
  document.querySelector('.my-url').textContent = e.url;
  document.querySelector('.my-storage').textContent = JSON.stringify(e.storageArea);
});
```

なるほど。`addEventListener`を利用するのですね。
ということで、localStorageに保存したキー「auth_info」の有無によってログイン状態を判別するhookを用意しました。

```hooks/login/useLoggedIn.ts
import { ref, useStore } from '@nuxtjs/composition-api'

export const useLoggedIn = () => {
  const store = useStore()
  const isLoggedIn = ref<boolean>(store.getters['auth/isLoggedIn'])

  // ローカルストレージのログイン状態を監視
  window.addEventListener('storage', (event) => {
    if (event.key === 'auth_info') {
      if (event.newValue) {
        isLoggedIn.value = true
      } else {
        isLoggedIn.value = false
      }
    }
  })

  return { isLoggedIn }
}
```

そして`localStorage.removeItem('auth_info')`でキー自体を削除するコードをログアウト時の処理に組み込みました。
すると、上記のhookをページ内でwatchすることで、`false`が返ってきた場合には未ログイン状態としてログイン画面へリダイレクトすることができました。

```pages/main.vue
import { useLoggedIn } from '~/hooks/login/useLoggedIn'

export default defineComponent({
  components: {},
  layout: 'global',
  middleware: ['guard/auth'],
  setup() {
    const router = useRouter()

    const { isLoggedIn } = useLoggedIn()

    watch(isLoggedIn, (val) => {
      if (!val) {
        // ログアウトした場合はログイン画面へ遷移
        router.push('/login')
      }
    })

    return {}
  },
})
```

# おわりに
薄々面倒だろうと気づいてはいましたが、やはり別タブの扱いは面倒でした。
ラズベリーパイにSyncthingをインストール


## インストール
```bash
sudo apt install syncthing
```

## サービス化
```bash
sudo systemctl enable syncthing@${USER}.service
sudo systemctl start syncthing@${USER}.service
```

## WEB UIにアクセス

sshポートファーディングでリモートの8384ポートをホストの9999ポートにポートフォワーディングしブラウザから[http://localhost:9999](http://localhost:9999)にアクセスる


```ssh
ssh -L 9999:localhost:8384 pi@192.168.0.xxx
# pi@192.168.0.xxx`はラズパイの環境に置き換える
```
SEOについてまとめ

# はじめに
仕事でSEOについて接する機会があり、メモがてら、理解したことを残します。

# 最終更新日
2022年10月24日

# 注意
最新の状態を確認して下さい。


# インデックスについて

### Q インデックス登録は、何が起きてるの？
A （最終的には）データベースに登録されている。
この時点では、特に検索順位は関係無い。

### Q 何故、インデックスを登録している？
A 該当のサイトを素早く見つけるため。
ページごとに、いちいちアクセスしていたら、Googleがパンクするため。

### Q インデックスされているかは、どうすれば分かる？
A site:xxx とやれば分かる。検索結果が表示されたら、インデックスに登録されている。
サーチコンソールでも確認出来る。
ちなみに、site:には色々種類がある。
https://digitalidentity.co.jp/blog/seo/algorithm/google-site-operator.html

### Q インデックス登録されても、検索順位に出ないけど、何故？
A インデックスされる＝順位にでるでは無い。
様々な要因で出ない理由になりうる。

### Q インデックス登録はいつされる？
A 分からない。
必ずしもインデックス登録されるとは限らない。Google側も、ハッキリ明示していない。


### Q PVの変動とインデックスは関係あるの？
A サイトによる。あったり、無かったり。
サーチコンソールで傾向を追うと良い。


# ペナルティについて

### Q Googleのペナルティーって何？
A サイトが、Googleのガイドラインに違反している場合に来る警告のこと。

### Q 手動ペナルティーって何？
A Googleのスタッフが、手動でホームページの調査を行ってペナルティー判定する。

### Q 自動ペナルティーって何？
A Googleの検索アルゴリズムがサイトを巡回した際にガイドラインに反したページに対して自動で与える。



# コアアップデートについて

### Q Googleのコアアップデートって何？
A 検索結果をより良くするために、Googleが検索アルゴリズムの見直しを行う。
SEOの順位に関係してくる。

### Q Googleのコアアップデートは何回するの？
A 年に2～4回行われる。

### Q Googleのコアアップデートはいつやる？
A 分からない。
twitterで予告してくる。
https://twitter.com/searchliaison
https://twitter.com/googlesearchc


# サイト評価について

### Q サイトはどうすれば良いサイトと評価される？評価を知りたい。
A 参考までに。
https://www.willgate.co.jp/promonista/google-algorithm/


### Q 検索順位が下がった。何故？
A　様々な要因があるので、一概に言えない。
考えられることの一部として、コアアップデート、Googleの不具合、インデックスが外れた、競合に負けた、etc

### Q 人の文章をパクって、コピーすると何で良くないの？
A 重複コンテンツとみなされる恐れがある。
ペナルティの判定の要因の1つでもある。

### Q 明らかに、うちのサイトが他のサイトに内容がパクられている、どうすれば良い？
A Googleに訴えられる。
https://support.google.com/legal/answer/1120734?hl=ja


### Q 自分のサイトが、重複しているか知りたい。
A Googleの検索結果URLの1番後ろに「&filter=0」を追加して再検索すると、確認できる。

### Q 競合が知りたい。
A ツールを使うと良いでしょう。


何か思い出しましたら、続きを記載します(　･ิω･ิ)
rel="noopener"

# rel="noopener"とは？
一種のセキュリティ対策で、`target="_blank"`で開いたページに仕込んである悪意のあるコードから元のページを守ることができる。  
`rel="noopener"`を使用しなければ、遷移先に`window.opener.location = "hogehoge.com"`とあれば、遷移してきた元のページが`hogehoge.com`に置き換わってしまう可能性があり、フィッシング詐欺に遭う可能性が出てくる。
```
<a href="https://google.com" target="_blank" rel="noopener">Google</a>
```


## 参照
- [リンクのへの rel=noopener 付与による Tabnabbing 対策](https://blog.jxck.io/entries/2016-06-12/noopener.html)
- [HTML 本当は怖い target="_blank" 。rel="noopener" ってなに？](https://chaika.hatenablog.com/entry/2018/12/06/110000)
[Edge] Microsoft Learnの英語と日本語を切り替えるアドオン

# はじめに

便利なのでシェアします😁🎉

# en-us と ja-jp の切り替え

Microsoft Learn （旧Docs）は、英語ページと日本語ページではURLの途中に挟まっている「en-us」と「ja-jp」が違うだけです。例えば下記のように。

> https://learn.microsoft.com/ja-jp/certifications/exams/pl-300

https://learn.microsoft.com/ja-jp/certifications/exams/pl-300

> https://learn.microsoft.com/en-us/certifications/exams/pl-300

https://learn.microsoft.com/en-us/certifications/exams/pl-300

# 英語ページと日本語ページを切り替える必要性

- 機械翻訳が変で、原文を読みたい
- リンクが英語ページにはってあり、日本語ページを読みたい
- 英語ページのほうが情報が早い

などなど

# 英語ページと日本語ページを切り替えるEdgeアドオン

URLを毎回ポチポチと切り替えても大丈夫なのですが、Microsoft Edgeには便利なアドオンがあります。

### 英語ページ（en-us）と日本語ページ（ja-jp）を切り替える

https://microsoftedge.microsoft.com/addons/detail/enus-%E3%83%9A%E3%83%BC%E3%82%B8%E3%81%8B%E3%82%89-jajp-%E3%83%9A%E3%83%BC%E3%82%B8%E3%81%AB%E7%B4%A0%E6%97%A9%E3%81%8F/akjjgiefpfhfdncdnngfdhoaibhjpkgo

これを入れればワンクリックで切り替えができる💪😁

以上、便利なので使ってみてください～

# 対応言語

めちゃくちゃあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/02b26dac-fc3c-a3ea-3b1d-eaa2ed8dbe86.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/f18798f2-72d3-87fc-02d0-370d5a929649.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80467/0d0cc69f-a6d9-96f9-dd39-1eabe3b7365b.png)

# 補足

この拡張機能はURL内の「en-us」や「ja-jp」などを切り替えるように構成されているようなので、別にMicrosoft Learn専用のアドオンではありません。他にもURL内の「en-us」などで言語を切り替えられるようになっているページであれば切り替えが可能なようでした。

# まとめ

EdgeのアドオンはChromeでも使えるんでしたっけ？🤔
Pythonで透過pngの背景色を指定しつつjpgにする

https://stackoverflow.com/questions/9166400/convert-rgba-png-to-rgb-with-pil

# やりたいこと
- どこかのフォルダにあるpngを全部処理
- 同じフォルダに出力
- 背景色を自分で指定

# コード
- モジュールが無いって言われたら `pip install pillow`

```python:png2jpg.py
from PIL import Image
import glob
import re
import os

png_list = glob.glob('<pngがあるディレクトリ>/*.png')

for pngfile in png_list:
  png = Image.open(pngfile)
  png.load() # required for png.split()
  jpgfile = pngfile.replace(".png", ".jpg")

  background = Image.new("RGB", png.size, (255, 255, 255)) # 背景色
  background.paste(png, mask=png.split()[3]) # 3 is the alpha channel

  background.save(jpgfile, 'JPEG', quality=80) # jpgの品質はよしなに
```

- 実行
```shell
python png2jpg.py
```
Local環境（Docker）をngrokを利用して外部公開する

SlackAPIをLocalで利用しようと思ったけど、httpsのURLしか対応していない...
そこでngrokを利用してlocalhost:8080を外部公開することにしました。

DockerでLocal開発環境を構築し、バックエンドにFastAPIを使用しています
# docker-compose.yml
以下のようにdocker-compose.ymlに記述することで外部公開することができました。
```
  ngrok:
    image: wernight/ngrok:latest
    ports:
      - 4040:4040
    environment:
      NGROK_PROTOCOL: http
      NGROK_PORT: server:8080 # Serverがバックエンドのサービス名（Port8080）
```

FastAPIはASGIフレームワークなので、Nnginxのコンテナを立てなくても実行できました。
（ASGIがまだよくわかっていないです）

# アクセスしてみる
localhost:4040にアクセスすると以下のような画面が表示されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545959/f4dc1a4f-ce8e-f9a2-87b8-657a84796806.png)
httpsの方をクリックすると、localhost:8080で表示されていた画面にアクセスすることができました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545959/00025ec2-8167-c4db-7316-8d8a42ae371d.png)
コンテナを再起動すれば、外部公開されるURLも変わります。

思った以上に簡単に外部公開できました。
これでSlackAPIが利用できそうです。

ngrokのコンテナ起動中だと外部公開されているのも嫌なので、SlackAPI使用しない間はコンテナを停止して運用したいと思います。（厳密には無料アカウントだと起動時間に制限があるようですが...）

# 参考記事

https://speakerdeck.com/gishi_yama/mild-web-sap06?slide=11

https://qiita.com/ntm718/items/9c374406f5b9457e7878
SSM Patch Managerの自動化ハンズオンしてみた

# 初めに
https://www.zead.co.jp/column/ssm_patch/

上記記事にPatch Managerを自動的に行う方法があったので、実際に作ってみた。

# ハンズオン
## メンテナンスウィンドウ
まず初めにメンテナンスウィンドウで実施する時間をスケジュール設定する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/7b95130c-f7f3-8b62-51de-0f8ed0eb34d1.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/30a76d22-ea74-2af9-9094-c38a671d5903.png)

## パッチベースライン
バッチベースラインでパッチ対象の定義を行う。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/3159e5e0-d63f-cd77-fa90-7db81611aca5.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/3667e3b6-5c32-463a-8075-d8245829b47a.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/aa5fa9ba-4304-4e42-3b27-b892bbeb1207.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/3793e702-fad7-dccf-d335-18cd6703e5b6.png)
ベースラインができていることを確認する。
![Screenshot at Oct 24 21-43-41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/1f9a495e-51f2-7f13-b554-2f6b8e8b4015.png)
パッチグループの設定もしておく。
![Screenshot at Oct 24 21-51-38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/f8b5e5f0-d246-42e8-816f-c28375d6743c.png)

## パッチ適用設定
パッチの適用対象設定を行う。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/a5be1367-4139-165e-4f02-eb50d3491632.png)
![Screenshot at Oct 24 22-00-48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/1221501f-5f28-03c4-2845-162ba743eb62.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/e9087198-d192-5477-b3cf-ecb3f8241d2d.png)
JetpackComposeのmaterial3でswipeableなどのinternalな一部の関数の代替を使う方法

本記事はJetpackComposeにイラついた中級プログラマーが思いをそのままにつづったものです。

# 具体的には

※知っている部分は飛ばしてください
※安定すれば意味ない記事です 2022/10/24

`Android`を`kotlin`でデザインする際に`xml`ではなく`宣言型UI`である`JetpackCompose`を用いてUIを描けるJetpackComposeを`Material3`で入れたのだが、開発段階ということもあって、表で使える関数がかなりありません。（Material3の物は使えるのだが、内部で使われているクラスやインターフェースや関数がマジでinternal）

# イラついたところ
※特に意味はない無駄情報

[Material3の公式っぽいところ](https://m3.material.io/develop/android/jetpack-compose)がAndroidを紹介していますが、[Component一覧](https://m3.material.io/components)から適当なコンポーネントを選んで[Androidの公式リファレンス](https://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#button)に跳ぶのですが、なんと見本のコードの中で出されている関数がMaterial3だと存在しなかったり、そもそもMaterial3だとinternalだったりする。

## みんなの心の叫びがこれ

https://issuetracker.google.com/issues/229839039?pli=1

**PLEASE STOP MAKING ALL USEFUL APIS INTERNAL**

**PLEASE STOP MAKING ALL USEFUL APIS INTERNAL**

**PLEASE STOP MAKING ALL USEFUL APIS INTERNAL**

## 公式の解答はこれ（超意訳）

**これがイライラする経験であることは知っています。しかしMaterial3はまだまだ開発途上であり、現在多くの重大なバグがあるので、Material3の公開範囲を当面制限してます。**

**まだまだアルファ版です。現在APIの形状は柔軟なままであり、開発者のフィードバックを取り入れることが可能です。コピペして自力で改造してください。**

# 意味のある情報（対処法）

https://android-developers.googleblog.com/2022/07/jetpack-compose-1-2-is-now-stable.html

ということで、おもむろにMaterial3の前のバージョンをimplementに突っ込みます。

```: build.gradle(:app)
    implementation 'androidx.compose.material:material:1.2.1'
```

そして、`Project Structure`の`Dependencies`から`app`を片っ端から最新の安定版にします。（ただの趣味）
※なおmaterial3は安定版なんてまだない模様(1.0.0-rc01が最新なので最新を入れた ※LCならリコリスだったのに)

https://developer.android.com/jetpack/compose/designsystems/material2-material3#approaches

**一般に、M2 と M3 の両方を 1 つのアプリで長期間使用しないでください。** と書いてありますが、Material3が安定したら止めるのでヨシ！

これで`Modifier.swipable()`などが使えるようになります。やったね！

※`OptIn(ExperimentalMaterialApi::class)`とか`@OptIn(ExperimentalLayoutApi::class)`とか、`@ExperimentalMaterial3Api`などを忘れないように。あと`@Preview`と`@Composable`も

※同関数名がかぶったりする影響でエラーが出るかもしれませんが、`Alt+Enter`でもするか、名前空間でもつけて区別させてあげてください。
Reactチュートリアルをやった感想

仕事でReactを触ることになりそうだったので、[チュートリアル](https://ja.reactjs.org/tutorial/tutorial.html#before-we-start-the-tutorial)をやってみた
結果、感じたこと、気づいたことをメモする

# 環境
OS：Mac（M1）
エディタ：VS Code

# 最終的なアウトプット
- https://github.com/Kaito-Ozaki/react-tutorial

# やる前の状態
### 知識
- HTML,CSSはちょっと触ったことある、JavaScriptは業務で1年ほど使用しているという状態
- Reactについては、ほぼ知らない。hooksという機能があること、Vue.jsと比較されがちなことを知っているくらい
### 気持ち
- 普段、バックエンド開発しかしていないので、フロントのフレームワーク触るのちょっとドキドキする
- とりあえず公式が丁寧にステップを刻んでくれているので、丁寧にコミットしていくことを心がけたい（普段の業務でもやりたいこと、、）

# やった後の状態
### 知識
- コンポーネント単位での開発ってこんな感じなのか、というのがぼやっとイメージついた
- コンポーネント間での状態受け渡しの流れについて、ぼやっとイメージがついた
### 気持ち
- 2,3時間程度でサクッとできるのはいいな、と思った
- 「とりあえずReactを触れたぞ！」という気持ちになったw
  - フロントわからない、、怖い、、という気持ちは薄れた
- 疑問がいくつか出てきた
  - hooksはどこでどう使うんだ？
  - CSSはどう書くといいんだろう？　ピュアなCSSを書く感じなのか？
- このチュートリアルをやったら、Reactの機能を一通り知れる訳ではなさそう

# その他やってる最中に思ったこと
- 環境構築ほぼいらない。楽だ
  - 自分の環境だと一度も詰まらなかった
  - 最悪、ブラウザでも実行できるので簡単にチャレンジできる
- HTML, CSSの知識はほぼいらない。触りを知っているだけでもやれる
- コードの書き方についてのフォローが地味にいい
  - イミュータブルにすることの大切さを丁寧に伝えてくれていたり
  - ちゃんと三項演算子使って書くようにしていたり
- [React Developer Tools](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=ja) 便利そう。コンポーネントの構造が見れる
 　![devtools.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646249/1a9a417b-edf3-55f7-2da8-9c7488e1e55b.png)

# まとめ
サクッと「Reactってのにとりあえず触ってみたいぜ！」「フロント怖いからちょっと慣れたい、、」みたいな期待値で触るのにちょうど良いものだと思った

一方で、実際に開発するというところとのギャップは色々ありそうなので、チュートリアルをやっただけで「React触られるぜ！」みたいな感じになるかというとそうではなさそう

とりあえず自分はもうちょっと理解を深めるために以下あたりやっていこうと思った
- [公式ドキュメント](https://ja.reactjs.org/docs/getting-started.html)
  - なんだかんだ公式読むのが良さそうなので、読んでみる
- [Next.jsチュートリアル](https://nextjs.org/learn/foundations/about-nextjs)
  - [React を学びたいなら Next.js チュートリアルがおすすめ。](https://www.ritolab.com/entry/241)という記事もあるし良さそう
- [TypeScriptとReact/Next.jsでつくる 実践Webアプリケーション開発](https://gihyo.jp/book/2022/978-4-297-12916-3)
  - しっかり学ぶならやっぱり本を読んで手を動かして、だと思うのでやる
タイトルの本文

# QiitaのAPIを叩いてみた
今回はqiitaのapiをたたいてみて記事と投稿者のユーザー情報を取得してみたました！
### 背景
今回なぜQiita APIを使ってみようと思ったかざっくりまとめると
- 会社でqiitaを用いてテックブログを始めた
- 入社して３ヶ月新米エンジニアの勉強
- 興味本位！！！笑
## 使用した技術
- Next.js
- TypeScript
- useSWR
- tailwindCSS
- Mantine
になります！フロントの技術モリモリです！では早速APIを叩きます！
なお、今回は使用技術の前提知識や環境構築は省きます。

`````
const js = () =>{
}
`````
Gitでコミットメッセージを修正する

一度コミットしたコミットメッセージの修正方法


# 直前にコミットしたコミットメッセージを修正する
`git commit --amend`で修正を行う
```
$ git add ~~~
$ git commit -m "test"
$ git log --graph --oneline
* ec2dbbb (HEAD -> main) test


$ git commit --amend -m "testtest"
$ git log --graph --oneline
* ec2dbbb (HEAD -> main) testtest
```


# 何個か前にコミットしたコミットメッセージを修正する
ログの確認
```
$ git log --graph --oneline
* 1d2459b (HEAD -> main) hogehoge
* 5126d20 hoge
* 103c35b testtest
```
`git rebase -i`で修正を行う。  
`HEAD~`の後には最新のコミットを1として何個前か指定をする  
※今回は3個前の"testtest"を変更するため、`HEAD~3`を指定。
```
$ git rebase -i HEAD~3
```
viエディタの起動  
insertモードで、変更したいコミットの`pick`を`edit`に変更
```
edit 103c35b testtest
pick 5126d20 hoge
pick 1d2459b hogehoge
```
viエディタを修了し、`git commit --amend`でコミットメッセージの修正  
修正後は`git rebase --continue`で完了
```
$ git commit --amend -m "test"
$ git rebase --continue

$ git log --graph --online
* af798ad (HEAD -> main) hogehoge
* bdb8a2f hoge
* d9df22d test
```


## 参照
[Gitのコミットメッセージを後から変更する方法をわかりやすく書いてみた](https://www.granfairs.com/blog/staff/git-commit-fix)
ROSのロボコンへの導入

# 前提

これはロボコンでROSの導入を考えている人の背中を押せるような記事にしたいと思っています。  
それとROSを導入して一年(より短い)で感じたこと、利点、懸念点をまとめたものです

あと技術的なことは書かないので別で探してください
私がよく参考にしている記事

https://qiita.com/srs/items/5f44440afea0eb616b4a

ここまで読んでも大丈夫という人はぜひ最後までお付き合いください

# ほんへ

## 動機

まず、ここが大事だと思います。

ROSを入れて何ができるか、どういう風に開発が変化するかがモチベにも関わってきますしね。
一応、無印のROSを導入しました

### 利点

**とにかく簡単！！！！！**

ですかね。

wifiでの接続はIPアドレスを設定するだけですし、
マルチスレッドでコードを走らせるので複数のことを一つのPCで簡単にできますし、
ノード(実行されているプログラム)間のデータのやり取りも簡潔に記述できます

UARTのように送信するデータサイズなんか気にしないで送ることができるので高級で幸せなプログラミングができます

### 懸念点
開発が止まった技術なので今後廃れていきます。なので無印のROSは今後使うかどうかは慎重に判断するべきですね。学ぶならROS2をおすすめします
今回は枯れている技術なので勉強のしやすい無印ROSを導入したのでROS2の導入を考えているところは、一応参考にしてみてください

### 使用例
ノード、メインのデータ処理のノード、通信関係を管理するノード、ゆかりさんをしゃべらせるノードしか書かなかったので簡単なことしかしていません(lidarのノードもあったのですが、lidarが重量の都合で消えたのでお察しください)

## 導入までの流れ

まず前提ですがROS自体が結構簡単だったのが大きいですね。

- メインプログラマが一人！
- 特に上から継承できた技術もない！
- c++わからん！

こんな状態のプログラム班でも導入できるくらいには簡単でした。

### 必要な技術

- 本当に必須な技能
  - C++
  - cmake

- 必須ではないがあったほうがいい知識
  - python
  - シェルやlinuxの知識

- ROSでよく見る技術
  - 画像認識
  - lidar, slam, その他
  - IMU
  - その他

>必須な技能に関しては精通しているほどでなくても大丈夫で、最低限使えるできる程度に覚えておければ十分です

### やってみる

上に書いた必須技能さえ満たせていれば問題なく個々のシーケンスは超えられると思います

1. インストールしてみる

https://qiita.com/srs/items/e0e0a9dc3f94c2d3348e

基本的にはここに書いてある通りにやれば大丈夫だと思います
インストールで躓いたときにシェル周りの知識が乏しいと少し対応に手間取りますが、本当に書いてあるコマンド通りにすればインストールできるので書いてある通りにやりましょう(n敗)

2\. 使ってみる

https://qiita.com/srs/items/26ca826802d07a9e3d4e

ここから始めましょう
基本的にコピペしてからいろいろ変えてみてホエーってやるのがいいと思います(諸説あり)

3\. 勉強を進める

上に書いてある[記事](https://qiita.com/srs/items/5f44440afea0eb616b4a)や、実際にlidarを購入してみて使ってみるのがいいと思います

pythonの書き方や様々なライブラリの使い方などは少なくとも無印のROSではいろんな記事があふれているので探しやすいと思います

4\. 使う

実際に使ってなんぼなので頑張ってください
シリアル通信であればrosserialというものがあり、そのままUARTで使えるとかなんとか……

うちは今年CAN通信だったので適当にpythonでパッケージ引っ張ってきてそのまま使った感じですかね

あとは部として定着させるなり、個人で技術を伸ばすなり頑張ってください

## まとめ

**とりあえず使ってみればいいと思う。簡単だから。** という感じですかね

本当に記事が出そろっていますし、技術的な情報だったらいくらでもまとめたものが出てくる印象なので新しい開拓も非常に楽でうれしいですね。

英語の資料が多くて調べにくい時もあるのですが、探してみれば意外と日本語もあるし調べ方が悪かっただけみたいなことも多いので根気よくやりましょう。

何か不備や知りたいことがあればコメントやtwitterのDMでお願いします

[twitter](https://twitter.com/karupicat)
４０代おっさんPythonを勉強する（JSOＮファイルの読み書き編）

## 本記事について

この記事はプログラミング初学者の私が学んでいく中でわからない単語や概要を分かりやすくまとめたものです。
もし不正などありましたらコメントにてお知らせいただければ幸いです。

## JSON

- 軽量のデータ交換フォーマット
- 多くのプログラミング言語で使われている。データ交換に便利
- [JSONの紹介](https://www.json.org/json-ja.html)

| JSON         | Python       | 表現方法 | 例 |
| ------------ | ------------ | --- | --- |
| object       | dict         | {"key":value, "key": value ...}のように記述 | {"apple":150, "orange":120} |
| array        | list / tuple | [1, 2, 3 ...]のように記述 | ["apple", 100] |
| string       | str          | ダブルクォートで括る | "apple" |
| number       | int / float  | 数字 | 25 |
| true / false | True / False | trueかfalse | true |
| null         | None         | null | null |

```python
# 辞書型の階層的なデータ
company = \
{
"department": { 
        "Information Technology": {
            "floor": "3rd",
            "person": {
                "Sato Taro": "Manager",
                "Suzuki Hanako": "Software Engineer"
            }
        },
        "Human Resources": {
            "floor": "2nd",
            "person": {
                "Takahashi Akiko": "Manager",
                "Tanaka Kentaro": "Administrator"
            }
        },
        "Sales": {
            "floor": "1st",
            "person": {
                "Ito Jiro": "Manager",
                "Kimura Takuya": "Sales person"   
            }
        }
    }
}

import json
company_json = json.dumps(company)
company_json # jsonフォーマットの文字列になる
```

- ファイルに保存する

```python
with open('company.json', "w") as f: # ファイルcompany.jsonに保存
    json.dump(company, f)
```

- ファイルから読み込む

```python
with open('company.json', 'r') as f: # ファイルcompany.jsonから読み込む
    company = json.load(f)
print(company)
type(company) # 辞書型になっているか確認 
```

- 読み込んだ後は普通にPythonのデータ型で処理できる

```python
#  階層的に表示する
for c in company:
    print(c)
    for d in company[c]:
        print('\t|-->', d)
        for i in company[c][d]:
            if i == 'floor':
                print('\t\t|-->', i, company[c][d][i])
            else:
                print('\t\t|-->', i)
                for j in company[c][d][i]:
                    print('\t\t\t|-->', j, company[c][d][i][j])
```

## 参考

https://www.kitakyu-u.ac.jp/news/2022/08/003215.html
バックアップ手法メモ

フルバックアップ
    すべてのデータを完全に複製

差分バックアップ
    フルバックアップからの変更や追加されたデータを複製

増分バックアップ
    前回からの差分のみバックアップ

トランザクションバックアップ
    初回フルバックアップ以降の操作を記録している
文字の情報交換でprogramming

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">pc-van,nifty,mix,地元でのパソコン通信運営してた　

<a href="https://twitter.com/hashtag/%E7%9F%AD%E6%AD%8C?src=hash&amp;ref_src=twsrc%5Etfw">#短歌</a></p>&mdash; naokiakutagawa (@naokiakutagawa) <a href="https://twitter.com/naokiakutagawa/status/1584002205652488195?ref_src=twsrc%5Etfw">October 23, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

チャットだけの情報交換でプログラムを40年ほど前から書いていた。　
https://twitter.com/naokiakutagawa/status/1584647676565811200?s=46&t=1fiLkLL4MHcqYv7oiqYA3w

会わないとプログラム書けないという人の気持ちがわからない。　

プログラマ:顔を見合わせて会議、テレビ会議、コメント・チャット。 仮説（194）
https://qiita.com/kaizen_nagoya/items/2f9d2969e8b30e12f0c1
### 最後までおよみいただきありがとうございました。
いいね　💚、フォローをお願いします。
####  Thank you very much for reading to the last sentence.
Please press the like icon 💚　and follow me for your happy life.
[Xcode]Coverage.profdataの中身を見る

## はじめに
今回、Coverage.profdataの中身を見る方法について調べたので、備忘録として記事を書きます。
実際には、中身を見るというよりllvm-covコマンドを使って、ターミナルでパーセンテージを表示する方法です。
## llvm-covを使ってカバレッジを表示
llvm-covのreportコマンドを使うことで、Coverage.profdataのカバレッジを見ることができます。
ターミナルで以下のコマンドを実行します。
```
$ xcrun llvm-cov report -instr-profile {Coverage.profdata} { 〇〇.app/〇〇　}
```
上記のコマンドを使うことで、カバレッジをターミナルに表示することができます。

## 実際のプロジェクトでコマンド実行
![スクリーンショット 2022-10-24 21.47.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1379778/c71699be-74f4-2886-aa0c-59ecd5f012c4.png)

## 参考記事
- https://yanamura.hatenablog.com/entry/2015/12/13/002035
- https://zenn.dev/masasam_shi/articles/swift-code-cov-in-cli

## おわり
おわり
ABC168 D - .. (Double Dots) が解けて、叫ぶ

# [問題](https://atcoder.jp/contests/abc168/tasks/abc168_d)
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/6e35180c-a2cc-3ecc-0d57-6ce67947b949.png)
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/1686de35-136f-a7e8-234f-f3ebfed84de2.png)

# 思考のプロセス
**・絵をかいて理解に努める**
&emsp;**入力例1**
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/3e77e893-5774-e9e3-43d4-5671d578f947.png)
&emsp;**入力例2**
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/75ec65a5-96e0-b8a7-af4e-2ce2bafddbcc.png)
&emsp;とりあえず、絵を眺めて考えた。
&emsp;ステップとして以下のように分けて考えた方が良いと思いました。

**・Yes or No を判定する事だけ考える**
&emsp;何気なく書いた上図の赤丸の図に注目しました。
&emsp;**部屋1 から START し、全ての部屋に BFS で探索できた場合、
&emsp;メモした工程数は <font color="red">各部屋から 部屋1 への最短距離と言えませんか？</font>**
&emsp;入力例2であれば、部屋 3 <=> 部屋 4 、部屋 4 <=> 部屋 2 が繋がっているので
&emsp;BFS が上手くいきません(勿論 部屋 5 <=> 部屋 6 も しかりです。)。 
&emsp;そこはコードに工夫が必要です。

**・Yes の場合、道しるべを如何に用意するか考える**
&emsp;求められるアクションは以下だと思いました。

&emsp;&emsp;部屋 1 => 部屋 5 に移動した場合、部屋 1　から来たことになります。
&emsp;&emsp;よって部屋 5 には道しるべ **1** を配置

&emsp;&emsp;部屋 1 => 部屋 6 に移動した場合、部屋 1　から来たことになります。
&emsp;&emsp;よって部屋 6 には道しるべ **1** を配置

&emsp;&emsp;部屋 5 => 部屋 3 に移動した場合、部屋 5　から来たことになります。
&emsp;&emsp;よって部屋 3 には道しるべ **5** を配置

&emsp;&emsp;部屋 5 => 部屋 4 に移動した場合、部屋 5　から来たことになります。
&emsp;&emsp;よって部屋 4 には道しるべ **5** を配置
&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;・
&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;・
&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;・
&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;・
&emsp;これは BFS で移動する度にメモしていけばクリアできる気がしました。

# コードに落とす
&emsp;以下で AC でした。
&emsp;https://atcoder.jp/contests/abc168/submissions/35937244
&emsp;今回は BFS の本質(特徴)を捉えて応用できるかを問われている気がしました。

&emsp;楽しかった! 出会いに感謝 m(_ _)m
【numpy】2つのベクトルの任意のベクトルからの回転角を算出する方法

# 概要
下図左側のように2つのベクトルの間の角度を算出する方法は内積などを取れば良く、よく知られている。本記事では、2つのベクトルの角度に加え、下図右側のように**任意のベクトルを基準とした2つのベクトルの回転角を算出するコード**を[get rotation angle between two vectors](https://chadrick-kwag.net/get-rotation-angle-between-two-vectors/)の記事を参考にして紹介する。
Google Colabで作成したコードは、[こちら](https://colab.research.google.com/drive/17iVlTG_4vXiYU_65qvxr3YmTbhWrr02l?usp=sharing)にあります。

![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1599258/b9249e21-544d-dbb3-882b-d9808abb28d2.png)


# 各種インポート
```Python:各種インポート
import numpy as np
import matplotlib.pyplot as plt
```

# 2つのベクトルの角度
```Python:
def vector_to_vector_angle(vector_1, vector_2):
    unit_vector_1 = vector_1 / np.linalg.norm(vector_1)
    unit_vector_2 = vector_2 / np.linalg.norm(vector_2)
    cos = np.dot(unit_vector_1, unit_vector_2)
    rad_angle = np.arccos(cos)
    angle = rad_angle / np.pi * 180
    return angle
```
* ``vector_* / np.linalg.norm(vector_*)``で単位ベクトルに変換します。
* 単位ベクトルに対して``np.dot(unit_vector_1, unit_vector_2)``で内積を取り、2つの角度の$\cos(\theta)$を求めます。
* ``np.arccos(cos)``で、$\theta$を求めます。
* $\theta$はラジアンなので、``rad_angle / np.pi * 180``で度に変換します。

# 任意のベクトルからの回転角
```Python:任意のベクトルからの回転角
def vector_to_vector_rotation_angle(vector_1, vector_2):
    unit_vector_1 = vector_1 / np.linalg.norm(vector_1)
    unit_vector_2 = vector_2 / np.linalg.norm(vector_2)
    cos = np.dot(unit_vector_1, unit_vector_2)
    rad_angle = np.arccos(cos)
    angle = rad_angle / np.pi * 180
    cross = np.cross(vector_1, vector_2)
    if cross < 0:
        angle *= -1
    return angle
```
途中までは、2つのベクトルの角度と同じです。
* ``cross = np.cross(vector_1, vector_2)``で、2次元のクロス積を求めます。(``np.cross(vector_1, vector_2)``は、``vector_1[0]*vector_2[1]-vector_2[0]*vector_1[1]``で定義されていて、$|vector_1||vector_2|\sin(\theta)$となり、$\sin(\theta)$が求まるので回転方向を決めるのに役立ちます。)
* ``cross < 0``のとき、$\sin(\theta)$が負となり回転角も負となります。

# サンプルでの実装結果
```Python:サンプルでの実装結果
# サンプル1
vector_1 = np.array([3, 5])
vector_2 = np.array([4, 2])
angle = vector_to_vector_angle(vector_1, vector_2)
rotate_angle = vector_to_vector_rotation_angle(vector_1, vector_2)
print(f'2つのベクトルの角度: {angle:.2f}')
print(f'vector_1を基準とした回転角: {rotate_angle:.2f}')

# 図に表示
fig, ax = plt.subplots()
ax.quiver(*vector_1, angles='xy', scale_units='xy', scale=1, color='r', label='vector_1')
ax.quiver(*vector_2, angles='xy', scale_units='xy', scale=1, color='b', label='vector_2')
ax.set_aspect('equal')
ax.set_xlim(0, 5)
ax.set_ylim(0, 5)
ax.legend()
plt.show()
```
```:出力結果
2つのベクトルの角度: 32.47
vector_1を基準とした回転角: -32.47
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1599258/fe312b4e-a206-af05-e492-1cc41d8f3020.png)

# 注意事項
* vector_1とvector_2＝λvecotr_1(λ>0)の場合、0°が期待されるが正しく計算されない場合がある。
* vecotr_1とvector_2=-λvecotr_1(λ>0)の場合、180°が期待されるが正しく計算されない場合がある。
* 0ベクトルがある場合は正しく計算されない。


# 参考資料
https://chadrick-kwag.net/get-rotation-angle-between-two-vectors/
IP-VPNをかんたんに説明してみる

# 勉強前の理解度
* VPNの方式の一つ
* たぶん主流

# IP-VPNの概要
　IP-VPNでは、通信事業者が用意した閉域ネットワークを利用してVPNを構築する。そのため、インターネット回線を利用した**インターネットVPNに比べ盗聴や改ざんのリスクが低く、通品品質が高い**。
　しかし、その性質上数千円～数万円程度の月額料金が発生するため、インターネットVPNより**コストがかかる。**(インターネットVPNはルーターの購入費用など初期投資のみで自社で構築可能である)
　なお、IP-VPNの契約数は増加傾向であったが、近年は横ばいで推移している。

# MPLS(Multi-Protocol Label Switching)
　ラベルを利用したパケット転送技術。閉域ネットワーク内では、MPLSを利用してデータがやり取りされている。MPLSでは、IPアドレスではなくラベルによってパケット転送を行うため、IPルーティングよりも高速でパケットを転送できる。
　IP-VPNは、**LER**(Label Edge Router)と**LSR**(Label Switching Router)を用いてMPLSを実現する。LERを通過する際にラベルの取り付けと取り外しが行われ、LSRが付与されたラベルを元にパケットを転送する。つまり、パケットを送る際の流れは以下のようになる。

1. 送信元のLERでラベルを取り付け、LSRに転送する
1. LSRがラベルに基づいてパケットを転送する
1. 送信先のLERでラベルを取り外す


# 参照
[【支援士22年 #8】IP-VPNのきほん - YouTube](https://www.youtube.com/watch?v=ETnXd7SPYR4)
[VPNの構築費用はいくらかかる？【安く抑えるコツとは】 | システム開発会社を探すなら「比較ビズ」](https://www.biz.ne.jp/matome/2005089/)
[総務省｜令和3年版 情報通信白書｜提供状況](https://www.soumu.go.jp/johotsusintokei/whitepaper/ja/r03/html/nd242210.html)
[VPNとは](https://www.infraexpert.com/study/ipsec.html)
EPELリポジトリ(レポジトリ)とは・・・？

<b>リポジトリは知っているけど、EPELリポジトリとはなにが違うんだろう？？？</b>

#■リポジトリとは？
下記サイトを確認したら保存場所のようなものであるらしい
>「容器、貯蔵庫、倉庫、集積所、宝庫などの意味を持つ」
https://e-words.jp/w/%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA.html

保存場所でありつつ、いつでも情報、ソースなどダウンロードしてくるものを格納している
CentOS標準(公式)のリポジトリから、yumコマンドでパッケージをダウンロードしてインストールすることができる。

⇒ではなんのためにリポジトリという格納場所を設けているのか？
 パソコンの中に格納しておけばいいものの、わざわざ別に保存場所を設けるのは効率悪いなと思っていたが、分散させることがメリットとのこと。

万が一、一元的に管理しており、
PC内にウィルスが入り、保存してある情報を書き換えられたりした場合、
一気に感染する恐れがあるため、分散にしている。

もちろんローカルの中にCDやDVDに情報を入れて、一元的に管理することができるがそれはローカル環境のインターネットに接続しない環境限定にしたほうがいいと思います。


#■EPRLリポジトリとは
>EPELは、Extra Packages for Enterprise Linuxの略で、 Red Hat Enterprise Linux(RHEL)向けの追加パッケージを提供するリポジトリ
https://livescamp.com/learn/epel

一般的なリポジトリは公式のリポジトリであり、標準のパッケージ
ただ標準リポジトリに存在しないソフトウェアもある。
⇒サードパーティ製のリポジトリ

公式が出したリポジトリではないため、
インストールして何かあったときはサポート対象外。すべて自己責任のため注意が必要みたいです。
４０代おっさんPythonを勉強する（プレーンテキストファイルの読み書き編）

## 本記事について

この記事はプログラミング初学者の私が学んでいく中でわからない単語や概要を分かりやすくまとめたものです。
もし不正などありましたらコメントにてお知らせいただければ幸いです。

## 基本のファイル入出力

- ファイルの読み書き

```python
tobj = open(filename, mode)
```

- fobjはopen()関数が返したファイルオブジェクト
- filenameはファイル名、場所がわかるようにパスも必要な場合がある
- modeはファイルのタイプや操作モード
  - 第一文字
    - `r`=>読み出し、ファイルが存在しない場合はエラー
    - `w`=>書き込み、ファイルが存在しない場合は新しく作り、存在する場合は上書き
    - `x`=>書き込み、ファイルが存在する場合はエラー（上書きミスを防ぐため）
    - `a`=>書き込み、ファイルの後ろに追記
  - 第二文字
    - `t`=>テキスト
    - `b`=>バイナリ
- デフォルトは`rt`、テキストの読み出し
- 最後にファイルを閉じる必要がある

### ファイルの書き込み

```python
text  = """aaa
bbb
ccc
ddd"""

f = open('abcd.txt', 'w', encoding="utf-8") # ファイルを開く
#  encoding="utf-8", "shift_jis", "euc_jp"
f.write(text) # 書き込み
f.close() # 閉じる
```

- OSによってデファクトの文字コードが変わることがあるの注意
- ここでは`encoding="utf-8"`を指定している

### ファイルの読み出し

```python
f = open('abcd.txt', 'r') # もし文字コードが違う場合は後ろに加えても良い
texts = f.read() # 一気でファイルを読み出す、ファイルが大きい場合はメモリ不足の注意が必要
f.close()
print(texts)
```

- 一気で読み込むのは無理なら、イテレータを使って、一行ずつを読み出す

```python
f = open('abcd.txt', 'r')
for line in f: # 毎回一行だけ
    line = line.split() # 行末の改行を消す
    print(line) # 改行が入る
f.close()
```

- 一気で一行ずつのリストを返すのもできる

```python
f = open('abcd.txt', 'r')
texts = f.readlines() # ファイルが大きい場合はメモリの注意が必要
f.close()
print(texts)
```

### withによる自動的クローズ

- 開いたファイルを閉じ忘れると、参照されなくなるまでは開いたままで、メモリの無駄にもなる
- 共同のファイルだったら、他人が書き込むことができなくなる可能性もある
- それを防ぐために、コンテキストマネージャーを使って、自動的に閉じることができる

```python
with open('abcd.txt', 'r') as f:
    texts = f.readlines()
#  ファイルは自動的に閉じる
#  そのあと保存されたテキストを処理してもよい
#  ファイルが閉じてあとでf.read()をするとエラーになる
for line in texts:
    line = line.strip()
    print(line)
```

## 参考

https://www.kitakyu-u.ac.jp/news/2022/08/003215.html