OmniAICreator/Qiita-1.07M huggingface dataset:
[javascript]関数の合成

# 関数の合成

* 関数型プログラミングではロジックを分割して、小さな関数として定義する
* 関数は純粋関数であること（以下の特性を持つ）
    * 引数を取り、戻り値を返す
    * 引数はイミュータブル
    * 副作用は発生させない
* それらの関数を合成して、ロジックを完成させる。

# 実装例（ひらがなと半角英数への文字列変換）

* 引数の文字列をひらがなと半角英数に変換する
* 検索文字列と検索対象の文字列を統一してフィルタ検索するのに使ったりする。
* 処理の流れは以下。各処理は前処理の戻り値を引数にし、変換処理を行い、次の処理へ結果の文字列を渡す。
    * IN：対象文字列
    * 1.大文字変換→2.全角カナ変換→3.ひらがな変換→4.半角（英数）変換
    * OUT：変換後の文字列
* ※変換処理の詳細については、今回の記事の趣旨でないため割愛（ちなみに、この順序で変換する必要がある）

## 関数合成を利用しない場合（駄目な例）

* 関数の合成を使用しない例
* 関数が入れ子になっており、処理を追いづらい
* 関数の追加や削除があった際に改修が面倒

```typescript
// 2.全角カナ変換
function halfKanaToFullKana(str: string) {
  // 半角カナ→全角カナ変換は、変換表で愚直に置き換える必要がある。(KanaMap)
  const regExp = new RegExp(`(${Object.keys(KanaMap).join('|')})`, 'g');
  return str
    .replace(regExp, function (match) {
      const key = match as keyof typeof KanaMap;
      return KanaMap[key];
    })
    .replace(/ﾞ/g, '゛')
    .replace(/ﾟ/g, '゜');
}

// 3.ひらがな変換
function kanatoHira(str: string) {
  return str.replace(/[\u30a1-\u30f6]/g, function (s) {
    return String.fromCharCode(s.charCodeAt(0) - 0x60);
  });
}

// 4.半角(英数)変換
function fullToHalf(str: string) {
  return str.replace(/[！-～]/g, function (s) {
    return String.fromCharCode(s.charCodeAt(0) - 0xfee0);
  });
}

// 1.大文字変換→2.全角カナ変換→3.ひらがな変換→4.半角（英数）変換
// 再帰処理のため、内側の関数から外側に向かって処理が実行されている。
// 修正も困難であるし、関数が増えたらすごく読みづらい！！
export function toSearchWord(str: string) {
  return fullToHalf(kanatoHira(halfKanaToFullKana(str.toUpperCase())));
}

// 実行
const word = searchWordFunction('あアaAｱＡ');
console.log(word); // ああAAあA

```

## 関数合成を利用する場合（良い例）

* 関数を持ち回すため変数に格納する（関数第一級オブジェクトの特性）
* 高階関数とreducerによる再帰処理を行う関数を用意する（compose関数）
* compse関数の引数に、合成する関数の配列を指定することで、関数合成によるロジックの完成

```typescript

// 1.大文字変換
// 関数合成で使用するため、組み込み関数をラップして変数で持ち回す。
const covertUpperCase = (str: string) => str.toUpperCase();

// 2.全角カナ変換
const halfKanaToFullKana = (str: string) => {
  const regExp = new RegExp(`(${Object.keys(KanaMap).join('|')})`, 'g');
  return str
    .replace(regExp, function (match) {
      const key = match as keyof typeof KanaMap;
      return KanaMap[key];
    })
    .replace(/ﾞ/g, '゛')
    .replace(/ﾟ/g, '゜');
};

// 3.ひらがな変換
const kanaToHira = (str: string) =>
  str.replace(/[\u30a1-\u30f6]/g, (s) =>
    String.fromCharCode(s.charCodeAt(0) - 0x60)
  );

// 4.半角(英数)変換
const fullToHalf = (str: string) =>
  str.replace(/[！-～]/g, (s) => String.fromCharCode(s.charCodeAt(0) - 0xfee0));

// 関数配列を引数に、関数を返却する（高階関数）
// 返却する関数は、reducerで前の結果を受け取り（argとcompose）、
// 関数を再帰的に実施する（f(compose)）
const compose =
  (...fns: Function[]) =>
  (arg: string) =>
    fns.reduce((compose, f) => f(compose), arg);

// 1.大文字変換→2.全角カナ変換→3.ひらがな変換→4.半角（英数）変換
// 処理の順番通りに関数を渡してやればよいので直感的
// 関数の追加や削除も楽。
export const searchWord = (str: string) =>
  compose(
    covertUpperCase,
    halfKanaToFullKana,
    kanaToHira,
    fullToHalf)
    (str);

// 実行
const word = searchWord('あアaAｱＡ');
console.log(word); // ああAAあA

```

# 終わりに

* 関数型プログラミングになれるまでは、駄目な例の書き方を行っていた。
* 高階関数や、純粋関数、カリー化、関数の第一級オブジェクト等、関数型プログラミングの特性を理解し、関数合成を駆使したプログラミングを意識したい。
* 今回のtipsでは、上記を踏まえ、compose関数が全てといってよい。
Obsidianのマークダウンエディタの書式を変更する方法

まず vault配下の`.obsidian/snippets/`にcssファイルを配置する

以下は一例
```style.css
/* Headingのサイズを変更する */
body {
  --h1-size: 1.50em;
  --h2-size: 1.30em;
  --h3-size: 1.20em;
  --h4-size: 1.12em;
  --h5-size: 1.12em;
  --h6-size: 1.12em;
}

/* editing modeが'Live Preview'であってもHeadingに'#'も表示させる */
div.is-live-preview div:not(.cm-active)>span.cm-header-1:not(.cm-formatting):before {
	content: "# ";
	color: gray;
}
div.is-live-preview div:not(.cm-active)>span.cm-header-2:not(.cm-formatting):before {
	content: "## ";
	color: gray;
}
div.is-live-preview div:not(.cm-active)>span.cm-header-3:not(.cm-formatting):before {
	content: "### ";
	color: gray;
}
div.is-live-preview div:not(.cm-active)>span.cm-header-4:not(.cm-formatting):before {
	content: "#### ";
	color: gray;
}
div.is-live-preview div:not(.cm-active)>span.cm-header-5:not(.cm-formatting):before {
	content: "##### ";
	color: gray;
}
div.is-live-preview div:not(.cm-active)>span.cm-header-6:not(.cm-formatting):before {
	content: "###### ";
	color: gray;
}
```

設定→Appearance→CSS snippetsから上記のcssファイルを有効化すると、編集時の書式が無事変更できる

before
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676735/26608e36-bcc3-53cd-cdac-9f3e90bf7c93.png)

after
![Screen Shot 2023-09-16 at 21.59.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676735/b46b427a-24de-9144-f30b-7836dba87d06.png)


ちなみにMacなら`⌘ + option + i`でChromeと同じようにDeveloper Toolsが開く(Electron製だかららしい.スゴい)ので、動作しなくなったらそこからHTML classとか見て調整する
Python備忘録5(外部接続)

# ファイル入出力
## ファイル入出力1
```python:textio.py
file_path = 'textfile.txt'

with open(file_path, mode='w', encoding='utf-8', newline='\n') as f:
    for i in range(10):
        f.write(f'line{i}\n')


with open(file_path,mode='r', encoding='utf-8') as f:
    for l in f:
        print(l,end='')
```

```console:console
line0
line1
line2
line3
line4
line5
line6
line7
line8
line9
```


## with
```python:with1.py
filePath = 'output1.txt'

class WithWrite:
    def __init__(self, fileName):
        self.__fileName = fileName

    # withに入るときに実行される(__init__実行後)
    def __enter__(self):
        self.__file = open(self.__fileName, mode='w', encoding='utf-8')
        return self

    # withを抜けるときに実行される
    def __exit__(self, exc_type, exc_val, traceback):
        self.__file.close()

    def write(self, msg):
        self.__file.write(msg)


writeStrings = ['あああああ','いいいいい','ううううう','えええええ','おおおおお']
# WithWriteクラスの__enter__メソッドでreturnでself(インスタンス)が帰ってきてtに代入される
with WithWrite(filePath) as t:
    for s in writeStrings:
        t.write(s + '\n')

```

```tex:output1.txt
あああああ
いいいいい
ううううう
えええええ
おおおおお

```
Rubyのfoo?.!の「.!」とはなにか？

## はじめに

最近とあるRubyのコードで `foo?.!` という実装を見かけた。個人的にはあまり見かけない実装だったので気になって調べてみた。

## 検証環境

* Ruby 3.2.2
* irb 1.6.2

## 結論
* `.!` は論理否定をする返す
* `.!` はインスタンスメソッドである

以降については調査した内容をまとめます。

## `.!` はどんな挙動をするのか

irbで `foo.!` と `!foo` の挙動を比較してみた結果、どちらも同じ挙動をすることが分かった。

### `foo.!` の場合
```ruby
irb(main):001:0> true.!
=> false
irb(main):002:0> false.!
=> true
irb(main):003:0> nil.!
=> true
irb(main):004:0> "foo".!
=> false
```

### `!foo` の場合

```ruby
irb(main):005:0> !true
=> false
irb(main):006:0> !false
=> true
irb(main):007:0> !nil
=> true
irb(main):008:0> !"foo"
=> false
```

## `!` はメソッドで演算子形式を呼び出せる

`TrueClass` の親の親である[BasicObject Class](https://docs.ruby-lang.org/ja/latest/class/BasicObject.html#I_--21)に`!`はインスタンスメソッドが定義されており、`!` はメソッドであることがわかりました。

またRubyリファレンスマニュアルの[演算子式](https://docs.ruby-lang.org/ja/latest/doc/spec=2foperator.html)の冒頭に以下の説明がありました。

> プログラミングの利便のために一部のメソッド呼び出しと制御構造は演算子形式をとります。Rubyには以下にあげる演算子があります。

```
高い   ::
       []
       +(単項)  !  ~
       **
       -(単項)
       *  /  %
       +  -
       << >>
       &
       |  ^
       > >=  < <=
       <=> ==  === !=  =~  !~
       &&
       ||
       ..  ...
       ?:(条件演算子)
       =(+=, -= ... )
       not
低い   and or
```

つまり `!` はメソッドであり、演算子形式でも利用できるということなんですね。

同じように `+` も [Integer class](https://docs.ruby-lang.org/ja/latest/class/Integer.html#I_--2B)にインスタンスメソッドとして定義されているので、以下のように演算子形式・メソッド形式の両方で呼ぶことができきます。

```ruby
irb(main):016:0> 1 + 2
=> 3
irb(main):017:0> 1.+ 2
=> 3
```

なるほど〜、そういうことだったんですね。

※ もし誤りがありましたら指摘ください。

## `!foo` と `foo?.!` はどっちが一般的か

### Rubyリファレンスマニュアル

マニュアルでは[not](https://docs.ruby-lang.org/ja/latest/doc/spec=2foperator.html#not) では、例として `! me` が案内されており、`.!` の記載は見当たりませんでした。

### Rubocop

[Style/OperatorMethodCall](https://docs.rubocop.org/rubocop/cops_style.html#styleoperatormethodcall)というCopがあり、演算子をメソッド形式で呼ぶことは推奨されていませんでした。

### Ruby Style Guide

Rubocopの元となっている[Ruby Style Guideでも Operator Method Call](https://rubystyle.guide/#operator-method-call)は非推奨と案内されていました。

これらの情報を踏まえると `.!` 表記は非推奨という判断で良さそうです。

## まとめ

`foo.!` について記法として推奨されているのか否か調べてみましたが、結果としては非推奨ということが分かってよかったです。非推奨ではありますが、実装的には問題なく利用することもできますので、好みで使用するのも有りだとは思います。ただ基本的にはRubocopやStyle Guideの方針に沿った方が良いと思いますので、特別な理由がない限りは `foo.!` 記法は使用せず、`!foo`にしたいと思います。
新人が結合試験をやって気づいたこと

# 初めに

新卒で研修が終わり、初めての現場に入ったら結合試験から取り組むことになりました。やっている中で気づいたことが多々あったので自分への戒めとして書き残します。

### 1.わからないところは構わず先輩に聞く

（私の場合は)結合試験段階からの参画なのでシステムのことなど1ミリもわかりません。試験をこなしていく中で段々と理解が深まっていきましたが、それでもわからない箇所は多々あります。わからない状態でテスト結果を「〇」にしても、実際は「×」で他のメンバーに迷惑をかけてしまうことにもなりかねないので、わからない箇所があれば早めに聞きましょう。

### 2.ドキュメントをきちんと読む
1でわからないところがあれば先輩に聞くと書きましたが、逐一聞いていたらきりが無いです。先輩の時間を無駄に消費してしまいますね。そこで自分なりに調べてから聞くことが重要です。大体のことはドキュメントに書かれています。それを読んで、ある程度理解を深めたうえでもわからなかった場合に先輩に質問しましょう。これによりお互いの時間が無駄になりません。（私は最初の頃に逐一聞いてしまい先輩の時間を無駄にしてしまいました。。）

### 3.脳死で試験をやらない
試験仕様書には「実行する内容」と「予想結果」が書かれています。たま～～～～～～～～にどちらかが間違っていることがあります。脳死でテストをしていると絶対に気づきません。（実際は脳死でやっていてもテスト結果が「×」になるので気づくと思いますが）何のためにこの試験項目を実施しているのかを意識しながら取り組むと、システムの理解度が向上すると共に、試験仕様書のミスにも気づけるようになると思います。

### 4.エビデンスは手順も含めて綺麗に取る
試験は実施とともにエビデンスを取る必要があります。実際に試験結果が正しいのかを表す証拠ですね。私は現場参画してすぐのころ、「結果の画面だけ貼れば大丈夫でしょ」という気持ちでやっていました。しかし後日にエビデンスを見直すと何を表しているのかわからないエビデンスだらけでした。。。自分ひとりがその時だけ分かっていても、他者が理解できないエビデンスはエビデンスではなかったのです。。。エビデンスは他者がいつ見てもわかるようにしなければいけません。


### 5.実施した試験の見直しをする
人間ですので誰でもミスはします。しかし試験でのミスはマズいです。なので「10項目実施したらエビデンスの見直しをする。」など本当にミスをしていないのか、エビデンスは合っているのか、をチェックしてミスを最低限にしましょう。これをやり始めてから自分の間違いに気づくようになりました。

### 6.説明の際は相手の理解度を考慮する
試験を行っていて疑問が出てくると先輩に質問しなければいけません。先輩はシステムへの理解度が新人より格段にあるはずです。しかし全てを把握しているわけではありません。
例えば「試験No60の項目は予想結果が本当に合っていますでしょうか」と聞いたとします。この情報だけで答えることはできないでしょう。
もっとわかりやすく
「試験No60の項目、画面で言えばログイン画面のログイン機能の箇所です。予想結果では（ログアウトするとマイページに遷移する）と書かれていますが、実際はログイン画面に遷移します。この予想結果は正しいでしょうか？」などと聞くべきです。
相手が自分と同じ理解度であるとは思ってはダメです。

### 最後に
今回の現場では結合試験から取り組みました。コードというコードは書きませんでしたが色々な知見を深めることができたと思います。何か気づいたことがあればコメントいただけると幸いです。
RasberryPiのメモ書き

## ハードウェアバージョン調べるコマンド

```
$ cat /proc/device-tree/model
Raspberry Pi 2 Model B Rev 1.1
```

## SDカードから別のメディアにまるごとコピー
参考
### まるごとコピー
```
$ git clone https://github.com/billw2/rpi-clone.git
$ cd rpi-clone
$ sudo fdisk -l
(コピー先のデバイス名確認)
$ sudo ./rpi-clone sda
```

### コピー先のメディアからブート on Rasberry Pi2
1. SDカード上の/boot/cmdline.txtのROOTをコピー先メディアのPARTUUIDにする
2. コピー先メディアの/etc/fstabの/bootをSDカードの/bootのPARTUUIDにする
3. reboot

### コピー先のメディアからブート on Rasberry Pi3以降
1. 電源落としてSDカード抜いて電源入れる



# 引用元

https://blog.memo-labo.com/?p=1697

https://tomosoft.jp/design/?p=8721
Thymeleaf + Springboot + Mybatis + MySQL + VSCodeー目次

### 概要図
　[Thymeleaf+VUE+springboot+mybatis+MySQLー概要図](https://qiita.com/training_zhang/items/aa0ef3b007c75ac5fede)

### 環境準備
　[Thymeleaf + Springboot + Mybatis + MySQL + VSCodeー環境準備](https://qiita.com/training_zhang/items/5f2fe2da48fb65eece27)

### 画面遷移(@Controller)
　[Thymeleaf + Springboot + Mybatis + MySQL + VSCodeー画面遷移(@Controller)](https://qiita.com/training_zhang/items/6208f5b28f0673f7ac9e)

### RESTful API(@RestController)
　[Thymeleaf + Springboot + Mybatis + MySQL + VSCodeーRESTful API(@RestController)](https://qiita.com/training_zhang/items/221ba93fb317dc30cb21)

### ThymeleafとVuejs V2の統合
[Thymeleaf + Springboot + Mybatis + MySQL + VSCodeーThymeleafとVuejs V2の統合](https://qiita.com/training_zhang/items/84f5f0190e233459092e)

### MyBatis
[Thymeleaf + Springboot + Mybatis + MySQL + VSCodeーMyBatis](https://qiita.com/training_zhang/items/cc9b3467e4924c94b77e)
Power Automate: Lists の参照列の設定方法

# 背景
会社で Lists の参照列に対してアイテムの設定方法が分からないって話があったので、まとめ

結論としては、
- 参照列の内部Field名で、json 形式にして、参照先の Item Id を渡してやればOK
```jsonj:参照列の設定
"列名": {
  "Id": {参照列の追加したいアイテムのId}
}
```

# 概要
1. [リストの設定を動的設定にする](#リストの設定を動的設定にする)
1. [参照列の元Listsで追加したい Id を調べる](#参照列の元listsで追加したい-id-を調べる)
1. [上記Idを使って、追加・更新をする](#上記idを使って追加更新をする)

# 前提
今回の例

# 詳細
## リストの設定を動的設定にする
List Nameを、変数を使って List ID で設定する。
こうすることで、動的設定になるので、item の設定が json 形式になる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/0797fcf3-909b-44fb-a821-404c1149d3fa.png)

## 参照列の元Listsで追加したい Id を調べる
参照列を設定する為には、参照先の定義された Item ID が必要となるので、それを調べる

とはいえ、追加順に 1 から連番されるので、特に調べずに上からの番号で設定しても案外いける。
実際には、Userに選ばせることになるだろうから、Title/Idをセットにして取得して Adaptive Card で選ばせる感じかな。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/27545aea-e76b-3268-2abc-cc11fafa3772.png)

## 上記Idを使って、追加・更新をする
列名の json Item で以下のように設定すればOK
```jsonj:参照列の設定
"列名": {
  "Id": {参照列の追加したいアイテムのId}
}
```

具体的には以下な感じ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/b3cb27e2-e70a-e146-589e-a3003007585b.png)

ここで、Field 名は、表示名ではなく、内部野名前。
Sortすれば、アドレスに出てくるのでそれを利用するのが楽
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/d38b2ed7-31fd-84e5-9427-15c295dd9169.png)

# あとがき
User も 参照列もこんな感じでいけるのに、URL は、Jsonで設定は未対応・・
Link.desc で見えるのになぁ・・
１日100ビルドエラー、１日100grep

お金をいただいて、プログラムするっていろいろあると思う。

天才プログラマのやることに文句をつけるつもりはない。

凡人プログラマのつぶやきです。

凡人プログラマができることっていったら、
１日100ビルドエラー、１日100grep
だと思う。

夜型の凡人プログラマでない限り、午前中にビルドしない日は、仕事してない日だと思っていいかも。

朝から打ち合わせが入っても、手元のコンピュータではビルドしてるって当たり前やん。
議事録担当だっても、まわりの人に、発言内容はチャットで送ってねって頼んで、
なるべくビルドに専念してる。

議長の時だって、題材が別のプロジェクトの場合は、手元のビルド過程を間違って画面共有してはいけない。流石に、議長の時は、題材のプロジェクトをビルドしよう。

そして、時間の半ばくらいで、そういえば、さっきビルドしたエラーを、チャットで送ったけど、誰か、このエラーとったことありますか？ってネタ振ろう。

ビルドもせずに、ありえない架空の話で打ち合わせの時間を無駄にすごさせようという人がしばしばいる。

脳内コンパイラの性能のいい方なら、脳内コンパイラのエラーを取ることに意味はある。
脳内コンパイラが全部だけということはない。コンパイラを書いたことがある人なら、
脳内コンパイラの方が、実在するコンパイラより性能がいいということはしばしばある。
まだ、その人の脳内コンパイラを、ソースコードに落としていないだけなんだったり。
早く、ソースコードにしてって頼もう。

脳内コンパイラの性能がありえない状態なのに、脳内コンパイラのエラーが、納期までの題材では関係ないのに、延々と発言しつづける場合がある。お客様の場合には、止められない。

もくもくと、自分の手元のビルドエラーをとりつづけながら、関連性の有無の確認は都度するようにするといいかも。

毎日、絶帝１００ビルドしているかっていうとそうじゃないです。
１００ビルドは目標ではないです。

手から出てくるプログラムが、コンパイルエラーがないものしか書かない人がいる。
つぎつぎと、エラーなしでビルドできるのなら、それはそれでいい。
それも才能のうち。

凡人プログラマは、文法なんかおぼえちゃいない。
詩のように、思いついた言葉を書き出して、コンパイルして、コンパイルエラーがでてから、文法に沿ったプログラムに書き換えている。

ビルドエラーがでないこともある。ソフトウェアのインストール作業で、よく使うOSの版についてビルドするときには、そんな日もある。誰もつかっていないOSの版だとつぎつぎビルドエラーがでることもある。

１００ビルドする時のある例を紹介しよう。

新規開発で、対象OSのバージョンが３種類あり、最終出荷コンパイラが決まっていないため、３種類のコンパイラでコンパイルしているときには、同じソースで同時に９回ビルドする。

基本、９種類dockerを起動し、gitでソースを取り込んでビルド。
リリース用のビルドと、テストコードを含んでビルドする場合の２種類を同時にビルドする場合がある。合計１８種類を同時にビルド。


Visual Studioを利用している場合には、まず定義に飛ぶ。

# １００grep

ビルドエラーがでたら、エラーメッセージにもとづいてすぐにgrep

エラー対象の文字列が、どのファイルに存在するか。どれくらいの頻度で出現しているか。
共出現する単語になにがあるかなどの分析をする場合もあれば、しない場合もある。

正規表現の書き方に慣れていない時には、２−３回やりなおすことがある。
そんな状態だと、１ビルドで数回grepすることもある。

慣れてきて、grepが何を出すかがわかってくると、grepしなくてもよくなるかもしれない。
構造のよいソースコード群だと、何回かgrepしているうちに構造がつかめてくる。

構造の悪いソースコード群だと、grepするたびに発見があるかもしれない。
延々とgrepする日は続く。

grepする数が減ってくるのはそれでよい。
ずっと１日100ビルドエラー、１日100grepという趣旨ではない。

最初にそのソースコード群に出会った時には、それくらいするといいかもという目安。
目標ではない。


# 文書履歴(document history)
ver. 0.01 初稿 20230917
ver. 0.02 grep追記　20230918
### 最後までおよみいただきありがとうございました。

いいね　💚、フォローをお願いします。
#### Thank you very much for reading to the last sentence.

Please press the like icon 💚　and follow me for your happy life.
AWS SAAの模試を受けて不足していた知識

こちら後で見返す用のアウトプットなのでページ構成は適当です。ご了承ください。

## 現在の状況
Udemyの講座をすべて視聴し終わった
AWS CLIは取得済

## 間違えたところ
#### Redshift 
スナップショット用の無料ストレージある。

#### OpsWorks
・OpsWorks Stack：負荷分散、データベースモデル、アプリケーションサーバーなど様々なレイヤーを含むスタックとしてアプリケーションをモデル化できる。
・PuppetとChef

#### S3
・バケット全体のアクセス→バケットポリシー
・オブジェクト単体→ACL

日付ベースのプレフィックス→パフォーマンス向上（3500リクエスト/秒）


#### AWS Storage Gateway
データ転送用なので、データ移行用ではない
キャッシュ型ボリューム→S3がプライマリー
保管型ボリューム→ローカルがプライマリー

#### Amazon SQS
システムの分離に使用される。並行処理
要求をキューに格納し、ワーカープロセスを実行できる。

#### Snowball Edge
100TBまで

#### エラーコード500
リクエスト処理ができていないエラー
[解決方法]
・アプリケーションで再実行メカニズム有効
・リクエスト率を徐々に増やす
・複数プレフィックスにオブジェクト分散

#### Lambda
他リソースにアクセスする必要があるときはIAMロールの設定が必要

#### AWS WAF
Cloudfrontのリファラル制御を実装できる

#### Glacier
標準取り出し：3~5時間
迅速取り出し：1~5分
大容量取り出し：5～12時間

#### Route53とCloudfront
ALIASレコードをRoute53に設定すると良い

#### リザーブドインスタンス
リザーブドインスタンスの価格メリットは、購入したリザーブドインスタンスの総数に基づいて、一括請求グループの一部であるすべてのアカウントに適用される

#### EC2の権限設定
リソース単位：IAMポリシー
インスタンス単位：タグで判別

#### EFS
複数のEC2からアクセス可能
ファイルロックができる
助言、注意するときに気をつけること（備忘録）

目次
1. 背景
2. 助言、注意するとき

# 背景
コミュニケーションが下手なので。。

# 助言、注意するとき
モチベーションを上げるような伝え方をする

例
- 「ーが良いなと思った、〜したらもっと良くなると思う」
- 「自分も勉強になった」という感謝を伝える
Windows使いはScoopを入れましょうね。

## Scoop?
ScoopはWindows用のコマンドラインインストーラです。Macにおけるhomebrewみたいな？
Windowsではデフォルトで`winget`がありますが、それより使いやすいし何より数がありますから。
とりあえず入れておいて損はないツールでしょう。
## インストール
```
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
irm get.scoop.sh | iex
```
を実行するだけです。
これでscoopがインストールされます。
## 使ってみる
### アプリのインストール
試しにgitをインストールしてみましょう。
本来ならばインストーラをダウンロードしなくてはならないですが…
```
scoop install git
```
これで終わりです。
### バケットの追加
Scoopにはバケットというのが存在します。リポジトリみたいなやつです。
これを追加するとインストールできるアプリの数が増えます。
とりあえずfirefoxなどが入っているextrasを追加してみます。
```
scoop bucket add extras
```
### アプリのアンインストール
```
scoop uninstall <package>
```
ちなみにインストールされているアプリの一覧は
```
scoop list
```
で確認可能です。
## 以上
以上です。インストーラーをダウンロードする手間が省けて楽ですね。
Youtubeライブのコメントをする入力欄

# はじめに
ライブ配信にコメントするときにフォーカスが外れて面倒。

# コード
デバッグツールのsnipettsに張り付けて、実行するとコメント欄を作成できる。
ちなみにドラッグ可能
```js
// コメント送信関数
function sendComment(str) {
    const iframe = top.document.querySelector('iframe#chatframe');
    const input = iframe.contentDocument.querySelector('yt-live-chat-text-input-field-renderer #input');
    const sendButton = iframe.contentDocument.querySelector('#input-panel yt-button-shape button');
    input.innerText = str;
    input.dispatchEvent(new Event('input'));
    setTimeout(()=> sendButton.click(), 0);
    
}

// 入力フィールドのドラッグ開始位置を格納する変数
let dragStart = { x: 0, y: 0 };

// 入力フィールド作成関数
function createInputField() {
    // 新しいinput要素を作成
    let inputField = document.createElement('input');
    inputField.type = 'text';
    inputField.id = 'custom-input';
    inputField.placeholder = 'Type your comment here...';
    inputField.style.position = 'absolute';
    inputField.style.right = '0';
    inputField.style.top = '50%';
    inputField.style.zIndex = '10000000000';

    // Enterキーが押されたときのイベントリスナーを追加
    inputField.addEventListener('keydown', function(event) {
        if (event.key === 'Enter' || event.keyCode === 13) {
            // 入力欄の内容を取得
            let comment = inputField.value;

            // 入力欄をクリア
            inputField.value = '';

            // コメントを送信
            sendComment(comment);
        }
    });

    // ドラッグ開始イベントのリスナーを追加
    inputField.addEventListener('mousedown', function(event) {
        // ドラッグ開始位置を記録
        dragStart = { x: event.clientX - inputField.offsetLeft, y: event.clientY - inputField.offsetTop };
    });

    // ドラッグ中イベントのリスナーを追加
    document.addEventListener('mousemove', function(event) {
        // ドラッグ中でなければ無視
        if (!dragStart.x || !dragStart.y) return;

        // 入力フィールドの位置を更新
        inputField.style.left = event.clientX - dragStart.x + 'px';
        inputField.style.top = event.clientY - dragStart.y + 'px';
        inputField.style.right = 'auto';
    });

    // ドラッグ終了イベントのリスナーを追加
    document.addEventListener('mouseup', function(event) {
        // ドラッグ開始位置をリセット
        dragStart = { x: 0, y: 0 };
    });

    // 作成したinput要素をページの末尾に追加
    document.body.appendChild(inputField);

    // 作成したinput要素にフォーカスを設定
    inputField.focus();
}

// 入力欄を作成
createInputField();
```
MacOS(ventura-13.5.2,M1)上にRaspberry Pi PicoのC言語クロス開発環境を導入してみた

# はじめに
MacOS(ventura-13.5.2,M1)上にRaspberry Pi PicoのC言語クロス開発環境を導入する

## まずはpicoの公式ドキュメント通りにやってみた
brew導入済みが前提です
```
 ventura-13.5.2$ cd
 ventura-13.5.2$ brew tap ArmMbed/homebrew-formulae
 ventura-13.5.2$ brew install arm-none-eabi-gcc
 ventura-13.5.2$ mkdir pico
 ventura-13.5.2$ cd pico
 ventura-13.5.2$ git clone https://github.com/raspberrypi/pico-sdk.git --branch master
 ventura-13.5.2$ cd pico-sdk/
 ventura-13.5.2$ git submodule update --init
 ventura-13.5.2$ cd ..
 ventura-13.5.2$ git clone https://github.com/raspberrypi/pico-examples.git --branch master
 ventura-13.5.2$ cd pico-examples
 ventura-13.5.2$ mkdir build
 ventura-13.5.2$ cd build
 ventura-13.5.2$ export PICO_SDK_PATH=../../pico-sdk
 ventura-13.5.2$ cmake ..
 ventura-13.5.2$ cd blink
 ventura-13.5.2$ make -j4
```

ここで、以下のエラーが出てbuildが止まる問題が発生。
```
arm-none-eabi-gcc: fatal error: cannot read spec file 'nosys.specs': No such file or directory
```

## arm-none-eabi-gccでは失敗する(?)との情報を得てコンパイラ関係を入れ替える

[参考URL](https://github.com/raspberrypi/pico-sdk/issues/1482 "参考URL")

```
 ventura-13.5.2$ brew uninstall arm-none-eabi-gcc
 ventura-13.5.2$ brew autoremove
 ventura-13.5.2$ brew install --cask gcc-arm-embedded
 ventura-13.5.2$ make -j4
```

これにて無事にbulid完了。自分の環境では、gcc-arm-embeddedのインストール(ファイルの入手)に時間がかかった
JSでデストラクチャリングを使って名前の衝突を回避する

# はじめに
[Chome拡張機能のチュートリアル](https://developer.chrome.com/docs/extensions/mv3/getstarted/tut-quick-reference/)をやっていてリストからオブジェクトへの変換で詰まったので簡易モデルでテストしていたら、そこでもまた詰まったのでGPT先生に解決してもらった方法を記録
## デストラクチャリングとは
GPT先生より
>JSにおいてオブジェクトや配列から特定の要素を取り出して、簡潔な構文を使って新たな変数に代入する方法です。
ES6から導入された機能で、コードをより簡潔で読みやすくし、特定の要素にアクセスする際に冗長なコードを減らすのに役立ちます。

## オブジェクトデストラクチャリング
デストラクチャリングを使ってオブジェクトから特定の要素を変数に代入する
```destruct_to_object.js
const person = { firstName: 'Ama' ,lastName: 'Tatsu' };
const { firstName, lastName } = person;

console.log(firstName); //'Ama'
console.log(lastName); //'Tatsu'
```

## 配列デストラクチャリング
デストラクチャリングを使って配列から特定の要素を変数に代入する
```destruct_to_list.js
const numbers = [1, 2, 3];
const [first, second, third];

console.log(first); //1
console.log(second); //2
console.log(third); //3
```

## やったこと

```test.js
const test = {
    list:["a", "b", "c"]
};

const { list }=test; //testオブジェクトからlistキーの配列を受け取る
//配列の要素をオブジェクトにしてるだけ
const list_to_map = test1.map((hoge) => {
    return { "content": hoge };
});

console.log(list_to_map); //{content: 'a'}, {content: 'b'}, {content: 'c'}
```
「整式の割り算」の勉強を始めました。xは実数? ChatGPT-3.5先生へ

ポイントは2つです。新課程で、
「整式の割り算」(数Ⅱ)について
①多項式への呼び名の変更があった。今後、整式と呼んではイケナイですか？
　過去問(2003東京都立大)に、はじめから呼び名なしの問題文もありました。
　過去問(2023京都大学前期)に、整式とありました。最新ですか？
②整式の割り算のxの条件は、複素数でもいいですか？普通に考えれば、実数？省略可？

(2023/09/18追加)
iを代入していいのか(youtube) 4:09 ＜　# 109. (★★) 数Ⅱ 整式の割り算（東京都立大）＜　math karat 様より
https://youtu.be/B0u-JlIOAk8

# ChatGPT-3.5先生へ
### 参考資料
■多項式と整式について
現在の学習指導要領では，数学Ⅱのところで整式という言葉が使われています。...
https://www.chart.co.jp/subject/sugaku/suken_tsushin/77/77-9.pdf
＜79号 2014年5月＜数研通信（51号〜最新号）　【教授用資料】**オススメです。**
https://www.chart.co.jp/subject/sugaku/suken_tsushin.html

過去問 2003 東京都立大前期【１】
x^12をx^4-1で割ったときの余りを求めよ．
https://mathexamtest.web.fc2.com/2003/200311262/2003112620100mj.html

過去問 2023 京都大学前期【１】問２
整式x^2023−１wを整式x^4+...
https://mathexamtest.web.fc2.com/2023/202310541/2023105410100mj.html

### 入力文(1行ずつです。)
```
数研出版様の整式を多項式への呼び名の変更は、数研出版様の独自ルールですか
整式を多項式への呼び名の変更は、数学の新課程によるものですか
整式の割り算について、実数や複素数の条件が必要ですか
整式の割り算の計算に、整式という表現が必要ですか
CharGPT-4先生へよろしくお伝え下さい
```
### 以下回答抜粋です。
```
＞2021年9月までの情報に基づいてお答えすると、....
＞私の知識は2021年9月までのものであり、...
＞整式（多項式）同士の割り算において、実数や複素数の条件は特に必要ありません。...
＞整式は代数的な式の一種で、多項式とも呼ばれ、...
＞もちろん、お伝えいたします。
```

# ChatGPT-４先生へ
どなたか、私の代わりに聞いて、解説してもらうと助かります。よろしくお願いします。


# サイト内部検索 "割ったときの余り"
大学入試数学問題集成 様＞

https://cse.google.com/cse?cx=a8908fbc24340ebc5&q=%22%E5%89%B2%E3%81%A3%E3%81%9F%E3%81%A8%E3%81%8D%E3%81%AE%E4%BD%99%E3%82%8A%22&oq=%22%E5%89%B2%E3%81%A3%E3%81%9F%E3%81%A8%E3%81%8D%E3%81%AE%E4%BD%99%E3%82%8A%22&gs_l=partner-web.12..0i4i37i512l3j0i30i15j0i4i30i15j0i4i30i15i10j0i30i15j0i4i30i15j0i5i30l2.4795.4795.0.7497.1.1.0.0.0.0.248.248.2-1.1.0.csems%2Cnrl%3D10...0....2.34.partner-web..0.1.248.CE1jgXsWmbA

数学入試問題 様＞

https://www.google.com/search?q=site%3A%2F%2Fkamelink.com%2F+%22%E5%89%B2%E3%81%A3%E3%81%9F%E3%81%A8%E3%81%8D%E3%81%AE%E4%BD%99%E3%82%8A%22&oq=site%3A%2F%2Fkamelink.com%2F+%22%E5%89%B2%E3%81%A3%E3%81%9F%E3%81%A8%E3%81%8D%E3%81%AE%E4%BD%99%E3%82%8A%22&aqs=chrome..69i57j69i58.18839j0j4&client=ms-android-huawei&sourceid=chrome-mobile&ie=UTF-8

T氏の数学日記 様＞

https://www.google.com/search?q=site%3A%2F%2Fmathmathmass.exblog.jp%2F+%22%E5%89%B2%E3%81%A3%E3%81%9F%E3%81%A8%E3%81%8D%E3%81%AE%E4%BD%99%E3%82%8A%22&oq=site%3A%2F%2Fmathmathmass.exblog.jp%2F+%22%E5%89%B2%E3%81%A3%E3%81%9F%E3%81%A8%E3%81%8D%E3%81%AE%E4%BD%99%E3%82%8A%22&aqs=chrome..69i57j69i58.22234j0j4&client=ms-android-huawei&sourceid=chrome-mobile&ie=UTF-8
LINE BOTで引用メッセージ付きメッセージを返信してみる

# はじめに

[Messaging APIで引用メッセージを送受信できるようになりました](https://developers.line.biz/ja/news/2023/09/14/send-and-receive-quote-messages-using-the-messaging-api/)らしいのでLINE BOTでやってみました。

# やってみる

とりあえずBotに送られてきたメッセージを引用して即答させてみようと思います。
[LINE Bot SDKとLangChain.jsでGPT入りLINE Bot Serverを作ってみる](https://qiita.com/bathtimefish/items/77b0d8d7d79aa2b6f5db)で作った料理の材料を教えてくれるBotを利用します。

[ドキュメント](https://developers.line.biz/ja/docs/messaging-api/sending-messages/#send-quote-messages)をみると

```example.json
"messages": [
    {
      "type": "text",
      "text": "Yes, you can.",
      "quoteToken": "yHAz4Ua2wx7..." // 引用対象となるメッセージの引用トークンを指定する
    }
  ]
```

という感じで`quoteToken`プロパティに引用するメッセージのquoteTokenを渡せば良いみたいです。

とりあえず改造する前のBotサーバーに`カレーライス`というメッセージを投げると以下のようなメッセージオブジェクトになっていました。quoteTokenが含まれてますね

```event.json
Events: [
  {
    "type":"message",
    "message": {
       "type":"text",
       "id":"473163877602558162",
       "quoteToken":"b4UJv7x2pLiTwU9irCPJ1...",
       "text":"カレーライス"
    },
    "webhookEventId":"01ABAEQEGB2FGB5PAXB2D3BRBXW",
    "deliveryContext":{"isRedelivery":false},
    "timestamp":1694858952584,
    "source": {
       "type":"user",
       "userId":"T5fee7cec2ab8ef912c5373957ab38509"
    },
    "replyToken":"82eea180218f49838dba4d9dc812eb52",
    "mode":"active"
  }
]
```

Botサーバーの[返信用TextEventMessage](https://github.com/bathtimefish/line-bot-server-langchain-example/blob/main/src/lib/event.ts#L35)の作成箇所を以下のようにします

```src/lib/event.ts
    textEventMessage = {
      type: 'text',
      id: event.message.id,
      quoteToken: event.message.quoteToken,
      text: await getMessageFromAI(event.message.text),
    };
```

これでサーバーを実行すると以下のようになりました。Botからの返信に送信したメッセージが引用されていますね。

![Screenshot_20230916-191946.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61995/bc5482e2-2d6c-8bb6-2640-820e64d8275c.png)

# おわりに

ちなみに現時点での[line-bot-sdk-nodejs](https://github.com/line/line-bot-sdk-nodejs) v7.5.2のTextEventMessage型には`quoteToken`が定義されていません

https://github.com/line/line-bot-sdk-nodejs/blob/next/lib/types.ts#L377

つまり現時点ではTypeScriptでトランスパイルエラーが発生します。まあそのうちアップデートがかかるでしょうが、こういうAPIの更新は早めにSDKが追従ほしいところです。。
ロストテクノロジー化する外部設計

## はじめに

ロストテクノロジーとは、過去に存在したが、**何らかの理由**で後世に伝えられず、現代では再現不可能となった技術です。

外部設計を行った結果を外部設計書に記録してプロジェクトを円滑に進める行為が~~予算の理由で~~ロストテクノロジーとなり、結果として後世に外部設計手法が伝えられないのではないかという考察を行ってみたいと思います。

## 外部設計書について

外部設計書は、本来は要件定義を行う顧客と、外部設計を行う開発間で合意を取るために必須の設計書ですが、顧客が欲しいのは「開発されたプロダクト」であり「設計書」ではないというジレンマがあります。

![外部設計.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136165/80ce3974-7f59-4dcf-8e8a-31884f36728c.png)

顧客目線では、ちゃんと動くビジネスや業務課題を解決するソフトウェアがあればよいだけです。

ところが、手戻りなく無駄なく開発を行おうとすると、**外部設計時点**できちんと要求を満たしているかを確認する必要がありますが、書類から実際のソフトウェアの動作まで想像するのは熟練のエンジニアでもかなり難しいという問題があります。

期限があるので一旦は承認は行うものの、**受入試験時**に「期待値と違う」ということもよくあります。受入試験時に調整するのであれば、外部設計時の承認は不要にも思えます。
しかし、**「承認を受けた外部設計書」** が存在しないと無限に受入対応が発生するリスクが出てきます。

また、運用開始後に機能追加や改修を行う場合に外部設計書が存在しない場合、仕様解析から行うことになり、リバースエンジニアリングのコストが追加されたり、そもそも改修の見積もりができないといった新たな問題も発生します。

総じて、外部設計書の重要度が増すのは「受入試験」工程より後で、初期の外部設計時に作るのが最も合理的でコストも最小になるにも関わらず、そのコストや期間が捻出されず、「後仕様」と言って申し訳程度のドキュメントを後で提出するといった傾向がある様に思えます。

## あれ？設計者が減っていく・・・？

**「書けるけど書かない」** のと **「書けない」** のは別の話です。

アジャイル開発と称して、外部設計を行う事ができるエンジニアが、顧客窓口と直接会話して外部設計～詳細設計～実装～単体試験まですべてを行えば外部設計書はなくても開発案件としては、一応成立します。（運用フェーズの問題は残ります）

しかし、経験値の低いエンジニアがこれだけの工程をこなすことは難しいです。
また、アウトプットとしてソースコードしか存在していない状況は、外部設計について認知する機会を減らしてしまっています。

顧客からすると開発会社の若手を育てるのにお金を払う義理はないのですが、このまま放置しておくと、外部設計を行う人間が減っていき、開発案件自体を行うことができなくなっていくことが予想されます。
上級SEと言われる設計ができる人々は定年などの理由で確実に減っていくからです。

## おわりに

昭和の町工場が、技術の伝承ができなくて消えつつあるのと同様に、令和のIT工場が、外部設計手法の伝承ができずに消えていく可能性を考察してみました。

アジャイル開発をやめて昔のウォーターフォール開発にすることは現実的ではないし、それで解決する問題でもないように思えます。

ただ、アジャイル開発手法を取る限りは未経験エンジニアでも案件にアサインされると同時に、設計と開発の能力を求められるチャレンジングな状況となっていくでしょう。

ゆでガエルにならないように、生存戦略を考えないといけないかもしれません。

## おまけ１（新卒エンジニア向け手紙）

https://qiita.com/kaku3/items/2c8d4d783be7ce4fc9ea

https://qiita.com/kaku3/items/0bf1703cb8d6f84afbc5

## おまけ２（新卒エンジニア向け記事）

https://qiita.com/kaku3/items/fb949aa1a53f1f71c796

https://qiita.com/kaku3/items/aa2f81cf1e3974b8ad3a

https://qiita.com/kaku3/items/937354cc180c8bee823b

https://qiita.com/kaku3/items/b1c94328f273c750286b

## おまけ３（パイセン向け記事）

https://qiita.com/kaku3/items/cafccb1ee631d9f61190

https://qiita.com/kaku3/items/422b5427024d29da6a6e

## おまけ４（...は難しいシリーズ）

https://qiita.com/kaku3/items/34b40446337a59213a75

https://qiita.com/kaku3/items/f8411523cce000de750e

https://qiita.com/kaku3/items/5b11d2e1aace73c36340

## おまけ５（営業A短編シリーズ）

https://qiita.com/kaku3/items/03aae7b9e3c70c55f513

https://qiita.com/kaku3/items/3378ea55b1240d7360a1

## おまけ６（エンジニアのためのお仕事問題集）

2030年にIT人材が最大79万人不足するとのことで、学習用の資料をgitで**無料**公開してます(不定期更新)。
よろしければどうぞ。

[エンジニアのためのお仕事問題集](https://github.com/kaku3/workbooks)
postgresqlの備忘録（接続まで）

## 目標

WindowsにpostgreSQLをインストールして環境変数にパスを通して`psql`コマンドでpostgreSQLに接続するまで。

## Installation

PostgreSQLをインストールする

https://www.enterprisedb.com/downloads/postgres-postgresql-downloads

## 環境変数の設定

環境変数編集画面を開いてpathを通す

デフォルトのインストールでは次のpathを登録すればいい。

```
C:\Program Files\PostgreSQL\16\bin
```

## 接続・切断

環境変数を設定してからターミナルを再起動後次のコマンドで接続可能。

```bash
psql -U postgres
```

次のコマンドで接続を切断することができる。

```bash
\q
```

## 個人的な使い方

結局ORMとかを使ってDBを操作するので最低限の使い方だけ覚えて実際のDBの状況を確認できる程度になればいい。SQLとかも全部を覚える必要はない。最低限確認とテストができるように準備している。

## 参考記事リスト

- https://www.javadrive.jp/postgresql/
- https://postgresweb.com/introduction-to-postgresql
Open JTalk(最新版)のコンパイル

### HTK HTSのインストール

[register form](https://htk.eng.cam.ac.uk/register.shtml)からregister

[htk](https://htk.eng.cam.ac.uk/download.shtml)と[htk-decode](https://htk.eng.cam.ac.uk/prot-docs/hdecode.shtml)をダウンロード

[nitech](http://hts.sp.nitech.ac.jp/?Download)からpatchをダウンロード

フォルダーにまとめて
```sh
patch -p1 -d . < HTS-2.3_for_HTK-3.4.1.patch
```
で適用。
その後
```sh
./configure
make
sudo make install
```

### Open JTalkのインストール
[htp-engine-api](https://hts-engine.sourceforge.net/)をダウンロードしてコンパイル、インストール

[Open JTalk](https://open-jtalk.sourceforge.net/)からソースとHTS voiceをダウンロード、解凍してまとめる

その後
```sh
./configure --with-hts-engine-header-path=/usr/local/include --with-hts-engine-library-path=/usr/local/lib --with-charset=UTF-8
make
```
実行はこう
```sh
echo "これで完了です。"|./bin/open_jtalk -x ./mecab-naist-jdic -m ./nitech_jp_atr503_m001.htsvoice -ow open-talk.wav
```

参考
[Linuxで音声読み上げ - Just $ A sandbox](https://myuon-myon.hatenablog.com/entry/2015/04/09/214655)
[Open JTalkで音声合成 - 人工知能に関する断創録](https://aidiary.hatenablog.com/entry/20130921/1379751472)
[Ubuntuで「open-jtalk」日本語音声合成を使ってみる](https://brokendish.org/ubuntu/3100/)
[Open JTalk で MMDAgent のメイちゃんに喋らせてみた - 凹みTips](https://tips.hecomi.com/entry/20120221/1329838707)
[Open JTalk (テキストを音声へ変換)をインストールし、使ってみる | レンタルサーバー・自宅サーバー設定・構築のヒント](https://server-setting.info/centos/open-jtalk-install.html)
ARMとx86の違い

# CISCとRISCについて
ここに書いてあります。

https://basics.k-labo.work/2017/10/10/%E3%83%97%E3%83%AD%E3%82%BB%E3%83%83%E3%82%B5%E3%81%AE%E7%A8%AE%E9%A1%9E%E3%81%A8%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3/

一言でいうと、
- RISCは単純な命令に強い
- CISCは複雑な命令に強い


# ARMとx86の違い
ARMの設計方針はRISCで、x86の設計方針はCISCです。
なので、RISCとCISCの違いがARMとx86の違いです。

ARMは単純高速が強みなので、携帯、電卓、ハードディスク、ルータなどで使われる。2015年においては、携帯電話で9割超のシェアを占めた。

x86はパソコン、スパコン、サーバ、家電機器や産業機器の組み込みシステムで使われる。

以上をまとめると、
| アーキテクチャ |設計思想| 強み | 使用場所 |
| --- | --- | --- | --- |
| ARM |RISC| 単純・高速| 携帯電話、電卓、ハードディスク、ルータ |
| x86 |CISC| 複雑 | パソコン、スパコン、サーバ、家電機器、産業機器 |

# 参考文献
https://blog.yossarian.net/2020/11/30/How-many-registers-does-an-x86-64-cpu-have#:~:text=Because%20x86%2D64%20evolved%20from,the%20full%2064%2Dbit%20register.&text=So%20that's%2016%20full%2Dwidth,Registers%20in%20this%20group%3A%2068

https://basics.k-labo.work/2017/10/10/%E3%83%97%E3%83%AD%E3%82%BB%E3%83%83%E3%82%B5%E3%81%AE%E7%A8%AE%E9%A1%9E%E3%81%A8%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3/

https://ja.wikipedia.org/wiki/ARM%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3
PoetryとPyenvでPythonのバージョン管理

# はじめに
PoetryとPyenvでプロジェクトを作成しようとしたら躓いたのでメモ代わりに投稿する。

# pyenv global を用いる場合
pyenvで指定しているデフォルトのバージョンを用いる時は何も考えずにPoetryのコマンドを叩く。
```
poetry init 
poetry install
```

# pyenv local を用いる場合
デフォルト (global) とは異なるバージョンを指定 (`pyenv local`) して、Poetryプロジェクトを作りたい時はひと手間必要である。
先の場合と同じコマンドを叩くと以下のようなエラーが出る。
`The currently activated Python version 3.10.9 is not supported by the project (^3.80). Trying to find and use a compatible version.`

この場合は先に仮想環境を作成してからPoetryプロジェクトを作成する。
```
pyenv local [指定したいバージョン]
python -m venv .venv
poetry init
poetry install
```
厳密には`poetry init`の実行は仮想環境を作成する前でも構わない。
serverless framework を使ってHelloWorld

# はじめに

この記事では、Serverless Frameworkの基本的な使い方を説明します。Serverless Frameworkは現在、サーバーレスアーキテクチャを効率的に構築するための主要なツールの一つです。

# Serverless Frameworkとは
Serverless Frameworkは、サーバーレスアーキテクチャを簡単に、効率よくデプロイ・運用するためのオープンソースのツールです。このツールは、AWS Lambda, Azure Functions, Google Cloud Functionsなど、多くのクラウドプロバイダに対応しています。

# チュートリアル

## ディレクトリ構成
```
.
├── Dockerfile
├── README.md
├── assets
│   └── index.html
├── docker-compose.yml
├── functions
│   └── hello
│       └── handler.py
├── package-lock.json
├── package.json
└── serverless.yml
```

この構造では、functionsディレクトリがLambda関数のコードを、assetsディレクトリがフロントエンドのHTMLファイルを、serverless.ymlがServerless Frameworkの設定を格納しています。

## 設定ファイル
各設定ファイルについて簡単に説明します。

### Dockerfile
このDockerfileは、Python 3.8をベースに、Node.jsとServerless Frameworkをインストールしています。

```Dockerfile
# ベースイメージ
FROM python:3.8

# Node.jsをインストール
RUN apt-get update && apt-get install -y nodejs npm

# Serverless Frameworkをインストール
RUN npm install -g serverless

# ワークディレクトリを設定
WORKDIR /app

# Pythonの依存関係をコピー&インストール
COPY requirements.txt .
RUN pip install -r requirements.txt

# package.jsonをコピー&インストール
COPY package.json .
RUN npm install
```

### docker-compose.yml
このファイルは、Dockerコンテナの設定を行います。AWSのクレデンシャルを環境変数としてコンテナに渡しています。

```docker-compose.yml
version: '3'
services:
  serverless_app:
    build: .
    volumes:
      - .:/app
    environment:
      - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
      - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
      - AWS_DEFAULT_REGION=${AWS_REGION}
```

### .env
AWSのクレデンシャルとデフォルトのリージョンを設定します。

```.env
AWS_ACCESS_KEY_ID=xxxxxxx
AWS_SECRET_ACCESS_KEY=xxxxxxx
AWS_REGION=ap-northeast-1
```

### serverless.yml
このファイルで、AWS Lambda関数とAPI Gatewayの設定を行います。

```serverless.yml
service: serverless-framework-tutorial

provider:
  name: aws
  runtime: python3.8
  region: ap-northeast-1  

functions:
  hello:
    handler: functions/hello/handler.hello
    role: arn:aws:iam::xxxxxxxxxx:role/serverless-framework-role
    events:
      - http:
          path: hello
          method: get
          cors: true
```

## Lambda

```
import json

def hello(event, context):
    body = {
        "message": "Hello, world!"
    }

    response = {
        "statusCode": 200,
        "body": json.dumps(body),
        'headers': {
            'Access-Control-Allow-Origin': '*'
        }
    }

    return response
```

このPythonスクリプトは、単純な"Hello, world!"メッセージを返すLambda関数を定義しています。
mpg123でリモートのファイルの再生

I2Sで新潟精密のFN1241が接続されたAtherosのモジュールはUSBもあるのですが、USBから再生するとなぜか音がよくないので、別のサーバに音源をおくことを考えてみました。

MP3ファイルはUSB HDが接続されたNetBSD/c1kにおきます。

MP3やストリームで検索するとicecast2がでてきます。c1kのarmv6はnon hfでpkgはarmv4しか使えません。

armv6hfのpkgにはicecast2はありますが、armv4にはないのでセルフでコンパイルしてみます。

結構コンパイルも苦労したのですが、どうにかビルドは出来たのですが使い方が分かりません。ネットで検索しても古い情報とか多くてよく分かりません。

そもそもicecast2はmp3ファイルを、操作しているようで、音質劣化につながると思われ、他の方法を調べてみます。

mini_httpdでmp3ファイルを見えるようにすればmpg123は再生できます。

ただ、連続して再生する事が出来ません。

mpg123にはemacsのフロントエンドがあるようですが、emacsは大きいです。

また自分でスクリプトを書くのも面倒です。

mpg123のソースを見てみたところplaylistという機能があることがわかりました。

playlistはhttpでも拾えるのでmp3のファイルがあるサーバにhttpのplaylistを置いておいて、それで再生する事ができました。

```
# /usr/local/bin/mpg123 --utf8 --ignore-mime -@ http://10.0.1.41:8080/shibuya/li
st.txt
High Performance MPEG 1.0/2.0/2.5 Audio Player for Layers 1, 2 and 3
        version 1.31.1; written and copyright by Michael Hipp and others
        free software (LGPL) without any warranty but with best wishes

Directory: http://10.0.1.41:8080/shibuya/

Terminal control enabled, press 'h' for listing of keys and functions.

Playing MPEG stream 1 of 8: 01.mp3 ...

MPEG 1.0 L III cbr192 44100 stereo

Title:   Lawns                           Artist: 渋谷毅                            
Comment: 8+C52CC56F4F83279DE1FC2A89A38954B9+84696548
Album:   カーラ・ブレイが好き
Year:    2022                            Genre:  Jazz,                          
```

--ignore-mimeを付けないとエラーになりました。

![MP3Play.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/54e602cf-4da9-48a0-202d-89359e88653c.png)

list.txtはURLではなくファイル名だけでいけました。

```:list.txt
01.mp3
02.mp3
03.mp3
04.mp3
05.mp3
06.mp3
07.mp3
08.mp3
```

以下のようにして、list.txtを作ります。

```
# ls -1 *.mp3 > list.txt
```

CDのリッピングはiBook Dual-USB MacOS X 10.4のiTunesでおこなっています。MP3でもcbr192くらいあれば十分高音質です。

MP3ファイルをコピーして、ファイル名変換してからtarでくくってNetBSDにもっていきます。

https://qiita.com/yamori813/items/3fc13ea14ad3addf06a0

ほぼ一行野郎のCGIでlistを作るようにしてみました。

```sh:list.cgi
#!/bin/sh

echo "Content-type: text/html
"

LIST=`ls -1 ../${QUERY_STRING}/*.mp3 | sed 's/^.../http:\/\/'${SERVER_NAME}'\//'`

echo "${LIST}"
```

```
# /usr/local/bin/mpg123 --utf8 --ignore-mime -@ http://10.0.1.41:8080/cgi/list.cgi?shibuya
```

みたいに使えます。
【学習】Linuxコマンド　Day12 ~実践、シェルスクリプトの基本~

# 今日学ぶこと
- シェルスクリプト

# シェルスクリプトとは
複数のコマンドラインをシェルで実行できるようにまとめたファイル。
これまでパイプラインを駆使して複数のコマンドを繋いだが、さらに複雑な操作に対応できるといえる。
条件分岐やループなどプログラミング言語のような機能も使うことができ、シェルスクリプトを実行するだけで何度も同じ操作を再現できる。

# シェルスクリプトを作ってみる
シェルスクリプトを作るうえでまずは"シバン"を書くことを理解する。
これは「どのシェルで実行するか」を指定するための記述。
```
#!/bin/bash
```
この次の行からコマンドを実際に記述していくこととなる。
それでは実際に作ってみる。
```
$ mkdir ~/bin
$ cd bin 
$ vim test.sh
```
mkdirでシェルスクリプトの置き場をつくったあとにvimでtest.shを新規作成。
```
#!/bin/bash
ls -F | nl
```
シバンの2行目以降が実行されることとなるため、実際には3行目、4行目と追記していくことが可能。
インサートモードからノーマルモードに切り替えて、保存後、実行権限を与える。
```
$chmod 755 test.sh
```
そして作成したtest.shを実行してみる。
```
$ test.sh
1 test.sh*
```
記述したコマンドが実行されていることが確認できた。

### 繰り返し処理
forを用いて繰り返し処理を行ってみる。
今回はvimでtest.shを編集して書いてみる。
```
#!/bin/bash
for i in 1 2 3
do 
echo $i
done
```
保存後、実行。
```
$ test.sh
1
2
3
```

### 条件分岐
ifを使用した条件分岐を試してみる。
変数TESTが1の場合"1"と表示する。
```
#!/bin/bash
TEST=1
if [ $TEST -eq 1 ]; then
    echo "1"
else
    echo "none"
fin
```
ここで細かいところだが個人的な注意点。
if [ $TEST -eq 1 ]
この[]の前後の部分などに適切にスペースが入っていないとmissingとなり、うまく実行されなかったため、正確にスペースを空けることに注意。

次にcaseを使用した条件分岐。
キーボードからの値も取得してみる。
```
#!/bin/bash
$ read -p: TEST
case "$TEST" in
"a" ) echo "A" ;;
"b" ) echo "B" ;;
"c" ) echo "C" ;;
esac
```
保存後、実行してみる。
```
$ test.sh
:a 
A
```
しっかりと"a"を取得し、"A"を返していることが確認できた。

# おつかれまでした
今回も基本的な部分かと思いますがシェルスクリプトについて簡単に実践してみました。
利便性を最初に理解でき、これまでの学習してきたvimも活用できて復習にもなったかと思います。
そしてまさに条件分岐、繰り返しはプログラミング言語のような機能で、自分としてはすんなり理解はできました。ただ同様にスペースなど正確に入力しないといけない点とうまく動かないときはエラー文をしっかり確認するべき点がこの先扱う際に注意していきたいです。
【インフラ備忘録】ロードバランサー、Redis、AWS Fargate

業務の中で触れたインフラ周りの知識を整理する。
    今回はロードバランサー、Redis、AWS Fargateについての備忘録です。


## Load Balancer
##### なぜ使う？
仮に1つのサーバーでWebサイトを運営すると、そのサーバーの処理能力以上のアクセスがあった場合に、レスポンス低下、サーバーダウンの危険性がある。

##### 何をしてくれる？
サーバーへのアクセスを集約して、リソースに余裕のあるサーバーの転送先として選択するなど、アクセスを振り分けてくれる.AWS ELBはEC2インスタンスへのヘルスチェックを行い、高可用性を担保してくれます。また負荷に応じてキャパシティの自動増減も行なってくれます。


## Redis
##### 何者？
インメモリキャッシュ。メモリを活用して高速にキャッシュへのアクセスを可能にしたDBの仕組み。

##### なぜ使う？
DBアクセス負荷が増大した場合、処理能力の低下や可用性の低下の危険性がある。

##### 何をしてくれる？
アクセス頻度の高いデータをキャッシュに配置して可用性を高める。データアクセスを高速にしたい場合に活用を検討する。

## AWS Fargate
##### 何者？
サーバレスでコンテナを実行するコンピューティングエンジン.

##### なぜ使う？
サーバレスでコンテナを動かすことで、サーバー管理などを行わないで、アプリケーションの構築に集中したい。

##### 何をしてくれる？
サーバーのインフラストラクチャのプロビジョニングやスケーリングをAWS側が担ってくれる。ユーザーがインフラストラクチャの管理を気にすることなく、コンテナをデプロイし、実行することが可能になる。
ニューラルネットワークの予測の不確実性（Stochastic gradient Langevin dynamics・概要編）

# はじめに
Stochastic gradient Langevin dynamics (SGLD) でニューラルネットワークの予測の不確実性を算出する手法を紹介します。  


# Stochastic gradient Langevin dynamics  
確率的勾配降下法とランジュバン動力学によるを組み合わせて、パラメータの事後分布をサンプリングする手法です。  
SGLDの更新式に従ってパラメータを更新し、その過程のパラメータを事後分布からのサンプリングとして近似的に使用します。

バッチサイズを$b$、データセットのサイズを$n$、パラメータの更新量は下記になります。  
$$
\Delta \theta = \frac{\alpha}{2}\Bigl(\frac{n}{b}\sum_i \nabla \log p(y_i|x_i,\theta) + \nabla \log p(\theta)\Bigr) + \sqrt{\alpha} \mathcal{N}(0,\rm{I})
$$
ここで、$\alpha$はSGLDのパラメータです。  
上式は確率的勾配降下法によるパラメータの更新に正規分布に従うノイズを付加した形になっています。  

パラメータ$\theta$でのデータ$x$の予測を$p(y|x,\theta)=\mathcal{N}(f(x;\theta),\sigma^2)$、正解を$y$とすると、$\log p(y|x,\theta)=-\frac{\ln 2\pi\sigma^2}{2} - \frac{(y-f(x;\theta))^2}{2\sigma^2}$となります。  
つまり、この場合2乗誤差を最小化すればよいことになります。  
また、$p(\theta)$に関しても平均0の正規分布を仮定すれば、パラメータのL2ノルムを最小化すればよいことになります。  

### DP-SGDとの関係  
SGLDの更新式は、差分プライバシーを保証した確率的勾配法（DP-SGD）と等価であることが知られています。  
DP-SGDの更新式は下記で定義されます。
```math
\Delta \theta = \eta \biggl( \frac{1}{b} \sum_{i} {\rm clip}_C (\nabla \log p(y_i|x_i, \theta)) + \frac{1}{n}\nabla_{\theta} \log p(\theta) + \mathcal{N}(0,\sigma^2c^2\rm{I}) \biggr) 
```
ここで、${\rm clip}_C$はベクトルのL2ノルムを最大$C$に制限する関数、$\eta$は学習率、$c$と$\sigma$はDP-SGDのパラメータです。
DP-SGDのパラメータが$C=\frac{b\sqrt{2}}{\sigma \sqrt{\eta n}}$を満たす際に、SGLDと等価になります。  


### 不確実性の算出  
推論結果の事後分布は、パラメータの分布$p(\theta)$を考え、積分で$\theta$を消去することで求めます。  
$$
p(y|x) = \int p(y|x, \theta)p(\theta) {\rm d}\theta
$$
この積分をSGLDでパラメータをサンプリングした結果$\{\theta_1, \cdots, \theta_n\}$を用いて近似します。  

事後分布の期待値と分散は下記の通り求めることができます。  
$$
\mu(y) = \frac{1}{n}\sum_{i=1}^n f(x;\theta_i)
$$
$$
{\rm Var}(y) = \sigma^2 + \frac{1}{n}\sum_{i=1}^n f(x;\theta_i)^T f(x;\theta_i) - \mu(y)^T \mu(y)
$$



### 参考資料
- M. Welling and Y. W. Teh, Bayesian learning via stochastic gradient Langevin dynamics, ICML, 2011.
- M. Abadi, et al., Deep learning with differential privacy, ACM CCS, 2016.
- B. Li, et al., On connecting stochastic gradient MCMC and differential privacy, AISTATS, 2019.
【django-allauth ver0.56】"NameError: name 'allauth' is not defined"の対処法

# はじめに
Djangoでユーザ認証付きwebアプリの開発中に起こったエラー。

ユーザ認証機能追加のためにdjango-allauthをインストールし、settings.pyのINSTALLED_APPSに以下のように追加

    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'allauth', #この行を追加
        'app', #アプリ名（今回は関係なし）
    ]

その後諸々の作業を進め、python manage.py runserverでローカルサーバーを起動したところ以下のエラーが。

allauth.account.middleware.AccountMiddleware
NameError: name 'allauth' is not defined

allauthが未定義とのこと。
INSTALLED_APPSには追加されているのになぜ？

# 動作環境
##### OS
・windows 10 pro

##### モジュール
・Django 4.1.1
・django-allauth 0.56.1

# 原因と解決方法
例のごとくGPT先生にエラー文を叩きつけてお聞きしたところ、今回のエラーはミドルウェアの設定不足が原因らしい。

ChatGPT:https://chat.openai.com/

正しく動作させるには、settings.pyのMIDDLEWAREに以下の記述を追加しなくてはならないとのこと。

    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
        'allauth.account.middleware.AccountMiddleware', #この行を追加
    ]

こんなの前まで書かなかった...となるのもそのはずで、ver0.56.0から記述が必要になったとか。改めてバージョン変更は注意して行わないとですね...

参考サイト:[django-allauth公式ドキュメント](https://django-allauth.readthedocs.io/en/latest/release-notes/recent.html#section-2)

# おわりに
モジュールはアプデ前に、公式ドキュメントをチェックすると自戒しておきます。
ソースコードをGitHub等に公開する際には、requirements.txtには~=等を使って明確なバージョン記載しておきましょう。
Astroで作ったサイトをFirebaseHostingで公開してみた

## 概要
Astroで作ったサイトをFirebaseHostingで公開してみたので、備忘のために手順を記載します。
簡単にWEBサイトをホスティングできる上に無料で使用できるのでおすすめです。
Astroの[公式サイト](https://docs.astro.build/ja/guides/deploy/google-firebase/)に手順が載っているので参考にしてください。

## 手順
### 1. firebase-toolsをインストール
```
npm install -g firebase-tools
```

### 2. firebase.jsonと.firebasercをプロジェクトのルートに作成し、次の内容を記入します。
`firebase.json`:
```
{
  "hosting": {
    "public": "dist",
    "ignore": []
  }
}
```
`.firebaserc`:
<YOUR_FIREBASE_ID>には、FirebaseのProjectIDを記載してください。
```
{
  "projects": {
    "default": "<YOUR_FIREBASE_ID>"
  }
}
```

### 3. Firebaseにビルド・デプロイ
1. `npm run build`を実行
2.  その後、`firebase deploy`を実行
3.  2を実行した時に最後の方に表示されている
`Hosting URL: https://XXX.web.app`にアクセスするとHostingされていると思います。

※途中Firebase側でログインが必要になる時があります。その時は、以下コマンドで一度ログアウトして、ログインし直すことでデプロイすることができました。
```
$ firebase logout
$ firebase login
```
AmongUsのModを作ろう

# AmongUsのModを作ろう

https://qiita.com/yokingkun/items/d6984636f1bfe53fe18a

この記事へのアンサー記事です．
なお，筆者は[TownOfHost](https://github.com/tukasa0001/TownOfHost)というプロジェクトで実際にMod開発に携わっています．

## Mod開発はむずかしい

そんなことはありません．ただModを作るだけならそんなに難しくはないです．既存Modの改変であればもっと簡単です．C#自体難しい言語ではないので，センスのある人ならあっという間に慣れることができるでしょう．

## Unityより難しい

これは場合によると思います．僕自身Unityに詳しいわけではありませんが，少なくとも既存のゲーム性に手を入れる程度の改変であればAssetを扱う場面は基本的にないため，ほとんどの場合では問題にならないのではないかと思います．
AmongUsのModに関しては，ほとんどのプロジェクトがオープンソースで開発されているため，既存Modのコードを参考にしたり，場合によっては一部分をコピペでまるごと持ってくることもできます．これは全部コードで書かれているからこその利点ではないかと思います．

## アプデ対応大変

これも場合によります．僕や元記事の筆者さんはそれぞれ大きなModの開発メンバーなので基本的に自分でアプデ対応をする必要がある人ですが，そういうアプデ対応に幸福を感じるタイプの変な人が先陣を切って対応をするので，わからなかったらそれを真似すればよいです．

## サポートが大変

これはその通りです．定期的に変な人が現れます．場合によってはサポートを積極的に行わない方向性で進めるのもありかもしれません．

## 得られるもの

僕個人の話になりますが，Mod開発を通じてたくさんのものを得ました．技術的な面もそうですが，開発作業等での経験的な面が大きいです．
TownOfHostでは開発メンバーがたくさんいるので，ちょっとしたチーム開発のような形になっています．このような経験はなかなか得られないと思います．
また，TownOfHostに本格的に関わる以前，AmongUsの著名な実況者集団である高田村で一時使用されていた[AUModS](https://github.com/AUModS/AUModS)というModに[継続的にコントリビュートしていました](https://github.com/AUModS/AUModS/pulls?q=is%3Apr+is%3Amerged+author%3AHyz-sui)．これはシンプルに嬉しかったですね．頑張っていればそういうこともあるかもしれません．

## 競合が多い

これは何を目的にModを作るかによるでしょう．名声を得るためにMod開発に手を出すのは元記事と同様おすすめしません．ですが，｢自分が使うため｣｢身内と遊ぶため｣といった動機であれば，そもそも競合を気にする必要が全くもってありません．

# 結論

元記事の筆者さんも書かれているとおり，Mod開発は面白いです．そもそも，既存Modに要望を投げるよりも，自分で作ってしまったほうが手っ取り早いです．今のAmongUsに飽きた人，少し物足りないと感じている人，ぜひチャレンジしてみると良いと思います．

# 最後にこれだけ

Modを作る際は[Modポリシー](https://www.innersloth.com/among-us-mod-policy/)をよく読み，そして従いましょう．また，既存Modを改変する際はそのModのライセンスをよく調べ，クレジット表記などは忘れぬように．

https://www.innersloth.com/among-us-mod-policy/
ChatGPTと会話しながら簡単なPython実行環境を構築したのでメモメモ

どうもこんにちは。
たまたま一日暇だったので、勉強がてらPythonの実行環境をdockerを使用して構築してみました。

なんの筋道も立てずに「環境構築してみよー」と思って始めてみたのですが、やはり**ChatGPT**さんにお世話になりました。

# 下準備

下準備として、python環境を構築するためのディレクトリを作成しておきます。
プラスでsample.pyファイルに`print("hello world")`を記述して保存しておくと良いです。

# AIとの会話の内容

まず、以下のように雑に教えを乞いました。

```
Macbookのローカル環境でDockerを使用してPythonの開発環境を構築したい。

自分のPCには、/Users/test_user/code/python_testディレクトリを作成した。
python_testディレクトリを作業用ディレクトリとして開発環境構築をする手順を教えて。

python_testディレクトリには、sample.pyというファイルが配置されていて、`print("hello world")`のコードのみが?記述されている。

コンテナを立ち上げて、ターミナルで`docker-compose exec コンテナ名 python sample.py`のようにファイルを実行> できるように環境構築をしたい。
```

雑でしかない。。。
自分なりのプロンプトを調査、作成してみようかな。。。

ChatGPTさんの返答はこちら。

![スクリーンショット 2023-09-16 15.35.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2711491/d5c6943b-62cd-2c4e-5012-03e983b481dd.png)

なんともまぁご丁寧に。。。

ではその通りにやってみるとしましょう。

# 実際にやってみたものの。。。

`Dockerfile`と`docker-compose.yml`を作成して、`docker-compose up --build`を実行したところ、エラーが出てしまいました。

エラー文を抜粋して示します。

```
 => ERROR [python-service 3/4] COPY requirements.txt .                                                                                                         0.0s
------
 > [python-service 3/4] COPY requirements.txt .:
------
failed to solve: failed to compute cache key: failed to calculate checksum of ref bd0a5f83-f4ec-4065-887d-abd5d6fb4091::4n3wivx3ezds2tho9ntk1rbvu: "/requirements.txt": not found
```

"/requirements.txt": not found。。。つまり、そんなファイルないですよ。と言われてしまっているわけですね。

ならば、とりあえず作業ディレクトリに`requirements.txt`という名前で空のファイルを作ってみましょう。

```
touch requirements.txt
```

ということで作成できたので、もう一回`docker-compose up --build`実行！

```
[+] Building 226.5s (9/9) FINISHED
```

およそ4分かかりましたが、無事構築成功です。

しっかりと`hello world`も出力されていますね。

```
[+] Running 2/1
 ✔ Network python_test_default             Created                                                                                                             0.0s 
 ✔ Container python_test-python-service-1  Created                                                                                                             0.0s 
Attaching to python_test-python-service-1
python_test-python-service-1  | hello world
python_test-python-service-1 exited with code 0
```

# まとめ

めちゃめちゃ初歩的なことをしてみましたが、Railsとは違って、サーバーを立てっぱなしにしないアプリケーションにはまだ慣れませんね。。。

これを機にPythonで色々な機能をくっつけられたらいいなぁという希望を持って今回は終わりにします。

以上

# ソースコードはこちら

https://github.com/pdc-kurashina/python_sample_qiita_01
ローカルアプリをローカルサーバで立ち上げてみんなで接続する

## はじめに
そういえば世界に公開しないようなローカルアプリケーションを仕事仲間だけで動かしたいときってどうやるの？ってなって情報探してみたら思っていたほど情報がなかったのでメモする。びびるぐらい簡単だった

## IPを調べよう
ローカルipを調べて、そのipを指定してサーバを立ち上げる

```console
PS C:\Users\yoshi> ipconfig
  Wireless LAN adapter Wi-Fi:
  IPv4 アドレス . . . . . . . . . . . .: 192.168.XXX.43
  
soil_analysis> python manage.py runserver 192.168.XXX.43:8080
  Django version 4.2.2, using settings 'config.settings'
  Starting development server at http://192.168.XXX.43:8080/
  Quit the server with CTRL-BREAK.
```

## スマホからつないでみよう！
みんなで同じwi-fi（今回はレオパのwifi）に接続する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94562/36bafa01-8e94-496f-a7ea-707459b4f49e.png)

ブラウザにip直打ちであっさり接続できる:laughing:
もちろんPCからも同じ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94562/0f9fdcfa-39e4-0cd0-b12e-57ec65e8bb4f.png)