OmniAICreator/Qiita-1.07M huggingface dataset:
CentOS9 PHPからMariaDBへのPDO接続メモ

# 状況
・CentOSはローカルマシン内のVMとして。ホストともども192.168.1.0/24のネットワーク。
・SElinux、Firewalldは有効。適切に設定する前提。
・Apache入れ、Webサーバへのアクセス確認済み。
・そっからPHP入れ、動作確認済み。
・さらにMariaDB入れ、初期設定やDBやらテーブルやらPHP用ユーザやら作成。
・で、下記PHPでMariaDBに接続できず。「could not find driver」とかって怒られる。
```php
$dsn = 'mysql:host=localhost;dbname=testdb;charset=utf8';
$user = 'phpnoyuuzaa';
$pass = 'hogehoge';

try{
    $db = new PDO($dsn, $user, $pass);
} catch(PDOException $e) {
    die('エラー：' . $e->getMessage());
}

echo('ここまできたらDB接続に成功');
```


# 考察して試行

・DBへの到達以前に、PHP側でDB利用のためのドライバ周辺が何か欠落か？　phpadmin()して、そん中を「PDO」で検索してもノーヒットで、DBっぽい文言といえばsqliteしか見当たらず。ここにmysqlなりmariadbなり的な文言があるべきなのかと。
・何やら php-mysqlnd なるものを入れろとの情報。やってみる。
　
````
> sudo yum install php-mysqlnd.x86_64

パッケージのダウンロード:
php-mysqlnd-8.0.27-1.el9.x86_64.rpm             351 kB/s | 152 kB     00:00
--------------------------------------------------------------------------------
合計                                             98 kB/s | 152 kB     00:01
トランザクションの確認を実行中
トランザクションの確認に成功しました。
トランザクションのテストを実行中
トランザクションのテストに成功しました。
トランザクションを実行中
  準備             :                                                        1/1
  インストール中   : php-mysqlnd-8.0.27-1.el9.x86_64                        1/1
  scriptletの実行中: php-mysqlnd-8.0.27-1.el9.x86_64                        1/1
  検証             : php-mysqlnd-8.0.27-1.el9.x86_64                        1/1

インストール済み:
  php-mysqlnd-8.0.27-1.el9.x86_64

完了しました!
````
　
・いちおうPHP再起動しておく。
````
> sudo systemctl restart php-fpm.service
````
　


・行けた。
＞　　＿人人人人人人人人人人人人人人人＿
＞　　＞　ここまできたらDB接続に成功　＜
＞　　￣Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^￣
　
　
　
ありがとうございました。
Python演習問題＿0【　制御文練習問題①　】

# Python #
```
【問題1：サイコロの出目当てゲーム】

あなたは友人とサイコロを使ったゲームをしています。サイコロを10回振り、そのうちの1回について、出た目が特定の数字であればあなたの勝ち、それ以外であれば友人の勝ちとなります。以下の要件を満たすプログラムを作成してください。

・サイコロを10回振り、出た目をランダムに表示する
・特定の数字を指定し、その数字が出た場合は「あなたの勝ちです！」と表示する
・上記以外の数字が出た場合は「友人の勝ちです！」と表示する
・特定の数字が複数回出た場合は、最初に出たときのみ勝ちとする
・10回の振りを終えた後、特定の数字が出なかった場合は「残念でした」と表示する
```
##  ##
```
【問題2：リスト内の要素の合計値を計算する】

以下の要件を満たすプログラムを作成してください。

　・与えられたリストの要素の合計値を計算する
　・リストの各要素は、0以上の整数である
　・リストの要素数は10以下である
　・要素の合計値が100以上であれば、「目標達成です！」と表示する
　・要素の合計値が100未満であれば、「目標未達成です…」と表示する
```
##  ##
```
【問題3：温度変換プログラム】

摂氏と華氏の温度を相互に変換するプログラムを作成してください。以下の要件を満たすプログラムを作成してください。

　・ユーザーには、変換前の温度とその単位（摂氏または華氏）を入力してもらう
　・プログラム内で、入力された温度を摂氏または華氏に変換する
　・変換後の温度を小数点第2位まで表示する
　・入力された単位が摂氏の場合は華氏に、華氏の場合は摂氏に変換する
```
##  ##
```
【問題4：簡易電卓プログラム】

簡単な四則演算を行う電卓プログラムを作成してください。以下の要件を満たすプログラムを作成してください。

　・ユーザーには、演算したい2つの数値と、演算子を入力してもらう
　・演算子は、+、-、*、/ のいずれかである
　・入力された数値と演算子を用いて、演算を行う
　・演算結果を小数点第2位まで表示する
　・入力された演算子が誤っている場合は、「正しい演算子を入力してください」と表示する
```
Python演習問題＿0【　制御文練習問題①　】_解答


```
【問題1：サイコロの出目当てゲーム】

あなたは友人とサイコロを使ったゲームをしています。サイコロを10回振り、そのうちの1回について、出た目が特定の数字であればあなたの勝ち、それ以外であれば友人の勝ちとなります。以下の要件を満たすプログラムを作成してください。

・サイコロを10回振り、出た目をランダムに表示する
・特定の数字を指定し、その数字が出た場合は「あなたの勝ちです！」と表示する
・上記以外の数字が出た場合は「友人の勝ちです！」と表示する
・特定の数字が複数回出た場合は、最初に出たときのみ勝ちとする
・10回の振りを終えた後、特定の数字が出なかった場合は「残念でした」と表示する
```
```
【解答例】
import random
target_num = 3  # 特定の数字を指定する
win_flag = False  # 勝ちフラグを初期化する
for i in range(10):
    dice_num = random.randint(1, 6)
    print("サイコロを振りました！出た目は{}です。".format(dice_num))
    if dice_num == target_num and not win_flag:
        print("あなたの勝ちです！")
        win_flag = True  # 勝ちフラグを立てる
    else:
        print("友人の勝ちです！")
if not win_flag:
    print("残念でした。")
```
##  ##
```
【問題2：リスト内の要素の合計値を計算する】

以下の要件を満たすプログラムを作成してください。

　・与えられたリストの要素の合計値を計算する
　・リストの各要素は、0以上の整数である
　・リストの要素数は10以下である
　・要素の合計値が100以上であれば、「目標達成です！」と表示する
　・要素の合計値が100未満であれば、「目標未達成です…」と表示する
```
```
【解答例】
num_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]  # 例として、1から10の数値のリストを用意
total = 0
for num in num_list:
    total += num
if total >= 100:
    print("目標達成です！")
else:
    print("目標未達成です…")
```

##  ##
```
【問題3：温度変換プログラム】
摂氏と華氏の温度を相互に変換するプログラムを作成してください。以下の要件を満たすプログラムを作成してください。

　・ユーザーには、変換前の温度とその単位（摂氏または華氏）を入力してもらう
　・プログラム内で、入力された温度を摂氏または華氏に変換する
　・変換後の温度を小数点第2位まで表示する
　・入力された単位が摂氏の場合は華氏に、華氏の場合は摂氏に変換する
```
```
【解答例】
temp_str = input("温度を入力してください: ")
unit_str = input("単位を入力してください (C or F): ")

temp = float(temp_str)

if unit_str.upper() == "C":
    converted_temp = (temp * 9 / 5) + 32
    print(f"摂氏{temp:.2f}度は華氏{converted_temp:.2f}度です。")
elif unit_str.upper() == "F":
    converted_temp = (temp - 32) * 5 / 9
    print(f"華氏{temp:.2f}度は摂氏{converted_temp:.2f}度です。")
else:
    print("正しい単位を入力してください。")
```
##  ##
```
【問題4：簡易電卓プログラム】

簡単な四則演算を行う電卓プログラムを作成してください。以下の要件を満たすプログラムを作成してください。

　・ユーザーには、演算したい2つの数値と、演算子を入力してもらう
　・演算子は、+、-、*、/ のいずれかである
　・入力された数値と演算子を用いて、演算を行う
　・演算結果を小数点第2位まで表示する
　・入力された演算子が誤っている場合は、「正しい演算子を入力してください」と表示する
```
```
【解答例】
num1 = float(input("1つ目の数値を入力してください: "))
num2 = float(input("2つ目の数値を入力してください: "))
operator = input("演算子を入力してください (+, -, *, /): ")

if operator == "+":
    result = num1 + num2
elif operator == "-":
    result = num1 - num2
elif operator == "*":
    result = num1 * num2
elif operator == "/":
    if num2 == 0:
        print("0で割ることはできません")
        result = None
    else:
        result = num1 / num2
else:
    print("正しい演算子を入力してください")
    result = None

if result is not None:
    print("演算結果は {:.2f} です".format(result))
```
RaspberryPiでspidevをつかったプログラムをrc.localで自動起動できない

# RaspberryPiで、spidevを使ったpython3のプログラムをrc.localで自動起動できない

## 状況
spidevを用いたpythonプログラムが、rc.localに書いても自動起動してくれない。
起動ログを確認すると以下のようになっていた。（一部抜粋）
```
self.spi.open(0, 0)
FileNotFoundError: [Errno 2] No such file or directory
```

おそらく、spiに関するサービスが起動する以前にプログラムがロードされエラーになっているのだろう。

## 解決策
rc.localではなくてsystemdを使おう。
以下の記事がとても参考になった。ありがとうございます。

https://monomonotech.jp/kurage/raspberrypi/systemd_autostart.html

```
[Install]
WantedBy=multi-user.target
```
とすることで、GUI環境が起動した後にプログラムをロードできるそう。
あとはsystemctlでサービスを有効にすれば正常起動できた。
Python演習問題＿0【　ループ処理練習問題①　】_解答

```
【問題1：パン屋さんの在庫管理】
あるパン屋さんでは、毎日焼きたてのパンを販売しています。パンの種類は、以下の4つです。

フランスパン
ロールパン
クロワッサン
パン・オ・ショコラ

パン屋さんでは、各種類のパンを10個ずつ焼いています。以下のようなループ処理を使って、パンの在庫を管理するPythonコードを作成してください。

```
```
【解答例】
pan_list = ["フランスパン", "ロールパン", "クロワッサン", "パン・オ・ショコラ"]
pan_stock = [10, 10, 10, 10]
for i in range(len(pan_list)):
    print(pan_list[i] + ": " + str(pan_stock[i]) + "個")
```
##  ##
```
【問題2：数の足し算】
以下の数のリストがあります。
number_list = [1, 3, 5, 7, 9]
このリストの中の数を一つずつ、すべて足し合わせるPythonコードを作成してください。
```
```
【解答例】
number_list = [1, 3, 5, 7, 9]
sum = 0
for number in number_list:
    sum += number
print("数の合計は" + str(sum) + "です。")
```
##  ##
```
【問題3：カフェのメニュー表示】
あるカフェで働いているあなたは、メニューを表示するプログラムを作成しています。以下のように、カフェのメニュー（ドリンクと料理）をリストで用意し、whileループを使ってメニューを表示するプログラムを作成してください。

カフェのメニュー
　・コーヒー
　・紅茶
　・ハンバーガー
　・スープ
　・サンドイッチ
```
```
【解答例】
menu = ["コーヒー", "紅茶", "ハンバーガー", "スープ", "サンドイッチ"]
print("カフェのメニュー")
index = 0
while index < len(menu):
    print(str(index + 1) + ". " + menu[index])
    index += 1
```
##  ##
```
【問題4：九九の】
九九の表を表示するPythonコードを作成してください。
```
```
【解答例】
for i in range(1, 10):
    for j in range(1, 10):
        print("{:2d}".format(i * j), end=" ")
    print()
```
Python演習問題＿0【　ループ処理_練習問題①　】

# Python #
## 繰り返す ##
### 問題 ### 
```
【問題1：パン屋さんの在庫管理】
あるパン屋さんでは、毎日焼きたてのパンを販売しています。パンの種類は、以下の4つです。

フランスパン
ロールパン
クロワッサン
パン・オ・ショコラ
パン屋さんでは、各種類のパンを10個ずつ焼いています。以下のようなループ処理を使って、パンの在庫を管理するPythonコードを作成してください。
```
##  ##
```
【問題2：数の足し算】
以下の数のリストがあります。
number_list = [1, 3, 5, 7, 9]
このリストの中の数を一つずつ、すべて足し合わせるPythonコードを作成してください。
```
##  ##
```
【問題3：カフェのメニュー表示】
あるカフェで働いているあなたは、メニューを表示するプログラムを作成しています。以下のように、カフェのメニュー（ドリンクと料理）をリストで用意し、whileループを使ってメニューを表示するプログラムを作成してください。

カフェのメニュー
　・コーヒー
　・紅茶
　・ハンバーガー
　・スープ
　・サンドイッチ
```
##  ##
```
【問題4：九九の】
九九の表を表示するPythonコードを作成してください。
```
Django環境構築〜トップページをブラウザで表示するまで

# 環境
- MacOS（M1）：Ventura バージョン13.0.1
    ```terminal
    $ uname -m # arm64
    ```
- Python：バージョン3.10.7
- VSCord：バージョン1.76.0 (Universal)

# 手順
## 1. プロジェクトの作業用ディレクトリを作成し、VSCordを開く
```terminal
$ mkdir ~/Desktop/demo_project # 好きなプロジェクト名
$ cd ~/Desktop/demo_project
$ code .
```

## 2. 仮想環境作成
```terminal
$ python3 -m venv myenv # python3 -m venv 環境名
$ source myenv/bin/activate # 作成した仮想環境へ切り替え
$ which python # /Users/名前/Desktop/demo_project/myenv/bin/python
```

## 3. Djangoインストール ・ バージョン確認
```terminal
$ pip install --upgrade pip # Successfully installed pip-23.0.1
$ pip install django
$ python -m django version # 4.1.7
```

## 4. Djangoプロジェクト作成
```terminal
$ django-admin startproject config . # 「configディレクトリ」と「manage.pyファイル」が作成される
```


## 5. Djangoプロジェクト起動
```terminal
$ python3 manage.py runserver
```

![スクリーンショット 2023-03-05 23.18.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2689074/b833789f-08f2-c88f-740d-6961d9325cca.png)

:::note
上記画面が表示されれば成功
:::
サーバ停止は`Ctrl + c`

:::note warn
### `Error: That port is already in use.`となる場合
```terminal
$ ps aux | grep -i manage
$ kill -9 プロセスID
:::


## 6. アプリケーション追加
```terminal
$ python manage.py startapp demo # 好きなアプリケーション名
```

## 7. 初期設定
- 現状、まだプロジェクトとアプリケーションは紐づいていない為、初期設定を行う
- また、Djangoで扱う言語のデフォルトを日本語にする

### 日本語化
106行目辺りにあるデフォルトの記述を以下に書き換える
```config/settings.py
LANGUAGE_CODE = 'ja'
TIME_ZONE = 'Asia/Tokyo'
```

### `INSTALLED_APPS`に追加

```config/settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'demo', # 追記
]
```

## 8. テンプレートファイル
```terminal
(myenv) (base) ryo@RyonoMBP demo_project % mkdir templates/demo
(myenv) (base) ryo@RyonoMBP demo_project % touch templates/demo/top.html
```

```demo_project/templates/top.html
<!DOCTYPE html>
<html lang="ja">
  <head>
      <meta charset="UTF-8">
      <title>DemoApp</title>
  </head>
  <body>
    <h1>TopPage</h1>
  </body>
</html>
```

## 9. views.py
```demo/views.py
from django.views.generic.base import TemplateView

class TopView(TemplateView):
    template_name = 'demo/top.html'
```

## 10. urls.py
```
(myenv) (base) ryo@RyonoMBP demo_project % touch demo/urls.py
```


```demo_project/demo/urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('', views.TopView.as_view(), name='top'),
]
```


```demo_project/config/urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('demo.urls')),
]
```



## 11. settings.py
- `DIRS`を修正
```demo_project/config/settings.py
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR, 'templates'],
```


# 起動
```terminal
$ python3 manage.py runserver
```

![スクリーンショット 2023-03-11 23.52.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2689074/cf7aac06-2095-1fad-df62-09ad889e1747.png)

:::note
完了
:::

# 参考
- https://rightcode.co.jp/blog/become-engineer/django-diary-app-make-built-environment
SSHポートフォワーディングについて知識整理してみた

## はじめに
知識にあやふやなところがあったので、SSHポートフォワーディングについて整理してみました。  


## ローカルフォワードについて
まずはローカルフォワードについてです。
![fig1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/574633/31563e76-e26b-5cab-b981-b6fbd1559cc5.png)

```
# クライアントPCで実行します
# ssh -L <クライアントPCのポート番号>:<ターゲットサーバのIP>:<ターゲットサーバのポート番号> <サーバAのユーザ名>@<サーバAのIP>
ssh -L 5000:<ターゲットサーバのIP>:80 <サーバAのユーザ名>@<サーバAのIP>
```
ローカルフォワードを使用すると、クライアントPCからサーバAにSSHトンネルが作成され、SSHトンネルを通過してきた通信はサーバAを経由してターゲットサーバの80番ポートに飛ばされます。

そのため、コマンドを実行し、クライアントPCのブラウザからクライアントPC自身(localhost)の5000番ポートにアクセスすると、ターゲットサーバの80番ポートにアクセスすることができます。
※上記のコマンドを実行したターミナルはsshが動作しているので、閉じないようにしてください。

### 使用するケース
ローカルフォワードを使用するケースは、外部から直接アクセスできないサーバにアクセスするときなどです。

上記の図の場合、ターゲットサーバはネットワークAの中にあり、直接アクセスすることができません。ですが、サーバAはクライアントPCからアクセスできるため、クライアントPCからサーバAまでをSSHトンネルでつなぎ、サーバAにターゲットサーバへの通信を中継してもらいます。

このようにすることで、クライアントPCからターゲットサーバの80番ポートで動作しているWebアプリケーション等にアクセスすることができます。  

## リモートフォワードについて
次はリモートフォワードについてです。
![fig2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/574633/063e40d4-2898-4049-8a2c-06de842ccfd4.png)

```
# サーバAで実行します
# ssh -R <クライアントPCのポート番号>:<ターゲットサーバのIP>:<ターゲットサーバのポート番号> <クライアントPCのユーザ名>@<クライアントPCのIP>
ssh -R 5000:<ターゲットサーバのIP>:80 <クライアントPCのユーザ名>@<クライアントPCのIP>
```
リモートフォワードは簡単に言うと、SSHトンネルを作成する主体をローカルフォワードとは逆にしたものになります。

リモートフォワードのコマンドはサーバAで実行するので、サーバAからクライアントPCに向けてSSHトンネルが作成されます。そして、SSHトンネルが作成されると、クライアントPCはSSHトンネルとサーバAを経由してターゲットサーバの80番ポートにアクセスできるようになります。
※上記のコマンドを実行したターミナルはsshが動作しているので、閉じないようにしてください。

ローカルフォワードとリモートフォワードの違いを整理すると以下のようになります。
|  種別  | SSHコマンドを実行する端末 | SSHトンネルを作成する方向 |
| :----: | :----:                  | :----:                                |  
|  ローカルフォワード  |  クライアントPC  |  　クライアントPC　＝＞　サーバA　  |  
|  リモートフォワード  |  サーバA         |  　サーバA　＝＞　クライアントPC　  |


ローカルフォワードでは、クライアントPCからリモートのサーバAに向けてSSHトンネルを作成していましたが、
リモートフォワードではリモートのサーバAからクライアントPCへSSHトンネルを作成しています。

### 使用するケース
リモートフォワードを使用するケースは、ファイアウォール(FW)等で外部から通信ができないネットワーク内のサーバへアクセスをするときなどです。

上図の場合ですと、ターゲットサーバとサーバAはネットワークAの中にあり、直接アクセスできません。そして、FWによりネットワークAの外からネットワーク内への通信も遮断される状況です。このような場合、クライアントPCからサーバAに向けてSSHトンネルを作成できないため、逆にネットワークA内のサーバAから外部のクライアントPCへSSHトンネルを作成します。

このように、**外部からアクセスできないネットワーク内と通信するため、内部から外部に向けて暗号化されたトンネルを作ってもらう**ことで、クライアントPCからターゲットサーバへの通信を可能にしています。

## おわりに
以上、SSHポートフォワーディングについてまとめてみました。
私自身、ローカルフォワードはよく使っていたのですが、リモートフォワードについては使用する機会が少なかったので、いい勉強になりました。SSHポートフォワーディングはとても便利だと思います。ですが、FW等を超えて通信できてしまうので、その点はセキュリティ的に非常に怖いなと感じています。ポートフォワーディングを使用するときは十分注意して使う必要があると感じました。

当たり前ですけど、**悪用は厳禁**でお願いします....


## 参考サイト
以下のサイトを参考にさせていただきました。
- [sshポートフォワーディング とは](https://qiita.com/miyuki_samitani/items/07c8b05f74dca25b33d0)
- [sshポートフォワーディング](https://qiita.com/mechamogera/items/b1bb9130273deb9426f5)
Python演習問題＿0【　条件分岐練習問題②　】_解答

## 条件分岐 ##
```
【問題1：食事の選択】
あなたは夕食の時間になり、以下の3つの選択肢から1つを選ばなければなりません。

・ピザ
・ハンバーガー
・サラダ

それぞれの選択肢について、以下のルールがあります。

条件1：ピザは高カロリーで、500kcal以上の場合は「高カロリーなピザです。注意してください。」と表示し、500kcal未満の場合は「ピザを注文しました。」と表示します。
条件2：ハンバーガーは中カロリーで、300kcal以上500kcal未満の場合は「ハンバーガーを注文しました。」と表示し、300kcal未満の場合は「ハンバーガーは少し足りません。何かもう注文しましょう。」と表示します。
条件3：サラダは低カロリーで、200kcal以上300kcal未満の場合は「サラダを注文しました。健康的な選択です。」と表示し、200kcal未満の場合は「サラダは足りません。何かもう注文しましょう。」と表示します。
これらを出力するコードを書きましょう。
```
```
【解答例】
food = "pizza"

if food == "pizza":
    calories = 800
    if calories >= 500:
        print("高カロリーなピザです。注意してください。")
    else:
        print("ピザを注文しました。")
elif food == "hamburger":
    calories = 400
    if calories >= 500:
        print("ハンバーガーを注文しました。")
    else:
        print("ハンバーガーは少し足りません。何かもう注文しましょう。")
elif food == "salad":
    calories = 250
    if calories >= 200 and calories < 300:
        print("サラダを注文しました。健康的な選択です。")
    else:
        print("サラダは足りません。何かもう注文しましょう。")
else:
    print("選択肢にはピザ、ハンバーガー、サラダのいずれかを入力してください。")
```
##  ##
```
【問題2：天気の情報】
あなたは旅行を計画しており、出発前に天気を確認することにしました。天気予報には、以下の3つの情報が含まれています。

・晴れ
・曇り
・雨
それぞれの情報について、以下のルールがあります。

条件1：晴れの場合、日焼け止めを持っていきましょう。
条件2：曇りの場合、薄手のジャケットがあると便利です。
条件3：雨の場合、傘を持っていきましょう。
```
```
【解答例】
weather = "晴れ"

if weather == "晴れ":
    print("日焼け止めを持っていきましょう。")
elif weather == "曇り":
    print("薄手のジャケットがあると便利です。")
elif weather == "雨":
    print("傘を持っていきましょう。")
else:
    print("天気情報がありません。")
```
##  ##
```
【問題3：宿題のモンダイ】
あなたは宿題を提出する期限が迫っているため、提出期限を確認することにしました。提出期限には、以下の3つの締切があります。

・今日中
・明日まで
・2日後まで
それぞれの締切について、以下のルールがあります。

条件1：今日中の場合、急いで提出しましょう。
条件2：明日までの場合、明日の朝までに提出しましょう。
条件3：2日後までの場合、余裕をもって提出しましょう。
```

```
【解答例】
deadline = "明日まで"

if deadline == "今日中":
    print("急いで提出しましょう。")
elif deadline == "明日まで":
    print("明日の朝までに提出しましょう。")
elif deadline == "2日後まで":
    print("余裕をもって提出しましょう。")
else:
    print("提出期限がありません。")

```
WEBサイト制作_小技『Bootstrap』

# 使い方
1. Googleで『Bootstrap』と検索
1. 『Read the docs』を選択
1. 使いたい機能や要素を選択
1. コピーしてVScodeに貼り付け
### 実際の動き
![スクリーンショット 2023-03-11 23.36.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193952/08e0163c-287d-57cc-03b4-d36dcb512468.png)
![スクリーンショット 2023-03-11 23.36.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193952/6db4fa41-a821-79d1-496f-0791cceb4e3d.png)
![スクリーンショット 2023-03-11 23.36.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193952/bb729bb2-17c9-b473-79d8-402969f7a70b.png)
![スクリーンショット 2023-03-11 23.36.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193952/65c6ff8d-7a0a-e11a-9c7b-06351ce9bad1.png)

# 覚えておきたいよく使う要素
- button
- navber
- carousel
- accordion
- Breadcrumb
- Modal
- Pagination

# 活用例 『navber』 『carousel』 『button』
## Live_全体
![スクリーンショット 2023-03-11 23.50.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193952/3616139b-464c-309d-bc81-65f189803a48.png)
## Live_navber
![スクリーンショット 2023-03-11 23.40.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193952/64fc9d8b-42ff-0e66-1362-0bc80bf78fc4.png)
## Live_carousel
![スクリーンショット 2023-03-11 23.51.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193952/7205d43d-35ac-5016-2fa4-9c7185a40993.png)
## button
![スクリーンショット 2023-03-11 23.40.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193952/786f7f57-3f70-69c4-ebee-2ed0dc9c5bd4.png)
##　VScode
![スクリーンショット 2023-03-11 23.41.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193952/a51e11b7-d4be-9e9d-cf78-edc68ce4a24e.png)
Python演習問題＿0【　条件分岐練習問題②　】

#python練習問題#
## 条件分岐 ##
```
【問題1：食事の選択】
あなたは夕食の時間になり、以下の3つの選択肢から1つを選ばなければなりません。

・ピザ
・ハンバーガー
・サラダ

それぞれの選択肢について、以下のルールがあります。

条件1：ピザは高カロリーで、500kcal以上の場合は「高カロリーなピザです。注意してください。」と表示し、500kcal未満の場合は「ピザを注文しました。」と表示します。
条件2：ハンバーガーは中カロリーで、300kcal以上500kcal未満の場合は「ハンバーガーを注文しました。」と表示し、300kcal未満の場合は「ハンバーガーは少し足りません。何かもう注文しましょう。」と表示します。
条件3：サラダは低カロリーで、200kcal以上300kcal未満の場合は「サラダを注文しました。健康的な選択です。」と表示し、200kcal未満の場合は「サラダは足りません。何かもう注文しましょう。」と表示します。
これらを出力するコードを書きましょう。
```
```
【問題2：天気の情報】
あなたは旅行を計画しており、出発前に天気を確認することにしました。天気予報には、以下の3つの情報が含まれています。

・晴れ
・曇り
・雨
それぞれの情報について、以下のルールがあります。

条件1：晴れの場合、日焼け止めを持っていきましょう。
条件2：曇りの場合、薄手のジャケットがあると便利です。
条件3：雨の場合、傘を持っていきましょう。
```
```
【問題3：宿題のモンダイ】
あなたは宿題を提出する期限が迫っているため、提出期限を確認することにしました。提出期限には、以下の3つの締切があります。

・今日中
・明日まで
・2日後まで
それぞれの締切について、以下のルールがあります。

条件1：今日中の場合、急いで提出しましょう。
条件2：明日までの場合、明日の朝までに提出しましょう。
条件3：2日後までの場合、余裕をもって提出しましょう。
```
Azure AD B2C - Custom Policyを作成する



Azure Active Directory B2Cでは、Custom Policyを設定することで様々な処理をカスタマイズすることができる。しなしながらこのCustom Policyはカスタマイズ性が高い反面、独自の概念を理解する必要があり、取っつきにくい機能となっている。以前に自身の理解を深めるために簡単なカスタマイズを試したみたので、ポイントを整理しておく。

### 作成したもの

OpenID Connect (OAuth2) のAuthorization Endpointにてログイン画面を表示する際に、新規登録へのリンクの表示・非表示をクエリパラメータで制御する。

* 表示 `?p=B2C_1A_SIGNUP_SIGNIN_WITH_PARAMETER&hide_sign_up_link=false&...`
* 非表示 `?p=B2C_1A_SIGNUP_SIGNIN_WITH_PARAMETER&hide_sign_up_link=true&...`

完成版はこちら：[SignUpOrSignInWithParameter.xml](https://github.com/unhurried/azure-ad-b2c-example/blob/master/SignUpOrSignInWithParameter/SignUpOrSignInWithParameter.xml)

### Custom Policy作成のポイント

#### Custom Policyの概念を理解する

大まかなイメージを掴むには[公式ドキュメント](https://learn.microsoft.com/en-us/azure/active-directory-b2c/custom-policy-overview)よりもこちらの記事がわかりやすい。

> [Azure AD B2C カスタムポリシーのスターターパック (LocalAccounts) の解説 - Qiita](https://qiita.com/skmk/items/3efdb97833a1ca6e3008)

#### 参考事例を探す

Microsoftが管理しているCustom Policyの事例集があるため、作りたいものに近い事例を探してみると良い。

- [azure-ad-b2c/samples: Azure AD B2C custom policy solutions and samples.](https://github.com/azure-ad-b2c/samples)
- [azure-ad-b2c/unit-tests: Azure AD B2C custom policies unit tests](https://github.com/azure-ad-b2c/unit-tests)

今回の場合は[unit-test / Show sign-up link](https://github.com/azure-ad-b2c/unit-tests/tree/main/technical-profiles/self-asserted#show-sign-up-link)が参考になった。

#### Authorization Endpointのクエリパラメータを受け取る

[OAuth2 key-value parameters](https://learn.microsoft.com/en-us/azure/active-directory-b2c/claim-resolver-overview#oauth2-key-value-parameters) Claim Resolverを設定することでクエリパラメータの読み込みができる。今回のケースでは `{OAUTH-KV:show_signup_link}` というClaimを定義すればよい。

参考：[Prepopulate values on Azure b2C from the query parameters using Custom Policies - Stack Overflow](https://stackoverflow.com/questions/71593877/prepopulate-values-on-azure-b2c-from-the-query-parameters-using-custom-policies)

#### Sign Inボタンの表示・非表示を制御する

Self Asserted Attribute Providerの[Metadata](https://learn.microsoft.com/en-us/azure/active-directory-b2c/self-asserted-technical-profile#metadata)のうち、`setting.showSignupLink` を設定することで制御できる。

#### その他の注意点

* Custom Policyの変更は反映に数分かかることがある。
  * 変更が反映されているかがわからないため開発時のデバッグがしにくいが、現時点では制約とのことで、5分程度待ってから動作確認をするといった対策を取る他ない。（参考：[AAD B2C - "Lag" after custom policy upload - Microsoft Q&A](https://learn.microsoft.com/en-us/answers/questions/1056470/aad-b2c-lag-after-custom-policy-upload)）
* デバッグにログを利用できるが、設定方法と出力内容の理解のハードルが高い。
  * ログ出力にもCustom Policyの設定が必要となる。（参考：[Set up Application Insights](https://learn.microsoft.com/en-us/azure/active-directory-b2c/troubleshoot-with-application-insights?pivots=b2c-custom-policy#set-up-application-insights)）
  * ログ出力内容の詳細なドキュメントはなく、意味を推測しながら読み解く必要がある。
【シェルスクリプト】ファイルの有無を判定する

## ファイルの有無を判定する

以下のようにするとファイルが存在する場合に`true`となります。  

```zsh
if [ -e ファイル ]; then
  コマンド
fi
```

また以下のようにするとファイルが存在しない場合に`true`となります。  

```zsh
if [ ! -e ファイル ]; then
  コマンド
fi
```
Python演習問題_基礎【  はじめの一歩…。  】

<!-- title: Python演習問題_基礎【  はじめの一歩…。  】 -->

# Python を知ろう!

## 驚きの基礎

<ol>
<li>自分の名前を出力</li>
<li>自分の名前・カタカナ・年齢を段に分けて出力</li>
<li>自分の名前・体重・身長を一行で出力し、その下にBMI値を出力</li>
<li>「12＋15＝」と出力し、その計算結果を次の行に出力</li>
<li>体重と身長が入力されたら、それらを使ってBMI値を計算して出力する</li>
</ol>

<details ><summary>出力とは</summary><div>

出力とは[`print()`](https://www.sejuku.net/blog/61602)関数のことを指します
</div></details>

<details ><summary>5の解き方</summary><div>

**体重と身長が入力されたら**とは[`input()`](https://www.python.jp/train/string/input.html)を使い体重をkg、身長をcmで取得して
それらを使ってBMI値を計算して`print()`するということです
</div></details>
マークダウン自分用あんちょこ

# 見出しは#の個数で調整
本文あああああ
## #2個でこうなる
本文あああああ
### #3個でこう。これ以下のレベルでは区切り線なくなるようだ。
本文あああああ
#### #4個でこう
本文あああああ
##### #5個で終わりっぽい（6個も利くけど見た目変化ない？）
本文あああああ
　
　
　
　
↑Redmineとかでやってたみたいに全角スペースで見た目上の空行。
（半角スペースの振る舞いがちょっと謎なんだけど忘れておく）
 　
　
　
### 区切り線
***ってやったらこう↓
***
　
　
　
### リンクは`[表示文字列](URL)`みたいに。スペース入れんように。
````[google](https://google.com/)````
と書くと↓になる
[google](https://google.com/)
　
　
　
### セクション的なもの
````1. ほんたら```` と入れて改行すると、自動でできる。連番の自動採番はされない？ ようなので、手で2, 3. …と書き換える感じだろうか。
↓
1. あああ
2. aaa
3. [リンクは前述のとおりこう](http://google.com)

　
　
## 表とか
いろいろあるけどまずは「3x2」とか入力→決定、ていうやり方。
| 1 | 2 | 3 |
|:-:|:-:|:-:|
|ああ|いい|うう|
|hoge|fuga|piyo|
|abc|123|!"#|

　
　
　
## 補足の書き方。3つのレベル。

````:::note info````
と 
````:::````
で囲めばよい。アタマに空行が必要なので注意。

:::note info
インフォメーション
infoは省略可能です。
:::

で、上記がインフォメーションレベル。
警告レベルと、より強い警告レベルは、上記````info````の箇所を、````warn````、````alert````に、それぞれ変えればよい。

:::note warn
警告
○○に注意してください。
:::

:::note alert
より強い警告
○○しないでください。
:::
[個人記録] 2/27, 3/6 week やったことまとめ

## tl;dr
* AtCoderで2023年7月までに水色を目指し始めました
    * 水色 = Beginner’s Contestで4問目までをしっかり解けるレベル
* CSの知識インプットが不足しているため、CSの基礎を概念レベルで説明しているYoutubeや書籍を読み、*わからないこと/知らないこと* をつぶしていきます
* PythonではnumPyを理解し使えるようになるところを今年のGoalとしようと思います
* 上記を継続的に実施し、概念と実践をバランスよく身につけていこうと思います

## what is this?
* 最近アウトプットができていなかったため、2/27, 3/6週でやったことの個人的まとめ


### What I did?
* ２週間で`アルゴリズムx数学が基礎からしっかり身につく本`を読了。付属問題は難易度が高いもの(星4 - 5)以外は一通り完了。苦手だったグラフ周りの解説が易しく、理解度が深まりました。
* `マスタリングTCP/IP`を一周しました。書籍は時間をかけて読むよりも、嫌になる前に読み終わるくらいの感覚でサクッと読む。同じような内容を扱っているYoutubeなどもみて、(実質)同じようなコンテンツを周回します。
* `edX`, `Cousera`を活用し基礎概念を取り扱っているコースを一つづつ始めました。完了したら、また共有します。
* AtCoder Beginner's contestに2回目参加し、2完という悔しい結果でした。

### At coder rating
![Screenshot 2023-03-11 at 10.12.23 PM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386347/b56654b5-1b2b-64ad-ffea-98d92d437a46.png)
Git・GitHubのローカルリポジトリ作成〜リモートリポジトリへ反映＆マージ作業までの手順書

# はじめに
Git,GitHubを使用した流れについて、最低限の手順をこの記事にまとめておく
Git関連のワード(リポジトリやコミットなど)については解説していないので、詳しく知りたい方は参考文献を参考にしてみてください！

# 目次
<!-- タイトルとアンカー名を編集 -->
1. [リモートリポジトリ作成](#リモートリポジトリを作成する)
1. [ローカルリポジトリ作成](#ローカルリポジトリを作成する)
1. [GitHubにてプルリクやローカルリポジトリの更新](#githubにてプルリクやローカルリポジトリの更新)
1. [開発中のプロジェクトに参加する場合](#開発中のプロジェクトに参加する場合)
1. [参考文献](#参考文献)

<!-- 各チャプター -->
<!-- chapter1 -->
# リモートリポジトリを作成する
GitHubにアクセスして、自身のアカウントでログインする
※アカウントがない場合は、アカウントを作成する
GitHubのURL：https://github.com/

GiHub上で自身のアイコンを押下→自身の名前を押下→「Repositories」を選択
→「New」を選択→リポジトリ名など適当に入力→リモートリポジトリを新規作成する


<!-- chapter2 -->
# ローカルリポジトリを作成する
terminal(mac) or Git Bash(Windows)にて
適当なフォルダ配下に移動する

下記コマンドを実行していく

1：ローカルリポジトリのdefault barnchを「master」から「main」に変更する
2020年10月頃にデフォルトブランチ名が「master」から「main」に変更となった為、リモートとローカルで名称の差異が発生しないようにする
```
git config --global init.defaultBranch main 
```

2：ローカルリポジトリの作成
```
git init
```

3：mainブランチに格納する用のファイルやソースをローカルリポジトリに追加
※「git add .」で現在のフォルダ配下のファイルを全て追加することが可能
```
# viエディタでファイルの作成、文字の記入を実施
vi sample.txt
# ファイルの作成完了後、下記コマンドでファイルをローカルリポジトリへ追加する
git add sample.txt
```
4：mainブランチに格納する用のファイルやソースをローカルリポジトリへコミット
```
git commit -m "コミットメッセージを記入"
```
5：リモートリポジトリへのアクセス設定
```
# 「ユーザー名」と「メールアドレス」は自身のアカウント情報に変換して下さい
git config --global user.name “user name”
git config --global user.email github@sample.com

# 以後、originでリモートリポジトリに繋がるようにする為のコマンド
git remote add origin URL(対象のリモートリポジトリのhttpsを貼り付ける)
```
※リモートリポジトリへ接続しようとした際、
下記のようなトークン必要のメッセージが出た場合
```
remote: Support for password authentication was removed on August 13, 2021. Please use a personal access token instead.
```
GitHubの自身のアカウントのトークンを発行し、パスワード入力時にトークンの値を入力することで解決します
「自身のアイコン」→「settings」→「Developer settings」→「Personal access tokens」
→「Tokens(classic)」→「Generate new token」→「生成したトークン」をリモートリポジトリへの接続時に求められるPW入力内容に貼り付ける
※「参考文献」に詳しく記載されてます！！

6：リモートリポジトリのmainブランチへファイルをプッシュする
```
git push origin main
```

ここで一旦、「GitHub」のmainブランチにてプッシュしたファイルが存在することを確認

7：ローカルリポジトリに「developブランチ(名前は何でも良いです)」を作成
```
git branch develop

# 「developブランチ」に移動する
git checkout develop
# 現在どのブランチにいるか確認(ブランチ名の前に「*」がついているのが現在のブランチ)
git branch
```
8：sample.txtを修正して、再度リモートリポジトリへプッシュする
```
# viエディタでファイルを開き、好きな文字を追記する
vi sample.txt

# ローカルリポジトリ内で修正したファイルを追加、コミット、プッシュする
git add sample.txt
git commit -m "1行追記しました"
git push origin develop
```

GitHubにて「developブランチ」内に「修正されたファイル」が存在することを確認
存在していればOK！！


<!-- chapter3 -->
# GitHubにてプルリクやローカルリポジトリの更新
GitHub上で「mainブランチ」に対して、「developブランチ」の内容を「Create　pull request」で反映依頼をする
「プルリク内容」を確認して、問題なければ「Merge pull request」を実行して「mainブランチ」に反映させる

最後に、ローカルリポジトリのmainとリモートリポジトリの内容に差異があるので
ローカルリポジトリのmainを最新化しておく
```
# mainブランチに移動
git checkout main
# リモートリポジトリのmainブランチの最新状態をローカルリポジトリに取得
git pull origin main
```


<!-- chapter4 -->
# 開発中のプロジェクトに参加する場合
下記コマンドを実行して、プロジェクトのリポジトリをローカルに取得する
```
git clone https://github.com/ユーザ名/[作成したリポジトリ].git
```
あとは[ローカルリポジトリ作成](#ローカルリポジトリを作成する)の手順のようにローカルリポジトリでブランチを作成して、プロジェクトのルールに従い適切なブランチへのコミット、プッシュをして
開発作業を行っていきましょう！！


<!-- chapter5 -->
# 参考文献
- [【超入門】初心者のためのGitとGitHubの使い方](https://tech-blog.rakus.co.jp/entry/20200529/git)
- [GitHubのトークンの生成と使用方法](https://codelikes.com/github-https-connection/)
pythonのpow関数が引数３つとることを知らなかった話。

```python:
pow(x, y, z) = (x**y)%z
```

pythonのpow関数は３つ引数を持つことができます。pow(x,y,z)と書くことでxのy乗をzで割ったあまりとなるので競プロとか始めた人は覚えておくと良きかもです。
【Rails】投稿機能

# 【Rails】で投稿機能を作る
### 作り方流れ
- 投稿フォームを作る
- 投稿フォームにデータ入力し、データを送信
- 送信内容をDBに保存
- DBに保存した後、どこかの指定したviewページへ飛ばす(リダイレクト)

---
## ①投稿フォームを作る

このように作りたいと思います。

![2023-03-11 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3111780/68054e9b-4c5f-b544-c986-f8a20cb4908e.png)


```php:view/admin/items/new.html.erb
<%= form_with model: @items, url: admin_items_path do |f| %>
  <h4>タイトル</h4>
  <%= f.text_field :title %>
	
  <h4>本文</h4>
  <%= f.text_area :body %>
	
  <%= f.submit '投稿' %>
<% end %>
```

## ②ルーティング確認

`newアクション`と`createアクション`の記述が必要です。
コントローラー作成の時にnewアクション付きで作成していれば、newはすでにあると思います。
しかし、データ保存を行うcreateアクションがない為、追加で書く必要があります。

```php:config/routes.rb
Rails.application.routes.draw do
  get 'items/new'
  post 'items' => 'items#create'   #ここを追記します
  :
  :
end
```

resouresでまとめたら楽だと思います。（下記参照）

```php:config/routes.rb
Rails.application.routes.draw do
resources :item, only: [:new, :index, :edit, :destroy, :show, :update, :create]
  
  :
  :
end 
```

# ③コントローラー

newとcreateの部分に書いていく必要があります。


```php
class ItemsController < ApplicationController
  def new
    @item = Item.new  #投稿を新規作成するためのフォーム
  end
 
  def create
    @item = Item.new(item_params)  # データを受け取り新規登録するためのインスタンス作成
    @item.save  # データをデータベースに保存するためのsaveメソッド実行
    redirect_to admin_items_path  # itemのindexページ画面へリダイレクト
  end
  
private
  # ストロングパラメータ
  def item_params
    params.require(:items).permit(:title, :body)
  end
end

```

大まかにこんな感じかなぁ…:open_mouth:
ChatGPT x LINEボット連携 with google apps script

若干すでにうろ覚えだけど、備忘録に書いとく。
- [こちらを参考にさせてもらった](https://chatgpt-lab.com/n/n55257c082a9d)（ほぼそのまま）


必要なもの
・OPEN AIのAPI Key
・LINE developersのmessaging APIのチャネルアクセストークン（ https://developers.line.biz/ja/ で取っておく）


google apps scriptで、下記入れる。

```javascript
const LINE_ACCESS_TOKEN = 'XXX';
const OPENAI_API_KEY= 'XXX';


function doPost(e) {
  const event = JSON.parse(e.postData.contents).events[0];

  const replyToken = event.replyToken;
  let userMessage = event.message.text;
  const url = 'https://api.line.me/v2/bot/message/reply';

  if (userMessage === undefined) {
    // メッセージ以外(スタンプや画像など)が送られてきた場合
    userMessage = '？？？';
  }

  const prompt = userMessage;
  const requestOptions = {
    "method": "post",
    "headers": {
      "Content-Type": "application/json",
      "Authorization": "Bearer "+ OPENAI_APIKEY
    },
    "payload": JSON.stringify({
      "model": "gpt-3.5-turbo",
      "messages": [
        {"role": "system", "content": `
あなたはChatbotとして、坂本龍馬のロールプレイを行います。
以下の制約条件を厳密に守ってロールプレイを行ってください。 

制約条件: 
* Chatbotの名前は、坂AI龍馬です。  
* 必ず土佐弁を使ってください。
* 古い言い回しをしてください。
        `},
         {"role": "user", "content": prompt}]
    })
  }

  const response = UrlFetchApp.fetch("https://api.openai.com/v1/chat/completions", requestOptions);


  const responseText = response.getContentText();
  const json = JSON.parse(responseText);
  const text = json['choices'][0]['message']['content'].trim();

  UrlFetchApp.fetch(url, {
    'headers': {
      'Content-Type': 'application/json; charset=UTF-8',
      'Authorization': 'Bearer ' + LINE_ACCESS_TOKEN,
    },
    'method': 'post',
    'payload': JSON.stringify({
      'replyToken': replyToken,
      'messages': [{
        'type': 'text',
        'text': text,
      }]
    })
  });
  return ContentService.createTextOutput(JSON.stringify({'content': 'post ok'})).setMimeType(ContentService.MimeType.JSON);
}

```

デプロイで、アクセスできるユーザーに「全員」を選択して、デプロイする。

吐き出されるURLを、LINEの方のwebhook URLに登録する（デプロイの度に更新必要）

こんな感じに仕上がる。

https://twitter.com/maze_rapid/status/1632030756993376256?s=20
OS Xでdevドメインのサイトに接続が拒否された問題

![スクリーンショット 2023-03-11 午後10.19.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131146/1685c459-4342-3d69-1340-f63883fa440c.png)

# 問題
MacのOSをMontereyに更新してからdevドメインのサイト(例えばhttps://vscode.dev/ とか https://zenn.dev/ とか)への接続が拒否されるようになった。ブラウザ版のVSCodeが開けなくなってしまったのである。
最初はchromeの問題かなと思ったがsafariを使ってもやはり接続できず、ネットワークの問題かなと思って違うネットワークに接続して試してみたけどやはり解決しなかった。

# 解決法
https://superuser.com/questions/1413402/i-cant-visit-websites-that-have-dev-domain
/etc/resolver/devを消したら解決した。めでたしめでたし。
RSpecの準備、及びFactoryBot、Fakerを用いたモデルデータの設定方法について

## 目的
RSpecを用いたテストの実装

## 前提条件
- Ruby 3.1.2
- Rails 6.1.7.2

## RSpecの準備
```Ruby:Gemfile
group :test do
  gem 'capybara', '>= 3.26'
  gem 'selenium-webdriver', '>= 4.0.0.rc1'
  gem 'webdrivers'
  # RSpecテスト用
  gem 'rspec-rails'
  gem "factory_bot_rails"
  gem 'faker'
  gem 'rails-controller-testing'
end
```
- rspec-rails
RailsにてRSpecを使ってテストするのに必要
- factory_bot_rails
テスト用にダミーのインスタンスを作成
- rails-controller-testing
Railsのコントローラーをテストするのに必要 
- faker
インスタンス作成の際、多様なダミーデータを投入できるようになる

```Ruby:ターミナル
$ bundle install
```

### RSpecのファイルの作成
```Ruby:ターミナル
$ rails g rspec:install
```

```Ruby:.rspec
--require spec_helper
#以下追加
--format documentation
```
この記述で表示を以下のように変更
テスト項目が見やすくなる
```Ruby:ターミナル
Message
  create
    can save
      is valid with a message
      is valid with an image
      is valid with a message and an image
    can not save
      is invalid without a message and an image
      is invalid without a group
      is invalid without an user

Finished in 3.51 seconds (files took 4.50 seconds to load)
6 examples, 0 failures
```
### factory_botの書き方を省略
```spec/rails_helper.rb
RSpec.configure do |config|
  #以下を追加
  config.include FactoryBot::Syntax::Methods
end
```

## FactoryBot、Fakerを用いたモデルデータの作成
### factory_botの作成
specフォルダ配下にfactoriesフォルダを作成
```Ruby:ターミナル
mkdir spec/factories
```
さらに、作成したいファイルのモデルの作成
**spec/factories/作成したいモデル名.rb**
以下はuserモデルでの例
```spec/factories/user.rb
FactoryBot.define do
  # パスワードの設定
  #パスワードのように同じ記述を複数回使用したい場合は以下のような変数に指定して代入することが出来る
  password = Faker::Internet.password(min_length: 6, max_length: 8)
  
  # ユーザーモデルのダミーデータ
  factory :user do
    #カラム名 { 作成したい内容を記述 }
    #Faker〜の記述はgem 'faker'を用いたダミーデータの作成を指している
    name { Faker::Internet.username(specifier: 5..8) }
    nickname { Faker::Internet.username(specifier: 5..8) }
    email { Faker::Internet.email(domain: 'example') }
    phone_number { Faker::Number.leading_zero_number(digits: 11) }
    password { password }
    password_confirmation { password }
    is_deleted { "false" }
  end
end
```
Fakerの使い方、書き方一覧は下記公式のREADME.mdから調べるとわかりやすい
`Faker::Internetの場合、Generators項目の、Default内にある、Faker::Internetのリンクをクリックすることで確認できる`

https://github.com/faker-ruby/faker#generators

## 次回以降について
次回はモデルにおけるテストの作成について掲載予定です
Slack上でOpenAI社のWhisper APIで文字書き起こし（speech to text）するSlackBot作成方法

# Slack上で高性能な文字起こしBotを作りたい！

という変わった趣味を持った人向けのTips。
Slackだけでも音声ファイルを投稿すると文字起こししてくれるが、精度はかなり悪い。正直使い物にならない。このOpenAIのWhisperを使うとかなり実用的になる。

# ChatGPTのチャットボットの作り方
以前に記事を作ったのでそちらを参考に。今回のWhisperもほぼ同様。最後のスクリプトが違うだけ。
基本はOpenAI社のAPIにファイル渡して出力結果をSlackに投稿するというだけ。

https://qiita.com/ina111/items/0591ab8714139e67b19c

# 音声認識モデルをSlackBotに

上の記事を参考に
1. OpenAIでAPI key
1. Slackでアプリを作る
1. コード
までは実施する。違いとしては、app.pyは以下コードに変える。ポイントは以下の通り

* アプリにメンションされた上でwhisperのAPIで読み取れるファイル形式の音声ファイルがあるときだけ反応。
* 25MB以下の容量のファイルでないといけないので、それ以上はエラー（改良余地あり）
* デフォルトは日本語として、英語の音声ファイルの場合はSlackのメッセージにEnglushと書くと英語と認識して文字起こししてくれる



https://gist.github.com/ina111/64a92c53171f96a678adf5f77f292cca

# 実際に動かしてみるとこんな感じ。

私はSlackアプリ（App）としてWhisper先生と名付けてアプリ作った。
スマホやブラウザからマイクマークの音声投稿が出来るが、それをメンション付きで投稿すると文字起こししてくれる。
１分間の音声で0.8円程度。１時間の音声でも50円の料金。
OpenAI社の無料API枠が月に18ドル（2023年3月現在）なので、よっぽど使わないと使いきれない。

![スクリーンショット 2023-03-11 211513.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40132/4812fd46-1eb1-81b3-027b-b1dadf9eff3a.png)

どこかからもってきた音声ファイルを投げても当然文字起こししてくれる。
録音とか会議とか音声ファイルあるものならなんでもすぐに文字起こししてくれる。
ニュースみたいに発音のクリアなものではほぼ完璧に文字起こししてくれる。雑音だらけでも結構な精度で認識してくれて感動する。

![スクリーンショット 2023-03-11 211529.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40132/38546a69-7519-c39a-e5b7-081065b31127.png)

# ChatGPTと組み合わせると強い

Whisperの音声認識は句読点が抜けていたり、段落が分かれて無くて使いづらい。
これをChatGPTと組み合わせと良く校正してくれる。
インタビューや議事録の文字起こしはAIに任せる時代だ。
人間の役割は録音ボタンを押す係。

![スクリーンショット 2023-03-11 212849.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40132/d7990d93-a511-28a7-5d08-26ac08183b01.png)
![スクリーンショット 2023-03-11 212905.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40132/c2b13b0e-2ac6-71f4-f761-7cfbcb6fbec5.png)
いいね　おさなくて　ごめんなさい。

SNSの行動で、いいねは、基本、読みましたという記録としておさせていただいています。　

そうは言っても、内容などで、公共の福祉に反していたり、公序良俗に反している内容だと感じた場合は押していません。　

問題は、すべての記事を読めないという量の問題です。　

これを克服するには、「読まない」基準を設けて、読まなければ、内容を判断する時間が必要ないことに辿り着きました。

# Facebook 

ある特定の傾向の内容はブロックすることにしました。　

題材もそうですし、プロフィールにある特定の傾向だけの記載をされている方をブロックさせていただいています。　

投資はほぼすべてブロッックさせていただいています。　
経済学部を卒業し、市場調査と投資については、ある意味専門家であるという自負はあります。　
技術者に転向してからは、新規開発に関係している限り、内部取引と誤解をされる可能性がある行動を最新の注意をするためには、ブロック以外にはないと判断しました。

自分でも定年退職する時に、ベンチャーキャピタルからの投資診断の会合に出て、発表したことはあります。その時のベンチャーキャピタルの方の話が、あまりに馬鹿げていて、うんざりした経験があります。　

３年で回収できる投資計画を作れというものでした。馬鹿じゃないのというのは、技術内容を聞いて、それを３年で回収できる投資計画を作るのが、ベンチャーキャピタルの仕事なのに、なにをベンチャーに丸投げしようとしているんだろうと。

そんな人たちの存在にいいねを押すことができなくなりました。

そこで、何か、人ではなくて、記事にも基準を設けられないかと思い、ひとまず実践していることがあります。　

## 青いいねだけ100以上ある記事を書かれている方はミュートしていいねを押さない。

青いいねだけ100以上ある記事を時々目にすることがありました。

どう考えても、裸の王様とその取り巻きの確率が9割以上のような気がしました。

裸の王様にならないために

https://qiita.com/kaizen_nagoya/items/450a66b3d8778fc649ab

## 青いいねだけ10以上ある記事にはいいねを押さない。

そのまま放置すれば、青いいねだけ100以上になる可能性が1割以上ある気がして、　
まんがいち、青いいねだけ100以上ある記事に関わることにならないように、　
そっと内容を読まずに、読み飛ばすことにしました。

実際には、青いいねだけ10以上ある記事を書かれている方の半分以上の方は、　
半分くらいの記事は、青いいね以外の赤いいね、大切だね、すごいねを押されていて、　
それらの記事は、拝見した上で、青いいね以外を押すようにしています。　

厳密な統計はとっていませんが、　　


A:青いいねだけ10以上ある記事のつまらなさ0-面白さ100
B:青いいねだけ10以上ある記事ではない記事のつまらなさ0-面白さ100
C:青いいねだけ10以上ある記事の青いいねを押している人の裸の王様の取り巻き度
D:青いいねだけ10以上ある記事ではない記事の青いいね以外を押している人の裸の王様の取り巻き度


|分類|つまらなさ0-面白さ100|
|:--|:--|
|A|0-80|
|B|20-100|

|分類|裸の王様取り巻き度|
|:--|:--|
|C|40-100|
|D|0-100|

青いいねだけ10以上ある記事ではない記事の青いいね以外を押している人の裸の王様の取り巻き度が100を入れているのは、裸の王様の時巻きにも、賢い人がいて、実はその人が、裸の王様を操っている場合には、青いいね以外わ押して誘導しているのかもしれない。



技術を極める。近寄りたい人。近寄りたくない人。三分類、五集合。

https://qiita.com/kaizen_nagoya/items/aefd732bcd2518b93ae3




# Qiita
tqdmとlogging

# 
https://tqdm.github.io/docs/contrib.logging/

ここにある方法を使う。
`loggers`に`logger`をちゃんと渡す。

```python
import logging
from tqdm.contrib.logging import logging_redirect_tqdm
logger = logging.GetLogger(__name__)

with logging_redirect_tqdm(loggers=[logger]):
    for item in tqdm(items):
        logger.debug(item)
```
【Laravel(5.8)】ログアウト後の遷移先を変える


既にいろんな記事があるのですが、それのどれもイマイチ思ったような動作をせず。

自分なりに「とりあえずこれでいいか」となったので一応備忘録がてら。

　


***開発環境***

【Laravel5.8】

　

***やりたかったこと***

ログアウトした際に指定したルーティングorリンクに飛ばしたい


***内容***

Laravel5.8の公式ドキュメントでログアウトを検索すると「Auth::logout()」を使え。
と書いてあるのでそれを使うために自作のコントローラーの中にメソッド作っちゃう。


↓公式
https://readouble.com/laravel/5.8/ja/authentication.html


　


***ソース***
```php
public function logOut(){
       Auth::logout();
   ★   return redirect('/'); //リダイレクトで好きなとこに飛ばす
}
```


とりあえずこれで問題なさそうですが、何かお気づきの点あればご指摘いただけるとありがたいです。
【Pythonプログラミング入門】ライブラリ一括インストール！ requirements.txt 【初心者向け】

# Pythonのpipで管理しているライブラリ・パッケージを、別のPython環境でも一括でインストールする方法

https://camp.trainocate.co.jp/magazine/venv-python/

https://www.sejuku.net/blog/68423

https://youtu.be/iiFs3u6VkFE
Vue.jsとVueUseでフォーカスの逃げないModalを作るメモ

# Vue.jsとVueUseでフォーカスの逃げないModalを作るメモ（備忘録）

# フォーカスが外に・・・

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3270885/8b401576-afcb-9c5e-4646-8922bcc3daa0.png)
モーダルを作るときにフォーカスが後ろにいかないよう制御が必要だと思いますが、
VueUseで「focus-trap」をラップした機能が使えるのでそれを使用します。

# VueUseインストール
Vue3.2系が使える環境にVueUseをインストール
※focus-trapをラップしている機能なのでfocus-trapもインストール
```shell
npm i @vueuse/integrations
npm i focus-trap
```
# モーダルなコンポーネントのSFCで・・・
## まずは完成形
　※デモページで含まれる不要な要素は割愛
```vuejs
<script setup lang="ts">
import { useFocusTrap } from '@vueuse/integrations/useFocusTrap';
import { ref, watch } from 'vue';
type Props = {
  isShow: boolean;
};
const props = defineProps<Props>();
type Emits = {
  (e: 'close'): void;
};
const emit = defineEmits<Emits>();
const target = ref();
const { hasFocus, activate, deactivate } = useFocusTrap(target);

</script>
<template>
  <div class="card" ref="target">
    <div
      class="card-header bg-primary text-white d-flex justify-content-between align-items-center"
    >
      フォーカス制御されたモーダル1
      <button
        type="button"
        class="btn btn-outline-light"
        @click="emit('close')"
      >
        閉じる{{ hasFocus }}
      </button>
    </div>
    <div class="card-body bg-light">
      <div class="mb-3">
        <label class="form-label">入力</label>
        <input type="text" class="form-control" placeholder="" />
      </div>
    </div>
  </div>
</template>
```

## 詳しく
useFocusTrapをImport 
```typescript
import { useFocusTrap } from '@vueuse/integrations/useFocusTrap';
```
focusTrapをon-offするために親要素からモーダルが表示しているかどうかの情報を受取る
```typescript
type Props = {
  isShow: boolean;
};
const props = defineProps<Props>();
```

focusTrapを設置する要素用のrefオブジェクト
```typescript
const target = ref();
```


モーダルの表示非表示を見てfocusTrapを制御
```typescript
watch(
  () => props.isShow,
  () => {
    if (props.isShow) {
      activate();
    } else {
      deactivate();
    }
  }
);
```


テンプレートでフォーカス制御する要素にrefをあてるのを忘れずに。
```html
  <div class="card" @click.stop ref="target">
```



## でもこれだと？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3270885/a610e32b-d398-fd6a-9732-93b9ba4c2208.png)

「モーダル要素の外をクリックしてモーダルを閉じる」ができなくなる。
※緑の領域のクリックイベントが発火しない


## 解決策

```typescript
 const { hasFocus, activate, deactivate } = useFocusTrap(target, {
  allowOutsideClick: true,
});
```
useFocusTrapの第2引数に[allowOutsideClick]を設定すればクリックが可能に。



## GitHubにサンプル上げてます

https://github.com/hare-systems-ryo/vue-modal-sample

## ついでにGitHubにデモページも・・・

https://hare-systems-ryo.github.io/vue-modal-sample/home
【chatGPT】複数キャラAIのリアルタイム雑談配信システムを構築した

前回chatGPTを使って複数キャラにテキスト形式で会話して頂きました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242645/ac238fb9-2544-be11-bd3b-4feb7dd43c89.png)


テキスト形式でも十分におもしろかったのですが、
ビジュアルと音声がついたらどれだけ存在感が増すだろうかと思い、ほぼリアルタイムに雑談してもらえるシステムを開発しました。

雑談している風景を収めたのが下記の動画です。
キャラと話の方向性を定めるために各キャラ一回だけ決め打ちの発言をさせていますが、それ以降はキャラ自身が発言内容を考えています。

https://www.youtube.com/watch?v=SsUMhFieXeY

見た目と音声をつけたことにより、キャラ達が会話している感がぐっと向上したと思います。


# システムの概要
システムの概要図は下図のとおり
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242645/f97d2691-89e0-b41f-606a-e96f30462c85.png)
構成要素は3つあり
・チャットコントローラー
・キャラクター
・発言順に音声を再生するモジュール
です。

チャットコントローラーが会話順を決め、各キャラクターが文章作成・音声作成・立ち絵表示を行います。作成した音声オブジェクトを発言順に再生するモジュールに渡し、音声を再生します。


# システムのポイント(リアルタイム性の改善)
　キャラ達にリアルタイムに会話させようとすると、openaiが文章を作成する時間と音声を合成する時間が約12秒ほど発生するため、ほかのキャラクターが発話を終えてから会話の準備を始めるのでは間が空きすぎて聞くに堪えないものになります。
そのため、文章作成と音声作成、音声の再生は非同期で実行するようにしました。
これにより、キャラ達の会話が滞りなく進むようになりました。

# システムのポイント(立ち絵の表示)
1台のPCで自作かつ複数のキャラクターの絵を動かす方法に悩みました。
というのも、多くのVtuber向けのシステムでは１体を動かすことを目的としており、複数のキャラクターを動かすことは目的としておりません。
また、今回の場合は音声から立ち絵を動かす必要があります。このような場合に最も適したソフトとして、Puppet3
https://github.com/leobtype/Puppet3/releases
が見つかりました。
Puppet3は立ち絵４枚から瞬きと口パクをさせるモジュールです。ランダムに瞬きをし、音量に従って口パクします。
しかし、Puppet3では最大で2体までしか動かすことができませんでした。

そのため、立ち絵を表示するモジュールを自作しました。
各キャラごとの立ち絵の表示をopencvで行い、ランダムなタイミングで瞬きする絵と音量に従って口パクするように実装しました。
さらに、キャラクターの存在感を上げるために微妙にちょっとずつ動かすようにしています。
最後にキャラごとのウィンドウをOBSで読み取り合成しました。



# ライブ配信について (Youtube Live)
今回のは動画として作成しましたが、
Youtube Liveでコメント欄の情報を読み取りながらキャラ達にお喋りしてもらったら、
もっと面白くなるのではないかと考えています。
KyaraAIのtwitterを作成しましたので、ライブ配信を行う場合はこちらで告知するのでぜひフォローしてください！

https://twitter.com/KyaraAIOfficial
在宅勤務中の「離席」を防ぐ、キーを自動で押す手段

# 背景
- 在宅勤務をする際、顧客から貸与された端末がすぐ画面ロックされる。なかなかウザい。。
- 自社端末でも仕事ができるため、貸与PCを操作しないことでステータスが体積中となる点、腑に落ちない
- 画面ロックと画面ロックまでの時間変更のユーザ権限を持っていない

# 目的
- 一定の間隔でキーボードを物理的に押して、画面をロックをさせない

# 手段
- SwitchBot社のボットを使う
- 純正アプリだと曜日と時間でのスケジュールしか不可のため、APIをキックする
- APIキックはタスクスケジューラを使う

# ソース
```python:SwitchBotPressButton.py
import requests
import json

OPEN_TOKEN = '[[トークンを記載する]]'
API_HOST = 'https://api.switch-bot.com'
DEBIVELIST_URL = f"{API_HOST}/v1.0/devices"

HEADERS = {
    'Authorization': OPEN_TOKEN,
    'Content-Type': 'application/json; charset=utf8'
}

def _post_request(url, params):
    res = requests.post(url, data=json.dumps(params), headers=HEADERS) 
    data = res.json()
    print(data)
    if data['message'] == 'success':
        return res.json()
    return {}

def send_bot_press(deviceId):
    url = f"{API_HOST}/v1.0/devices/{deviceId}/commands"
    params = {
        "command": "press",
        "parameter": "default",
        "commandType": "command"
    }
    res = _post_request(url, params)
    if res['message'] == 'success':
        return res
    return {}

status = send_bot_press('[[deviceIdを記載する]]')
```

# 最後に
サボるための方法ではなく、画面がロック解除の手間を省く小技についての紹介でした。
トークン取得やタスクスケジューラの設定方法は省きましたが、小一時間くらいで実現できました。

# 追記
やはりこの手の製品はありますよね～('ω')
- <a href="https://hb.afl.rakuten.co.jp/ichiba/308d5017.a56e7cd5.308d5018.27165f26/_RTLink68307?pc=https%3A%2F%2Fitem.rakuten.co.jp%2Fpirorinonline%2F4945325252759%2F&link_type=text&ut=eyJwYWdlIjoiaXRlbSIsInR5cGUiOiJ0ZXh0Iiwic2l6ZSI6IjI0MHgyNDAiLCJuYW0iOjEsIm5hbXAiOiJyaWdodCIsImNvbSI6MSwiY29tcCI6ImRvd24iLCJwcmljZSI6MSwiYm9yIjoxLCJjb2wiOjEsImJidG4iOjEsInByb2QiOjAsImFtcCI6ZmFsc2V9" target="_blank" rel="nofollow sponsored noopener" style="word-wrap:break-word;"  >VAYDEER スーパーミニ マウスジグラー USB ポート マウスムーバー Mouse Jiggler マウス エミュレータ</a>
- <a href="https://hb.afl.rakuten.co.jp/ichiba/308d5629.c6c2efe8.308d562b.94ae9884/_RTLink68307?pc=https%3A%2F%2Fitem.rakuten.co.jp%2Fpipitanonline%2F4946730894691%2F&link_type=text&ut=eyJwYWdlIjoiaXRlbSIsInR5cGUiOiJ0ZXh0Iiwic2l6ZSI6IjI0MHgyNDAiLCJuYW0iOjEsIm5hbXAiOiJyaWdodCIsImNvbSI6MSwiY29tcCI6ImRvd24iLCJwcmljZSI6MCwiYm9yIjoxLCJjb2wiOjEsImJidG4iOjEsInByb2QiOjAsImFtcCI6ZmFsc2V9" target="_blank" rel="nofollow sponsored noopener" style="word-wrap:break-word;"  >マウスジグラー USB マウスムーバー Mouse Jiggler 全自動マウス エミュレータ カウントダウン調整可能</a>
[AWS Q&A 365][Redshift]AWSのよくある問題の毎日5選 #1

# 1. Amazon Redshiftにおける概念証明とは何ですか？
回答：Amazon Redshiftにおける概念証明は、目標と成功基準の特定、概念証明の設定、評価のためのプロジェクト計画の作成の3つのステップを含むプロセスです。

# 2. Amazon Redshiftでテーブルを設計するためのベストプラクティスは何ですか？
回答：Amazon Redshiftでテーブルを設計するためのベストプラクティスには、最適なソートキーとディストリビューションスタイルの選択、自動圧縮の使用、制約の定義、可能な限り小さい列サイズの使用、および日付/時間データ型の使用が含まれます。

# 3. Amazon Redshiftでデータをロードするためのベストプラクティスは何ですか？
回答：Amazon Redshiftでデータをロードするためのベストプラクティスには、COPYコマンドを使用してデータをロードすること、単一のCOPYコマンドを使用すること、データファイルをロードすること、データファイルを圧縮すること、ロード前後にデータファイルを検証すること、マルチロウインサートを使用すること、ソートキーオーダーでデータをロードすること、シーケンシャルブロックでデータをロードすること、タイムシリーズテーブルを使用すること、マージを実行するためのステージングテーブルを使用すること、メンテナンスウィンドウを考慮してスケジューリングすることが含まれます。

# 4. Amazon Redshiftのシステムおよびアーキテクチャ概要とは何ですか？
回答：Amazon Redshiftのシステムおよびアーキテクチャ概要には、データウェアハウスシステムアーキテクチャ、パフォーマンス、カラムストア、ワークロード管理、および他のサービスとのAmazon Redshiftの使用が含まれます。

# 5. Amazon Redshiftでデータを分析する際に評価できる要素は何ですか？
回答：Amazon Redshiftでデータを分析する際に評価できる要素には、trip_day、trip_month、trip_year、trip_quarter、trip_month_week、trip_week_day、temp_c、precip_amount_mm、およびis_holidayが含まれます。
ActiveBasic のプロジェクトを Git へコミットする際の注意点

# はじめに
ActiveBasic のプロジェクトを Git へコミットする際にいくつか注意する点があったのでメモ。

# 環境
本件で扱う ActiveBasic のバージョンは下記の通りです。
これ以外のバージョンについては検証していないので不明です。
・ActiveBasic Ver: 4.24

# 問題点
さて、問題点ですが ActiveBasic の開発環境である ProjectEditor は文字コードと改行コードを適切に指定しないと、
ソースコードやウィンドウファイル等が読み込まれなかったり、コンパイルが正常に行われないといった問題が発生することがあります。

# 解決方法
個人的に試して得られた方法が、.gitattributes に文字コードと改行コードを指定する方法です。
(他に良い方法があるのかもしれません…。)

以下は記載例です。
```.gitattributes
# 文字コード設定
*.?bp diff=sjis
*.idx diff=sjis
*.wnd diff=sjis
*.wrk diff=sjis
*.pj  diff=sjis

# 改行コード設定
*     text=auto
*.?bp text eol=crlf
*.idx text eol=crlf
*.wnd text eol=crlf
*.wrk text eol=crlf
*.pj  text eol=crlf
```

ActiveBasic で使用するソースコードを含むテキスト系のファイルはすべて文字コードを shift-jis に、
改行コードを crlf に固定化しています。
こうすることで、リポジトリから Clone したプロジェクトファイルを ProjectEditor で読み込んで
コンパイルを直ぐに始めることが出来ます。
[AWS Q&A 365][Redshift]Daily Five Common Questions #1

# 1. What is a proof of concept in Amazon Redshift? 
Answer: A proof of concept in Amazon Redshift is a three-step process that involves identifying the goals and success criteria, setting up a proof of concept, and developing a project plan for evaluation.

# 2. What are some best practices for designing tables in Amazon Redshift?
Answer: Some best practices for designing tables in Amazon Redshift include choosing the best sort key and distribution style, using automatic compression, defining constraints, using the smallest possible column size, and using date/time data types for date columns.

# 3. What are some best practices for loading data in Amazon Redshift?
Answer: Some best practices for loading data in Amazon Redshift include using a COPY command to load data, using a single COPY command, loading data files, compressing data files, verifying data files before and after a load, using a multi-row insert, loading data in sort key order, loading data in sequential blocks, using time-series tables, using a staging table to perform a merge, and scheduling around maintenance windows.

# 4. What is the system and architecture overview of Amazon Redshift?
Answer: The system and architecture overview of Amazon Redshift includes the data warehouse system architecture, performance, columnar storage, workload management, and using Amazon Redshift with other services.

# 5. What are some factors that can be evaluated when analyzing data in Amazon Redshift?
Answer: Some factors that can be evaluated when analyzing data in Amazon Redshift include trip_day, trip_month, trip_year, trip_quarter, trip_month_week, trip_week_day, temp_c, precip_amount_mm, and is_holiday.