OmniAICreator/Qiita-1.07M huggingface dataset:
Elixirで定期実行 〜Quantum〜

# 今回の仕様
- 10秒に一度メッセージを表示
- 1分に一度メッセージを表示

# プロジェクト作成
スーパバイザツリーも一緒に作成
```
$ mix new quantum_experiment --sup
$ cd quantum_experiment
```
# quantum追加
```diff_elixir:mix.exs
defmodule QuantumExperiment.MixProject do
   # 〜省略〜
  defp deps do
    [
+     {:quantum, "~> 3.0"}
      # {:dep_from_hexpm, "~> 0.3.0"},
      # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
    ]
  end
   # 〜省略〜
end
```

```
$ mix deps.get
```

# 残りのソース

ここに定期実行するタイミングを設定します
```elixir:config/config.exs
import Config

config :quantum_experiment, QuantumExperiment.Scheduler,
  jobs: [
    {{:extended, "*/10 * * * *"}, {QuantumExperiment, :pirnt, ["10秒"]}},
    {"*/1 * * * *", {QuantumExperiment, :pirnt, ["1分"]}}
  ]

config :quantum_experiment, QuantumExperiment.Scheduler, debug_logging: false
```

```diff_elixir:lib/quantum_experiment/application.ex
defmodule QuantumExperiment.Application do
  # See https://hexdocs.pm/elixir/Application.html
  # for more information on OTP Applications
  @moduledoc false
  use Application

  @impl true
  def start(_type, _args) do
+   QuantumExperiment.pirnt("開始")
    children = [
      # Starts a worker by calling: QuantumExperiment.Worker.start_link(arg)
      # {QuantumExperiment.Worker, arg}
+     QuantumExperiment.Scheduler
    ]

    # See https://hexdocs.pm/elixir/Supervisor.html
    # for other strategies and supported options
    opts = [strategy: :one_for_one, name: QuantumExperiment.Supervisor]
    Supervisor.start_link(children, opts)
  end
end
```

```elixir:lib/quantum_experiment/scheduler.ex
defmodule QuantumExperiment.Scheduler do
  use Quantum, otp_app: :quantum_experiment
end
```

```elixir:lib/quantum_experiment.ex
defmodule QuantumExperiment do
  # 〜省略〜
  def pirnt(message) do
    "#{DateTime.utc_now()}:#{message}"
    |> IO.puts()
  end
end
```

# リリース&実行
```
$ MIX_ENV=prod mix release
$ _build/prod/rel/quantum_experiment/bin/quantum_experiment start
```

# 実行結果
```
2024-09-11 20:30:27.375304Z:開始
2024-09-11 20:30:30.377932Z:10秒
2024-09-11 20:30:40.377856Z:10秒
2024-09-11 20:30:50.377814Z:10秒
2024-09-11 20:31:00.377606Z:10秒
2024-09-11 20:31:00.377638Z:1分
2024-09-11 20:31:10.377778Z:10秒
2024-09-11 20:31:20.377745Z:10秒
2024-09-11 20:31:30.377790Z:10秒
2024-09-11 20:31:40.377637Z:10秒
2024-09-11 20:31:50.377805Z:10秒
2024-09-11 20:32:00.377843Z:10秒
2024-09-11 20:32:00.377906Z:1分
```
# ハマったこと
`mix run`は
```
2024-09-11 20:30:27.375304Z:開始
```
と表示後終了してします

`iex -S mix`は終了せずに動きました
余分な表示をさせない為に結果「リリース&実行」の方法にたどりつきました

# ソース(github)
https://github.com/ymn-t-yamanashi/quantum_experiment
M5StickC Plus2 のRTCを同期する

M5Unified を使ったRTC同期のソースコードが見つからなかったので書きました。

# ソースコード

``` cpp
#include "M5StickCPlus2.h"

#include <WiFi.h>
#include "time.h"
const char* ssid       = "wifiiiii";
const char* password   = "passssss";

void setup()
{
    // put your setup code here, to run once:
    M5.begin();
    M5.Lcd.setRotation(3);
    M5.Lcd.fillScreen(BLACK);
    M5.Lcd.setTextSize(1);
    M5.Lcd.setCursor(40, 0, 2);
    M5.Lcd.println("RTC NTP TEST");
    // connect to WiFi
    Serial.printf("Connecting to %s ", ssid);
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED)
    {
        delay(500);
        Serial.print(".");
    }
    Serial.println(" CONNECTED");
    // Set ntp time to local
    configTime(3600L * 9, 0, "ntp.nict.jp", "ntp.jst.mfeed.ad.jp");

    // 起動ごとに時刻同期するために同期タイミングを一時的に変更
    auto default_interval = sntp_get_sync_interval(); // ミリ秒単位
    sntp_set_system_time(1, 0);                       // 1秒

    // Set RTC
    struct tm timeInfo;
    if (getLocalTime(&timeInfo))
    {
        M5.Rtc.setDateTime(timeInfo);
    }

    sntp_set_system_time(default_interval * 1000, 0); // 同期タイミングを戻す

    // disconnect WiFi
    WiFi.disconnect(true);
    WiFi.mode(WIFI_OFF);
}

void loop()
{
    M5.Lcd.setCursor(0, 30);
    M5.Lcd.printf("Data: %04d-%02d-%02d\n", M5.Rtc.getDate().year, M5.Rtc.getDate().month, M5.Rtc.getDate().date);
    M5.Lcd.printf("Time: %02d : %02d : %02d\n", M5.Rtc.getTime().hours, M5.Rtc.getTime().minutes, M5.Rtc.getTime().seconds);
    delay(500);
}
```

# 処理内容の説明

* setup()
  * WiFiに接続する
  * NTPの同期タイミングを変更する（デフォルトで3時間？）
  * NTPサーバーに接続し、ローカルの時刻を更新する
  * ローカルの時刻をもとにRTCの時刻を更新する
  * NTPの同期タイミングを戻す
* loop()
  * RTC から取得した日時を、500ミリ秒ごとに表示する

# はまりポイント

同期タイミングを変更せずに時刻更新を行うと、Wifiが常時接続されていない＆常時起動しておくための装置ではないため、時刻同期が全然行われない。
時刻同期が行われないままgetLoclTime()をすると、M5Stickを起動するたびに、時差分の9時間ずつ時計がずれていく。
そのため起動時には必ず時刻同期を行うようにする。


# 参考にさせていただいたサイト

* https://lang-ship.com/blog/work/m5stickc-rtc-ntp/#google_vignette
* https://rikoubou.hatenablog.com/entry/2021/04/09/181612
* https://lang-ship.com/blog/work/m5stickc-rtc-ntp/
* https://take4-blue.com/program/arduino%EF%BC%8Desp32%E3%81%AEntp%E6%8E%A5%E7%B6%9A%E3%81%A7%E6%99%82%E5%88%BB%E8%A8%AD%E5%AE%9A/
Elixirで実行ファイルをビルドする 〜escript〜

# 今回作る実行ファイルの仕様
- 足し算と引き算ができる
- 足し算: ./escript_experiment --add --v1 値 --v2 値
    ```:実行例
    ./escript_experiment --add --v1 10 --v2 2
     12 
    ```
- 引き算: ./escript_experiment --sub --v1 値 --v2 値
  ```:実行例
  ./escript_experiment --sub --v1 10 --v2 2
  8
  ```
- 上記以外はエラーメッセージを表示
  ```:実行例
  ./escript_experiment --s --v1 10 --v2 2
  引数が間違っています
  ```

# プロジェクト作成
```
$ mix new escript_experiment
$ cd escript_experiment
```

# ソースを書く
```elixir:lib/escript_experiment_cli.ex
defmodule EscriptExperiment.CLI do
  def main(args \\ []) do
    args
    |> OptionParser.parse(strict: [add: :boolean, sub: :boolean, v1: :integer, v2: :integer])
    |> calculation()
    |> IO.puts()
  end

  defp calculation({[add: true, v1: v1, v2: v2], [], []}), do: v1 + v2
  defp calculation({[sub: true, v1: v1, v2: v2], [], []}), do: v1 - v2
  defp calculation(_), do: "引数が間違っています"

end

```

```elixir:mix.exs
defmodule EscriptExperiment.MixProject do
  use Mix.Project

  def project do
    [
      app: :escript_experiment,
      version: "0.1.0",
      escript: escript()
    ]
  end

  # Run "mix help compile.app" to learn about applications.
  def application do
    [
      extra_applications: [:logger]
    ]
  end

  defp escript do
    [main_module: EscriptExperiment.CLI]
  end

end  
```

# ビルド
```
$ mix escript.build
```

# 実行
```
$ ./escript_experiment --add --v1 10 --v2 2
12
$ ./escript_experiment --sub --v1 10 --v2 2
8
$ ./escript_experiment --s --v1 10 --v2 2
引数が間違っています
```

# ソース(github)

https://github.com/ymn-t-yamanashi/escript_experiment
L-tek dance padをコントローラーとして利用する場合について(windows向け)

## はじめに
コナステ版DDRやstepmaniaを頑張っている人には認知されているであろう L-Tek dance padについての記事です。
入力を読み取ってコントローラー化したい人向けの内容です。 (そんなやついるのか...?


### コントローラーの入力について
pythonを使い、調べている限りだと３つの値を保有しているリストとしてコントローラーの入力が管理されている。
コントローラーの入力は、パネルを押した時と離した時に発生しており、下のような入力が発生している。

##### 入力例：[1,2,0]
押しているペダルの管理だが、入力例のリストの真ん中の値(入力例では2)で押しているペダルを管理している。
各ペダルには数字が割り振られており、押しているペダルに紐づけられた数字の合計により押しているペダルを管理することができる。

##### パネルごとの数字について
左パネル：1 、右パネル：２、上パネル：４、下パネル：８

### パネルと値の変動についてのイメージ
・左パネルのみを押した場合(左:1)
[1,0,0]→[1,1,0]

・左パネルを押しつつ、次に右パネルを押した場合(左:1、右:2)
[1,0,0]→[1,1,0]→[1,3,0]
左と右を踏んでいるため最終的には合計した３の値になる

・左右のパネルを踏んだ状態から、右パネル→左パネルの順に足を離した場合
[1,3,1]→[1,1,0]→[1,0,0]

・全パネルを踏んだ場合について
[1,15,0]
※1+2+4+8=15

##### 同時に踏んだ場合について
4枚同時に踏んだら、[1,0,0]→[1,15,0]となるように思えるが、完璧に同時に踏むことは不可能であり、実際には４枚のパネルを順番に踏んでいると認識されるため、[1,0,0]→[1,2,0]→[1,3,0]→[1,11,0]→[1,15,0]というような値の変化になる。

読み取る値の更新時間のようなものを設定したら[1,0,0]→[1,15,0]のような遷移もいけるかもしれません。


## ソースコードを書く前に必要なこと
今回はpythonのHIDをpipでインストールしてプログラムを作成しています。
HIDでは入力を読み取るためにデバイスのID的なやつを読み取る必要があります。
windows10だと、デバイスマネージャー→ヒューマンインターフェースデバイス→HID標準ゲームコントローラー→右クリックしてプロパティを表示→詳細→ハードウェアID　という流れで調べることができます。
ハードウェアIDの一番上に表示される値を利用します。

ハードウェアIDの利用方法についてですが、筆者が実際に表示された値を使い解説します。
##### 実際に表示された値:HID\VID_03EB&PID_8041&REV_0100&Col01
この値の 03EB(ベンダーID)と8041(プロダクトID)を利用します。


## 作成したプログラム
押したパネルや離したパネルに対応した数字の差分を利用して押したパネルや話したパネルを特定しています。
パネルに割り当てられている数字は２進数の値で管理されているため同時に踏まれているパネルの状態などを特定することもできます。

同時踏まれているパネルの計算例
・合計3→左と右のパネルが踏まれている
・合計11→左、右、下のパネルが踏まれている

```python:test.py
import hid
import keyboard 

# デバイスのリストを取得
for device in hid.enumerate():
    print(device)
    
# ダンスパッドのベンダーIDとプロダクトIDを確認
vendor_id = 0x03EB  # ダンスパッドのベンダーIDに変更
product_id = 0x8041  # ダンスパッドのプロダクトIDに変更

# デバイスをオープン
gamepad = hid.device()
gamepad.open(vendor_id, product_id)

# 非ブロッキングモードに設定
gamepad.set_nonblocking(True)



Last_Input=[1, 0 ,0]

# 入力を読み取る
while True:
    #read(デバイスから読み取りたいデータの個数を入れる)
    #l-tek padの場合は３つの値をまとめたリストで最大なので3以上の数を設定する
    New_Input = gamepad.read(10)
    
    #入力などを感知したら
    if New_Input:
        print(f'Report: {New_Input}')
        #押された場合について
        if New_Input[1]>Last_Input[1]:
            #押されたパネルの特定
            if New_Input[1]-Last_Input[1]==1:
                #keyboard.press_and_release('a') 
                print("左押した")
            elif New_Input[1]-Last_Input[1]==2:
                #keyboard.press_and_release('b') 
                print("右押した")
            elif New_Input[1]-Last_Input[1]==4:
                #keyboard.press_and_release("c")
                print("上押した")            
            elif New_Input[1]-Last_Input[1]==8:
                #keyboard.press_and_release('d') 
                print("下押した")
         
        
        #離した場合について
        if Last_Input[1]>New_Input[1]:
            #離したパネルの特定
            if Last_Input[1]-New_Input[1]==1:
                print("左離した")
            elif Last_Input[1]-New_Input[1]==2:
                print("右離した")
            elif Last_Input[1]-New_Input[1]==4:
                print("上離した")            
            elif Last_Input[1]-New_Input[1]==8:
                print("下離した")

        
        Last_Input=New_Input 


```
Auth.jsのv5でLINEプロバイダーを使用してsignInするとエラーになる'state' is not specified. 

# 問題
AUth.jsのv5を使って以下のコードでsignInを呼び出しても、エラーとなる。
日本語で書かれている記事も無かったため、誰かのためになればと思い記載。

#### エラー内容
error=INVALID_REQUEST
error_description='state' is not specified. 

#### 問題のコード
```
export const { handlers, signIn, signOut, auth } = NextAuth({
  providers: [LINE({
    clientId: process.env.AUTH_LINE_ID,
    clientSecret: process.env.AUTH_LINE_SECRET,
  })],
}
```

# 解決策
providersのLINEのパラメータに``checks:["state"]``を追加する。
具体的には以下の通り。

#### 解決したコード
```
export const { handlers, signIn, signOut, auth } = NextAuth({
  providers: [LINE({
    clientId: process.env.AUTH_LINE_ID,
    clientSecret: process.env.AUTH_LINE_SECRET,clientSecret: process.env.AUTH_LINE_SECRET、
    checks:["state"],
  })],
}
```

# 参考サイト
https://github.com/nextauthjs/next-auth/issues/9596
EC2のApache2からFlaskを使わずにPython+seleniumを実行する方法メモ

# はじめに
タイトル通りの内容。
躓いたし、どうせ今後も忘れた頃にやるだろうから対処方法を残す。
多分WindowsやWSLなどでも同様の対処で動くはず。

# 結論
1. `pip install chromedriver-autoinstaller`を実行
2. 以下のように書く
```python
import chromedriver_autoinstaller as chrome_inst
from selenium import webdriver
chrome_inst.install()
driver = webdriver.Chrome()
driver.get("<URL>")
```

`chromedriver-autoinstaller`はchromeのバージョンを自動で合わせてくれるライブラリなので、様々な問題がこれで解決する。
以上。

# 発生した問題
なぜか`webdriver.Chrome()`の部分でタイムアウトが発生する。
具体的なエラーは以下のとおり。
```
selenium.common.exceptions.SessionNotCreatedException: Message: session not created: Chrome failed to start: crashed.
  (timeout: Timed out receiving message from renderer: 60.000)
  (The process started from chrome location /var/www/.cache/selenium/chrome/linux64/128.0.6613.137/chrome is no longer running, so ChromeDriver is assuming that Chrome has crashed.)
```

色々調べた結果、これの根本的な原因がchromeのバージョン不一致によるものらしい。
ということで、それを自動調節してくれる上記ライブラリを使用することで解決できた。

なお、Apache2から以下のようにvenvのPythonを実行する場合は権限に注意する。
```php
$ret = exec("env/bin/python main.py")
```

具体的には、`chromedriver-autoinstaller`が`/var/www/.local`を使用するため、そこに対して[この記事](https://qiita.com/yuu1111main/items/77976d7ece0ecfb35157)を参考に権限を付与する。
合わせて、`/var/www/.cache`をseleniumが使用するため、ここにも権限を付与する。
2回やるのが面倒なら、先に両フォルダを作ってから`/var/www`に対して権限を付与すれば良い。
セキュリティ的なところは知らん。自己責任でよろしく。
【Go】配列(スライス)などの値を標準出力でデバッグするときは、エスケープして出したほうがいいかもという話

普通に出力した場合
```go
arry := []string{"a b", "c", "d"}
fmt.Println(arry)
// [a b c d]
```
"a b" は一つのアイテムであるが、普通に出力するとアイテムごとに空白で区切られてしまうので分かりづらい。

エスケープして出してみる
```go
arry := []string{"a b", "c", "d"}
fmt.Println(fmt.Sprintf("%#v", arry))
// []string{"a b", "c", "d"}
```
printf系の関数を使って、書式指定子を `%#v` とする。
`#`をつけることで、Go構文表現のままで出力してくれるので認識しやすい。

参考にしたもの
https://qiita.com/KEINOS/items/9bf8d33b0c616f85ba4a
https://pkg.go.dev/fmt
Pixel Watch間でのSuica移行手順

## TL;DR
~~スマホ側のアプリから移行元のSuicaを削除して、~~ 移行先でSuicaを復旧させる。
これを書いているときに気づいたが、両方手元にある場合、多分そもそも削除する必要が無い。(すっごい楽じゃん……知らんかった……)

## 経緯
Pixel Watchを初代→3へ更新し、Suicaを移行しようとしたのだが、スマホ↔Pixel Watch、物理Suica→Pixel Watch等の移行記事は多くあるものの、Pixel Watch↔Pixel WatchのSuica移行手順はかろうじて1つ見つかるだけだった。
(それもコメントとして残っているだけで手順とは呼び難い。)
そのため、こうしてメモを残しておく。


## 手順 (両方手元にある場合、恐らく2から可能)
1. (手放す際などには1から) 移行元Pixel WatchのSuicaを削除
    * スマホのGooglePixelWatchアプリでGoogleウォレットを開き、Suicaの詳細画面へ行く
    * 「スマートウォッチからカードを削除します」を選択 
    (Googleウォレット側のサーバへ保存されるらしい？)
    <img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3328036/998c80d3-bf89-d6ef-aacc-33bca5cff724.png">
    
    <img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3328036/3a300b74-6d6f-eb16-969c-636dc7c8b018.png">
        

1. (両方手元にある場合ここから可) 移行先でSuicaを復旧
    * 手順通り移行先Pixel Watchをセットアップ
    * スマホのGooglePixelWatchアプリでGoogleウォレットを開き、「スマートウォッチに追加」→「新しいカードを追加」→ 「Suica」→「別デバイスから移行する」で別デバイスに保存されているSuicaを選択

    * 削除した場合
    <img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3328036/9a9f2070-6246-e9ab-fb29-30b8bcda9fbb.png">


    * 削除していない場合 (試しに3→1へ戻そうとしてみた)
    <img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3328036/1321c94a-2608-a835-5776-f20eaf1c8cb1.png">

以上。
削除しない場合の手順を実際行ったわけではないので、「違うんだが？教えてやるか……」という心優しい方がいましたらご指摘ください。
決してめんどくさがったわけではないです。決して。

## 参考
- [価格.com - 『既存のモバイルsuicaからの移行について』 Google Pixel Watch 2 Wi-Fiモデル のクチコミ掲示板](https://bbs.kakaku.com/bbs/J0000042676/SortID=25581286/)

### 余談
(Pixel Watch 3 45mm 画面がデカくていい。最近Galaxy Watchが強いのでもっと頑張ってほしい。)
【ProxmoxVE】apt-get出来ない環境での追加パッケージ確認方法

本番環境での利用を想定した場合、セキュリティ上の制限などでインターネット上のリポジトリへアクセスすることができない場合もあると思います。
そのような環境でパッケージを追加したい場合に、入手すべきパッケージバージョンと依存関係の確認方法を模索し試してみました。

ProxmoxVEバージョンは8.2-1です。

大丈夫だとは思いますが、各種サイトへのアクセスやファイルのダウンロードは自己責任で。

### 背景
別途記事にする予定ですが、Proxmoxは標準では通知機能が少なく（Sendmail、SMTP、Gotifyの3つ）、私が見てきた範囲の運用監視で利用することが多いSyslog・SNMPが使えないことから、rsyslog・snmpdをProxmoxへ導入しようとしたことがきっかけです。
ですがProxmoxVEの場合、インストールメディア内にはProxmoxとして必要なパッケージしか含まれていないようで、少なくとも導入を試そうとしたrsyslog、snmpdは見つかりませんでした。

おそらく通常のDebian系Linuxであれば、インストールメディアを使うことで、インターネットアクセスが出来なくても一通りのパッケージ導入ができると思います。

### 導入したいパッケージのバージョン確認方法
１．アーキテクチャの確認
 「apt list」コマンドにてインストール済パッケージのアーキテクチャを確認します。
 私の環境（ProxmoxVE、Intel Core i7）の場合はamd64でした。
 
２．/etc/apt/sources.list の内容を確認
 「deb http://ftp.jp.debian.org/debian bookworm main contrib」
 のようにURLやディストリビューションなどが記載されています。
 上記の場合は
 ・ディストリビューション：bookworm
 ・コンポーネント：main, contrib
 を表しているようです。

３．該当するサイトへアクセス
 上記の場合は「 http://ftp.jp.debian.org/debian 」へアクセスし、
 dists > bookworm > main > source とリンクをたどります。
 要は「 https://ftp.jp.debian.org/debian/dists/bookworm/main/source/ 」です。

４．Sourcesに記載されているパッケージバージョンを確認
 上記URLから「Sources.gz」をダウンロードし、展開したSourcesファイルをテキストテキストエディタで開くと、パッケージに関する情報が確認できます。
 rsyslogならこんな感じ。
```
Package: rsyslog
Binary: rsyslog, rsyslog-mysql, rsyslog-pgsql, rsyslog-mongodb, rsyslog-elasticsearch, rsyslog-kafka, rsyslog-gssapi, rsyslog-gnutls, rsyslog-openssl, rsyslog-relp, rsyslog-czmq, rsyslog-hiredis, rsyslog-snmp, rsyslog-kubernetes
Version: 8.2302.0-1
～～以下省略～～
```
 この「Version」に記載されているバージョンが、導入すべきバージョンになるようです。
 一応、インターネット利用可能なProxmoxVEでapt listにて確認したバージョンと一致していました。

５．パッケージ入手
 rsyslogを導入した際のサイトですが、下記サイトにて依存関係も確認できるので、rsyslog本体と依存しているパッケージを確認しながらダウンロードしました。
 https://packages.debian.org/bookworm/rsyslog
 ほかにも「 https://debian.pkgs.org/ 」などいくつかのサイトがあるようです。

### 最後に
当然ですが、インターネット接続可能な環境であればapt-getのほうがずっと楽です。
また、導入する環境がインターネット接続不可でも、自宅等インターネット接続可能な環境でProxmoxVEを構築できる場合は、バージョン確認だけでもapt listで確認したほうが楽ですし、確実だと思います。
CORSとプリフライトリクエストについて

## 1. はじめに
CORS（Cross-Origin Resource Sharing）は、Webアプリケーション開発において重要な仕組みであり、CORSエラーを経験したことがある方も多いかと思いますが、そもそもCORSとは何なのか、その仕組みとエラーの解決方法について、業務でエラーになってしまったため記録として記事を残します。

## 2. オリジンとは？
CORSを理解するためには、まず「オリジン」の概念が重要です。**オリジン**は、URLの**スキーム**（http/https）、**ドメイン**、**ポート番号**の組み合わせで構成されます。例えば、以下の2つのURLは異なるオリジンとみなされます

- `https://example.com`
- `http://example.com:8080`

ブラウザは、異なるオリジン間でリソースのやり取りをデフォルトで許可していません。これをセキュリティの観点から制御するために導入されたのが**CORS**です。

## 3. CORSの基本的な仕組み
CORSは、あるオリジンのウェブページが別のオリジンのリソースにアクセスする際、サーバー側がそのリクエストを許可するかどうかを制御する仕組みです。

例えば、`https://siteA.com`から`https://siteB.com`のAPIにデータをリクエストする場合、`siteB.com`のサーバーがCORSヘッダーで許可を行います。

### 代表的なCORSヘッダー
- **Access-Control-Allow-Origin**: どのオリジンがリクエストを許可されているか（例: `https://example.com`または`*`）。
- **Access-Control-Allow-Methods**: 許可されたHTTPメソッド（例: `GET`, `POST`, `PUT`）。
- **Access-Control-Allow-Headers**: 許可されたカスタムヘッダー（例: `Authorization`, `Content-Type`）。
- **Access-Control-Allow-Credentials**: クッキーなどの認証情報を許可するか（例: `true`）。

## 4. プリフライトリクエストとは？
特定の状況下で、ブラウザは**プリフライトリクエスト**というものをサーバーに送信します。これは、実際のリクエストを送る前に、そのリクエストが許可されているかどうかを確認するためのものです。`OPTIONS`メソッドを使用して、サーバーにアクセス可能かを問い合わせます。

プリフライトリクエストが必要になる条件：
- HTTPメソッドが `GET` や `POST` 以外の場合（例: `PUT`, `DELETE`）。
- カスタムヘッダーを使用している場合。

## 5. CORSエラーの原因と解決策
CORSエラーは、サーバーが適切にCORSヘッダーを返さなかったり、ブラウザが期待する設定がなされていない場合に発生します。以下は、よくあるCORSエラーの原因と解決策です。

### よくあるCORSエラー
- **`Access-Control-Allow-Origin`が設定されていない**: サーバーがリクエスト元のオリジンを許可していない場合。
- **プリフライトリクエストが拒否される**: `OPTIONS`リクエストに対して適切なヘッダーを返さない場合。
- **認証情報が送れない**: `Access-Control-Allow-Credentials`が`true`に設定されていない場合、クッキーなどの認証情報は送信できません。

### 解決策
- サーバー側で`Access-Control-Allow-Origin`を設定し、必要なオリジンを許可する。
- 使用するメソッドやヘッダーをサーバーで明示的に許可する。
- 認証情報を含める場合は、`Access-Control-Allow-Credentials: true`を追加し、オリジンを`*`ではなく特定のオリジンに設定する。

## 6. まとめ
CORSは、Webセキュリティを確保するための重要な仕組みですが、正しく設定されていないと開発中にエラーを引き起こす可能性があります。

サーバー側で適切にCORSヘッダーを設定し、リクエストの内容に応じた処理を行うことが、エラーを回避するための鍵です。

## 7. 参考
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
linux(Rocky Linux 9)にCloudflareを導入する方法

### Cloudflare WARPのインストールと設定手順

このガイドでは、CentOSにCloudflare WARPをインストールし、設定する手順を示します。

#### 1. リポジトリの追加

まず、Cloudflare WARPのリポジトリを追加します。

```bash
curl -fsSl https://pkg.cloudflareclient.com/cloudflare-warp-ascii.repo | sudo tee /etc/yum.repos.d/cloudflare-warp.repo
```
参考リンク: [Cloudflare WARPリポジトリの追加](https://pkg.cloudflareclient.com/)

#### 2. パッケージの更新とインストール

次に、パッケージのリストを更新し、Cloudflare WARPをインストールします。

```bash
sudo dnf update
sudo dnf install cloudflare-warp
```

#### 3. Cloudflare WARPの設定と接続

Cloudflare WARPを設定し、接続を行います。

```bash
warp-cli registration new
warp-cli connect
```

接続が成功したことを確認するには、以下のコマンドを実行して`warp=on`と表示されることを確認します。

```bash
curl https://www.cloudflare.com/cdn-cgi/trace/
```
参考リンク: [Cloudflare WARPのセットアップと確認](https://developers.cloudflare.com/warp-client/get-started/linux/)

#### 4. `warp-cli mode` の使用方法

`warp-cli mode`コマンドで利用可能なモードを確認し、適切なモードに切り替えることができます。各モードの説明は以下の通りです。

- **warp**: CloudflareのWarp VPNを使用します。
- **doh**: DNS over HTTPS（DoH）を使用します。
- **warp+doh**: Warp VPNとDoHの両方を使用します。
- **dot**: DNS over TLS（DoT）を使用します。
- **warp+dot**: Warp VPNとDoTの両方を使用します。
- **proxy**: プロキシモードを使用します。
- **tunnel_only**: トンネル専用モードを使用します。

モードのヘルプを表示するには、以下のコマンドを実行します。

```bash
warp-cli mode --help
```

これで、Cloudflare WARPのインストールと設定が完了です。
Kotlinのinvoke()ってなに？

# ざっくり言うと
- invoke()が付いていた場合はメソッド名は無く、クラス名を使って呼び出している
→Android Studioで呼び出し元を知りたければ、クラス名をctlキーを押しながらクリックする

# もう少し詳しく
- invoke()は、メソッド名を省略できると言う意味の方が近いカモ
（メソッド名が無くても呼び出せるし、「invoke()」とインスタンス名に続けて書くこともできる）
- 例外として、インスタンスがnullableな場合は、省略ができなかったりする

```kotlin:省略ができない例
hogeHogeClass?invoke()
```
【AWS】EBS ストレージタイプまとめ


| タイプ | ユースケース | 
| --- | --- | 
| 汎用SSD | ・ 仮想デスクトップ<br>・S3の中では<font color="darkorange">**一番コストが高い**</font> | 
| プロビジョンドIOPS<br> (io1, io2) | ・ 64,000IPOS, 1,000MB/s スループット<br>・S3の中では<font color="darkorange">**一番コストが高い**</font> | 
| プロビジョンドIOPS<br> (io2 Block Express) | ・ 超高性能なデータ処理用<br>・256,000IPOS, 4,000MB/s スループット<br>・<font color="darkorange">**コストよりも性能**</font> が優先される場合に選択 | 
| スループット最適化HDD | ・プロビジョンドIOPSに比較して性能は落ちるものの、コスト最適を求める場合に選択 | 
| コールドHDD | ログやアーカイブなど、利用頻度の低いデータ | 
| マグネティック | 古い世代のタイプで基本利用しない |
意外と忘れていたJavaScriptの書き方

## 始めに
reactやtypescript、Rails7の仕様になれるため、JavaScriptの復習を基礎から行っているが案外抜けていた考えがあったので備忘録として、、、

## 参考著書
以下の書籍を参考にさせていただきました！
(アフィリンクじゃないよ!!)

https://www.amazon.co.jp/%E3%82%B9%E3%83%A9%E3%82%B9%E3%83%A9%E3%82%8F%E3%81%8B%E3%82%8BJavaScript-%E6%96%B0%E7%89%88-%E6%A1%9C%E5%BA%AD-%E6%B4%8B%E4%B9%8B/dp/4798173266/ref=sr_1_1?crid=3NIFQ1ZY68WO1&dib=eyJ2IjoiMSJ9.s6yblccBqbnFS6APztGBhDABxnlz2la3ZXJ9o5kxDdB6IHdL2SoKbrJp5Z4uvc8P8KP_Tj_FB7CfQvtzzGoaxGB5kKG9muNIArwi2iWMcOyXPbJ7yjFamOjZhxk2ld56SK-YclTOpm_XYkGdUJ2Ds3z5UL7x2hHKF4czZ7StXbuQFcRJ8i5htCJOJU0ggQE6bDhjWla15MjJq7F2nwZsbXB29tUV2b1gyCni0HvEolN669zzw5iIhy6q6zOprs2RPM69cFreWf5AUFYDZW1to85YXT87YLc4XNhdw8SrdZg.9-qFvp-T2JrocaulDxAc52-yXbHjVaJZxzB0vtLreRQ&dib_tag=se&keywords=%E3%82%B9%E3%83%A9%E3%82%B9%E3%83%A9%E3%82%8F%E3%81%8B%E3%82%8Bjavascript&qid=1726068116&sprefix=%E3%82%B9%E3%83%A9%E3%82%B9%E3%83%A9%E3%82%8F%E3%81%8B%E3%82%8B%2Caps%2C162&sr=8-1

## console.log()の出力
```JS
console.log('hoge');
```
これで出力できるが他に
```JS
// ;を補完してくれる（風習的にはNG）
console.log('hoge')
```
```JS
// あからさまNGだがこれでも出力される
console    .      log('hoge')
```
これらも出力される

## エスケープ処理
以下の文章を修正する。
```JS
// NG
let text = '私は'Javascript'を学ぶ'
```
```JS
// エスケープする
let text = '私は\'Javascript\'を学ぶ'
```
一部''を""に変えればいいじゃーんと思っていたがそうでもなかった。
ちなみにバクスラはmacだと**option+¥**

呼び出すなら
```js
`今日、${text}活動をします`
```
こんな感じ

## 式の概念
- 式は値を返すもの
- 宣言は式ではない
この概念から
```js
'name'
```
は式。
ちなみに

10 + 20 = 30
の

10と20は**オペランド**、
+は**オペレーター**という名称がある。
オペランドの数に応じて二項演算子、単項演算子と呼び名が変わる。

## 配列イディオム
```JS
// 配列の要素数を取得
配列.length
```
```JS
// 配列の末尾に追加
配列.push('hoge')
```

```JS
// 配列の最後を抜き取る
配列.pop()

const hoge = ['a','b','c'];
const last = hoge.pop();
console.log(last);

// 結果
c
// もとの配列は減る 
['a','b']
```

```JS
// 含まれるか確認
配列.includes(要素)
// true/falseで返る
```

```JS
// 配列を１つの文字列にする
配列.join(区切り文字)

const hoge = ['a','b','c'];
const a = hoge.join('と');
console.log(a);

// 結果
aとbとc
```

```JS
// 文字列から配列へ
文字列.split(区切り文字)

const hoge = 'a,b,c';
const a = hoge.split(',');
console.log(a);

//結果
[a, b, c]
```
金融ITのお勉強をしてみた2

[前回](https://qiita.com/tanaka2645/items/92475802645013bd1a71)の続き。

Fintech,BaaS,EmbeddedFinance 等の用語整理から日本におけるFintechの実例を調べてみる。

住信SBIネット銀行　NEOBANK　を中心に調査。

# 住信SBIネット銀行　NEOBANKとは
公式サイト

https://www.netbk.co.jp/contents/

https://www.netbk.co.jp/contents/neobank/

公式サイトより抜粋。
> 住信SBIネット銀行は、開業以来の取り組みで培った最先端のテクノロジーと金融のノウハウを活用し、パートナー企業へ銀行機能を提供するBaaS（Banking as a Service）プラットフォームによって、新たな付加価値の創造を目指す「NEOBANK」サービスを推進しています。
2020年のNEOBANKサービス提供開始以来、10社を超えるパートナー企業との提携・サービス展開をしており、多くのお客さまにご利用いただいております。

現在は18のパートナー企業にBaaSを提供している。
（直近では、2024年7月1日にケイアイスター不動産と「ゆたかバンク」を公開している）

# サービスの構造

```plantuml
@startuml
actor ユーザー
participant "非金融企業" as NonFinCompany
participant "BaaSプロバイダー" as BaaS
participant "銀行" as Bank

ユーザー -> NonFinCompany: サービス要求
NonFinCompany -> BaaS: BaaS API呼び出し
BaaS -> Bank: 銀行API呼び出し
Bank -> BaaS: 金融サービス提供
BaaS -> NonFinCompany: サービス結果
NonFinCompany -> ユーザー: 結果表示
@enduml
```
この構造とNEOBANKの構造を考えると、
銀行＋BaaSプロバイダーが"住信SBIネット銀行"で、
非金融企業がその"パートナー企業"、
ユーザーは非金融企業のサービスを受けていたユーザーとなる。

https://www.yamada-denki.jp/service/neobank/

例えばヤマダNEOBANKでは、ユーザーはヤマダ電機の顧客を指す。

ヤマダホールディングスが提供する家電や家具などの自社製品の購入を促し、
ヤマダNEOBANK自体で稼がなくてもヤマダホールディンクス全体の経済圏の規模を拡大、安定させるためのピースとして活用するとのこと。

導入した結果はどうだったのだろうか？決済資料を見てみる。

https://www.yamada-holdings.jp/ir/presentation.html

ヤマダNEOBANKに対しての記載は多くない。家電や住宅ローンなどの抱き合わせの商品開発は行っているが、ヤマダNEOBANK自体では稼いでおらず、また売り上げ・経済圏の拡大に寄与できているかの分析はあまり行っていないようにみえる。
また、導入初年度には書かれていた口座数についても導入翌年度からは触れられておらず、サービス自体がどれだけ使われているのかも判断できない。


直接の稼ぎを目標にしていない分、アウトカムの設定が難しく、計測指標が設定しにくい　＝　撤退の判断が難しい、やめることができない。サービスといえるかもしれない。

実際の銀行の支店では、支店がなくなったとしても実際に利用には問題は出ないようになっているが、
仮にヤマダNEOBANKをたたむとなった時、住信SBIネット銀行の1口座として利用できるのか？様々なサービスはどうなるのか？という点は非常に気になる。

非金融企業としては、金融業に手を出すハードルを下げているBaaSなのかもしれないが、
そこに1度手を出すと、引くことは難しい。。。のかもしれない。

実際にサービス停止したBaaSの例も気になる。次はそれを調べてみる。
リベンジハッカソン


## 目次
1. ハッカソンの概要
2. 前回のハッカソンの課題
3. 制作物
4. ハッカソンを通して学んだこと
5. これからの課題

## 1. ハッカソンの概要
今回参加したのはサポーターズさん主催のハッカソン vol.8！  
作成物は自由。  
私はエンジニアの友達がいないので、4人の即席チームで参戦しました。チームのメンバーたちはハッカソン初めてでアプリの制作したことない人が2人、実務エンジニア経験のある人は1人と私でした。

技育キャンプの記事: [こちら](https://x.com/geek_pjt/status/1812434333220933875?s=46&t=hxjk70Akf81vhMIHEAZyIQ)

## 2. 前回のハッカソンの課題
実際に todo リストではありますが、TypeScript で Express と Prisma を使ってバックエンドも書いて作りました。

1. Supabase や Firebase などの SaaS に頼らずバックエンドも開発し、一通りのアプリ開発を体験し、バックエンドの知識を構築することで、アプリケーション開発知識をつける。
   - 実際に todo リストではありますが、TypeScript で Express と Prisma を使ってバックエンドも書いて作りました。
   - [クライアントリポジトリ](https://github.com/Naoki-ganbarimasu/todolist-fullstack-client)
   - [サーバーリポジトリ](https://github.com/Naoki-ganbarimasu/todolist-fullstack-server)

2. IT 系の記事を読み込み、基礎知識を定着させる。仕事で使う用語や IT 用語を使いこなすレベルまで持っていく。
   - 単語は Qiita や Zenn で記事を読んで勉強しましたが、量が多くてどのくらい定着したのかは不明。

## 3. 制作物
私たちが作ったのは『IT Words』というエンジニアを目指す人向けに毎日少しずつコンピュータサイエンスを学べるクイズアプリです。IT 用語がたくさんあってわかりにくいし、新しい単語も出るため、IT の単語アプリがあったら便利だろうという話になり、制作に至りました。  
バックエンドは経験豊富なつよつよに任せて、フロントエンドは Figma を使い、私を中心に開発を進めました。

- Figma の詳細: [こちら](https://www.figma.com/design/R2VErZEdW2F4OEpXvSoYQ2/Untitled?node-id=0-1&node-type=canvas&t=NQ3O5qXp7uobzDb0-0)
- 発表資料: [こちら](https://www.canva.com/design/DAGK1ND_7kk/-ouyxV1VT2nvn2Cc0yi8rg/view?utm_content=DAGK1ND_7kk&utm_campaign=designshare&utm_medium=link&utm_source=viewer)

## 4. ハッカソンを通して学んだこと
普段は個人開発をしているので、改めて「チーム開発っていいよな」と感じました。  
今回はオンラインでのハッカソンで、みんな学生で隙間時間を利用しての制作だったため、進捗報告や各メンバーの開発時間管理（学業との兼ね合い）をミーティングで話し合い、計画的に進めることができました。これにより、マネージメントの勉強にもなりました。

## 5. これからの課題とまとめ
### 技術を高める！
今回のハッカソンで他のチームの完成度が高すぎて、自分の技術力のなさに気づきました。負けてられません💪

課題について言語化できずに悩んでいます。今後もハッカソンなどのイベントに参加し、自分の足りないところを明確化していきたいと思います。
鉄筋の詳細設計について詳しく解説：初心者向けガイドとその重要性

鉄筋の詳細（Rebar Detailing）は、建物や構造物の耐久性と強度を向上させるための重要なプロセスです。コンクリート自体は引張力には弱いため、鉄筋を使って補強する必要があります。鉄筋の詳細設計について理解することで、構造物の安全性と効率性を高めることができます。

## 鉄筋の詳細設計とは？
鉄筋の詳細設計は、コンクリート構造物に必要な鉄筋の配置、数量、種類を決定し、その具体的な図面や指示を作成するプロセスです。この設計は、建設現場で鉄筋を効果的に埋め込むために重要であり、構造物の強度と安定性を最大化する役割を果たします。

### 鉄筋の詳細設計の目的
鉄筋の詳細設計には、いくつかの主要な目的があります。

* 構造的な整合性：鉄筋の詳細設計は、荷重を均等に分散させ、ひび割れや曲げ、その他の損傷を防ぐために、鉄筋を適切に配置することを確保します。
* 建設効率の向上：正確な設計により、建設チームは補強作業をより効率的に実行でき、エラーの発生や再作業の必要性を減らすことができます。
* コスト管理：詳細な設計により、必要な鉄筋の正確な数量を見積もることができ、無駄を省き、コストを削減することができます。

## 鉄筋の詳細設計の主要な要素
鉄筋の詳細設計には、慎重に考慮すべきいくつかの重要な要素があります。

1. 鉄筋曲げスケジュール（BBS）
鉄筋曲げスケジュール（Bar Bending Schedule）は、構造物に必要な各鉄筋の種類、サイズ、形状、数量を指定する包括的なリストです。このスケジュールには、鉄筋の切断と曲げの寸法が記載されており、各鉄筋が所定の位置にぴったりと収まるように設計されています。これにより、材料の無駄を最小限に抑え、鉄筋の製作と配置のための明確な計画を提供します。

2. 鉄筋の配置と間隔
鉄筋の配置と間隔は、鉄筋コンクリート構造物の性能にとって重要です。設計は、各鉄筋の正確な位置を指定し、構造物が圧縮、引張、せん断などの荷重に耐えることを考慮します。適切な間隔は、特定のエリアに応力が集中するのを防ぎ、構造的な失敗のリスクを減少させます。

3. 重ね継ぎとアンカー
重ね継ぎ（Lapping）は、必要な長さを維持するために2つの鉄筋を重ねることを指し、アンカーは鉄筋がコンクリート内にしっかりと埋め込まれることを確保します。どちらも鉄筋の詳細設計の重要な側面であり、構造全体の補強の連続性と安定性を確保します。お客様のニーズに合わせたプロフェッショナルな設計サービスで、施工の精度を高め、[コストを削減しましょう。詳細は鉄骨製作図面をご覧ください](https://www.steeldetailing.com.au/working-drawings-and-shop-drawings-services/)。

## 鉄筋の詳細設計の重要性
### 規格遵守の確保
専門的な鉄筋の詳細設計は、建築基準法や規制への遵守を確保するために不可欠です。異なる地域や建築物の種類によって、特定の基準に従う必要があります。詳細設計者は安全で法的に適合するプランを作成するために、これらの基準を熟知している必要があります。

### 構造安全性の向上
正確な鉄筋の詳細設計は、構造物全体の安全性に大きく貢献します。設計の不備があると、コンクリート内部に弱点が生じ、倒壊や重大な損傷のリスクが高まります。反対に、詳細に計画された鉄筋の配置は、地震や強風などの環境要因に対する構造物の耐久性を高めます。構造的完全性とコンプライアンスを確保するために設計された専門的な鉄筋詳細サービスにより、[建設プロジェクトの精度と品質を向上させます。詳細は鉄筋詳細設計をご覧ください](https://www.steeldetailing.com.au/rebar-detailing-scheduling/)。

### 鉄筋の詳細設計における一般的な課題
鉄筋の詳細設計は、その重要性にもかかわらず、いくつかの課題を伴います。

* 設計の複雑さ：現代の建築デザインは複雑な補強パターンを必要とすることが多く、正確な設計が困難です。
* 調整の問題：設計は、配管、電気、空調システムなどの他の建設要素と調整する必要があります。これにより、設置時の競合を避けることができます。
* 人的ミス：設計のミスは、建設中にコストのかかるエラーを引き起こし、プロジェクトの予算やスケジュールに影響を与える可能性があります。

鉄筋の詳細設計は、コンクリートを使用したあらゆる建設プロジェクトにおいて不可欠な要素です。これは、強度、安定性、安全性を確保し、コスト管理と廃棄物削減に役立ちます。鉄筋の詳細設計について理解することで、建設の専門家は計画、設計、そして長い耐用年数を持つプロジェクトの実行をより良く行うことができます。
oh-my-zshをinstallしたらasdfでinstallしたものが使えなくなった

## 起きている事象
oh-my-zshをinstallしたらnpm commandが使えなくなりました。
:::note info
oh-my-zshとは
Zshシェルのためのカスタマイズと管理を容易にするフレームワークです。
私はGit commandをタブ補完して欲しくてinstallしました。
:::
```
➜  ~ asdf list
nodejs
 *22.6.0

// asdfでnodejsをinstallしている
 
➜  ~ npm  
zsh: command not found: npm

// npmが使えない

➜  ~ which npm
npm not found

➜  ~ which nodejs
nodejs not found
```

## 解決した方法
私はbashでinstallしたasdfのnodejsがoh-my-zshをinstallしたことにより使えなくなっていました。
ちゃんと公式サイトにZshの場合のinstall方法が書いてありました。
以下のコマンドを叩き、.zshrcにasdf.shを追加したらOKです。
```
echo -e "\n. $(brew --prefix asdf)/libexec/asdf.sh" >> ${ZDOTDIR:-~}/.zshrc
source ~/.zshrc
```

## 参考サイト
公式サイト: 
https://asdf-vm.com/ja-jp/guide/getting-started.html#:~:text=%E4%B8%8B%E8%A8%98%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%A7%E3%80%81~/.zshrc%E3%81%ABasdf.sh%E3%82%92%E8%BF%BD%E5%8A%A0%E3%81%97%E3%81%BE%E3%81%99%3A

## JISOUのメンバー募集中！
プログラミングコーチングJISOUでは、新たなメンバーを募集しています。
実践的なカリキュラムで、あなたのエンジニアとしてのキャリアを最短で飛躍させましょう！
興味のある方は、ぜひホームページからお気軽にカウンセリングをお申し込みください！
https://projisou.jp/
[スレッド] ファーミング戦略をバリデーターにアウトソースする [Berachain翻訳]


:::note info
本記事は下記の翻訳となります。
[『[Thread] Outsourcing farming strategy to validators』](https://blog.berachain.com/blog/thread-outsourcing-farming-strategy-to-validators)
:::

## Proof of Liquidity の見過ごされがちだがクールな側面

> Proof of Liquidity の見過ごされがちだがクールな側面

> バリデーターが dapps から独自トークンでインセンティブを受け取り、そのインセンティブを委任者と共有できるため、ユーザーは今や自分の yield farming 戦略を完全にバリデーターにアウトソースすることができます。pic.twitter.com/2GtSg7dLnK

https://x.com/camiinthisthang/status/1826692027679211689

> ユーザーは自身のリスクプロファイルに基づいてバリデーターを選択し、新しいトークンの評価や購入に伴うすべてのプロセスを、より洗練された主体に完全にアウトソースしながら、そのメリットを享受することができます。

https://x.com/camiinthisthang/status/1826692080816849298

> これは非常に強気な見方だと思います。なぜなら、通常は効果的なファーミングができないかもしれない多くの未経験ユーザーが、特別な優位性や内部知識などを必要とせず、自分のリスクプロファイルに合うと判断したトークンを受け取り始めることができるからです。ファーミングの初心者ですか？Berachain がこれを解決します。

https://x.com/camiinthisthang/status/1826692136521355603

---

:::note info
【Sunrise とは】
Sunrise は Proof of Liquidity(PoL)と Fee Abstraction（手数料抽象化）を備えたデータ可用性レイヤーです。 私たちは DA の体験を再構築し、多様なエコシステムからのモジュラー型流動性を活用してロールアップを立ち上げています。

- [Sunrise - Specialized DA Layer for Proof of Liquidity](https://sunriselayer.io/)
- [Sunrise / Gluon Docs](https://docs.sunriselayer.io/)

【Social Links】

- [X(旧 Twitter)[英語])](https://twitter.com/SunriseLayer)
- [X(旧 Twitter)[日本語])](https://twitter.com/SunriseLayer)
- [Discord Community](https://discord.com/invite/sunrise)
- [Medium](https://sunriselayer.medium.com/)
- [Github](https://github.com/sunriselayer)
- [Linkedin](https://www.linkedin.com/company/sunriselayer)

【お問合せ】
Sunrise へのお問い合わせはこちらから 👉 [Google Form](https://forms.gle/h8RVahxRtXUvYwnv6)

![1080x360.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3839047/8971d83b-3331-4757-dc72-320d28618735.jpeg)

:::
WindowsからMacにSSH接続する

こんにちは。

WindowsからMacにSSH接続をしたくなったので、手順を紹介します。

といっても、Macで少し設定をいじるだけです。

# 実行環境

- サーバーOS：MacOS Squoia(15.0)
- クライアントOS：Windows11

# 手順

## Macでの操作

[システム設定] -> [一般] -> [共有] を開きます。

![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3325175/59d64fc7-4980-494d-92ae-43e146730973.png)

リモートログインをオンにします。

![図2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3325175/46557a1e-a75e-0f34-77f1-487a76bcfa82.png)

リモートログインの横のiマークを選択し、"ssh xx@xxx.xxx.x.x"の部分をメモってください。

![図3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3325175/b6b2afc2-54ff-bde0-ba0e-a26680654cd6.png)

## Windowsでの操作

コマンドプロンプトやPowerShellなどを開きます。
先ほどメモをした"ssh xx@xxx.xxx.x.x"を入力します。
パスワードを聞かれるので、Macを起動する際に使うパスワードを入力しましょう。
これで接続完了です。

![図4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3325175/87843a03-0c69-15b9-12da-092f98aca240.png)

# 最後に

いかがでしたでしょうか。

WindowsからMacへのSSH接続は意外と簡単にできますね。

MacからWindowsにSSH接続をしたい場合は、以下の記事が参考になると思います。

https://qiita.com/aki-743/items/607af5c4b40fcd8ff47c
【初心者】仕事をちょっと効率化するコマンドプロンプトのテクニック

## はじめに
通常のWindows操作では時間がかかることも、コマンドプロンプトを使えば一瞬でできたりします。
たまに使いたくなった時に毎回コマンドを探すのも手間なので、簡単なリファレンスとしてまとめておきます。

## 

### フォルダ構成だけコピー　【XCOPY】
```bat:中のファイルを除いてフォルダだけをコピー
xcopy /t /e コピー元フォルダ コピー先フォルダ
```
たとえば作業に使ったフォルダを次の作業でも雛形として使いたいとき。
エクスプローラーと違い、コマンドプロンプトではコピーの動作を細かく指定できます。
上記のような記法を使えば、ファイルはコピーせずフォルダ構成のみコピーするといった挙動を実現できます。

### 一括リネーム　【REN】
```bat:フォルダ内のすべてのファイルの拡張子をtxtに変更
ren * *.txt
```
システムから出力された拡張子がついていないファイルを規定の拡張子に変更しないといけないときなど。
ファイルを1つ1つ手でリネームしていくしかないシチュエーションで、ワイルドカードを使った一括リネームが役立ちます。

### ファイル名一覧取得　【DIR /b】
```bat:ファイル一覧をクリップボードに出力
dir /b | clip
```
ファイル名一覧がクリップボードに入った状態になるので、テキストエディタやExcelに通常通り貼り付けて利用できます。
<br>

```bat:ファイル一覧をテキストファイルに出力
dir /b > fileList.txt
```
カレントフォルダ直下にfileList.txt（任意のファイル名）を作成し、その中にファイル名一覧を出力します。

## おわりに
コマンドプロンプトを使った作業の効率化についてまとめてみました。
また新しいテクニックに触れたら随時追加していきます。

## 参考記事
- [【Windows】ファイルはコピーせずにフォルダ構成のみをコピーする方法｜もりさんのプログラミング手帳](https://moripro.net/windows-xcopy/)

- [フォルダ内のファイル名の一覧を簡単に取得する方法(Windows)｜スタッフブログ｜株式会社インソースマーケティングデザイン](https://insource-mkd.co.jp/staff-blog/10903/)
WSL上のnpmコマンドがある日突然見つからなくなった件

WSL上のUbuntu24.04LTSにNode.jsをインストールして使っていたnpmコマンドが、ある日突然実行できなくなりました。

fnmを使ってインストールしたものなのですが、シェル起動時のランコマンドにパスを追加する処理があり、その中でエラーが起きていました。

```sh:.bashrc
# fnm
FNM_PATH="/home/kr/.local/share/fnm"
if [ -d "$FNM_PATH" ]; then
  export PATH="$FNM_PATH:$PATH"
  eval "`fnm env`"
fi
```
```
error: Can't create the symlink for multishells at "/run/user/1002/fnm_multishells/11058_1726029612715". Maybe there are some issues with permissions for the directory? Permission denied (os error 13)
```

上記のエラーが原因でnpmコマンドにパスが通っていないようでした。

エラーに書いてるパスを調べてみると、

`/run/user/1002/fnm_multishells`というディレクトリが存在していませんでした。

ですので、以下のコマンドを実行して、ディレクトリを作成して実行ユーザに読込み権限を与えることで解決しました。

```sh
sudo mkdir /run/user/1002/fnm_multishells
sudo chown -R {ユーザ名} /run/user/1002
```

参考：https://github.com/Schniz/fnm/issues/1119
【Mac】ショートカット.appを使用してPDFのファイルサイズを小さくする方法

## 「PDFのファイルサイズを最適化」を使用する

「PDFのファイルサイズを最適化」を使用するとPDFを圧縮できます。

![スクリーンショット 2024-09-11 23.52.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/51194f23-c6a8-9e65-7dfc-05d13993f259.png)

![スクリーンショット 2024-09-11 23.52.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/740cebab-11fc-5262-d3d9-cb60bc6b4e81.png)

## 「PDFページから画像を作成」を使用する

「PDFページから画像を作成」を使用して解像度を低く設定することでファイルサイズを小さくすることができます。

![スクリーンショット 2024-09-11 23.53.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/90ecd779-e78f-6f06-fabd-ffe2864f3172.png)

![スクリーンショット 2024-09-11 23.51.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/802c4e97-5b29-a084-932d-cce95fe656d3.png)
Git何もわからん。ReactのフォルダをPushさせてくれ。

## GithubにローカルフォルダをPushをしたい
GithubにPushすれば、何かいいことがあるらしい。
今回はローカルで作成していたReactアプリのフォルダをPushした。

## 手順
ブランチを移動・なければ作成する。
```  
git checkout ブランチ名 

#ブランチの作成されてない場合は以下。
git checkout -b ブランチ名 
```

ローカルフォルダの準備
すでに作成したReactプロジェクトのフォルダに移動します。
```
cd フォルダ名
```
Gitリポジトリを初期化します。
```
git init
```
GitHubで作成したリポジトリをローカルリポジトリに紐づけます。
```
git remote add origin https://github.com/あなたのユーザー名/リポジトリ名.git
```
ReactプロジェクトをGitHubにpushする
すべてのファイルをステージングエリアに追加します。
```
git add .
```
ファイルをコミット（保存）します。
```
git commit -m "初めてのコミット"
```
GitHubにpushします。
```
git push -u origin ブランチ名
```
これでローカルのReactプロジェクトがGitHubにアップロードされる。

## 余談
OpenAIのAPIキーはGithubにアップロードされると、勝手に検知してそのAPIキーは使用不可になることを知った。
あまりに偉い。
Helpfeel Cosense を使ってみた

# Helpfeel Cosense を使ってみた

https://cosen.se/product

## はじめに

はじめまして。

この記事では、[Helpfeel Cosense](https://cosen.se/product) というサービスを使って、使い方・できることをまとめたいと思います。

この記事が、皆さんのお役に立てれば幸いです。

## Helpfeel Cosense とは

![Helpfeel Cosense](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3836663/99187dc2-c242-931d-4c7b-a465e62c316e.png)


### Helpfeel Cosense の前身サービス

![Scrapbox](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3836663/d5f1145c-c059-0246-e9a0-19c9af274579.png)

#### Scrapbox の独自性

- 高い検索性

- 書きやすさ・読みやすさを追求した UI

- チャット感覚のコミュニケーション

#### 変更理由

名称からは、人とのつながりが想起しにくく、本サービスの本質的な価値を十分に伝えられていないというジレンマを抱えていました。

### ナレッジイネーブルメントツール「Helpfeel Cosense」とは

https://corp.helpfeel.com/news/pressrelease-20240521

「Helpfeel Cosense」は、2024 年 5 月 21 日に「Scrapbox」 というサービスから名称変更されたサービスです。

「Helpfeel Cosense」は、メモ帳のようなライトな書き心地と充実した分析レポートにより、組織にドキュメント文化を定着させます。

#### Helpfeel Cosense の特徴

- 新人でも情報を見つけられる検索機能

- メモや会話がそのまま組織のナレッジに

- 成果を可視化することで変化を促進する分析レポート

## 使い方

### 初期設定

以下のサイトからアカウント作成を行ってください。

:::note info
Google アカウントが必要です。
:::

https://scrapbox.io/login/google

その後、「Username」などを設定することができます。

### 新しいページの作り方

- 上部にある「+」ボタンを押す

- 自分で設定した「Project URL」の後に「new」を入力すると作ることができます。（例：`https://scrapbox.io/qiita/new`）

### ページの書き方

#### ページタイトル

一番最初の行に書いた内容が「ページタイトル」に設定されます。

```text:ページタイトルの例
ページタイトルを設定してみた

ここでは、ページタイトルの設定方法を学びます。
```

上記の例では、「ページタイトルを設定してみた」がページタイトルとして設定できています。

#### 基本的な使い方

##### 段落

行頭にスペースまたはタブを入れて段落を作ることができます。

```text:スペースを使って段落を作る
スペースを使って段落を作る

 スペースで段落を作ることができます。
 タブでも段落を作ることができます。
```

```text:タブを使って段落を作る
タブを使って段落を作る

    タブで段落を作ることができます。
    スペースでも段落を作ることができます。
```

##### `[]` と `#`

`[]` や `#` を使うことで、他のページに飛ぶことができます。

```text:角括弧を使って他のページを参照する
`[]` を使って他のページを参照する

ページタイトルは、[ページタイトルを設定してみた]を参照してください。
```

```text:ハッシュを使って他のページを参照する
`#` を使って他のページを参照する

ページタイトルは、 #ページタイトルを設定してみた を参照してください。
```

:::note warn
`#` を使う時は、`#参照したいページタイトル`の前後に半角スペースを入れてください。
:::

`[]` の中に画像 URL や動画 URL を書くと画像や動画を表示できます

```text:Youtube の動画を表示する
Youtube の動画を表示する

[https://www.youtube.com/watch?v=FpBSZc7IyPg]
```

## 所感

Helpfeel Cosense を使ってみた感想として、Markdown 記法よりも簡単に使いこなせるサービスだと思いました。
また、参照したリンクがページの下部に示されているため、一目で関連情報がわかる点がよかったです。

## おわりに

この記事では、Helpfeel Cosense を使ってみました。

この記事が、エンジニアとして活躍する皆様に貢献できたら幸いです。
【Serverless Framework】Windows環境にインストール

# 実行環境
OS：Windows11 Home 23H2
Node.js：20.17.0

# Node.jsインストール

公式サイトからLTSバージョンのmsiをダウンロードし、インストール
「node-v20.17.0-x64.msi」
公式サイト
https://nodejs.org/en/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3615802/2ab22b0b-4435-4f8f-d1c6-71849530fd3c.png)

・インストール確認
node- v
```php:コマンドプロンプト
C:\Users>node- v
v20.17.0
```

# Serveless Frameworkインストール

・インストール
npm install -g serverless

```php:コマンドプロンプト
C:\Users>npm install -g serverless

added 57 packages in 3s

15 packages are looking for funding
  run `npm fund` for details
npm notice
npm notice New patch version of npm available! 10.8.2 -> 10.8.3
npm notice Changelog: https://github.com/npm/cli/releases/tag/v10.8.3
npm notice To update run: npm install -g npm@10.8.3
npm notice
```

・インストール確認
serverless --version
```php:コマンドプロンプト
C:\Users>serverless --version

Serverless ϟ Framework

 • 4.2.5
```
AWS Control Towerとは

## AWS Control Towerとは
マルチアカウントの環境をセットアップ・管理するためのマネージドサービス。

https://aws.amazon.com/jp/controltower/


具体的には、、

### 1.マルチアカウント環境を迅速に設定
適切に設計された**マルチアカウント環境を 30 分以内にセットアップ**する。
### 2.オートメーションと組み込みガバナンス
組み込みのガバナンスで**AWS アカウントの作成を自動化**する。
### 3.事前設定済みのコントロール
事前に構成されたコントロールを使用して、**ベストプラクティス、標準、規制要件を適用**する。
### 4.サードパーティーのソフトウェアを大規模に統合
**サードパーティーソフトウェアを大規模にシームレスに統合**して、AWS 環境を強化する。

## 料金
AWS Control Tower は**追加料金なしで利用できる**。
ただ、AWS Control Tower をセットアップすると、ランディングゾーンおよび必須のコントロールをセットアップするように設定された AWS のサービスの費用が発生。
一部の AWS のサービスは追加料金がかからないが、
- AWS Service Catalog
- AWS CloudTrail
- AWS Config
- Amazon CloudWatch
- Amazon Simple Notification Service (Amazon SNS)、
- Amazon Simple Storage Service (Amazon S3)
- Amazon Virtual Private Cloud (Amazon VPC) 
などのサービスの料金が、これらのサービスの使用量に基づいて発生する。

## 特徴
- 1.ランディングゾーン
AWS Control Tower では、新しいランディングゾーンのセットアップを自動化する。 

::: note info
ランディングゾーンとは、
セキュリティとコンプライアンスのベストプラクティスに基づいた、Well-Architected による**マルチアカウントの AWS 環境**。
:::

- 2.Account Factory
アカウントファクトリーは、設定可能なアカウントテンプレートとして、新しいアカウントのプロビジョニングを標準化するのに役立つ。
::: note info
アカウントファクトリーとは、
組織内の新しいアカウントのプロビジョニングを自動化するもの。
:::

- 3.包括的なコントロール管理
コントロールを使用することで、特定のガバナンスポリシーが AWS 環境に適用され、AWS Organizations の組織単位 (OU) 内で有効になる。
コントロールには、検出的、予防的、積極的があるが、必須でも任意でもいい。

::: note info
コントロールは、
セキュリティ、オペレーション、コンプライアンスに関するあらかじめパッケージ化されたガバナンスルール。
:::

- 4.ダッシュボード
AWS Control Tower ダッシュボードでは、AWS 環境を継続して視覚的に確認できる。
プロビジョニングされた OU とアカウントの数や、有効化なコントロール数を表示したり、OU とアカウントのステータスをそれらのコントロールと照合できる。
 
::: note info
有効なコントロールに関して、違反しているリソースをリストとして確認することもできる。
:::
AWS で React アプリを作成して公開する方法

# 概要
この記事は、下のサイトを参考にやってみて、つまづいた箇所の説明を詳しく書いたものです。
＊ AWSに慣れるため、開発環境もEC2に作成するという無駄なことをしてますが、ご容赦ください。

https://aws.amazon.com/jp/getting-started/hands-on/build-react-app-amplify-graphql/module-one/

# 環境
事前に準備した以下の環境を用いています。
- **AWS EC2**
使用しているOSはAmazon Linuxです。OpenSSH がプリインストールされています。
 gitをインストールしておきます
```
sudo yum install -y git
```

# gitHub リポジトリの作成
1. gitHub でリポジトリを作成

2. EC2インスタンスに作成したリポジトリをクローン
＊ この記事では、gitHub と SSHを介してやり取りするので、SSH用のアドレスでリポジトリをクローンしておきます
```
git clone git@github.com:{ユーザー名}/{リポジトリ名}.git
```

# EC2 から gitHub への SSH 接続設定
参考サイト

https://qiita.com/shizuma/items/2b2f873a0034839e47ce

### EC2インスタンスで Key Pair を作成
```
ssh-keygen -t rsa -f ~/.ssh/id_{KeyPair名}
```
KeyPair名は任意に設定してください
作成された Key Pair は ~/.ssh に保存されます

### SSHへの秘密鍵の登録
SSH を起動し、作成した Key Pair の秘密鍵を登録します
```
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_{KeyPair名}
```
上記を .bashrc に記載しておくと、シェル起動時に実行されます

### gitHub リポジトリへの公開鍵の登録
- 公開鍵の内容を表示してコピーします
```
cat ~/.ssh/id_{KeyPair名}.pub
```
- gitHubのリポジトリのページを開き、以下を行います
1. リポジトリのページの上部のメニューから「Settings」 を押します
1. 左メニューにある「Deploy Keys」を押します
1. 上部にある「add deploy key」を押します
1. 「Deploy keys / Add new」ページで、先ほどコピーした秘密鍵の中身を「Key」欄にペーストし、「Add Key」ボタンを押して登録します

# Reactアプリの作成とgitHubへのpush
- Reactアプリを作成
```
create-react-app <アプリ名>
```
<アプリ名>フォルダが作成され、Reactアプリの作成準備ができます。git の初期化も行われ、最初のコミットがされます。

- ReactアプリをgitHub にpush
```
cd <アプリ名>
git remote add origin git@github.com:<ユーザー名>/<リポジトリ名>.git
git branch -M main
git push -u origin main
```

# AWS Amplify でのデプロイ
これは下記サイトを参照してすんなりとできました。

https://aws.amazon.com/jp/getting-started/hands-on/build-react-app-amplify-graphql/module-one/

# まとめ
gitHub への SSH接続ですこしつまづきましたが、AWSを使うとアプリの公開やCDが簡単にできることが分かりました。
【TypeScriptで学ぶデータ構造】スタック

## スタック

最後に入れたデータを最初に取り出していくデータ構造の一種
後入れ先出し（Last In, First Out）


イメージは**一つづつ積み上げていった積み木を上から取っていく感じです。**

### 具体的な例としては、ブラウザの「戻る」機能
`ブラウザトップページ→Qiitaの記事1→おすすめから飛んだQiitaの記事2`

と移動した場合、上記がスタック内に積まれ、おすすめから飛んだQiitaの記事2にいる状態で「戻る」矢印を押下するとおすすめから飛んだQiitaの記事2が取り出され（削除され）Qiitaの記事1が表示される。

また、テキストエディターの「戻る」（command or ctr + z）も後入れ先出しなので操作履歴はスタックの構造ですね！


## スタックを再現したstackクラス

addメソッドでitems配列にデータを格納します。
そして、removeメソッドを実行するたびに後から入れたデータが削除されます（取り出されます）


以下のコードを実行すると

`1000を格納→5000を格納→10000を格納→10000を取り出す→5000を取り出す`という処理が行われます。（ブラウザの例と同じ）

```stack.ts
class Stack<T> {
	private items: T[] = [];
	private top: number = -1; //スタックのトップを管理

	//要素をスタックに追加するメソッド（標準のpushメソッドを使うともう少しシンプルになる）
	add(item: T): void {
		this.top += 1;
		this.items[this.top] = item;
	}

	//スタックの一番上の要素を削除して返すメソッド（標準のpopメソッドを使うともう少しシンプルになる）
	remove(): T | undefined {
		if (this.isEmpty()) {
			return undefined;
		}
		const poppedItem = this.items[this.top];
		this.items.splice(this.top, 1);
		this.top -= 1;
		return poppedItem;
	}

	//スタックが空かどうかを確認するメソッド
	isEmpty(): boolean {
		return this.top === -1;
	}

	//スタックの内容を表示（表示用です）
	printStack(): void {
		console.log(this.items.join(" "));
	}
}

// 使用例です
const stack = new Stack<number>();
// スタックに1000を格納
stack.add(1000);
stack.add(5000);
stack.add(10000);

//この時点では1000 5000 10000
stack.printStack();

//取り出す処理。下記の場合、10000が取り出され、↓
stack.remove();
//次に以下で5000が取り出される
stack.remove();
//残ったのは最初に入れた1000
stack.printStack();

```

## JavaScript標準のメソッド

### pushメソッド
配列の末尾に指定された要素を追加するメソッド

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/pop

### popメソッド
配列から**最後**の要素を取り除き、その要素を返すメソッド

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/pop
タイ語品詞付与・係り受け解析モデルcamembert-thai-base-uposリリース

[6月25日の記事](https://qiita.com/KoichiYasuoka/items/e77ead5a495d7ad75b12)の続きだが、[PhayaThaiBERT](https://huggingface.co/clicknext/phayathaibert)のトークナイザを改造して「เก็บไว้」や「คนเดียว」を正しくトークナイズできるようにした上で、タイ語の品詞付与・係り受け解析モデル[camembert-thai-base-upos](https://huggingface.co/KoichiYasuoka/camembert-thai-base-upos)を試作してみた。Google Colaboratoryで動かしてみよう。

```
!pip install esupar
import esupar
nlp=esupar.load("KoichiYasuoka/camembert-thai-base-upos")
doc=nlp("แม่อย่าเก็บไว้คนเดียว")
import deplacy
deplacy.serve(doc,port=None)
```

「แม่อย่าเก็บไว้คนเดียว」を係り受け解析してみたところ、私(安岡孝一)の手元では以下の結果が得られた。

```
1	แม่	_	NOUN	_	_	3	nsubj	_	SpaceAfter=No
2	อย่า	_	AUX	_	_	3	aux	_	SpaceAfter=No
3	เก็บ	_	VERB	_	_	0	root	_	SpaceAfter=No
4	ไว้	_	AUX	_	_	3	aux	_	SpaceAfter=No
5	คน	_	NOUN	_	_	3	obj	_	SpaceAfter=No
6	เดียว	_	NUM	_	_	5	nummod	_	SpaceAfter=No
```

![thai.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428317/2e618592-039b-110f-a913-c0554f763115.png)

単語の切れ目は正しくなったのだが、係り受けに関しては、残念ながらうまく解析できていない。[4月2日の記事](https://qiita.com/KoichiYasuoka/items/851bbe0299f43c7eb4e9)と見較べても、リンクのラベルが3つも間違っている。やっぱり、トークナイザを改造しても、なかなか精度が上がらないなあ。
AtCoder ABC 263 B - Ancestor のサンプル例どうにかならなかったのか

自分の理解力のなさと、どこにも吐き捨てることのできない思いを
チラ裏として、ここに放ちます、駄文で失礼します。読むだけ時間の無駄かと思います。

AtCoder ABC 263 B 問題を解こうとしました。
https://atcoder.jp/contests/abc263/tasks/abc263_b

問題文を読んで、さっぱり理解ができなかったため、
ページ下部の入力サンプルをみて動きを確認しようとしたところ
以下のような形式
```
N
1 2 ... N-1 
```
の二つしかありませんでした。(N=3,10のパターンの2種、以下入力例）

#### 入力例1
```
3
1 2
```
#### 入力例2
```
10
1 2 3 4 5 6 7 8 9
```
この二つの例なら N-1 でいいじゃんと思ったらWrong Answer

[解説](https://atcoder.jp/contests/abc263/editorial/4540)見ても、[解説動画](https://atcoder.jp/jump?url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3D8RI_IJX6VQY%26t%3D1828s)見ても,
解くには動的計画法を使うんだ！！としか書かれていませんが

問題をかみ砕くところから解説までの話が飛躍しすぎていると感じます。

とりあえずいいサンプルがないかを探した結果、[Qiita解説記事(@sano192)](https://qiita.com/sano192/items/ba71a912c3dd5bdd5e38)に
```
7
1 1 3 3 5 5
```
とあり、そういう入力もあるんだと思う一方で、どうやって思いつくのと思いました。

こういった問題を初見でかみ砕くのは無理ではと思い、最初は質問にでも乗せようかと思いましたが、期待される回答が来る気がしなかったのでチラ裏としてここに記載しました。

この問題が解けている人は初見で問題文を読み解くことができるのかが疑問です。

単純に問題のタイトルがAncestor:祖先であり、祖先をたどる問題は基本的に動的計画法で解く　というふんわりした概念があるから理解できているだけなのじゃないかと思っていますが、どうなんですかね。

X.comでも同じように問題文理解できない人が少しは散見されましたので、過去の先輩方に同情を馳せつつ、
本日の、この問題に費やした２時間は無駄だったなと思ってこの記事を閉じたいと思います。（問題解く5分　解説読む1時間半 記事書く15分ぐらい）

### 要するに何が言いたいのか


AtCoder ABC 263 B - Ancestor のサンプル例どうにかならなかったのか
投稿 48 関数 2024/08/17

本日の勉強時間　0.5H

関数とは、入力を与え、あらかじめ決められた処理を行なって結果を返す仕組み。
関数は　呼びだす　というワードを使う。

入力：引数
出力：戻り値

種類として
　　・ビルドイン関数
  　・ユーザー定義関数

   がある。
文字と整数の組のソート

今日から学んだことのアウトプットとして記事に残そうと思います。
今回はn行続く文字と整数の組について、同じ文字があればそれらを足し合わせ最終的に降順に直し出力するというものです。
```C++:
#include <iostream>
#include<map>
#include<vector>
#include<algorithm>
using namespace std;
int main(){
    int n;
    cin >> n;
    map<string, int> SD;
    for (int i = 0; i < n; ++i){
        string s;
        int d;
        cin >> s >> d;
        SD[s] += d;
    }
```
stringをキーとして、intを値に持つmapを作成。
文字列に対応する整数をmapに追加、すでに存在する場合、加算。

```C++:
    vector<pair<int, string>> DS;
    for(auto iter = SD.begin(); iter != SD.end(); ++iter){
        DS.push_back(make_pair(iter->second, iter->first));
    }
    sort(DS.begin(),DS.end(),greater<pair<int,string>>());
    for(int i = 0; i < DS.size(); ++i){
        cout << DS[i].second << " " << DS[i].first << endl;
    }
    return 0;
}
```
mapの全要素をループで処理し、それぞれの要素をベクターに追加。
iter->first は文字列、iter->second は対応する整数の合計。
ソート関数で降順に並び替え、for文で結果を出力。
以上です。

マップ関数に少し苦手意識があるので改善したいと感じました。
このQiitaの記事も上手くなるために書き続けたいと思います。
TryHackMe Writeup：OhSINT



# 最初に

オープンソースインテリジェンスに関するRoom「OhSINT」に取り組みます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2152468/eddc3638-0f1d-5647-291a-3a4f400b0ed6.png)


OhSINTという言葉を初めて聞いたので、少し調べてみました


>一般に公開されている情報源からアクセス可能なデータを収集、分析、決定する諜報活動の一種である。米国国防総省（DoD）によって、「特定の情報要件に対処する目的で、一般に入手可能な情報を収集し、利用し、適切な対象者に適時に普及させた情報」と定義されている。

引用元：https://www.nec-solutioninnovators.co.jp/ss/insider/security-words/41.html


ちょっと悪用厳禁な感じもありますが、とりくんでいきます！！


# Task 1


画像1枚から何がわかるのだろうか。。。



## What is this user's avatar of?

まずexiftoolでプロパティをみていきます。

Copyrightに`OWoodflint`というキーワードがありますね
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2152468/8ca5b855-c4ac-6b61-2f88-81666445ce6b.png)

これをWebで調べてみると、ツイッターがあってそのアイコンがかわいい猫でした(=^・^=)


## What city is this person in?

前問のWeb調査の中で、GitHubもあり、そこに出身地が記載されていましたね

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2152468/c5132d15-99b8-f145-6175-b50d1b6443bb.png)


メール削除した方がいいよ、というPull Requestがありました、、、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2152468/6f729d22-cca3-1780-1595-1ae70624d3d9.png)


## What is the SSID of the WAP he connected to?


これが難しかったです。。。
BSSIDは以下なのはわかったのですが、SSIDがわからない。。。
```
B4:5D:50:AA:86:41
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2152468/5e8ee8d6-eb51-8ba9-2da5-fc3bcf95d0d2.png)



https://wigle.net/　
を使うみたい
ただ、使い方がわからず適当に操作していたら`Daily Limit`と表示された...
絶望....

日を改めて再度チャレンジ！
以下の手順ですすめました！

1. 登録してメール認証
1. Basi Search を選択
1. BSSIDに`B4:5D:50:AA:86:41`を入力 
1. 右側に検索結果が出力

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2152468/018f141f-bef4-fa92-41ca-ca3dbbe33db4.png)


最大限拡大するとSSIDが見えるようになります！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2152468/a43cc2c4-39f0-8c75-23a7-82f93d615ca7.png)




## What is his personal email address?

GitHubに記載されていますね


## What site did you find his email address on?


GitHubに記載されていますね（3回目）

## Where has he gone on holiday?

WordPressでブログをしているみたいで、そこに記載されています


## What is the person's password?

そもそも何のパスワードなのか。。。という感じがします
Hintを見てみると`Check the Source code`とあった。

ソースコードに文字を隠しこむなら比較的自由度の高いWordPress、かつ自分で文字を入れられるところだと思い、そこに絞って調査

例えば、以下のページだと、`Hey`と`Im in New York right now, so I will update this site right away with new photos!`が作成者のつくったところなので、ソースコードでもそこの部分だけを検索してみていきます。
例えば`New York`で検索すれば、該当箇所だけ確認できます！
https://oliverwoodflint.wordpress.com/


この方法で全ページ調べたら、みつかりました！

https://oliverwoodflint.wordpress.com/2019/03/03/the-journey-begins/

# 最後に

今回学んだことは以下です

- **個人情報はあまり公開しないように！！！**

以上！