OmniAICreator/Qiita-1.07M huggingface dataset:
Android Management API を使って専用端末をつくるためのノウハウを少し

[Rakuten mini](https://network.mobile.rakuten.co.jp/product/smartphone/rakuten-mini/)とか、一昔前の端末は普段遣いにはつらいけど、ICカード専用端末だったり音楽プレイヤーとして使うには結構まだまだ使えます。

ただ、専用端末なら専用端末らしくしたいですよね。この記事では、Android Management APIで利用できる専用端末機能について説明します。

## そもそもAndroid Management APIはどうやったら利用できるの？

手っ取り早いのは、Google公式のサンプルを利用することです。

https://developers.google.com/android/management/quickstart?hl=ja

https://colab.research.google.com/github/google/android-management-api-samples/blob/master/notebooks/codelab_kiosk.ipynb

上から順番に流していけば、"ポリシー"が適用できる状態になるはずです。

## KIOSKモードと、カスタムランチャーモード

Android Management APIで利用できる専用端末機能には、２種類のモードがあります。

Androidのホーム画面の代わりに1個のアプリを固定しまうのが、KIOSKモード。
そうじゃなくて、いくつかのアプリだけをシンプルなホーム画面から起動できるのが、カスタムランチャーモード。

||KIOSK|カスタムランチャー|
|--:|:--:|:--:|
|画面イメージ|![kiosk1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/74571/502e53a6-ba5d-fb0f-794a-9b9ec767fa09.gif)|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/74571/dac4f4d8-f0ef-8aff-cd1a-0f50b9679109.png)|


KIOSKは、一見すると1個のアプリ以外起動できないように見えるが、じつは起動制限は特にないので、上記の例だと、LINEから起動可能なアプリは起動できる。キャンペーンの連絡があってキャンペーン情報をブラウザで見ることができない？なんてことはないのでご安心を。

いっぽうで、設定画面などにはどちらのモードでも飛べないので、たとえば「WiFiが繋がらない」といったときのトラブルには対応できないことに注意しておきたい。

### KIOSKモードにする方法

```
{
  "applications": [
    {
      "packageName": "com.android.chrome",
      "installType": "FORCE_INSTALLED"
    },
    {
      "packageName": "jp.naver.line.android",
      "installType": "KIOSK"
    }
  ],
  ...
}
```

このように、applicationsで**１つのアプリ**を `installType: KIOSK` 指定する。

### カスタムランチャーモードにする方法

```
{
  "applications": [
    ...
  ],
  "kioskCustomLauncherEnabled": true,
  ...
}
```

このように `kioskCustomLauncherEnabled: true` 指定をする。

## 設定画面へのアクセスや電源ボタン長押しメニューを封じる

上記のサンプルを動かしたPixel 6aでは設定画面に飛べないが、いくつかのデバイスでは、**ボリュームキーを押して、そこから音量設定に飛び、さらにそこから設定画面に飛べてしまう**。

![kiosk2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/74571/3d77be6a-40e2-c5e3-1769-94c6f423050f.gif)

また、**電源ボタン長押しメニューもデバイスによってはカスタマイズされている**ので、これを封じたいケースもあるだろう。

https://developers.google.com/android/management/reference/rest/v1/enterprises.policies?hl=ja#KioskCustomization

`kioskCustomization` というのを使うといろいろ封じたり、逆に許可したりもできる。

```
  "kioskCustomization": {
    "powerButtonActions": "POWER_BUTTON_BLOCKED"
  },
```

→長押ししても「ブルッ」とするだけでメニューが出なくなる。

```
  "kioskCustomization": {
    "deviceSettings": "SETTINGS_ACCESS_BLOCKED"
  },
```

→ボリュームキーからの設定画面へ飛べなくなる
![kiosk3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/74571/ef16a523-debe-8e16-2f86-f6c0dbfc84cf.gif)


## まとめ

ここまで理解していれば、あとは応用次第で、

* カメラ/ギャラリー専用端末
* 音楽プレイヤー専用端末
* キャッシュレス決済専用端末

などいろいろ作れるようになります。

使い古したデバイスを単機能で使いたい場合には本当に便利なので、皆さまぜひAndroid Management APIの専用端末を試してみてください。
KillercodaへKatacodaのシナリオを移行する (Node-RED Playground)

# はじめに

2022年6月15日にKatacodaのサービスが終了しました。

LinuCの資料を見ていた時にKatacodaの代替え先としてKillercodaを見つけました。

https://lpi.or.jp/news/event/page/20230520_01/20230520_linuc.pdf

https://killercoda.com/

# Katacodaのシナリオを移行する

![スクリーンショット 2023-12-11 0.30.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/b72f27c7-9859-c1de-2713-fd7c66a25851.png)

ドキュメントを見ると、KatacodaのシナリオをほぼそのままKillercodaへ移行できそうです。

https://killercoda.com/creators

サンプルのシナリオを参考にして、一番シンプルなシナリオを作成します。

https://github.com/killercoda/scenario-examples/tree/main/foreground-background-scripts

![スクリーンショット 2023-12-11 0.39.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/ac09d56f-7679-f066-d03b-6f8dcf6dfa0d.png)

Killercodaのシナリオの作り方を見ながらGitHubの設定を行います。

https://killercoda.com/creators/get-started

## 1. GitHubのユーザー名とレポジトリ名を登録する

![スクリーンショット 2023-12-11 0.50.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/f7e2fe7c-e89a-28b0-c6f0-5544e5c35dfa.png)

## 2. レポジトリのDeploy Keysを設定する

![2-1_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/ba63fcf1-7255-6e48-982e-7cbfac80d937.png)

![2-2_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/4b4bb9d1-7ef6-920e-4eb4-5ab3b7deea98.jpeg)

## 3. レポジトリのWebhooksを設定する

![3-1_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/09561f2e-79cc-2a2b-5c51-607509fd62bd.png)

![3-2_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/4c4bad02-7b26-87c6-ac05-baea16508a98.jpeg)

# Killercodaのシナリオ

nvm、Node.js、Node-REDをインストールして起動するバージョンとDocker imageでNode-REDを動かすバージョンを作成しました。

![スクリーンショット 2023-12-11 0.50.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/b6e54dd5-41f6-3a96-708a-6b18f6682fd6.png)

https://killercoda.com/node-red-tester/

https://github.com/kitazaki/killercoda-scenario/

## シナリオを選択する

Node-REDが起動するまでしばらく待ちます。
STARTを押して次のページへ進み、URLをクリックするとNode-REDフローエディタが表示されます。
では、良きNode-REDライフを！

![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/5bb3fb39-adc7-2d8a-402c-8d87a5e84ea6.jpeg)

![2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/43b502fb-7566-4234-af32-3892f4da680e.jpeg)

![3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/cfbe08db-548a-8adb-4d43-cf90baf8dd35.jpeg)

![スクリーンショット 2023-12-11 1.14.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/3591ac93-09b8-84e8-32a9-4b809faf0734.png)

![スクリーンショット 2023-12-11 1.13.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/ea41feb4-efb1-d234-561c-81a326bbf936.png)
格安PCのWindows がボリュームライセンスという闇

## TL;DR

- 格安のWindows PCを購入したらWindowsがボリュームライセンスだったんだが！？
  - HWだけほしくて買ったので個人としてはセーフ！
- 安いものを買うときは**安かろう悪かろう**の気持ちで！

## 概要

[Proxmox](https://proxmox.classact.co.jp/)の自宅評価用に[格安PC](https://www.amazon.co.jp/%E6%9C%80%E5%A4%A72-9GHz-16GB%E3%81%BE%E3%81%A7%E5%A4%89%E8%A3%85%E5%8F%AF-2TB%E3%81%BE%E3%81%A7%E6%8B%A1%E5%A4%A7%E5%8F%AF%E8%83%BD-%E7%9C%81%E3%82%B9%E3%83%9A%E3%83%BC%E3%82%B9pc-%E8%B1%8A%E5%AF%8C%E3%81%AA%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%BC%E3%83%95%E3%82%A7%E3%83%BC%E3%82%B9/dp/B0BHZCLGXH/ref=sr_1_36?adgrpid=59011200611&gclid=CjwKCAiAjrarBhAWEiwA2qWdCFxUMR0aH7PWWV0UbdjuB36pb4tspVykZJe_dPre8sA4ojeFX2-7FxoCiuIQAvD_BwE&hvadid=651252578864&hvdev=c&hvlocphy=1009306&hvnetw=g&hvqmt=e&hvrand=9243949584473357870&hvtargid=kwd-296004158587&hydadcr=1399_13593663&jp-ad-ap=0&keywords=%E3%83%9F%E3%83%8Bpc&qid=1701698964&sr=8-36&th=1)をポチりました。
※自分で組んだり、ラズパイあたりを使ったほうが安いのかと思ったのですが、ミニPCのほうが安かったので。

でもせっかくWindowsがインストールされているなら何か有効活用（Proxmox上のゲストOSにインストールとか）できないかな～ってライセンス確認したらびっくりした、という闇。


## Windows OSのライセンスの種類
まずはWindows OSのライセンス種別の確認です。

| ライセンス種別           | ライセンスの対象   | 購入方法                              | 利用者                     | 備考                                      |
|----------------------|--------------|-------------------------------------|-------------------------|-----------------------------------------|
| フルパッケージ (FPP)   | 購入者          | 単体で購入                                | 個人ユーザー                  | 「リテール（Retail）ライセンス」とも呼ばれる       |
| OEMライセンス          | ハードウェア       | PCメーカーや販売代理店を通して供給                  | 個人ユーザー/法人ユーザー       | 「DSP版」と「OA3版」がある                   |
| ボリュームライセンス (VL) | 法人            | 法人がOSのライセンスを複数個用意する際に使用         | 法人ユーザー                  | EnterpriseエディションはVL限定              |


## 確認結果
コマンドプロンプトから`slmgr -dli`で確認したら以下の結果でした。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2459468/d2e254cb-49ae-c168-0cab-eff128a3371a.png)

見ての通りボリュームライセンスですね…
まさに闇って感じです。


## そんな闇からの防衛術
安さには理由があった！というところで、**安かろう悪かろう**の精神で行くことが防衛術でしょうか。


一方で[このようなレビュー](https://www.amazon.co.jp/gp/customer-reviews/RD6DEPGN32U0P/ref=cm_cr_getr_d_rvw_ttl?ie=UTF8&ASIN=B0BHZCLGXH)もあり、実は合法なのかもしれません。
※個人としてはHWだけ入手できれば良かったのでこれ以上の調査はしません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2459468/75ada816-6e26-a2da-0f66-e4b9435f527c.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2459468/16bf73f6-a04f-e8c7-22b8-37fbdc74a51e.png)


ですが、[利用中のWindows OSが利用不可能になるリスク](https://answers.microsoft.com/ja-jp/windows/forum/all/%E3%83%9C%E3%83%AA%E3%83%A5%E3%83%BC%E3%83%A0/50cbed05-f144-482c-960c-7eef25d68270)はある点は認識しておいたほうがいいかもしれません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2459468/a3782c75-2a16-5b13-aeb0-7abc84cc646c.png)


## 参考


https://answers.microsoft.com/ja-jp/windows/forum/all/%E3%83%9C%E3%83%AA%E3%83%A5%E3%83%BC%E3%83%A0/50cbed05-f144-482c-960c-7eef25d68270

https://www.amazon.co.jp/gp/customer-reviews/RD6DEPGN32U0P/ref=cm_cr_getr_d_rvw_ttl?ie=UTF8&ASIN=B0BHZCLGXH

https://www.itmedia.co.jp/pcuser/articles/2310/19/news191.html#3
chakraUIを用いた左メニュー作成

# はじめに
この記事は2023年度の振り返りです。

chakraUIを利用しています。
これだけで色々なデザインを再現でき、今のところ困っていないので重宝しています
ただ、この場合どうするんだっけ？というのがあったので、その時の備忘録です。


# 目標レイアウト
PCアプリのLINEの様な左メニューがあるレイアウト

イメージ図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632357/1cccdf85-536d-aaaf-a894-df02663d4c2a.png)

# 抜粋のソース
```javascript:main.tsx
  <Grid
    templateAreas={`"nav main"`}
    gridTemplateRows={'100% 1fr 30px'}
    gridTemplateColumns={'50px 1fr'}
    h="100vh"
    gap="0"
  >
    <GridItem bg="teal.400" area={'nav'} p={0}>
      <Stack
        height="100vh"
        direction="column"
        alignItems="center"
        justifyContent="space-between"
      >
        <Box p={2}>
          <NavMenu />
        </Box>
        <Box p={2}>
          <NavConfig />
        </Box>
      </Stack>
    </GridItem>
    <GridItem
      bg="white"
      area={'main'}
      p={2}
      overflowY="scroll"
      borderTop="1px solid"
      borderColor="gray.200"
    >
      <Outlet />
    </GridItem>
  </Grid>
```
```javascript:NavMenu.tsx
   <VStack>
    <NavLink to="/">
      <Button colorScheme="gray" variant="solid" size="sm" w="100%">
        <FontAwesomeIcon icon={faHouse} />
      </Button>
    </NavLink>
    <NavLink to="/todo">
      <Button colorScheme="gray" variant="solid" size="sm" w="100%">
        <FontAwesomeIcon icon={faRectangleList} />
      </Button>
    </NavLink>
  </VStack>
```
```javascript:NavConfig.tsx
  <VStack>
    <ConfigTabs />
    <ChangeLogDrawer />
  </VStack>
```

# 完成図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632357/4f80c0f2-686e-d5d4-8363-4f7bdb8818d1.png)

# さいごに
chakraUI色々できて、いいですよね。。。
react以外の対応版も出てくれると嬉しいのですが
2023年のAlbaについて

## はじめに

この記事は[Ruby Advent Calendar 2023](https://qiita.com/advent-calendar/2023/ruby
)の記事です。参加しようとしたときにはすでに枠が埋まっていたのですが、12月2日の枠で「代わりに投稿」できそうだったので投稿しています。

## Albaについて

Albaは私（@okuramasafumi）が開発しているRuby向けJSONシリアライザです。

https://github.com/okuramasafumi/alba

ウリは高速さ・容易さ・機能性です。また、JRubyとTruffleRubyでも動作します。詳しくは上記リンクからREADMEを参照して下さい。

## 2023年までのコミット数

さて、Albaの開発は2020年から始まっており、2022年にはほぼ完成形と呼べるに至りました。バージョンとしては[2.1.0](https://github.com/okuramasafumi/alba/releases/tag/v2.1.0)がリリースされています。

実際、コミット数を以下のコマンドで調べると2023年は少な目となっています。

```
❯ git log --since="2020-01-01" --until="2020-12-31" --pretty=oneline | wc -l
     216
❯ git log --since="2021-01-01" --until="2021-12-31" --pretty=oneline | wc -l
     290
❯ git log --since="2022-01-01" --until="2022-12-31" --pretty=oneline | wc -l
     229
❯ git log --since="2023-01-01" --until="2023-12-31" --pretty=oneline | wc -l
     144
```

では、2023年は何をしていたのか、というのがこの記事のテーマです。

## gemをメンテナンスする

https://github.com/okuramasafumi/alba/issues?q=is%3Aissue+is%3Aclosed

2023年にはissueが約15個ほど投稿されました。ペースとしては月に1つくらいです。これらのうちのいくつかはHOW TO的な話だったりREADMEに書いてある内容だったりするのですが、一方で他のものはバグの報告だったりします。

バグがあるなら直さなくてはいけません。が、ここで「バグ」というのは完全に「壊れている」ということ以外に「こうなっているのが自然では？」というものも含みます。「含みます」と書きましたが、「含んでいます」のほうが正確かもしれません。つまり、Albaの開発においてはユーザーの自然な期待に反しているものについてバグとして扱うことにしています。ここで「自然な期待」というものはあえて広めに定義しています。

例えば以下のようなissueを考えます。

https://github.com/okuramasafumi/alba/issues/277

これはエラーというわけではありません。しかし、あるクラスに定義されたメソッドの優先度がシリアライズ対象のオブジェクトが持つ同名のメソッドよりも低いというのは直感的ではありません。歴史的経緯によりこうなっているという仕様であり、当初は修正を渋っていたのですが、最終的にはバグと見なして修正することにしました。

しかし、全てのissueについて修正を行うわけではありません。例えば以下のissueを取り上げます。

https://github.com/okuramasafumi/alba/issues/346

これは機能追加の要望ですが、既存の機能セットとの重複やコードの複雑性との兼ね合いを考えたとき、単純に追加するのはあまり良くないと思われたため、提案の形で返信をしたところ、納得してもらってクローズされました。

このような修正を続けた結果、現在のAlbaは非常に洗練されたもの（当社比）となっています。

## ゼロissueの達成

https://gihyo.jp/news/report/01/rubykaigi2019/0003 にあるように、Jeremy Evansという人は自身の開発するgemのissueをゼロにするポリシーを持っているようです。非常にかっこいいポリシーだと思い、私も真似をしてみることにしました。

結果、無事にオープンなissueを0にすることができました。利用者がそこまでは多くないのと、わかりやすいバグや機能要望はすでに修正済みであることが大きいと思います。

## Albaにおける面白いRubyコード

ここでは少し目線を変えて、Ruby的な側面からAlbaを紹介したいと思います（Ruby Advent Calendarの記事ですし！）

例えば以下のコードです。

https://github.com/okuramasafumi/alba/blob/40cbf5f85e88cf12c2bf2dff4140cf4a7bd59956/lib/alba/resource.rb#L25-L35

[このコミット](https://github.com/okuramasafumi/alba/commit/a52b2c14b090dace8cb13e26c6c186c800db09dd)で導入されたものですが、以前のコードでは各内部変数をループで初期化しており、その際に`instance_variable_set`を使っていたため速度に問題がありました。この部分がボトルネックではないことはわかっていたのですが、それでも遅いのは嫌だったので改善の方法を探りました。単純に変数を列挙すれば速度は改善しそうでしたが、それでは変数が増えたときの修正箇所が増えてしまいます。検討の結果、変数を単純に列挙したコードと同等のコードを文字列として生成してそれを一括で`eval`することで両者のメリットを得ることができると判断しました。もちろんデメリットとしてはコードが複雑になることですが、`initialize`メソッド内部で完結するので割に合うかなというところです。

それ以外にもいくつかちょっと凝ったコードはありますが、全体的には素直な書き方にして読みやすさを重視しています。

## まとめ

gemをメンテナンスすることについて日本語で書かれた記事はあまり見かけないのでこの記事を書きました。何かの参考になれば幸いです。
RailsのTurbo Framesを利用してシンプルな遅延読み込みを実現

# はじめに

Railsアプリでデータベースの内容を表示する際、データベースのクエリーが返ってくるまでに時間がかかる場合に、結果が返ってくる前の段階でスケルトンを表示したいことがありました。

# Turbo Framesの利用

この挙動はTurbo Framesの遅延読み込みを導入すれば解決できそうと考えて調べていたところ、以下の記事が参考になりそうでした。

https://railsnotes.xyz/blog/simple-lazy-loading-hotwire-turbo-frames-rails

## 遅延読み込み先の設定

```ruby:app/controllers/welcome_controller.rb
class WelcomeController < ApplicationController
  def index_lazy
    @contents = Content.all.limit(10)
  end
end
```

```erb:app/views/welcome/index_lazy.html.erb
<%= turbo_frame_tag :index_lazy do %>
  <% @contents.each do |content| %>
    <%= link_to content, data: {turbo_frame: '_top'} do %>
      <div><%= content.name %></div>
    <% end %>
  <% end %>
<% end %>
```

```ruby:config/routes.rb
Rails.application.routes.draw do
  get '/index_lazy', to: 'welcome#index_lazy'
end
```

## 遅延読み込み元の設定

```erb:app/views/welcome/index.html.erb
<%= turbo_frame_tag :index_lazy, src: '/index_lazy', loading: :lazy do %>
<% end %>
```

# スケルトンの設定

リストが表示されるまでは空白となっているため、空白ではなくスケルトンを表示するようにします。

```erb:app/views/welcome/index.html.erb
<%= turbo_frame_tag :index_lazy, src: '/index_lazy', loading: :lazy do %>
  <% 10.times do  %>
    <!-- Skelton -->
  <% end %>
<% end %>
```

# おわりに

Turbo Framesの遅延読み込みを導入して、ページ表示の挙動を制御することができました。Hotwire関連はまだ使った経験が少ないので、いろいろと試していきたいと思います。
IBM i(旧AS400)のQSHでSSHが実行できない時に確認すること


## ホストコードページの設定を確認

使用するクライアントアプリによって設定する場所は異なりますが、IBM i Access Client Solutionsでは以下の「ホスト・コード・ページ」という箇所を「939 日本（拡張ローマ字）」に設定する必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243130/c75488a1-3ab7-1fe1-28b1-0fdc847efb02.png)

## CCSIDの設定を確認

文字化けを防ぐ為に、CCSIDを`5035`に設定する必要があります。

```bash
CHGJOB CCSID(5035)
```

## サインイン中のユーザーIDが8文字以下になっているか確認

IBM iのソフトウェアの多くが[AIX OS](https://ja.wikipedia.org/wiki/AIX)向けに作成されている為、ユーザーIDが8文字を超えることが基本的に想定されていません。
もし8文字を超える場合、メモリのバッファオーバーフローなどが発生する可能性がある為、あえて制限されています。

どうしても8文字を超えるユーザーIDを使用したい場合は、`/QOpenSys/QIBM/UserData/SC1/OpenSSH/etc/sshd_config`に以下の設定を追加するか

```config:sshd_config
ibmpaseforienv PASE_USRGRP_LIMITED=N
```

以下のコマンドを実行することで、10文字まで使用可能になります。

```bash
ADDENVVAR ENVVAR(PASE_USRGRP_LIMITED) VALUE('N') LEVEL(*SYS)
```
GradioをAWS EC2 Instanceで動かす方法

本記事は タダの2年目 Advent Calendar 2023 の11日目の記事です。

他の人が書いていた[Streamlitで遊んでみよう](https://qiita.com/toro-osushi/items/d2443afa2d45fdc3a154)という記事が勉強になったので、別のモック製作系ライブラリであるGradioについての紹介記事、GradioをAWS EC2 Instanceで動かす方法を書こうと思います。

GradioはPythonのライブラリで、使うことによってお手軽にWEBアプリのモックを作成することができます。まだ軽く使った段階なのであまり深くは語れませんが、機械学習系のWEBアプリに適していると言われています。
Streamlitとどう違うのかはそのうち両方使って検証したいですね。
参考:[デモ作成ライブラリGradioを使ってみた【Python】](https://engineerblog.mynavi.jp/technology/introduction-gradio/)


# 初めに
最初に環境を置いておきます。
AWSのLinuxインスタンスならだいたい動くと思います。
ハードウェア:AWS Ec2 Instance t3.large
OS:Ubuntu 22.04

# 1.ローカル環境でGradioを動かすには
取りあえずローカル環境でGradioを動かしてみます。
Gradioを使うにはまずライブラリをinstallする必要があります。
```
$pip install gradio
```
ライブラリをインストールしたら後はコードを書くだけで基本動きます。
コードの例:[AIモデルの予測結果の可視化を楽にしたい? Gradioを使ってみよう!](https://zenn.dev/ohke/articles/9ce51323c44f80)
```python
import gradio as gr

def hello(name: str) -> str:
    return f"Hello, {name}!"

hello_interface = gr.Interface(fn=hello, inputs="text", outputs="text")
hello_interface.launch()
```
上記のコードを実行する。
```
$python app.py
```
実行結果
下にアクセスするとWEB UIを確認することができます。
```
Running on local URL:  http://127.0.0.1:7860
```
たったこれだけで動いて、こんな感じのシンプルなUIを作ってくれます。
![スクリーンショット 2023-12-11 001044.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276309/a8690770-7e04-f1ac-3b11-28f559ba8efd.png)
しかし、AWS EC2 Instanceで動かす場合一工夫が必要になります。

# 2.AWS EC2 InstanceでGradioを動かすには
EC2でGradioを動かすにはPythonのコードとEC2のセキュリティグループなどの設定を変更する必要があります。
まずはPythonのコードから。
現状のコードでは、ローカル(実行しているPC)からしかアクセスができないので、サーバー化してやる必要があります。そこで、launch()の中にオプションを入れます。
```python
hello_interface.launch(server_name="0.0.0.0")
```
このオプションにより、外部のPCからでもGradioにアクセスできるようになります。

次にEC2のセキュリティグループの設定です。
AWSのセキュリティグループの設定にはインバウンドルールとアウトバウンドルールの二種類があります。
Gradioの通信を通すようにその二つのルールを変更しなければいけません。
1.インバウンドルール
Gradioの通信プロトコルはTCPであり、Gradioはデフォルトでは7860のポートを使用します。この使用するポートはこちらで指定できるため、好きなポートを使ってもらって構いません。
従って、インバウンドルールにプロトコルはTCPであること、ポートは7860を使うことを明記してルールを追加します。
![スクリーンショット 2023-12-11 003026.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276309/3769e2f4-251e-5637-4f68-13fa71e4a4ea.png)
2.アウトバウンドルール
こちらは基本的にすべてのトラフィックが許可されてると思いますが、もし制限されている場合はこちらもインバウンドルールと似たような形でルールを追加してください。

もしかしたらマシン自体の設定でファイアウォールを設定している場合がありますので、動かない場合はファイアウォールも確認してみてください。

以上の準備を整えたらEC2で実行したGradioに外部のマシンからアクセスが可能になります。
server_portを書き換えたため、実行結果は次のようになります。
```
Running on local URL:  http://0.0.0.0:7860
```
勿論、外部のPCからこのURLへアクセスしてもGradioにアクセスすることはできません。
Gradioに外部のマシンからアクセスする際は、
```
http://(EC2のパブリックIPアドレス):7860
```
にアクセスしてください。

以上がGradioをAWS EC2 Instanceで動かす方法になります。
ありがとうございました。
Mapbox GL JS ver3 で実装された distance expression

# 背景
昨日、[MapLibre GL JS の expression](https://qiita.com/humohumo/items/6460188ab7e8214a89bd#%E8%B7%9D%E9%9B%A2distance) で書こうとしたけど未対応だった、`distance` expression。
Mapbox GL JS (ver3.0.1)での結果をあらためてまとめてみました。
なお、Mapbox GL JS の `distance` expressionは、投稿時点（2023.12.11）時点では、日本語ドキュメントでは「未対応」となっていますが、先日リリースされた ver 3.0.0 で実装された機能です。

# 書き方
```JavaScript: コード
'circle-color': [
  'interpolate', 
  ['linear'], 
  [
    'distance', 
    { type: 'Point', coordinates: [center.lng, center.lat] } // ここでは、center = map.getCenter()
  ], 
  0, '#0ff',  // 近いと水色
  100*1000, '#ff0', // 100キロ離れると黄色
  200*1000, '#f0f' // 200キロ以上離れるとマゼンダ
],
```

# 結果
<p class="codepen" data-height="400" data-default-tab="result" data-slug-hash="RwvdOLp" data-user="humo-tech" style="height: 400px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/humo-tech/pen/RwvdOLp">
  maplibre expressions (within)</a> by humo (<a href="https://codepen.io/humo-tech">@humo-tech</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

# まとめ
簡単に書けました。おぉ。これはいいですね。
駅から◯キロメートル離れた位置にある店舗、とかそういうのに使えますかね。

# おまけ
先日、#30DayMapChallenge 時に試していたものがあったのを忘れていました。

https://x.com/hrykyn/status/1729565753471275144?s=20

これは「ポリゴンとポイント」の距離判定をしたものなんですが、タイルの切れ目で色塗りが変わってしまったりしたので、こういう使い方はあまり想定されていないのかな？という印象です。
（「ポイントとポイント」の使い方が一番しっくり来てます）
[IBM Cloud認定試験] IBM Cloud for SAP v1 Specialty 受験体験記

# IBM Cloud for SAP v1 Specialtyについて
IBM Cloud for SAP v1 Specialtyは、主にIBM CloudにおけるSAPの分野の専門性を認定する試験です。
現在は英語だけではなく、日本語でも受験可能な試験となっています。

https://www.ibm.com/training/certification/ibm-cloud-for-sap-v1-specialty-S2112400

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134250/fd8ffcc2-d3d0-140f-9467-b46707164f9f.png)

# 学習教材
### Study Jam （おすすめ度：★★★）

https://community.ibm.com/community/user/cloud/discussion/study-jam-discussion-for-ibm-cloud-for-sap-specialty-2023

- 2023年の6月に開催されたグローバルの試験対策セッションのリプレイと資料です。
- 内容が一通り網羅されているので、試験対策のとっかかりとしてはよいのではないかと思います。
- Day1からDay3までのリプレイを見たうえでQuizに合格すると、Open Badgeがもらえます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134250/a6c257c9-4fc6-b537-33c1-683e01002aff.png)

### ラーニングパス （おすすめ度：★★★）

https://www.ibm.com/training/path/ibmcloudforsapspecialty

- IBMが公式で提供しているラーニングパス（試験対策のe-Learningコース）です。
- Study Jamの内容をより深掘りしたような内容となっている印象です。
- ラーニングパスの中に記載されている細かい内容についても問われる場合がありますので、一通り内容を抑えておくとよいかもしれません。
- こちらも途中で出てくるQuizに合格するとOpen Badgeがもらえます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134250/4b853d37-14a3-42ee-f413-e960ff8ecbd2.png)

### IBM Cloud Prep （おすすめ度：★★★★）

https://ibm-cloud-prep.yourlearning.ibm.com/certifications/ibm-cloud-sap

- 模擬試験とStudy Guideを提供しているIBM Cloud認定試験の専用対策サイトです。
- 基本的には、ラーニングパスを一通りやったあと、ここの模擬試験をやって、わからないところがあったらStudy Guideを参照するという流れで学習を進めました。
- Study Guideの内容は、ラーニングパスの内容で網羅されている印象でしたので、わからないところがあったときにチラ見したくらいでした。
- 模擬試験とStudy Guideは、英語で提供されていますが、日本語で受験される場合は、Google翻訳やDeepL翻訳などのツールを利用して、学習を進めるとよいと思います。

# 試験結果
テストセンターで受験し、無事に合格することができました。ちなみに試験言語は日本語でした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134250/f5842469-1244-f938-5783-1ba3f46cbb05.png)

# 受験した感想
- そこそこ細かいサービスの仕様についての問題も出題されましたが、ラーニングパスとIBM Cloud Prepの模擬試験をやって、内容を理解していれば回答を推測できる問題ばかりだった印象でした。
- SAPそのものの知識を問う問題は出題されないため、SAPの知識や経験がない方でも十分に合格が狙える試験だと思いました。
- とはいえ、SAPの基本用語やソリューションの概要などを理解していないと解けない問題も出題されるため、そのあたりはきちんと抑えておく必要があります。
- IBM Cloudの基礎知識とSAPの基礎知識を交えて問う問題がほとんどなため、試験ページのOverviewに記載されている通り、受験前にProfessional Architect, Professional Developer, Professional SREのいずれかを取得されることを強くおすすめします（おそらくProfessional Architectが一番被りが多いと思います。）

# 個人的に抑えておいたほうがよいと思った範囲
メモ書き程度ですが、以下のあたりは特に抑えておくとよいと思いました。
当然ですが、これらが試験に必ず出るという意図ではありませんので、ご注意ください。

- SAPの基本用語（S/4 HANAとはなんぞや？など）
- IBM CloudのSAP認定ソリューション
    - Bare Metal for Classic, Virtual Servers on VPC, Power VS, VMware Solutions Dedicatedの4つ
    - それぞれの特徴やユースケースなど
- Network
    - VPC, Direct Link, Transit Gatewayあたり
- Security
    - セキュリティグループ, ACL, Hyper Protect Crypto Servicesあたり
- Storage
    - Block Storage, File Storage, Object Storageの特徴やユースケース
    - Veeamなどのバックアップソリューション
Amazonの良さについて今一度考える

# Amazonは便利：Amazonの良さについて考える

## 内容
Amazonはオンラインショッピングの第一線にいるといっても過言ではない程の、多くの便利な機能を提供しています。本記事では、Amazonの良さについて注目すべき機能や利点を掘り下げていきます。

##目次
1.**Amazon Prime会員特典の拡充**
-迅速な配送だけでなく、Prime VideoやKindle Unlimitedなどのデジタル得点も紹介します。

2.**スマートスピーカーとの連携**
-Amazon EchoやAlexaとの統合により、新しい生活スタイルを提供しています。

3.**パーソナライズされたショッピング体験**
-推奨商品やパーソナライズされた広告により、ユーザー体験が向上している点を取り上げます。

4.**Amazon Payの利用拡大**
-ウェブサイトやアプリでの決済が簡単になり、オンライン決済の一手段としての役割を紹介します。

## 本文
### 1. Amazon Prime会員得点の拡充
Amazon Prime会員は、迅速な配送だけでなく、Prime VideoやKindle Unlimitedといったデジタル特典にもアクセスできます。

### 2. スマートスピーカーとの連携
Amazon EchoやAlexaは、スマートホームデバイスとの連携や音声コマンドによる操作が可能です。これにより、ユーザーはかていないの様々な機器を制御し、新しい生活様式を築くことができます。

### 3. パーソナライズされたショッピング体験
Amazonは豊富なデータをもとにユーザーに最適な商品を提案します。推奨商品やパーソナライズされた広告を通じて、ユーザーはより興味深い商品にであうことができます。

### 4. Amazon Payの利用拡大
Amazon Payはオンライン決済をより簡単にし、ウェブサイトやアプリでのシームレスな決済体験を提供しています。これにより、購買プロセスがより効率的になります。

## まとめ
Amazonが提供するこれらの便利な機能は、私たちの日常生活を変えています。これからもAmazonがどのように進化していくか、期待が高まります。

## リンク
-[Amazon Prime会員特典](https://www.amazon.co.jp/amazonprime)
-[Amazon Echo](https://www.amazon.co.jp/amazonecho)
-[Amazon Pay](https://pay.amazon.com/jp)
作成したレポートの0からの引き渡し

# 本記事で伝えたいこと
Power BIを活用したい方、活用を促進したい方のための資料を作成しました。

# 資料の利用シーン
1. 有識者・経験者が依頼を受けてレポートを作成
2. 依頼者の方でもレポートのメンテナンスをしたいので、Power BI Desktopをインストール
3. レポートを作成した人が依頼者に設定内容や方法を説明
→ <font color="Blue">このタイミングで使う資料</font>
4. Power BIの利用者が増加

# 作成した資料
資料の上から順に参考のサイトや作成したものを表示しながら説明する。
+　「必須」列：説明時に解説する項目
-　「説明後に自習」列：説明時は概略のみ伝えて、後から設定内容を確認しながら自習する項目

![0からの引き渡し_20231210-01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3626635/6e5c9876-1301-7156-7a27-c06f4b183c96.jpeg "0からの引き渡し")
ChatGPTをGASで使う

# APIの練習
ChatGPTのAPI練習としてGASを使ってみました。
練習用なのでコードは雑です。。

処理内容は**ボタンを押したら原文をリライトする**

手順
1. OpenAIのサイトに行き、APIキーを発行する
2. スプシを開いて拡張機能 > Apps Script を開きます。
3. プロジェクト設定 > スクリプトプロパティで API_KEY を設定して先程発行したトークンを貼ります。
4. 設定ができたら、ソースコードを作成したら関数名をコピーしておいてボタンを押したら処理が実行できるようにしたら完了
<details>
<summary>ソースコード</summary>

```javaScript
function ChatGptOutput() {
  //シートの取得
  let sheet = SpreadsheetApp.getActiveSheet();

  //取得してくるデータ
  let original_for_output_text = sheet.getRange("A:A").getValues();
  let output_length = original_for_output_text.filter(String).length;
  let datas = sheet.getRange(1,1,output_length).getDisplayValues();
  let exeptaionText = "下記をそれぞれリライトしてください";
  let mtext = "";
  //出力処理 説明文なので1からスタート
  for(var data = 1;data < datas.length;data++)
  {
    var spritData = datas[data].toString().split("\n");
    for(var i = 1;i < spritData.length;i++)
    {
      mtext += spritData[i]+"\n";
    }
  }
  let message = [{'role': 'user', 'content': exeptaionText+"\n"+mtext}]
  Logger.log(message);
  const response = ChatGptMessage(message);
  Logger.log(response);

  //取得したデータを行ごとに分ける
  let spritTextArray = response.split("\n");
  Logger.log(spritTextArray);

  let sum = 0;
  for(var data = 0;data < datas.length-1;data++)
  {
    for(var i = 0;i < 3;i++)
    {
      if (spritTextArray[sum] !== undefined && spritTextArray[sum] !== null) {
        var text = spritTextArray[sum].slice(1);
        let setData = sheet.getRange(data+2,i+2);
        setData.setValue(text);
        sum++;
      }
    }
  }
}

function ChatGptMessage(message)
{
    // OpenAIのエンドポイント
    const apiUrl = 'https://api.openai.com/v1/chat/completions';

    // パラメータ設定
    const requestBody = {
    'model': 'gpt-3.5-turbo',
    'temperature': 0.7,
    'max_tokens': 2048,
    'messages': message
  }

    // 送信内容を設定
    const request = {
      method: "POST",
      muteHttpExceptions : true,
      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer ' + PropertiesService.getScriptProperties().getProperty('API_KEY'),
      },
      payload: JSON.stringify(requestBody),
    }

    let response = JSON.parse(UrlFetchApp.fetch(apiUrl, request).getContentText());
    try {
        // ChatGPTのAPIレスポンスをセルに記載
      if (response.choices) {
        return response.choices[0].message.content;
      } else {
        // レスポンスが正常に返ってこなかった場合の処理
        return response;
      }
      } catch(e) {
        // 例外エラー処理
        return e;
      }
}
```
</details>

![スクリーンショット 2023-12-10 233241.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550031/2b363241-8278-0ca6-354c-15763e5bdc75.png)
Dockerfileでcd使いたい場合

# 失敗例

「RUN cd /tmp」を実行しても次の行ではカレントディレクトリは移動したことにならないので、「RUN cd ./tesh.sh」の実行で、そんなファイル無いというエラーになる。

```:Dockerfile
RUN cd /tmp
RUN cd ./tesh.sh
```

# 方法①

cd の代わりに WORKDIR を使う。
ただし、以降の命令のカレントディレクリも変わってしまうので、それは困るというなら「方法②」

```:Dockerfile
WORKDIR /tmp
RUN ./tesh.sh
```

# 方法合②

「&&」で１行に命令をまとめる。一時的にカレントディレクトリを変えるイメージ。「RUN cd /tmp && ./test.sh」以降の命令では、WORKDIRで設定したカレントディレクトリは変わらない。

```:Dockerfile
RUN cd /tmp && ./test.sh
```
Discordでユーザー一覧をCSV出力するBotを作ってみた

## 初めまして
初めまして！さばと言います。
色んなプラットフォームでニュース書いたりブログ書いたり備忘録書いたりしていましたが、Qiitaは初めての投稿です。

なんか気付いたらアドカレ~~前日~~当日になってたので、慌てて書いているんですが、本当だったらブラウザからFelicaカードの読み取りをするという内容で投稿しようとしていました。
ちゃんと動くプログラムも作ってあったんはずなんですが、プログラムが**何もしてないのに壊れちゃった**ので、急遽「DiscordのBotを作った話」をしようと思います。

## やりたいこと
Discordのサーバー参加者の一覧を出力したいと思ったことがある方は少なくないはず。
名簿と照合したり、ロールを自動で付与したりといった作業をするには、やっぱりCSVファイルの一覧などが欲しくなります。

ですが、Discordの標準機能ではそのようなエクスポート機能がありません。
ということで今回は、Discordのサーバーの参加者一覧を取得し、CSVで出力するBotを作っていきたいと思います。

## 前提条件
DiscordのBotは誰でも作ることができ、権限があればサーバーに追加することができます。
サーバーに追加するにはDiscord Developer PortalにてBotの登録をし、トークンを入手します。
この辺りを済ませ、すでにトークンを持っている前提で進めます。（初見だと意外に面倒な手順なのですが、説明はサボらせてください...）

## どうやって作るの？
Pythonで実装するにあたって、discord.pyという便利なライブラリがあります。
サービス終了するかも？といったニュースがありますが、現時点では使えます。

## 環境構築
Pythonが実行できる環境で、以下のライブラリをインストールしておきます。
python-dotenvについてはbot作成に必須ではないのですが、トークンを.envファイルに分離しているため、プログラムを動かすのに必要です。
```
pip install discord.py
pip install python-dotenv
```

## コード
get_member.pyと.envファイルを用意します。
```get_member.py
import discord
import os
from dotenv import load_dotenv

class MyClient(discord.Client):
    async def on_ready(self):
        print(f'Logged on as {self.user}!')
        
    async def on_message(self, message):
        print(f'Message from {message.author}: {message.content}')
        if message.author == self.user:
            return
        if message.content.startswith('$hello'): #botの意思疎通確認コマンド
            await message.channel.send('Hello!')
            
        elif message.content.startswith('$get_members'): #メンバー一覧を取得してCSVに出力するコマンド
            members_list = []
            async for member in message.guild.fetch_members():
                roles = [role.name for role in member.roles if role.name != "@everyone"]
                roles_str = ", ".join(roles) if roles else "None"
                members_list.append(f"{member.display_name},{member.id},{roles_str}")
            with open('output-files/members.csv', 'w', encoding="utf-8") as file:
                file.write('\n'.join(members_list))
                await message.channel.send('Saved!!')

        else:
            print('Command not found.')

intents = discord.Intents.default()
intents.message_content = True
intents.members = True

client = MyClient(intents=intents)
load_dotenv()
client.run(os.environ['TOKEN'])
```

```.env
TOKEN='ここにトークンを書く'

```

## 解説
コマンドプロンプトからget_member.pyを実行すると.envに記述したトークンを読み込んでdiscord.pyが動きます。（get_members.pyにハードコーディングしてもいいですが、GitHubなどでコードを管理するときにうっかりお漏らしするのを防ぐため分離しています。GitHubを使うときは.gitignoreに.envファイルを載せておきましょう。）

botが正常に動作すると「Logged on as \{Bot名\}!」とプロンプトに表示されます。

適当なチャンネルで「$hello」と送信すると、チャンネルにて「Hello!」と帰ってきます。

では、「$get_members」と送信してみましょう。サーバーの参加人数によりますが、数秒してから「Saved!!」と帰ってきます。
これと同時に、get_members.pyがある階層にoutput-filesというディレクトリが作成され、その中にmembers.csvができていればOKです！

出力されるCSVの構造は以下の通りです。
```members.csv
表示名,内部ID,ロール,...
```
内部IDとは、Discordの内部的に各アカウントに付与されているIDのことで、表示名を変えたとしてもこのIDは不変です。
サーバー参加者のアカウントを識別する場合、この内部IDを使った方が良さそうです。

もし、コマンドを増やしたい場合はon_message関数中にてelifで増やしていきます。

## 注意点
この記事のBotはコマンドの送信者やコマンドの送信チャンネルを限定していないため、プログラムの実行中は誰かかがどこかのチャンネルでコマンド送信すると実行されてしまいます。
今回の実装では出力結果は自分の手元PCにしか保存されませんが、念のため注意しましょう。
QQプロット

## QQプロットとは
2つの比較したい分布、回帰分析の残差が正規分布に従うかを調べる図である。直線か直線ではないか。
（一直線上になれば正規分布ということ。）
正規確率プロット(probability plot)はQQプロットの一種である。
![スクリーンショット 2023-12-11 0.04.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3536819/ecc71c6a-48ba-6b93-95ef-7bfc4a180334.png)
とりあえず名前だけ覚えておけ。AIサービスたち。

## はじめに
最近のAIブーム、色んな企業が色んなツール、サービス出して把握しきれんよ。。。
とりあえず、有名どころだけ押さえて整理してみるかと思い、執筆しております。

## 全体図
![AIサービス.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3553959/6e93f458-3a07-8f96-937e-af1d0db56e70.png)

## 文章生成AI
* **ChatGPT**
  * 開発　：OpenAI
  * モデル：GPT（3.5, 3.5Turbo, 4, 4Turbo, 4V）
  * 概要　：OpneAIが開発･提供しているchatAI、一番有名
* **Bard**
  * 開発　：Google
  * モデル：LaMDA、PaLM、Gemini
  * 概要　：Googleが開発･提供しているchatAI
* **Copilot for Microsoft365（旧名：Microsoft365 Copilot）**
  * 開発　：Microsoft
  * モデル：GPT
  * 概要　：Microsoftの複合サービス
   　　　　ofiice支援、BingAIChat等複数のツールを内包

## 画像生成AI
* **DreamStudio**
  * 開発　：StabilityAI
  * モデル：Stable Diffusion（SDXL, JSDXL）
  * 概要　：StabilityAI公式が出してる画像生成サービス
* **Midjourney**
  * 開発　：Midjourney
  * モデル：-
  * 概要　：小規模な研究機関が提供している画像生成サービス、discordBotを利用
* **DALL-E**
  * 開発　：OpenAI
  * モデル：DALL-E（2, 3）
  * 概要　：OpenAIが提供している画像生成サービス、chatGPTからも利用可能
* **Canva**
  * 開発　：Canva
  * モデル：-
  * 概要　：資料作成等のデザインサービス、文章・デザイン生成の一部にAI機能を搭載
* **Stable Diffusion WebUI**
  * 開発　：-
  * モデル：Stable Diffusion（SDXL, JSDXL）
  * 概要　：Stable DiffusionはOSSのため利用ツールが多種ある。その中で一番有名

## 動画生成AI
* **Gen-2**
  * 開発　：Runway
  * モデル：-
  * 概要　：Runwayが提供している動画生成サービス、テキストや画像から生成可能
* **HeyGen**
  * 開発　：HeyGen
  * モデル：-
  * 概要　：口パク動画(音声付き)生成サービス、講演者が要らなくなる
* **Stable Video Diffusion**
  * 開発　：StabilityAI
  * モデル：-
  * 概要　：StabilityAIが提供している動画生成サービス、まだ試験段階

## 音声生成AI
* **VALL-E(X)**
  * 開発　：-（Microsoft：論文発表のみ）
  * モデル：VALL-E(X)
  * 概要　：Microsoft発表の技術を利用した音声生成サービス、3秒間の音声で学習
* **RVC**
  * 開発　：-
  * モデル：-
  * 概要　：リアルタイムボイスチェンジサービス、モノマネ大会にもってこい

## コード生成AI
* **GitHub Copilot**
  * 開発　：GitHub
  * モデル：GPT
  * 概要　：GitHubが提供しているコード生成サービス、名称ややこしい
* **Code Llama**
  * 開発　：Meta
  * モデル：GPT
  * 概要　：Metaが提供しているコード生成サービス、Pythonに特化モデルがある
* **CodeWhisperer**
  * 開発　：Amazon
  * モデル：GPT
  * 概要　：AWS用のコード生成サービス、個人利用は無料

## まとめ
種類多すぎ、名称変更多すぎ、モデルとサービスの切り分け難しいなと感じました。
各分野3つくらいに主要サービスが絞られてくると利用者側としては嬉しいですね。
ご興味あるサービスありましたら、ぜひ利用してみてください。
では、よいお年を～。
【HTML】文字付きの水平線を表示させる方法

以下のように記述すると段落の間に水平線を引けます。

```html
<p>第一段落のテキスト。</p>

<hr />

<p>第二段落のテキスト。</p>
```

水平線の中央にテキストを表示するには以下のようなCSSを記述します。

```css
hr {
  border: none;
  border-top: 3px double #333;
  color: #333;
  overflow: visible;
  text-align: center;
  height: 5px;
}

hr:after {
  background: #fff;
  content: '§';
  padding: 0 4px;
  position: relative;
  top: -13px;
}
```
Djangoでの多言語対応（i18n）

## 対象の読者
Djangoを学び始めたばかりのプログラマーで、多言語対応のウェブアプリケーションを開発したいと考えている方。


## i18nとは
様々な地域での法律や規制、文化によって異なる要件に対応させることです。


## _()の意味
Djangoでは、アンダースコア()は翻訳用のマーカーとして使用されます。これは、Djangoの翻訳ツールがテキストを検出して翻訳用のカタログに追加できるようにするためのものです。例えば、_(“Hello World”)で囲まれたテキストは、翻訳対象のテキストとしてマークアップされます。

## 翻訳カタログ(Translation Catalog)
翻訳カタログは、Djangoアプリケーション内のテキストを翻訳するためのデータベースまたはデータファイルのことを指します。これは、各言語ごとにテキストとその対応する翻訳バージョンを格納します。翻訳カタログは通常、Djangoの管理コマンドを使用して生成され、アプリケーションのlocaleディレクトリ内に保存されます。

#### 翻訳カタログの生成と編集
翻訳カタログの生成は、以下のコマンドを使用して行います。
```
$ python manage.py makemessages -l <言語コード>
```

生成された.poファイルをテキストエディタで開き、テキストとその対応する翻訳を追加または編集します。
#テンプレートファイル名や行番号
msgid "オリジナルのテキスト"
msgstr "翻訳後のテキスト"

#### 翻訳カタログのコンパイル
翻訳カタログをコンパイルして、実際の翻訳ファイル(.mo ファイル)を生成します。
```
$ python manage.py compilemessages
```

## アプリケーションで翻訳を使用
Djangoアプリケーション内で翻訳を使用するには、テンプレートやPythonコードで gettext関数や{% trans %}テンプレートタグを使用します。Djangoはユーザーの選択した言語に基づいて適切な翻訳を表示します。


## ユーザーが使用する言語を指定するための方法
- ブラウザの言語設定
Djangoは、ユーザーのブラウザから送られてくるAccept-Language HTTPヘッダーを見て、ユーザーの言語を推測します。これはブラウザの言語設定に基づいています。
- URLパラメータ
Djangoは、URLの一部として言語コードを含めることで、特定のビューで使用する言語を指定することができます。
- セッションやクッキー
Djangoは、ユーザーが明示的に言語を選択した場合(例えば、言語選択ドロップダウンメニューを使用して)、その選択をセッションやクッキーに保存することができます。これにより、ユーザーが次にサイトを訪れたときに同じ言語が使用されます。


## Djangoの国際化(i18n)機能とGoogle翻訳の違い
Djangoの国際化(i18n)機能は、アプリケーションの開発者が提供する翻訳を使用して、アプリケーション内のテキストを翻訳します。一方、Google翻訳は、Googleが提供する翻訳サービスで、ウェブページ全体や任意のテキストを翻訳することができます。しかし、Google翻訳は動的な翻訳を提供するため、その結果は常に完全に正確であるとは限らない。


## まとめ
Djangoのi18n機能は、多言語対応のウェブアプリケーションを開発する際に重要なツールです。これにより、開発者はアプリケーション内のテキストを翻訳し、異なる言語のユーザーに対応することができます。この記事では、Djangoのi18n機能の基本的な使い方と、それがどのように動作するかについて説明しました。これにより、開発者は自分のアプリケーションをより広いユーザーベースに対応させることができます。
日本語プログラミング言語Mind は今年2023年で生誕38周年 どんな言語が同時代にあったのか調べてみる

# はじめに
日本語プログラミング言語Mind は今年2023年で生誕38周年。Mindが生誕した1985年にはどんな言語が同時代にあったのか調べてみます。

https://qiita.com/advent-calendar/2023/mind

日本語プログラミング言語 Mind（マインド）Advent Calendar 2023 11日目の記事です。

# Fortran

1954年に誕生。世界最初の高水準言語。
1985年はFORTRAN 77とFortran 90の間なのでFORTRAN 77が全盛
Fortran 90からは半角小文字が使われ始めましたが、この時代は半角大文字でプログラミングしていましたね。

# COBOL
1959年に誕生。コンピュータが事務処理に使われるのは画期的なことだった！？
第3次規格	1985年制定	構造化プログラミングとなる
永遠の半角大文字プログラミング言語！？

# BASIC
1964年に誕生。FORTRANユーザーは使いやすかった！？
N88-BASICが1981年に誕生。NECのパソコンにフロッピーディスクでついてきた。
QuickBASICが1985年に誕生。

# Pascal
1970年に誕生。
Turbo Pascalが1983年に誕生。Delphiの祖先

# C
1972年に誕生。機械語の影響が強い超低空飛行高級言語
Turbo Cが1987年に誕生。2万円程度の比較的安価なCコンパイラ1
Quick Cが1987年に誕生。2万円程度の比較的安価なCコンパイラ2

# C++
1983年に誕生。OOP！
MS C/C++ 7.0が1992年に誕生。超高級ブランド品C/C++コンパイラ

# おわりに
まさにこのあたりがMindの競合製品であった！？
Forthは当時国内でどうやって入手できたかはまったくわかりません。
BigQueryでn個の組み合わせの出現数を算出したい

ChatGPTにBigQueryの分析用クエリを教えてもらっていたら、面白いクエリが出てきたので簡単に記事に書いてみる。

# やりたいこと

ARRAY型のカラムの中で、特定のn個の要素の組み合わせ（順不同）の出現数を調べたい。

例えば、以下のようなデータが与えれ、2個の組み合わせを求めるとき、
```sql
WITH sample_data AS (
  SELECT
    ["A", "B", "C"] as field1
  UNION ALL
  SELECT
    ["A", "B"] as filed1
  UNION ALL
  SELECT
    ["B", "D"] as filed1
)

SELECT
  *
FROM sample_data
```


|field1|
|-|
|"[A,B,C]"|
|"[A,B]"|
|"[B,D]"|


こんな出力がしたい。
（1行目は、"A", "B"の組み合わせが全体で2回出現していることを意味している。）


|a|	b|	cnt|
|-|-|-|
|A|	B|	2|
|A|	C|	1|
|B|	C|	1|
|B|	D|	1|

# クエリ

自分で考えてもあまりいい方法が思い浮かばなかったので、ChatGPTに聞いてみたところ面白いクエリを教えてくれた。

```sql:ChatGPT考案のおもしろクエリ
WITH sample_data AS (
  SELECT
    ["A", "B", "C"] as field1
  UNION ALL
  SELECT
    ["A", "B"] as field1
  UNION ALL
  SELECT
    ["B", "D"] as field1
)

, combs AS (
  SELECT
    a,
    b
  FROM sample_data
    , UNNEST(field1) as a
    , UNNEST(field1) as b
  WHERE
    a < b
)

SELECT
  a,
  b,
  COUNT(*) as cnt
FROM combs
GROUP BY
  a, b
ORDER BY
  cnt DESC
```

まず結果を確認してみると、以下の通りで期待していた出力と一致していることが分かった。

|a|	b|	cnt|
|-|-|-|
|A|	B|	2|
|A|	C|	1|
|B|	C|	1|
|B|	D|	1|

クエリはとても短くシンプルで、肝となるのは下の部分。

```sql
  FROM sample_data
    , UNNEST(field1) as a
    , UNNEST(field1) as b
  WHERE
    a < b
```

field1（n個の要素が入った配列）の要素を2回UNNESTしているため、配列の中で各要素の全部の組み合わせの行を生成している。だが、そのままでは順序のみ違う二つの配列（例：["A", "B"], ["B", "A"]）がそれぞれカウントされてしまうため、`a < b`という条件を付けることでどちらか片方のみを取得するように設定している。（数値だけでなく文字列も問題なく動作する）

また、UNNESTとWHERE条件の数を増やすことで組み合わせの数を変更することもできる。
例えば、3つにしたいときは以下のようにする。`a < b AND b < c`を満たす組み合わせは要素が同じものの中では一つしかないため、順不同の組み合わせと同じ意味となる。

```sql
  FROM sample_data
    , UNNEST(field1) as a
    , UNNEST(field1) as b
    , UNNEST(field1) as c
  WHERE
    a < b
    AND b < c
```

ただ計算量がどんどん増えていくため、大きいデータを用いるときにはあまり向かないかもしれない。（数百万行のデータで3つの組み合わせを行ったときは数秒で終了したため、ある程度実用性はありそう）
Git初心者の疑問 -git mergeとgit rebaseの違いとは？-

# はじめに
Gitはプロジェクト管理システムの一種ですが、私は今までSVNを使ってきました。しかし、前職から転職したのをきっかけに、触れたことがなかったGitを使い始めました。

開発作業で他人の変更を自分の環境に取り込みたいとき、Gitではどうすれば…？調べた結果、**git merge**というものがあると分かりました。しかしこれを使っている内に、あることに気づきました。マージしただけなのにコミット履歴に何かいる。それはマージコミットでした。

変更内容以外のコミット履歴が増え続けるのは、作業履歴を振り返る際に分かりづらくなるため、避けたい…。チームの先輩に相談したところ、**rebase**を使っていることを知りました。（初めからマージ方法を伺っていればと反省しましたが、その点についてはご容赦ください。）

本記事では「git merge」と「git rebase」の違いについて備忘録としてまとめました。

# git merge
現プロジェクトではブランチを以下のように運用しています。（ローカルリポジトリ）

masterブランチ
developブランチ
┗feature/Aブランチ
&nbsp;&nbsp;&nbsp;&nbsp;feature/Bブランチ

私がfeature/Aブランチを作成して開発作業をしている最中に、feature/Bブランチがdevlopにマージされたとします。このとき私はローカルリポジトリで以下のように操作していました。

```sh:git
// 1. リスト1最新のdevelopブランチをローカルにプルする
$ git checkout develop
$ git origin develop pull

// 2. feature/Aブランチをdevelopブランチにマージする
$ git checkout feature/A
$ git merge develop

// 3. origin/feature/Aブランチにプッシュする 
$ git push
```

リポジトリの履歴を簡単な図にすると、このようになります。

![図_merge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618564/ed7e5036-deff-2b69-48f2-b46dba473300.png)

# git rebase
一方でgit rebaseでは以下の操作をします。

```sh:git
// 1. リスト1最新のdevelopブランチをローカルにプルする
$ git checkout develop
$ git origin develop pull

// 2. feature/Aブランチをdevelopブランチにマージする
$ git checkout feature/A
$ git rebase develop

// 3. origin/feature/Aブランチにプッシュする 
$ git push -f origin/feature/A
```

すると、履歴はこのようになります。
![図_rebase.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618564/37efd341-af05-9fb5-8bd2-299d2d113686.png)

mergeとの分かりやすい違いは、developの変更にマージした時にrebaseではマージコミットが作られないことです。git rebaseを行うとfeature/Aブランチのコミットがカットされ、developブランチの先頭に再作成（コピー）されます。そのため履歴を一本にすることができ、変更履歴が見やすくなります。

ただし、以下の注意が必要になります。
* git pushは強制プッシュ（git push -f）でないとリモートに反映できない。
* rebaseは必ず自分だけが使うブランチでのみ使用する。（複数人が使うブランチでrebaseをすると整合性がとれなくなるため。）

# こんなときどうする
万が一誤ってrebaseをしてしまった場合は以下のコマンドを実行します。
```sh:git
$ git reflog 
// 履歴から戻したいポイントのハッシュ番号を確認
$ git reset --hard HEAD@{番号} 
$ git push -f origin ブランチ名
```

また、コンフリクトが発生した場合は競合しているファイルを修正して再度コミットした後に以下のコマンドを実行してrebaseを続けます。
```sh:git
// コンフリクトを解消してrebaseを続行する
$ git rebase --continue
```

# おまけ
GitのクライアントツールであるSourceTree（Mac版）ではなぜかデフォルトで強制プッシュができないようになっています。しかし、設定変更等の手順を踏めばできるようになります。詳しい手順は以下の記事を参考にしました。
["Mac版SourceTreeでForce Push （強制プッシュ）を行えるように設定する"](https://zenn.dev/tanukidevelop/articles/70482ff0ed30d1)

以上です。

# 参考文献
* [あなたはmerge派？rebase派？綺麗なGitログで実感したメリット](https://style.biglobe.co.jp/entry/2022/03/22/090000)
* [git rebaseの具体的なメリット](https://zenn.dev/tana0102/articles/475d8952933af6)
* [7. rebaseでマージする](https://backlog.com/ja/git-tutorial/stepup/13/)
* [間違ってrebaseしてリモートリポジトリにpushしちゃったけど、戻したい](https://qiita.com/sakuraniumarete/items/7f9e6bed7da0bd247915)
rex0220 計算式プラグイン ユーザーカスタマイズ項目の取得

計算式プラグインで、ユーザーカスタマイズ項目を取得する例です。

# 概要

ユーザーカスタマイズ項目は、文字列かユーザー選択の形式で、５０個まで設定できます。
ただ、kintone 標準機能では、ユーザーカスタマイズ項目を取得する手段がなく、JavaScript カスタマイズが必要です。
計算式プラグインでは、UINFO 関数により簡単にユーザーカスタマイズ項目を取得できます。

- 計算式ツールで、ユーザーカスタマイズ項目の取得する例
    - UINFO("営業太郎", "#boss,#LINE")  // "営業太郎" の上長とLINE を表示
        - -> ["4,TEST-LINE-営業太郎"]


![2023-12-10_23h23_00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/f69cb27d-8a11-2fb5-e5c0-b420d8c131ff.png)

# ユーザーカスタマイズ項目

- ユーザーカスタマイズ項目の設定画面
![2023-12-10_23h10_29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/ca1422ae-d7a2-46ba-8a45-537cf8812fd4.png)

- LINE: 文字列項目
![2023-12-10_23h10_09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/daf47fa6-377d-e445-4195-915667c7c835.png)

- boss: ユーザー選択項目
![2023-12-10_23h10_57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/62ff2660-9b7e-889d-c710-fe6e04241041.png)

# 文字列のユーザーカスタマイズ項目

UINFO 関数に、ユーザーコードとカスタマイズ項目の"#項目コード"を指定すると、文字列の配列で取得できます。
あとは、文字列の配列として、計算式に利用できます。

```.js
UINFO("営業太郎", "#LINE")  // "営業太郎" のLINE を表示
-> ["TEST-LINE-営業太郎"]

UINFO(ARRAY("営業太郎","yamada hanako"), "#LINE")
-> ["TEST-LINE-営業太郎","YAMADA-LINE"]
```

# ユーザー選択のユーザーカスタマイズ項目

UINFO 関数に、ユーザーコードとカスタマイズ項目の"#項目コード"を指定すると、ユーザーID の配列を取得できます。

```.js
UINFO("営業太郎", "#boss")  // "営業太郎" の上長のユーザーID を表示
-> ["4"]

UINFO(ARRAY("営業太郎","yamada hanako"), "#boss")
-> ["4","2"]
```

UINFO 関数は、ユーザーコードと同様にユーザーID で、各種情報を取得できます。

```.js
LET(
  boss, UINFO("営業太郎", "#boss"),  // 上長のユーザーID
  bossName, UINFO(boss, "name"),  // 上長の名前
  bossName
)
-> ["山田花子"]

LET(
  boss, UINFO(ARRAY("営業太郎","yamada hanako"), "#boss"),  // 上長のユーザーID
  bossName, UINFO(boss, "name"),  // 上長の名前
  bossName
)
-> ["山田花子","レックス"]
```
fsharpでfelicalib.dllを使用し、felicaからidmを取得してみる。

用意するもの
- RC-S300などのPASORIリーダーと初期設定
- felicalib.dll
- fsharpの開発環境

felicalib.dllは下記より

http://felicalib.tmurakam.org/

早速ですがソースコード
```fsharp
open System.Runtime.InteropServices
open System

(*
    felicalib.dllの場所を絶対パスで入れておくとわかりやすいが
    まあ相対パスでもちゃんと配置すれば動きます。
    open, close, initなどはAPI仕様書に書いてあります。
    http://felicalib.tmurakam.org/refdoc/
*)
module InteropWithNative =
    [<DllImport(@"felicalib.dll")>]
    extern IntPtr pasori_open()

    [<DllImport(@"felicalib.dll")>]
    extern void pasori_close()

    [<DllImport(@"felicalib.dll")>]
    extern void pasori_init(IntPtr)

    [<DllImport(@"felicalib.dll")>]
    extern IntPtr felica_polling(IntPtr, int, int, int)

    [<DllImport(@"felicalib.dll")>]
    extern void felica_getidm(IntPtr, byte[])



(* pasoriのpointerをopenで取得する *)
let pasoriPointer = InteropWithNative.pasori_open ()


(* pasoriをinitする *)
InteropWithNative.pasori_init (pasoriPointer)

(* felicaのpollingを開始する *)
let felica_polling = InteropWithNative.felica_polling (pasoriPointer, 0xffff, 0, 0)

(* 返り値を入れるbyteArrayを用意する *)
let byteArray = Array.zeroCreate 8

(* byte to string *)
let byteToStr byteArr = BitConverter.ToString(byteArr)

InteropWithNative.felica_getidm (felica_polling, byteArray)

printfn "IDm: %A" (byteToStr byteArray)

(* log.txtファイルに書き出す *)
let log = System.IO.File.AppendText("log.txt")
log.WriteLine(byteToStr byteArray)
log.Close()

```

fsharpでC++などで作成されたライブラリを使用する際は、InteropServicesを使用します。
あとは自分で型定義を書いてあげて使う感じですね。
最近はcopilotのお陰でC++側のAPI仕様書をコメントアウトで書いておけば勝手に書いてくれます。

注意点として、x86系で作成されたライブラリに対応する場合、fsharpのコンパイルもx86系で通す必要があります。
fsprojの<PropertyGroup>下に```<PlatformTarget>x86</PlatformTarget>```などとしておくと良いでしょう。

こんな書き方するなら無理に関数型言語使わなくてもC#とかVBでええやんっていう話なんですが、F#のほうが手続き型であっても書きやすい気がするのです。めちゃくちゃシンプルに書けます。

もしJSで書くならff-napiとか、最近ならkoffiを使用することになると思います。

https://koffi.dev/

JSでも同じことができるんですけど、JSはIntPtrみたいなポインタの操作が面倒なのと、返り値などの操作が非常に面倒くさいのと、そもそもx86系のnode.jsを入れておかないとx86のDLLがうまく動きません。そういうハマりがあるので仕方がなくFsharpで頑張ったということでした。普通はVBかC#でいいと思います。サンプルも豊富にあるし。

F#で外部dllを使うソースコードがあんまりなかったのですが、まあ動いたのでOKとしましょう。
固定小数点16,16で遊ぶ3(除算)(M0、M0+)


固定小数点16,16で遊ぶ3(除算)(M0、M0+)

目的
センサーの値を計算する

x = 0x0009 0000
y = 0x0002 0000

割られる数を16ビット左シフトする

x / y = 0x0004 8000


プログラム

```c++


#define DIV(q,w) ((int)( ( (((long long)(q))<<16) /  ((long long)(w))) ))

void setup() {
  Serial.begin(9600);

  int x = 0x00090000;
  int y = 0x00020000;

  Serial.print("x / y =");
  Serial.println(DIV(x,y),HEX);
}

void loop() {
}

```

結果


```

x / y =48000


```
LLMを活用して記事を作る



# はじめに
※この記事は[KLab Engineer Advent Calendar 2023](https://qiita.com/advent-calendar/2023/klab) 11日目の記事です。

この記事では、今年になってだいぶ馴染み深くなったLLMを活用し、記事を効率よく作るための工夫の具体例を述べています。

**LLM（Large Language Model）** は、文章生成のための強力なAI技術です。大量の文書データを学習することで、人間が書くような流暢で自然な文章を生成することが可能になります。

さらに、その生成速度は人間が手でタイピングする速度をはるかに超え、ライティング作業の時間を大幅に短縮することができます。

# LLMを活用した思考の可視化と文書化

## STEP1 思いつくままに書く

思考を文章化・構造化する最初のステップは、**思いつくままに書く**ことです。
頭の中に浮かんだアイデアや考えを箇条書きにしてみましょう。
この段階では、完璧な文章を書く必要はありません。
大切なのは、思考を具体的な言葉に変換し、それを記録することです。
箇条書きにすることで、思考の断片を可視化し、全体像を掴みやすくなります。


## STEP2 LLMに整理させる

次に、この箇条書きをLLMに整理させます。
LLMは関連する情報を見つけてそれらを適切にグルーピングすることにも使えます。
また、それぞれの項目をより具体的な文章に変換し、一貫したストーリーを形成することも可能です。
このようにして、LLMを使うことで、思考を効率的に文章化・構造化することができます。


## STEP3 中身を肉付けする

構造化した項目ができたら、それぞれの項目についてどんな中身にするかを考えます。
詳細な説明や具体的な事例、関連する情報など、項目を肉付けする要素を考えて書き出しましょう。
そして、それらの要素を元にAIに文章化してもらいましょう。


## STEP4 編集する
AIが生成した文章はあくまで「原材料」です。
人間が自身の視点で取捨選択や訂正を加え、「書き手の色」を出しながら仕上げていきます。


# 質の高い記事を効率よく作るための工夫

## 一度のプロンプトに書く命令は一つにする
同時に複数の指示を出すと、AIはそれらを適切に処理できず、結果的に低品質な文章を生成する可能性があります。

## プロンプト作成時に核になる言葉を書く
この核となる言葉は、文章を生成するための基盤となります。
例えば「AIの未来」を核にすると、AIの可能性や課題、将来の展望などについてAIが文章を生成します。
核となる言葉は、あなたが書きたい内容の主題に直結するものを選びましょう。

## プロンプトで方向性も示す
核となる言葉だけではAIは広範な内容を生成してしまう可能性があります。
そのため、具体的な視点やアプローチをプロンプトに含めることで、AIに記事の方向性を示すことができます。
例えば「AIの未来とその社会への影響」のように、具体的な視点を加えると、AIはその視点に沿った内容を生成します。

## 内容をAIに丸投げしない
プロンプトはあくまでAIの文章生成を導くための道具であり、最終的な内容はあなた自身の判断によるものです。
AIはあなたの思考を補助するツールであって、代わりに考える存在ではありません。
そのため、プロンプト作成では自分自身の意図を明確にし、それを基にAIを活用することが重要です。


# あとがき

実は、この記事の大部分もLLMを活用して書いています。
利用したのはGPT-4です。
まさに記事の内容通り、以下の手順で作成しました。

1. 自分の考えていることを思いつくままに並べる
2. AIにグルーピングさせる
3. AIに記事の構成のアウトラインを出力させる
4. アウトラインの分量を調整
5. 各項目の中身のアイデアを並べる
6. 各項目ごとにAIに文章化させる
7. 項目間で重複した内容を削除したり構成の修正をする
8. AIに誤字脱字などを修正させる

これらの手順を踏むことで、手間や頭の疲労度が大幅に減りました。
筆者は伝わりやすい文書を一発で書くことを苦手としていて、推敲にもかなり苦労していました。
しかし、LLMの活用により、その疲労度は約1/3程度に軽減されたと感じています。

最後に、この文章を書く時に最初に使ったプロンプトを紹介します。
このくらいの分量を与えることでかなりスムーズに整理、執筆ができました。
何かの参考になれば幸いです。

```
頭を整理して記事に書く内容を検討したいので、以下を関連度が高いものをグループにまとめて欲しいです。
最終的にLLMのAIの使い方に関する初心者向けの記事にしようと思っています。

ただ作らせるだけでは質が低い
質の高い中身を効率よく作るための工夫
頭の中のとっちらかった内容を文章化したり構造化・分類するのに役立つ
手を使う方が早いものとAIを使うことが良いこと
工程を分解しつつ1工程だけ実施する
文脈が近いものをグルーピングする
文章力のサポート
情報整理のサポート
文章校正や編集のサポート
プロンプトを作る時に気をつけるテクニックや流れ
AIの癖を試行錯誤で
取捨選択は人が最終判断するがAIにサポートさせることはできそう
機械に処理しやすいように箇条書きの文体を揃える形もありそう
```
Pythonのインストールしたライブラリがインポートできない

この記事はIPFactory Advent Calender 2023 10日目の記事です。

https://qiita.com/advent-calendar/2023/ipfactory

# 原因
**`sudo pip3`を使用してしまい、実際の実行環境のパスとは違う場所にライブラリをインストールしていた**

sudo管理者権限での実行と一般ユーザでの実行で関連付けられているPythonバージョンが違いました。

# 経緯
## sudo pip3 installをやってしまった
tensorflowライブラリをインストールしたくて、やってしまいました
```bash
sudo pip3 install tensorflow
```
importしようとするとエラーになります。確認のため`pip3 list`をしました。しかしPackageの一覧に無い！(それもそのはずです。`sudo pip3 list`をすると出てきます。)

## ログを見返してみた
現在使用しているのは**python3.11**です。しかし、上記の`sudo pip3 install tensorflow`した時のログ確認すると、これが目に入りました。
```
Requirement already satisfied: packaging in /usr/local/lib/python3.8/dist-packages (from tensorflow) (21.3)
```
待て待てpython3.8？？？これはおかしいと思い調べると、
```
$ which python3.8
/usr/bin/python3.8
```
```
$ which python3.11
/home/aaa/.asdf/shims/python3.11
```
2個ある……しかも場所が全然違います。恐らくaptで3.8、asdfで3.11を入れていたようです。

## sudo pip3 --versionを調べる
```
$ pip3 --version
pip 23.3.1 from /home/aaa/.asdf/installs/python/3.11.0/lib/python3.11/site-packages/pip (python 3.11)
```
```
$ sudo pip3 --version
[sudo] aaa のパスワード:
pip 20.0.2 from /usr/lib/python3/dist-packages/pip (python 3.8)
```
はい、こちらsudoが原因のようで間違いないです。sudoがあるかないかでインストール先が変わってしまうことが確認できました。

# まとめ
考えなしにsudoを使ってはいけないことを学びました。
Pythonが3.8と3.11の両方あるのも、整理しないといけないですね。

---
この記事はIPFactory Advent Calender 2023 10日目の記事です。
9日目はK5h1n0君でした。

https://k5h1n0.hatenablog.com/entry/2023/12/09/234605
祝休日・謹賀新年：202４年の目標 

謹賀新年：今年の目標

https://qiita.com/kaizen_nagoya/items/8ade72629f62c392576c

の改訂版です。
　
Happy Holidays and New Year.

![xnenga2022.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51423/591f8e2c-c4f3-e004-cabe-307c27bca15e.png)


<この項は書きかけです。順次追記します。>
This article is not completed. I will add some words in order.

Qiita Countdown ~~Advent~~ Calendar 2021の色が、私の今年の年賀状と似ていると話題になっている件

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

今年も年賀状を作成しません。一昨年の年賀状の一部削除版を掲載します。間違い探しになっています。お気づきの方で、他にもご意見、ご感想のある方は、コメント欄にお願いします。

転職5年目を迎える前に、今年の目標を立てようと思います。

＜この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。＞

# 文書履歴
ver. 0.01 初稿 20231210

### 最後までおよみいただきありがとうございました。

いいね　💚、フォローをお願いします。

####  Thank you very much for reading to the last sentence.

Please press the like icon 💚　and follow me for your happy life.