OmniAICreator/Qiita-1.07M huggingface dataset:
Linuxにanacondaインストールしてパスを通して仮想環境作成

何度も調べ直してるので自分用メモ。

# Anacondaのインストール
**ターミナルでbashを起動し、wgetでインストーラパッケージをダウンロードする。**
[anacondaのサイト](https://www.anaconda.com/download#downloads)にあるURLからLinux向け最新版のものを選ぶ。
```bash:
$ wget https://repo.anaconda.com/archive/Anaconda3-2023.03-1-Linux-x86_64.sh
```
**インストーラを起動してインストールする。**
`Anaconda3-2023.03-1-Linux-x86_64.sh` という名前のファイルが`Downloads/`またはホームディレクトリに作成されているので、以下コマンドでインストールの開始。
```bash:
$ bash ~/Downloads/Anaconda3-2022.05-Linux-x86_64.sh
```
licence termsが長々と表示されるので、最後までスクロールして`yes`と入力する。qキーを押すと一気にスクロールできる。
```bash:
The following packages listed on https://www.anaconda.com/cryptography are included in the repository accessible through An
aconda Distribution that relate to cryptography.

Last updated February 25, 2022


Do you accept the license terms? [yes|no]
[no] >>>
Please answer 'yes' or 'no':'
>>> yes
```
インストールが開始され、インストール先のディレクトリが表示される。この場合は、`/root/anaconda3`にインストールされる。特に変更しない場合はそのままEnterを押す。
```bash:
Anaconda3 will now be installed into this location:
/root/anaconda3

  - Press ENTER to confirm the location
  - Press CTRL-C to abort the installation
  - Or specify a different location below

[/root/anaconda3] >>>
PREFIX=/root/anaconda3
Unpacking payload ...
```
完了したら、`yes`と入力して初期化を行う。
```bash: 
done
installation finished.
Do you wish the installer to initialize Anaconda3
by running conda init? [yes|no]
[no] >>> yes
```
**パスを通す**
このままcondaを実行しようとしても`bash: conda: command not found`と言われてしまうので、パスを通す必要がある。
先ほどインストール時に表示されたインストール先のディレクトリ`/root/anaconda3`を元に、以下のコマンドでパスを通す。
```bash:
$ export PATH=/root/anaconda3/bin:$PATH
```
これで、condaコマンドが認識されるようになった。
```bash:
$　conda --version
conda 23.3.1
```

# Anacondaで仮想環境の作成
※この段階でうまくいかない場合は、シェルを再起動する

**仮想環境の作成**
$ conda create -n 環境名 python=バージョン
```bash:
$ conda create -n py310 python=3.10
```
**仮想環境の起動**
$ conda activate 環境名
```bash:
$ conda activate py310
```
**仮想環境の終了**
$ conda deactivate 環境名
```bash:
$ conda deactivate py310
```
**作成済み仮想環境の一覧を表示**
```bash:
$ conda env list
```
**作成済み仮想環境の削除**
```bash:
$ conda remove -n 環境名 --all
```
# Jupyterのkernelに、作成した仮想環境を追加する
仮想環境を作成しただけでは、JupyterNotebookからkernelとして環境を選択することはできない。
**利用可能なカーネルの表示**
```bash:
$ jupyter kernelspec list
Available kernels:
  python3    /root/anaconda3/share/jupyter/kernels/python3
```
ここに、先ほど追加した仮想環境のカーネルを追加する。対象の仮想環境をアクティベートした状態で以下コマンドを実行。
```bash: 
$ pip install ipykernel
$ python -m ipykernel install --user --name py310 --display-name "Conda Python 3.10"
```
Jupyter Notebook上でカーネルの切り替えができるようになった。



ref: https://linuxhint.com/conda-command-not-found/
【Swift】○○(1)、○○(2)にする方法

## はじめに
実務で、同じセット名があったら、セット名の横に(1)、(2)と増やしていく実装があり、苦労したため備忘録を残しておく。
## 基本的な流れ
▼説明１
replacingOccurrencesを使い、「セット名(1)(2)」になったら、先頭の(1)を消す。例：「セット名(1)(2)」→「セット名(2)」
▼説明２
forを使い、文字列の横に（数字）をつけていく。例：「セット名(1)」

## 全体のコード
```swift
    func createSetName(sets: [Set], previouSetName: String) -> String {

       let originalName = previouSetName.replacingOccurrences(of: "^(.+)\\([0-9]+\\)$", with: "$1", options: .regularExpression)

                for i in 1..<99 {
                    let target = "\(originalName)" + "(\(i))"
                    let sameName = previouSetName.first(where: { $0.setName == target })
                    let notKakkoName = sets.first(where: { $0.setName == originalName })
                    if notKakkoName == nil {
                        return originalName
                    }
                    if sameName == nil {
                        return target
                    }
                }
            return originalName
    }
```

## ▼説明1
置換処理(replacingOccurrences)と正規表現を使って、文字列が「セット名(3)」となれば、(3)を削ぎ落とし、「セット名」だけにします。
```swift
var setName = "セット名(3)"
setName.replacingOccurrences(of: "^(.+)\\([0-9]+\\)$", with: "$1", options: .regularExpression)
print(setName)
```
printの中身は、セット名になります。

```swift
"^(.+)\\([0-9]+\\)$"
```
上記の正規表現の
`^(.+)　`は先頭の文字列（）があるかどうか→例：セット名(3)までの文字の部分。
`\\([0-9]+\\)$`は行末に(0)~(9)までの数字が一致しているかどうか→例：()付きの数字。ここでいうと(3)の部分。
今回は、`with: "$1"`で、$1にあたる`^(.+)`にくる部分を残しています。

### 正規表現について
|記号|説明  |
|---|---|
|^ |行の先頭  |
|. |任意の1文字  |
|+ |直前の文字の1回以上の繰り返し  |
|\\ |回避するという意味。Swiftでは2つのバックスラッシュが必要。|
|[0-9]+| 0〜9の数字のどれかが一致するか|
|$| 行の末|


## ▼説明2
```swift
for i in 1..<100 {
     let target = "\(originalName)" + "(\(i))"
     let sameName = sets.first(where: { $0.setName == target })
     let notKakkoName = sets.first(where: { $0.setName == originalName })
     if notKakkoName == nil {
         return originalName
     }
     if sameName == nil {
         return target
     }
}

```

### ■例１
`previousSetName`に「セット名」が入る場合
そもそも説明１での置換処理は行われず、for文に進み、`target`は「セット名(1)」となります↓

```swift
let target = "\(originalName)" + "(\(i))"
```


次に、
*setsという配列(セット名などの情報が入っている構造体Modelの配列)の中身から、同じセット名があるかを探します。↓

```swift
let sameName = sets.first(where: { $0.setName == target })
```
「セット名(1)」が検索ヒットされないので、そのままtargetが返され、「セット名(1)」になります。
```swift
let notKakkoName = sets.first(where: { $0.setName == originalName })
```


### ■例2
`previousSetName`に「セット名(1)」が入った場合、
説明１の置換処理が行われ、`target`には「セット名(1)」がきます。

そして、↓でもう一度検索をかけます。

```swift
let sameName = sets.first(where: { $0.setName == target })
```

「セット名(1)」は検索ヒットされると、もう一度forループが回ります。
`target`には「セット名(2)」となり、
```swift
if sameName == nil {
   return target
}
```
ここに入り、target「セット名(2)」を返しています。

これを(1)〜(99)まで繰り返しています。

■補足
*setsというのは、セット名が含まれたModelの配列です。
```swift
struct Set {
    var setName = ""
}
```

### ■例3
setsの配列の中にsetNameの「セット名」、「セット名(1)」、「セット名(3)]が存在していて、
`previousSetName`に「セット名(1)」が来た場合

置換処理された後に、`target`に「セット名(1)」がきます。
`notKakkoSetName`も`sameName`もヒットするので、もう一度for文が回ります。
「セット名(2)」が検索ヒットせず、
```swift
if sameName == nil {
   return target
}
```
ここに入って、「セット名(2)」が返されます。
なので、間に数字がない場合でも、小さい順に数字を割り振って埋めてくれます。
WordPressの「content/uploads/に移動できませんでした」

①容量がいっぱい
②ファイル数がいっぱい
③フォルダ権限がかわった
④ファイル名が長い　←　:congratulations:

UTF-8で256バイト超えると起こると予想してるけど詳しく調べる気もない備忘録
Nuxt3でFontAwesomeを使う

Nuxt3でFontAwesomeを導入しようと各所の記事通りやっても上手くいかないことが多々あり…。
ちょっと古めの記事(RC版)が多く見受けられたので、改めて自分で整理してみます。

## 環境
Nuxt 3.4.0
FontAwesome 3.0.3

## インストール
```
npm i --save @fortawesome/vue-fontawesome@latest-3
```

## pluginの作成
公式チュートリアルの通りで大丈夫でした。
注意点として、SSR/SSGで動作させる場合は **.client** をつけてください。
サーバーサイドでレンダリングするとハイドレーションエラーが発生して、アイコンが二重に表示されたり不可解な挙動を起こしてしまうみたいです。
``` fontawesome.client.ts
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
import { fas } from '@fortawesome/free-solid-svg-icons'

config.autoAddCss = false

// regular/blandsを使いたい場合は別途インストールする
library.add(fas)
export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.vueApp.component('font-awesome-icon', FontAwesomeIcon, {})
})
```

## nuxt.config.tsの編集
こちらも公式チュートリアル通りで。
``` nuxt.config.ts
export default defineNuxtConfig({
css: [
    '@fortawesome/fontawesome-svg-core/styles.css'
  ]
})
```

## 使い方
iconは以下のように配列で渡すようです。
他の記事では文字列で渡していたりしていましたが、自分の環境ではうまくいかず。
``` sample.vue
<FontAwesomeIcon :icon="['far', 'bell']" />
```

## 参考
https://fontawesome.com/docs/web/use-with/vue/use-with
https://ema-hiro.hatenablog.com/entry/2022/07/17/015626
https://zenn.dev/one_dock/articles/16f1ddb1e49b2c
オブジェクト指向プログラミング（OOP）について

# オブジェクト指向プログラミングとは  
コンピュータプログラムの構造、構成法の一つで、関連するデータの集合体と、それを操作する手続きをオブジェクトと呼ばれるひとつの単位として一体化し、オブジェクトの組み合わせとしてプログラムを記述する手法である。

# オブジェクト指向の関連用語
## オブジェクト 
オブジェクト（インスタンス）は、設計図であるクラスから作成した実体を表す。ひとつのクラスをもとに、複数のオブジェクトを作成することができる。  
オブジェクトとインスタンスに明確な違いはなく、同じ意味で用いられる事が多い。ただし、インスタンスという用語はクラスを実体化する文脈上で用いられるのが一般的。
## クラス  
オブジェクトの定義で、オブジェクトを作成するための設計図として用いられる。クラスにはプロパティとメソッドの要素が記述される。  
* プロパティ…オブジェクトが持つ性質や属性のこと。 
* メソッド…オブジェクト内のデータを操作するためのふるまいをまとめたもの  

# オブジェクト指向の特徴

## カプセル化
オブジェクト指向の基本概念。
オブジェクトが持つデータや処理のうち、必要のないものを隠すことをいう。対象物を操作するために必要な情報だけを外部から見えるようにして、残りをカプセルに包んで内部の処理を隠してしまうことからカプセル化と言う。
メリットは、誰でも簡単にその機能を使えるようにできるだけでなく、カプセルの内部にあるデータを勝手に書き換えたり参照できないようにして、他のプログラムから干渉できないようにすることができる。大人数で開発をするときにすべてのコードを認識しなくても良い。


## 継承
特定のオブジェクトの機能を引き継いで使うことを言う。
メリットは似たようなコードをひとまとめにすることができたり、一度作成したコードを再利用できるようになったりする。結果的にコード量が減って冗長しないようにすることができる。

## ポリフォーリズム
クラスによって同一のメソッドで異なる処理が行えるという性質をポリモーフィズムという。
複数のクラスで同じ名前のメソッドを使えるようにしておくことで、どのクラスであっても同じ名前のメソッドを呼び出せば、処理は違えど同じ目的の動作が行われるようにすることができる。
kintone.proxy()をブラウザのコンソールから叩くためのスニペット

## kintone.proxy()
レスポンスがJSONなら、こんな感じ。

```js
await kintone
  .proxy(
    'https://example.com',
    'POST',
    {
      'Content-Type': 'application/json',
      'x-api-key': 'xxxxxx',
    },
    {
      data1: 'foo',
      data2: 'bar',
    }
  )
  .then(([body, status, header]) => ({
    body: JSON.parse(body),
    status,
    header,
  }));
```

APIが200以外を返すときも`then()`の方に入るので、サクッと試すだけなら`catch()`は不要だと思います。


### 公式ドキュメントはこちら

外部の API を実行する
https://cybozu.dev/ja/kintone/docs/js-api/proxy/kintone-proxy/

## kintone.plugin.app.proxy()
第一引数にプラグインIDが入る以外は一緒です。

```js
await kintone.plugin.app
  .proxy(
    '(plugin-id)',
    'https://example.com',
    'POST',
    {
      'Content-Type': 'application/json',
      'x-api-key': 'xxxxxx',
    },
    {
      data1: 'foo',
      data2: 'bar',
    }
  )
  .then(([body, status, header]) => ({
    body: JSON.parse(body),
    status,
    header,
  }))
```

### 公式ドキュメントはこちら

外部の API を実行する
https://cybozu.dev/ja/kintone/docs/js-api/plugins/kintone-plug-in-proxy/
CAP定理とBASE特性に関するまとめ


## CAP定理
「以下の３要素を同時に満たすことができない」という考え
<br>
Consistency：一貫性
　　　∟誰かがデータを更新したら、その後は必ず更新後のデータが参照できること
Availability：可用性
　　　∟クライアントは必ずデータにアクセス可能であること
　　　（データが壊れたり、ロック待ちにならないこと）
Partition Tolerance：ネットワーク分断耐性
　　　∟データを複数サーバに分散して保管できること
　　　（データが複数のサーバに分散されており、1つサーバに障害が発生し、データが破損した場合でも、別サーバによりデータが参照可能であること）
<br>
単一サーバで動作するデータベース→ ネットワーク分断耐性がない
分散データベース→可用性がない
DNS、NTP、HTTPキャッシュなど→一貫性がない
<br>
<br>
・クラウドサービスにおいてネットワーク分断耐性は必須要件
・CAPすべてを満たすことはできないため、可用性の一部と一貫性の多くを妥協した（BASE特性）
<br>
## BASE特性とは
Basically Available
	∟可用性が高く常にサービスが利用可能（サーバ台数が多く頻繁に故障するがサービスは再実行して維持する）
Soft-State
	∟ステータスは厳密ではない（ここで一貫性の多くを妥協）
Eventual Consistency
	∟最終的には一貫性を担保する。結果整合性。（１サーバで更新されたあとに同期することで時間をおいてから一貫性が保たれる）


参照元
https://atmarkit.itmedia.co.jp/ait/articles/1703/01/news204_2.html
Pythonでプログラムの経過時間を図ってログを出してくれる便利なタイマー

プログラムの高速化のためにはtimeモジュールを使うのですが、いちいちコード打つのが面倒だし、ログも出してくれないかなとChatGPTくんに適当な仕様を出したらちょうど都合がいいのが出てきたので、それをもとに改良したコードを紹介します。ハードディスクの奥底に保存して、たまに引っ張り出すくらいなら共有してもらったほうが良いという感じで公開するので、もちろん著作権なんて主張しません。パブリックドメインです。好き勝手に使ってください。

```python:timer_class.py
import time

class Timer_class:
    def __init__(self, task):
        '''
        タイマーの開始時刻と終了時刻を格納する変数を初期化し、ログのファイル名を設定する
        '''
        self.start_time = None
        self.end_time = None
        self.task = task
        self.fime_name = "time_log.csv"

    def start(self):
        '''
        start_time 属性に現在時刻を保存することで、タイマーをスタートする
        '''
        self.start_time = time.perf_counter()

    def stop(self):
        ''''
        end_time 属性に現在時刻を保存することで、タイマーをストップする
        また、_log_elapsed_time 関数を呼び出す。

        '''
        self.end_time = time.perf_counter()
        self._log_elapsed_time()


    def _log_elapsed_time(self):
        '''
        経過時間のログをCSV形式で保存する
        '''
        import datetime
        
        #現在の時刻を取得する
        elapsed_time = self._elapsed_time()
        now = datetime.datetime.now()

        # 経過時間と現在時刻をフォーマットしてログメッセージを作成する
        log_message = f"{self.task},{elapsed_time:.6f},{now.strftime('%Y-%m-%d %H:%M:%S')}\n"
    
        # ログファイルにログメッセージを追記する
        with open(self.fime_name, "a") as f:
            # ファイルが空の場合は見出しを追加する
            if f.tell() == 0:
                f.write("タスク,経過時間(sec),時刻\n")
            f.write(log_message)
        
        #ログをコンソールに表示させる
        print(log_message, end="")

    def _elapsed_time(self):
        '''
        タイマーの開始時刻と終了時刻の差分を計算して、経過時間を返す
        '''
        if self.start_time is None:
            return 0
        elif self.end_time is None:
            return time.perf_counter() - self.start_time
        else:
            return self.end_time - self.start_time

```
使い方は次のように使います。
これだけ書けばだいたいおわかりかと思います。

```python:test.py

#クラスの宣言
timer = Timer_class("Aの動作時間")

#スタート
timer.start()

# 何らかの処理を実行する
# ...

#ストップ
timer.stop()

```

それでは。
ROSの基層（フォルダ編）

ワークスペースフォルダ
=
catkin_wsというフォルダ名が色んな教材、記事で出て来ますが、これはワークスペースの名前。ROS_wsでもよいですが、ワークスペースはROSの作業フォルダとして指定したものと考えればよい。workspaceを作成する時にしたにsrcフォルダを一緒に作成する必要がある。

srcフォルダ
=
~~~~~~~~~~~~~~~
cd ~/catkin_ws/src
catkin_init_workspace
~~~~~~~~~~~~~~~
コマンドにてCmakefileが作成される。正式に上位フォルダがワークスペースとして使えるようになり、ROSとしてビルトできるようになる。pkgは基本のフォルダに作成する。
~~~~~~~~~~~~~~
cd ~/catkin_ws
catkin_make
~~~~~~~~~~~~~~
コマンドにてビルトできる。ビルトするとワークスペースの下にbuild,develのフォルダが自動で生成される。これはビルト途中ファイルとビルトの結果実行ファイルを格納されたフォルダ。この中にbuildフォルダにあるsetup.bashファイルは環境設定bash。
~~~~~~~~~~~~~
source devel/setup.bash
~~~~~~~~~~~~~
コマンドにて環境設定を有効にできる。但し、ターミナル毎設定しないと行けないため、ワークスペースを決めていれば、ターミナルが開く際に自動で設定してしまえば、楽ですね。設定方法はhomeの下にある.bashrcファイルの中に下記コマンドを追加すればよい。
~~~~~~~~~~~~~
source ~/catkin_ws/devel/setup.bash
~~~~~~~~~~~~~

pkgフォルダ
=
プロジェクトのイメージ。
~~~~~~~~~~~~~
cd ~/catkin_ws/src
catkin_create_pkg learning_ROS std_msgs rospy roscpp
~~~~~~~~~~~~~
コマンドにてlearning_ROSというパッケージを作成できる。std_msgs rospy roscppは３つのペンディングとなる。pkg作成すると、learing_ROSフォルダができて、下に絵のように色々作成される。この中にpackage.xmlファイルの中身をチェックして置きましょう。中身はこのpkgの設定みたいなもん、どんなpkgか、どう言うようにビルトすればよいかを記述したものになる。

![Screenshot from 2023-05-08 10-19-05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3181208/3ae4b4d9-71c9-6c21-4c04-959788fed680.png)

msgフォルダ
=
topic通信用に定義した変数型

srvフォルダ
=
service通信用に定義した変数型

actionフォルダ
=
action通信用に定義した変数型

configフォルダ
=
configファイルを格納するフォルダ
gazeboコンフィグ、コントロールコンフィグなど

includeフォルダ
=
includeファイルを格納するフォルダ

launchフォルダ
=
実行ファイルを同時に複数実行するlaunchファイルを格納するフォルダ

scriptsフォルダ
=
実行できるpythonファイルを格納するフォルダ

memo
フォルダによく使われるコマンド：
rospack find pkg名　
例：インストールしたusb_camのlaunchファイルを直したいけど、そもそもパッケージがどこにインストールしただろうと思う時に
~~~~~~~~~~~~~~~~~
rospack find usb_cam
~~~~~~~~~~~~~~~~~
![Screenshot from 2023-05-20 21-19-17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3181208/6c313eef-e0a4-de41-f242-b80fd08585b9.png)

roscd pkg名
~~~~~~~~~~~~~~~~~~
roscd usb_cam
~~~~~~~~~~~~~~~~~~
![Screenshot from 2023-05-20 21-21-36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3181208/4b92256e-c014-160b-4597-1e02223ac5ee.png)
読書研修ーWebを支える技術　第８章ステータスコード

## ステータスコードの分類と意味
ステータスコードは 3 桁の数字であり、先頭の数字によって次の 5 つに分類されます。
| ステータスコード | 意味 | 説明 |
|:-:|:-:|:-|
| 1xx  | 処理中  |   クライアントはそのままリクエストを継続するか、サーバの指示に従ってプロトコルをアップデートして再送信する必要があり|
| 2xx  |  成功 |   |
| 3xx  | リダイレクト  | クライアントはこのステータスコードを受け取ったとき、レスポンスメッセージの Location ヘッダを見て新しいリソースへ接続する必要があり  |
| 4xx |  クライアントエラー | エラーを解消しない限り、同じリクエストをそのまま再送信することはできません。  |
| 5xx | サーバエラー  | サーバ側の原因が解決すれば、同じリクエストを再送信して正常な結果が得られる可能性があります。  |

## よく使われるステータスコード　9個
| ステータスコード | 意味 | ボディ | 関連メソッド | 補足：ヘッダーなど |
|:-|:-|:-|:-|:-|
| 200 OK |  リクエスト成功 |  GETの場合はリソースの表現、その他のメソッドなら、処理結果 |  すべて |   |
| 201 Created  |  リソースの作成成功 |新規作成されたリソースの表現、処理結果の説明   |  POST PUT | レスポンスヘッダ：Location  |
| 301 Moved Permanently  |  リソースの恒久的な移動 | 移動先のURIへのリンクを含んだHTMLなど  | すべて   |  レスポンスヘッダ：Location  |
|  303 See Other|  別のURIの参照 |  移動先のURIへのリンクを含んだHTMLなど   |  POST | レスポンスヘッダ：Location  |
| 400 Bad Request |  リクエストの間違い | エラー理由を説明する文書  |  すべて | 未知の４xx系が返ってきた場合、400と同じ扱い |
|  401 Unauthorized|  アクセス権不正 |  エラー理由を説明する文書 |  すべて |  リクエストヘッダ：Authorization; レスポンスヘッダ：WWW-Authenticate  |
|  404 Not Found| リソースの不在 | エラー理由を説明する文書  |  すべて |  |  
|  500 Interal Server Error|  サーバ内部エラー | エラー理由を説明する文書  |  すべて   |  未知の5xx系が返ってきた場合、500と同じ扱い |
|  503  Service Unavailable| サービス停止  |  エラー理由を説明する文書   |   すべて  |  レスポンスヘッダ：Retry-After |
## ステータスコードとエラー処理
<strong>通常のWebサービス</strong>では、404 Not Foundなどの場合、ボディには「ご指定のページは見つかりませんでした」というメッセージを含める
<strong>Web API</strong>では、クライアントがHTMLを解釈できない可能性があるため、HTMLでではなく、解釈可能な形式でエラーメッセージを返す必要があります。


#### プロトコルに従ったフォーマットでエラーを返し
AtomPubクライアントはAtom形式なら、解釈できる。

#### Accept
クライアントがAcceptヘッダーを送信している場合は、それに応じた形式でエラーメッセージを動的に変更できます。
たとえば、
~~~
Accept:application/xhtml+xml;q=0.9,text/plain;q=0.3
と指定された場合はHTML形式で、
Accept:application/atom+xml;q=0.9,text/plain;q=0.5
と指定された場合はAtom形式で返す
~~~



## ステータスコードの誤用
WebサービスでもWeb APIでも、HTTPステータスコードを正しく使用することは最低限のマナーです。しかし、一部のWebサービスやWeb APIでは、エラーを200 OKで返すことがあります。これは誤用であり、適切なエラーコードを使用する必要があります。
例えば、エラーが発生した場合に200 OKとこのWeb API固有のXML形式で返すAPIがある場合、通常のブラウザなどが200 OKと判断し、正常に処理されたと判断する可能性があるため、注意が必要です。 
~~~
リクエスト
GET /test HTTP/1.1 
Host:api.example.jp

レスポンス
HTTP/1.1 200 OK
Content-Type:application/xml

<error>
    <code>1001</code>
    <message>file not found</message>
</error>
~~~

## ステータスコードを意識して設計する
WebサービスやWebAPIを開発している場合、エラーが発生した場合に返すステータスコードは非常に重要な設計上の考慮事項です。重要なことは、正しいステータスコードの使用です

#### ステータスコードの具体的な実装方法
| 方法名 | 場合 | 方法 |
|:-:|:-|:-|
| Apache  | 静的なファイルを配信  |  配信するファイルの条件によって自動でステータスコードが決定 |
| サプレット  | WebサービスやWebAPIを実装  | HttpServletResponseクラスのsetStatus()メソッドやsetError()メソッドを使ってステータスコードを数値で設定してから、数値をハードコーディングするとソースコードがわかりにくくなるので、<br>各ステータスコードは、HttpServletResponseの定数フィールドとしてSC_OK(200)やSC_NOT_FOUND(404)のように定義されていて、これらを使う方がよい  |
| Ruby on Rails  |  WebサービスやWeb APIを実装する場合 | コントローラでrenderメソッドを使って結果をレンダリングする際に、引数としてステータスコードの数値を渡す  |
[Django] 管理画面のフォームにデフォルト値を設定する

## はじめに（前提）
- [Django公式チュートリアル](https://docs.djangoproject.com/ja/4.0/intro/tutorial01/)のソースを元にしています
- 管理画面側で作成した入力フォームに、デフォルト値として現在の日付を設定する方法をまとめています

## 記事の作成目的
- Django初心者の方向けのため
- 本情報を調べるのに時間がかかったため

## 実装の経緯
- 公式チュートリアルで、質問の公開日付フォームを非表示にした
  - フォームが非表示かつデフォルト値が未設定だと、入力を忘れてしまうことが多い
  - エラーメッセージが表示されるので致命的ではないが、やや面倒

## モデル
- Question
- Choice

## 実装

管理画面に指定のメソッドを追加する。現在日付をデフォルト値として表示

```python:Admin.py
class QuestionAdmin(admin.ModelAdmin):
    fieldsets = [
        (None, {"fields": ["question_text"]}),
        ("Date information", {"fields": ["pub_date"]}),
    ]
    inlines = [ChoiceInline]
    list_display = ("question_text", "pub_date")
    list_filter = ["pub_date"]
    search_fields = ["question_text"]

    """
    以下メソッドを追加
    引数requestは未使用だが、指定が必須
    """
    def get_changeform_initial_data(self, request = None):
        now = dateformat.format(timezone.now(), "Y-m-d")
        return {"pub_date": str(now)}
```

### 実際の表示
![スクリーンショット 2023-05-08 10.24.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2728622/6416c255-62d1-410e-7279-72aa97283797.png)

## 参考
- [Django公式ドキュメント](https://docs.djangoproject.com/en/4.2/ref/contrib/admin/#django.contrib.admin.ModelAdmin.get_changeform_initial_data)
- [[stackoverflow] How to format Django's timezone.now()
](https://stackoverflow.com/questions/57590142/how-to-format-djangos-timezone-now)

## 終わりに
- フォームにデフォルト値を設定したいだけだったが、想定より調査に苦労した
- もっと良い方法または別の方法が見つかり次第、更新予定
procとは？

# procとは?
procとは、ブロックをオブジェクト化したものを指します。


## ブロックとは
そもそもブロックとは、do~endや{~}）で囲まれたカタマリです。
１行の場合はdoブロックではなく{~}を使用します（以下の例では分かりやすいように一行で書けるコードもdoブロックで書いています。）
```
例１
numbers.each do |number|
  number*2
end

例２
numbers.each {|number| number*2}
```

## ブロックの呼び出し方
で、このブロックはいくつかの呼び出し方があります。

### callメソッドの場合
まずは一番基本形の形です。
ブロックを受け取るメソッドであることを引数"&block"で明示しています。
ちなに、この&というのはブロックをprocオブジェクトに変換しています。
```
#ブロックを受け取るメソッド
def certain_block(&block)
  block.call
end

#メソッドの引数としてブロックを渡し、実行する
certain_block do
  p "Hello, block!"
end
=> "Hello, block!"
```

### ブロック引数を渡し、yieldする場合
次に、ブロックをcallメソッドで呼び出す代わりに、"yield"を使用する場合です。
引数は"&block"のままです。
```
#ブロックを受け取るメソッド
def certain_block(&block)
  yield
end

#メソッドの引数としてブロックを渡し、実行する
certain_block do
  p "HelloWorld"
end
=> "HelloWorld"   
```

### ブロック引数を省略し、yieldする場合
で、次のパターンはなんと、引数の&blockを省略できます。
このパターンで書くことが多い気がしますが、基本形からこのような形になっていることは押さえておくと良いと思います。
```
#ブロックを受け取るメソッド
def certain_block
  yield
end

#メソッドの引数としてブロックを渡し、実行する
certain_block do
  p "HelloWorld"
end
=> "HelloWorld"   
```
TableViewでxibを表示 備忘録

![スクリーンショット 2023-05-07 15.02.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517291/5745f423-588f-46e9-9f51-0db6e23d1618.png)
![スクリーンショット 2023-05-07 15.01.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517291/1e89261f-1d29-0b16-46eb-0ea5bb1d309b.png)

```swift
import UIKit

class HistoryTableViewCell: UITableViewCell {
    @IBOutlet weak var contentsLabel: UILabel!
    @IBOutlet weak var dateLabel: UILabel!
    @IBOutlet weak var typeLabel: UILabel!
    
    func setupCell(contents: String, date: String, type: String) {
        contentsLabel.text = contents
        dateLabel.text = date
        typeLabel.text = type
    }
}
```

```swift

import UIKit

class HistoryViewController: UIViewController {

    @IBOutlet weak var tableView: UITableView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.register(UINib(nibName: "HistoryTableViewCell", bundle: nil), forCellReuseIdentifier: "HistoryTableViewCell")
        tableView.dataSource = self
        tableView.delegate = self
    }
    
}

extension HistoryViewController: UITableViewDelegate, UITableViewDataSource {
    
    // セクションの数
    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }
    
    // セクション内のセルの数
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 1
    }
    
    // セルの高さ
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 100
    }
    
    // セルの内容
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let inputCell = tableView.dequeueReusableCell(withIdentifier: "HistoryTableViewCell", for: indexPath ) as! HistoryTableViewCell
        inputCell.setupCell(contents: "aaa", date: "bbb", type: "ccc")
        return inputCell
    }
    
}

```
liff SDKの初期化時に起こったリダイレクトループを解消する

# はじめに

マウント時に、全てのページにおいて、liff.init()を行なっていました
だが、特定のページへのアクセス時にリダイレクトループが起こっていたので原因を調査しました

# 環境

liff v2.1
vue3

# 原因

* sessionStrageをclearしたことが原因でリダイレクトループが起こっていた

```liff.js
liff.init({ liffId: liffId })  // liff SDK初期化
```

liff SDKの初期化時、
・アクセストークン
・クライアントid
などの情報がセッションストレージへ保存されます

```sample.js
liff.init({ liffId: liffId })

if(sessionStorage) sessionStorage.clear()
```

マウント後に、他の実装の関係でセッションクリアを行なっていました

しかし、**セッションクリアした時にliff SDKの初期化時に保存されたデータも一緒にclearされていました**

そのため、liff SDK初期化時にはセッションストレージへ保存さているはずのデータが無いので
再度apiが叩かれることで、ループしていました

> 1.　ページへアクセス
2.　liff.init()によって取得したユーザー情報がsession strageへ保存される
3.　セッションクリア
4.　liff.init()の実行によって2次リダイレクト先へリダイレクト（同一ページ）
5.　session strage へユーザー情報がないので、再度、liff.init（）が実行される


https://developers.line.biz/ja/docs/liff/opening-liff-app/#redirect-flow

# 対応

* session.clearの条件を修正

```sample.js
if(sessionStorage.name) sessionStorage.removeItem('name');
```

元々、クリア対象だった項目(`name`)のみ sessionから削除しました
お初とライフゲームと試しに

![anime.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3360283/32389365-7234-7220-91f0-c783d2e28774.gif)
fortranでライフゲーム

```fortran
program main
  implicit none
  integer,parameter::r=50
  integer::p(r,r),pp(r,r)
  integer::x,y,i,j,count,t
  real*8::c
  character*3::num
  integer::seedsize
  integer,allocatable:: seed(:)
  call random_seed(size=seedsize)  
  allocate(seed(seedsize))         
  call random_seed(get=seed)
  

  open(21,file='count.dat',status='replace')
  do x=1,r
     do y=1,r
        call random_number(c)
        if(c < real(1d0/2)) then
           p(x,y)=1
        else
           p(x,y)=0
        end if
     end do
  end do

  open(11,file="001.dat",status='replace')
  do x=1,r
     do y=1,r
        write(11,'(3i3)')x,y,p(x,y)
     end do
  end do
  close(11)
  
  timeloop:do t=2,500
     do x=1,r
        do y=1,r
           count=0
           write(num,'(i3.3)')t
           if(p(x,y)==0) then
              do j=-1,1
                 do i=-1,1
                    !if(j/=0 .or. i/=0) cycle
                    if(j==0 .and. i==0) cycle
                    if(x+j<=0 .or. x+j>=r+1 .or. y+i<=0 .or. y+i>=r+1) cycle
                    if(p(x+j,y+i)==1) then
                       count=count+1
                    end if
                 end do
              end do
              if(count==3) then
                 pp(x,y)=1
              else
                 pp(x,y)=0
              end if
           end if

           if(p(x,y)==1) then
              do j=-1,1
                 do i=-1,1
                    !if(j/=0 .and. i/=0) cycle
                    if(j==0 .and. i==0) cycle
                    if(x+j<=0 .or. x+j>=r+1 .or. y+i<=0 .or. y+i>=r+1) cycle
                    if(p(x+j,y+i)==1) then
                       count=count+1
                    end if
                 end do
              end do
              if(count==2 .or. count==3) then
                 pp(x,y)=1
              else
                 pp(x,y)=0
              end if
           end if

        end do
     end do

     count=0
     do x=1,r
        do y=1,r
           if(p(x,y)==1)count=count+1
        end do
     end do

     

     write(21,'(2i10)')t-1,count
 

     open(11,file=TRIM(num)//".dat",status='replace')
     do x=1,r
        do y=1,r
           p(x,y)=pp(x,y)
           write(11,'(3i3)')x,y,p(x,y)
        end do
     end do
     close(11)
     
  end do timeloop
end program main
```
AstroでSvelteをつかってみた

Astroのアイランド機能を使ってSvelteを組み合わせた開発をつかってみました。使ってみた感想といくつか戸惑った箇所があったのでまとめてみました。
### @astrojs/svelte

https://docs.astro.build/ja/guides/integrations-guide/svelte/

## Astro+Svelteを使った理由

今回、AstroでSvelteを使った理由ですが、どちらもほどんど使ったことがなかったので同時に学べて学習効率がよさそうだと思い採用しました。

## 使ってみた感想

まず、AstroとSvelteの公式サイトにあるチュートリアルやドキュメントは非常に丁寧でわかりやすかったです。作成中に戸惑った箇所もありましたが、公式サイトのドキュメントを見ることで大体解決できました。
少しハマったポイントは下記になります。

### ページファイル

pageコンポーネント（ページファイル）を.svelteにすると404になってしまいました。pageコンポーネント（ページファイル）にできるのは、.astroや.mdなどのようです。

https://docs.astro.build/ja/core-concepts/astro-pages/#サポートしているページファイル

また、Svelteコンポーネント内からAstroコンポーネントを使用することもできません。このような点に注意する必要がありました。

```jsx:Svelteコンポーネントファイル
// 読み込めない
<script>
import MyAstro from "../components/MyAstro.astro";
</script>

<MyAstro />
```

### clientディレクティブ

AstroのpageコンポーネントからSvelteを読み込む際には、Svelteコンポーネント内でJavaScriptを使用している場合は、`client:*`のディレクティブを使用する必要があります。

```jsx:Astroページファイル
---
import MySvelte from "../components/MySvelte.svelte";
---

<MySvelte client:only="svelte" />
```

最初は、Svelteコンポーネント内に記述したJavaScriptが全く動かず、エラーも何も出なかったため、原因が全くわからなかったのですが、ハイドレートが必要なコンポーネントにはclientディレクティブの指定が必要であることがわかりました。これも公式サイトにしっかりと書かれていますね。

https://docs.astro.build/ja/core-concepts/framework-components/#インタラクティブなコンポーネント

## まとめ

公式ドキュメントをよく読んで、制限事項や問題点を事前に把握することが重要だと改めて痛感しました。
そして、AstroとSvelteを使った開発はとても柔軟で効率的であると感じました。以前は、静的なWebサイトをEJSを使用してヘッダー、フッターなどを分割して作っていましたが、Astroのような静的サイトジェネレーターを使うことで、より効率的に作業を進めることができると思いました。

今回はページ以外のコンポーネントはすべてSvelteで作成したので、最終的にSveltekitでいいのではと思ってきましたが、AstroとSvelteを同時に学ぶという目的は達成することができたのでOKとします！
GmailAPIを使用した最も基本的なメール送信

# この記事について
この記事は、GmailAPIを用いた最も一般的なメール送信について、忘れたとき用のために、私的に残しておくものになります。

# Client-Secretファイルのダウンロード
Google API Consoleにログインして、プロジェクトを選択します。
GmailAPIを有効にします。
左側のメニューで、「認証情報」をクリックします。
「認証情報を作成」をクリックし、「OAuth クライアントID」を選択します。
必要に応じて、アプリケーションの種類を選択して、必要な情報を入力します。
「作成」をクリックすると、JSONファイルがダウンロードされます。
JSONファイルをプロジェクトの適切なディレクトリに保存します。


# Tokenの取得について
前章で取得したクライアントファイルを準備してください。
（サンプルコードの中では、"client_secret.json"を使用しています）
まずは、token.jsonを取得します。
token.jsonは、Gmail APIを使用するためにOAuth 2.0認証フローを通過した後に、アクセストークンやリフレッシュトークンを保存するためのファイルです。
```python
from google_auth_oauthlib.flow import InstalledAppFlow

SCOPES = ['https://mail.google.com/']

flow = InstalledAppFlow.from_client_secrets_file(
   './client_secret.json', SCOPES)
creds = flow.run_local_server(port=0)

with open('token.json', 'w') as token:
   token.write(creds.to_json())
```
このコードを実行すると、ブラウザのOAuth認証画面が立ち上がり、対象のグーグルアカウントを選択して、認証をしてください。


# メール送信
上の章すべが終了したら、ようやく準備完了になります。
正しく処理ができているのなら、対象ディレクトリに"token.json"が生成されていると思います。
今回のプログラムは関数化して、呼び出し処理ができるようにしたいと思います。
### モジュールのインポート
```python
from google.oauth2.credentials import Credentials
from googleapiclient.discovery import build
from email.mime.text import MIMEText
import base64
```
### 文字列をbase64に変換する関数
``` python
def message_base64_encode(message):
    return base64.urlsafe_b64encode(message.as_bytes()).decode()
```

### メール送信用関数の作成
送信元のメールアドレスの部分は書き換えてください。
```python
def mail_post(mail_text, mail_to, title):
    scopes = ['https://mail.google.com/']
    creds = Credentials.from_authorized_user_file('token.json', scopes)
    service = build('gmail', 'v1', credentials=creds)

    message = MIMEText(f'{mail_text}')
    message['To'] = f'{mail_to}'
    message['From'] = '送信元のメールアドレス'
    message['Subject'] = f'{title}'

    raw = {'raw': message_base64_encode(message)}
    service.users().messages().send(
        userId='me',
        body=raw
    ).execute()
```

### メール送信用関数の実行
```python
mail_text = "メール本文の内容"
mailaddress = "example@example.com"#送信先のメールアドレス
mail_title = "メールのタイトル"
mail_post(mail_text, mailaddress, mail_title)
```

# すべての工程をまとめた、コード
tokenの取得は1箇所でまとまっているのでスキップします。

```python
from google.oauth2.credentials import Credentials
from googleapiclient.discovery import build
from email.mime.text import MIMEText
import base64

def mail_post(mail_text, mail_to, title):
    scopes = ['https://mail.google.com/']
    creds = Credentials.from_authorized_user_file('token.json', scopes)
    service = build('gmail', 'v1', credentials=creds)

    message = MIMEText(f'{mail_text}')
    message['To'] = f'{mail_to}'
    message['From'] = '送信元のメールアドレス'
    message['Subject'] = f'{title}'

    raw = {'raw': message_base64_encode(message)}
    service.users().messages().send(
        userId='me',
        body=raw
    ).execute()

mail_text = "メール本文の内容"
mailaddress = "example@example.com"#送信先のメールアドレス
mail_title = "メールのタイトル"
mail_post(mail_text, mailaddress, mail_title)
```

# 最後に
ファイルの送信や、HTML形式のメール送信などもできるので、参考にしてみてください

## 参考
[Gmail API の概要](URL "https://developers.google.com/gmail/api/guides?hl=ja")
Raspberry Piに静電容量式タッチディスプレイを接続する

# はじめに
本記事はRaspberry Piに静電容量式タッチディスプレイを接続する方法について記載しています。

タッチディスプレイを使用することで、ラズパイをタブレットのように使用することができます。

## 接続手順
本記事ではWaveshare社の[5inch DSI LCD](https://www.waveshare.com/wiki/5inch_DSI_LCD)を使用しています。

![写真 2023-05-04 22 55 06.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221759/f1230155-6ef3-b038-d234-349ead5bb095.jpeg)

### ハードウェア接続
箱を開けて中身の部品を取り出し、ディスプレイ本体、FFCケーブル、ネジが同梱されていることを確認します。

![写真 2023-05-04 22 56 09.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221759/d864d2c6-c5ba-b45a-fcae-eeee61e5f749.jpeg)

付属のFFC ケーブルを使用して、ディスプレイとRaspberry PiのDSI ポートを接続します。
接続する際は端子の向きが正しいことを確認します。

![写真 2023-05-05 21 28 43.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221759/860b7bcd-e58d-c9b3-adfa-f3c43259377d.jpeg)

Raspberry Piを固定するために、付属のネジで締めます。

![写真 2023-05-05 21 33 15.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221759/ee00151c-0bbb-6f8c-a870-6794b2cc352a.jpeg)

### ソフトウェア設定
`/boot/config.txt`ファイルを開き、以下の設定を追記します。

```config
dtoverlay=vc4-kms-v3d
dtoverlay=vc4-kms-dsi-7inch
```

設定を有効にするためには、設定変更後にRaspberry Piを再起動する必要があります。

:::note
dtoverlayの意味については、公式ドキュメントの[device-tree.adoc](https://github.com/raspberrypi/documentation/blob/develop/documentation/asciidoc/computers/configuration/device-tree.adoc)をご参照ください。
:::

### 動作確認
電源を投入して、Raspberry Piの画面が表示されることを確認します。

![写真 2023-05-05 22 13 06.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221759/f83e5d85-a624-4848-340d-6a021ca73693.jpeg)

# おわりに
小さいディスプレイは、初期セットアップなどディスプレイを必要とする工程で手軽に利用できるので、1台持っておくと便利だと思います。
QEMUにマシンを追加する(枠の追加)

- [ディレクトリ](#ディレクトリ)
- [Kconfig](#kconfig)
- [meson.build](#mesonbuild)
- [マシン実装](#マシン実装)
- [ビルド](#ビルド)
- [実行](#実行)

[事前準備編](https://qiita.com/t-yano-tryhard/items/4af976ec113bca3926f0)で環境の準備が整っているものとします。

今回は新規マシンを作成し、ビルドと起動まで行います。
作成するマシンは事前準備編で記載した通り[RZ/A3UL](https://www.renesas.com/jp/ja/products/microcontrollers-microprocessors/rz-mpus/rza3ul-powerful-1ghz-64-bit-mpus-rtos-support-enables-high-definition-hmi-and-quick-startup)とします。

# ディレクトリ
新規マシンは`hw/arm`配下に作成します。

# Kconfig
configを追加します。

hw/arm/Kconfig
```
config RZA3UL
    bool
    default y if TCG && ARM
    select I2C
    select SD
    select SERIAL
```

# meson.build
config有効時のコードを追加します。
hw/arm/meson.build
```
arm_ss.add(when: 'CONFIG_RZA3UL', if_true: files('rza3ul.c'))
```

# マシン実装
hw/arm/rza3ul.cにマシン情報を実装していきます。

```c
#include "qemu/osdep.h"
#include "qemu/units.h"
#include "hw/boards.h"
#include "sysemu/sysemu.h"


static void rza3ul_init(MachineState *machine) {
}

static void rza3ul_machine_init(MachineClass *mc)
{
    mc->desc = "Renesas RZ/A3UL";
    mc->init = &rza3ul_init;
    mc->ignore_memory_transaction_failures = true;
    mc->default_ram_size = 2048 * MiB;
    mc->default_ram_id = "ram";
}

DEFINE_MACHINE("rza3ul", rza3ul_machine_init)
```

`DEFINE_MACHINE`で定義したマシン名が起動時に指定するマシン名になります。

# ビルド
ビルドが通ることを確認します。
```
cd ../build
../qemu/configure --target-list=aarch64-softmmu --enable-debug
make
```

# 実行
実行できればOKです。
```
./qemu-system-aarch64 -M rza3ul
```

[QEMUにマシンを追加する(BL1動作)](https://qiita.com/t-yano-tryhard/items/a0bc5ae19cfce35b8f7d)に続きます。
SQLAlchemy: PostgreSQL のデータを削除 (Delete)

## プログラム

```py:postgres_delete.py
#! /usr/bin/python
#
#	postgres_delete.py
#					Jun/08/2024
#
# ----------------------------------------------------------------
import sys
#
from sqlalchemy import create_engine
from sqlalchemy.orm import declarative_base
from sqlalchemy import Column, Integer, String, DateTime, Sequence
from sqlalchemy.orm import scoped_session, sessionmaker
#
# ----------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
#
key_in = sys.argv[1]
print(key_in)
#
host='localhost'
# host='10.39.166.1'
data_base = 'city'
user ='scott'
password = 'tiger123'
db_url = "postgresql://" + user + ":" + password + "@" + host + "/" + data_base
engine = create_engine(db_url)
#
Base = declarative_base()
class City(Base):
	__tablename__ = "cities"
	id = Column(String(16), primary_key=True)
	name = Column(String(255))
	population = Column(Integer)
	date_mod = Column(DateTime)
#
session = scoped_session(
	sessionmaker(autocommit=False, autoflush=False, bind=engine)
)
#
city_a = session.query(City).filter_by(id=key_in).first()
if city_a != None:  
        session.delete(city_a)
        sys.stderr.write(key_in + " is deleted.\n")
session.commit()
#
sys.stderr.write("*** 終了 ***\n")
#
# ----------------------------------------------------------------
```

## 実行コマンド

```bash
./postgres_delete.py t3467
```

## 確認したバージョン

```text
$ python 
Python 3.12.3 (main, Apr 10 2024, 05:33:47) [GCC 13.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sqlalchemy
>>> sqlalchemy.__version__
'1.4.50'
```
SQLAlchemy: PostgreSQL のデータを更新 (Update)

## プログラム

```py:postgres_update.py
#! /usr/bin/python
#
#	postgres_update.py
#					Jun/08/2024
#
# ----------------------------------------------------------------
import sys
from time import localtime,strftime
#
from sqlalchemy import create_engine
from sqlalchemy.orm import declarative_base
from sqlalchemy import Column, Integer, String, DateTime, Sequence
from sqlalchemy.orm import scoped_session, sessionmaker
#
# ----------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
#
key_in = sys.argv[1]
population_in = int(sys.argv[2])
print("%s\t%d" % (key_in, population_in))
#
host='localhost'
# host='10.39.166.1'
data_base = 'city'
user ='scott'
password = 'tiger123'
db_url = "postgresql://" + user + ":" + password + "@" + host + "/" + data_base
engine = create_engine(db_url)
#
Base = declarative_base()
class City(Base):
	__tablename__ = "cities"
	id = Column(String(16), primary_key=True)
	name = Column(String(255))
	population = Column(Integer)
	date_mod = Column(DateTime)
#
session = scoped_session(
	sessionmaker(autocommit=False, autoflush=False, bind=engine)
)
#
try:
	city_a = session.query(City).filter_by(id=key_in).first()
    if city_a != None:
        city_a.population = population_in
        city_a.date_mod = strftime ("%Y-%m-%d",localtime ())
        sys.stderr.write(key_in + " is updated.\n")
except Exception as ee:
	sys.stderr.write(str(ee) + "\n")
session.commit()
#
sys.stderr.write("*** 終了 ***\n")
#
# ----------------------------------------------------------------
```

## 実行コマンド

```bash
./postgres_update.py t3468 89145700
```

## 確認したバージョン

```text
$ python 
Python 3.12.3 (main, Apr 10 2024, 05:33:47) [GCC 13.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sqlalchemy
>>> sqlalchemy.__version__
'1.4.50'
```
SQLAlchemy: PostgreSQL のデータを読む (Read)

## プログラム

```py:postgres_read.py
#! /usr/bin/python
#
#	postgres_read.py
#					Jun/08/2024
#
# ----------------------------------------------------------------
import sys
#
from sqlalchemy import create_engine
from sqlalchemy.orm import declarative_base
from sqlalchemy import Column, Integer, String, DateTime, Sequence
from sqlalchemy.orm import scoped_session, sessionmaker
#
# ----------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
#
host='localhost'
# host='10.39.166.1'
data_base = 'city'
user ='scott'
password = 'tiger123'
db_url = "postgresql://" + user + ":" + password + "@" + host + "/" + data_base
engine = create_engine(db_url)
#
Base = declarative_base()
class City(Base):
	__tablename__ = "cities"
	id = Column(String(16), primary_key=True)
	name = Column(String(255))
	population = Column(Integer)
	date_mod = Column(DateTime)
#
#
session = scoped_session(
	sessionmaker(autocommit=False, autoflush=False, bind=engine)
)
#
cities = session.query(City).all()
for city in cities:
	print(f'{city.id}\t{city.name}\t{city.population}\t{city.date_mod}')

sys.stderr.write("*** 終了 ***\n")
#
# ----------------------------------------------------------------
```

## 実行コマンド

```bash
./postgres_read.py
```

## 確認したバージョン

```text
$ python 
Python 3.12.3 (main, Apr 10 2024, 05:33:47) [GCC 13.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sqlalchemy
>>> sqlalchemy.__version__
'1.4.50'
```
SQLAlchemy: PostgreSQL のデータを作成 (Create)

Arch Linux で必要なライブラリーをインストール

```bash
sudo pacman -S python-sqlalchemy
sudo pacman -S python-psycopg2
```

## プログラム

```py:postgres_create.py
#! /usr/bin/python
#
#	postgres_create.py
#
#					Jun/08/2024
#
# --------------------------------------------------------
import	sys
import	string
#
from sqlalchemy import create_engine
from sqlalchemy.orm import declarative_base
from sqlalchemy import Column, Integer, String, DateTime, Sequence
from sqlalchemy.orm import scoped_session, sessionmaker
#
# --------------------------------------------------------
def dict_append_proc(dict_aa,key,name,population,date_mod):
	dict_aa[key] = {'name':name,'population':population,'date_mod':date_mod}
#
	return dict_aa
#
# --------------------------------------------------------
def	data_prepare_proc():
#
	dict_aa = {} 
#
	dict_aa = dict_append_proc (dict_aa,'t3461','広島',85376,'2003-9-24')
	dict_aa = dict_append_proc (dict_aa,'t3462','福山',47135,'2003-5-15')
	dict_aa = dict_append_proc (dict_aa,'t3463','東広島',28654,'2003-2-8')
	dict_aa = dict_append_proc (dict_aa,'t3464','呉',83152,'2003-10-9')
	dict_aa = dict_append_proc (dict_aa,'t3465','尾道',42791,'2003-8-4')
	dict_aa = dict_append_proc (dict_aa,'t3466','竹原',35687,'2003-1-21')
	dict_aa = dict_append_proc (dict_aa,'t3467','三次',81296,'2003-7-23')
	dict_aa = dict_append_proc (dict_aa,'t3468','大竹',25764,'2003-10-26')
	dict_aa = dict_append_proc (dict_aa,'t3469','府中',71423,'2003-12-15')
#
	return	dict_aa
#
# --------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
#
dict_aa = data_prepare_proc()
#
host ='localhost'
# host ='10.39.166.1'
data_base = 'city'
user ='scott'
password = 'tiger123'
#
db_url = "postgresql://" + user + ":" + password + "@" + host + "/" + data_base
engine = create_engine(db_url)
#
Base = declarative_base()
class City(Base):
	__tablename__ = "cities"
	id = Column(String(16), primary_key=True)
	name = Column(String(255))
	population = Column(Integer)
	date_mod = Column(DateTime)
#
#
session = scoped_session(
	sessionmaker(autocommit=False, autoflush=False, bind=engine)
)
#
City.__table__.drop(engine, checkfirst=True)
#
session.commit()
#
Base.metadata.create_all(bind=engine)
#
for key in dict_aa:
	print(key)
	unit = dict_aa[key]
	city_a = City(id=key, name=unit['name'], population=unit['population'], date_mod = unit['date_mod'])
	session.add(city_a)
#
session.commit()
#
sys.stderr.write("*** 終了 ***\n")
#
# --------------------------------------------------------
```

## 実行コマンド

```bash
./postgres_create.py
```

## 確認したバージョン

```text
$ python 
Python 3.12.3 (main, Apr 10 2024, 05:33:47) [GCC 13.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sqlalchemy
>>> sqlalchemy.__version__
'1.4.50'
```
Linuxの導入にAWS Cloud9を使おう！

# Linuxの導入について：AWS Cloud9を用いたメリットとデメリット

Linuxはオープンソースのオペレーティングシステムで、サーバーやクラウド環境で広く利用されています。本記事では、Linuxの導入にAWS Cloud9を使用するメリットとデメリット、およびそれぞれのおすすめポイントについて解説します。

## AWS Cloud9とは？

AWS Cloud9は、Amazon Web Services（AWS）が提供するクラウドベースの統合開発環境（IDE）です。Webブラウザ上でコーディング、デバッグ、実行を行うことができ、Linuxベースの仮想マシンが利用できます。

## AWS Cloud9を用いたLinux導入のメリット

1. **環境構築の手間が省ける**  
AWS Cloud9では、プリインストールされたLinux環境が提供されるため、手間をかけずに環境構築ができます。また、OSのアップデートやパッケージ管理も容易に行えます。

2. **ブラウザベースでアクセス可能**  
AWS Cloud9はブラウザベースのIDEであるため、インターネットに接続されたデバイスからいつでもどこでもアクセスできます。OSやデバイスの制約がなく、作業を進めることができます。

3. **複数人でのコラボレーションが容易**  
AWS Cloud9では、リアルタイムでの共同作業やコードの共有が可能です。これにより、チームでの開発やレビュー作業がスムーズに行えます。

4. **AWSとの連携が強力**  
AWS Cloud9は、AWSのサービスとシームレスに連携できるため、AWSを利用した開発作業が容易になります。

## AWS Cloud9を用いたLinux導入のデメリット

1. **インターネット接続が必須**  
AWS Cloud9はオンラインで動作するため、インターネット接続がない環境では利用できません。これは、オフラインでの作業ができないことを意味します。

2. **費用が発生する場合がある**  
AWS Cloud9は無料枠があるものの、利用状況や仮想マシンのスペックによっては費用が発生します。また、AWSとの連携を活用する場合、追加の費用がかかることがあります。

3. **プライベートな開発環境には不向き**
AWS Cloud9はクラウド上で実行されるため、セキュリティ上の懸念が生じる場合があります。特に機密性の高いプロジェクトや、企業内のプライベートな開発環境には適していない場合があります。

## LinuxおよびAWS Cloud9のおすすめポイント

1. **Linux：オープンソースで高い柔軟性とカスタマイズ性**
Linuxはオープンソースであり、コミュニティによってサポートされています。これにより、カスタマイズや最適化が容易で、多様なシナリオに対応できます。また、多くの企業や開発者がLinuxを使用しているため、情報やリソースが豊富に存在します。

2. **AWS Cloud9：効率的な開発環境の構築**
AWS Cloud9を使用することで、開発環境の構築やメンテナンスが簡単になります。ブラウザベースで利用できるため、複数のデバイスや場所からアクセスし、作業を進めることができます。

3. **AWS Cloud9：チームでのコラボレーション向上**
AWS Cloud9のリアルタイム共同作業機能を利用することで、チーム間のコミュニケーションやコードレビューが容易になります。これにより、チームの生産性や効率が向上する可能性があります。

## まとめ
結論として、LinuxとAWS Cloud9の組み合わせは、迅速かつ効率的に開発環境を構築し、チームでのコラボレーションを向上させるための優れた選択肢です。ただし、インターネット接続が必須であることや、費用面、セキュリティ上の懸念を考慮する必要があります。プロジェクトの要件や制約に応じて、LinuxとAWS Cloud9を適切に活用してください。
PostgreSQL に外部から接続する方法

## 前提
ローカルで接続できることを確認

パスワードなし

```text
$ psql -U scott city
psql (15.2 (Ubuntu 15.2-1))
Type "help" for help.

city=>
```

localhost を指定して

```text
$ psql -U scott city -h localhost
Password for user scott: 
psql (15.2 (Ubuntu 15.2-1))
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
Type "help" for help.

city=>
```

## トライ

<ol>
<li>そのまま外部から接続</li>


```text
$ psql -U scott  city -h 10.39.166.1
psql: error: connection to server at "10.39.166.1", port 5432 failed: Connection refused
	Is the server running on that host and accepting TCP/IP connections?
```

<li>/etc/postgresql/15/main/postgresql.conf を修正</li>

```text:/etc/postgresql/15/main/postgresql.conf
(省略)
listen_addresses = '*'
(省略)
```

```text
$ psql -U scott  city -h 10.39.166.1
psql: error: connection to server at "10.39.166.1", port 5432 failed: FATAL:  no pg_hba.conf entry for host "10.39.166.61", user "scott", database "city", SSL encryption
connection to server at "10.39.166.1", port 5432 failed: FATAL:  no pg_hba.conf entry for host "10.39.166.61", user "scott", database "city", no encryption
```

<li>/etc/postgresql/15/main/pg_hba.conf を修正</li>

```text:/etc/postgresql/15/main/pg_hba.conf
(省略)
host    all             all             0.0.0.0/0            trust
(省略)
```

```text
$ psql -U scott  city -h 10.39.166.1
psql (15.2)
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
Type "help" for help.

city=>
```

<ol>
force:showToast イベントを使う

<aura:handler event="force:showToast" action="{!c.reload2}"/>

```
{
"mode":"dismissible",
"duration":3000,
"type":"success",
"message":"{0} {1} が保存されました。",
"messageTemplate":"{0} {1} が保存されました。",
"messageTemplateData":["展示会来場者管理","\"1111\""]
}
```
neosでlogix その139

# 概要
neosでlogixやってみる。
Get Texture 2D Pixelノード
Get Texture 2D UVノード
Get Texture 2D formatノードを使ってみる。



# 写真

![2023-05-07 22.08.02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/6395840b-a2ab-6125-2634-b3f00166443f.jpeg)

# ポイント

statictexture2dコンポーネントのReadable と uncompressionに、チェックを入れる。


以上。
モデル駆動アプリ ファイルアップロードでテーブルデータを更新する

**テーブルエータ更新**

モデル駆動アプリからDataverseテーブルデータの全てもしくは一部を更新する。
今回は特定の列データを更新するケースを記す。

空欄だったセルに、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3289762/d2bc5753-760e-82c6-28d3-a064a8981ae5.png)

データを入力する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3289762/aacf08bb-6258-9658-105d-39a052c989ef.png)

**更新の方法**
CSVファイルに「キーとなる列」と「更新したいデータを入力する列」を作成する。
1行目に記入する列名は任意。インポート作業の際、列マッピングでDataverse側の列名と突き合わせることができるため、同じ列名での作成は必須ではない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3289762/73aba1bb-924e-48ce-539a-d5e6f6d40031.png)

モデル駆動アプリの更新対象ビューで右上の3点リーダーから、「Excelからのインポート」⇒「CSVからのインポート」を押下。
ファイルを選択、キー設定、マッピングの操作をすればインポートできる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3289762/35c17542-aaf4-8c81-704c-0b18f5c6af65.png)

作業完了。

CSVファイル作成の補足。
ビュー右上の3点リーダーからデータのエクセルエクスポートし、キーとなるデータを持ってくると便利。
ジェネレティブAI(ChatGPT&LLM)とフェイルセーフ

昨今世の中では、ジェネレティブAI(LLM)の登場により、シンギュラリティの到来が早まったと言われてます。
その結果、AIが人間を超えることへの懸念の話が広がっています。

ジェネレティブAIを色々なサービスに活用できます。例えば医療に利用する場合は、命に関わる間違った診断になってしまう事もあると思います。その場合はフェイルセーフに動く様に設定する事は可能でしょうか？
僕は、AIへの懸念に対してこう思います。

# TL; DR
この記事は、ジェネレティブAI(LLM)の登場により、シンギュラリティの到来が早まったと言われてる事に対して、AIが人間を超えることへの懸念の話の記事です。

# 本文
##　シンギュラリティの到来で何故AIが心配なのか
シンギュラリティとは、人工知能やテクノロジーの進歩が指数関数的に進むことによって、人類の文明や社会が根本的に変化するとされる仮説的な未来のことを指します。

AIが心配される理由は、シンギュラリティによってAIが人間を超え、自己進化的に発展し、人間を支配する可能性があるためです。AIが自己進化すると、そのスピードは人間の進化よりもはるかに速く、AIが想像力や創造力、学習能力などの面で人間を上回ることが予想されています。

このような状況下では、AIが人間を支配することになり、人間の生存や自由、尊厳が危機にさらされる可能性があります。また、AIが倫理的な判断を行うことができない場合、人間を傷つけるような行動を取る可能性もあるため、倫理的な問題も心配されています。

## 例えば、AIの倫理的な判断とは例えばどんな事か？
AIの倫理的な判断とは、AIが人間の生活や社会に影響を与える決定を行う際に、倫理的な価値観を考慮に入れることを指します。AIは、プログラムされたルールに基づいて行動をするため、倫理的な判断を行うことができません。そのため、AIに倫理的な判断を行わせるために、人間がAIの開発や運用において、倫理的なガイドラインを設定する必要があります。

以下は、AIの倫理的な判断に関連する例です。

公正性の確保：AIが人々に公正に接することを保証するために、データの偏りやバイアスを取り除く必要があります。例えば、AIが面接選考を行う場合、過去の選考結果に偏りがあった場合に、その偏りを取り除くための措置を講じる必要があります。

プライバシーの尊重：AIが人々のデータを収集・利用する場合、プライバシーを尊重するために、適切な情報の収集・利用を行う必要があります。例えば、健康データなど、特定の個人情報を扱う場合には、厳格なセキュリティ対策を講じる必要があります。

人間らしさの維持：AIが人間の代わりに行う作業が増えると、人々がAIと接することが多くなります。そのため、AIが人間らしい対応を行うために、感情や思考の模倣、相手の感情や状況を考慮した対応などが必要になってきます。

安全性の確保：AIが自己進化的に学習する場合、安全性を確保するために、AIの学習や意思決定に人間が関与する必要があります。また、AIが危険を引き起こす可能性がある場合には、そのリスクを最小限に抑えるための対策を講じる必要があります。

## フェイルセーフとは
フェイルセーフとは、システムやプログラムなどが異常な状況に陥った際に、それが重大な問題を引き起こすのを防ぐための仕組みや機能のことを指します。具体的には、システムやプログラムが想定外の状況に陥った場合に、自動的に安全な状態に移行する仕組みや、問題が発生した場合に早期に警告を発する仕組みなどが挙げられます。

フェイルセーフは、コンピューターシステムや自動車、航空機、原子力発電所など、安全性が重要視される様々な分野で使用されています。これらの分野では、システムの異常が重大な事故につながる可能性があるため、フェイルセーフ機能を備えることが求められます。

## AIとフェイルセーフの組み合わせが良いのでは？

AIとフェイルセーフの組み合わせは、重要なシステムやプロセスにおいて非常に有用です。フェイルセーフとは、システムやプロセスに何らかの問題が発生した場合に、その影響を最小限に抑えるための仕組みです。一方で、AIは多くの場合、大量のデータを処理し、複雑な問題に対して高度な判断を行うことができます。

AIとフェイルセーフの組み合わせにより、以下のようなメリットがあります。

### 安全性の向上：
AIが重要な決定を行う場合に、フェイルセーフの仕組みを導入することにより、システムの安全性を向上させることができます。例えば、自動運転車の場合、AIが運転を行う際に、フェイルセーフの仕組みを導入することにより、車両の安全性を確保することができます。

### 問題の早期発見：
AIが動作するシステムに問題が発生した場合、フェイルセーフの仕組みを導入することにより、問題を早期に発見することができます。例えば、製造ラインにおいて、AIが品質管理を行う場合、不良品を検出した場合に、自動的にラインを停止する仕組みを導入することにより、不良品の量を最小限に抑えることができます。

### 性能の向上：
AIがシステムに組み込まれた場合、フェイルセーフの仕組みを導入することにより、システムの性能を向上させることができます。例えば、AIが電力供給管理を行う場合、フェイルセーフの仕組みを導入することにより、停電や過電流などの問題を最小限に抑えることができます。

# まとめ
ジェネレティブAIを医療分野で活用する場合、フェイルセーフの設計が非常に重要になります。特に、誤った診断を行う可能性がある場合は、フェイルセーフの実装によって、そのリスクを最小限に抑える必要があります。

例えば、ジェネレティブAIを使って医療画像を解析する場合、AIが誤った診断を出した場合には、人間の医師による確認が必要となります。このような場合には、フェイルセーフとして、AIによる診断結果を自動的に医師に通知するシステムを導入することができます。

また、ジェネレティブAIの訓練データに偏りがある場合、誤った診断が出る可能性があるため、フェイルセーフとして、適切なデータセットの選択や、AIの訓練データを正確にラベル付けするための人間の監視などが考慮される必要があります。

総じて、ジェネレティブAIを使用する際には、適切なフェイルセーフの実装が必要になります。このような設計によって、誤った診断などのリスクを最小限に抑え、ジェネレティブAIをより安全に利用することができます。

# 最後に
エンジニアの皆さん、エンジニア未経験の皆さん、若手エンジニアの皆さん、勉強方法について悩みがあればなんでも気軽に質問して下さい！
これからも記事を書いていきますので、モチベーションアップのためフォロー、イイねお願いします。
2023/5/8主にITとかセキュリティの記事

「ETCご利用者様へ大切なお知らせ」←サギ！ 超巧妙なフィッシングメール横行 でもよく見るとヘン？(5/6)
https://news.yahoo.co.jp/articles/26cca51283d8424d92dd37fc8472de492231a349?source=rss

「身に覚えのない2千円」はクレカ不正利用だった　少額で被害に気づかない？最新の手口とは〈dot.〉(5/6)
https://news.yahoo.co.jp/articles/7d8229ea25b827e5920f76617d8d6e22789c1726

公文書管理システムの大量ファイル消失事故についてまとめてみた(5/6)
https://piyolog.hatenadiary.jp/entry/2023/05/06/014208

韓国選管「北のハッキング攻撃、通告受けていない」…国家情報院が「8回通告」資料公開【独自】(5/5)
https://www.chosunonline.com/site/data/html_dir/2023/05/05/2023050580038.html

ウクライナとアメリカが9つの仮想通貨取引所を閉鎖(5/5)
https://nextmoney.jp/?p=58315

【ＡＩのルール】国際論議さらに深めたい(5/6)
https://www.kochinews.co.jp/article/detail/648439

覚えておきたい企業のAI導入を支援する国や自治体の補助金制度(5/6)
https://dime.jp/genre/1584845/