OmniAICreator/Qiita-1.07M huggingface dataset:
PowerShellとChromeDriverでキーワード自動検索

## この記事は

PowerShellからChromeを起動し、"Qiita"と入力して検索する
ただし、それらは手作業ではなく **WebDriver を使って自動で行う**

## 検証環境

検証環境のバージョンを調べる

### Google Chromeのバージョン

Chromeブラウザから`chrome://settings/help`を開いてバージョンを確認する

> Chrome は最新の状態です
> バージョン: 109.0.5414.75（Official Build） （64 ビット）

### PowerShellのバージョン

`Windows + R`でファイル名を指定して実行を開き、`powershell`と入力してEnterキーを押す
`Get-Host`コマンドでPowerShellのバージョンを調べる

```powershell
> Get-Host
Version          : 5.1.22621.963
```

## 各種ソフトウェアを準備する

### ChromeDriver

[ChromeDriverのダウンロードサイト](https://chromedriver.chromium.org/downloads)から、使用しているChromeバージョンに合致するものを落とす
フォルダーの中に`chromedriver.exe`が入っているので、これを使う

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/8059e4ec-b6f7-058a-b8f6-5a3cb4845acf.png)

### WebDriver

[Seleniumのダウンロードサイト](https://www.selenium.dev/downloads/)から、**C#のdll**を落とす
フォルダーの中を`lib`→`net48`を進んでいくと、`WebDriver.dll`があるので、これを使う

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/8a87e1bd-d4a1-178a-0941-8cc757e64018.png)

`.nupkg`拡張子を`zip`拡張子にリネームし、解凍する

```powershell
mv .\selenium.webdriver.4.7.0.nupkg .\selenium.webdriver.4.7.0.zip
```

## プログラム（ソースコード）

作業用フォルダの中に、先に落とした`chromedriver.exe`と`WebDriver.dll`を入れておく

さらに、`main.ps1`を作成する
これがPowerShellのメインのコードになる

### PowerShell

作業フォルダの中に作った`main.ps1`の中身は下記の通り

```powershell:main.ps1
#Requires -Version 5.0

$webDriverDllPath = ".\WebDriver.dll"
$chromeDriverDirPath = ".\powershell\"
Add-Type -Path $webDriverDllPath

$Options = New-Object OpenQA.Selenium.chrome.ChromeOptions
$Options.AddArgument("useAutomationExtention=false")
# 「Chromeは自動テストソフトウェアによって制御されています」を非表示にする
$Options.AddExcludedArgument("enable-automation")
# ウィンドウサイズを最大にする
$Options.AddArgument("--start-maximized")

# Googleで Qiita を検索する
$chromeDriver = New-Object OpenQA.Selenium.Chrome.ChromeDriver($chromeDriverDirPath, $Options)
$chromeDriver.Url = "https://www.google.com/"
# GoogleトップのHTMLは難読化されているので、gLFyfなどという意味のわからないクラス名
$x = $chromeDriver.FindElement([OpenQA.Selenium.By]::ClassName("gLFyf"))
$x.SendKeys("Qiita")
$x.SendKeys([OpenQA.Selenium.Keys]::Enter)

exit

# 補足: Idでエレメントを検索する場合
# $x = $chromeDriver.FindElement([OpenQA.Selenium.By]::Id(""))
```

#### おまけ：パスワードなどの機密情報をソースコードに書く場合

PowerShellのSecure-Stringを使う

https://qiita.com/t13801206/items/67f0ddf625d3bdcf0b4d#%E3%82%BB%E3%82%AD%E3%83%A5%E3%82%A2%E3%83%91%E3%82%B9%E3%83%AF%E3%83%BC%E3%83%89%E7%94%9F%E6%88%90%E7%94%A8%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88

## 実行したときの様子

シンプルすぎて、クリップボードからの貼り付けのようにも見えてしまう

![anime.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/520ba227-cf4a-39aa-31de-12988e73b7d1.gif)

:::note warn
ブラウザを閉じても WebDriver のプロセスは残り続けるので、ちゃんと後始末する
:::

https://qiita.com/yuki-k/items/aeb4ec8f10c391ca1037

## 参考にさせていただいた記事

https://qiita.com/kk-ster/items/3485318539071ff9941a

https://github.com/senkousya/startSeleniumOnPowershell

https://www.selenium.dev/selenium/docs/api/dotnet/index.html

## 糸冬了！！
FlutterのWidgetテストが終わらない現象の対応

# 背景
- FlutterでFirebaseを組み込んだアプリのWidgetテストを行おうとすると、一向にテストが終わらない現象が発生したので備忘録として残します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245300/6721afff-d31a-a693-84a5-bccade098244.png)
- 結論として、Firebase.initializeApp()がプラットフォーム上でないと動作しないために発生している事象のようなので、Mockを用意してあげることで解決しました。

# コード
- testWidgetの中でFirebaseを初期化しようとしています。これがないとWidgetテスト実行時に
`No Firebase App '[DEFAULT]' has been created - call Firebase.initializeApp()`
と怒られていたために記述していました。

``` :該当コード
void main() {

  testWidgets('Counter increments smoke test', (WidgetTester tester) async {
    // Build our app and trigger a frame.
    await Firebase.initializeApp(
      options: DefaultFirebaseOptions.currentPlatform,
    );
    await tester.pumpWidget(const MyApp());

    expect(find.text('Flutter x Firebase'), findsOneWidget);
```

# 解決方法
- 代わりにFirebaseのmockを用意します。
- stackoverflowの[こちらのコメント](https://stackoverflow.com/questions/63662031/how-to-mock-the-firebaseapp-in-flutter/64730015#64730015)を参考にしています。

``` :修正後のコード
import '../mock.dart';

void main() {
  // Firebaseをmockしないとwidgetのテストが終わらない。
  setupFirebaseAuthMocks();
  setUpAll(() async {
    await Firebase.initializeApp();
  });

  testWidgets('Counter increments smoke test', (WidgetTester tester) async {
    // Build our app and trigger a frame.
    await tester.pumpWidget(const MyApp());

    expect(find.text('Flutter x Firebase'), findsOneWidget);
```

``` :mock.dart
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// URL：https://stackoverflow.com/questions/63662031/how-to-mock-the-firebaseapp-in-flutter/64730015#64730015

import 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';

typedef Callback = void Function(MethodCall call);

void setupFirebaseAuthMocks([Callback? customHandlers]) {
  TestWidgetsFlutterBinding.ensureInitialized();

  setupFirebaseCoreMocks();
}

Future<T> neverEndingFuture<T>() async {
  // ignore: literal_only_boolean_expressions
  while (true) {
    await Future.delayed(const Duration(minutes: 5));
  }
}
```

これでひとまずテストが動作するようになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245300/584f6cce-d443-0c27-b3e8-711311ac35ad.png)


# 参考リンク
- [How to mock the FirebaseApp in flutter](https://stackoverflow.com/questions/63662031/how-to-mock-the-firebaseapp-in-flutter/64730015#64730015)
- [[Github] flutterfire mock.dart](https://github.com/firebase/flutterfire/blob/master/packages/firebase_auth/firebase_auth/test/mock.dart)
- [Firebase auth unit testing error No Firebase App](https://stackoverflow.com/questions/63634609/firebase-auth-unit-testing-error-no-firebase-app/63701588#63701588)
PATH通してるのにctypesで`FileNotFoundError: Could not find module (or one of its dependencies)`

結果として、Windows版Python3.8での`ctypes.LoadLibrary`仕様変更、`os.add_dll_directory`の追加の話です。
つまり、ライブラリのサーチで単純にPATHを参照しないということでした。

https://github.com/python/cpython/issues/80266

## ハマったこと

Windows, Python 3.9で自前の`mylib.dll`を使いたい。
`mylib.dll`は`dep.dll`に依存している。

`mylib.dll`と`dep.dll`が同じディレクトリにある時は問題ない。

```python
import ctypes
dll = ctypes.CDLL(R"path\to\mylib")
```

ところが、`dep.dll`を他のディレクトリに追いやってPATHを通したうえで同じことをすると

> FileNotFoundError: Could not find module 'D:\XXXX\path\to\mylib' (or one of its dependencies). Try using the full path with constructor syntax.

などと言われる。


## 解決

[os.add_dll_directory](https://docs.python.org/3/library/os.html#os.add_dll_directory)を使って、dllのディレクトリ（サーチするパス）を明示的に与えてやれば解決した。

[このissues](https://github.com/python/cpython/issues/80266)は正直いってよく分からなかったので、
今回は単純に環境変数`PATH`を`add_dll_directory`に与えちゃうことにします。

```python
import ctypes
import os

dll = ctypes.CDLL(R"path\to\mylib")
# FileNotFoundError: Could not find module 'D:\xxxx\path\to\mylib' (or one of its dependencies). Try using the full path with constructor syntax.

for p in os.environ['PATH'].split(os.pathsep):
    if os.path.isdir(p):
        os.add_dll_directory(p)
    
dll = ctypes.CDLL(R"mylib")
# 問題なし
```

## これの問題は？

なんでこんな仕様になっているのかちゃんと調べていないが、PATHをそのまま使うのに何か危険があるのかもしれない。
解説か他の賢い方法があったら教えてください。
【Linux】Rustのインストールで詰んだとき (PATHが通ってない、 シェルからcargoコマンドが実行できない)

# 【Linux】Rustのインストールで詰んだとき (PATHが通ってない、 シェルからcargoコマンドが実行できない)

### この記事は

Debian派生ならうまく行くかも。

『Rustをインストール！』  https://www.rust-lang.org/ja/tools/install
"Rust is installed now. Great!" -> $.cargo/env -> ＼( ^ O ^ )／ って人向け。

### rustが実行できない、cargoが実行できない

なんでだろうね。(考えるのをやめた)

### 無理やり工事する (/usr/local/binにsyboliclink貼る)
Rustのコミュニティ日本語翻訳はこちら-> https://www.rust-lang.org/ja/tools/install
/usr/local/binって何ぞって人はこちらおぬぬめ-> https://linuc.org/study/knowledge/544/
シンボリックリンク？あやしそう！って人はこちらがこぬぬめ(作成方法)-> https://qiita.com/colorrabbit/items/2e99304bd92201261c60


#### とりあえずどうにかなるさコピペ文
```
echo -e "\n-----------------------"
chmod a+x .cargo/bin/cargo
echo -e "警告： /usr/local/bin/ に cargo のシンボリックシンクを作成します、実行には管理者権限が必要です。"
sudo echo -e "1/5: cargo を追加します"
sudo ln -s {$HOME}/.cargo/bin/cargo /usr/local/bin/cargo
echo -e "2/5: rustup を追加します"
sudo ln -s {$HOME}/.cargo/bin/rustup /usr/local/bin/rustup
echo -e "3/5: rustc を追加します"
sudo ln -s {$HOME}/.cargo/bin/rustc /usr/local/bin/rustc
echo -e "4/5: rustdoc を追加します"
sudo ln -s {$HOME}/.cargo/bin/rustdoc /usr/local/bin/rustdoc
echo -e "5/5: rustfmt を追加します"
sudo ln -s {$HOME}/.cargo/bin/rustfmt /usr/local/bin/rustfmt
echo -e "\n終了。これはあくまでもその場しのぎであることを覚えておいてください！\n"

```

### できなかったら、、、
他の方法をためしてくれ,,,そして解決法をインターネッツで公開してくれ...!
データ分析で使うコード (データ扱い編)

個人的に使うものを厳選して残しておきます。

### データのインポート

Pandasのread_csvは、CSVファイルを読み込むための関数です。

```Python
import pandas as pd
df = pd.read_csv('home/hoge.csv')
```
```Python
import pandas as pd
# デフォルトの区切り文字はコンマ。
# スペース区切りの場合は sep 引数を使用する。
df = pd.read_csv('home/hoge.csv', sep=' ')

# 自動的に最上行のデータをヘッダーにしたくない場合
df = pd.read_csv('home/hoge.csv', header=None)

# ヘッダーに使用する列名を指定するとき
df = pd.read_csv('home/hoge.csv', names=['A', 'B', 'C'])

# 読み込む列を指定したいとき
df = pd.read_csv('home/hoge.csv', usecols=[0, 1, 2])
```
### データのエクスポート
```Python
df.to_csv('home/new_hoge.csv') # CSVファイルに書き込む
```
### データの探索
Pandasのdataframeにデータをインポートしたら、
これらのメソッドを使ってデータがどのようなものであるかを知ることができる。
```Python
import pandas as pd
df = pd.read_csv('data.csv')

print(df.shape)
>>> (行数,列数)

print(df.head(5))
>>> 先頭から5行を表示

print(df.tail(3))
>>> 末尾から3行を表示

print(df.info())
>>> データフレームの情報を表示
>>> インデックスの情報,各列のデータ型,メモリ使用量などが表示

print(df.columns)
>>> 特徴ラベル一覧の表示

print(df.describe())
>>> データフレームの数値型の列に関する統計量を算出する
>>> count, mean, std, min, 25%, 50%, 75%, max などが出力
```
### データの抽出
データの検査やさらなる分析を行うために、
1つの要素などを抽出する必要があるときに便利なメソッド。
```Python
df2 = df.loc['列名A','列名B'] # '列名A'と'列名B'のデータ
df2 = df.iloc[0] # 0行目のデータ
df2 = df.iloc[:,0] # 0列目のデータ
df2 = df.iloc[0,0] # 0行0列目のデータ
```
### データ処理
データをそのまま使えない場合が多いので、
データ処理する必要がある。そのときに使うメソッド。
```Python
df.columns = ['a','b','c'] # 列名の変更

df.sort_values(col1) # 列col1を基準に昇順に並び替える
df.sort_values(col2,ascending=False) # 列col2を基準に降順に並び替える
df.sort_values(by=['列名1', '列名2'], ascending=[True, False])
# 列名1で昇順、列名2で降順でソートする。

pd.isnull() # 各要素がNaNかどうかを（True/False）のデータ構造を返す

df.dropna() # すべての行にNaNが含まれている場合に、それらの行を削除する。
df.dropna(axis=1) # 列方向の操作
df.dropna(axis=1,thresh=n) # その列にNaNがn個以上ある場合にその列を削除

df.fillna(0) # NaNの値を0に置き換える
df_new = df.fillna(0, inplace=False) # もとのデータフレームを変更したくない場合
df.fillna(df.mean()) # NaNの値を平均値に置き換える

df.astype(float) # データの中身をfloat型に変更する
```
2023/1/15主にITとかセキュリティの記事

市立45校のサイト更新用アカウントが改ざん被害 - つくば市
https://www.security-next.com/142799

富士通のネット回線サービスで不正通信 - クラウドやMSSなどにも影響
https://www.security-next.com/142871

医師私物スマホから院内音声がライブ配信 - 埼玉県内病院
https://www.security-next.com/142851

JWTのJavaScript実装「jsonwebtoken」に複数脆弱性
https://www.security-next.com/142795

英語検定試験「TOEIC」の申込サイトに大量のログイン試行
https://www.security-next.com/142803

アカマイ・テクノロジーズ、最新の調査レポート「SOTI インターネットの現状／セキュリティ：差し迫る敵」を発表　〜アジア太平洋・日本地域の金融サービス業界が深刻なリスクに直面(1/13)
https://securityinsight.jp/news/13-inbrief/5289-230113-1

中国が量子コンピュータで「暗号の壁」を破る？(1/13)
https://forbesjapan.com/articles/detail/60015

日本企業はセキュリティー責任者不足傾向　NRIセキュア調査　対策の強化問われる(1/13)
https://dempa-digital.com/article/393177

日本では半数以上の組織が未登録デバイスで業務プラットフォームにログイン--シスコ調査(1/13)
https://japan.zdnet.com/article/35198527/

振る舞い分析＋運用監視サービスの市場規模は2桁成長が続く(1/12)
https://bp-affairs.com/news/2023/01/20230112-11882.html

国境を超えるサイバー戦のリアル：英ドラマ「Undeclared War」に震撼(1/12)
https://agora-web.jp/archives/230110084125.html

未登録デバイスの利用、企業セキュリティの脅威に　シスコ調査(1/13)
https://www.zaikei.co.jp/article/20230113/705395.html

(ISC)²、アジア太平洋地域における2023年のサイバーセキュリティ業界の予測を公開(1/13)
https://japan.cnet.com/release/30819338/?ref=rss

東大、暗号鍵を送受信者間で一切やりとりしない超高セキュリティワイヤレス通信技術の開発に成功(1/13)
https://www.nikkei.com/article/DGXZRSP647329_R10C23A1000000/

Linux管理で人気のツール「CWP」の脆弱性悪用を確認、ただちにアップデートを(1/13)
https://news.mynavi.jp/techplus/article/20230113-2561798/

Juniper Networksの複数製品に緊急の脆弱性、ただちに確認とアップデートを(1/13)
https://news.mynavi.jp/techplus/article/20230113-2561700/

WindowsとExchange Serverに未特定の脆弱性、攻撃への悪用確認済みで要注意(1/13)
https://news.mynavi.jp/techplus/article/20230113-2559687/

量子コンピューターは既にRSA暗号を解読できると中国人研究者が主張も専門家からは「誤解を招く論文」「そんなに楽じゃない」との指摘も(1/13)
https://gigazine.net/news/20230113-chinese-researchers-claimed-quantum-encryption-crack/

Ripple最高技術責任者はFlareサポートアカウントの不正使用に警告(1/13)
https://nextmoney.jp/?p=56050

Google Chrome、プログラミング言語「Rust」の採用を発表(1/13)
https://news.mynavi.jp/techplus/article/20230113-2561774/

「Docker Desktop 4.16」が公開、「Docker Extensions」の一般提供が開始
イメージの脆弱性解析は最大4倍にまで高速化、メモリ使用量は最大で76％削減(1/13)
https://forest.watch.impress.co.jp/docs/news/1469901.html

「MacはWindowsよりも安全だ」神話はなぜ生まれ、なぜ崩れたのか(1/13)
https://news.yahoo.co.jp/articles/484ceff4089b3103c0f392cd36aeb6cfc6d0a2a3?source=rss

2022年に最も読まれたニュース記事は？ 2021年に続きフィッシング詐欺に関する記事が上位を占める(1/13)
https://internet.watch.impress.co.jp/docs/special/1470191.html

JR東日本、グループ6万台の端末にEDRを展開(1/13)
https://japan.zdnet.com/article/35198567/

ETC利用照会を騙るフィッシングに注意！(1/13)
https://ascii.jp/elem/000/004/119/4119825/?rss

アフラックとチューリッヒの情報流出についてまとめてみた(1/13)
https://piyolog.hatenadiary.jp/entry/2023/01/13/004052

富士フイルムのメールアドレスを騙った「なりすましメール」にご注意ください(1/13)
https://www.fujifilm.com/jp/ja/news/list/9064

北ガスジェネックスのお客さま情報漏えいの可能性に関するお詫びとお知らせ(1/13)
https://www.hokkaido-gas.co.jp/news/20230113_2

昨年の仮想通貨の犯罪的取引、制裁違反などで過去最大に＝リポート(1/13)
https://jp.reuters.com/article/fintech-crypto-crime-idJPKBN2TS044
DockerのMySQLの環境変数の変更が反映されない場合の解決方法

## 発生した事象
MySQLに接続するときのパスワードを`pass`から`password`に変更しようと思い
```yml:docker-compose.yml
version: "3.8"

services:
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: pass
    ports:
      - "3307:3306"
    volumes:
      - db:/var/lib/mysql

volumes:
  db:
```
から
```yml:docker-compose.yml
version: "3.8"

services:
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: password # 変更
    ports:
      - "3307:3306"
    volumes:
      - db:/var/lib/mysql

volumes:
  db:
```
に変更し、変更後のパスワードである`password`で接続しようとしたのですが何故かアクセスできませんでした。
```
$ mysql -u root -P 3307 -h 127.0.0.1  --password=password
ERROR 1045 (28000): Access denied for user 'root'@'172.21.0.1' (using password: YES)
```
ビルドし直したりキャッシュの削除も試してみたのですが変更されないままでした。


## 原因
`docker-compose.yml`に記載した
```yml
volumes:
  db:
```
のvolumeに変更前の設定が残っていたらしく、一回volumeを削除しないといけないようでした。

## 解決方法
`docker volume ls`コマンドでvolume一覧を確認するとvolumeが作られていることが確認できると思います。
```
$ docker volume ls
DRIVER    VOLUME NAME
local     sample_db
```
下記のコマンドでvolumeを削除します。
```
docker volume rm sample_db
```
再び`docker volume ls`コマンドでvolume一覧を確認するとvolumeが削除されていることが確認できると思います。
```
$ docker volume ls
DRIVER    VOLUME NAME
```
volumeの削除完了後`docker-compose up`でコンテナを起動したとき、今度は変更後のパスワードである`password`で接続することが確認できました。
```
$ mysql -u root -P 3307 -h 127.0.0.1  --password=password
mysql>
```
SwiftUIのプレビューで中華フォントになってしまうのを避ける

最近初めて個人制作でiOSアプリを作ったんですが、SwiftUI（というかStoryboardも）の **プレビューで中華フォントになる** のがあまりに気になってしまい、開発初期段階でイライラしてしまいました。

### ☆解決方法
1. メニューバー > Product > Scheme > Edit SchemeでターゲットのSchemeを編集します。
1. Run > Options > App Languageを **Japanese** にします。
1. ついでにApp RegionもJapanにしていいと思います。

これだけです。

※ちなみに、ここでやってること自体は中華フォントを避けることではなく、ビルドする環境を日本語にするというものです。なので実機でのテスト等も日本語環境で行われますのでご注意。基本的に日本語で作るのであればそれで問題ないとは思いますが。英語環境だと中華フォントになってしまうかなしい世界…。

意外とどこにも書いてなくて、当時はたどり着くまでに時間がかかりました。
windows10のプロダクトキーをPowerShellで確認する

# ライセンス認証キーが無い！
中古でThink padを購入したのですが、windowsのOS認証キーが印字された書類も何も添付されていなったんですよ。
エンジニアやってると、OSを壊して入れ直したりというのはしょっちゅうなので（？）、これは困りました。すわ、店側のミスかとクレーム入れてやろうかと思いましたが、調べてみたらプロダクトキーはPowerShell上で確認できるそうです。
やはり何事もまずは自分で調べてみるべきですね。恥をかく前で良かったです。
というわけで、手順を備忘録として残しておきます。

# 環境
Windows 10 Professional
PowerShell
特に変わったものは使わないです。

# 手順
なんてことは無く、PowerShellを起動してコマンドを打つだけです。
PowerShellの起動方法は今さらなので省略
打つコマンドは下記の通り。
```
PS C:\Users\hogehoge> wmic path softwarelicensingservice get OA3xOriginalProductKey
```
すると下記のような形式でプロダクトキーが出力されます。
```
OA3xOriginalProductKey
XXXXX-XXXXX-XXXXX-XXXXX-XXXXX
```
あとはこれをどこかしらにメモして大切に保管しておこう。

## windows7 or 8から10へアップグレードした場合
ちなみに、WindowsOSのライセンス認証キーに関してはいくつか種類があり、Windows7または8から10へアップグレードした場合は、上記のコマンドでは認証キーを確認できませんでした。
また別方法はいくつかありそうなので、今後もまとめてみたいと思います。
GitHub CLIのクイックスタートガイド

## 概要
- [GitHub CLI](https://cli.github.com) (command-line interface)は、コマンドラインからGitHubを使用するツール。
- GitHub CLIのコマンドは[gh](https://cli.github.com/manual/gh)で、対話形式で実行できる。オプションを指定して、非対話で実行することも可能。
- 対話形式では、ghが質問してくるので、それらに回答しながら作業内容を指示する。通常は回答の候補や選択肢を示してくれる。選択肢の場合は矢印キーで選択する。
- ghのインストール方法と簡単な使用法を説明する。

## 前提
- OSはmacOS Venturaを使用する。　※OSの相違はインストールにだけ影響

## Gitの最新版とghをインストールする。

```shell
% brew update     # Homebrew本体およびformulaを最新版に更新
% brew upgrade     # Homebrewでインストール済みのパッケージを最新版にアップグレード
% brew install git     # gitの最新版をインストール
% brew install gh     # ghをインストール
```

## ghの簡単な使用法

GitHubにログインする。

```shell
% gh auth login
```

GitHubリポジトリを作成する。

```shell
% gh repo create
```

GitHubからログアウトする。

```shell
% gh auth logout
```

## ghの便利なコマンド

GitHubリポジトリのリストを表示させる。

```shell
% gh repo list
```

ブラウザを開いて、GitHubリポジトリの内容を表示させる。

```shell
% gh repo view -w
```

リモートリポジトリをクローンする。

```shell
% gh repo clone <リポジトリ>
```

リモートリポジトリを削除する。

```shell
% gh repo delete <リポジトリ>
```
Tkinterのウィジェット一覧をリストで取得する


TkinterでGUIを作成するときに配置したウィジェットを一覧で取得する必要があったのでメモ。


```python
import tkinter as tk

# ウィジェット一覧をリストで取得
def get_all_widget (wid, finList=None) -> list:
    if finList is None:
        finList = []
    _list = wid.winfo_children()        
    for item in _list :
        finList.append(item)
        get_all_widget(item,finList)   
    return finList

root = tk.Tk()

# ～～～～～～～～～～
# ウィジェット配置処理は割愛。
# ～～～～～～～～～～

for wdg in get_all_widget(root):
    print(wdg)
```

#### 結果
直下だけでなくcanvasの中のwidgetも取得する。

```
.!application
.!label 
.!entry 
.!label2
.!entry2
.!label3
.!entry3
.!button
.!label4
.!canvas
.!canvas.!radiobutton
.!canvas.!radiobutton2
```
【GitHub】リポジトリにスターを付けたユーザーを表示する方法

# 初めに

今日初めてスターが付きました！どういったユーザーに評価されたのか気になり、スターを付けてくれたユーザーのリポジトリも見てみようと思いました。

# 方法

リポジトリの URL に、`/stargazers` を付与します。

## 例

`https://github.com/oiz-y/sagemath-lambda-container-sample`

であれば、

`https://github.com/oiz-y/sagemath-lambda-container-sample/stargazers`

とします。

# 参考記事

https://docs.github.com/ja/get-started/exploring-projects-on-github/saving-repositories-with-stars#viewing-who-has-starred-a-repository
生PHPでAPIルーティング, リフレクションで動的にクラスメソッド実行

# 生PHPで、APIルーティング
要件
`api/class/method`でのAPIリクエストを想定。
リフレクションで動的に実行する。

```php index.php
<?php
// var_dump($script_name['SCRIPT_NAME']); => /api/index.php
// var_dump($script_name['REQUEST_URI']); => /api/class/method

// URI`api/hoge/fuga?aa=1`から、`hoge/fuga`を取得
// デリミタは、URIの`/`と被らないように指定
$delimiter = '~';
$pattern = $delimiter .dirname($_SERVER["SCRIPT_NAME"]).'/([\w]*)/([\w]*)' . $delimiter;
$result = preg_match($pattern, $_SERVER["REQUEST_URI"], $matches);

// 正規表現より、`Index Out Of Bounds`は起きないはず
$paths = explode('/', $matches[1]);
$class = $paths[1];
$method = $paths[2];

// 今回は要件より、リクエストメソッドは見ない
// $_SERVER['REQUEST_METHOD'];
$class_file = __DIR__ . '/{$class}.php';
if(file_exists($class_file)){
    require_once $class_file;

    try{
        $reflection = new ReflectionClass($class);
    
        // 実行可能なクラスメソッドか？
        if($reflection->isInstantiable()
            && $reflection->hasMethod($method)
            && $reflection->getMethod($method)->isPublic()
            && $reflection->getMethod('__construct')->isPublic())
        {
            $controller = $o_reflection->newInstance();
            // $o_controller->

            echo '{"result":"ok"}';
        }
    
    }catch(ReflectionException $e){
        var_dump($e);
    }
    
}else{
    http_response_code(404);
    include './404.php';
    exit;
}

```

```.htaccess
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [QSA,L]

```
Jekyllでポートフォリオ開発　〜インストール〜

### Ubuntuにインストール

Github-pages自体がJekyllベースで出来ており、マークダウンでブログ書けるなど便利なため、ポートフォリオ開発の言語としてJekyllを選んだ。

まずRubyとそれに伴うプログラムをインストール
```
sudo apt-get install ruby-full build-essential zlib1g-dev
```

RubyGemsは、rootでインストールせず、.bashrcに保存
```
echo '# Install Ruby Gems to ~/gems' >> ~/.bashrc
echo 'export GEM_HOME="$HOME/gems"' >> ~/.bashrc
echo 'export PATH="$HOME/gems/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
```

GemでJekyllをインストール
```
sudo gem install jekyll bundler
```
[Python]10行以内で画像の背景を透過する

# tl;DR
https://twitter.com/clcoding/status/1614105406019891200?s=20&t=J_YC_AA87XbAX0iPxjol8Q

上ツイートの受け売りです

# やりたいこと
![tst.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883146/e866de7e-89bf-8a34-f07c-d0c8c7828bc5.png)

この画像から背景を消して...

![rembg_tst.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883146/c2fd3d2e-b9d8-acd5-d2af-b2c9427b955b.png)

こんな感じの画像を生成します。

# 前提
透過するわけなので、**JPEG**のようなアルファ値をもたないファイルは使えません。PNGなどに変換してください。

# 概要
**rembg**というライブラリを使用します。
画像を扱うために`PIL.Image`もインポートします。

https://github.com/danielgatis/rembg


```py
from rembg import remove
from PIL import Image
```

rembgの`remove()`に`PIL.Image`のインスタンスを渡すことで背景を消してくれます。

```py
in_path = 'tst.png'
out_path = f'rembg_{in_path}'

in_img = Image.open(in_path)
out_img = remove(in_img)
```

あとは処理された画像を保存すればOK。
```py
out_img.save(out_path)
```
Java Ramdomクラスの使い方

<h5>・Ramdomクラスとは</h5>
　Ramdomクラスは、指定した数字からランダムに１つ生成するクラスである。

```Java:Ramdom
    //Ramdomクラスのコンストラクタ、新規乱数ジェネレータを作成する。
    Ramdom ramdom = new Ramdom();
    //nextIntの引数には出したい個数を入れる。
    //10といれた場合10桁かつ0~9の10個の中からランダムで生成される。
    int ramdomInt = ramdom.nextInt(10);
    //nextIntのあとに+で入れる数字によって生成される数字を操作することができる。
    //今回の場合は, +1 なので 1~10 の10個の中からランダムで生成されるようにできる。
    int ramdomInt1to10 = ramdom.nextInt(10) + 1;
```
UnityとEpic Online Servicesを組み合わせたオンラインゲームの作成～⓪導入編～

# この(連載)記事の概要
これから3つの記事に分けて、次の環境でオンラインゲームの開発をする時の環境構築手順を紹介します！

フロントエンド：Unity
バックエンド：Epic Online Services

Epic Gamesの公式ホームページの説明が丁寧なので、この記事では全体の流れを紹介しつつ、細かい説明は公式HPのURLを張り付けています。

# Epic Online Servicesとは

Epic Gamesが提供している、無料でオンラインゲームのサーバーサイドを作る事が出来るツールです！！
ロビー機能やボイスチャットなどの機能を無料で実装できるツールは非常に稀なので必見ですね。


https://dev.epicgames.com/ja/news/introduction-to-epic-online-services-eos

# Epic Online Service導入の手順

### ①Developer Portalでの製品の設定
1つ目のステップは、「Developer Portalでの製品の設定」です。これは、Epicアカウントを作成するとEpic Gamesのウェブサイトから飛ぶことのできる「Developer Portal」というウェブページで行うものです。これでバックエンド側の設定を行います。

https://qiita.com/Ayuchan/items/f13aea3ac0ce95af0e03


### ②EOSとUnityの接続
②2つ目のステップは、ステップ１で設定した製品をUnityで扱えるようにすることです。必要なSDKをUnityにインストールして、EOSとUnityを接続します。言わば、バックエンドとフロントエンドを繋ぐ作業ですね！

URL：工事中

### ③EOSを応用したゲーム作り

③3つ目のステップは、Epic Online Servicesを応用して実際に自分のゲームで使用する事です。主にフロントエンド側の作業になりそうです。

URL：工事中
【ネットワーク】IPアドレスのCIDR表記とは


## CIDR表記とは

IPアドレスのネットワーク部のビット長を`/ビット長`で示す方法です。

例えば、`192.168.1.0~192.168.1.255`の範囲の場合は`192.168.1.0/24`と表記します。24ビットまでがネットワーク部、残り8ビットがホスト部になります。（IPアドレスは32ビット。8ビットずつ10進数で表示している。この場合、ネットワーク内に256のホストを配置できる。）

表記の違いだけで以下は全部同じ意味になります。

```
192.168.1.0~192.168.1.255
192.168.1.0/24
192.168.1.0/255.255.255.0（サブネットマスク表記）
```

192.168.1.0/24だったら`192.168.1.0~192.168.1.255`
10.0.0.0/24だったら`10.0.0.0~10.0.0.255`
と理解できることが大事です。

CIDRブロックで分割したネットワークをさらに分化したCIDRブロックのことをサブネットといいます。


## IPアドレスの管理

IPアドレスは、ICANNが一括管理しています。必要に応じて配下の団体へと配布する仕組みがとられています。

## プライベートIPアドレスの範囲


以下の範囲がプライベートIPアドレスとして使われます。

```
10.0.0.0~10.255.255.255
172.16.0.0~172.31.255.255
192.168.0.0~192.168.255.255
```


## ルートテーブル

インターネットはTCP/IPプロトコルによって成り立っています。

TCP/IPでは、ネットワーク機器であるルーターが「宛先IPアドレス」をみて、宛先IPアドレスに近い方のネットワークへと次々にパケットを配送していきます。

ルートテーブルは「宛先IPアドレス」と「次の配送先ネットワーク」を結びつける表です。
ルーターは、ルートテーブルを見て次にパケットを送る先を判断します。


## まとめ



CIDR表記は、IPアドレスのネットワーク部のビット長を`/ビット長`で示す方法です。
例えば、`192.168.1.0~192.168.1.255`の範囲の場合は`192.168.1.0/24`と表記します。
GitHubで管理したくないディレクトリを間違えてGitHubにあげてしまった！そんな時の対処方法

## 【はじめに】
GitHubで管理したくないファイルを間違えてGitHubにあげてしまった！
そんな時の対処法について備忘録も兼ね、node_modulesを例に簡単にまとめておきます。

## 【手順】

1. プロジェクトのルートディレクトリに.gitignoreを作成する
2. .gitignoreにGitHubで管理したくないディレクトリを追加する
3. 対象のディレクトリをgitの追跡対象から外す
4. .gitignoreをGitHubにpushする

### 1. プロジェクトのルートディレクトリに.gitignoreを作成する

```
$ cd プロジェクトのルートディレクトリ
$ touch .gitignore
```

.gitignore作成後のディレクトリ構成例
```
├scr
├node_modules
.gitignore
```

### 2. .gitignoreにGitHubで管理したくないディレクトリを追加する
```.gitignore
# GitHubで管理したくないディレクトリをここに追加する

node_modules/
```

### 3. 対象のディレクトリをgitの追跡対象から外す
```
$ git rm -r --cache [追跡対象から外したいディレクトリ]
$ git rm -r --cache node_module
```

### 4. .gitignoreをGitHubにpushする
```
$ git add .
$ git commit -m "[commit message]"
$ git push origin [branch_name]
```
最後にGitHubに.gitignoreをpushすればGitHubからnode_moduleが削除されます。
また、今後もgitの管理下から外れます。

他にもGitHubで管理したくないディレクトリがある場合、上記と同じ手順で対照することが可能です。
[環境構築]簡単にDockerでJupyter Labを立ち上げる


#### まず、Dockerfileを作成します
```Dockerfile
# Dockerfile
FROM jupyter/base-notebook

USER root

RUN pip install -y pandas numpy

RUN pip install jupyterlab

USER jovyan
```
- pipを実行するために、USER rootを書きます
- Jupyter Labを起動するために、USER jovyanを書きます(jovyanはJupyter Labのデフォルトユーザー)


#### Jupyter Labのイメージを作成します (Dockerfileのディレクトリに遷移する必要)

```bash
docker build -t my-jupyter-lab .
```
- my-jupyter-labじゃなくても好きに命名していいです
- . は Dockerfileのあるディレクトリです

#### Jupyter Labを起動します

```bash
docker run -p 8889:8888 -v "$PWD":/home/jovyan/work my-jupyter-lab jupyter lab
```
- 8889はhostのportで、8888はコンテナのportです
- /home/jovyan/workはupyter Labのデフォルトディレクトリです

最後に、ブラウザを開き、http://localhost:8889 にアクセスして、Jupyter Labを使用できます。
起動するたびに、上記のコマンドを実行してください

#### また、コンテナを停止する場合は
```bash
docker stop container_id
```
を実行してください

#### container_id は

```bash
docker ps
```
で確認できます
ページ遷移しても状態を維持したい(Streamlit)

## はじめに
StreamlitはPythonだけでWebアプリケーションが作成できるフレームワークです。

https://streamlit.io

ナビゲーションバーなどを配置してマルチページのような構成をとることもできるのですが、あくまで単一の画面を再レンダリングしているだけなので元のページに戻ると内容がリセットされています。

今回はページ遷移しても同じ内容を保持する方法について記載します。




## デモアプリ
ナビゲーションバーを利用して異なる複数の機能を持つアプリケーションです。(multiselecterでdfの列を選択する）

ページを切り替えだ後、元のページに戻ってきても選択した内容が、切り替えた時点の状態で表示されます。

https://ppspps824-multipagee-state-multipage-state-if9knq.streamlit.app/

## やり方
```st.session_state```を使います。

https://docs.streamlit.io/library/api-reference/session-state


ポイントは以下３点です。

- すべてのウィジェットの入力値をst.session_stateで保持する。
- ウィジェットの初期値をst.session_stateにする。

```python:python
# st.session_stateで入力値を保持する
st.session_state.select1 = st.multiselect(
    "select",
    options=st.session_state.df.columns.values,
    key="s1",
    # 初期値をst.session_stateにする
    default=st.session_state.select1,
)
```
- st.session_stateの初期化時はウィジェットに応じた初期値を設定する。

```python:python
if "df" not in st.session_state:
    st.session_state.df = pd.DataFrame(
        data=np.random.randint(0, 10, (1000, 10)), columns=range(10)
    )
    st.session_state.select1 = []
    st.session_state.select2 = []
```

### コード全体

```python:multipage_state.py
import numpy as np
import pandas as pd
import streamlit as st
from streamlit_option_menu import option_menu

selected = option_menu(
    None,
    ["page1", "page2"],
    default_index=0,
    orientation="horizontal",
)


if "df" not in st.session_state:
    st.session_state.df = pd.DataFrame(
        data=np.random.randint(0, 10, (1000, 10)), columns=range(10)
    )
    st.session_state.select1 = []
    st.session_state.select2 = []


if selected == "page1":
    st.session_state.select1 = st.multiselect(
        "select",
        options=st.session_state.df.columns.values,
        key="s1",
        default=st.session_state.select1,
    )

    df = st.session_state.df[st.session_state.select1]
    st.dataframe(df)

if selected == "page2":
    st.session_state.select2 = st.multiselect(
        "select",
        options=st.session_state.df.columns.values,
        key="s2",
        default=st.session_state.select2,
    )

    df = st.session_state.df[st.session_state.select2]
    st.dataframe(df)

```

## おわりに
マルチページにしたはいいものの、ページを何回も行き来するのでいちいち内容が消えて欲しくない！というときに使えると思います。
LDAP オブジェクトクラスの３つの型

LDAPでのオブジェクトの単位であるエントリは、必ずオブジェクトクラスに属し、オブジェクトクラスによってエントリの実体(エントリが人を表すのか、組織を表すのかなど)が決定。

●オブジェクトクラスには以下の3つの型がある。
・ABSTRACT(抽象型) 他のオブジェクトクラスを定義するための基底クラス。抽象型クラスでのみエントリを作成することができない。
・STRUCTUAL(構造型)　人や組織等を表すオブジェクトクラス。エントリには必ず１つの構造型クラスが適用されている必要がある(変更不可)
・AUXILIARY(補助型)　構造型クラスと共に使用するオブジェクトクラス。複数適用可。構造型クラスでは足りない属性を補う。補助型クラスのみでエントリを作成することはできない。

※オブジェクトクラスや属性はスキーマファイルで定義。
OpenLDAPをパッケージからインストールした場合、スキーマファイルは「/etc/openldap/schema」ディレクトリなどに配置。
実録！Firebaseのセキュリティルールをテストをしていたときに遭遇したエラーを解決！

# はじめに

`@firebase/rules-unit-testing`を使って、セキュリティルールをテストするためのコードを書いていました。

その時に書いていたコードの内容は次の内容です。

```typescript
import "jest";
import * as fs from "fs";
import {
  initializeTestEnvironment,
  RulesTestContext,
  RulesTestEnvironment,
} from "@firebase/rules-unit-testing";
import {
  doc,
} from "firebase/firestore";
import { v4 as uuidv4 } from "uuid";


describe("テスト /users", () => {
  let testEnv: RulesTestEnvironment;
  let user: RulesTestContext;
  const projectId = uuidv4();
  const uid = uuidv4();
  beforeAll(async () => {
    testEnv = await initializeTestEnvironment({
      projectId: projectId,
      firestore: {
        rules: fs.readFileSync("../firestore.rules", "utf8"),
      },
    });
    user = testEnv.authenticatedContext(uid, {});
    // ...
  });

  afterAll(async () => {
    testEnv.cleanup();
  });

  it("テスト1", async () => {
    const ref = doc(user.firestore(), "users", uid);
    // ...
  });
  it("テスト2", async () => {
    const ref = doc(user.firestore(), "users", uid);
    // ...
  });
});
```

テストを実行してみると、２番目に実行されたテストが失敗していました。

```shell
テスト /users
    ✓ テスト1 (97 ms)
    ✕ テスト2 (129 ms)
```

しかし、テスト2のみを実行してみるとテストは通りました。

# エラーの内容

発生したエラーの内容は次の内容です。

```shell
FirebaseError: Firestore has already been started and its settings can no longer be changed. You can only modify settings before calling any other methods on a Firestore object.
```

# エラーの原因

色々試していくと、上記のエラーが発生した原因は次のコードにあることがわかりました。

```shell
  let user: RulesTestContext;
  const uid = uuidv4();
  // ...
  beforeAll(async () => {
    // ...
    user = testEnv.authenticatedContext(uid, {});
    // ...
  });

  it("テスト1", async () => {
    const ref = doc(user.firestore(), "users", uid);
    // ...
  });
  it("テスト2", async () => {
    const ref = doc(user.firestore(), "users", uid);
    // ...
  });
```

共通の`RulesTestContext`をテストケースごとに使い回して、`user.firestore()`をその度に呼び出していたことが上記のエラーが発生した原因であることが判明しました。

# 解決方法

そこで、`authenticatedContext()`の呼び出しをテストケースごとに行い、使い回しをやめることにしました。

```ts
it("テスト1", async () => {
  const user = testEnv.authenticatedContext(uid, {});
  const ref = doc(user.firestore(), "users", uid);
  // ...
});
it("テスト2", async () => {
  const user = testEnv.authenticatedContext(uid, {});
  const ref = doc(user.firestore(), "users", uid);
  // ...
});
```

結果、以前のコードで発生していたエラーは解消されました。
【備忘録】React-Calendar導入

## インストール方法

```zsh
# npmを使う場合
npm i react-calendar

# yarnを使う場合
yarn add react-calendar
```

## コード
:::note warn
`import 'react-calendar/dist/Calendar.css'`を入れないと
綺麗なカレンダーの見た目にならないので要注意
:::

### 基本的な使い方
```jsx:MyCalendar.jsx
import { useState } from 'react'
import Calendar from 'react-calendar'
import 'react-calendar/dist/Calendar.css' // カレンダーのcss

const MyCalendar = () => {
  const [value, setValue] = useState()

  return (
    <div>
      <Calendar
        value={value}
        onClickDay={(e) => setValue(e)}
      />
      <div>{value}</div>
    </div>
  )
}
```


### CSS
日曜日を週終わりにしている場合、以下のようなCSSを適用

```css:globals.css
/* 土曜日だけ青色にする */
.react-calendar .react-calendar__month-view__days__day--weekend:nth-child(7n-1) {
  color: #00F;
}

/* active時の文字の色（選択後の日付の色） */
.react-calendar__tile--active {
  color: white !important;
}

/* 土曜を全部青色にしても今月以外は灰色にする */
.react-calendar .react-calendar__month-view__days__day--neighboringMonth {
  color: #757575 !important;
}
```

## 実装画面

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017749/093e6657-9189-7a91-4f7f-95de8478f487.png)
【GAS】 変数/定数を宣言する

変数/定数　を宣言する場合の使い方
※縦の列で表現しています。



| var　  | let       | const     |
|--------|-----------|-----------|
|再代入可能| 再代入可能| 再代入不可|
|再宣言可能| 再宣言不可| 再宣言不可|
【Android】webviewにアプリで作ったヘッダーを入れ込みたい

# やりたいこと
こんな感じで、webviewとアプリ側のヘッダーを連結させる画面を作成しようとしていました。
今までLinearLayoutでヘッダーを上部に固定し、その下にwebviewを配置していたので、このような実装ができるか調べてみた次第です。
（紫の`Scrollable Header`がアプリ側で作成したヘッダー。その下のGoogleのページがwebview）
![タイトルなし.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1274260/c47ebdc2-d21b-7f09-ba79-115a8d3e7e60.gif)

# 解決策
ScrollViewを使うことでめちゃくちゃ簡単に解決しました。

```Sample.xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.appcompat.widget.LinearLayoutCompat
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <androidx.appcompat.widget.AppCompatTextView
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:background="@color/purple_200"
            android:text="Scrollable Header"
            android:textSize="32sp" />

        <WebView
            android:id="@+id/top_webview"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1" />
    </androidx.appcompat.widget.LinearLayoutCompat>
</ScrollView>

```

# 注意点
ScrollViewは子となるViewGroupを1つしか持てないので、LinearLayoutなりを配置しましょう。
MutationObserverで要素を監視

# MutationObserverとは？
MutationObserverはDOMの変化を監視することができます。

```
// 変更を監視するノードを取得
const targetNode = document.getElementById('targetId');

// オブザーバーのオプション
const config = { attributes: true, childList: true, subtree: true };

// MutationObserverオブジェクトを生成
const observer = new MutationObserver((mutations) => {
    mutations.forEach((mutation) => {
        // 変更があった時の処理
        console.log(mutation.type);
    }
};

// 監視をスタート
observer.observe(targetNode, config);

// 監視を停止したい時
observer.disconnect();
```

# オブザーバーのオプション
- childList - 要素の子要素
- subtree - 要素の全ての子孫に対する変更
- attributes - 要素の属性の変更
- attributeFilter - 指定したものだけを監視するため
SwiftUIを触ってみた Part2

今日はCSVの読み込みについてやってみたので備忘録を残しておく

CSVファイルの中のデータを二次元配列に入れる  
次のように47都道府県のコンマ区切りのデータを用意して、
前回作ったプロジェクトのContentViewと同じ階層に入れた
```SampleCSV.csv
都道府県,
北海道,
青森県,
岩手県,
...
```

# CSVの読み込み
```ContentView.swift
struct ContentView: View {
    @State var prefArray: [[String]] = []
    var body: some View {
        VStack {
            RoundedRectangle(cornerRadius: 35)
                .overlay(
                    Text("NEXT")
                        .foregroundColor(.white)
                        .frame(height: 100)
                )
                .foregroundColor(Color(red: 0.226, green: 0.646, blue: 0.953))
                .frame(width: 100, height: 50)
                .onTapGesture {
                    prefArray = loadCSV(fileName: "SampleCSV")
                    print("ラベル： \(prefArray[0][0])")
                    print("1番目の要素： \(prefArray[1][0])")
                    print("3番目の要素： \(prefArray[3][0])")
                }
        }
    }
    // csvを読み込む関数
    func loadCSV(fileName: String) -> [[String]] {
        var csvArray: [[String]] = []
        let csvBundle = Bundle.main.path(forResource: fileName, ofType: "csv")!
        do {
            let csvData = try String(contentsOfFile: csvBundle,encoding: String.Encoding.utf8)
            let lineChange = csvData.replacingOccurrences(of: "\r", with: "\n")
            var lineArray: [String] = lineChange.components(separatedBy: "\n")
            lineArray.removeLast()
            
            for line in lineArray {
                var dataArray: [String] = line.components(separatedBy: ",")
                dataArray.removeLast()
                csvArray.append(dataArray)
            }
        } catch {
            print("Cannot Load \"\(fileName)\"!")
        }
        return csvArray
    }
}
```

出力結果
```
ラベル： 都道府県
1番目の要素： 北海道
3番目の要素： 岩手県
```
【Git】初回コミットを修正する方法

## 修正方法
以下のコマンドを実行します。
```:ターミナル
$ git rebase -i --root
```

するとGitで設定しているエディタが開きます。
```
pick f2a0ijl 最初のコミット
pick 4d506gf 2回目のコミット
pick 23456a5 3回目のコミット
```

最初のコミットの`pick`の箇所を編集します。

```
r f2a0ijl 最初のコミット
pick 4d506gf 2回目のコミット
pick 23456a5 3回目のコミット
```
すると以下のようにエディタに表示されます。
```
最初のコミット

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.

```
コミットメッセージを変更して保存し、エディタを閉じます。
```
initial commit

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.

```

コミットメッセージが変更されたことを確認して`push`します。
```
$ git push -f origin main
```
【完全備忘録】githubからcloneしてきたプログラムをdocker環境で動かすまで

## githubからcloneしてきたプログラムをdocker環境で動かしたい
完全備忘録です。また同じことをする際に困らないために。
今回なぜかfinderからソースコードを消してしまうというアホなことをしてしまい急遽cloneすることにしました。
この辺知識がないので時間を見つけて学習していかなきゃではありますが、念の為備忘録として残します。

## githubを開きcloneの準備をする
![スクリーンショット 2023-01-14 23.33.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589286/e3fad4b4-622e-8182-ab66-fe3297457454.png)

- 緑色のcodeを押下し、SSHを選択。コピーしておく

## ターミナルを開きコードを打ち込む
```
git clone git@github.com:○○○○○○○○/○○○○○○○○.git
```
- アプリを置くディレクトリへ移動し、上記コードを打ち込む(git以降は先程コピーしたもの)
- 上記を打ち込むとcloneが実行されます。

## dockerで扱えるようにする
#### ①cloneしたディレクトリへ移動する
```
cd toreka_project
```

#### ②.env.exampleをコピーして.envを作成
```
cp .env.example .env
```

#### ③docker-compose.ymlファイルがlaravelディレクトリ直下にあるので、イメージをビルドしてコンテナを起動する。
```
docker-compose build
docker-compose up -d
```

#### ④コンテナに入ってcomposer install, migrateを実行して完了
```
docker-compose exec app bash
composer install
php artisan migrate
exit
```

#### ⑤動作確認
http://localhost にアクセスしてLaravelのWelcome画面（Laravelのロゴと文字、Laravel関連ドキュメントへのリンク等）が表示されればOK。

#### ⑥phpMyAdmin確認
http://localhost:8080 にアクセスしてphpMyAdminが正常に表示されればOK。


以上。
あくまで今自分が作っているアプリにおけるやり方です。
【C】初めてのC言語（24. 条件付きコンパイル - その2）

# はじめに

前回の「defineとifdef～endifを用いた条件付きコンパイル」に続いて、 @nagisep さんから教えて頂いた「if defined」を用いた条件付きコンパイルについて学んだ結果をまとめてみました。

# 学習環境

* 今回は[paiza.io](https://paiza.io/ja/projects/new)のC言語のエディタを使いました。

# if definedを使った例

* `if defined`を使った方が、より柔軟に条件分岐できるようです。
  * `ifdef`だと`if～else`節しか使えないようですが...
  * `if defined`だと、`if～else if～else`節が使えるので、複数のシンボル（※以下の例だとFOOとBAR）を使った条件分岐を実現できます。
* `if defined`の場合は、AND（&&）とOR（||）で複数の条件を使うことができます。
  * @nagisep さんも指摘されていましたが、これは`ifdef`には無い機能なので、`if defined`の方が便利な感じがします。


```c:Main.c
#include <stdio.h>

#define FOO
#define BAR

int main(void){
#if defined(FOO) && ! defined(BAR)
    printf("FOO\n");
#elif ! defined(FOO) && defined(BAR)
    printf("BAR\n");
#else
    printf("FOO BAR\n");
#endif
}
```

```text:実行結果
FOO BAR
```




# 補足：これまでの学習の歩み

* [【C】初めてのC言語（1. Hello world）](https://qiita.com/nkojima/items/518c1a4ec06861d74b3c)
* [【C】初めてのC言語（2. 四則演算とフォーマット指定子）](https://qiita.com/nkojima/items/36ea93b7296ce9e8a55b)
* [【C】初めてのC言語（3. ポインタ）](https://qiita.com/nkojima/items/825bb9f931016faccd68)
* [【C】初めてのC言語（4. 構造体）](https://qiita.com/nkojima/items/40a1101f2f6f5800bc2d)
* [【C】初めてのC言語（5. 関数）](https://qiita.com/nkojima/items/1fa3317c04f25fe24276)
* [【C】初めてのC言語（6. 配列）](https://qiita.com/nkojima/items/eda3ff6675b47e7ab5f0)
* [【C】初めてのC言語（7. for文）](https://qiita.com/nkojima/items/a5659098f7e5275a96ec)
* [【C】初めてのC言語（8. 2次元配列）](https://qiita.com/nkojima/items/f5eb25a4f8d1725faa89)
* [【C】初めてのC言語（9. 関数のプロトタイプ宣言）](https://qiita.com/nkojima/items/57318d74bdfa670bf72e)
* [【C】初めてのC言語（10. 構造体配列）](https://qiita.com/nkojima/items/75530a3ca63924a14397)
* [【C】初めてのC言語（11. ヘッダファイル）](https://qiita.com/nkojima/items/a10cd943ed66e0cea7fd)
* [【C】初めてのC言語（12. 3つのからくり構文＋ポインタ演算）](https://qiita.com/nkojima/items/83cb40ec01cd6a6e6a87)
* [【C】初めてのC言語（13. メモリを扱う標準関数）](https://qiita.com/nkojima/items/13c8d942f282beb3c212)
* [【C】初めてのC言語（14. ヒープの利用）](https://qiita.com/nkojima/items/837557cc86ce9697611a)
* [【C】初めてのC言語（15. sizeofの注意点）](https://qiita.com/nkojima/items/6c9a3ba04c6348219578)
* [【C】初めてのC言語（16. 文字列の基本）](https://qiita.com/nkojima/items/d87ce0cb15dd1a26f21a)
* [【C】初めてのC言語（17. 文字列リテラル）](https://qiita.com/nkojima/items/527ef37d84cf9b201dc5)
* [【C】初めてのC言語（18. 文字列の受け渡し）](https://qiita.com/nkojima/items/a07ac9a9bb3b41296f1e)
* [【C】初めてのC言語（19. 文字列とバッファオーバーフロー）](https://qiita.com/nkojima/items/4d9cec9e686aee41eec2)
* [【C】初めてのC言語（20. 文字列を扱う標準関数）](https://qiita.com/nkojima/items/12ac7b9b64baae1a67d1)
* [【C】初めてのC言語（21. コマンドライン引数と二重ポインタ）](https://qiita.com/nkojima/items/818b857c81fccdfe65c2)
* [【C】初めてのC言語（22. マクロ処理）](https://qiita.com/nkojima/items/b89cb01c759ecdb7165c)
* [【C】初めてのC言語（23. 条件付きコンパイル）](https://qiita.com/nkojima/items/6831ab77617925f121a0)

# 参考URL

* [条件コンパイル - プリプロセッサについて](http://www.02.246.ne.jp/~torutk/cxx/preprocessor/cpp1.html)
LaravelのEloquentでtoArrayを使う場合はタイムゾーン設定が反映されないことがある

# 結論
Eloquentのattributeが、config/app.phpのtimezoneの設定が反映されずにUTCで取得されることがあります。  
この条件は下記の通りです。  
- toArrayまたはtoJson呼び出し時
- $castsプロパティにてdatetimeへのキャストが設定されているattribute

必要に応じてModelクラスのオーバーライドなど対策を行いましょう。

# 環境など
Laravel9系

# 理由
$castsにてdatetimeへキャストを設定したattributeをjsonserializeする際、CarbonのtoJsonメソッドが呼ばれます。  
このメソッドは必ずUTCの値を返すため、結果としてEloquentのtoArrayやtoJsonメソッドの結果もUTCになってしまいます。  
  
CarbonのtoJsonを呼び出している箇所: \Illuminate\Database\Eloquent\Concerns\HasAttributes::serializeDate

# 対策例
\Illuminate\Database\Eloquent\Concerns\HasAttributes::serializeDateメソッドを任意の形式で返却するようオーバーライドしましょう。   
```
    protected function serializeDate(DateTimeInterface $date): string
    {
        return $date->format(DateTimeInterface::RFC3339);
    }
```
Danger-KotlinのDangerfileをIntelliJ IDEAやAndroid Studioで認識させるための魔法のXML

```xml:idea/kotlinc.xml
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="Kotlin2JvmCompilerArguments">
    <option name="jvmTarget" value="1.8" />
  </component>
  <component name="KotlinCompilerSettings">
    <option name="scriptTemplates" value="systems.danger.kts.DangerFileScript" />
    <option name="scriptTemplatesClasspath" value="/usr/local/lib/danger/danger-kotlin.jar" />
  </component>
</project>
```

## タネ明かし
[READMEのココ](https://github.com/danger/kotlin#autocomplete-and-syntax-highlighting-in-intellij-idea-or-android-studio)をやったら↑の`kotlinc.xml`ができたのでこれを使い回せばプロジェクトごとにこの作業をやらなくて済む。
Java, Springboot、Thymeleafの設定まで

<h4>・はじめに</h4>
　この記事では、Spring BootでのWeb開発の始め方について書いていきます。
　使用するIDE: IntelliJ IDEA

<h4>・Spring initializrからダウンロード</h4>
　<b>Spring initializr</b>は、Spring bootアプリケーションをはじめるためのキットをダウンロードできるサービスです。このページからひな形をダウンロードします。
    https://start.spring.io/

ビルドツールの選択はMaven, Project Metadataに設定を入力します。
Dependenciesではあらかじめフレームワークを簡単に組み込むことができます。ここで使いたいフレームワークを選ぶと、フレームワークが設定された状態でダウンロードができる。（ここで設定しなくても後から設定できる）

<h4>・Tomcatの設定</h4>
　右上にある現在のファイルをクリック⇒実行構成の編集⇒新規追加⇒アプリケーションを選択する。名前を`Tomcat`にしてビルドと実行の右にあるメインクラスを選ぶ。
　（※プロジェクトからアプリ名→src→main→java→アプリ名Application.(java)を選択）
これでローカル環境でサーバーが建てられて、アプリが実行される。

<h4>・Thymeleafを使う。</h4>
    <h5>・Thymeleafの設定</h5>
　ThymeleafはJavaとHTMLをつなげるものである。使用するには、pom.xmlに書き加える必要がある。(Spring Initializrであらかじめ設定することもできる)
pom.xmlの<b>dependenciesタグ</b>の中に

```Java:pom.xml
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
```

を入れると設定完了。

 <h5>・HTMLをThymeleaf用に変える</h5>
　　HTMLファイルのhtmlタグに`xmlns:th="http://www.thymeleaf.org"を入れると完了
ServiceNow パッチ適用プログラムについての補記

ServiceNowを運用すると毎月のPatch適用が面倒ですが、Now SupportがスケジュールするChangeチケット通りに対応すると、意外と工数がかからないことに気づきました。
このパッチ適用のスケジュール（適用プログラム）を説明している公式の<a href="https://support.servicenow.com/kb?id=kb_article_view&sysparm_article=KB1080515">KB1080515</a>が、ものすごくわかりづらいため、翻訳を翻訳してみます。

---
> <b>パッチ適用プログラムと、以前の四半期パッチ適用プログラムの違いは何ですか？</b>
> パッチ適用プログラムの強化により、四半期ごとに 1 つの完全版パッチと、四半期ごとに 2 つの増分セキュリティパッチが提供されるため、スケジュールが予測しやすくなります。以前の四半期パッチ適用プログラムでは、四半期ごとに 1 回、完全版パッチをインスタンスに適用していました。主に週末にパッチを適用できるようスケジュールし、業務の中断を最小限に抑えます。

早い話が、「1月、4月、7月、10月のパッチについては、指定のパッチ(パッチターゲット)（例：2023年1月はTokyo Patch4）バージョンのパッチ適用を計画するけど、その他の月はセキュリティアップデートだから差分が少ないので、パッチ適用に多くの工数をかけなくてもいいよ」という内容です。

> <b>パッチ適用プログラムはどのようにスケジュールされていますか？</b>
> 四半期開始の約 2 週間前に、サポートされている各リリースファミリの最低限のパッチバージョン (パッチターゲットとも呼ばれます) と、パッチおよび後続のセキュリティパッチを適用する期間を、ServiceNow からお客様にお知らせします。上位のパッチバージョンに移行するか、以前のパッチを適用するかを毎回選択できます。
> 四半期の最初の月に、ServiceNow はお知らせした最低限のパッチバージョンをすべてのインスタンスに適用します。ServiceNow が自動的にスケジュールし、インスタンスをそのバージョンに更新します。

ものすごく回りくどいですね。
12月、6月は20日くらい、3月と9月はファミリーリリース（メジャーバージョンアップ）があるので23日くらいに、Now Supportから指定のパッチバージョンを翌月にパッチ適用するスケジュールを案内するから、それぞれ1月、4月、7月、10月末までにProductionインスタンスに適用しなさい（Changeチケットでスケジュールする）ねって事です。

> 各四半期の 2 か月目と 3 か月目に、ServiceNow はセキュリティ脆弱性に対するパッチを適用します。この場合、インスタンスがセキュリティパッチバージョンに移行されるよう自動的にスケジュールされます。ServiceNow は、非本番インスタンスの場合は約 1 週間前に、本番インスタンスの場合は 3 週間前に変更を作成します。ここでも、上位のパッチバージョンに移行するか、以前のパッチを適用するかを選択できます。
> セキュリティパッチにはセキュリティ修正のみが含まれており、パッチターゲットバージョンに増分的に組み込まれます。たとえば、パッチターゲットが Quebec パッチ 6 で、セキュリティパッチが Quebec パッチ 6a の場合、2 つのパッチバージョンの違いは Quebec パッチ 6a のセキュリティ修正です。通常、セキュリティパッチの修正数は 5 件未満ですが、必要に応じて修正を追加する場合があります。 

再掲となりますが、1月、4月、7月、10月<b>以外</b>に実施される予定のパッチはセキュリティパッチとなるため、変化点が少なく、パッチ適用に対する工数削減が可能です。
私が手掛けていた過去の案件の場合、スモークテスト程度の簡単なテストで動作確認で済ませていました。

---
<b>まとめ</b>
- ServiceNowのパッチ適用のコツは12月、3月、6月、9月にNowSupportから連絡があるパッチに注力する
- もしバージョンアップを行う場合は上記パッチ適用のタイミングに合わせて実施すると楽
- 1月、4月、7月、10月<b>以外</b>に適用される予定のパッチはセキュリティパッチであり、差分が少ないため、可能な範囲で手を抜いて適用を行う

以前のServiceNowのパッチは、リリースノートに記載のない修正（例えば日本語訳の文言が書き換わる）など、確認のテストが面倒で、その時の悪夢から毎月の適用を避ける傾向にあるように感じます。
上記のポイントをおさえて対応を行うと、パッチバージョンがあがるタイミングは実質3か月に1回となるので、確認テストが楽になります。
なるべく、運用の手間を省いてセキュリティを担保できるよう、よりよい運用設計をしていきましょう。
はじめてのARC 中1の挑戦

## ARC153

こんにちは。中学1年生のhiroyuk1です。（https://atcoder.jp/users/hiroyuk1 ）いつもは土曜夜にABCがあるのでそっちをやってるんですが、なかったのでARCをやってみました。過去問は全然解けなかったけど、本番に強いタイプなので、頑張りました。結構解けました。
A問題は、0埋め6桁の文字列に変換して解こうと思ったけど、解けないパターンを思いついてしまいました。いろいろと試行錯誤して12分かかって解けました。（https://atcoder.jp/contests/arc153/submissions/38005481 )
B問題は、最初はあきらめてたけど40分ぐらいから考え始めて、グリッドを縦横に2倍した図を使っていろいろ考えました。そして気づいたんです。向き。そうだ。向きだ。向きによってスタート位置を変える。（https://atcoder.jp/contests/arc153/submissions/38012199 )　ってことでB問題は解けて、64分かかりました。
残りは、いろいろと考えたけど全く分かんなかったです。まあ公式解説読んでも分からないのは仕方ないか。ということで初めてのARCだったということでした。
package.json　自分用メモ

#___

```
{
  "name": "ts-basic-demo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "webpack --mode=production",　
// npmスクリプトと呼ばれるもので、上で記載されたものを起動
//webパックを使って、本番用のファイルをビルドする

    "start": "webpack-cli serve --mode development"
  },

  "author": "",
  "license": "ISC",
  "devDependencies": {
    "ts-loader": "^8.0.12",
    "typescript": "^4.1.3",
    "webpack": "^5.11.0",
    "webpack-cli": "^4.3.0",
    "webpack-dev-server": "^3.11.0"
  }
}
```
草莽Erlang ── 25. lists:max

口で言うより行うことがErlang習得への近道と信じています。

https://qiita.com/mnishiguchi/items/9237780e849d80a85e11

## 異なる型の比較

Erlangではどんな型の組み合わせでも大小の比較判定が可能です。

```erlang
number < atom < reference < function < port < pid < tuple < map < list < bitstring
```

https://www.erlang.org/doc/reference_manual/expressions.html#term-comparisons

## lists:max

```
max([term, ...]) -> term
max(リスト) -> 最大値
```

リストの最大値を求めます。どんなリストに対しても実行可能です

https://www.erlang.org/doc/man/lists.html#max-1

練習してみます。

```erlang
> lists:max([1, 2, 3, 4]).
4

> lists:max([1.0, 2, 3, 4]).
4

> lists:max(["1", {2, 3}, '4', #{x => 5}]).
"1"
```

[listsモジュール](https://www.erlang.org/doc/man/lists.html)には他にもリスト処理のための関数がたくさんあります。


## Elixirにも挑戦したい

闘魂ElixirシリーズとElixir Schoolがオススメです。

https://qiita.com/torifukukaiou/items/3b65e5c04fa8c55f526e

https://elixirschool.com/ja

https://qiita.com/piacerex/items/09876caa1e17169ec5e1