OmniAICreator/Qiita-1.07M huggingface dataset:
Pythonで画像ファイルのIPTCを更新する（pyexiv2）

## はじめに

先日、Pythonのpyexiv2を使って、複数の画像ファイルにつけたIPTCのキーワードを集計するという記事を書きました。

https://qiita.com/st10/items/5ae77fd5393365cce42a

当初は、キーワードの集計ができたところでよしとしていたのですが、キーワードの更新もやってみようと思い、試してみました。

## 環境

* OS: Windows 11 Home 22H2
* Python: 64ビット版、3.11.4

## インストール

* pip install pyexiv2

## IPTC情報のうち、キーワードを更新する

サンプルの画像ファイルからIPTCのキーワードを取得して、取得したキーワードの末尾に現在日時の文字列を追加するという処理を行っています。

キーワードに限らず、更新したい要素の値を作り込み、「要素名: 値」で辞書を作成、作成した辞書をmodify_iptc()メソッドで更新するという流れになります。

```python
import pyexiv2
import datetime
import pprint

# JPEGファイルを読み込む
img = pyexiv2.Image(r'.\sample.jpg')

# IPTC情報を取得する
iptc_current = img.read_iptc()

# pprintで各データを表示する
print('## IPTC情報、キーワード更新前')
pprint.pprint(iptc_current)
print()

# キーワードに追加するための現在日時の文字列。
now_str = datetime.datetime.now().strftime('%Y/%m/%d %H:%M:%S')

# iptcのキーワードを操作する
# Iptc.Application2.Keywordsが存在しているかどうかの確認が必要
if 'Iptc.Application2.Keywords' in iptc_current:
    # キーワードが存在していたら、現在のキーワードを取得して、現在日時をキーワードに追加する
    keywords = iptc_current.get('Iptc.Application2.Keywords')
    keywords.append(now_str)
else:
    # キーワードが存在していなかったら、現在日時を値としてキーワードを設定する
    keywords = [now_str]

# 更新用のキーワードの辞書を作る
update_keywords = {'Iptc.Application2.Keywords': keywords}

# 辞書を引数にしてmodifyを実行して、キーワードを更新する
img.modify_iptc(update_keywords)

# 更新後の画像からIPTC情報を取得する
iptc_modified = img.read_iptc()

# キーワードを修正した後のIPTC情報を表示する
print('## IPTC情報、キーワード更新後')
pprint.pprint(iptc_modified)
print()

# クローズ処理
img.close()

```

## 結果

キーワードに現在日時を追加することができました。

```
## IPTC情報、キーワード更新前
{'Iptc.Application2.DateCreated': '2022-02-23',
 'Iptc.Application2.Headline': '冬のダム',
 'Iptc.Application2.Keywords': ['2月', '冬', '雪', 'ダム', '雪景色', '青空', 'サンプル'],
 'Iptc.Application2.RecordVersion': '4',
 'Iptc.Application2.TimeCreated': '10:41:18+00:00',
 'Iptc.Envelope.CharacterSet': '\x1b%G'}

## IPTC情報、キーワード更新後
{'Iptc.Application2.DateCreated': '2022-02-23',
 'Iptc.Application2.Headline': '冬のダム',
 'Iptc.Application2.Keywords': ['2月',
                                '冬',
                                '雪',
                                'ダム',
                                '雪景色',
                                '青空',
                                'サンプル',
                                '2023/09/25 23:41:39'],
 'Iptc.Application2.RecordVersion': '4',
 'Iptc.Application2.TimeCreated': '10:41:18+00:00',
 'Iptc.Envelope.CharacterSet': '\x1b%G'}
```

## 要素を消す方法

IPTCの要素自体を消すには、「要素名: None」という辞書を作って、作成した辞書をmodify_iptc()メソッドで更新します。

以下はキーワードを空にする例です。

```python
# iptcのキーワードを空にするため、Noneを値にした辞書を作る
keywords_none = {'Iptc.Application2.Keywords': None}

# 辞書を引数にしてmodify実行
img.modify_iptc(keywords_none)
```
OpenFOAMのSutherlandの熱伝導度

# Sutherlandの熱伝導度
ずっと謎だったSutherlandのところにある熱伝導度の式。OpenFOAM８だと下のような感じ。1.32とかの係数が謎でした。

```
template<class Thermo>
inline Foam::scalar Foam::sutherlandTransport<Thermo>::kappa
(
    const scalar p,
    const scalar T
) const
{
    scalar Cv_ = this->Cv(p, T);
    return mu(p, T)*Cv_*(1.32 + 1.77*this->R()/Cv_);
}
```

# オイケンの修正式というらしい。
「物性推算法」大江，データブック出版社を見ていてわかりました。単成分気体の熱伝導度のところにありました。

```math
\lambda=\frac{\eta}{M}(1.32Cv+3.52)
```

λは熱伝導度で，ηは粘性係数。似てる。ただ，3.52ってなんだとなりました。これも罠がありました。これは気体定数Rに係数をかけた値でした。Rが単位がcal/molKで，R=1.988というくせもの。

3.52=1.77x1.988=1.77Rでした。

というわけで，OpenFOAMのSutherlandで出てくる熱伝導度はオイケンの修正式によるものです。
Spring AI フレームワークを触ってみた

# Spring AI フレームワークを触ってみた

某ワークショップに参加したとき、Spring を使った Azure Open AI を使ったサンプルがあったのですが、ソースをみていると Spring Framework 自身が Open AIに対応しつつあるようなので触ってみました。

このあたり [Spring AI :: Spring AI Reference](https://docs.spring.io/spring-ai/reference/index.html)  あたりの話だと思います。

実験的な機能で今後変わる可能性がありますので、ご注意ください。

## 事前準備

手順にならって、 Spring CLI を使って準備をしますが、まずは Spring CLI をセットアップします。

以下で、`git clone` してビルドします。

```sh
git clone https://github.com/spring-projects-experimental/spring-cli $HOME/temp/spring-cli
cd $HOME/temp/spring-cli
./gradlew clean build -x test
```

以下で、`alias` をつけておきます。
```sh
alias spring='java -jar $HOME/temp/spring-cli/build/libs/spring-cli-0.0.1-SNAPSHOT.jar'
```

## プロジェクト作成

`spring boot new` で `ai-azure` というプロジェクトを作成し、`spring boot add` で、Azure Open AI の依存関係を追加します。

```sh
spring boot new ai-azure
cd ai-azure
spring boot add ai-azure
```

その後 `pom.xml` に以下を追加します。追加しないとAI関連のライブラリが見つからないでしょう。

```xml
	<repositories>
		<repository>
			<id>spring-snapshots</id>
			<name>Spring Snapshots</name>
			<url>https://repo.spring.io/snapshot</url>
			<releases>
				<enabled>false</enabled>
			</releases>
		</repository>
	</repositories>
```

### ソースなど

`spring boot add` で AI関連のライブラリの他に、`/ai/simple` というエンドポイントが追加されます。
`aiClient` は、コンストラクタでDIされるので、それを使って呼び出しているだけのいたってシンプルなのです。

```java

    @GetMapping("/ai/simple")
    public Completion completion(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
        return new Completion(aiClient.generate(message));
    }
```

### 実行

以下の環境変数を設定します。

```sh
export SPRING_AI_AZURE_OPENAI_API_KEY=APIキー
export SPRING_AI_AZURE_OPENAI_ENDPOINT=https://your-env.openai.azure.com/
export SPRING_AI_AZURE_OPENAI_MODEL=gpt-35-turbo
```

そして実行します

```
mvn spring-boot:run
```

とりあえず、デフォルト値も設定されているので、なにも指定せずに呼び出してみます。
```sh
curl http://localhost:8080/ai/simple
{"completion":"Why don't scientists trust atoms?\n\nBecause they make up everything!"}
```

英語のジョークはよく分からないので、日本語で試してみます。

```sh
curl --get --data-urlencode 'message=ジョークを教えて' http://localhost:8080/ai/simple
```

レスポンス（整形済み） は毎回異なると思いますが、以下のような感じになります

```json
{
  "completion": "もちろんです！以下にジョークをお届けします：\n\n1. 「なぜゴリラは木から落ちないの？」\n「木の上でバナナを食べているからです！」\n\n2. 「なぜ魚はバンドを組むことができないの？」\n「スケールがないからリーダーがいないんです！」\n\n3. 「どうしてサーファーはバナナを食べるの？」\n「波を食べるためです！」\n\n4. 「なぜテニスコートはきれいにならないの ？」\n「いつもラケットが上手く掃除できないんです！」\n\n5. 「なぜピアノは泣いているの？」\n「黒鍵が白鍵にいじめられてい るからです！」\n\nどうでしたか？楽しんでいただけましたでしょうか？もしご希望があれば、もっとジョークをお届けしますのでお知らせください！"
}
```

ほぼ数行でAzure Open API を呼び出すことができて、ちょっと簡単すぎますね。`org.springframework.ai.client.AiClient` はもう少し色々機能がありそうなので、試してみていこうと思います。

以上
Laravel10でAutocomplete(自動補完)させる時に調べたこと

## はじめに

- TailwindCSS とか新しいフレームワーク使いたいけど、  
まだまだ、Bootstrap のほうが慣れてるよっていう状況です

そこから選択肢をいろいろ調査しました

## 事前調査

- 最近はHTML5で登場した`datalist`を使うようになっている
    - Bootstrapでも`datalist`を一応サポートしている風な雰囲気
- `Bootstrap-3-Typeahead`という以前からあるライブラリが存在する

というところまで

## 参考資料

https://getbootstrap.jp/docs/5.0/forms/form-control/#datalists

https://github.com/bassjobsen/Bootstrap-3-Typeahead

## 事前準備

- 対象となるModelは実装済み

## 手順

1. サーバーのレスポンス

    とりあえずJSON形式で返しておけばなんとかなる

    ```php:例
    class AutocompleteController extends Controller
    {
        public function __invoke(Request $request)
        {
            // 入力した文字を受け取って
            $query = $request->get('query');
            // 検索
            $data = empty($query) ?
                User::all() :
                User::where('name', 'LIKE', '%'. $query. '%')->get();
            // JSONで返す
            return response()->json($data);
        }
    }
    ```

2. フロントの動作

    1. `datalist`を利用する場合は`onkeypress`イベントとかに`Option`を更新または作り直す処理を追加する

    2. `Bootstrap-3-Typeahead`の場合  
        ```javascript:bladeの例
        $('#input').typeahead({
            minLength: -1, // 空文字でも検索できるように
            source: (query, process) => 
                $.get("{{ route('autocomplete') }}", 
                    { query: query },
                    (data) => process(data)),
        });
        ```

## おまけ

### inputのautocomplete属性

https://developer.mozilla.org/ja/docs/Web/HTML/Attributes/autocomplete

- これはブラウザがいままでの入力を元に補完するための属性
    - 決まったルールもあるっぽい
        ```html
        <!-- メールアドレス -->
        <input type="text" autocomplete="email">

        <!-- 氏名 -->
        <input type="text" autocomplete="username">

        <!-- 
            その他、たくさんある
         -->
        ```

## おわりに

そもそもスマホの普及により、この手のAutocompleteが使われなくなっている
しかし、パソコンでアクセスすることが多いサービスの場合は便利
[Typescript] as constの活用

## Literal Union の検証

ユニオンタイプは多分Typescriptで一番よく使われるタイプの一つだと思います。色んなタイプを組み合わせてマージされた形ですが、特定の変数が色んな形のタイプを持つ場合、便利に使うことができます。

特に、Mapped Typeを定義する時、keyのタイプをユニオンで指定することはよくあることです。

ただ、このユニオンタイプには一つの問題があり、それは特定の変数が特定のユニオンに属するかどうかを直接的に検証することができないということです。

しかし、もしユニオンがリテラル型で構成されている場合、as const を使ってこの問題を解決することができます。

```ts
type Fruit = 'apple', 'banana', 'grape';
```
このようなユニオンがあるとする。

まず、このユニオンに属するリテラル型を配列にします。 そして、この配列の後ろに as const を付けて、要素を read-only な状態にします。

```ts
const fruitList = ['apple', 'banana', 'grape'] as const;
```
完成された配列を持ってlookup typeを使ってユニオンを新しく定義することができます。lookup typeが分からない場合はこの[リンク](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html)を参考してください。

```ts
const fruitList = ['apple', 'banana', 'grape'] as const;

type Fruit = typeof fruitList[number];
```
これで `fruitList` を利用して type guard を実装できるようになりました。

```ts
function isFruit(val: any): val is Fruit {
  if (fruitList.includes(val)) return true;
  return false;
}
```

## Object Literal での活用

下記のような object があるとします。

```ts
const capitals = {
  japan: 'tokyo',
  korea: 'seoul',
  china: 'beijing',
}
```
この object の value を引数として受ける関数を作りたい場合はどうすればいいでしょう。

```ts
const capitals = {
  japan: 'tokyo',
  korea: 'seoul',
  china: 'beijing',
}

function goAbroad(
  from: 'tokyo' | 'seoul' | 'beijing',
  to: 'tokyo' | 'seoul' | 'beijing'): string {
  ...
}
```
このように一つ一つ書く方法もありますが、この方法があまり満足できないことは誰もが知っているでしょう。

ここでも as const が輝きます。

```ts

const capitals = {
  japan: 'tokyo',
  korea: 'seoul',
  china: 'beijing',
} as const

type Capital = typeof capitals[keyof typeof capitals]
// Capital === 'japan' | 'korea' | 'china'

function goAbroad(from: Capital, to: Capital): string {
  ...
}
```

どういうことが起こっているのか説明しますと、まずtypeof capitalsは次のようなタイプを返すことになります。

```ts
type typeOfCapitals = typeof capitals;
// type typeOfCapitals = {
//    readonly japan: "tokyo";
//    readonly korea: "seoul";
//    readonly china: "beijing";
// }
```
ここに keyof をつけると、次のような値が得られます。

```ts
type keyOfTypeOfCapitals = keyof typeof capitals;
// type keyOfTypeOfCapitals = 'japan' | 'korea' | 'china'
```
これで、上で説明した lookup type を利用した方法で再びユニオンを作ることができます。

```ts
type keyOfTypeOfCapitals = keyof typeof capitals;
type Capital = typeof Capital[keyOfTypeOfCapitals];
// Capital === 'tokyo' | 'seoul' | 'beijing'
```
Android Studio: Basic Views Activity を使う

テンプレート Basic Views Activity を使います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/8aa36482-94f8-e405-e972-5c57e880ffe3.png)

app/src/main/res/values/strings.xml を編集

```xml:app/src/main/res/values/strings.xml
<resources>
    <string name="app_name">example02</string>
    <string name="action_settings">Settings</string>
    <!-- Strings used for fragments for navigation -->
    <string name="first_fragment_label">First Fragment</string>
    <string name="second_fragment_label">Second Fragment</string>
    <string name="next">Next</string>
    <string name="previous">Previous</string>

    <string name="lorem_ipsum">
 ある猫がはつかねずみと知り合いになり、
        猫がねずみに、あなたをとても好きだし友達になりたいんだ、
        としきりに言ったので、
        とうとうねずみは猫と一緒に暮らし家事をすることを承知しました。
        「だけど、冬に備えなくてはいけないね。
        そうしないとひもじい思いをするよ。」と猫は言いました。
        「それでネズミくん、君はあちこち出歩けないよ。
        そうしないといつか罠にかかるだろうからね。」\n\n

        親切な忠告に従い、一壺の脂肪を買いましたが、
        その壺をどこに置いたらいいかわかりませんでした。
        だいぶ考えた後、とうとう猫が、
        「それをしまっておくのに教会よりもよい場所はわからないね。
        だってそこからは誰もものをとっていかないからな。
        祭壇の下に壺を置いて、
        本当に困るまでそれに触らないでおこうよ。」と言いました。\n\n

        それで壺は安全な場所に置かれましたが、まもなく、
        猫はそれがとても欲しくなり、ねずみに言いました。
        「ネズミくん、話したいことがあるんだ。いとこが息子を産んで、
        僕に名付け親になってもらいたいと頼んでるんだよ。
        その子は白に茶色のぶちで、
        洗礼のとき洗礼盤の上で抱くことになっているんだ。
        今日は出かけさせてくれ。それで君だけでうちのことをやってくれ。」
        「ええ、ええ。」とねずみは答えました。
        「もちろん行ってください。
        それでなにかとてもおいしいものをもらったら、
        私のことを思い出してくださいね。
        甘い洗礼の赤ワインを一滴私も飲みたいわ。」\n\n

    </string>
</resources>
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/55126300-f8a0-b8f2-a535-1e0177192a68.png)

## Run 'app'
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/f921b5eb-b374-2391-040e-2c7800a7fe15.png)

## Build APK(s)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/bce76f91-be7f-7d2e-a2ae-1618842bee6a.png)

## 実機で実行した結果
APK ファイルを USB で実機に持っていって、インストールします。
![android_template.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/61dbdd7e-9756-b749-8e73-cd7dfc398367.jpeg)
[初心者]Vue Routerを使用してルーティングを実装する

# はじめに
今回、Vue3とVuetifyを使用してフロント画面の実装をしてみたくなったので、その際に必要だったルーティングを調べたりしました。



### Vue Routerのインストール
Vue Routerをインストールします。
(Vue CLIを使用してプロジェクトを作成した場合Vue Routerはデフォで含まれているらしいです。)
```
$ npm install vue-router
```
プロジェクトのルートディレクトリにrouterというディレクトリを作成し、その中にindex.jsというファイルを作成します。
src/router/index.jsの感じです。

components配下にHome.vueとHoge.vueというファイルを作成しそれぞれのパスを指定します。

``` js:index.js
import { createRouter, createWebHistory } from "vue-router";
import Home from "../components/Home";
import Hoge from "../components/Hoge"; 

const routes = [
  {
    path: "/",
    name: "Home",
    component: Home,
  },
  {
    path: "/hoge",
    name: "Hoge",
    component: Hoge,
  },
];

const router = createRouter({
  history: createWebHistory(),
  routes,
});

export default router;
```

次にmain.jsにルーティングの設定をインポートします。
```js:main.js
import { createApp } from "vue";
import App from "./App.vue";
import vuetify from "./plugins/vuetify";
import { loadFonts } from "./plugins/webfontloader";
import router from "./router/index"; // Vue Routerの設定をインポート

loadFonts();

createApp(App).use(vuetify).use(router).mount("#app"); //.use(router)を追加
```
そしてApp.vueをいじります

```vuejs:App.vue
<template>
    <Header />
    <router-view /> //追記
</template>

<script setup>
import Header from "./components/Header.vue"; 
</script>
```
最後にクリックした時に想定したページに飛ぶように設定していきます。
ヘッダーcomponents配下に作成します。
イメージ
![スクリーンショット 2023-09-29 14.26.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1462552/2642dcb5-dd34-25c3-a51a-cd3874d583fc.png)

それぞれにパスを指定していきます。
```vuejs:Header.vue
<template>
  <v-app-bar app color="black">
    <v-spacer />
    <div class="menu">
      <v-btn text to="/">HOME</v-btn> //パスを指定
      <v-btn text to="/hoge">HOGE</v-btn> //パスを指定
    </div>
  </v-app-bar>
</template>
```

いけた。
バックエンドエンジニアがフロントエンドのコンテナイメージを環境に依存しないで利用できるようにしたかったけどできなかった話

フロントエンドのコンテナイメージを作ったことないバックエンドエンジニアが偉そうに「フロントエンドのコンテナもDev, QA, Stage,Prod環境で同じものを使うべき」と言ったのに出来なくて赤っ恥をかいたという話。

# 何が起きていたか
上に書いた通りなんですが、フロントエンドのコンテナイメージを環境ごとに作成していました。作成していたコンテナイメージはSingle Page Applicaion(以下SPA)でWebブラウザ上で動作するフロントエンドです。バックエンドエンジニアとしては環境ごとにコンテナイメージを生成するのは気持ちが悪いですよね。「Stage環境とProd環境で違うコンテナイメージを使ってたら、テストしたものと違うのをProd環境にデプロイするんだから信頼性なくない？」って気持ちになるのではないかと思います。これは良くないと思い、「全部の環境で同じコンテナイメージを利用しましょう」と提案しました。

# 何が問題だったのか
各環境で別のコンテナイメージを作成しなければならなかった理由は **環境毎にバックエンドのホスト名が違うから** でした。

バックエンドエンジニアなら「ホスト名を環境変数に入れればいいじゃん」となると思います。しかし、フロントエンドはWebブラウザ上で動作します。サーバ上で動作していないので、サーバの環境変数をそのまま使うことはできません。こうなるとサーバの環境変数をブラウザ上に注入する仕組みが必要になります。

# 何故できなかったのか
今回のSPAの構成は **React + Next.js + Nginx** でした。 React + Next.js のレベルではSPAの生成方法として以下の3つがあります。

1. Statis Site Generation(SSG)
1. Server Side Rendering(SSR)
1. Client Side Rendering(CSR)

Next.jsではSSGがパフォーマンス的に推奨されています。今回のフロントエンドでもSSGが採用されていました。ビルド時に `export` をして事前に静的HTMLを作成していました。SSGでは `export` 時に静的HTMLを生成し、それをNginxからWebブラウザに配布します。このため、Webブラウザの配布時にホスト名を変更するという方法は利用できなくなります。

SSRを利用するにはWebサーバをNode.jsに変更しなければなりません。また静的HTMLを使う場合はSSRは使えません。今更サーバを変更できず、かつ静的HTMLを使うことも変更できなかったのでSSRは使えませんでした。

最後の方法はCSRです。これを使えば各環境で同じコンテナイメージを利用可能でした。ただし以下の2つの理由から不採用になりました。

1. 修正が多く、そのコストとリスクを払う価値がなかった
1. ホスト名を取得するためにHTTP通信が発生するためユーザ体験を損なう可能性があった

最初にCSRでホスト名を取得する方式をとっておけばコンテナイメージを同一にできる可能性はあったのですが、今更変えられない状況でした。

# 赤っ恥をかいた

バックエンドエンジニアがフロントエンドの流儀も知らずに偉そうなことを言って赤っ恥をかきました。とても恥ずかしかったですが、知らない事やわからない事をそのままにしておくと、成長もありません。敢えて恥をかきに行き、知識を増やしましょう。


# 参考文献
* [SSGが推奨されている件](https://nextjs.org/learn/basics/data-fetching/two-forms)
* [静的HTML生成](https://nextjs.org/docs/pages/building-your-application/deploying/static-exports)
* [SPAアプリケーションのコンテナ化と設定値について](https://mzqvis6akmakplpmcjx3.hatenablog.com/entry/2020/10/04/231223)
Nginxのビルドコマンドメモ（Ubuntu20.04）

## ビルドに必要なもの
```
apt install -y build-essential libpcre3 libpcre3-dev
```

## ビルド
オプション類は以下から必要なものを指定する
https://gakumon.tech/nginx/nginx_install_option.html
```
git clone https://github.com/nginx/nginx
cd nginx
./auto/configure --without-http_gzip_module --with-stream
make && make install
```

## シンボリックリンク作成
```
ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/nginx
ln -s /usr/local/nginx/conf/nginx.conf /etc/nginx/nginx.conf
```
64bit版VBAで自然順ソート（StrCmpLogicalW ）

```vb
Option Explicit

Private Declare PtrSafe Function StrCmpLogicalW Lib "SHLWAPI.DLL" (ByVal lpStr1 As LongPtr, ByVal lpStr2 As LongPtr) As Long
'Private Declare PtrSafe Function StrCmpLogicalW Lib "SHLWAPI.DLL" (ByVal lpStr1 As String, ByVal lpStr2 As String) As Long

Sub test()
    Dim i As Long
    Dim j As Long
    Dim tmp As String
    
    Dim ary
    ary = Array("テスト1", "ワイン", "テスト11", "テスト02", "焼酎", "ビール")
    Dim max As Long
    max = UBound(ary)

    For i = 0 To max - 1
        For j = i + 1 To max
            If StrCmpLogicalW(StrPtr(ary(j)), StrPtr(ary(i))) < 0 Then
            'If StrCmpLogicalW(StrConv(ary(j), vbUnicode), StrConv(ary(i), vbUnicode)) < 0 Then
                tmp = ary(i)
                ary(i) = ary(j)
                ary(j) = tmp
            End If
        Next j
    Next i
    
    Debug.Print Join(ary, vbLf)
End Sub
```
↓結果
```
テスト1
テスト02
テスト11
ビール
ワイン
焼酎
```

文字列ではなくポインタで渡すのがポイント（ポインタだけに）

よくあるパターン（コメントアウトの方）だと、以下の結果となる。
```
テスト1
テスト02
テスト11
ビール
焼酎
ワイン
```
よくある数字順に並べるパターンであれば正常に動いているように見えるが、
全角文字は化けて順序が狂う（サンプルだとワインの「ワ」が化ける）
Apple watchで電子名刺 〜2023年秋〜

# きっかけ
2年ほど前，スマートホームに興味が出た頃にNFCタグで何ができるかを考えていた．結局実家住まいの僕にできることの限界はあって，NFCタグやNFCシールを使うぐらいならiPhoneのショートカットアプリを起動させればいいやと思ったし，NFCカードを名刺代わりに使って自分のWebサイトに誘導させる以外のアイデアが思い浮かばなかった．そして，それならNFCカードを買わずに普段身につけているApple Watchから誘導すればいいじゃないかと思った．

# 前提
- Apple Watchを身につけている（watchOS 10.0.1，iOS 17.0.2）
- 相手と交換したいなんらかの情報がインターネット上に用意してある（自分のWebサイトやX（旧Twitter）など）
- iPhoneの言語設定を英語にしているため用語が違う場合は適宜読み替えてほしい

# 今回やること
- インターネット上の紹介したいページでQRコードを生成する
- Apple Watch上に設定する

# インターネット上の紹介したいページでQRコードを生成する
まず紹介したいページをWebブラウザで検索して表示する．僕はGoogle Chromeを使っているため右クリックして「このページのQRコードを作成」を押せば今後必要となるQRコードが作成される．もしくは検索バーの右にある共有ボタンからも作成できる．X（旧Twitter）のQRコードもブラウザ経由で作成できたはず．表示できたらスクショを撮ってiPhoneの写真アプリに保存する．

# Apple watch上に設定する
:::note warn 
Watch OSがwatchOS 10.0.1より前の場合はウィジェットとして画面上に配置できた．iPhoneの連絡先アプリにQRコード用のページを作成して画像にQRコードを指定してうまく配置する（配置には試行錯誤が必要）．その後Apple Watchのウィジェットに連絡先アプリを配置して必要になったら呼び出せばQRコードを表示させることができる（おすすめのWatch FaceはInfograph）．
:::
ウィジェットから呼び出して表示させたQRコードはOSのアプデによってスマホで読み込めなくなったため，仕方なくこれまで使っていたWatch Faceとは別にWatch FaceとしてPhotosを設定してQRコードの画像を指定する方法で対処した．

**コツ**
- QRコード部分が画像の中で左上に配置されるように調整
- 時刻の位置は下（時刻がQRコードに被っていなければ読み取れるはず）
- コンプリケーションはどちらもオフ

<img src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3191770/757229a1-833d-e22a-1a64-4a20cd4b4ebf.jpeg width=40%>

**使い方**
watchOSがwatchOS 10.0.1になったことに伴ってApple Watch上からWatch Faceの変更をするのが面倒になった（誤作動が起きなくなって良くなったが）．Watch Faceを変更するために画面を長押ししてPhotosに変更すれば，QRコードの画面がApple Watch上に出てくるので相手に読み込んでもらえば良い．

# 参考文献
~~この記事は以下の情報を参考にして執筆しました。~~
OSのアプデによって手間が増えているので，もし似たようなことをApple Watchでしているサイトがあったら教えてほしい．個人的には以前のOSで連絡先アプリを使うというところが僕の会心の工夫点だと思っているのでこの記事の方法はあんまり面白味がない……．
円滑なプランニングを実現するプランニングポーカーのメリット

# はじめに
私は4月に新卒で株式会社Relicに入社し、現在バックエンドエンジニアとして働いています。
私が配属されたチームではスクラム開発を採用しており、プランニングの前日にプランニングポーカーを実施するようになった結果、様々なメリットがあったのでご紹介させていただきたいと思います。

# プランニングポーカーとは？

プランニングポーカーとは、プロダクトバックログアイテム（以下PBI）やタスクの見積りを行う際に使う手法になります。
私のチームで行っているプランニングポーカーの手順としては以下のようになっています。

- 次のスプリントで着手するPBIをまとめる
- 各PBIについて、やるべきことをある程度リストアップしておく
- 開発メンバー全員で各PBIがどの程度のポイントなのかを考え、同時に提出する
- なぜ自分がこのポイントをつけたのか根拠を発表し、最終的なポイントを全員で検討する

このポイントは実際にかかりそうな時間を元に出すのではなく、前のPBIのポイントなどを参考にした相対見積もりで考えます。
また、ポイントは[フィボナッチ数](https://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A3%E3%83%9C%E3%83%8A%E3%83%83%E3%83%81%E6%95%B0)を用いることが一般的です。


# プランニングポーカーを行う上で大事なこと

### 基本全員が参加すること
ポイントの見積もりはできる人だけでやればいいと思うかもしれませんが、ポイントは一人で見積もりするよりもチーム全員で見積もったほうが正確で早く見積もることができます。初心者も含めた、開発メンバー全員で各PBIに向き合いましょう。

### 人のポイントや意見に文句を言わないこと
プランニングポーカーにおいて大切なことは、メンバー全員が納得してポイントを決めることです。ポイントを出した人にはその人なりの根拠があるので、自分と違う意見だったとしても真っ先に否定するのではなく、聞き入れて全員で納得した状態でポイントを決められるようにしましょう。

### ツールや実際のカードなどを使用して全員同時にポイントを出すこと
例えば、一つのPBIに対して、あるメンバーが13ポイントと提案し、別のメンバーが5ポイントを提案した場合、どうすべきでしょうか？自分の提案が過大評価だと感じて、他のメンバーに合わせようとするかもしれません。
しかし、プランニングポーカーでは各自が自身の判断を持ち、それに根拠を持ってポイントを示すことが重要です。他のメンバーが見逃しているかもしれない側面があるため、全員が独自のポイントを同時に示すよう心掛けましょう。
ちなみに私達のチームでは以下のサービスを使用しています。

https://firepoker.io/#/


# プランニングポーカーを実施するメリット
- **各PBIでやることが明確になる**
    - 同じPBIでも人によって捉え方は違うので、自分ひとりでは気づけないタスクなどに気づくことがあります
    - また、全員でやることを議論していく中で新たなタスクが見つかることもあリます

- **プランニング時に工数を見積もりやすくなる**
    - 議論を行うことでやることが明確になるので工数が見積もりやすくなります
    - 着手後に思ったより工数がかかってしまい期限までに間に合わない...という状況が少なくなります

- **開発メンバー全員が各PBIの仕様を知ることができる**
    - メンバー全員が当事者となって参加するので、 各PBIの仕様を全員で共有することができます
    - 各PBIの仕様を把握していると、リリース時の手動テストなどを行うときや、実装のアドバイスを求められる際に役立ちます。

- **大きすぎるPBIを分割することができる**
    - 工数が多くて1スプリントで終わらないようなPBIがあった場合分割することができます
    - ポイントはフィボナッチ数列に基づいてつけられるので、例えば最終的なPBIのポイントが13であれば、5と8に分割することを検討することができます

- **コミュニケーションが取れる**
    - 自分と他のメンバーのポイントを比べてみたり、意見を共有することはとても楽しいです
    - プランニングポーカーでは、全員がポイントに基づいた意見を交換するため、普段あまり話さないメンバーも議論に参加する機会があります


# おわりに
この記事では私たちのチームで行っているプランニングポーカーのメリットについて紹介しました。時間がかかってしまうなどのデメリットも存在するかもしれませんが、上記のメリットを考えると、プランニングポーカーを導入する時間はチーム全体でPBIについて議論するための貴重な時間であると言えます。導入されていない方は、ぜひ一度試してみてはいかがでしょうか。
リモートでのチーム開発における心理的安全性の確保に向けた工夫

## はじめに
私は4月に新卒として株式会社Relicに入社し、現在はバックエンドエンジニアとして働いています。私たちのチームは全国各地に散らばっており、ほぼ完全にリモートでコミュニケーションを取っています。しかしリモートでのコミュニケーションには課題があり、特に心理的安全性を確保することが難しいと感じています。
この記事では、リモートでのチーム開発における心理的安全性の確保に向けた私たちの取り組みを紹介します。

## 会議中は基本ミュートにしない
オンライン会議ではミュートに設定される方も多いと思います。しかし会議中ミュートにする人が多いと以下の現象が起こる可能性があり、コミュニケーションが困難になることがあります。

- 全員が考え込むと誰も話さない時間が生じる
- ミュートにしない人同士でしか会話をしなくなってしまう
- 誰からも返事がなくて嫌な気持ちになる
- ミュートを解除してから話すのだと返事が遅れてしまう

このような状況を避けるために、基本的にミュートにはせず、積極的に発言して会議に参加することが重要であると考えます。最低限**自分に関係する話題をしている時は相槌を打ったりなにか聞かれたらすぐに反応する**ように心がけると良いかと思います。

## デイリーミーティング
デイリーミーティングはプロジェクトの進捗を確認するだけでなく、以下の目的で実施しています。

- 悩みを抱えているのなら相談する
- みんなに話したいことを共有する
- 雑談がしたければ雑談する

デイリーミーティングは毎日の開発の中で全員が絶対に発言する絶好の機会であり、他のメンバーの状況を知るための非常に重要な時間です。リモートのチームでは基本的にメンバーの状況が不透明であり、悩みを抱えていても気づきにくいため、全員が集まってなんでも話せるこの時間で問題を解決していきます。

## ちょっと悩んでも分からなかったことはSlackですぐ聞く
前述した通り、リモートのチームでは基本的にメンバーの状況が不透明であるため、わからないことがあっても聞きにくいと思ってしまうことがあります。しかし、わからないことはSlackでチャンネルに投稿し、時間がある時に分かる人が回答したりハドルなどで相談にのるという運用にしておけば、メンバーの状況が分からなくても気軽に相談できるようになります。
当たり前のことだと思われるかもしれませんが、一人で悩んで時間を無駄にしたり、期限までにタスクが終わらないことは避けるべきなので、いつでも気軽に相談できる仕組みや環境づくりをすることはとても重要であると考えます。

## Gatherなどのツールを用いて心理的距離を縮める
私たちのチームではGatherというサービスを用いて、バーチャルオフィスに気が向いた時に集まるようにしています。いつ集まるかなどは特に決めていませんが、「今から1時間ほどGatherにいます」とSlackで誰かが投稿すると、時間のある人がGatherに集まるような運用をしています。
Gatherに集まっているときは話したくなったらすぐに話しかければ良いだけなので、比較的**現実に近い形のコミュニケーション**を取ることができます。

## 勉強会を開く
チーム内での知識の格差を埋めるために、不定期でチーム内勉強会を開催しています。内容についてはDatadogを用いたエラーログの見方、OAUTH2.0、インボイス制度についてなど様々ですが、基本的にチームメンバーが気になることを、知っている人が説明していく会になっています。全員で知識を共有することで、一人しかできない仕事をなくすことができたり、**作業の分担**ができるようになったり、**全員が議論に参加できる**ようになることがメリットです。
リモートでのチームは複数人がまとまって知識を共有する機会は作ろうとしなければできないので、意図的にこのような時間を作ることも大切であると考えます。

## おわりに
様々なリモートでのチーム開発における心理的安全性の確保のための工夫をご紹介しました。リモートでの開発は対面よりもどうしてもコミュニケーション量が減ってしまうものですが、相談しやすく、何でも話せるチーム環境を築いていくことがほぼの業務の質にも繋がってくるのかなと思います。
ビットとは何ぞや

C言語を1週間前に学習し始めたばかりで早速「符号あり／なし」の違いのところで躓きました。そもそもビットって結局何のためにある単位なのでしょうか…状態です。
数弱なのでこういう自分が知らない面倒でややこしい基礎から今まで24年間逃げ回っていたわけですが、今度こそ逃げないぞ、ということで…
以下、ウェブサイトで見ながら学んだことを随時更新していきます。

# ビットの大きさが違うと何が違うのか
ビット数の違い≒処理速度の違い、です。
nビットの時に2ⁿ通りの状態を表すことができます。
https://programming.pc-note.net/c/bit.html#:~:text=C%E8%A8%80%E8%AA%9E%E3%81%A7%E6%9C%80%E3%82%82%E3%82%B5%E3%82%A4%E3%82%BA,%E3%81%AE%E3%80%8C1%E3%83%90%E3%82%A4%E3%83%88%E3%80%8D%E3%81%A7%E3%81%99%E3%80%82&text=1%E3%83%90%E3%82%A4%E3%83%88%E3%81%AF256%E9%80%9A%E3%82%8A,%E3%81%AE%E7%8A%B6%E6%85%8B%E3%82%92%E8%A1%A8%E3%81%9B%E3%81%BE%E3%81%99%E3%80%82



https://abm.asukabook.com/jp/expert/64or32.html

# n進数
2進数：1桁で2通り、2桁で4通り、3桁で8通りの数を表せる。
8進数：1桁で8通り、2桁で64通り、3桁で512通りの数を表せる。


# C言語と8進数
C言語は12バイト＝1ビットという時代を経ているので、8進数表記を標準でサポートしています。
各桁、0～7までの数を使って表すので10進数と区別がつかないため、
先頭を「0」にした数字の並びを8進数として扱います。
https://af-e.net/c-language-octal/

# 16進数
現在のコンピュータは4バイトをひと単位として使うことが多い（int型も4バイト）。
16進数は4ビットを1桁で表し、4バイトは4*8=32ビット。
つまり8桁で4バイトを表せる。
https://www.cc.kyoto-su.ac.jp/~yamada/programming/bit.html#:~:text=%E3%81%97%E3%81%8B%E3%81%97%EF%BC%91%EF%BC%96%E9%80%B2%E6%95%B0%E3%81%A0%E3%81%A8,%E3%81%A7%E8%A1%A8%E3%81%9B%E3%82%8B%E3%81%93%E3%81%A8%E3%81%AB%E3%81%AA%E3%82%8B%EF%BC%8E

# 16進数をC言語で10進数として出力する
以下。16進数は「0x」を頭に付けてください。

```qiita.c
#include<stdio.h>
#include<stdint.h>
int main(void)
{
	int x = 0xA0;
	printf("%d\n", x);
}
```
出力のデフォルトは10進数なのでそのままでよし。

# C言語とビット
型（char,int,long int）によって確保できるデータの大きさが決まります。
https://chokuto.ifdef.jp/urawaza/datatype.html



# C言語の「signed（符号あり）」「unsigned（符号なし）」何が違うのか
- signed（符号あり）：マイナスの値を取り扱うことができます。
- unsigned（符号なし）：0からプラスの値しかとれません。

https://lightgauge.net/language/c-language/signed-unsigned-value

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3564033/6ffedb22-5647-6288-e081-062d32a15ef8.png)
Javaで「StringBuilderオブジェクトの作成と基本的な使い方」の動作を確認してみた

# 概要

Javaで「StringBuilderオブジェクトの作成と基本的な使い方」の動作を確認してみました。以下のページを参考にしました。

https://www.javadrive.jp/start/stringbuilder/index3.html

# 実装

以下のファイルを作成しました。
```JSample3_1.java
class JSample3_1{
  public static void main(String[] args){
    StringBuilder sb = new StringBuilder();
    sb.append("watch's price is ");
    sb.append(100);
    sb.append(" yen.");

    System.out.println(sb.toString());
  }
}
```

以下のコマンドを実行しました。
```
$ javac JSample3_1.java 
$ java JSample3_1 
watch's price is 100 yen.
```

# まとめ

何かの役に立てばと。
スッキリわかるJava入門 実践編 第３版 まとめ - part6 -ファイル操作

# はじめに
こんにちは　◤●ㅅ●◥ﾉ

今回はファイル操作について学びました！

## 第６章　ファイルの操作
### 1.ファイル操作の事前知識
ファイルとは
データをコンピュータに記憶させる時の基本単位のこと

ファイルの読み書きは必ず以下の順序で行う
手順を守らないと致命的な不具合につながる
1.「最初に１回」ファイルを開く
2.「必要な回数」ファイルのデータを読み込み、書き込み
3.「最後に１回」ファイルを閉じる

ファイルの読み込み、書き込み方法の種類
・ランダムアクセス
　ファイルのあちこちに読み書きをする方法
・シーケンシャルアクセス
　ある場所から連続して少しずつ読み書きする方法

### 2.テキストファイルの読み書き
ファイルに文字情報を書き込む
→java.ioパッケージのFileWriterクラスを利用する
※必要な情報を書き込んだらファイルを閉じる前に必ずflush()を呼び出す
→呼び出さないとファイルに正しくデータが書き込まれないことがあるため

ファイルの先頭から１文字ずつデータを読み取る
→java.ioパッケージのFileReaderクラスを利用する

### 3.バイナリファイルの読み書き
普段利用しているさまざまなファイルは大きく２種類に分類できる
・テキストファイル
　文字として解釈可能なデータ（文字列）
・バイナリファイル
　文字とは解釈できないデータ（バイト列）

バイナリファイルの書き込み→FileOutputStreamクラス
バイナリファイルの読み込み→FileInputStreamクラス
を利用する

文字とコードの違い
文字「A」
コード「01000001」
のような感じ実質的には同じだけど人間がわかりやすいようにしている

漢字などの他のものだとどうなるのか
→アルファベット、数字、カタカナ、漢字など様々ある
　→ある文字にどのようなバイト表現を割り当てるかというルールを決める
　　→文字コード体系(UTF-8など)

### 4.ファイル操作の落とし穴
ファイル操作をする際に陥りやすい、陥ると致命的な不具合につながる落とし穴がある
→ファイルを閉じるという操作

:star: 必ずclose()されることを保証する
途中でreturnしたり例外が発生したりする場合であっても、ファイルを開いたら必ず閉じる

:star: ファイルを確実に閉じる方法
close()は必ずfinallyブロックに書く

### 5.ストリームの概念
JVMの外部データはメモリ不足になることを配慮して少しずつ読み書きするのが基本
このアプローチに沿ったデータの読み書きのようすを __ストリーム__ という概念で捉える

ストリームはデータが少しずつ流れてくる「小川」のイメージで捉える

JVMは起動直後に３つのストリームを自動的に準備している
・標準出力
・標準出力エラー出力
・標準入力

通常ストリームはJVM外部のデータを少しずつ読み書きする際に利用するが、
内部の読み書きにも応用できる
→StringReaderクラスを利用する

### 6.フィルタの活用
Javaの世界ではストリームの途中に様々な変換処理をする部品を挟み込むことが可能であり、
それらはフィルタと呼ばれている
Javaが標準で準備しているCipherOutputStreamフィルタを１つ挟むだけで実現できる
 JavaAPIではたくさんのフィルタが提供されており、それらは次の特徴を持っている
1.Filter~クラスを継承している
2.単独で存在できず、ストリームに接続する形で生成する
3.複数のフィルタを連結することができる

 JavaAPIには、たくさんの種類のフィルタが標準で提供されている
中でも利用頻度が高いのはjava.ioパッケージに準備された４つのフィルタ
文字情報用：BufferedReader,BufferedWriter
バイト情報用：BuferedInputStream,BufferedOutputStream

この４つのクラスは __バッファリングフィルタ__ と総称されている
バッファリングフィルタは上流から少しずつ流れてくるデータを溜め込み、まとまった量になったら下流に流す仕事をしてくれる
データを溜めて一定量ずつまとめて処理するメリットは何か
1.処理性能の向上
少量のデータを複数回より、まとめて１回で書き込む要求をする方が圧倒的に速い
2.まとまった単位でデータを読める

### 7.ファイルシステムの操作
ファイルそのものに対して操作を行うには別のAPIを用いる必要がある
→java.io.Fileクラス

java.io.Fileには懸念点が２つある
1.備えているファイル操作用の命令が少なく、中途半端
2.ファイルやフォルダを指し示す責務と各種の操作をする責務があり役割が混在している

解決するために
java.nio.file.Pathインタフェース
java.nio.file.Filesクラス
が導入されている

## まとめ
ストリームはJVMがデータをやりとりする小川のイメージ
ファイルを前から順に読み書きする方法をシーケンシャルアクセスという
ファイルは必ずfinallyブロックまたはtry-with-resources文を利用して閉じる必要がある
ファイルは他のストリームやフィルタに連結して使用できる
ファイルの読み書きには通用バッファリングフィルタを併用する
java.io.Fileを用いて、特定のファイルやフォルダを指し示すことができる

今回もありがとうございました！
ではまた〜　◤●ㅅ●◥ﾉ"
Django + ChatterBotで5分でチャットボットを作ろう！

**Django** と**Chatterbot**の組み合わせで**簡単にチャットボットがサイト内、アプリ内に作れる**ことを知っていましたか？

「Djangoで業務システムを作っている方」、
「Djangoで自作サイトやアプリを開発している方」、
「Djangoで何か面白いものを作れないか探している方」、

そんな方に届けばいいなと思って記事を書いています。

今日はチャットボットをDjangoで導入するパッケージについて解説します。
最初に**Chatterbot**というPythonパッケージから簡単に説明します。


### Chatterbot

 **ChatterBot**は、Pythonで会話型のAIを構築するためのライブラリです。

大きな特徴と言えば、
ユーザーとの会話から学習し、
レスポンスを改善していく能力を持っています。

使い方の手順さえ覚えれば、
プログラミング初心者でも容易に**チャットボットを開発**できるシンプルなライブラリだと思います。

使用例
- 自動応答システムの開発
- AIによるカスタマーサポートの自動化

### DjangoでChatterbotを使うメリット

**Djangoとの統合が超絶簡単にできる**:
Django ChatterBotは、DjangoプロジェクトにChatterBotを簡単に統合できるように設計されています。設定とインストールが簡単で、ウェブアプリケーションにチャットボット機能を追加するのが容易です。

**APIが使える**:
Django ChatterBotは、RESTful APIを提供しており、これによりフロントエンドとの連携や、他のアプリケーションとのインタラクションが可能です。

**カスタマイズ機能も豊富**:
ChatterBotの豊富なカスタマイズオプションと拡張性を利用して、特定のビジネス要件やユーザーエクスペリエンスに合わせてチャットボットを調整することができます。

### インストールから使えるところまで（コード例付き）

1. パッケージのインストール:
    pipを使用してDjango ChatterBotをインストールします。

    ```python
    pip install django-chatterbot
    ```

2. Django設定ファイルに記述:
    Djangoのsettings.pyファイルに、ChatterBotの設定を追加します。

    ```python
    INSTALLED_APPS = [
        # ...
        'chatterbot.ext.django_chatterbot',
    ]

    CHATTERBOT = {
        'name': 'Django ChatterBot Example',
        'trainer': 'chatterbot.trainers.ChatterBotCorpusTrainer',
        'training_data': [
            'chatterbot.corpus.english.greetings',
            'chatterbot.corpus.english.conversations'
        ]
    }
    ```

3. URLの設定:
    Djangoのurls.pyファイルに、ChatterBotのAPIエンドポイントを設定します。

    ```python
    from django.urls import path
    from chatterbot.ext.django_chatterbot import urls as chatterbot_urls

    urlpatterns = [
        # ...
        path('chatterbot/', include(chatterbot_urls, namespace='chatterbot')),
    ]
    ```

4. データベースのマイグレーション:
    Djangoのマイグレーションコマンドを実行して、ChatterBotのデータベーステーブルを作成します。

    ```python
    python manage.py migrate
    ```
5. サーバーの起動:
    Djangoの開発サーバーを起動して、チャットボットを動作させます。
    ```python
    python manage.py runserver
    ```
    これでチャットボットの導入は完成です。
    シンプルイズベスト！

### おわりに

ここまで読んでいただいた方、
本当にありがとうございます！

でも、思っていたより簡単にDjangoでチャットボット使えそうでしょ？

みなさんのDjangoライフがより一層楽しくなることができれば私も幸いです。

では、終わりにします。

フォローやライクいただけますとうれしいです。
暇な方はポチってください（笑）
【CSS】要素を中央寄せしたいときに用いる手法3選

<section>
  <h1>【CSS】要素を中央寄せしたいときに用いる手法3選</h1>
  <section>
    <h2>はじめに</h2>
    <p>※こちらはフロントエンド初心者のかた向けの記事になっています。<br>CSSによって要素を中央寄せしたいときによく用いていた手法を3選紹介します。</p>
  </section>
  <section>
    <h2>その1　display:flexを用いた中央寄せ</h2>
    <p>中央寄せしたい要素の親要素に対して下記のようなflexを付与させます。そうすることで子要素は中央寄せになります。この手法を用いる場合、子要素は1つのみだと調整しやすいです。</p>
    <p>
      <pre style="max-width: 800px; width: 100%;">
        .parent-element {
          display: flex;
          justify-content: center;
          align-items: center;
        }
      </pre>
    </p>
  </section>
  <section>
    <h2>その2　display:gridを用いた中央寄せ</h2>
    <p>中央寄せしたい要素の親要素に対して下記のようなgridを付与させます。そうすることで子要素は中央寄せになります。</p>
    <section>
      <h3>1つの子要素を中央寄せしたい場合</h3>
      <p>
        <pre style="max-width: 800px; width: 100%;">
          .parent-element {
            display: grid;
            place-content: center;
          }
        </pre>
      </p>
    </section>
    <section>
      <h3>複数の子要素をすべて中央寄せしたい場合</h3>
      <p>
        <pre style="max-width: 800px; width: 100%;">
          .parent-element {
            display: grid;
            place-content: center;
            place-items: center;
          }
        </pre>
      </p>
    </section>
  </section>
  <section>
    <h2>その3　position: absoluteを用いた中央寄せ</h2>
    <p>中央寄せしたい要素の親要素に対してposition:relativeを付与させます。子要素にはposition:absoluteと一緒にtransformを付与することで中央寄せになります。position:abusoluteを用いてるのでレイアウトの崩れが起きないように気をつけてください。</p>
    <p>
      <pre style="max-width: 800px; width: 100%;">
        .parent-element {
          position: relative;
        }
        .child-element {
          position: absolute;
          top: 50%;
          left: 50%;
          transform: translate(-50%, -50%);
        }
      </pre>
    </p>
  </section>
  <section>
    <h2>さいごに</h2>
    <p>X軸方向に中央寄せをする手法は色々思いつくと思いますが、Y軸方向に中央寄せをする方法もいくつか思いつけるようになったら一歩前進ですね。</p>
  </section>
</section>
🔰MacOSXでRPGツクールMV製ゲームを快適に遊ぶためにやったこと

本稿は非エンジニアのRPGツクールでのゲーム作者（ツクラー）の方向けに書き直しました。
元記事

https://qiita.com/nomurasan/items/d76270366c627645a332

開発者目線で書いていますが、プレイヤーとしても使える情報があるはず、です。

## RPGツクールMV製のゲームを安全・安定した環境で遊ぶ
RPGアツマール（現在は閉鎖）で遊べていたようなオープンな場所があれば良いのですが、plicyかふりーむ以外の選択肢を取った場合（自サイトでの公開など）は実行環境を自前で用意しなければなりません。
PRGMVだとwwwディレクトリ（Windowsゲームを想定しているのでフォルダと呼ぶべき？）があり、index.htmlをブラウザで開けばゲームを実行することができます。
少なくともwineを使うよりは安定するし早いです。

しかし、普通に開くとCORSエラーが起こるので、サクッとローカルでWebサーバーを立てて回避しましょう、というアプローチを検討します。

<details>
<summary>画像で見るCORSエラーとは？</summary>

### エラーメッセージは異なる可能性があります
![スクリーンショット 2023-09-29 17.20.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122800/ab302b43-5f1d-be8f-688b-99056e55e5ed.png)

URL欄が「`file://〜/（プロジェクト名）/www/index.html`」だと上のようになります。

</details>

### 最低限必要なコマンド（ターミナルを使用）
```
npm install live-server  # 1回だけ実行すれば以降は不要
npx live-server
```

これで実行できます。
セーブ後にサーバーやマシンを再起動しても当然、ロードして続きから遊べます。

一応、Windowsでも理屈的には同じ方法が使えますが、元々exeが動く環境なのでこの方法を採用するメリットは薄いです。

## finderからダブルクリックで起動したい！
さて、本題です。
元記事からスピンアウトした理由とも言います。

せっかくだからなんちゃってMac/Linux対応版としてプロジェクトに１つファイルを入れれば完成する仕組みを置いておきます。

### 1. Game.exeと同じフォルダに以下を置いてください
``` Game.command
#!/bin/sh

cd $(dirname $0)/www
npx live-server
```

この内容をコピペしてメモ帳などに貼って「`Game.command`」という名前で保存してください。

### 2. Game.commandに実行権限を付与してください
Game.commandに実行権限を付与するためにはターミナルを使用します。
念の為、Windowsの場合はPowerShellです。

1. `npm install live-server`
1. `chmod +x Game.command`

順番はありません。ただし、どちらも実行してください。
2.は特に注意が必要で、`Game.command`がある場所で実行する必要があるので、「cdコマンド」と「ファイルパス」について少し調べる必要があります。
ChatGPTに聞くのが一番ベストです。

### 3.（遊ぶ人） ゲームを起動します
`Game.command`をダブルクリックで実行します。
ブラウザが開き「`http://127.0.0.1:8080/`」にアクセスするので、通常起動した後は思い思いにプレイ！
ウッカリindex.htmlを直接ひらいてURL欄が「`file://〜/（プロジェクト名）/www/index.html`」のようになってしまわないように！

### 4.(開発者) 普通に圧縮して配布します
おしまい。
【postgre】縦持ちデータを横持ちにする方法

# お客様先からの要件
##### ※下記で使用するデータは全てテストデータです。
**「時系列順に格納されているデータから、1社員1列ごと見れる【横持ち勤務時間テーブル】を作成してほしい」**



下記2テーブルを使い1社員1列ごとのデータを抽出します。
<b>【社員テーブル】<b>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3528749/a641fc6c-6459-0bbd-ef93-f8cc4f2b53df.png)

<b>【縦持ち勤務時間テーブル】<b>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3528749/0283a1ec-6916-85f9-1128-28db1a6cac5f.png)

この時、格納するテーブルでは社員番号がprimary key に設定されるため
単純なselect文では、下記エラーが発生します。
<b>duplicate key value violates unique constraint "*******"<b>

**社員番号がprimary keyであるため1社員ごとに１列抽出しなければなりません。**
下記が抽出イメージです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3528749/ff427b13-1a55-692f-855b-88e76e61f505.png)


 上記イメージを抽出するのに3行程で試してみました。

### phase1


```sql
with temp1 as
(
select
"社員番号"
,"名前"
,"労働時間"
,"日付"
,ROW_NUMBER() OVER (PARTITION BY "社員番号"
ORDER BY "日付" ASC) as "カウント"
FROM "勤務時間テーブル"
)
```
**上記Queryで社員番号ごとに日付を古い順に番号を振っていきます。**
上記with句で表示されるテーブルは下記になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3528749/8404a393-b8e9-a195-690b-a262d9ad5fc6.png)

```sql:ポイント
ROW_NUMBER() OVER (PARTITION BY "社員番号"
ORDER BY "日付" DESC) AS "カウント"
```

次の行程で縦持ちだったデータを横に持ってきます。


### phase2

```sql:
temp2 as
(
select
"社員番号"
,max(case "カウント" when 1 then "労働時間" else null end )as "10/01"
,max(case "カウント" when 2 then "労働時間" else null end )as "10/02"--横持ちデータへ置換
,max(case "カウント" when 3 then "労働時間" else null end )as "10/03"--横持ちデータへ置換
from temp1
group by "社員番号"
)
```
簡単に説明しますと、ポイントと記載のある上記Queryでカウント列を作成しました。
そのカウント列が
**1の場合の労働時間の列名を10/01
2の場合の労働時間の列名を10/02
3の場合の労働時間の列名を10/03**
と列名を付けられ、group byで社員番号ごとに並べられます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3528749/3f21b110-0bd3-bd32-9aeb-9f5f9dfe0a83.png)


### phase3

そして最後の行程で
上記with句で作成したテーブル【temp2】と【社員テーブル】を社員番号をキーに結合し完成です。

Queryをまとめると↓
```sql:
with temp1 as
(
select
"社員番号"
,"名前"
,"労働時間"
,"日付"
,ROW_NUMBER() OVER (PARTITION BY "社員番号"
ORDER BY "日付" DESC) as "カウント"
FROM "勤務時間テーブル"
),
temp2 as
(
select
"社員番号"
,max(case "カウント" when 1 then "労働時間" else null end )as "10/01"
,max(case "カウント" when 2 then "労働時間" else null end )as "10/02"--横持ちデータへ置換
,max(case "カウント" when 3 then "労働時間" else null end )as "10/03"--横持ちデータへ置換
from temp1
group by "社員番号"
),
select
A."社員番号"
,B."名前"
,"10/01"
,"10/02"
,"10/03"
from temp2 as A
left join "社員テーブル" as b
on A."社員番号" = B."社員番号"
```

上記Queryで最初にイメージしていたデータ抽出ができました。



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3528749/ff427b13-1a55-692f-855b-88e76e61f505.png)
## 最後に
今回は縦持ちのデータを横持ちに変更するSQLについて記載しました。
SQL開発の長い方であればより簡単に、横持ちに変換することが可能かもしれませんが
今回は少し丁寧に、そして確実にできる方法について解説してみました。
私自身もQiita記事にはいつも助けられています。この記事で誰か一人でも疑問解消につながれば幸いです。
お付き合いただきありがとうございました。

-------------------------------------------------


株式会社ジールでは、初期費用が不要で運用・保守の手間もかからず、ノーコード・ローコードですぐに手元データを分析可能なオールインワン型データ活用プラットフォーム「ZEUSCloud」を提供しております。
ご興味がある方は是非下記のリンクをご覧ください：
https://www.zdh.co.jp/products-services/cloud-data/zeuscloud/
Prep内でのデータの並べ替え / Tableau Prep

### データの並び替え

Tableau Prepは前加工ツールなので、思い通りにデータがソートされていないので見づらい、データ検証したい時に、データが並んでいれば画面で確認できるのに、検証しずらいと思うことがあります。
そんなときに、ORDER BY 関数を使って、データを意図的に並べ替えます。

Countryのアルファベット順にデータを並べ替えたい場合

フィールド名：Country
{ ORDERBY [Country]ASC:LOOKUP([Country],0)}

##### Point！！
Lookupで引数を0にすることで、自分自身の値を持って来て、ソートを行います。
この計算フィールドのフィールド名を、元の値と同じフィールド名で指定すれば、ソートのための列を増やさないでソートすることが可能です。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3531257/d0f90875-894b-1342-c511-397631db54f7.png)

{ ORDERBY [Country]ASC:LOOKUP([Country],0)}
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3531257/ef5bd141-95b4-d716-7171-7920621a05f1.png)

Sortという項目ができて、アルファベット順に並びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3531257/80d68a22-2dd9-0402-be31-810a4da55e37.png)

ところで、同じ項目が二つできてしまった。。。もちろんどちらかの項目をこの後削除すればよいわけですが、先ほど作ったSortの計算フィールド名をCountryにして上書きするとスッキリします。

しかし、さきほど作成した計算フィールドのフィールド名をCountryにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3531257/48e6e001-1397-9a8e-a84c-bc4329bbdca3.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3531257/82964d20-91e2-ffde-84cd-2f0812daac4a.png)
git commitとgit pushの違いなど、今日gitについて学んだこと

スクールの課題の合格要件に、機能を新しく作成する毎に、commmitすること、と言うのがあった。

メンターさんによると、実際の現場ではとっても長ーいコードにエラー等が発生した際、過去の状況に戻って見返したりすることがあるため頻繁にcommitする必要があるとのこと。

なるほど〜！！

ってことで、私も、
現在開発中のアプリをcommitする準備を始めた。

その前に、まずは、
```
git init
```
して、gitを使用する準備をしようと思った！
その前に念の為、ls -a　で、gitのファイルが既に無いか確認してみた。
init　してないから無いはず...

なのに、
あれ？？
ある！！

なんでだろう...

![スクリーンショット 2023-09-29 16.38.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3566175/38f46ddd-dcc3-8ba9-a062-0bd56abcdae4.png)

メンターさんに聞いてみると、rails new　でアプリのディレクトリー等を作成する時に、一緒に作ってくれちゃうとのこと！！

そうだったんだ！！知らなかった、メンターさんありがとう！

では、
戻って、commitする準備をしよう！

```
git add .
```
して、ディレクトリー毎まとめてcommitする準備をする。

よし、準備できたから、

```
git commit -m "~~~"
```
してcommit完了！

おっと、でもでも待てよ！！
これだけで保存できてるのだろうか？
今まで、保存というと、githubにリポジトリーを作成し、commit　の後に　push して保存みたいなことしかしたことなかった私は、このcommitだけで保存できている気がしない。

そこでまたメンターさんに聞いてみた！

commitすると、自分のPCの「.git」のファイルの中に、今の状態のファイルが保存されるので、自分のPCの中で、後で見返したりすることができるらしい！！

へえ！！そうだったんだ！

 pushは、基本、他者にも共有する必要がある時に使用するもの！！

なるほど〜〜！！
初学者の私にとっては、とっても勉強になった！


以上、お疲れ様でした〜！
Cloud9からTerraformでIAMロールを作成時に『creating IAM Role (): InvalidClientTokenId: The security token included in the request is invalid』が出たので調査

# はじめに
terraformからrole作成時に下記のエラーが出たので調査してみました。
> creating IAM Role (): InvalidClientTokenId: The security token included in the request is invalid

# 実行環境
- cloud9
- terraform

# 結論
CLIクレデンシャルが設定できていませんでした。
。。。。がオチだと思っていたのですが、

実際のところ、
『**Cloud9 インスタンスプロファイルをデフォルトから他のIAMロールに変更**』が必要だったみたいです。

# でもせっかく調査したので、CLIクレデンシャルのアレコレまとめ

- マネコンからログインしているIAMユーザのアクセスキーID&シークレットアクセスキーの取得

- cloud9のターミナル上で設定
```
$ aws configure
AWS Access Key ID [None]: {アクセスキーID}
AWS Secret Access Key [None]: {シークレットアクセスキー}
Default region name [None]: ap-northeast-1
Default output format [None]: json
```

- defaultの認証情報プロファイルの確認
```
$ cat credentials
[default]
aws_access_key_id = {アクセスキーID}
aws_secret_access_key = {シークレットアクセスキー}

➡接続できない場合は、credentialsにaws_session_token=XXXXXXXXXを追記する
```

- ~/.aws/configに認証情報のプロファイルを設定
```
[profile sample]
region=ap-northeast-1
mfa_serial={MFAが有効になっている個人アカウントのiamロール}
role_arn={スイッチしたい別アカウントのiamロール}
source_profile=default
```

# 解決策

1. cloud9のインスタンスプロファイルの確認
デフォルトのインスタンスプロファイル（AWSCloud9SSMInstanceProfile）が割り当てられている。
➡デフォルトのIAMロールだと権限が足りないためIAM権限の設定ができない

2. Cloud9からAWS managed temporary credentialsのスイッチを「OFF」

3. IAMロールを作成　
EC2タイプの『AdministratorAccess』を選択

4. EC2インスタンス(Cloud9)のIAMロールを2で作ったものに変更

5. ロールの変更を反映させるためにEC２インスタンスを再起動

(追記)
あるいは、既存のIAMロールに以下のポリシーを追加してもよさそうです。
- PowerUserAccess
- IAMFullAccess


強い権限を与えているため、セキュリティ的にはアレですが、ひとまずこれが動くようになりました。適切な権限付与等は今後引き続き勉強してみようと思います。


# 参考
https://dev.classmethod.jp/articles/aws-cli_initial_setting/
https://qiita.com/mokkos/items/7de9793ea37528e11e3e
https://go-journey.club/archives/17029
【OpenAI API】presence_penaltyとfrequency_penaltyの違い

# この記事は?
OpenAI APIを用いて、GPTによる返答を生成する際、様々なパラメータを指定することができる。
そのパラメータの中で、`presence_penalty`と`frequency_penalty`の違いが分かりにくかったので解説する。
# API Referenceによる記載
OpenAIの[API reference](https://platform.openai.com/docs/api-reference/chat/create)には次のように記載されている。
> presence_penalty (number or null Optional Defaults to 0)
> Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics.

> **frequency_penalty** (number or null Optional Defaults to 0)
> Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim.

### Deeplによる翻訳

**presence_penalty**
2.0 から 2.0 の間の数値。正の値は、新しいトークンがこれまでにテキストに現れたかどうかに基づいてペナルティを課し、モデルが新しいトピックについて話す可能性を高める。

**frequency_penalty**
2.0から2.0の間の数値。正の値は、新しいトークンに、これまでのテキストにおける既存の頻度に基づいてペナルティを与え、モデルが同じ行を逐語的に繰り返す可能性を低下させる。

↓

両方ともトークンの繰り返しを抑制するペナルティ。
何が違うかよくわからない。

# 詳細説明
パラメータの詳細については[こちら](https://platform.openai.com/docs/guides/gpt/parameter-details)に書かれている。
各ペナルティはトークンの出現確率に次のように関係しており、`presence_penalty`と`frequency_penalty`は式中の`alpha_presence`と`alpha_frequency`に対応している。

```
mu[j] -> mu[j] - c[j] * alpha_frequency - float(c[j] > 0) * alpha_presence
```
* `mu[j]` is the logits of the j-th token
* `c[j]` is how often that token was sampled prior to the current position
* `float(c[j] > 0)` is 1 if `c[j] > 0` and 0 otherwise
* `alpha_frequency` is the frequency penalty coefficient
* `alpha_presence` is the presence penalty coefficient

式を見てみると、`alpha_frequency`には過去のトークン出現回数が直接かけられているが、一方、`alpha_presence`には過去にトークンが出現しているかどうかの0か1の二値がかけられている。

つまり、同じトークンの出現回数が増えるほど`frequency_penalty`によるペナルティは増加するが、`presence_penaltyによるペナルティは一定（同じトークンか過去にあらわれていない場合は0）となる。

# まとめ
### presence_penalty
* 過去に同じトークンが現れたか否かによって、一定のペナルティを課す。
### fequency_penalty
* 過去に同じトークンが現れた回数が増えれば増えるほど、大きなペナルティを課す。

# 参照
https://platform.openai.com/docs/guides/gpt/parameter-details
GithubActionsで別リポジトリを参照する

Githubで、ビルドは別のリポジトリで実施するが、リリース作業などは別リポジトリで実施したいことがあります。
また、カレントリポジトリにある添付ファイルと別リポジトリーにある添付ファイルをS3にアップロードしたいこともあるかもしれないです。
その場合、デフォルトであるGITHUB_TOKENの権限では、別リポジトリーを操作することが出来ません。

personal access tokensを使う方法もあるのですが、条件などあるため使えないことも多いです。
そこで、GithubAppを使用して、見解を取得する方法を記載します。

### Github Appの作成

* 下記にアクセスして、New Github Appをクリックします。

```
https://github.com/settings/apps/
```
```
https://github.com/organizations/<組織>/settings/apps
```

* 名前やURLなどは適当に入れてもらっていいです。
* WebhookのActiveは、チェックを外します。
* Repository permissionsのContentsのアクセスをRead以上にします。
* Create Github Appをクリックします。

### インストール

作成したら、Generate a private keyをクリックして、keyを保存してください。
private keyとApp IDを使用します。

* Install Appでインストールします。
* インストールするとリポジトリを選択できますので、ファイル操作を許可したいリポジトリを選択します。

* 操作したいリポジトリのsecretsにAPP_IDとPRIVATE_KEYを登録します。
* PRIVATE_KEYは、-----BEGIN RSA PRIVATE KEY-----と-----END RSA PRIVATE KEY-----を含めて、登録します。

### GithubActions

```yml
name: Github App

on: 
  workflow_dispatch:
    inputs:
      tag:
        required: true

permissions:
  contents: read

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3
        with:
          fetch-depth: 0
          ref: main
      - name: Generate github token
        id: generate_token
        uses: tibdex/github-app-token@v2
        with:
          app_id: ${{ secrets.APP_ID }}
          private_key: ${{ secrets.PRIVATE_KEY }}
      - name: Get Release data
        id: release_data
        uses: robinraju/release-downloader@v1.8
        with:
          repository: 操作したいリポジトリ
          tag: ${{ github.event.inputs.tag }}
          token: ${{ steps.generate_token.outputs.token }}
          fileName: '*'
      - name: Check LS
        run: |
          ls -la
```

### 説明

* 下記で、github app tokenを使用できるようにします。
* steps.generate_token.outputs.tokenに権限があるトークンが登録されます。

```
      - name: Generate github token
        id: generate_token
        uses: tibdex/github-app-token@v2
        with:
          app_id: ${{ secrets.APP_ID }}
          private_key: ${{ secrets.PRIVATE_KEY }}
```

* 例で、別リポジトリのタグに添付してるファイルを取得します。
* repositoryに操作したいリポジトリを指定します。
* tokenには、GithubAppで設定した権限を取得できるようにsteps.generate_token.outputs.tokenを指定します。

```
      - name: Get Release data
        id: release_data
        uses: robinraju/release-downloader@v1.8
        with:
          repository: 操作したいリポジトリ
          tag: ${{ github.event.inputs.tag }}
          token: ${{ steps.generate_token.outputs.token }}
          fileName: '*'
```

あまり需要がないのか情報がなかったのですが、別リポジトリを操作する方法になります。
例で、ファイルの操作をしていますが、PRや別のWorkflowを操作するなどGithubAppで権限を与えれば、色々操作出来ます。
Pythonのモジュール/パッケージ/ライブラリ、from / importの違いについて(初心者向け)

# 
## はじめに

本業がプログラマじゃないけどPythonをたまに使う自分向けのメモです。PythonでFromとimportをおまじないとして使ってたり、モジュール/パッケージ/ライブラリの整理が少し経つと忘れてしまう人向けのメモです。自作ライブラリやサブフォルダとか作りたくなってきた人はちゃんと理解しましょう。

## ソースコード区分の概念

### モジュール

[モジュール](https://docs.python.org/ja/3/tutorial/modules.html)は、Pythonプログラムの1つのファイル(xxx.py)です。
モジュールは、関数、クラス、変数などのコード要素を定義することができます。
他のPythonプログラムから**import**文を使用してモジュールを読み込み、そのコード要素を使用することができます。
モジュールは再利用可能なコードの1つの最小単位となります。ある機能の実装を1つのモジュールにまとめておくことで、他のプログラムで簡単に利用できるようになります。

### パッケージ

パッケージは、Pythonプログラムの複数のモジュールをまとめたものです。
パッケージは、**ディレクトリとその中に含まれるモジュールファイル群**（＝ディレクトリ+その配下の.pyファイル、その他設定ファイルなど）から構成されます。
またパッケージには、**\_\_init__.py**という名前の特別なファイルを含めます。このファイルには、パッケージの初期化コードなどが含まれます。
他のPythonプログラムから**import**文を使用してパッケージを読み込むことができます。

もう一歩踏み込むと、パッケージは[「ドット付きモジュール名」を使用して Python のモジュール名前空間を構造化する方法](https://docs.python.org/ja/3/tutorial/modules.html#packages)とのことです。例えばいろんなパッケージフォルダごとに別々のcommon.pyのようなモジュールファイルが多数あったとしても、import <パッケージの名前>.commonとすることで一意にモジュールを識別することができます。

### ライブラリ

ライブラリは、複数の関数、クラス、モジュールやパッケージの集まりです。
ライブラリは、**特定の目的を持つコードの集合体**であり、一般に**汎用的に再利用可能**なコードの塊です。ライブラリをインストールすることで一般的なタスクを実行するための関連する一連の関数やクラスを提供します。例えば、mathライブラリは数学的な演算を行う関数を提供します。

また主要なライブラリは、Pythonの標準ライブラリやサードパーティのライブラリとして提供されることがあります。
例えばpip install matplotlibのようにすることで公開されているライブラリをインストールし、コード上でimport matplotlibすることで数学的なプロットをするモジュールを使えるようになります。

### つまり？

簡単に言えば、モジュールは1つのファイル、パッケージはモジュールをまとめたもの（ディレクトリ）、ライブラリは再利用可能なコードの集まりという関係です。パッケージは主に複数のモジュールを整理するために使用され、ライブラリは特定の目的を持つコードのコレクションです。

## importとFromの区分

### import

importはimport対象のモジュールの中身全てを取り込みます。対象がライブラリならライブラリ全体を取り込みます。例えば、import datetimeとすると、datetimeライブラリのすべての機能を利用でき、各種モジュールの機能やクラスにアクセスできます。

しかし、使用時は**ライブラリ名の後にドットを使って関数やクラスなどを指定する必要**があります。日付や時刻を表すオブジェクトを作るときは、datetime.dateやdatetime.timeというように書かなければなりません。

### from

fromは、特定のモジュール、クラス、または関数をインポートするための方法です。
fromを使用すると、importした要素を**ライブラリ名を指定せずに直接使用できます**。例えば、from datetime import date, timeとすると、dateやtimeというオブジェクトを作るときに、モジュール名を書かなくても済みます。

### つまり？

importとfromの違いは、モジュールの全体か一部かを利用するかという点です。importはモジュール全体を利用できますが、モジュール名を付けなければならないことが多くなります。fromはモジュールの一部だけを利用できますが、モジュール名を省略できることが多くなります。どちらを使うかは、目的や好みによって異なります。

- モジュール内のほとんどの機能を使う場合はimportを使う
- モジュール内の一部の機能しか使わない場合はfromを使う
- モジュール内に同じ名前の機能がある場合はimportを使って区別する
- モジュール名が長すぎる場合はimport asを使ってエイリアス（別名）を付ける

### fromやimportの使い方の例

```py:
# モジュールのインポート
import module_name

# モジュール内の特定の要素のみをインポート
from module_name import function_name

# パッケージのインポート
import package_name

# パッケージ内の特定の要素のみをインポート
from package_name import module_name

# パッケージ内の特定のモジュールから特定の要素をインポート
from package_name.module_name import function_name
```

### ライブラリから * を import 

from math import * みたいな書き方も見ます。ワイルドカードを使ったimportは非推奨のコードです。mathライブラリのあらゆるモジュールを取り込むという意味ですが、未知のコードを読み込んだり、定義済みの名前を上書き・コンフリクトしてしまう可能性があるからです。

## 終わりに

Qiitaとか技術ブログもいいけど、まずはPythonのドキュメンテーションを検索してちゃんと読むのも大事ですね。

もうちょっと図や表を使って整理したりimportパターンを網羅したいですがそれはまた今度。