OmniAICreator/Qiita-1.07M huggingface dataset:
[paiza]山あり谷ありラジバンダリ

# ありおりはべりいまそかり
`最近、ひたすら紙を折り続けるということがマイブームとなっているあなたは、今日もひたすら紙を折り続けています。それも、折り紙のような凝った折り方ではなく、紙の右辺が上から左辺に重なるような二つ折りを、ただひたすら繰り返すだけです。
`

おいおいおい、プログラムのし過ぎで頭おかしくなったんか？
刺し身にたんぽぽ載せる仕事とかに転職したほうがいいんじゃない？
かと不安になる問題文の冒頭。。。

https://paiza.jp/works/mondai/real_event/origami

# 面倒くさいので画面パタメータをListでもらった後のFunctionだけ
ちなみに引数のListを作ってる箇所は[こっちの記事](https://qiita.com/AsilHatake/items/842548e48ae4a0eae119)に書いてあるYO!!

```javascript:origami.js
// [問題文（原文）]
// 最近、ひたすら紙を折り続けるということがマイブームとなっているあなたは、今日もひたすら紙を折り続けています。それも、折り紙のような凝った折り方ではなく、紙の右辺が上から左辺に重なるような二つ折りを、ただひたすら繰り返すだけです。
// さて、上記のように N 回折ったあと手順を逆に辿るように紙を広げます。すると、山折りと谷折りの折り目が等間隔に並んだ紙の完成です。あなたはこの折り目を眺めるのが好きですが、実際に紙を折るには紙の大きさや厚さから数回が限界です。
// 
// そこで、紙を上記のように折る回数 N が与えられるので、紙を折って広げたあとの山折り谷折りの折り目を計算するプログラムを作成してください。
// 
// 2回折り (N = 2) の場合は以下のように折り目が付きます。
function origami(lines) {
  // 入力は以下のフォーマットで与えられます。
  // 
  // N
  // 
  // N は紙を上記の形式で折る回数を表します。
  const foldPattern = getFoldPattern(Number(lines[0]));

  // 山折りの折り目を "1"、谷折りの折り目を "0" として、答えとなる折り目を左から順に "0" と "1" からなる文字列として一行に出力してください。 
  console.log(foldPattern.join(''));
}

// 折り目取得
function getFoldPattern(foldCnt) {
  // Nが0の場合、折り目は存在しないので空配列
  if (foldCnt === 0)
    return [];

  // 再帰的にN-1回の折り目パターンを取得
  const previousPattern = getFoldPattern(foldCnt - 1);
  // 真ん中は谷折りなので0固定で、右側は左側の値を反転させたやつになるためリバースして値を入れ替えた
  return [...previousPattern, 0, ...previousPattern.reverse().map(fold => fold === 0 ? 1 : 0)];
}

module.exports = {
  origami
};
```

再帰で折り目をドンドン作っていくような作りになってます。
以下の部分を解説
`return [...previousPattern, 0, ...previousPattern.reverse().map(fold => fold === 0 ? 1 : 0)];`

1回目のループ：[][0][]
→0
真ん中は必ず谷折りになるので0を固定で（2回目以降も同じ）

2回目のループ：[0][0][0→1]
→001
左側：1回目のループで出来た値
右側：谷折りの反対は山折りなので値を入れ替える

3回目のループ：[001][0][001→100→011]
→0010011
左側：2回目のループで出来た値
右側：右側を反転して値も逆さにした感じ

つまるところ。。。
- 1つ前の結果が左側に出来る
- 真ん中は絶対に**谷折りの0**
- 反対側は左側の結果を並び順と値を逆にしたもの

っていうのが分かれば、**再帰**で求めるのが1番分かりやすいのかなって言うことで、こんな実装になってます。
GitHub copilotのチャットがVisual Studio Codeで使えなくなったときの対処方

## 何故かチャットだけ使えない

以下の様な症状が出た

- サインインしているのに「サインインしてください」というボタンが出る
- サインインボタンを押して、WEBでリダイレクトが入るのに「サインインしてください」が出続ける
- チャットだけ使えず、エディタ上では良い具合に補完してくれる
- サインアウトや画面の更新を繰り返しても、エラーが出る

## 対処方法

設定ファイルのCache関連のファイルを一通り削除することで解消。
細かい設定などをしている方は

Ubuntu: `~/.conf/Code/以下`
Mac: `~/Library/Application\ Support/Code/以下`
Windows: `知りません`

`Code/User`あたりは設定ファイルが入っているので、消さない様にしましょう。

## 公式のドキュメント

このあたりを参考に、サインアウトなども試したが上手く行かなかった。

https://docs.github.com/ja/copilot/troubleshooting-github-copilot/troubleshooting-issues-with-github-copilot-chat-in-ides
【Ruby】eachメソッドで便利なやつ

## 概要
eachメソッドで使える便利なものをまとめました。
配列のメソッドがほとんどなのでそっち調べたほうが早いかも。

https://qiita.com/yyykms123/items/e1bcb838f56100d12025

## 起点、回数の指定
### **`first(n)`**
* 先頭からn個の要素分まで実行する（回数指定）

~~~ ruby
num = [1, 2, 3, 4, 5, 6, 7, 8, 9]

# 先頭から3回まで
num.first(3).each do |num|
  puts num
end

# result
1
2
3
~~~

### **`last(n)`**
* 末尾n個の要素分、実行する（起点指定）

~~~ ruby
alphabet = ["A", "B", "C", "D", "E",]

# 末尾3回分まで
alphabet.last(3).each do |num|
  puts num
end

# result
"C"
"D"
"E"
~~~

### **`list[n1..n2]`**
* n1個目からn2個目分まで実行する（回数・起点指定）

~~~ ruby
list = ["くま", "とら", "うさぎ", "かめ", "たこ", "ひと"]

# 要素2（うさぎ）から要素4（たこ）まで
list[2..4].each do |num|
  puts num
end

# result
"うさぎ"
"かめ"
"たこ"


# .silce(n1..n2)でも可能
list.slice(2..4).each do |num|
  puts num
end

# result
"うさぎ"
"かめ"
"たこ"
~~~

## 配列を操作
### **`list.uniq`**
* 重複したものを無視する

~~~ ruby
num = [1, 1, 2, 2, 2, 3]

# 重複したものは無視する
num.uniq.each do |num|
  puts num
end

# result
1
2
3
~~~

### **`list.push(n)`** 
* 末尾にnを追加して実行
### **`list.unshift(n)`**
* 先頭にnを追加して実行

~~~ ruby
num = [1, 2, 3]

# 先頭に要素を追加
num.push("Ruby").each do |num|
  puts num
end

# result
"Ruby"
1
2
3

# 末尾に要素を追加
num.unshift(81).each do |num|
  puts num
end

# result
1
2
3
81
~~~

## インデックス番号の使用

### **`each_with_index`** 
* インデックス番号を扱うことができる

~~~ ruby
name = ["田所", "木村", "平野"]

# 第一引数が要素、第二引数がインデックス番号
name.each_with_index do |name, num|
  puts "#{num}番目は#{name}さんです"
end

# result
"0番目は田所さんです"
"1番目は木村さんです"
"2番目は平野さんです"
~~~
### **`each.with_index(n)`**
* 初期値をnとしてインデックス番号を扱うことができる
* `each`メソッドと`with_index`メソッドの合せ技であり、`each_with_index`とは違う

~~~ ruby
name = ["遠野", "三浦", "橋田"]

# インデックス番号を1から始める
name.each.with_index(1) do |name, num|
  puts "#{name}さんは#{num}着です"
end

# result
"遠野さんは1着です"
"三浦さんは2着です"
"橋田さんは3着です"
~~~

## 要素を好きなように切り分けて実行

### **`each_slice(n)`**
* 配列の要素を指定したn個分切り分けて実行できる[^1]

~~~ ruby
array = 1..10

# 2個づつに分けて実行
array.each_slice(2) do |array|
  p array
end

# result
[1, 2]
[3, 4]
[5, 6]
[7, 8]
[9, 10]

# 3個づつに分けて実行
array.each_slice(3) do |array|
  p array
end

# result
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
[10]
~~~
### **`each_cons(n)`**
* 連続したn個分の要素を一つづつずらして取得できる[^1]

~~~ ruby
array = 1..7

# 3つ分の要素を一つづつ分けて実行
array.each_cons(3) do |array|
  p array
end

# result
[1, 2, 3]
[2, 3, 4]
[3, 4, 5]
[4, 5, 6]
[5, 6, 7]
~~~

### **`each_line`** 
* 改行ごとに切り分ける

~~~ ruby 
animals = "cat\ndog\nrabbit\nhamster"

animals.each_line do |animal|
  puts animal
end

# result
"cat"
"dog"
"rabbit"
"hamster"
~~~


[^1]:`each_slice(n)`と`each_cons(n)`は下記のようにも記載できる
    ~~~ ruby
    array = 1..10

    # 変数を3つ
    array.each_slice(3) do |n1, n2, n3|
      puts "#{n1}, #{n2}, #{n3}"
    end

    # result
    "1, 2, 3"
    "4, 5, 6"
    "7, 8, 9"
    "10, , "
    ~~~
bashでcondaコマンド実行時bash: C:\Users\user_namenaconda3\Scripts: No such file or directory

## 発生した問題
以前からvscodeのターミナルgit bashやmsys bashでcondaコマンドを実行した際に
```
bash: C:\Users\user_namenaconda3\Scripts: No such file or directory
```
というエラーが発生しておりanacondaが使用できない状態だった。一方でwindows cmdやpowershellでは問題なくcondaコマンドが利用できる。

## 解決方法
どうやらvscodeのpython拡張機能が原因で/aをパスから消してしまうらしいのでpython拡張機能を無効にしたら問題なく動作しました。

https://marketplace.visualstudio.com/items?itemName=ms-python.python

## 参考
https://stackoverflow.com/questions/78429677/anaconda-dont-work-in-vsc-gitbash-terminal-wrong-path
Voltaのインストール手順（macOS, zsh）

## アジェンダ
JavaScriptツールチェインを簡単に管理できるVoltaのインストール手順を以下に説明します。この手順では、macOSのzshを使用しています。

## インストール手順
### 方法1: 公式インストールスクリプトを使用

1. **Voltaのインストール**:
Voltaは公式インストールスクリプトを使用して簡単にインストールできます。ターミナルを開き、以下のコマンドを実行してください。

https://docs.volta.sh/guide/getting-started

```sh
curl https://get.volta.sh | bash
```

### 方法2: Homebrewを使用

1. **Voltaのインストール**:
Homebrewを使ってVoltaをインストールするには、以下のコマンドを実行します。

```sh
brew install volta
```

**-----　!!!ここから共通手順!!!　-----**

2. **インストール後の確認**:
インストールが完了したら、ターミナルを再起動するか、以下のコマンドを実行してシェルの設定をリロードします。

```sh
source ~/.zshrc
```

3. **Voltaのインストール確認**:
Voltaが正しくインストールされているかどうかを確認するために、以下のコマンドを実行します。

```sh
volta --version
```

バージョン情報が表示されれば、インストールは成功です。

## 任意:手動で環境変数を設定する場合
Voltaのインストールスクリプトは、必要な環境変数の設定を自動的に行ってくれます。
なので、手動で環境変数を設定する必要は基本的にはありませんが、もしうまく動作しない場合(インストール後にVoltaのコマンドが見つからないなど)や何らかの理由で手動設定が必要な場合、手動で環境変数を設定する必要があります。

1. **zshrcファイルの編集**:

```sh
vim ~/.zshrc
```

2. **環境変数の追加**:

以下の行を `.zshrc` ファイルの末尾に追加します。

```sh
export VOLTA_HOME="$HOME/.volta"
export PATH="$VOLTA_HOME/bin:$PATH"
```

3. **設定の反映**:

`.zshrc` ファイルを保存して終了し、以下のコマンドを実行して設定を反映します。

```sh
source ~/.zshrc
```

これでVoltaが正しく動作するはずです。

## Node.jsやnpmのインストール

Voltaを使ってNode.jsやnpmをインストールするには、以下のコマンドを使用します。

```sh
volta install node
volta install npm
```

この手順により、必要なツールチェインを簡単に管理できるようになります。

## 参考
- [Introduction | Volta](https://docs.volta.sh/guide/)
- [Node.jsのバージョン管理ツール「Volta」のインストール・導入方法・使い方を解説 | フクログ](https://fukulog.net/volta/)
React, TypeScript に後から Electron を足したときのメモ

既存の React + TypeScript プロジェクトに Electron を後乗せしたときのメモ

contextBridge や ipcRenderer などの Electron の基本的なものに関しての理解はあるものとする

ディレクトリ構成

```
./
├── electron/
│   ├── electron.ts
│   ├── preload.ts
│   └── tsconfig.json
├── src/
│   ├── @types/
│   │   └── electron.d.ts
│   └── app.tsx
├── package.json
└── tsconfig.json
```

### 既存ファイルの修正

とりあえずのパッケージインストール

```jsx
npm install electron electron-builder@24.6.3 --save-dev
```

package.json に以下を追記

- homepage: ビルドされる index.html 内のファイルパスが相対パスとなるよう指定
- main: ビルド対象
- scripts: ビルドコマンドを定義．React のビルドでビルドフォルダ内がリセットされるためコマンド順序は固定
- build: ビルドオプション

```jsx
{
  "homepage": "./",
  "main": "build/electron/electron.js",
  ~~~
  
  "scripts": {
	  "dist": "react-scripts build && tsc -p electron && electron-builder --win --x64 --dir"
  },
  "build": {
    "extends": null,
    "files": [
      "build/**/*"
    ],
    "directories": {
      "buildResources": "assets"
    },
    "win": {
      "icon": "build/favicon.ico"
    }
  }
}
```

<br />
App.tsx で BrowserRouter を使用していたため、HashRouter に変更

```jsx
function App() {
  return (
    <div className="App">
      <HashRouter>
        <Routes>
          {routes}
        </Routes>
      </HashRouter>
    </div>
  );
}
```

---

### React からの Electron プロセス呼び出し

electron/preload.js でAPIを定義

ついでに src/@types/electron.d.ts で型を参照したいため export も行っておく

```jsx
import { contextBridge, ipcRenderer } from 'electron'

const apiHandler = {
    sendEvent: async (event: string) => {
        return await ipcRenderer.invoke(event)
    },
    listenChannel: (channel: string, func: (param: any) => void) => {
        ipcRenderer.on(channel, (event, param) => func(param))
    }
}
contextBridge.exposeInMainWorld('apis', apiHandler)
export type ApiHandler = typeof apiHandler
```

<br />
src/@types/electron.d.ts に型を記述

```jsx
import { ApiHandler } from '../../electron/preload'

declare global {
    interface Window {
        apis: ApiHandler
    }
}

export {}
```

<br />
ここまでの実装で React と Electron の紐づけが済んでいるはず

任意の場所で window から処理を呼べる
```jsx
useEffect(() => {
  window.apis.sendEvent('send-event').then(msg => {
    console.log(msg)
  })
  
  window.apis.listenChannel('listen-channel', (msg: string) => {
    setState(msg)
  })
}, [])
```


`npm run dist` から作成される exe が正常に実行出来たら完了
Ubuntuでdockerをインストールするとき困ったこと

下記の文を参考にUbuntuでスクレイピング環境を構築中で、困ったことがあったので補足します。

https://qiita.com/ryome/items/4b6b934b1b2021acfa26

対象はこちらです。

```shell
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
```

## 対策

1. GPGキーダウンロード

```shell
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

```

2. DockerのAPTリポジトリを/etc/apt/sources.list.d/docker.listに追加

```shell
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
```

3. パッケージアップデート、インストール

```shell
sudo apt update
sudo apt-get install docker-ce docker-ce-cli containerd.io
```
Implicit Differentiation 暗黙の微分！？

今回は、Implicit Differentiation （陰関数積分）について、考察していきたいと思います！

## Implicit Function（陰関数）

まず、Implicit Function（陰関数）についてや。

陰関数とは、Explicit Function（陽関数）の様に、明示的に $y=f(x)$ という形で表されていない関数のことや。例えば、 $F(x,y)=0$ という形で表される関数のことを陰関数と言うんや。ここで、 $F$ は $x$ と $y$ の両方に依存する関数やけど、 $y$ を直接的に $x$ の関数として表すことはできへん。

### 例：

例えば、円の方程式 $x^2+y^2−r^2=0$ は陰関数の一例や。この方程式は $x$と $y$ の関係を示してるけど、 $y$ を $x$ の明示的な関数として表してへん。

### 陰関数定理 (Implicit Function Theorem)：

陰関数定理は、ある条件のもとで陰関数を明示的な関数として表現できることを保証する定理や。

### 陰関数定理の内容：

1. まず、 $F(x,y)=0$ がある点 $(a, b)$ で定義されていて、 $F(a,b)=0$ であるとする。
    
     $F(x,y)=0$ 
    
    $(a, b)$
    
     $F(a,b)=0$ 
    
2. また、 F が $(a, b)$ の近傍で連続的に微分可能であり、$\frac{\partial F}{\partial y}(a, b) \not= 0$ であるとする。
    
    $F$
    
    $(a, b)$
    
    $\frac{\partial F}{\partial y}(a, b) \not= 0$ 
    

このとき、$(a, b)$ の近傍で $y$ を $x$ の関数として表す $y=g(x)$ が存在して、 $g(a)=b$ かつ $F(x,g(x))=0$ が成り立つんや。

### 具体例：

先ほどの円の方程式を使ってみるとな、
$x^2+y^2−r^2=0$ 
この方程式を $y$ について解くと、
$y=\pm \sqrt{r^2-x^2}$
これは円の上半分と下半分のそれぞれを表しているんや。

### 実用例：

陰関数はグラフの形状を分析したり、最適化問題の制約条件を定義するのに使われることが多いで。また、物理や工学の多くの問題でも利用されるんや。

## Implicit Differentiation（陰関数積分）

陰関数微分（Implicit Differentiation）について詳しく説明するな。これは、 $x$ を $y$ の明示的な関数として表せない場合でも、微分を使って $x$ と $y$ に関する変化率（微分係数）を求める方法や。

### 基本的な考え方

陰関数微分の基本的なアイデアは、関数  $F(x,y)=0$  の両辺を  $x$ について微分することや。この過程で、  $y$ は  $x$ の関数として扱われるから、  $y$ を微分する際には連鎖律（Chain Rule）を使うんや。

### 手順

具体的な手順をステップバイステップで説明するで。

1. **関数の設定**：
関数  $F(x,y)=0$  が与えられているとする。ここで、 $y$ は  $x$  の関数 $y=g(x)$ として暗黙的に定義されているんや。
2. **両辺を $x$ について微分**：
関数  $F(x,y)=0$  の両辺を  $x$ について微分する。
    
    $$
    \frac{d}{dx}[F(x, y)]=\frac{d}{dx}[0]
    $$
    
3. **連鎖律を適用**：
連鎖律を適用して  $y$ の微分を含む形に展開する。ここで  $y$ は  $x$ の関数と見なされるため、 $\frac{dy}{dx}$ を含む項が現れる。
    
    $$
    \frac{\partial F}{\partial x} + \frac{\partial F}{\partial y}\frac{dy}{dx} =0
    $$
    
4. **求めたい微分を解く**：
得られた方程式を $\frac{dy}{dx}$ について解くことで、  $y$ の  $x$ に関する変化率を求める。

### 具体例

実際の例を使って説明するわ。

### 例：円の方程式

円の方程式 
$x^2+y^2=r^2$ を考える。この方程式に対して $\frac{dy}{dx}$ を求めるで。

1. **関数の設定**：
    
    $$
    F(x, y) = x^2+y^2−r^2=0
    $$
    
2. **両辺を xxx について微分**：
    
    $$
    \frac{d}{dx}[ x^2+y^2−r^2]=\frac{d}{dx}[0]
    $$
    
3. **連鎖律を適用**：
    
    $$
    \frac{\partial}{\partial x}[ x^2]+\frac{\partial}{\partial x}[y^2]−\frac{\partial}{\partial x}[r^2]=\frac{\partial}{\partial x}[0]
    $$
    
    $$
    2x+2y\frac{dy}{dx}=0
    $$
    
4. **求めたい微分を解く**：
    
    $$
    2x+2y\frac{dy}{dx}=0
    $$
    
    $$
    2y\frac{dy}{dx}=-2x
    $$
    
    $$
    \frac{dy}{dx}=-\frac{x}{y}
    $$
    

### まとめ

陰関数微分は、関数が明示的に表されていない場合でも、微分を通じて変数間の関係を解析する強力な方法や。連鎖律を適用することで、明示的に $y=g(x)$と表せなくても、 $y$ の $x$ に関する微分を求めることができるんや。

こちらが、今回参考にした動画（学校の授業以外で ）です。ウチのまとめよりも、こっちの方が分かり易いと思うで。 このチャンネルの日本語訳も、大学生の人たちが作ってると思うで。

[https://youtu.be/qb40J4N1fa4](https://youtu.be/qb40J4N1fa4)


---
投稿 36 DMZ 2024/08/05

本日の勉強時間　0.5H

社内ネットワークを不正アクセスやサイバー攻撃から防ぐ方法の1つに、DMZ（非武装地帯）があります。 DMZは、インターネットと社内ネットワークの間に設けられた緩衝領域を指します。 DMZで社内ネットワークへのアクセスを防ぐことで、社内ネットワークを守る仕組みです。
maturin AttributeError モジュールはあるのに関数がない

maturinでRustコードをビルドして、Pythonからインポートする段階でエラーが出ました。
```.stderr
AttributeError: module 'pymodtest' has no attribute 'add_two'
```

## 環境
Github Actions:
    - ubuntsu-latest
    - Python 3.12
    - maturin 1.7.0

## ソースコード
[Github](https://github.com/chiveslimey/Inline-maturin)
fixedブランチに修正版もあります

## ディレクトリ構成
```
inline-maturin
    | -- inline_maturin.py
    | -- test_inline_maturin.py
    | -- pymodtest
    |    | -- Cargo.toml
    |    | -- pyproject.toml
    |    | -- __init__.py
    |    | -- src
    |    |    |  -- lib.rs
```

## 状況
- ImportErrorではない（インポート自体は成功）
- インポートしたモジュールから関数にアクセスしようとするとエラー

## 解決策
\_\_init__.pyを削除する

## 考察
maturinは、\_\_init__.pyが存在するモジュールをPythonとRustの混合モジュールとして解釈するようです。[^1]
[^1]: 参考：https://www.maturin.rs/project_layout#mixed-rustpython-project

すると、maturinはPythonコードが入ったフォルダを探そうとします。しかし、今回そのフォルダは作っていないため、maturinはこのモジュールを空モジュールとして認識してしまい、AttributeErrorが送出されていたようです。
Tera Termでログを取る際の注意点

## はじめに
Tera Termは、下記の手順でログを取得することができる。
1. Tera Termで機器にログイン
1. 「ファイル」タブから「ログ」を選択
 ![スクリーンショット (471).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3517570/c112146b-dcd9-64ca-300a-d98b1eeda8b6.png)
1. ログファイルの保存先を選択し、保存を押下
![スクリーンショット (472).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3517570/347e0715-05bf-1885-52e7-42a6718fd521.png)
1. 実行したコマンドがログに記録される

しかし、後からログを見返すと、

**「Tera Termのログと、実際の実行画面が違う...」**

といった現象が起こることがある。
実行画面をコピペしてログを取ればこのような現象は避けられるが、タイムスタンプ付きでログを取りたい場合などは難しい。

本記事は、Tera Termでログを取る際の注意点について、筆者の体験を基にまとめたものである。

## 注意点
### コピペでコマンドを実行すること
事前にメモ帳などにコマンドを用意しておき、Tera Termにペーストして実行することをお勧めする。

理由は、Tera Termのログは実行画面で入力した文字列が瞬時に記録されてしまうからだ。
コマンドを打ち間違えた場合や、↑キーでコマンド履歴を使用した場合など、実行画面に表示された文字列は全てログに記録される。

Tera Termでログを取る際は「コピペでコマンドを実行」を基本として、
次に、タイムスタンプ付きでログを取る際の注意点について記載する。

### 空エンター後にコマンドを実行すること
前回のコマンドから時間を空けてコマンドを実行する場合は、空エンターを実行してからコマンドを実行することをお勧めする。

理由は、前述した通り、実行画面に表示された文字列が瞬時に記録されることで、実際の実行時刻とログ上の実行時刻が異なってしまうからだ。

例えば、下記画像のように、sh arpコマンドの実行から時間を空けてclear arp-cacheコマンドを実行したい場合、空エンターを実行しないと、赤枠の部分でclear arp-cacheコマンドを実行することになる。
そのため、実際の実行時刻とログ上の実行時刻に差異が生じてしまう。

この現象を回避するには、コマンドの実行直前に空エンターを実行し（①）、clear arp-cacheコマンドをペーストして実行（②）すればよい。
![画像4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3517570/d879aaca-9d65-c034-c0ae-b498963a07d4.png)

### コマンドは入力後すぐに実行すること
同様の理由で、コマンドを入力した状態でしばらくしてから実行した場合も、実際の実行時刻とログ上の実行時刻に差異が生じる。

そのため、コマンドを実行する際は「空エンター→コマンドをペースト→実行」の流れを滞りなく行うことが重要である。

以上
Homebrewのインストール手順

## アジェンダ

macOSでパッケージマネージャーのHomebrewをインストールする手順を紹介します。Homebrewは、ソフトウェアのインストールや管理を簡単にするためのツールです。
※zshシェルやbashシェルを使用している場合でも問題なくインストールできます。

## インストール手順

### 1. ターミナルを開く

まず、ターミナルを開きます。zshシェルまたはbashシェルを使用している場合でも以下の手順でインストール可能です。

### 2. Homebrewのインストールコマンドを実行

下記リンク先からインストールコマンドをターミナルにコピーして貼り付け、実行します。これによりHomebrewのインストールが開始されます。

https://brew.sh/ja/

```sh
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```

### 3. インストール手順に従う

インストーラーが開始されるので、表示される指示に従って進めてください。途中でパスワードの入力を求められる場合があります。指示に従ってインストールを完了させます。

### 4. パスを設定する

インストールが完了したら、パスを通してと言われるので、Homebrewのパスを設定する必要があります。使用しているシェルに応じて、次のコマンドをターミナルに入力して実行します。

#### zshシェルを使用している場合

```sh
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile
eval "$(/opt/homebrew/bin/brew shellenv)"
```

#### bashシェルを使用している場合

```sh
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.bash_profile
eval "$(/opt/homebrew/bin/brew shellenv)"
```

このコマンドは、Homebrewの環境変数をシェルに追加し、設定を反映させます。

### 5. インストールを確認する

最後に、Homebrewが正しくインストールされたことを確認するために、次のコマンドを実行します。

```sh
brew --version
```

バージョン情報が表示されれば、インストールは成功です。

## パスの設定の確認・再設定
もし、インストール手順の4の工程の`パスの設定`を忘れていないか確認したい場合は以下の方法をとります。

## パスが設定されているかの確認
1. **シェルの設定ファイルを確認する**
使用しているシェルによって、設定ファイルが異なります。以下のコマンドを使って設定ファイルを確認します。

- **zshの場合**
```sh
cat ~/.zshrc
```

- **bashの場合**
```sh
cat ~/.bash_profile
cat ~/.bashrc
```

2. **Homebrewのパスが設定されているか確認**
設定ファイル内に以下のような行があるか確認します。
```sh
export PATH="/usr/local/bin:/usr/local/sbin:$PATH"
```

または、M1 Mac の場合:
```sh
export PATH="/opt/homebrew/bin:/opt/homebrew/sbin:$PATH"
```

### パスの再設定方法
もしパスが設定されていなかった場合、以下の手順で再設定します。

1. **設定ファイルを開く**
- **zshの場合**
```sh
vim ~/.zshrc
```

- **bashの場合**
```sh
vim ~/.bash_profile
vim ~/.bashrc
```

2. **Homebrewのパスを追加**
設定ファイルに以下の行を追加します。環境によって適切なパスを選んでください。

- **Intel Macの場合**
```sh
export PATH="/usr/local/bin:/usr/local/sbin:$PATH"
```

- **M1 Macの場合**
```sh
export PATH="/opt/homebrew/bin:/opt/homebrew/sbin:$PATH"
```

3. **設定を反映**
設定ファイルを保存した後、以下のコマンドで設定を反映します。

- **zshの場合**
```sh
source ~/.zshrc
```

- **bashの場合**
```sh
source ~/.bash_profile
source ~/.bashrc
```

## 参考
- [【インストール方法から使い方まで】Homebrew についてわかりやすく解説！よく使うコマンドも | キカガクブログ](https://www.kikagaku.co.jp/kikagaku-blog/homebrew-install-howto/)
LLM同士にディベートさせてビジネスプランを作るスクリプト作ってみた

# LLM同士のディベートでビジネスプランを作成する方法

OpenAIのGPTモデルを活用して、LLM（大規模言語モデル）同士にディベートをさせてビジネスプランを作成するスクリプトを作成しました。このプロジェクトのリポジトリは[こちら](https://github.com/takurot/llm_business_plan_debate_with_graphai)です。

## コンセプト

ビジネスプランを作成する際には、さまざまなアイデアや視点を取り入れることが重要です。しかし、これを実現するためには多くの時間と労力が必要です。そこで、OpenAIのGPTモデルを使って、効率的にビジネスプランを生成する方法を考えました。

このスクリプトでは、2つのLLMが指定したテーマについてディベートを行い、その過程でビジネスプランを練り上げていきます。最終的には、生成されたビジネスプランをMarkdown形式で出力し、さらに詳細なアイデアを深堀りすることも可能です。

## 使い方

### 必要なもの

1. **Python**: このプロジェクトはPythonで実装されていますので、Pythonがインストールされている必要があります。
2. **OpenAI APIキー**: OpenAIのGPTモデルを使用するために必要です。OpenAIのサイトからAPIキーを取得してください。

### インストール手順

1. **リポジトリのクローン**:
    ```bash
    git clone https://github.com/takurot/llm_business_plan_debate_with_graphai
    cd llm_business_plan_debate_with_graphai
    ```

2. **必要なライブラリのインストール**:
    ```bash
    pip install openai markdown2
    ```

3. **OpenAI APIキーの設定**: スクリプト内の`your_openai_api_key`を取得したAPIキーに置き換えます。

### スクリプトの実行方法

#### 新しいテーマでディベートを開始する場合

テーマを指定してディベートを開始するには、以下のように実行します：

```bash
python llm_debate_business_plan.py --theme "持続可能なエネルギーソリューション" --iterations 10
```

このコマンドは、持続可能なエネルギーソリューションというテーマで10回のディベートを行います。ディベートの結果として、初期のビジネスプランが`business_plan.md`として保存され、その後、深堀りされたビジネスプランが`deepened_business_plan.md`として保存されます。

#### 既存のビジネスプランを深堀りする場合

既存のビジネスプランファイルを読み込んで、さらにアイデアを深堀りするには、以下のように実行します：

```bash
python llm_debate_business_plan.py --file "business_plan.md" --iterations 5
```

このコマンドは、指定された`business_plan.md`ファイルを読み込み、各セクションに対して詳細なアイデアや改善点を提案し、5回のディベートを行います。深堀りされたビジネスプランは`deepened_business_plan.md`として保存されます。

### コードの概要

#### 主な関数

- **get_llm_response(prompt, role)**: OpenAI APIを使って、指定されたプロンプトに対するLLMの応答を取得します。
- **debate_on_theme(theme, iterations)**: 指定されたテーマに基づいて、LLM同士がディベートを行います。イタレーションの数も指定できます。
- **generate_business_plan(history, theme)**: ディベートの履歴からビジネスプランをMarkdown形式で生成します。
- **deepen_ideas(business_plan_content, iterations)**: 既存のビジネスプランを読み込み、各セクションに対してさらに詳細なアイデアや改善点を提案し、イタレーション数だけディベートを繰り返します。

#### 主な実行部分

- コマンドライン引数に基づいて、新しいテーマでディベートを開始するか、既存のビジネスプランを深堀りするかを判断します。
- 新しいテーマでディベートを行う場合、指定されたテーマとイタレーション数でディベートを行い、ビジネスプランを生成します。
- 既存のビジネスプランを読み込む場合、各セクションに対して詳細なアイデアや改善点を提案し、ビジネスプランを深堀りします。

## まとめ

このプロジェクトは、OpenAIのGPTモデルを活用して、効率的にビジネスプランを生成するための新しいアプローチを提供します。ビジネスプランの作成にかかる時間と労力を大幅に削減できるため、ビジネスアイデアの迅速な展開が可能になります。

興味がある方は、ぜひ[リポジトリ](https://github.com/takurot/llm_business_plan_debate_with_graphai)をチェックしてみてください。そして、フィードバックや提案があれば、お気軽にお知らせください。

---

これで、GraphAIを使用せずにLLMを使ったビジネスプラン生成のプロジェクトについての技術ブログ記事の完成です。この記事が、読者の皆さんにとって有益な情報源となることを願っています。
Linuxで大きいファイルを効率的に削除するためのTips

# はじめに

Linuxでディスク容量を圧迫している大きいファイルを特定し、効率的に削除する方法を紹介します。ディスク容量が少なくなった際や不要な大きいファイルを整理したい場合に役立つコマンド集です。

## 1. ディスクの使用状況を確認する

まずは、ディスクの使用状況を確認しましょう。ディスク全体の容量や使用中の容量、空き容量を確認するには、`df`コマンドが便利です。

```bash
$ df -h
```

`-h`オプションをつけることで、人間にわかりやすい単位（KB、MB、GBなど）で表示されます。

## 2. 大きいディレクトリを見つける

次に、ディレクトリの中でサイズが大きいものを見つけます。特定のディレクトリやそのサブディレクトリのサイズを確認するには、`du`コマンドを使います。

```bash
$ du -h ./ | grep [0-9]G
```

このコマンドでは、現在のディレクトリ（`./`）以下のディレクトリやファイルのサイズを表示し、1GB以上のものだけを`grep`で抽出しています。

## 3. 大きいファイルを直接見つける

もし特定のファイルを見つけたい場合は、`find`コマンドを使うと便利です。次のコマンドで、1GB以上のファイルを検索できます。

```bash
$ find ./ -size +1G
```

`-size +1G`オプションで1GBを超えるファイルを探し、現在のディレクトリ（`./`）以下を再帰的に検索します。

## 4. ファイルをサイズ順にソートして表示

ディレクトリ内のファイルをサイズ順に並べて確認するには、`ls`コマンドを使います。

```bash
$ ls -lS
```

`-lS`オプションで詳細情報付きでファイルをサイズ順にソートして表示します。これにより、特に大きいファイルを一目で確認できます。

## 5. ファイルを削除する

不要なファイルが見つかったら、`rm`コマンドで削除します。たとえば、`test.hoge`というファイルを削除するには次のコマンドを使用します。

```bash
$ rm test.hoge
```

ファイルを削除する際には、本当に削除して良いかどうか慎重に確認してください。誤って必要なファイルを削除すると、データの復旧が難しい場合があります。

## 6. 一定期間経過したファイルをまとめて削除

特定の更新日から一定期間経過したファイルを削除するには、`find`コマンドと`xargs`を組み合わせることができます。例えば、更新日から30日以上経過したファイルを削除するには以下のコマンドを使用します。

```bash
$ find ./ -mtime +30 -name "*.hoge" | xargs rm -f
```

`-mtime +30`オプションは、更新日から30日以上経過したファイルを検索します。逆に、30日以内のファイルを削除したい場合は`-mtime -30`とします。

## 7. ファイルのパーミッションを変更して削除する

削除しようとしたファイルが権限の問題で削除できない場合、`chmod`コマンドでファイルのパーミッションを変更してから削除することができます。

```bash
$ chmod 755 test.hoge
$ rm test.hoge
```

`755`の権限設定は、所有者に読み書き実行権限、グループとその他のユーザーに読み取りと実行権限を与えます。

## まとめ

これらのコマンドを活用すれば、大きいファイルや不要なファイルを素早く特定し、効率的にディスク容量を管理できます。定期的なメンテナンスを行うことで、システムのパフォーマンスを維持し、ディスク容量の圧迫を防ぎましょう。
Git LFSインストール後のgit push無限ループ解決法

# はじめに
　この記事はあくまで個人のメモ的なもので、とりあえず解決した方法を載せたものです。これをしとけば一応解決すると思いますが、もっといい方法があるかもしれません。

# 環境
* Ubuntu 20.04 LST
* git version 2.25.1
* git-lfs/3.5.1 (GitHub; linux amd64; go 1.21.8)

# 事例
Git LFSをインストール後に`git push`をしようとした際に、以下のように`username`と`password`で無限ループに陥った。

```bash
$ git push
Username for 'https://github.com': example
Password for 'https://example@github.com': 
Username for 'https://github.com': 
Password for 'https://github.com': 
Username for 'https://github.com': ^C
Exiting because of "interrupt" signal.
```

# 解決策
　下記のQ&Aを参考に、Gitのパスワードのキャッシュアウト時間を設定した。 
　例では、3600秒間パスワードがキャッシュアウトしないようにすることが出来る。実際にはもっと短くても良いだろう。
```bash
$ git config --global credential.helper 'cache --timeout=3600'
```
https://stackoverflow.com/questions/44549542/cannot-push-to-bitbucket-after-installing-git-lfs

# おわりに
　この事例に関して、日本語の記事やQ&Aがざっと見て見つからなかったので記事にしてみました。今回、私はGitのパスワードのキャッシュアウト時間を設定することで解決しましたが、セキュリティの観点では色々な人に怒られそうな解決法だと思います。（セキュリティ面は詳しくないのでご勘弁を…）再度になりますが、もっといい方法があると思いますので、この方法は応急処置的なものだと考えていただけるとありがたいです。
お問い合わせフォームの設定に関して

## wordpressのcontact form7で設定する場合の注意点
1.送信元の設定
OO株式会社 <noreply@domain.com>
会社名やドメイン名に間違いがないか

2.題名に問題ないか
お問合せの場合、「HPからお問い合わせがありました。」
エントリーの場合、「エントリーからお問い合わせがありました。」

3.メッセージ本文で全ての項目が追加されているか

4.自動送信メールを設定しているか

・送信先のメールアドレスがクライアントのメールになっているか

・送信元の設定ができてるか
例：OO株式会社 <noreply@domain.com>

・題名設定
例：【会社名】お問い合わせありがとうございます

・追加ヘッダー特に指示がなければ空に設定

・メッセージ本文
---------------
例
[name]様

お世話になっております。
OO株式会社へのお問合せありがとうございます。
以下の内容でお問い合わせを受け付けいたしました。

※このメールはシステムからの自動返信です

-----お問い合わせ内容-----
お名前：
メールアドレス：
\----------------------------

OOO株式会社
TEL:00000000
FAX:00000000
メール：test@⚪︎⚪︎.com
住所：〒111-1111　東京都港区●●5-6-7-8
営業時間：平日 ●時～●時


---------------

5.リキャプチャを設定しているか
スパム対策。google設定が必要なので特に先方の指示がなければ必要なし
typosでtypoチェックをしよう

typosはタイポチェックツールです。
恥ずかしい間違いをする前に入れておきましょう！

https://github.com/crate-ci/typos


## 実行サンプル
![CleanShot 2024-08-06 at 12.35.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3442/d8d17c18-2f85-b26d-a8f7-5a3daa822806.png)



## インストール

```
# cargo
cargo install typos-cli

# brew
brew install typos-cli
```

## 使い方

### 設定ファイル

除外したいファイルやキーワードがあれば設定ファイルに記載しておきましょう。

```toml:~/.config/typos.toml
[files]
# envやpubファイル等は除外
extend-exclude = [
    "*.pub",
    "Brewfile",
    "*env*",
]

# 固有のアプリ名や造語を登録
[default.extend-words]
regist = "regist"
```

### 実行方法

実行するとこんな感じで教えてくれます。
コンフィグファイルはXDG_CONFIG(~/.config)を考慮していないようなので、自分でパスを指定する必要があります。必要があれば指定しておきましょう！

```bash
% typos --config ~/.config/typos.toml .

error: `formated` should be `formatted`
  --> ./client/src/components/Map/GroupSearch/MapCanvas.jsx:7:10
  |
7 | import { formatedPin, unfocus } from '../../../libs/map';
```

ファイルパス込みのコマンドをフルで記載するのはしんどいので、aliasかabbrを使うと良いでしょう
僕は、aliasだとそのままhistoryに残るのでabbrで展開して実行するのが好みです。

```bash:.zshrc or .bashrc
alias typos="typos --config ~/.config/typos.toml ."
```


```zsh:zsh/abbreviations
abbr -S typos="typos --config ~/.config/typos.toml ."
```

https://qiita.com/n3_x/items/2a7d5aa0cdc6cdcff40a

## sedで修正

見つけてしまったら直したくなると思うので、findとgsedで修正する方法を書いておきます。
srcを探索して、beforeをafterに置き換えるコマンドです。
sedはBSD系とGNU系があるので注意ですね！

```zsh
# brew install gnu-sed
find ./src/ -type f -exec gsed -i 's/before/after/g' {} +
```

## typosをいつ実行するか？

僕の場合は、LSPとしてnvimに組み込んでいます

![CleanShot 2024-08-06 at 12.25.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3442/0e4e43b2-887a-7c28-b72c-ff792af3aa8c.png)


https://github.com/tekumara/typos-lsp/tree/main

pre-commitやGithub Actionsで対応するのも良さそうです。
お好みの手段で自動的に検知できると嬉しいですね！

https://qiita.com/naro143/items/009af8897643fe990db8

https://qiita.com/lemonade_37/items/23a5a5cbd493801e5f23
inputのnameの設定早見表

<table>
<tr>
<th>姓名</th>
<td>name</td>
</tr>
<tr>
<th>姓</th>
<td>family-name</td>
</tr>
<tr>
<th>名</th>
<td>given-name</td>
</tr>

<tr>
<th>メールアドレス</th>
<td>email</td>
</tr>
<th>会社名</th>
<td>organization</td>
</tr>
<tr>
<th>電話番号</th>
<td>tel</td>
</tr>
<tr>
<th>郵便番号</th>
<td>postal-code</td>
</tr>

<tr>
<th>都道府県</th>
<td>address-level1</td>
</tr>

<tr>
<th>市区町村</th>
<td>address-level2</td>
</tr>
<tr>
<th>番地・マンション名（1行目）</th>
<td>address-line1</td>
</tr>

<tr>
<th>番地・マンション名（2行目）</th>
<td>address-line2 </td>
</tr>
<tr>
<th>生年月日</th>
<td>bday</td>
</tr>
<tr>
<th>生年月日（日）</th>
<td>bday-day</td>
</tr>
<tr>
<th>生年月日（月）</th>
<td>bday-month</td>
</tr>
<tr>
<th>生年月日（年）</th>
<td>bday-year</td>
</tr>
<tr>
<th>性別</th>
<td>sex</td>
</tr>
<tr>
<th>ユーザーネーム</th>
<td>username</td>
</tr>
<tr>
<th>現在のパスワード</th>
<td>current-password</td>
</tr>
<tr>
<th>新パスワード</th>
<td>new-password</td>
</tr>
<tr>
<th>クレジットカードナンバー</th>
<td>cc-number</td>
</tr>
<tr>
<th>クレジット名前</th>
<td>cc-name</td>
</tr>
<tr>
<th>クレジットセキュリティコード</th>
<td>cc-csc</td>
</tr>
<tr>
<th>クレジットセキュリティコード</th>
<td>cc-csc</td>
</tr>
<tr>
<th>クレジット有効期限(月）</th>
<td>cc-exp-month</td>
</tr>
<tr>
<th>クレジット有効期限(年）</th>
<td>cc-exp-year</td>
</tr>



</table>


都道府県はselect要素だと、自動入力が効かないため、input要素にするのことを推奨
生年月日の自動入力はSafariのみ有効。Chromeは未対応
カナ表記に関してルールは特に決まっておりません

## autocompleteを設定する
```<input type="text" name="postal-code" autocomplete="postal-code" />```



## 参考文献
https://ics.media/entry/11221/
https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofill
インスタグラムのフォロワーを買うメリットとデメリットを徹底解説

## はじめに
インスタグラムは、その登場以来、個人の生活やビジネスのマーケティング戦略に革命をもたらしました。フォロワー数が多いことは、ブランドや個人がより広いオーディエンスにリーチするための重要な手段となっています。しかし、フォロワーを購入することは、その即効性と見た目の影響力にもかかわらず、長期的なデメリットを伴うことがあります。

## インスタのフォロワーを買うメリット
### 1. 即時性と視認性の向上
フォロワーを購入することで、アカウントの視認性は瞬時に向上します。これは特に新しいプロダクトやキャンペーンを立ち上げたい企業にとって大きな利点です。短期間で多くのフォロワーを獲得することで、アルゴリズムによる推薦が増え、自然と真のフォロワーも増える可能性があります。

### 2. ブランディングと信頼性の強化
フォロワー数が多いアカウントは、ブランドの認知度を高め、潜在顧客に対する信頼感を即座に構築します。これにより、新たなビジネス機会が開かれ、特に新規事業や新製品に対する市場の受け入れがスムーズになります。

### 3. 広告効果と収益性の増加
多くのフォロワーを持つアカウントは、広告主やブランドにとって魅力的な広告の場所となります。これにより、直接的な広告契約やアフィリエイトマーケティングの機会が増え、それに伴い収益も増加します。また、フォロワーの数は、投資家やパートナー企業にとっても魅力的な指標となり得ます。

## インスタのフォロワーを買うデメリット
### 1. 信頼性の損失と偽の印象
購入したフォロワーは実際のエンゲージメントや興味を持っていないため、時間が経つにつれてそのアカウントの活動が本物ではないことが露呈するリスクがあります。このような行為は、長期的にはブランドの信頼性を損ね、真の顧客やフォロワーからの信頼を失うことにつながります。

### 2. エンゲージメント率の低下
購入したフォロワーは通常、エンゲージメントを提供しません。これにより、エンゲージメント率が低下し、Instagramのアルゴリズムによってアカウントの露出が減少します。この結果、本当にブランドに興味を持っているユーザーの目に止まる機会が減少することになります。

### 3. ポリシー違反とそのリスク
インスタグラムは、フォロワーの購入や不正な方法でのエンゲージメントを明確に禁止しています。これらの規則を破ると、アカウントが警告を受けるだけでなく、最悪の場合、削除される可能性があります。このようなペナルティは、ブランドのオンラインでの存在感に大きな打撃を与えることがあります。

## 比較分析
自然な方法でフォロワーを増やす戦略は、真のエンゲージメントと持続可能な成長を促します。一方で、フォロワーを購入する戦略は、短期的な利益をもたらす可能性がありますが、長期的なリスクを伴います。

## ケーススタディ
実際にフォロワーを購入したブランドの事例では、当初は注目を集めましたが、エンゲージメントの低さとフォロワーの質の問題が露呈し、最終的にはブランドの評価が下がる結果となりました。このケーススタディは、短期的な成功が長期的な失敗につながることの一例です。

## 結論
インスタグラムのフォロワーを購入することは魅力的な選択肢に見えるかもしれませんが、持続可能なブランドとコミュニティを築くためには、自然な成長を選ぶべきです。真のファンとの関係を大切にし、品質の高いコンテンツでエンゲージメントを高めることが成功の鍵です。

## FAQ
Q1: フォロワーを購入する主なリスクは何ですか？
A1: アカウントの信頼性損失、エンゲージメントの低下、そしてInstagramの規約違反によるアカウントの停止や削除があります。

Q2: 自然にフォロワーを増やす方法は？
A2: 定期的な高品質な投稿、ターゲットオーディエンスとの積極的なエンゲージメント、及びコンテストやキャンペーンを通じてのユーザーとの交流が効果的です。
git使い方memo



#01 Git､GitHubについて学ぼう							https://dotinstall.com/lessons/basic_gitgithub_branches
#03 WindowsにGitをインストールしよう							https://dotinstall.com/lessons/basic_gitgithub_remotes
#04 git configで各種設定を進めていこう							
	作業用フォルダの設定						
	ターミナルの起動						
	git --version						
	git config						
							
#05 作業の流れを確認しよう							
	作業の流れ						
	リポジトリ						
	コミット						
	ワーキングディレクトリ						
	ステージングエリア						
	git init						
	git add						
	git commit						
	git log						
							
#07 git statusで状況を確認しよう							
#08 git logで履歴を確認してみよう							
#09 変更内容を確認してみよう 							
#10 git diffで差分を確認してみよう							
#11 直近のコミットメッセージを修正しよう 							
#12 直近のコミット内容を修正しよう 							
#13 git checkoutで過去に戻ってみよう							
#14 git add .を使ってみよう							
#16 .gitignoreを設定してみよう							
#17 git resetの挙動を理解しよう							
							
							
#01 ブランチを使ってみよう 							
#02 コミットを保存していこう							
#03 ブランチを操作してみよう							
#04 mainブランチに切り替えてみよう							
#05 マージの挙動について理解しよう							
#06 ブランチをマージしてみよう							
#07 ブランチを削除してみよう							
#08 ブランチの作成､切替えを同時に行ってみよう							
#09 mainブランチにもコミットを保存しよう							
#13 コンフリクトを解消していこう							
				#15 git rebaseの挙動を理解しよう			
							
#01 リモートリポジトリを扱ってみよう 							
#02 GitHubでリポジトリを作ってみよう 							
#03 ローカルリポジトリを設定しよう							
#04 作業の流れを確認しよう							
#05 git remoteコマンドを使ってみよう							
#06 git pushコマンドを使ってみよう							
#07 GitHubでリポジトリを確認していこう 							
#08 GitHubで新しいコミットを作ってみよう							
#09 git fetchコマンドを使ってみよう							
#10 リポジトリの同期を完了させよう 							
#11 プルリクエストについて理解しよう							
#12 プルリクエストを作ってみよう							
#13 プルリクエストの詳細を確認しよう							
#14 ローカルリポジトリを更新しよう							
#16 Windowsでリポジトリをダウンロードしよう							
#17 リモートリポジトリを削除してみよう
プロダクトマネージャーの挑戦: SlackとZendeskのサポートシステムをFoqalに移行した話

こんにちは、プロダクトマネージャーをしているToruです。今回は、SlackとZendeskの双方向サポートシステムをFoqalに移行した経験について共有したいと思います。
背景
Slackを利用したサポートは、ますます一般的になってきています。しかし、Slack上でのサポートは、タスクの管理が難しく、ワークロードが増加する傾向があります。従来のチケットシステムに戻すのは簡単ですが、それでは柔軟性が失われます。
Foqal導入の経緯
多くのサポートツールを比較した結果、私たちのチームはFoqalを選びました。その理由は、Foqalが提供する柔軟なワークフローと自動化機能、そして知り合いの会社での成功事例が大きかったです。
Foqalの特徴
絵文字によるチケット起票とワークフロー設定: 特定の絵文字を使って簡単にチケットを起票し、それに対応するワークフローを設定できます。
チャンネル毎のワークフロー: パートナー向けや社内向けのチャンネルで異なるワークフローを設定し、特定のテンプレートを使用できます。
Zendeskのフォームテンプレートとの同期: Slack上でZendeskと同様のフォームを表示し、必要な情報を入力してもらうことが可能です。
一斉通知機能: サポートの休止期間など、重要なお知らせを特定のチャンネルやタグに一斉に通知できます。
導入プロセス
Foqalの導入にあたり、Zendesk Sandboxを使って設定を確認しました。Foqalの柔軟なワークフロー設定には多少のクセがありましたが、Foqalのチームによる手厚いサポートのおかげでスムーズに導入できました。
今後の展望
現在、Slackからのチケットを日に20件ほど処理しています。今後も社内外からの問い合わせにスムーズに対応できるよう、Foqalを活用していきます。

この記事では、Foqalの具体的な機能とそのメリット、導入プロセスについて詳しく紹介しています。プロダクトマネージャーやサポートエンジニアの方々にとって、有益な情報が満載です。ぜひご一読ください！
https://blog.torut.tokyo/entry/2024/04/21/143119
Ubuntuでchromedriverをインストールするとき困ったこと

下記の文を参考にUbuntuでスクレイピング環境を構築中で、困ったことがあったので補足します。

https://qiita.com/Moh_no/items/a835f77b6b4e3972fbbe

対象はこちらです。

```shell
$ sudo sh -c 'echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list'
$ sudo wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
$ sudo apt-get update
$ sudo apt-get install google-chrome-stable
```

## キーリング管理

```shell
$ sudo wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
```

上記コマンドで警告発生

```shell
Warning: apt-key is deprecated. Manage keyring files in trusted.gpg.d instead (see apt-key(8)).
```

## 対策

1. GPGキーダウンロード

```shell
wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub > /usr/share/keyrings/google-linux-signing-key.gpg

```

**error**

次のエラーが発生した場合

```shell
-bash: /usr/share/keyrings/google-linux-signing-key.gpg: Permission denied
```

コマンドを下記に変更

```shell
sudo wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo tee /usr/share/keyrings/google-linux-signing-key.gpg
```

2. aptアップデート

```shell
echo "deb [signed-by=/usr/share/keyrings/google-linux-signing-key.gpg] http://dl.google.com/linux/chrome/deb/ stable main" | sudo tee /etc/apt/sources.list.d/google-chrome.list
```

3. パッケージアップデート、インストール

```shell
sudo apt update
sudo apt install google-chrome-stable
```

**error**

次のエラーが発生した場合

```shell
E: Conflicting values set for option Signed-By regarding source http://dl.google.com/linux/chrome/deb/ stable: /usr/share/keyrings/google-linux-signing-key.gpg !=
E: The list of sources could not be read.
```

複数のsigned-byオプションが設定しているので長谷資した不具合。
重複項目の削除が必要。

コマンドを下記に変更

```shell
sudo wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo tee /usr/share/keyrings/google-linux-signing-key.gpg
```

3-1. apt一覧確認

```shell
grep -r "google-linux-signing-key.gpg" /etc/apt/sources.list /etc/apt/sources.list.d/
```

3-2. 重複項目削除

```shell
sudo vim /etc/apt/sources.list.d/google-chrome.list
```

3-3. 次のファイル内容を確認

```
deb [signed-by=/usr/share/keyrings/google-linux-signing-key.gpg] http://dl.google.com/linux/chrome/deb/ stable main
```

ほかのファイルにも同様の設定があったら削除します。
【PHP】スーパーグローバル変数$GLOBALS


## $GLOBALSとは

$GLOBALSとは、PHPの定義済み変数のひとつで、グローバルスコープで使用可能な全ての変数への参照を含む配列となっています。

つまり、関数の中でグローバル変数を参照したい場合に$GLOBALSを使用します。

> ローカル変数：関数の中で定義され、関数の中でのみ生存 
> グローバル変数：関数の外で定義され、関数の外でのみ生存


## サンプル

+ $GLOBALSは、キーにグローバル変数名を指定してあげることで変数を参照できる。

```php:例1
<?php

// グローバル変数
$global_number = 'グローバルな数字です';
$global_name = 'グローバルな名前です';

function test1_func() {
    // ローカル変数 (未定義のためエラー)
    echo $global_number;
    echo $global_name;

    // 関数内でグローバル変数を取得
    echo $GLOBALS['global_number'];
    echo $GLOBALS['global_name'];
}
test_func();

実行結果
グローバルな数字です
グローバルな名前です
```

---


+ $GLOBALSは、配列が格納されている場合も添字を続けて指定することで参照できる。

```php:例2
<?php

// グローバル変数
$name = ['sato', 'tanaka', 'yamada'];
$birthday = [
    ['1980/01/01', '1980/04/01', '1980/07/01'],
    ['1990/02/01', '1990/05/01', '1990/08/01'],
    ['2000/03/01', '2000/06/01', '2000/09/01']
];
$gender = [
    'sato' => 'man',
    'tanaka' => 'woman',
    'yamada' => 'man'
];

function test2_func() {
    // 関数内でグローバル変数を取得
    echo $GLOBALS['name'][2];
    echo $GLOBALS['birthday'][2][0];
    echo $GLOBALS['gender']['yamada'];
}
test2_func();

実行結果
yamada
2000/03/01
man
```

---


+ $GLOBALSは、変数にオブジェクトが格納されている場合は、アロー演算子「->」を利用することでプロパティやメソッドを参照できる。

```php:例3
<?php

class User {

    public $name;
    public $age;

    public function __construct($name, $age) {
        $this->name = $name;
        $this->age = $age;
    }

    public function view() {
        echo "名前は{$this->name}です<br>";
        echo "年齢は{$this->age}歳です<br>";
    }
}

$user = new User('tanaka', 25);

function test3_func() {
    // 関数内でインスタンスプロパティの取得
    echo $GLOBALS['user']->name."<br>";

    echo $GLOBALS['user']->view();
}
test3_func();

実行結果
tanaka
名前はtanakaです
年齢は25歳です
```

---


+ $GLOBALSを利用してグローバル変数の値を設定することもできる。

```php:例4

<?php

class User {

    public $name;
    public $age;

    public function __construct($name, $age) {
        $this->name = $name;
        $this->age = $age;
    }

    public function view() {
        echo "名前は{$this->name}です<br>";
        echo "年齢は{$this->age}歳です<br>";
    }
}

// グローバル変数
$number = 100;
$array = [1,2,3,4,5];
$user = new User('tanaka', 25);

function test4_func() {
    // キーにグローバル変数を指定し値を設定
    $GLOBALS['number'] = 200;

    // 配列の場合はグローバル変数と添字を指定し値を設定
    $GLOBALS['array'][4] = 55;

    // アロー演算子を利用してインスタンスプロパティの値を設定
    $GLOBALS['user']->name = 'sato';
    $GLOBALS['user']->age = 40;
}
test4_func();

echo $number."<br>";
echo $array[4]."<br>";
$user->view();

実行結果
200
55
名前はsatoです
年齢は40歳です
```

:::note alert
注意
「$GLOBALS」と「global」は関数内でグローバル変数を参照できる点は一緒だが
グローバル変数の参照方法が異なるので違いに注意
:::

> $GLOBALSはスーパーグローバル変数です（定義済みの変数）。
> globalキーワードは、あくまでもその関数内で使うその変数のスコープをグローバルにするというだけのものです。
> （その変数自体がスクリプト全体に対してグローバルになるわけではありません）

## 参考
+ [PHP 公式リファレンス](https://www.php.net/manual/ja/reserved.variables.globals.php)
+ [【初心者向け】phpの$GLOBALSとは？特徴と使い方を徹底解説](https://webukatu.com/wordpress/blog/34412/)
+ [教えて!goo](https://oshiete.goo.ne.jp/qa/7438182.html)

<br>
著者: E.R (株式会社ウィズツーワン)
【ChatGPT＋Code Interpreter】で文章を横に移動する。


　どうも、カーブミラーです。

　今回は、文章を横に移動します。

:::note info
本記事は、ChatGPT（有料版）
で行なっております。画像は
あります。　あしからず。
:::

　まずは、ニュース。

　動画生成AIである
　　Runway Gen-3 Alphaにも
　　　画像から動画を作成できる
　　　　機能が追加されました。

　画像をスタートに使うこと、
　　エンドに使うことが
　　　できるようになりました。

　もちろん、
　　テキスト（Prompt）とともに
　　　使うこともできます。

　詳しくはこちらをどうぞ。
[Runway公式ポスト](https://x.com/runwayml/status/1820450326383669564?t=6lUUobwynhiq-msWK16VSw&s=03)
***
　次は、NoLangに関してです。

　日本の動画生成AI（？）である
　　NoLangのStandard以上のプランで、
　　　クレジットを追加購入
　　　　できるようになりました
[マーベリック公式ポスト](https://x.com/sayhi2ai_jp/status/1820231701655961715?t=6NhrfuEwa6J4tV8gg3dxFA&s=03)
***
　さて、本題です。

　昨日（2024/08/05）は
　　文字を一文字ずつ出す
　　　アニメGIFを作成しました。
[【ChatGPT＋Code Interpreter】で文字列を一文字ずつ出すアニメGIFを作成します。](https://qiita.com/kabumira/items/a487f89d6301b4c83132)

　どうやら
　　タイプライター風テロップと
　　　呼ばれるもののようですね。
　　　　知りませんでした。

　今回は、
　　一文字ずつではなく、
　　　文章を横に移動させます。

　出来上がりがこちら。
![chatgpt_animation (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457238/16c28c79-3451-c37d-1e58-34d7657bce7b.gif)

　Promptがこちらです。
```Text:
CodeInterpreterで、白い正方形（512×512）の中央に、“I am a ChatGPT.”という文章を黒色で、フォントサイズを48で、右から左へとテロップみたいに出して左側に消えていくアニメGIFを作成してください。
コードは不要です。
指示に不明な点があれば質問してください。
```

　詳細説明は省きますが、
　　ひとつだけ。

　“左側に消えていく”を
　　入れないと、文章すべてが
　　　表示されたところで
　　　　止まります。

　場合によっては
　　入れないやり方を
　　　取る必要があるかもしれません。
***
　ここからは
　　蛇足ですが、
　　　Promptを
　　　　わかりやすくしたいと
　　　　　思います。

　理由は
　　上記Promptでは
　　　設定と処理が混在していて、
　　　　読みにくい。

　　また、
　　　変更を加える際に
　　　　どこを変更すればよいかを　　　　　　　わかりやすくするためです。

　とりあえず、やり取りをどうぞ。
　　セッションの続きです。
***
***user***
指示Promptをわかりやすくしてもらえますか？
コード不要です。
実行も不要です。

***GPT-4o***
わかりやすい指示の例は以下の通りです：

---

1. 512×512ピクセルの白い正方形画像を作成する。
2. 中央に「I am a ChatGPT.」という文章を黒色で描画する。
    - フォントサイズは48
    - フォントは任意の読みやすいもの（例：DejaVuSans-Bold）
3. 右から左へと文字がテロップのように移動して、左側に消えていくアニメーションGIFを作成する。
    - 全体のフレーム数は60（1秒あたり30フレーム）
    - 文字が画面の右端から左端に完全に移動するように配置する
4. 完成したGIFを保存する。

---

***user***
初期設定と処理内容に分けてください

***GPT-4o***
以下のように初期設定と処理内容に分けて指示をわかりやすくしました。

---

### 初期設定

1. 画像のサイズ：512×512ピクセル
2. 背景色：白
3. テキスト：「I am a ChatGPT.」
4. テキストの色：黒
5. フォントサイズ：48
6. フォント：DejaVuSans-Bold（または同等の読みやすいフォント）
7. フレーム数：60（1秒あたり30フレーム）

### 処理内容

1. 512×512ピクセルの白い正方形画像を作成する。
2. 中央に「I am a ChatGPT.」という文章を黒色で描画する。
    - フォントサイズは48
    - フォントはDejaVuSans-Bold
3. 右から左へと文字がテロップのように移動して、左側に消えていくアニメーションGIFを作成する。
    - 文字が画面の右端から左端に完全に移動するようにフレームごとに配置する
4. 完成したGIFを保存する。

---

***user***
初期設定と処理内容（設定はすでに初期設定にあるので、変数名だけにする）を書き出して

***GPT-4o***
了解しました。初期設定と処理内容を以下のように書き出します。

---

### 初期設定

1. 画像のサイズ: `width = 512`, `height = 512`
2. 背景色: `bg_color = (255, 255, 255)` （白）
3. テキスト: `text = "I am a ChatGPT."`
4. テキストの色: `text_color = (0, 0, 0)` （黒）
5. フォントサイズ: `font_size = 48`
6. フォントパス: `font_path = "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf"`
7. フレーム数: `frames = 60` （1秒あたり30フレーム）

### 処理内容

1. 白い正方形画像を作成する。
2. 画像中央にテキストを描画する。
3. テキストを右から左へと移動させ、左側に消えていくアニメーションGIFを作成する。
    - 各フレームにおけるテキストの位置を計算して配置する (`x`, `y`)
4. GIFを保存する (`gif_path`).

---
***

　最後のPromptでは
　　Code Interpreterの使用を
　　　宣言していませんが、
　　　　別のセッションで
　　　　　実行したところ、
　　　　　　問題なく実行できました。

　まぁ、私個人としては
　　宣言したいところですが😅

　みなさんの
　　作品制作の糧に
　　　なれば、幸いです。

　今回は、ここまで。
新生成AIモデルChatGPT-4oは一人情シスの救世主！–情報システム部門を刺激するメディア「情シスのじかん」より

「情シスのじかん」は、情報システム部門のプロフェッショナルを対象としたメディアです。実務に役立つノウハウや革新的なアイデアを提供し、学びとネットワーキングの場を提供することを目指しています。最新の技術動向やベストプラクティス、成功事例を通じて、情シス担当者のスキルアップをサポートします。

「情シス『目』ニュース」では、日々発信されるさまざまなトピックスを情シス・エンジニアの方々向けに「再解釈」した情報を掲載中。AI、働き方、経済など幅広いニュースをピックアップし、業務に役立つほか、つい同僚に話したくなる面白い話題まで身近で自分事化しやすくお届けします。

### 新生成AIモデルChatGPT-4oは一人情シスの救世主！–情シスの「目」ニュース
![josys-eye-01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3816554/1307e758-beb8-038c-4498-635b7ec3028e.jpeg)

今回の注目ニュースは、すでにご存じの方も多いであろう「最新の生成AIモデル、ChatGPT-4o」の登場についてです
https://josys.wingarc.com/chatgpt-4o

### 情報システム部門を刺激するメディア「情シスのじかん」とは？
![情シスのじかんbyWingArc1st (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3816554/89afaa7e-b941-a10a-c813-8485daca4502.png)

初めまして、『情シスのじかん』です。
近日遂に、日本中の情シス部門のあなたを刺激するメディアが発足します！🚨
さぁ、テクノロジーを飼い慣らし、仕事や生活の質を向上させ、一緒に未来を切り拓きましょう。皆様の生活リズムに合わせた情報発信で、常に寄り添い、共に未来を切り拓くためのメディアです。

ぜひ、情報システム部門の皆様の活動の取材をさせてください。

https://josys.wingarc.com/about
Gradioは趣味の技術なのか？

## 求人 0 件
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54688/f3031ddf-d700-877b-d3ad-2ae918ac6872.png)

画像の通り、まったく私の仕事探しに役立ちそうにないです。

## 趣味で頑張ろう
ZeroGPU始めたばかりで、gradioもう少し勉強しようかと思ったが仕事決まってからにしよう。
iPhoneの実機からMacのlocalhostに接続する方法

Mac上のモック化されたAPIサーバーにiPhoneの実機から接続する方法です。

# 手順
* iPhoneのインターネット共有を有効にします
* MacからiPhoneのネットワークを利用するようにネットワーク設定を変更します
* MacのIPアドレスを調べます
* MacのIPアドレスをコードで指定します(例: `http://172.20.10.2/hoge.json` )
* iPhoneの実機からAPIなどを実行します

参考
https://ishwar-rimal.medium.com/accessing-macs-localhost-on-your-iphone-5d564a387f09
【小ネタ】diffコマンドの終了ステータスを変更する

## 背景
diffは2つのファイルを比較し、その差分を表示するコマンドです。
diffコマンドの終了ステータスは、次の3パターンです。
- `0`: 差分なし
- `1`: 差分あり
- `2以上`: エラー

今回、GitHub Actions内で二つのファイルの差分を出力しようとしたところ、この仕様によりGitHub Actionsが失敗扱いになってしまいました。
単に差分だけを表示したい場合、差分がある場合も正常終了となるのが望ましいです。
この記事では、diffコマンドの終了ステータスを書き換えるスクリプトを、自分用のスニペットも兼ねて紹介します。

## コード
```bash
#!/bin/bash
diff -u old new >> /dev/stdout || exit_code=$?
if [[ $exit_code = 1 ]]
then
  :
else
  (exit $exit_code)
fi
```

### 解説
```sh
diff -u old new >> /dev/stdout || exit_code=$?
```
まず、diffコマンドが「差分あり（終了ステータス`1`）」または「エラー（終了ステータス`２`以上）」を返した場合に、その終了ステータスを`exit_code`変数に保存します。

`||`はシェルスクリプトの演算子で、左側のコマンドが失敗した場合のみ右側のコマンドが実行されます。
`$?`は一つ前のコマンドの終了ステータスが格納されている変数で、今回は`0`以外が入ります。


```sh
if [[ $exit_code = 1 ]]
then
  :
else
  (exit $exit_code)
fi
```

終了ステータスが`1`の場合は何も処理を行わず(`:`)、それ以外はステータスコードを`exit`コマンドに渡して終了します。
diffが正常終了していた場合、`exit_code`は空なので、ステータス`0`で終了します。
それ以外のdiffコマンドのエラーの場合は、そのエラーコードが`exit`コマンドにそのまま渡されます。

もし差分が**ない**場合をエラーにしたい場合は、`exit_code`が空の場合の条件分岐を追加してください。

### 終了ステータス
#### 差分あり => 正常終了
```sh
--- old 2024-08-06 10:23:00
+++ new 2024-08-06 09:43:12
@@ -0,0 +1 @@
+a
```

```sh
$ echo $?
0
```

#### 差分なし => 正常終了
```sh
echo $?
0
```

#### ファイルが存在しない => エラー
```sh
diff: old: No such file or directory
```

```sh
$ echo $?
2
```

## 終わりに
diffコマンドに限らず、シェルスクリプト内でコマンドの通常の終了ステータスを書き換えたい状況は時々発生します。
diffコマンドは特に、終了ステータスが他のコマンドと比べて独特なため、参考になれば幸いです。
Javaのprintf機能： System.out.printfメソッドの使い方とフォーマット指定子

Javaでは```printf```関数が直接的に提供されるわけではありませんが、```System.out.printf```メソッドを使用して同様の機能を実行することができます。 ```System.out.printf```は```PrintStream```クラスのメソッドで、特定の形式に合わせてフォーマットされた文字列を出力する役割をします。

### 基本的な使い方

```System.out.printf```メソッドは、次の形式を持ちます:

```java
javaコードをコピーする
public class Main {
    public static void main(String[] args) {
        int number = 10;
        double doubleNumber = 3.14159;
        char character = 'A';

        // 整数出力
        System.out.printf("整数: %d\n", number); // 出力: 定数: 10

        // 浮動小数点数字出力
        System.out.printf("浮動小数点数字: %f\n", double Number); // 出力: 浮動小数点 数字: 3.141590

        // 文字出力
        System.out.printf("文字: %c\n", character); // 出力: 文字: A
    }
}
```

上記の例題で```System.out.printf```メソッドは、```System.out```オブジェクトを使用して標準出力にフォーマットされた文字列を出力します。 ここで使用されたフォーマット指定者は、C言語の'printf'関数と同じ形式を持ちます。

### 主要フォーマット指定者

ジャワで使用される主なフォーマット指定者は以下の通りです:

- ```%d```: 10進数の整数を出力します。
- ```%f```: 浮動小数点の数字を出力します。
- ```%c```: 文字を出力します。
- ```%s```: 文字列を出力します。
- ```%b```: boolean値を出力します('true' または 'false')。
- ```%n```: 新しい行に対するプラットフォーム-独立した行の改行文字列を出力します。

### フォーマット指定者オプション

フォーマット指定者の後には、オプションを追加して出力の正確な形式を指定できます。 例えば:

- ```%d```は基本的に右揃えですが、```%10d```のように数字を入れて左揃えを特定できます。
- ```%f```は基本的に小数点以下6桁まで出力するが、```%.2f```のように数字を入れて小数点以下2桁まで出力できます。

### 例外処理

Javaの```printf```メソッドは、フォーマット指定者とパラメータのタイプが一致しない場合、```Illegal Format Exception```例外を発生させます。 したがって、フォーマット指定子とパラメータのタイプを一致させることが重要です。

### 結論

Javaでは、```System.out.printf```メソッドを通じて、C言語の```printf```関数と類似した機能を提供します。 これを利用してテキストを特定の形式に合わせて出力したり、ファイルのフォーマットに合わせてデータを保存するなどの作業を行うことができます。
ユーザー認証：DeviceとSorcery

# はじめに
ユーザー認証機能について、スクール内の課題の中ではSorceryを使用していました。今回、アプリ作成にあたり改めて調べてみるとDeviceというものがあることを知りました。なのでDeviceとSorceryは何が違うのか等、調べたことをアウトプットしたいと思います。

# ユーザー認証について
認証機能とは、ユーザーが自己の身元を証明し、システムへのアクセス権を得るプロセスを指します。

## 1. Device

### 特徴
- **フル機能**: ユーザー登録、ログイン、ログアウト、パスワードリセット、セッション管理など、多くの機能があらかじめ用意されている。
- **カスタマイズ性**: オプションで機能を追加したり、設定を変更したりできる。

### メリット
- **簡単に導入できる**: 初心者でも比較的簡単に設定できる。
- **ドキュメントが豊富**: 公式のドキュメントが充実しているので、困ったときに参考にしやすい。

### デメリット
- **重い**: 多機能が故に、必要ない機能も含まれていることがある。
- **カスタマイズが難しい場合がある**: デフォルトの動作を変更するにはやや手間がかかることも。

### 使用ケース
- 大規模なアプリや、ユーザー管理が重要なアプリに適している。

---

## 2. Sorcery

### 特徴
- **軽量**: 必要最低限の機能があり、シンプルな構造。
- **柔軟性**: 自分のアプリに合わせた機能を選んで実装できる。

### メリット
- **軽い**: 不要な機能を省けるので、アプリが軽くなる。
- **カスタマイズしやすい**: 自由に機能を追加したり変更したりできる。

### デメリット
- **ドキュメントが少なめ**: Deviceに比べて情報が少ないため、初心者には難しく感じるかも。
- **機能追加が必要**: 基本機能が少ないので、必要な機能を自分で追加する必要がある。

### 使用ケース
- シンプルなアプリや、特定の要件があるアプリに向いている。

---

## アプリ作成初心者にはどちらがいいか
- **Device**がオススメとされているそうです。多機能でドキュメントも豊富だから、学びやすいし、すぐに使える状態になるため。。

---

## おまけ：これらのgemの由来
- **Device**: 2010年に登場し、Railsアプリケーションのユーザー認証を簡素化することを目的に作られた。
- **Sorcery**: 2011年にリリースされ、シンプルさとカスタマイズ性を重視して作られた。

## 参考になりそうなサイト

https://zenn.dev/junki555/articles/e4172b3b79c29e

https://zenn.dev/m_ole0/articles/c6da054738d0bc
ニューラルネットワーク関連リンク集

## ディープラーニングにおける中間層の役割とは？基本的な仕組みや考え方を解説

https://dl.sony.com/ja/deeplearning/about/middle_layer.html

## 生成AIエージェントの実装入門

https://qiita.com/YutaroOgawa2/items/cb5b1db9f07a1c4f3f54
[paiza]本の整理 (paizaランク A 相当)

# なんだかんだでAランクまで来ちゃったよ。。。
最初にSランクの簡単そうなやつを1問解いてから、Dランクで無双がしたいという浅はかな理由で始めて、C・Bと特に面白いことも言えずにダラダラ解いて来たけど、とうとうAランク問題に突入しました。

https://paiza.jp/works/mondai/real_event/book_sort

# 面倒くさいので画面パタメータをListでもらった後のFunctionだけ
ちなみに引数のListを作ってる箇所は[こっちの記事](https://qiita.com/AsilHatake/items/842548e48ae4a0eae119)に書いてあるYO!!

```javascript:bookSort.js
// [問題文（原文）]
// あなたはパイザ図書館で働く図書館員です。
// 
// パイザ図書館には N 冊の蔵書があります。この蔵書はすべて 1 段からなる本棚で管理されています。そして、それぞれの本には 1 から N までの相異なる整数の ID がついています。本棚の本は ID 順に並んでいます。
// 
// しかし、ある日、あなたが蔵書の点検をしていると、本棚の本がバラバラに並べられていることに気づきました。
// そこで、あなたは、次のルールに従って本を並び替えることにしました。
// 
// 次の手順を N 回繰り返す。
// 
// 1. i (1 ≦ i ≦ N) 回目の手順では、まず本棚の左から i 番目の位置に立つ。
// 2. 左から i 番目の位置にある本から、本棚の右端にある本までのうち、最も ID が小さい本の位置を歩きながら見つける。この位置を j とする。
// 3. i = j なら、何もしない。 i ≠ j なら、i 番目の本と j 番目の本を入れ替える。
// 
// 
// 本を取り出して入れ替えるのには時間がかかります。そこで、このルールに従って本を整理するときに、何回本を入れ替える必要があるのかを計算してください。
// 
// 例)
// 
// 5 冊の本が、本棚に次の順番で並んでいたとします。ただし、数字はそれぞれの本の ID を表します。
// 
// 5 4 3 2 1
// 
// このとき、ルールに従うと、次のように本が整理されます。
// 
// i = 1 のとき (1 番目の本と 5 番目の本の位置が入れ替わる)
// 
// 1 4 3 2 5
// 
// i = 2 のとき (2 番目の本と 4 番目の本の位置が入れ替わる)
// 
// 1 2 3 4 5
// 
// i = 3 のとき
// 
// 1 2 3 4 5
// 
// i = 4 のとき
// 
// 1 2 3 4 5
// 
// i = 5 のとき
// 
// 1 2 3 4 5
// 
// 本の交換は i = 1 のときと i = 2 のときのみ起こっているので、このときの出力は 2 となります。
function bookSort(lines) {
  // 入力は以下のフォーマットで与えられます。
  // 
  // N
  // a_1 a_2 ... a_N
  // 
  // ・1 行目に本の冊数を表す整数 N が与えられます。
  // ・2 行目に、 1 番目の本の ID を表す整数 a_1、 2 番目の本の ID を表す整数 a_2、 ...、 N 番目の本の ID を表す整数 a_N がこの順に半角スペース区切りで与えられます。
  // ・入力は合計で 2 行となり、末尾に改行が 1 つ入ります。

  // 入力チェック面倒くさいので正常系のみ対応するよ
  let list = lines[1].split(" ").map(v => Number(v));
  let swapCnt = 0;
  for (let i = 0; i < list.length; i++) {
    let min = list[i];
    let minIdx = i;
    for (let j = i + 1; j < list.length; j++) {
      if (list[j] < min) {
        min = list[j];
        minIdx = j;
      }
    }
    if (minIdx !== i) {
      let tmp = list[i];
      list[i] = list[minIdx];
      list[minIdx] = tmp;
      swapCnt++;
    }
  }

  // 本の交換をする回数を整数で出力してください。
  console.log(swapCnt);
}

module.exports = {
  bookSort
};
```

ソートって結構色々種類あるけど、これは **選択ソート**になるのかな？