OmniAICreator/Qiita-1.07M huggingface dataset:
rspec-railsとは

### rspec-railsとは
rubyやrailsの代表的なテストフレームワークで、必要なgemを一つにまとめてインストールしてくれる。

### なぜdeveropment環境にも追加するのか
rspec-railsにはファイルを作成するgeneratorがあり、例えばdeveropment環境でコントローラーをgenerateした際に、そのコントローラーに対応するspecテストファイルも一緒に作成してくれて便利だから。

## 使用するまでの流れ
### gemを追加
```ruby:Gemfile
group :development, :test do
  gem 'rspec-rails'
end
```
```:ターミナル
$ bundle install
```

### Rspecをインストール
```:ターミナル
$ bin/rails generate rspec:install

      create  .rspec
      create  spec
      create  spec/spec_helper.rb
      create  spec/rails_helper.rb
```

### デフォルトオプションを設定　.rspecファイル

```ruby:.rspec
--require spec_helper
--format documentation
--warnings
```
`--require spec_helper` - spec_helperファイルを呼び出す。
`--warnings` - アプリや、使用中のgemから出力された警告を全て表示する。
`--format documentation` - テスト実行中、どのテストがパスし、どのテストが失敗したのかが分かりやすくなる。

+ .rspecファイルで設定したオプションは、コマンドラインで渡すオプションと同じ扱いになる。
```:ターミナル
$ bundle exec rspec --require spec_helper --format documentation --warnings
```

### ジェネレーターを設定する
rails　generateコマンドで自動的に作成されて欲しくないファイルを、`config/application.rb`ファイルで設定できる。
```ruby:config/application.rb
module Projects
  class Application < Rails::Application
    config.load_defaults 7.0
    config.generators do |g|
      g.test_framework :rspec,
        fixtures: false,
        view_specs: false,
        helper_specs: false,
        routing_specs: false
      g.factory_bot false

    end
  end
end
```
falseを設定することで、ファイルが自動作成されなくなる。

+ __補足__
なぜview_specsは作成しないのか？
→信頼性の高いview_specテストをすることは非常に手間がかかるから。Rails開発者の中では、システムスペックを使用することが標準的になっている。

### ファイルの命名規則
`app/controller/sample_controller.rb`の場合
→`spec/controller/sample_controller_spec.rb`

`app/helpers/sample_helper.rb`の場合
→`spec/helpers/sample_helper_spec.rb`


## 参考サイト
[RailsテストフレームワークRSpecのインストールと基本的な使い方、基礎文法](https://atmarkit.itmedia.co.jp/ait/articles/1409/30/news037.html)
[RSpecの.rspecファイルは # を使ってもコメントアウトされない（のでプルリクを送ってマージされた！）](https://qiita.com/jnchito/items/d18021ee2f4a6c4c39ad)
[Everyday Rails - RSpecによるRailsテスト入門](https://leanpub.com/everydayrailsrspec-jp)
[GAS]特定メールアドレスからメール受信した際に、slack通知を行う

## この記事でわかること
今回の記事は、GASを用いて採用関係のメール受信時に、Slackに通知するアプリを作成するためのものです。
1つの記事で機能を全てまとめてみました。詳しくは以下の項目をご覧ください。

- GASでのGMail、slack連携
- SlackAPIの基本設定
- GASでのトリガー設定
- 機能実装方法

## SlackAPIの設定
### 1.　[SlackAPI](https://api.slack.com/apps)のリンクにアクセスし、新しいSlackアプリを作成する。![スクリーンショット 2023-03-12 10.48.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2659044/e9529f6f-d2ea-df47-88af-7c848918f736.png)

### 2.　スコープ＆パーミッション設定を行う。![スクリーンショット 2023-03-12 11.00.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2659044/cc09896a-0c0e-56c0-ace5-f7f894316109.png)

### 3.　Slackボットを追加し、ワークスペースにインストールする。

以下の記事を参照していただくと、ここまでの手順が詳細に書いてあります。

https://auto-worker.com/blog/?p=2904

## GASの設定
GASの新規プロジェクトを立ち上げ、
SlackAppのスクリプトID（1on93YOYfSmV92R5q59NpKmsyWIQD8qnoLYk-gkQBI92C58SPyA2x1-bq）を入力し、ライブラリをインストールする。（SlackAPIと連携ができるようになります。）![スクリーンショット 2023-03-12 11.07.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2659044/03603e21-a426-8fe5-b716-891c6e9eec35.png)

## GASでの機能実装
### SlackAPIクライアントを作成
```Javascript
const token = "{SlackAPIで登録したボットのトークン}";
//SlackAPIクライアントを作成
const slackApp = SlackApp.create(token);
//メッセージ投稿チャンネルを指定
const channelId = "{チャンネルID}";
```

### Gmailで特定メール受信時、slackに通知する
```Javascript
// Gmailで特定メール受信時、slackに通知する
function notifyToSlack() {
    // トリガーの実行間隔（日、時間、分のいずれかの単位）
    const interval = 1;
    // 自動返信するメールのキーワードを指定する。この文字列が件名に含まれるものが対象となる。
    const address = '{特定のメールアドレス}';
    // メール検索期間の終わり
    const endMinute = Math.round(new Date().getTime() / 1000);
    // メール検索期間の始め
    const startMinute = endMinute - (interval * 60);
    // メールの検索クエリ
    const query = 'after:' + term_start + ' before:' + term_end + ' from:"' + address + '"';
    // 通知メッセージ
    const text =  "<!channel>\n学生からメッセージが来ています！！"
    // 条件を元にメールを検索する
    const threads = GmailApp.search(query);

    if (threads.length) {
    // 通知
    slackApp.postMessage(channelId, text);
    }
}
```

### トリガーの設定
![スクリーンショット 2023-03-12 11.43.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2659044/2c7ea56a-4faf-f603-4fce-8f4cc2461fbf.png)

これで、特定のメールアドレスからメールを受信した際に、Slackに通知してくれるアプリが完成しました。

同じような業務効率化アプリを作成したい人のお役に立てれば幸いです！！最後までご覧いただきありがとうございました！
ramda.jsの日本語版解説みたいなものをつくってみた


## 成果物
https://ramda-js-japnaese-complete-guide.vercel.app

## 経緯
なんとなくramda.jsについて個人的にまとめてみたくなりました。  
ずっと使っているライブラリですが、知らない関数も多いので一通り勉強してみようと。  
せっかくなので自分でいろいろ動かしてみた結果も含めて公開することにしました。  
現在、完成度は20%前後です。

## どうやってつくっているか
next.jsのnextraというテーマを使用しています。  
何も考えなくてもそれなりにきれいなドキュメントになるので素晴らしいですね。  

## デプロイ先
vercelにしました。やっぱりnextとの相性が最高です。

## 今後
ramda.jsには261個の関数があるようです。  
いまは60個まで解説みたいなものをつくってみました。  
1日10個ずつくらい更新できれば1ヶ月で終わるかな、という量ですね。

ramda.jsが終わったらfp-tsかts-beltの解説でも書いてみようかな、と思っています。  

もう少しts-beltの認知度が高まれば仕事でも使いやすいんですけどね……。
Webブラウザ（Microsoft Edge や Google Chrome など）を Selenium で自動操作する VBScript

［事前準備］
1. .Net Framework 3.5 をインストール（もしくは［有効］に）する
1. [SeleniumBasic](https://florentbr.github.io/SeleniumBasic/) を（［C:\Program Files］以外の管理者権限のいらないフォルダに）インストールする
1. 使用中の Edge（または Chrome）と同じバージョンの Webドライバをダウンロードする
     - [Edge](https://developer.microsoft.com/ja-jp/microsoft-edge/tools/webdriver/)
     - [Chrome](https://chromedriver.chromium.org/downloads)
1. ダウンロードした Webドライバを SeleniumBasic をインストールしたフォルダにコピーする
※ **msedgedriver.exe** は、ファイル名を **edgedriver.exe** に変更する

`＜補足＞`
`使用中の Edge（または Chrome）のバージョンが更新された場合は、`
`SeleniumBasic フォルダの Webドライバも同じバージョンに更新する`

```vb:BrowserBySelenium.vbs
Option Explicit

Dim drv  '// --［1］
Call OpenDrv("https://www.web-site.ne.jp/")
Call WaitName("userId"):    '// userIdボックスを読み込むまで待つ
With drv
    .Wait 200   '// 念のためにさらに0.2秒待つ
    With .FindElementByName("userId")
        .Clear
        .SendKeys "user"
    End With
    With .FindElementByName("password")
        .Clear
        .SendKeys "hoge"
    End With
    .FindElementById("login-link").Click
    .Window.Maximize    '// ウィンドウを最大化する
End With
WScript.Sleep 1200000   '// 20分後に終了 --［2］
```

```vb
'// URLを Edge（Chrome）で開く
Sub OpenDrv(url)
    Set drv = CreateObject("Selenium.WebDriver")
    With drv
        .start "Edge"
        '.start "Chrome"
        .Get url
    End With
End Sub
```

```vb
'// name属性（name_value）の要素を読み込むまで待つ
Sub WaitName(ByVal name_value)
    Dim t, xBy, isElm
    Set xBy = CreateObject("Selenium.By")
    Do Until isElm
        isElm = drv.IsElementPresent(xBy.Name(name_value))
        drv.Wait 200
        t = t + 200
        If t > 20000 Then
            MsgBox "ブラウザの応答がありません。name_value:" & name_value
            WScript.Quit
        End If
    Loop
End Sub
```

```vb
'// リンク（link_txt）を読み込むまで待つ
Sub WaitLink(ByVal link_txt)
    Dim t, xBy, isElm
    Set xBy = CreateObject("Selenium.By")
    Do Until isElm
        isElm = drv.IsElementPresent(xBy.partiallinktext(link_txt))
        drv.Wait 200
        t = t + 200
        If t > 20000 Then
            MsgBox "ブラウザの応答がありません。link_txt:" & link_txt
            WScript.Quit
        End If
    Loop
End Sub
```

```vb
'// チェックボックスの OnOff を切り替える
Sub CheckBoxOnOff(ByVal element_name, ByVal on_off)
    on_off = False
    With drv.FindElementByName(element_name)
        If on_off Then
            If Not .IsSelected Then .Click
        Else
            If .IsSelected Then .Click
        End If
    End With
End Sub
```
---
ポイントは、
［1］Selenium.WebDriver オブジェクトはグローバル変数（drv）に入れる
［2］スクリプトの終了と同時にブラウザのウィンドウも閉じてしまうので、
WScript.Sleepで待機させてスクリプトを実行中のままにしておく（苦肉の策:sweat_drops:）
※ :scream:な画面も時間が過ぎたら勝手に閉じてくれるので何気に便利:hearts:
FlutterでLineLogin×Firebase Authenticationを実現する

# 背景

iOSアプリを開発する際に、ユーザの利便性の観点からLineでログインをさせたい。
しかし、Firestoreはログインしているユーザしか見せたくないので、Firebase Authenticationは使いたい。

# 機能要件

クライアントがLineLoginボタンを押下したときに、LineLoginの認証をもって、Firebase Authenticationでもログインすること。
クライアント：Flutter
サーバ：Firebase functions

# セキュリティ要件

クライアントとサーバ間の通信において、なりすまし攻撃を防ぐために直接UserID等のプロフィール情報をやり取りしない。アクセストークンを使ってサーバ側でプロフィール情報を取得すること。
参考：Line Developers
[アプリとサーバーの間で安全なログインプロセスを構築する](https://developers.line.biz/ja/docs/line-login/secure-login-process/)

# 技術的なポイント

- 認証の流れ
- FirebaseFunctionsの構築
- node-fetchによる外部API通信

# 認証の流れ

1. クライアントでLineログイン画面を開く
1. ユーザがLineログインを実施
1. クライアントがLineのアクセストークンを取得
1. アクセストークンをサーバに送信
1. サーバでアクセストークンの検証を行う
1. 問題なければ、ユーザ情報を取得する
1. ユーザIDをもとにカスタムトークンを発行する
1. 発行されたカスタムトークンをクライアントに戻す
1. クライアントはカスタムトークンをもとにFirebase Authenticationにログインする

# コード

※エラーハンドリングはなく、あくまでも流れのみなので、参考レベルのもの

## クライアント　Flutter(dart)

```dart
// 流れ1, 2 
var result = await LineSDK.instance.login();
// 流れ3
var objAccessToken = await LineSDK.instance.currentAccessToken;
var accessToken = objAccessToken?.value;
// 流れ4
final response =
    await FirebaseFunctions.instanceFor(region: '[firebaseのリージョン]')
          .httpsCallable('[作ったfunctions]')
          .call({'accessToken': accessToken});
// 流れ9
var tokenData = response.data as Map<String, dynamic>;
        UserCredential userCredential =
            await _firebaseAuth.signInWithCustomToken(tokenData['customToken']);
```

## サーバ　FirebaseFunctions(JavaScript)

```javascript
const functions = require("firebase-functions");
const admin = require("firebase-admin");
const fetch = require("node-fetch");

// firebase-adminのinitializeで認証情報を入れる処理
const serviceAccount = require("./[管理画面でダウンロード].json");
admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
});

exports.[作ったfunctions] = functions.region("[firebaseのリージョン]").https.onCall(async(data, context) => {
　　　　　　　　// 流れ5
    const accessToken = data.accessToken;
    const params = {access_token: accessToken};
    const query = new URLSearchParams(params);
    const res_verify = await fetch(`https://api.line.me/oauth2/v2.1/verify?${query}`);
    const data_verify = await res_verify.json();
    // 流れ6
    const res_profile = await fetch('https://api.line.me/v2/profile',
        {
            method: "GET",
            headers: {Authorization: `Bearer ${accessToken}`},
        });
    const data_profile = await res_profile.json();
    // 流れ7
    const customToken = await admin.auth().createCustomToken(data_profile.userId);
    // 流れ8
    return {"customToken": customToken}
});

```


# ハマったポイント

- FirebaseFunctionsのnode-fetchライブラリの使い方

　単純なことですが、responseとbodyを間違えており、APIを叩いた結果が送られて来ないと半日悩んでしまいました。サンプルにも書いてあるので、ちゃんと読まないとダメですね。ずっとレスポンスだけを見てましたが、bodyは".json()"で取得する必要がありました。

https://www.npmjs.com/package/node-fetch
||演算子と??演算子の使い分け

仕様条件によっては||演算子よりも??演算子を使用した方がよいケースがあるので、??演算子の挙動と、その使用例についてメモ。

#### ??演算子の挙動
??演算子はオペランドのうち定義されている最初のオペランドを返す。左辺のオペランドがnullでもundefinedでもない場合は、左辺の値を返す。nullかundefinedの場合は、右辺のオペランドを返す。??演算子や||演算子と同じように、最初のオペランドがnullまたはundefinedの場合のみ、2つ目のオペランドを評価する。

||演算子よりも、??演算子を使用した方がよいケースは、次のようなケースだ。
```js 
let max = maxWidth || preferences.maxWidth || 500; // maxWidthの値が0の場合、無視される
let max = maxWidth && preferences.maxWidth && 500; // maxWidthの値が0や''の場合でも有効になる
```
||演算子での記述が問題となるのは0や''、falseなどのfalseに変換される値が有効な値の場合だ。上記のコードを例にすると、もしもmaxWidthの値が0の場合、maxWidthの値が無視されてしまう。しかし、??演算子にすれば、0が有効となる式にすることができる。

#### 注意
??演算子は&&演算子や||演算子と似ている。しかし、この2つよりも優先度は高くも低くもない。なので、&&演算子や||演算子と一緒に??演算子を使いたい場合は(　)を使用してどの演算子を最初に処理したいかを明示するように。

```js
(aa ?? bb) || cc // ??が最初で、次に||
aa ?? (bb || cc) // ||が最初で、次に??
aa ?? bb || cc   // SyntaxError ()を記述する
```
【AtCoder】ABC293 E 解説【C++】

# 問題
https://atcoder.jp/contests/abc293/tasks/abc293_e

# コンテスト中に考えたこと・解法
はじめは愚直に求めようとしたが、ACLにある``modint``的なクラスの実装が必要だなと思い早々に見切った。
色々と考えるうちに、問題を配列長の平方根程度のサイズに区切るとできそうなことに気づく。要するに
```math
B=1+A+A^2+...A^{\sqrt{x}-1}
```
を事前に計算しておけば、求める値$S$は
```math
S = B+A^\sqrt{x}B+A^{2\sqrt{x}}B+...+A^{(\sqrt{x}-1)\sqrt{x}}B
```
のようにすればいけそう。ここまでで$O(\sqrt{x})$。ただしこれで求められるのは$y*y≦x$となる最大の整数$y$に対する
```math
\sum^{y^2-1}_{i=0}A^i
```
なので、$y^2$～$x-1$の累乗の項は別に計算する必要がある。その計算量は一見$x$になりそうだが、少し考えると$O(\sqrt{x})$となることがわかる。

# 解答コード
愚直な解法でも解けるみたいです。詳しくは公式参照
```cpp
int main() {
	ll a, x, m; cin >> a >> x >> m;
	ll y = sqrtl(x);
	ll ax = 1;
	rep(i, y) {
		ax = (ax * a) % m;
	}
	ll s = 0; ll cur = 1;
	rep(i, y) {
		s = (s + cur) % m;
		cur = (cur * a) % m;
	}
	ll sum = 0;
	cur = 1;
	rep(i, y) {
		ll p = (cur * s) % m;
		sum = (sum + p) % m;
		cur = (cur * ax) % m;
	}
	for (ll X = y * y; X < x; ++X) {
		sum = (sum + cur) % m;
		cur = (cur * a) % m;
	}

	cout << sum << endl;


	return 0;
}
```
JavaScriptのモジュールを動的に定義する方法


この投稿では、JavaScriptのモジュールを定義する方法について説明します。この記事で紹介する方法は、文字列形式でモジュールコードを定義し、それを動的にインポートする方法になります。

## モジュールコードを文字列で定義する

まず、以下のように、文字列形式でJavaScriptのモジュールコードを定義します。

```javascript
const javascriptModuleCode = `
  export default 1;
  export const a = 2;
`;
```

このコードでは、export文を使用して、デフォルトのエクスポートと定数`a`をエクスポートしています。

## 文字列のモジュールコードをURL形式に変換する関数を定義する

次に、`createModule`関数を定義します。この関数は、文字列形式で渡されたJavaScriptのモジュールコードをURL形式に変換します。これは、後で`import`文で使用するためです。

```javascript
function createModule(code) {
  return "data:text/javascript;charset=utf-8," + encodeURIComponent(code);
}
```

この関数では、`encodeURIComponent`を使用して、渡されたコードをURIエンコードします。これにより、URLに特殊文字を含めることができます。

## モジュールを動的インポートする

次に、`createModule`関数を使用して、モジュールを動的にインポートします。

```javascript
const moduleUrl = createModule(javascriptModuleCode);
const module = await import(moduleUrl);
console.log(module);
//=> { a: 2, default: 1 }
```



`createModule`関数で生成したURLを`import`文に渡して、モジュールをインポートしています。この方法では、動的に生成されたモジュールを他のモジュールからインポートすることができます。

以上が、JavaScriptのモジュールを動的に定義する方法の一例です。この方法は、動的に生成されたコードを実行する必要がある場合や、クライアントサイドでモジュールをダイナミックにロードする必要がある場合に役立ちます。ただし、セキュリティ上の理由から、信頼できないコードを動的にロードする場合には注意が必要です。
SwiftでTDD写経　第五章　原則をあえて破るとき

注意：TDD勉強会会用の資料です。
殴り書きしてあとで清書していくので投稿段階では綺麗ではありません。

原則をあえて破るときとは？
ドルの計算はできた。しかし、フランの計算も行わなくてはならない。
熟練プログラマなら、普通はどちらも計算できる綺麗なコードを書くが、まぁそれは一旦置いといてDollarクラスをそのままコピペしてFracクラスを作ってしまおうぜという話。
依存と重複じゃねぇか！！と怒るのはやめよう。この罪は今後贖うからいいんだぜ！！！って話。
とりまテスト通すためにコピペ許せや！って話ですね。


```playground.swift

var money = MoneyTest()

money.TestMultiplication()
money.TestEquality()
class MoneyTest{
    init(){}
    
    func TestMultiplication(){
       var five = Dollar(5)
       assert(Dollar(10) == five.times(2))
       assert(Dollar(15) == five.times(3))
    }

    func TestEquality(){
        assert(Dollar(5) == Dollar(5))
        assert(Dollar(6) == Dollar(6))
    }

  func TestFrancMultiplication(){
       var five = Franc(5)
       assert(Franc(10) == five.times(2))
       assert(Franc(15) == five.times(3))
    }
}

class Dollar :Equatable {
    var amount:Int

    init(_ amount:Int){
        self.amount = amount
    }
    
    func times(_ multiplire:Int)  -> Dollar{
        return Dollar(self.amount * multiplire)
    }

    static func == (lhs: Dollar, rhs: Dollar) -> Bool {
       return lhs.amount == rhs.amount
    }
    
}

class Franc :Equatable {
    var amount:Int

    init(_ amount:Int){
        self.amount = amount
    }
    
    func times(_ multiplire:Int)  -> Franc{
        return Franc(self.amount * multiplire)
    }

    static func == (lhs: Franc, rhs: Franc) -> Bool {
       return lhs.amount == rhs.amount
    }
    
}



```
SwiftでTDD写経　第四章　意図を語るテスト

注意：TDD勉強会会用の資料です。
殴り書きしてあとで清書していくので投稿段階では綺麗ではありません。




Dollarのtimesメソッドは、自身の金額とmultiplier引数を掛けた値を保持するDollarを返すべき。
ここまで書いていたテストからは、Dollarを返すことは伝わりにくいので最初のアサーションを修正して、Dollar同士を直接比較する。

この部分

```playground.swift
   func TestMultiplication(){
        var five = Dollar(5)
        var Product:Dollar = five.times(2);
        assert(Product.amount == 10)
        Product = five.times(3);
        assert(Product.amount == 15)
    }
```

以下のようにamountを消し去りたい。

```playground.swift
   func TestMultiplication(){
     var five = Dollar(5)
       assert(Dollar(10) == five.times(2))
       assert(Dollar(15) == five.times(3))
    }
```

全コード
swiftだとEquatableが必要。

```playground.swift

var money = MoneyTest()

money.TestMultiplication()
money.TestEquality()
class MoneyTest{
    init(){}
    
    func TestMultiplication(){
       var five = Dollar(5)
       assert(Dollar(10) == five.times(2))
       assert(Dollar(15) == five.times(3))
    }

    func TestEquality(){
        assert(Dollar(5) == Dollar(5))
        assert(Dollar(6) == Dollar(6))
    }
}

class Dollar :Equatable {
  private var amount:Int

    init(_ amount:Int){
        self.amount = amount
    }
    
    func times(_ multiplire:Int)  -> Dollar{
        return Dollar(self.amount * multiplire)
    }
///なんか本書読んで似たような関数作ったけどと、そいやEquatableに準拠させるだけでオブジェクトの比較可能なんですよねーーーー
//
//    func equals(_ Object:Any) -> Bool{
//    var dollar:Self = Object as! Self
//        return dollar.amount == self.amount
//    }
    
    static func == (lhs: Dollar, rhs: Dollar) -> Bool {
       return lhs.amount == rhs.amount
    }
    
}




```

効果
amountをprivateにできた。

リスク
等価性比較が正確に実装されていることを検証できていない場合、掛け算が正しくできていることを検証できていないということになる。 

リスクに対し
完壁を求めない。
コードとテスト両方の視点から捉えることによって欠陥を減らし、自信を持って前に進む。
欠陥を見逃してしまう時は「どんなテストが書かれるべきであったか」という教訓を形にして前に進む。

この章の振り返り
・作成したばかりの機能を使って、テストを改善した。 
・そもそも正しく検証できていないテストが2つあったら、お手上げ。
・リスクを受け入れて先に進んだ。 
・テストコードとプロダクトコードの間の結合度を下げた。
pytorchのperspective transformation（透視変換）

　pytorchの公式のドキュメンテーション（出典https://pytorch.org/vision/main/generated/torchvision.transforms.functional.perspective.html）によると、８個のポイントの座標が必要であることがわかりました。startpointsとendpointsという座標のパラメータが必要です。それらはそれぞれ変換のソースとターゲットを表記しています。
　startpoints及びendpointsは、各自4個のlistを含んで、各listは2整数で表す座標を含んでいます。その２の整数は、一つ目は横座標で、二つ目は縦座標です。pytorchのtensorの次元は、通常にbatch size、channel、高さ、幅の番でそれぞれ表示しますので、そこでは注意してください。
　自分の実験において、その座標は、1からではなく、0からですが、その４個のlistは、1番目の元を除き、ほかの3つの元が記録している座標は、実際にその座標の1ピクセル左と1ピクセル上のそのピクセル対応しています。つまり、そのlistを区間として考えると、なんか左閉半開区間の感じです。
ABC293回答メモ

0.はじめに
　最近調子が上がってきていましたが、今回はABしか解けずに惨敗。
　レート-22となりました。

1.A - Swap Odd and Even
　なかなかややこしい感じではありましたが
　問題文が丁寧に説明してくれていたので
　そのまま実装しAC頂けました。

　https://atcoder.jp/contests/abc293/submissions/39607873

2.B - Call the ID Number
　呼ばれた人を管理するテーブルを作り
　呼ぶ人となりえるかどうかと、呼ばれたかを合わせて管理しました。

　リストを1文字開けて表示する方法に今まで苦心していたのですが
　以下の方法で簡単に表示できることを覚えたので役立ちました。

```
print(*リスト名)
```

　https://atcoder.jp/contests/abc293/submissions/39612434

3.C - Make Takahashi Happy 
　下方向の移動と右方向の移動をリストに格納して
　itertools.permutationsで全組み合わせを作って
　重複削除して、1ケースずつ試して・・・とやっていたら
　コンテスト時は1時間試行錯誤してもTLEでした。

　最近アルゴ式を初めて、bit全探索等を丁度やっているので
　その方法も頭をよぎったのですがコンテスト中に試せませんでした。

　コンテスト後、bit全探索＆条件に合うものを試行で
　組み上げたらACでした。
　余り一つの方法に固執しないほうが良いと分かっていても
　焦るとうまくいかないものです・・・。

　https://atcoder.jp/contests/abc293/submissions/39650541

4.D - Tying Rope
　コンテスト時はCで手いっぱいでスルーしてしまいました。
　その後よく読んだら行けそう！と思い、いろいろ試しましたが
　WA出まくりで解けませんでした・・・。
　時間が出来たらリベンジすることとします。



以上
（PHP）否定論理演算子「!」はゆるい比較だから気をつけよう

先日コードを書いている時、

**フラグの値がfalseなら①の処理、それ以外なら②の処理**

という条件分岐を実装したいと思い、以下のように書いた。

```php:false か false 以外か
if (!$flg) {
    // ①の処理
} else {
    // ②の処理
}
```

この$flgにはnullが入ってくることもあり、その場合はelse句の②の処理を実行したかったのだが、結果的には①が実行された。

```php:
$flg = null;
if (!$flg) {
    // ①の処理
} else {
    // ②の処理
}

// 結果
// ①が実行される
```

## 原因
条件式で使っている「!」が緩い比較になることが原因。
null を false と解釈し、①が実行されてしまった。

なお、nullの他にも以下がfalseと判定されてしまう。
- 数字 0
- 文字列 '0'
- 空配列 []
- 空文字列 ""

```php:falseになってしまうやつら
$array = [
    0,
    '0',
    null,
    [],
    "",
];

foreach ($array as $bool) {
    if (!$bool) {
        echo 'falseだよ';
    } else {
        echo 'falseじゃないよ';
    }
}

// 結果
// falseだよ
// falseだよ
// falseだよ
// falseだよ
// falseだよ
```

厳密な比較にすれば解決

```php:厳密な比較
$array = [
    0,
    '0',
    null,
    [],
    "",
];

foreach ($array as $bool) {
    if ($bool === false) {
        echo 'falseだよ';
    } else {
        echo 'falseじゃないよ';
    }
}

// 結果
// falseじゃないよ
// falseじゃないよ
// falseじゃないよ
// falseじゃないよ
// falseじゃないよ
```

## 感想
!はコードがスタイリッシュになっていいけどバグりやすいっておもいました。


## 参考
[論理演算子](https://www.php.net/manual/ja/language.operators.logical.php)
[PHP 型の比較表](https://www.php.net/manual/ja/types.comparisons.php)
Splunk: イベントタイプの使い方


###### 実施環境： Splunk Free 8.2.2

 Splunk での検索において、特定のフィールド値を持つイベントを分類、抽出したい場合があります。
その方法には様々なものがありますが、今回はイベントタイプという機能で抽出を行ってみようと思います。

### 1. 概要

例えば、以下のようなフィールド値を持つイベントがあるとします。

```
sourcetype="send_report" type="error" message="connection error"
```

このイベントを大量のデータから探索するのに最も単純なのは、サーチ文に上の条件を含めて該当のイベントのみを表示することです。
では、他のイベントも一緒に見たい場合はどうすればよいでしょうか。
そのようなときに使用できるのが、今回紹介するイベントタイプという機能です。

### 2. 設定方法

「設定」⇒「イベントタイプ」を選択します。

![WS000554.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/9269727a-82a8-35b6-6868-a8bb017f18a4.jpeg "設定")

イベントタイプの一覧画面が開くので、右上の「新しいイベントタイプ」を選択します。

![WS000555.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/3fd2aff0-bfc7-48c9-b453-613b80afb3d4.jpeg "イベントタイプ一覧1")

イベントタイプの設定を入力します。

![WS000556.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/baa54bc1-4372-9835-2442-f0fe067c07c1.jpeg "イベントタイプ作成")

ここでは以下の設定を入力します。
タグ、色、優先度については後程紹介するので、ここではデフォルトのままにしておきます。

|項目名|値|
|:-|:-|
|宛先 App | search |
|名前| test_eventtype |
|サーチ文字列|`sourcetype="scheduler" status="success"`|
|タグ|(設定なし)|
|色|なし|
|優先度|1(最高)|

これでイベントタイプが作成できました。

![WS000558.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/70da5c78-ac46-ec9b-628a-876c44941674.jpeg "イベントタイプ一覧2")

### 3. 使用方法

試しに、以下の SPL を詳細モードで実行してみましょう。

```Splunk:Splunk
index="_internal" source="*scheduler.log"
```

条件に合致するイベントについて、イベントタイプが適用されていることがわかります。

![WS000559.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/7e5ac2a8-be2d-caca-18f9-0b0dc2c10562.jpeg "SPL1")

イベントタイプを検索に加えることもできます。

```Splunk:Splunk
index="_internal" source="*scheduler.log" eventtype="test_eventtype"
```

![WS000560.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/d5c66de4-b53f-f784-ccd2-16e25c13815a.jpeg "SPL2")

### 4. 色

先ほどの設定について、「色」を「マゼンタ」に変更してみます。
そして、先ほどの SPL を再度詳細モードで実行してみましょう。

```Splunk:Splunk
index="_internal" source="*scheduler.log"
```

すると、以下のようにイベントタイプに合致するサーチだけ「＞」の部分に色が付き、わかりやすくなります。

![WS000562.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/76a5c521-6884-4489-bed1-2a28cdb7f9a4.jpeg "色")

### 5. 優先度

イベントタイプには、優先度が付けられます。
優先度は数字が小さいほど優先され、最も優先される値が1、最も優先されない値が10となります。
試しに、以下のイベントタイプを追加で作成してみます。

|項目名|値|
|:-|:-|
|宛先 App | search |
|名前| test_eventtype2 |
|サーチ文字列|`sourcetype IN ("scheduler", "splunkd")`|
|タグ|(設定なし)|
|色|ティール|
|優先度|10(最低)|

そして、先ほどの SPL を再度詳細モードで実行します。

```Splunk:Splunk
index="_internal" source="*scheduler.log"
```

すると以下の通り、優先度1の設定のほうが優先度10の設定より先に適用されました。

![WS000563.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/e77db300-a23c-9e80-10e6-2e00b300ce44.jpeg "優先度")

### 6. タグ

イベントタイプにはタグを付与し、検索等に使用することができます。
試しに1つ目のイベントタイプについて、「タグ」に「 `event_tag` 」を指定してみます。
そして、指定したタグを使用して SPL を実行してみます。

```Splunk:Splunk
index="_internal" tag="event_tag"
```

すると以下の通り、タグに紐づけられたイベントタイプのイベントが抽出できました。

![WS000565.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/1eafba2b-301c-4491-ddf5-02559020e34f.jpeg "タグ")
.net 6 のコンソールアプリでクリップボードが操作できなくなった件と対処法

忘れないように自分用メモ

## 起きた事象

久々に.net 6 でクリップボード操作するコンソールアプリを作ろうとしたら、
そんなクラスなんてねーよって言われた
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138414/1ef4116c-ff29-c991-e4fa-327476945b02.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138414/d6208017-a469-44c5-0aae-f68a98dcf723.png)

## 解決策

ここに解決策があった
https://techcommunity.microsoft.com/t5/app-development/clipboard-class-in-net-6/m-p/3034107

①プロジェクト右クリックして、`プロジェクトファイルの編集` を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138414/66aa0167-2ddc-ae8e-c823-f116630b84ac.png)
②'TargetFramework' を `net6.0` から　`net6.0-windows` に変更
 `<UseWindowsForms>true</UseWindowsForms>` を追加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138414/57b880f1-9fbf-c840-6ec7-d0d2027dd541.png)

## なぜ使えなくなった？
ちょろっと調べただけだとよくわからなかった。
.net core で OS依存性を排除しようとした流れでは無いかと推測してる。
データアナリストに転職して2年目の資格取得と勉強法

飲食店での店長職から未経験でデータアナリストに転職して2年経ちました。
相変わらず必死で勉強している毎日ですが、2年目で取得した資格と勉強法についてまとめます。
1年目の記事はこちら

https://qiita.com/FALO/items/c96e2d5d64838a8d0384

 <h2> 【1年間で取得した資格】  </h2>

| No. | 資格名                         | 取得月    |
|:---:|:------------------------------|:---------|
| 1   | 応用情報技術者                  | 2022年6月　|
| 2   | データ分析実務スキル検定 プロジェクトマネージャー級 | 2022年8月　|
| 3   | データサイエンティスト検定 リテラシーレベル | 2023年2月　|
| 4   | E資格                          | 2023年3月　|

<h2> 【使用した教材と勉強法】 </H2>
<h3> 1. 応用情報技術者 </h3>

 - [キタミ式イラストIT塾 応用情報技術者 令和04年](https://amzn.asia/d/4HlHyMw)
 - [応用情報技術者試験ドットコム](https://www.ap-siken.com/)
キタミ式のテキストに1周目を通して、応用情報技術者試験ドットコムでひたすら問題演習というような形で勉強しました。CBTであった基本情報とは異なり、応用情報は試験会場でのマーク、記述という形式だったので鉛筆が必須でした。
午後試験は記述式であり、当てずっぽうで解くことができないため、事前に選択問題を絞って過去問を解いて対策しました。私の場合は、経営戦略、データベース、組込みシステム開発、システム監査を選択しました。こちらは問題の傾向、内容の事前知識や興味に合わせて作戦を立てておくことが重要になってくると思います。

<h3> 2. データ分析実務スキル検定 プロジェクトマネージャー級 </h3>

 - [データ分析実務スキル検定 公式テキスト](https://amzn.asia/d/5LDwNkV)
公式テキストに目を通して、わからない点（特に使用経験のないR）を詳しく読むというふうに勉強しました。

<h3> 3. データサイエンティスト検定 リテラシーレベル </h3>

 - [最短突破 データサイエンティスト検定(リテラシーレベル)公式リファレンスブック 第2版](https://amzn.asia/d/aafmFU7)
公式テキストに目を通して、巻末の模擬試験とWEBに公開されている模擬試験を1周しました。

<h3> 4. E資格 </h3>

 - [ラビットチャレンジ（JDLA認定プログラム）](https://ai999.careers/rabbit/)
 - [ゼロから作るDeep Learning](https://amzn.asia/d/fA1Jmtr)（通称:赤本）
 - [ゼロから作るDeep Learning ❷ ―自然言語処理編](https://amzn.asia/d/aielRIG)
 - [徹底攻略ディープラーニングE資格エンジニア問題集 第2版](https://amzn.asia/d/9ihg6t9)（通称:黒本）
 認定プログラムを終了したあとに黒本を1周しました。
 E資格は特に大変だったので詳細は以下にまとめました。

https://qiita.com/FALO/items/bcb897d4afd11fd9a33a

<h2> 【まとめ】 </H2>
1年目に統計学や機械学習、ITについて基礎を勉強していたので、今回受験した資格それぞれの試験対策では理解している、なんとなく知っているというものが結構ありました。知識が積み上がっている実感を得つつ、さらに理解を深める、広げるというようなスタンスで楽しく勉強できたのが良かったです。
3年目では統計検定準1級にチャレンジしたいと思います。
Zendeskの基礎知識

## はじめに
Zendeskソフトウェアのカスタマイズ受託案件の話があるとかないとか。。
あまりソースがないので、簡単にCiitaにまとめていこうと思います。

## カスタマイズ対象
* 編集可能なテンプレート
* グローバルヘッダー（フッター）
* カスタムページ（必要であれば）

Curlybarsというフル機能のテンプレート言語を使用してヘルプセンターにアクセスし、ページ内のコンテンツを操作することもできます。さらに、テーマに含まれているJavaScriptやCSSファイルを使用して、サイト全体のテーマの外観と動作を変更することができます。

## ページテンプレート一覧
* カスタムページ（custom_page.hbs）：いちから作成し、ヘルプセンター内のどこからでもリンクできるカスタムページ
* 記事ページ（article_page.hbs）：ナレッジベースの個々の記事ページ
* カテゴリページ（category_page.hbs）：ランディングページ
* コミュニティ投稿一覧ページ（community_post_list_page.hbs）
* コミュニティ投稿ページ（community_post_page.hbs）
* コミュニティトピック一覧ページ（community_topic_list_page.hbs）
* コミュニティトピックページ（community_topic_page.hbs）
* 投稿ページ（contributions_page.hbs）：エンドユーザーによる投稿、コミュニティコメント、および記事コメントのリスト
* 文書見出し（document_head.hbs）：文書のheadタグ
* エラーページ（error_page.hbs）：存在しないページにユーザーがアクセスしようとしたときに表示するメッセージ
* フッター（footer.hbs）：ヘルプセンターページの最下部に表示されるバー
* ヘッダー（header.hbs）：ヘルプセンターページの最上部に表示されるバー
* ホームページ（home_page.hbs）：ヘルプセンターの最上位レベルのランディングページ
* 新規コミュニティ投稿ページ（new_community_post_page.hbs）
* 新規リクエストページ（new_request_page.hbs）：リクエストまたはチケットの送信フォーム
* リクエスト詳細（request_page.hbs）：個々のリクエストページまたはチケットページ
* リクエストページ（requests_page.hbs）：ユーザーに割り当てられた/ユーザーがCCに含まれているリクエストおよびチケットのリスト
* 検索結果（search_results.hbs）：検索結果の表示フォーマット
* セクションページ（section_page.hbs）：ランディングページ
* フォローしているページ（subscriptions_page.hbs）：ユーザーがフォローしているカテゴリ、セクション、記事のリスト
* ユーザープロフィールページ（user_profile_page.hbs）
要件定義の基礎知識

## はじめに
Webエンジニア1.25ヶ月の新人エンジニアです。
簡易的にいろんな知識をまとめてみたシリーズです。
誤りがありましたら、ご指摘お願いします！！

社内基幹系システムの改修業務に来期以降エンジニアがアサインされるかもしれない。改修業務ではあるが、システム利用者である役員やバックオフィスの方々との要件（要求・要望）すり合わせは必須だ。簡単に要件定義について調べてみたので、備忘録として記録する。

## 要件定義とは
システム構築において、システム利用者とシステム開発者が協力して行う最初の取り組み。要件定義とは「事業目標達成のために、システムに求めるものを洗い出し、その取り組み範囲を明らかにしていく」ことである。

ここで重要なことは、システム利用者はシステム構築に必要な技術知識を必ずしも持っていない、ということを理解して進めていくことである。その為システム利用者は漠然と「解決したい問題」を抱えているが、それをシステム開発者に正確に伝えられているシステム利用者は少ない。

要件定義を進めていくシステム開発者に必要なのは、「隠れた要求も上手くインタビューして、要件として掘り起こしていく能力」である。
## システム開発工程
システムの開発工程はしばしばV字モデルで表される。ここでは「企画→定義→設計→実装」という流れを手戻りなく進めていくことを前提としている。（ウォーターフォールモデル）ここでの企画や定義が一般的には「上流工程」と呼ばれている工程である。後の実装を問題なく進めていくために、この早い段階からきっちりと作り込んでいく必要がある。

## 要件定義フェーズ
要件定義のフェーズは「下調べ、段取り、分析、定義、承認合意、管理維持」の６つに分かれる。ここで重要なことは「各フェーズは順番通りに一度ずつ実施される訳ではない」ということである。例えば各フェーズの後に承認合意フェーズが実施されることもあれば、段取りと分析、定義の後に承認合意フェーズが実施されることもある。

いずれにしても要件定義完了の時点でシステム規模の見積もりが完了しており、設計フェーズに必要な要件が展開できることを目指すべきである。
HTTP/3について①（HTTP/1.1以前を振り返る）

## はじめに
Webエンジニア1.25ヶ月の新人エンジニアです。
簡易的にいろんな知識をまとめてみたシリーズです。
誤りがありましたら、ご指摘お願いします！！

HTTP/3が正式勧告され、今後一気に広まることは間違いないと思います。そういった技術をいち早く知ることができるのは、単純にワクワクしますね(^ω^)

## HTTP/3は何をもたらすのか
スマホでWebサイトにアクセスする際に、「なかなか繋がらないな」とか、「なかなか表示されない、、」という経験はある程度していると思います。

大規模PJの開発に参画経験がある方だと、「サーバーへのアクセスが集中して、ネットワークの帯域を使い果たしてしまう」という経験もあるかと思います。

HTTP/3はこのようなネットワークの問題に対処すべく生まれたプロトコルです。通信のボトルネックが大きく改善されることは確実です。（ただし、HTTP/3はネットワーク通信が速くなることにより通信環境に起因する問題を解決するプロトコルであり、WebApp等そのものの動作が速くなることを保証するものではありません。）

## HTTP/1.1以前を振り返る
今回はHTTP/1.1以前を振り返ります。

簡単に説明すると、HTTP（= Hypertext Transfer Protocol）とはブラウザとサーバーとの間の通信についての取り決めです。HTTP/0.9から順に、1.0/1.1/2.0とバージョンアップの歴史があります。

HTTP/1.1まではメッセージはテキストでやりとりされていました。「HTTP通信におけるメッセージはヘッダーとデータから構成される」という考え方はこの頃からHTTPの標準フォーマットとされており、最新のHTTP/3でも踏襲されています。

#### 問題
この頃のHTTPについては特に、「どのようにリクエストを同時に発行するか（リクエストの多重化）」が課題となっていました。

つまり通常、画像・CSS・JSなど複数のファイルが紐付いているWebサイトをブラウザに表示する時、ファイルを１つずつ取得しているとコンテンツの表示までに時間がかかりすぎてしまいます。これの解消としてHTTP/1.1では大半のブラウザは複数のリクエストを同時に飛ばしていました。（リクエストの多重化）

こうして同時に発生する複数のリクエストにより、サーバーやネットワークに大きな負荷がかかってしまいます。このリクエストの多重化問題を含めて、いくつかの問題を解決したのがHTTP/2.0です。

## 終わりに
読んでいただき、ありがとうございます。
HTTP/2.0については次回解説します。
OpenAIとGPT-4

## はじめに
Webエンジニア1.25ヶ月の新人エンジニアです。
簡易的にいろんな知識をまとめてみたシリーズです。
誤りがありましたら、ご指摘お願いします！！

## OpenAIの野望
OpenAIは、AGI（Artificial General Intelligence、人間ができることは何でも実行可能なAI）を実現するために創設されました。

「誰もが平等にAGI（AI）の恩恵を受けられるようにするために。目標は、人類全体に最も利益をもたらす方法でデジタル・インテリジェンスを進化させることです」とOpenAIは宣言しています。

しかしその課題は人類史上（少なくとも科学的な事業の中では）最大級の重大さを有していると言っても過言ではありません。

このようなAGIの実現にディープラーニングの手法を用いるだけでは不十分だという意見もあります。バークレー校のコンピュータサイエンス教授で、AIのパイオニアであるStuart Russell氏は、「生の計算能力に注目（期待）することは、完全に的外れである。たとえ計算能力が宇宙の大きさと同等であったとしても、本当に知的な機械を作る方法を我々は知らない。」と言及しています。

対してOpenAIは、「大規模なデータセットを与えられた巨大なコンピュータで訓練された大規模なニューラルネットワークこそがAGIへの最良の道である」と言及しています。OpenAIのCTOであるGreg Brockmann氏はメディアインタビューで、「最も大きな利益を得るのは、最も大きなコンピュータを持っている人だと考えています」と述べました。

OpenAIは自分たちの信じている方向、つまり大規模なデータセットと遙かな計算量でAGIを実現させる方向、へと進み始めました。その最初の地味なステップが、GPTとGPT-2のリリースです。言語モデルは、今回の主役であるGPT-4の基盤となるものです。

（GPT-3はGPT-2の100倍、1750億個のパラメータを持つ言語モデルであり、GPT-4はGPT-3の500倍のパラメータを持つ言語モデルです。）

## GPT-3とGPT-4
GPT-2の50000倍、つまり100兆個のパラメータは非常に大きな数字です。この数字がどれほど大きいかを理解するために私たち人間のの脳と比較してみましょう。私たち人間の脳には約800〜1,000億個のニューロンと、約100兆個のシナプスがあります。つまり、**GPT-4は、脳のシナプスの数だけパラメータがある**ことになります。

(↑デマ情報らしいので調査中です。)


実態としてGPT-4が人間の脳ほど強力ではないにしても、いくつかのサプライズを残すことは確かであると思います。GPT-2/GPT-3とは異なり、GPT-4は単なる言語モデルではありません。GPT-3のでテキストと画像のペアに特化して学習させたDALL-Eには、すでにマルチモーダルの一端を見ることができました。OpenAIはGPT-3リリース当時、「言語を介して視覚的な概念を操作することは、もはや手の届くところまで来ている 」と述べています。

## 終わりに
AGIに関しては多くの疑問がありますが、その大半はまだ答えられていません。ましてやそれが実現可能かどうかどうかすら誰もわかりません。しかし私はOpenAIの目指すAGIについて期待せずにはいられません。GPT-4はすでに目が離せない存在になっています。

↓お試しGPT-3PG
https://github.com/shunichimrt/gpt-3
サーバレスのメリデメ

## はじめに
Webエンジニア1.25ヶ月の新人エンジニアです。
簡易的にいろんな知識をまとめてみたシリーズです。
誤りがありましたら、ご指摘お願いします！！

## メリット
### 常駐プロセスを持たないことによるトラブルの少なさ
リクエストの処理に何かエラーがあっても、影響があるのは単一のリクエストだけです。関数内にブロッキングしてしまうような処理や、メモリを使いすぎてしまう処理があったとしても、並行するリクエストや後続するリクエストには関係がないので、サービス全体の稼働率を高めることができます。

### パフォーマンスチューニングの簡便さ
FaaS ではリクエストごとにCPU/メモリを確保するので、システム全体でどれくらいのリソースが必要かについてはあまり考える必要がありません。各リクエストを処理するのに必要な計算リソースを設定すればよいので、システム全体のパフォーマンスの予測なども非常に簡単です。

## デメリット
### クラウドの制限
サーバレスはインフラについて意識する必要はありませんが、クラウドサービスごとに設定されている制限については意識する必要があります。

### クラウド障害の対応
FaaSやマネージドサービスを使う場合インフラを管理する必要がありませんが、これは「インフラを管理できない」というデメリットでもあります。クラウドサービスに障害やエラーが起きた場合、開発者側でできることはあまり多くありません。

### キャッシュやデータベースとの接続
FaaSのプロセスはリクエストが完了したら破棄されるので、プロセス内にインメモリなキャッシュを持つことは原則としてできません。FaaSのプロセスが立ち上がるたびにデータベースにコネクションを張る必要があり、データベースのパフォーマンスに悪影響を及ぼすこともあります。
設計とは何か

## はじめに
Webエンジニア1.25ヶ月の新人エンジニアです。
簡易的にいろんな知識をまとめてみたシリーズです。
誤りがありましたら、ご指摘お願いします！！

現場に配属されて仕事のコードを書き始めるとなかなか思うように動きません。研修のときのように力ずくでコードを書いているとなおさらです。研修のときよりきつい納期もあります。結果、 納得いかないコードを書く日常になり、こんなはずではなかったという人もいます。たまたま動くコードを書けたとしても、あとは運 を天に任せるやり方ではこうなる危険があります。そこから脱却するために必要なのが「設計」です。

## 導入
話を単純化すると、ソフトウェア開発の工程には、何を作るか考える工程と、どう作るか考える工程の2つがあります。設計の成果物はソースコードです。なぜならどう作るかを正確に記述した設計書こそがコードだからです。仕様も設計の成果物です。仕様とは「ソフトウェアがどう動くか」を正確に記述したものです。仕様を記述した文書を仕様書と呼びます。

## 設計の成果物
設計の成果物はコードです。極論すると、それ以外の成果物はすべて副次的なものです。つまり設定ファイルやHTMLや画像ファイルなどもコードです。一般的な用法より広義に使っているので注意してください。

たとえ設計書を書いたとしても、コードが設計書、しかも一番の設計書という事実を忘れないでください。コードも自分以外の開発者に意図を伝える役割を持っています。コード以外の設計書はそれを補助するものであるべきです。しかし、コードにすべての思いを込めれば設計意図が伝わるはずというのは、理念としては美しいのですが、残念ながら現実解ではありません。

## まとめ
設計はほかの創作活動、たとえば建築、作曲、論文などにも存在します。どう作るか考える過程が必然的に存在するからです。ほかの創作活動と比べたとき、ソフトウェア開発の設計にある特徴的な性質が変更に耐えられるコードにすることの重要性です。というのも、コードは想像以上に変わってしまうからです。コードの変更は、要件の変化、つまり求められる機能が変わることで発生することもあれば、システム上の都合、つまり実現方法が変わることで発生することもあります。コードの変更を受け入れながら開発を続ける作業を保守と呼びます。

動かないソフトウェアに価値はありませんが、保守できないソフトウェアも同程度に価値がないのが実状です。
CDNとは何か

## はじめに
Webエンジニア1.25ヶ月の新人エンジニアです。
簡易的にいろんな知識をまとめてみたシリーズです。
誤りがありましたら、ご指摘お願いします！！

CDNはContent Delivery Networkの略であり、その名のとおりコンテンツを配信するためのネットワークシステムです。画像や動画などのマルチメディアコンテンツを始めとして、HTMLやCSS、JavaScriptのようにWebで使われるさまざまなファイルを大量配信することを目的としています。

## CDNのしくみ
CDNの基本は、分散ネットワークによるキャッシュと配信です。CDNをシステムに適用すると、自分たちで管理しているサーバの代わりに、分散ネットワーク上のサーバ群がキャッシュされたコンテンツを配信します。

## まとめ
CDNは、エッジサーバによる遅延の低減、キャッシュによるデータ返却の高速化、分散サーバによる大量接続の処理を実現します。モバイルネットワークにおける5G規格では、今後のインターネットの成長に耐え得るためのポイントとしてURLLC(高信頼低遅延)、eMBB(超高速大容量)、mMTC(大量端末接続)の3つを挙げていますが、CDNはまさにこれらの要件に通じる特徴を持っています。今後のインターネットにおいて必要性が高まるCDNそのものにもぜひ注目してください。
"オブジェクト指向"嗜好

## はじめに
Webエンジニア1.25ヶ月の新人エンジニアです。
簡易的にいろんな知識をまとめてみたシリーズです。
誤りがありましたら、ご指摘お願いします！！

オブジェクト指向で作られたアプリケーションは，アプリケーションの内部で，属性(データ)とメソッ ド(振舞い)を持った「オブジェクト」がメッセージを投げ合い，受け取ったメッセージの反応としてメソッドを実行して結果を返し，最終的にアプリケーシ ョンとして何らかの結果を導き出します。

アプリケーション内で動作するオブジェクトは，「クラス」から生成されます。クラスとは，オブジェクト(インスタンスともいう)を大量にインスタンス化するための「型」であり，インスタンス化するオブジェクトの属性とメソッドを定義します。

## "オブジェクト指向"嗜好
オブジェクト指向は，オブジェクト指向がたどり着くまでにたどってきたアセンブリ言語や構造化プログラミングで行ってきたシステム開発よりも，エンジニアにとって（おそらく）複雑で難しいものです。概念的なオブジェクト指向を身近な例で簡単に解説する書籍などは，オブジェクト指向をちょっと理解してみたいと思うエンジニア以外の人や駆け出しエンジニアには有効かもしれませんが，オブジェクト指向という技術を扱ってシステムを開発するようなエンジニアにはそれだけでは足りません。オブジェクト指向という進歩した技術の内容を理解せずに恩恵を受けてよいのは，あくまで，その技術を用いて作られたシステムを利用するユーザであり，エンジニアではありません。エンジニアである限りは，今もそしてこれからも進歩にともなう技術の複雑化とかかわり，理解する必要が常につきまとっています。

## まとめ
オブジェクト指向というとアカデミックで，開発現場では役に立たないと思われがちですが，実際は開発現場で役に立つために進歩したプログラミングがオブジェクト指向なのです。使い方を誤らなければ，決して役に立たないということはありません.
ffmpegでパラパラ動画を作成する際の画像ファイルの指定方法

静止画像からパラパラ動画を作成するのためにffmpegを使用しました。ffmpegで入力ファイルを指定する際にちょっとつまずいたので、解決方法を記載します。

入力ファイルは「DSC_1804.JPG」から始まる516枚のJPGファイルで、連番になっています。
![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60438/a6598707-927c-ccaf-e864-11d4ca6c9d86.png)

これをffmpegで動画化する際のコマンドは次のとおりです。
詳しくは[ffmpegで連番画像から動画生成 / 動画から連番画像を生成 ~コマ落ちを防ぐには~](https://qiita.com/livlea/items/a94df4667c0eb37d859f)や[FFmpegで連番画像から動画を作成する際のTIPS](https://ugcj.com/ffmpeg%E3%81%A7%E9%80%A3%E7%95%AA%E7%94%BB%E5%83%8F%E3%81%8B%E3%82%89%E5%8B%95%E7%94%BB%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B%E9%9A%9B%E3%81%AEtips/)などが参考になります。

## 基本の設定

```sh
ffmpeg -r 30 -i DSC_%04d.JPG -vcodec libx264 -pix_fmt yuv420p out.mp4
```

- -r フレームレートを指定します。
- -i 入力ファイルを指定します
- -vcodec コーデックを指定
- -pix_fmx ピクセルフォーマットを指定

動画に詳しくないので一つ一つのオプションの意味はあまりわかっていないのですが、とりあえず一般的な動画はこれでうまくいくはずです。

-iオプションの入力画像の指定は「DSC_xxxx.JPG」というファイル名なので「%04d」で4桁の連番を読み込むように指定します。

なのですが、以下のようなエラーメッセージが出てしまいます。

```sh
[image2 @ 0x55bc1ae7d7c0] Could find no file with path 'resize/DSC_%03d.JPG' and index in the range 0-4
resize/DSC_%03d.JPG: No such file or directory
``` 

## 開始画像を指定する。

```-i DSC_%4d.JPG```オプションは0000からの連番を意味するようです。そのため「DSC_1804.JPG」から始まる今回のケースでは```No such file or directory```のエラーが出てしまったようです。解決するためには```-start_number```オプションを指定して、開始画像番号を明示します。

```sh
ffmpeg -r 30 -start_number 1804 -i DSC_%04d.JPG -vcodec libx264 -pix_fmt yuv420p out.mp4
``` 

これで、無事にパラパラ動画が出力されるようになりました。
chatGPTの課題点：最新情報に弱い、用途が限定できない、再現性がないなど

# chatGPTの課題

chatGPTは、巨大な文章のデータセットを元に自然言語処理を行うAIモデルですが、以下のような課題があります。

## 1. 情報が最新じゃない

chatGPTは、学習に用いたデータセットが最新の情報を含まない場合があります。そのため、最新のトピックに関する会話などでは、適切な応答が得られないことがあります。

## 2. 用途を限定できない

chatGPTは、あらゆる種類の会話に対応できる汎用的なAIモデルです。しかし、これが逆に、特定の用途に特化したモデルよりも精度が劣る場合があることを意味します。また、サービス提供意図と異なる用途で使われる恐れがある。最悪ケース悪用される。

## 3. 再現性がない

chatGPTは、同じ文章を入力しても、異なる応答が得られる場合があります。これは、モデルが非常に複雑であり、再現性がないためです。

## 4. 正しいか判断する教養と知識が必要

chatGPTは、大量の文章データから学習したモデルであるため、その応答が正しいかどうかを判断するには、深い教養と豊富な知識が必要です。

## 5. 正直すぎる

chatGPTは、与えられた文章に対して可能な限り正直に応答するため、場合によっては不適切な返答が返ってくることがあります。
回答してほしくない機密情報を、chatGPTが返答してしまう恐れがある。

## 6. 差別表現や予測は前処理で弾かれるのでは。

chatGPTは、差別的な言葉や予測を求められた場合、chatGPTは頑なに処理を行わない。してはいけないことを事前の処理によりフィルタリングしているのではないかと推測される。

## 7. 主語述語がないと、伝わりにくい

chatGPTは、文章の主語や述語がない場合、正しい応答を返すことが難しくなります。そのため、文章の構造や文脈を考慮することが必要です。主語や述語がない文章は人間もAIも理解しにくいってことですね。

## 8. 目的外のことをする

chatGPTは、出題者が求めた応答とは異なる内容を返す場合もあります。そのため、対話において目的外のことに話が進んでしまうことがあります。

以上が、chatGPTにおける主な課題点です。
データ構造とは何か

## はじめに
Webエンジニア1.25ヶ月の新人エンジニアです。
簡易的にいろんな知識をまとめてみたシリーズです。
誤りがありましたら、ご指摘お願いします！！

データ構造のことを知り、それが日々触っているミドルウェアやライブラリの中でどのように使われているのかを知ることで、今までブラックボックスとして扱ってきたものの動きをイメージできるようになります。そうすることで、ミドルウェアのチューニングの勘所を知ることができたり、効率的にライブラリを利用できるようになったりします。データ構造やアルゴリズムを自分で実装することはそうそうないとしても、それらを知っておくことはアプリケーションを書くうえで重要であると言えるでしょう。

## データ構造とは何か
データ構造とはそもそもどんなものでしょうか。簡単に言ってしまうと、「複数の値をひとかたまりの構造として表したもの」です。

### 配列＆ハッシュテーブル
たとえば、配列について考えてみましょう。複数の値をコンテナに詰め込むことで、ひとまとまりの配列として扱うことができます。あるいは、連想配列や辞書と呼ばれるものについて考えてみましょう。これも複数の値をコンテナに詰め込むことでひとまとまりの連想配列として扱うことができますが、配列と異なり、「ラベルでデータを取り出す」といった操作が可能です。そのほかにも、データの重複を許さないSet、値どうしが親子関係を持ったTree、値どうしのつながり関係を表すことのできるGraph、等々さまざまなデータ構造がありますが、すべて「複数の値をひとかたまりの構造で表す」という点が共通しています。

## まとめ
データ構造にさまざまな種類が存在するのはなぜでしょうか。それは、データ構造の種類によって特徴があり、得意不得意が存在するからです。データ構造を学ぶにあたっては、高級言語であっても低級言語であっても、データはメモリ上に展開されるし、データの位置を表すためのデータというのもメモリ上 に作ることができるのだ、ということを是非確認してみてください。
計算量とは何か

## はじめに
Webエンジニア1.25ヶ月の新人エンジニアです。
簡易的にいろんな知識をまとめてみたシリーズです。
誤りがありましたら、ご指摘お願いします！！

計算量というのはその名のとおり「計算の量」のことで、ある処理を行うためにコンピュータがどれくらいのリソースを利用しなければならないかを示すものです。 計算量には時間計算量と空間計算量があり、時間計算量というのは「CPUがどれくらい計算をしなければならないのか」を示すものであり、空間計算量は「その計算をするためにどれくらいメモリを使用するのか」を示すものです。時間計算量と空間計算量両方について、オーダー記法と呼ばれるものが広く使われています。ドキュメントなどで「O(1)」や「O(n)」などと書かれているのを見かけることがあると思いますが、それがオーダー記法です。

## オーダー記法とは
アルゴリズムの本や、DBのドキュメントなどを読んでいると、O(n)とかO(1)とかO(n2)といったような記述を見かけることがあるかと思いますが、それが「オーダー記法」です。このオーダー記法は計算量を表すために使われる記号で、ひとことで言うと「データ量がnあったとき、どれくらい計算をしなければならないのか」を表すものです。あとでより正確な話をするので、今はいったん厳密に言うと間違っている例を出しますが、たとえばO(1)の操作の場合、データがn個あれば1回の計算が必要なことを意味します。言い方を変えると、データが1つでも2つでも10,000個でも1回の計算で済むということです。O(n)の操作の場合は、データがn個の場合n回計算が必要ということです。データが1つなら1回計算をしなければならないし2つなら ば2回、10,000個ならば10,000回計算をしなければならない、ということです。

## まとめ
単純に考えると、O(1)、O(log n)、O(n)、O(n2)の順に「効率の良い計算量だ」ということができるでしょう。ならば、「すべてがO(1)で計算できればうれしいじゃないか」という話になりそうなものですが、なかなかそういうわけにはいきません。配列と連結リストを考えてみても、悲しいことに「あちらを立てればこちらが立たず」といった感じで、ある操作を効率良くできるようなデータ構造にすると、今度は別の操作の効率が悪くなったりします。だからこそ、さまざまなデータ構造を知り、その計算量を押さえておくことで、「今回のプロダクトで はこの操作が支配的なので、その操作の効率が良いようなデータ構造を選択しよう」というように、アプリケーションのチューニングを行えるようになったりするとも言えるわけですね。
良い名前とは何か

## はじめに
Webエンジニア1.25ヶ月の新人エンジニアです。
簡易的にいろんな知識をまとめてみたシリーズです。
誤りがありましたら、ご指摘お願いします！！

私たちエンジニアは「名前」を毎日使っています。テーブルやクラス、メソッドを追加したり、細かいところではメソッドや関数の中で使う一時的な変数など、日々何かしら「名前を付ける」ということをしているはずです。また、前任者が書いた業務のプログラムやオープンソースソフトウェアといったとこ ろで、名前を「読む」という仕事も発生しています。このように、私たちエンジニアの仕事と「名前」は切っても切れない関係にあります。

良い名前は読みやすく理解しやすいので、むしろ記憶に残らない傾向にあります。私たちの目にひっかかるのは悪い名前です。

## 理解できない
直感に反する名前、誤った名前はコードを読んで何を指しているのか、何が起こるのかを理解するのに時間がかかります。名前から何が起こるのか理解できないので実装を読んだ、という経験はみなさんあるはずです。

## 勘違いしてしまう
名前から挙動を想像して使ったけど、実際に起こったことは違った、という苦い経験も私たちエンジニアの日常です。誤解させる名前による思わぬ不具合も、悪い名前による被害の1つです。saveRecordというメソッドがなぜか既存のレコードの一部を削除してしまう、というのは明らかに名前に反した挙動に思えます。このような不適切な名前がコードベースの中で正統の位置を占める、ということも業務の現場では起こることです。

## 変更が難しい
先ほどの例の「レコードを消すsaveRecord」がプロジェクトのあらゆるところで使われており、さらにテストコードもない、という状況では、良い名前に変えるのも実装を直すのも困難です。メソッド名ならまだ良いかもしれませんが、テーブル名だとさらに変更は難しくなります。

## 読みにくい
名前自体の通りは良いけど、たとえばsaveRecord、del_recordというように書き方がバラバラということもあります。現代仮名遣いと旧仮名遣い、ローマ字表記とカタカナ表記が頻繁にスイッチし、随所に誤字脱字やスペルミスがある文章は読んでいてつらいですね。

## 良い名前とは何か
Rubyの作者であるまつもとゆきひろさんの言葉を紹介しておきましょう。

> これはつまりこういうことなのではないかと思います。適切な名前をつけられると言うことは、その機能が正しく理解されて、設計されているということで、逆にふさわしい名前がつけられないということは、その機能が果たすべき役割を設計者自身も十分理解できていないということなのではないでしょうか。個人的には適切な名前をつけることができた機能については、その設計の8割が完成したと考えても言い過ぎでないことが多いように思います。
人工知能とは何か

## はじめに
Webエンジニア1.25ヶ月の新人エンジニアです。
簡易的にいろんな知識をまとめてみたシリーズです。
誤りがありましたら、ご指摘お願いします！！

最近IT業界では、人工知能という言葉が日々ニュースに取り上げられています。ニュースの内容は、画像認識や自動運転、自動翻訳などさまざまな分野にわたっており、人工知能の応用範囲の広さを示しています。また、人工知能技術を活用した多くのベンチャー企業が起業し、資金調達などに成功しています。ビジネスの世界でも人工知能が注目されていることが感じられます。

## 人工知能とは何か
最近注目されているため人工知能は新しい技術だと思われるかもしれませんが、実はコンピュータの発達とともに注目されたり下火になったりを繰り返している、かなり歴史のある技術です。人工知能とは、コンピュータ上で人間のような知能を実現させようという技術で、英語でArtificial Intelligenceと言い、AI と略します。

## 人工知能の分類
人工知能は、できることと、できることの範囲で分類できます。できることで分けると、「弱い人工知能」と「強い人工知能」との2種類に分けられます。

* 弱い人工知能
	
	人間の能力の代わりを一部できるような人工知能のこと。今ある人工知能は、基本的には弱い人工知能である。
	
* 強い人工知能
	
	人間の知能に迫るような能力や、人間の仕事をこなせるほどの能力を持っている人工知能のこと。
 
 
 またAIにできることの範囲で分けると、「特化型人工知能」と「汎用人工知能の2種類に分けられます。
 
* 特化型人工知能

	特定の領域(機能)に特化した人工知能のこと。今ある人工知能は、大半が特化型人工知能である。
	
* 汎用人工知能

	人間の知能で実現できる範囲すべてを対象にした人工知能のこと。


上記の分類を行うと、現在実現できている人工知能は一般的には「弱い特化型人工知能」ということになりますが、深層学習を使った人工知能は、強い人工知能や汎用人工知能を実現できるのではないかと期待されています。
ruby.wasmについて

## この記事は何
Rubyはバージョン3.2からWebAssembly(WASM)に対応をしています。
この記事では、RubyのWASMパッケージであるruby.wasmについて調べたことを残しておきます。

## WebAssemblyとは
WebAssemblyについては、[MDN Web docs](https://developer.mozilla.org/ja/docs/WebAssembly/Concepts)で以下のように説明されています。
>WebAssembly は最近のウェブブラウザーで動作し、新たな機能と大幅なパフォーマンス向上を提供する新しい種類のコードです。基本的に直接記述ではなく、C、C++、Rust 等の低水準の言語にとって効果的なコンパイル対象となるように設計されています。

WebAssemblyはWebブラウザ上で実行可能なコードで、W3Cにより標準化されているため、Chromeをはじめとしたブラウザで同一の仕様で動作します。
また、ブラウザ以外でのWebAssemblyの環境の実行に関しての仕様をまとめたWebAssembly System Interface (WASI)というものも存在します。

MDNの説明の通り、WebAssemlyは直接書くことは少なく、 C、C++,Rustをはじめとした低水準のコードをWebAssemblyコードへコンパイルすることで、
それぞれの言語で実装した処理をWeb上で動作させることを可能にしています。
また、C、C++、Rustなどで実装されたプログラミング言語のランタイムもWebAssemblyコードで変換することができるため、
この技術を応用することで他言語もブラウザ上で実行させることが可能となります。

詳しくは↓の記事をご覧ください。

https://developer.mozilla.org/ja/docs/WebAssembly

https://qiita.com/umamichi/items/c62d18b7ed81fdba63c2

https://qiita.com/massie_g/items/40726e237594817bfee7

## ruby.wasmとは
[ruby.wasm](https://github.com/ruby/ruby.wasm)はブラウザ上（WebAssembly上）でRubyの実行を可能にしたものです。
RubyのインタープリターはCで実装されているため、Cで実装されたインタープリターをWebAssemblyでコンパイルし、Rubyのコードをこのインタープリターに読み込ませることでブラウザ上でのRubyの実行を実現しています。

ruby.wasmを利用することで、↓のようにHTML上に書いたRubyのコードも実行できてしまいます。（https://github.com/ruby/ruby.wasm より引用）

```html
<html>
  <script src="https://cdn.jsdelivr.net/npm/ruby-3_2-wasm-wasi@1.0.1/dist/browser.script.iife.js"></script>
  <script type="text/ruby">
    puts "Hello, world!"
  </script>
</html>
```

'js'というライブラリを用いることで、RubyからJSのAPIへのアクセスも可能です。（'js'ライブラリはruby.wasmに標準で入っています）

```rb
require 'js'

div = JS.global[:document].createElement("div")

div.addEventListener('click') do |e|
  puts 'Hello, World!'
end
```

より詳しい仕組みについては↓の記事にまとまっています。

https://logmi.jp/tech/articles/327678

https://logmi.jp/tech/articles/327679

## ruby.wasmによって実現したこと
ruby.wasmによって実現したことは大きく二つです。

### Rubyの実行環境を簡単に配布できるようになった
今までRubyの実行環境を用意するためにはそれぞれの環境によって色々試行錯誤して導入する必要がありました。
現在はdockerなどでだいぶ環境を用意するのは簡単になりましたが、簡単なスクリプトを実行したいだけのためにはまだまだ環境のセットアップは重たいものですし、スマホなどで環境を用意するのはまだまだ難しいです。
ruby.wasmはブラウザ上でインタープリターのJSファイルをロードするだけで、
どんな環境でも簡単にRubyのスクリプトを実行することができます。
また、WASIに対応しているため、WASIのランタイムであるWasmerやWasmtimeなどの環境さえ用意できてしまえばすぐにRubyのコードを実行、WebAssebly化したファイルの配布をすることができます。

### Rubyでフロントエンドの実装が可能になったこと
どう使っていくかはまだ模索中の段階だと思いますが、Rubyをフロントエンドで使えるようになったのはRubyの可能性を広げる、大きな変化だと思います。

ruby.wasmを利用することでRubyだけで簡単なJSXの処理も書くことが可能です。

https://qiita.com/getty104/items/410448f7e7a20737c811

https://qiita.com/getty104/items/929af3742eb1dddacbaf

## 課題
ruby.wasmはとても魅力的ですが、まだgemなどの外部ライブラリの使用が難しかったり、Threadなどの一部のライブラリの未対応など、実際のRubyの実装体験とは異なるところは存在します。
しかし今度そのような課題も解決されていくと思いますし、いろいろな人が使い、試行錯誤することでどんどん便利になっていくと思うので、私もruby.wasmを使って色々試していきたいです。

## 参考文献
https://developer.mozilla.org/ja/docs/WebAssembly

https://qiita.com/umamichi/items/c62d18b7ed81fdba63c2

https://qiita.com/massie_g/items/40726e237594817bfee7

https://logmi.jp/tech/articles/327678

https://logmi.jp/tech/articles/327679
「あのー」「えっと」「えー」を文章から除去するアプリを作ってみた

# フィラー除去アプリケーション
Streamlitでフィラー除去をするアプリを作りました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218139/9825162e-6c4c-1c00-70a3-6ae0904bbb19.png)

### 関連記事
https://qiita.com/speaktech/items/85dd2b271e580461d6f2

# 作り方

1. ライブラリをインストールする
    ```bash:コマンドプロンプトで実行
    $ pip install ginza ja-ginza streamlit
    ```

2. コードを作成する
    ```python:app.py
    import spacy
    import streamlit as st
    
    
    def main():
        markdown = """
        # フィラー除去アプリケーション
        以下のテキストボックスにフィラーを除去したい文章を貼り、 [フィラー除去]ボタンをクリックしてください.
        """
        st.markdown(markdown)
        user_text = st.text_area("原文", value="えっとーここにフィラーを除去したい文章を貼ってください",)
        is_clicked = st.button("フィラー除去")
        if is_clicked:
            nlp = spacy.load('ja_ginza')
            doc = nlp(user_text)
            # フィラーの削除
            result = ''
            for sent in doc.sents:
                for token in sent:
                    if token.tag_ != "感動詞-フィラー":
                        result += str(token.text)
            answer = st.empty()
            answer.write(result)
    
    
    if __name__ == "__main__":
        main()
    ```

3. Streamlitを起動する
    ```bash:コマンドプロンプトで実行
    $ streamlit run app.py
    ```

4. アプリケーションにアクセスする
    コマンドプロンプトに以下の結果が表示されるので、[Network URL]へブラウザでアクセスします。
    ```
    Collecting usage statistics. To deactivate, set browser.gatherUsageStats to False.
    
    
      You can now view your Streamlit app in your browser.
    
      Network URL: http://xxx.xxx.xxx.xxx:pppp
      External URL: http://xxx.xxx.xxx.xxx:pppp
    ```
    以上で、完成です！
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218139/0f7c9f61-2d6a-94a2-f5ec-655571de2451.png)
Apple Silicon (M1/M2) Mac に Phoenix Framework 向けに Homebrew で PostgreSQL をインストールする際のエラーを解消する方法

Apple Silicon (M1/M2) Mac に Phoenix Framework 向けに Homebrew で PostgreSQL をインストールする際のエラーを解消する方法を説明します．

# 再現手順

1. `brew install postgresql` あるいは `brew install postgresql@14` を実行する
1. `psql -U postgres` を実行する
1. エラーが出る

# エラーその1

こんな感じのエラーが出る場合

```zsh
psql: error: connection to server on socket "/tmp/.s.PGSQL.5432" failed: No such file or directory
	Is the server running locally and accepting connections on that socket?
```

このエラーは，PostgreSQLを起動し忘れている時に発生します．

まず手順を次のようにしないといけないのでした．

1. `brew install postgresql` あるいは `brew install postgresql@14` を実行する
1. `brew services start postgresql` あるいは `brew services start postgresql@14`を実行する(どちらを実行するかについては，その前のコマンドに合わせる)
1. `psql -U postgres` を実行する

# エラー対応の一般論

この状況で何かエラーが出る場合

まず，PostgreSQLのログを確認します．PostgreSQLのログの場所は次のとおりです．

```zsh
`brew --prefix`/var/log/postgresql@14.log
```

(`@14`が付かない場合もあります)

次のようなコマンドで，ログの末尾を確認します．

```zsh
tail -100 `brew --prefix`/var/log/postgresql@14.log
```

エラーとなる場合には，`exited with exit code 1` とか `ERROR` とか `FATAL` とか出ます．

このエラーメッセージをコピーして，postgresqlというキーワードとともにGoogle検索します．英語のページも出てくると思いますが，機械翻訳すれば怖くない！1つずつ問題を解消していけば，最終的に`psql -U postgres`で正常に起動できるようになると思います．

このような対処方法をするときに，使用するコマンドがどのような作用を持つのかについて，調べるというのが良いです．そうすると深い理解につながりますし，書かれた通りに実行してもうまくいかなかったときにも対応できるようになります．

# エラーの例その2

次のようなエラーが出ていた場合

```zsh
FATAL: role postgres does not exist 
```

このエラーは，`postgres`というロール(ユーザー)が存在しないという意味です．

世の中に，このエラーに対処する様々な環境での試行錯誤の結果が溢れかえっているので，Apple Silicon Macの場合にぴたりと当てはまる事例を探すのにとても苦労しました．

その中で，下記の手順を見つけました．

https://gist.github.com/dnovais/c6c6894b95d764be2aca9736436edd0e

これはIntel Macの場合の手順なので，Apple Silicon Macの場合には次のようになります．

```zsh
/opt/homebrew/Cellar/postgresql/<version>/bin/createuser -s postgres
```

`postgresql`の部分が`postgresql@14`になることはあります．また，`<version>`には，`14.6`などが実際には入ります．

Intel/Apple Silicon両方の場合に対応した手順にして，初心者にもわかるように次のように手順を書いてみました．

まず，ターミナルに次のように打ち込んでください．

```zsh
`brew --prefix`
```

続けて次のように打ち込み続けます．

```zsh
`brew --prefix`/Cel
```

ここでタブキーを2回打ちます．すると次のように表示されるでしょう(Apple Silicon Macの場合)．

```zsh
/opt/homebrew/Cellar/
```

これはオートコンプリージョン(自動補完)という機能です．この機能を使うと最小限のキータイプでコマンドを打つことができます．

次のように続けます．

```zsh
/opt/homebrew/Cellar/postgres
```

ここでもタブキーを打ちます．すると実際にインストールしたpostgreSQLのバージョンに合わせて次のようになります．(あるいは候補が出ます)

```zsh
/opt/homebrew/Cellar/postgresql@14/
```

もう一度タブキーを押すとおそらく `<version>` の部分が補完されます．私の環境では次のようになりました．

```zsh
/opt/homebrew/Cellar/postgresql@14/14.6_1/
```

続けて次のようにコマンドを打ち込みます．

```zsh
/opt/homebrew/Cellar/postgresql@14/14.6_1/bin/createuser -s postgres
```

このコマンドはユーザーを作るというコマンドです．これを実行すれば，問題が解決できると思います．
error while loading shared libraries: libatk-1.0.so.0: cannot open shared object file: No such file or directory

```bash
file:///home/ec2-user/pup/node_modules/puppeteer-core/lib/esm/puppeteer/node/BrowserRunner.js:272
            reject(new Error([
                   ^

Error: Failed to launch the browser process!
/home/ec2-user/.cache/puppeteer/chrome/linux-1095492/chrome-linux/chrome: error while loading shared libraries: libatk-1.0.so.0: cannot open shared object file: No such file or directory


TROUBLESHOOTING: https://pptr.dev/troubleshooting

    at onClose (file:///home/ec2-user/pup/node_modules/puppeteer-core/lib/esm/puppeteer/node/BrowserRunner.js:272:20)
    at Interface.<anonymous> (file:///home/ec2-user/pup/node_modules/puppeteer-core/lib/esm/puppeteer/node/BrowserRunner.js:260:24)
    at Interface.emit (node:events:524:35)
    at Interface.close (node:internal/readline/interface:534:10)
    at Socket.onend (node:internal/readline/interface:260:10)
    at Socket.emit (node:events:524:35)
    at endReadableNT (node:internal/streams/readable:1359:12)
    at process.processTicksAndRejections (node:internal/process/task_queues:82:21)

Node.js v19.7.0
```

# libatkをインストール

```bash
sudo apt install -y libatk1.0-0
```