OmniAICreator/Qiita-1.07M huggingface dataset:
Redmine のチケットや Wiki などに ChatGPT とのやりとりの履歴を添付する

Redmine のチケットや Wiki などに ChatGPT との履歴を添付する方法です。

### 必要なもの

Redmine 5 以降
Google Chrome

### Redmine の設定

Redmine 5 以降で利用可能になった `CommonMark Markdown` を有効にします。

1. 管理者権限で Redmine へログインする
1. 「`管理`」→「`全般`」タブを開く
1. 「`テキスト書式`」から「`CommonMark Markdown (GitHub Flavored)`」を選択する
1. 「保存」をクリックする

![スクリーンショット 2023-09-20 10.57.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79373/20bc2aea-0b02-e710-c27b-200d1d07351b.png)

### Google Chrome の設定

Google Chrome で以下の拡張機能を有効にします。

1. [Tampermonkey](https://chrome.google.com/webstore/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo?hl=en) (ユーザースクリプトの追加・管理を簡単に行えるツール)
1. [ChatGPT Exporter](https://greasyfork.org/ja/scripts/456055-chatgpt-exporter) (ChatGPT の履歴を様々な形式で出力するユーザースクリプト)

[ChatGPT Exporter](https://greasyfork.org/ja/scripts/456055-chatgpt-exporter) を有効にするには事前に [Tampermonkey](https://chrome.google.com/webstore/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo?hl=en) が有効化されている必要があります。

### 利用方法

ChatGPT の履歴の画面の下の方に「`SELECT`」と表示されます。クリックして出力する履歴の内容・出力形式を選択します。

![スクリーンショット 2023-09-20 11.08.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79373/6d0506c7-92ed-c7f5-4c43-178cdf909568.png)

* ALL（履歴の全て）
* QUESTIONS（ユーザーの入力した内容）
* ANSWERS（ChatGPTが出力した内容）

![スクリーンショット 2023-09-20 11.10.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79373/5cc6f43d-1f4b-e1dc-b712-735b0c40569e.png)

選択可能は出力形式は以下の通りです。今回は「`TO MARKDOWN`」を選択します。

* TO TEXT
* TO MARKDOWN
* TO CSV
* TO JSON
* TO IMAGE

出力が完了するとローカル端末のダウンロードディレクトリに「`ChatGPT-Exporter.md`」と言うファイルがダウンロードされます。

### 注意点

1. [ChatGPT Exporter](https://greasyfork.org/ja/scripts/456055-chatgpt-exporter) を有効にする前に、[Tampermonkey](https://chrome.google.com/webstore/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo?hl=en) 拡張機能が Google Chrome にインストールされ、有効化されている必要があります。

1. [ChatGPT Exporter](https://greasyfork.org/ja/scripts/456055-chatgpt-exporter) は ChatGPT からの出力内容に関しては正確なマークダウンを生成しますが、ユーザーの入力に関してはプレーンテキストデータとして出力します。そのためユーザーの入力に関しては後から修正が必要になります。

以下のスクリーンショットは、ユーザー入力部分を修正前と修正後の状態を示しています：

__修正前のMarkdown__

![スクリーンショット 2023-09-20 11.20.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79373/51f38206-73d3-7d9d-b5b2-e57514535393.png)

__修正後__

![スクリーンショット 2023-09-20 11.21.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79373/98aec618-4a7f-4c6e-a7c5-37c962aede82.png)

![スクリーンショット 2023-09-20 11.22.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79373/3d543cc4-aa64-ce90-bb3d-52fa78d8d758.png)


### 参考サイト

* [ChatGPTでMarkdownテキストを取得する方法｜藤原 惟](https://zenn.dev/sky_y/articles/chatgpt-markdown-output)
* [【毎月更新】Redmine リリース前の新機能を先行チェック！テキスト形式のフィルタで複数キーワードのAND検索に対応など（2021年10月コミット分） | Redmine.JP Blog ](https://blog.redmine.jp/articles/updates/2021/10/)
サーバーレスフレームワークのSkeet が Google の 生成 AI 新モデル chat-bison-32k に対応しました

![vertex-ai-chat-bison-32k.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2780317/fa71c7a6-4402-20f7-ee39-b4b2ca46b581.png)

gm! エルソウルラボのkishi.solです。

オープンソースのサーバーレスアプリ開発ツール Skeet が、Google の生成 AI 新モデル chat-bison-32k に対応しました。

これにより、Skeet を利用する開発者はより手厚い AI サポートを受けながら開発することが可能になり、より高度なアプリケーションを短時間で開発することができます。また、アプリに組み込む AI の性能も大幅に向上したため、より高度なサービスを開発することが可能になりました。

## 新モデル chat-bison-32k について

![VertexAIChat32kJA.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2780317/0476f025-5fb9-f6a2-65dc-d45fb2c1eec9.png)



Google Cloud は 9 月 19 日に生成 AI の新モデル chat-bison-32k を発表し、Vertex AI で利用可能になりました。

新しいモデルでは、今まで 1024 がだった上限トークン数が、8196 まで増加しました。トークン数が大きければ大きいほど、より長い文章や大きいデータに対応でき、より高度な回答が可能になります。

特に Google の生成 AI の特長は、質問と回答のサンプルを教えることで特定の分野に特化した回答を生成できることです。トークン数の増加は、より専門的な詳細情報を学習できるようになり、より高度な回答が可能になります。

Skeet を使って作成されたデモアプリにおいてもこの新モデル chat-bison-32k を利用可能になっています。

ぜひ下記リンクより最新の Google 製生成 AI をお試しください。

https://skeeter.dev/ja/

## Google Cloud、Firebase 上でサーバーレスアプリを爆速開発できるオープンソースの Skeet フレームワーク

![SkeetJA.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2780317/74bd4ec1-9515-a395-c373-76b79cb3eceb.png)


Skeet は GCP (Google Cloud) と Firebase 上にフルスタックアプリを構築できるオープンソースの TypeScript 製サーバーレスフレームワークです。

Skeet を使えば、API サーバーから Web・iOS・Android アプリまですべてを TypeScript で爆速開発することができます。GraphQL や Firestore など、開発者体験の評判が良い技術を積極的に採用しています。

ChatGPT や Vertex AI などの AI を活用したアプリケーション開発や Solana などのブロックチェーンを活用した Web3 dApp 開発も簡単に行うことができる現代的なアプリケーションフレームワークとなっています。

下記リンクからデモをお試しいただけます。PaLM2・Vertex AI、そして Open AI 社の ChatGPT (GPT-3.5, GPT-4)も同時にお試しいただくことができますので、どちらがどのような特徴を持っているか比較検討していただくことができます。

https://skeeter.dev/ja/

また、こちらのデモのアプリは Skeet CLI を使えば 5 分でご自身の PC 環境やクラウド環境で動かすことが可能です。

まずはどのようなことができるかデモでイメージしていただき、その後は Skeet CLI を使ってすぐにアプリ開発をスタートできます。

Skeet CLI にも AI が搭載されており、チャットによるコード生成等の強力なサポートにより、開発者の生産性を大幅に向上させます。

https://github.com/elsoul/skeet-cli

Skeet は世界中すべてのアプリケーション開発現場の開発・メンテナンスコストを削減、開発者体験を向上させるためにオープンソースとして開発されています。

詳しくは公式ドキュメントを御覧ください。

https://skeet.dev/ja/
プログラミングのインターフェイスとは？イメージを簡単に説明

## インターフェイスとは
インターフェイスってのは、ある種の約束事やルールのようなものです。

## 身近な例１
例えば、友達とレストランに行く約束をするとき、「12時に駅前のマクドナルドで待ち合わせ」という約束をしたとします。
この約束事が、友達との間での「インターフェイス」のようなものです。

プログラムの中での「インターフェイス」も、この約束事に似ています。
特定のクラスやオブジェクトが、どんな動きをするのか、どんな情報を持つのかの「約束」を明示的に示しているんです。

## 身近な例２
例えば、ロボットの操作マニュアルがあったとして、そのマニュアルに「前に進むボタンを押すと、ロボットは前に進む」と書かれているとします。
これはロボットの「インターフェイス」の一部だと言えます。
操作マニュアル（インターフェイス）に従って、ボタンを押すと、約束された動き（前に進む）をロボットが実行できるというわけです。

## 結論
プログラムの中では、インターフェイスを使って、特定の機能や動きを持つことを「約束」します。
そして、その「約束」に従ってプログラムの他の部分が機能するように設計されています。

要するに、インターフェイスは「これを持っているよ」「これができるよ」という約束事を示すもので、それに従って様々な物やプログラムが動作するというわけです！
javascriptで一括で要素を追加する

# Document.createDocumentFragment()
新しい空の DocumentFragment を作成し、そこに DOM ノードを追加して画面外の DOM ツリーを作成します。

```js
var element = document.getElementById("ul"); // ul が存在することを仮定
var fragment = document.createDocumentFragment();
var browsers = ["Firefox", "Chrome", "Opera", "Safari", "Internet Explorer"];

browsers.forEach(function (browser) {
  var li = document.createElement("li");
  li.textContent = browser;
  fragment.appendChild(li);
});

element.appendChild(fragment);
```
### 出典
https://developer.mozilla.org/ja/docs/Web/API/Document/createDocumentFragment

# 繰り返す要素を表示させたい
色々探したけどやっとこれに辿り着いた。
見つけたきっかけは下です。

https://zenn.dev/toshihide2000/scraps/87957b8360cf84

https://qiita.com/39_isao/items/2fa8faed283d455f4181

https://uhyohyo.net/javascript/7_4.html

あとはブラウザの検証やディベロッパーツールを使ってみて確認してみてください。

# 感想
検索技術の低さで時間が掛かった。
少しでも他の方が検索に引っ掛かるように投稿しました。
ユーザーによるTeamsのチームを作成制限をする

## はじめに

Microsoft 365 環境ではデフォルトで誰でもTeamsアプリからチームが作成できる設定となっています。
この状態ですと意味もなくチーム作成されてしまい管理者が痛い目を見る可能性があります。

テナント内でTeamsのチームを作成できる人を管理者のみに設定します。

## GUIでチーム作成制限を設定

![](https://storage.googleapis.com/zenn-user-upload/944dc831b80d-20230725.png)

「Microsoft Entra管理センター or AzureAD ＞グループ＞全般」からユーザーによるMicrosoft365グループの作成制限することができます。

「Microsoft365グループ」の欄で「いいえ」を選択すればOKです。

***※反映まで少し時間がかかります。***

この設定を行うことでチームの作成はTeamsアプリからは不可能になり、各管理センターからチームを作成する必要があります。
Windowsのローカル環境でLaravelのGoogleログインにアカウント切り替えを実装してみた話

# はじめに
うわっ…私の記事、タイトル長すぎ…？
と思わなくもなかったのですが、↓の続編ということがわかりやすいようにしました。

https://qiita.com/fsd-yamagen/items/fa819d9c55a76ff0ce03

前回、LaravelのSocialiteを使ってGoogleのソーシャルログインが実装できたので、今回はログアウト→別アカウントでログインという処理を実装したら、思ったより苦労したという備忘録です。
環境やソースコードは前回のものを使っています。
# ログアウト処理の実装
まずは以下のように実装してみました。

**resources\views\welcome.blade.php**
好きな場所に以下のログアウト用リンクを設置

```PHP
@auth
	<a href="{{ url('/logout') }}">logout</a>
@endauth
```
**routes\web.php**
末尾に以下を追記

```PHP
Route::get('/logout', [GoogleLoginController::class, 'logout']);
```
**app\Http\Controllers\GoogleLoginController.php**
以下の関数を追加

```PHP
public function logout()
{
	Auth::logout();
	return redirect('/');
}
```
これでどうなったかというと、**ログアウト→同じアカウントで自動ログイン**という動作になりました。
考えてみれば当たり前なのですが、`Auth::logout();`というのはあくまでPHPで実装したアプリ内の話であり、Googleアカウントのログイン状態やアプリ連携には影響しないため、ログイン画面に戻ると同じアカウントでGoogle認証まで通ってしまうわけですね。
ちなみに、手動での連携の削除はGoogleアカウントの[サードパーティ製のアプリとサービス](https://myaccount.google.com/connections)からできます。
# どうやって解決したか
アプリ側からGoogleアカウントを制御することはできないのですが、色々と調べた結果、「approval_prompt = force」というパラメータを指定することで、強制的に認証画面を出せるということがわかりました（公式ドキュメントが[こういうの](https://cloud.google.com/dotnet/docs/reference/Google.Apis/latest/Google.Apis.Auth.OAuth2.Requests.GoogleAuthorizationCodeRequestUrl#Google_Apis_Auth_OAuth2_Requests_GoogleAuthorizationCodeRequestUrl_ApprovalPrompt)しかなくて探すのに苦労しました）（[Twitter](https://developer.twitter.com/ja/docs/authentication/api-reference/authorize)みたいにまとめて欲しい・・・）
というわけで、ログイン状態をチェックして、ログアウト状態の場合は強制的に認証画面に遷移するという実装が以下となります。

**app\Http\Controllers\GoogleLoginController.php**
以下の関数を書き換え。

```PHP
public function getGoogleAuth()
{
	return Auth::check() ?
		Socialite::driver('google')->redirect() :
		Socialite::driver('google')->with(['approval_prompt' => 'force' ])->redirect();
}
```
これで、ログアウト後に認証画面からアカウントを切り替えられるようになりました。
# おわりに
ソーシャルログインは便利ですが、アプリ側とソーシャル側のログイン状態や連携は別物というのを意識しておかないと、想定した動作にならないことがあるので注意が必要ですね。
Googleで複数アカウントを使い分けるケースはあまり無いかもしれませんが、会社の個人アカウントと情シスの運用アカウントを切り替えたり、共用PCでGoogleログインを使うなどで必要になった時に参考になれば幸いです。
Xcode15でiOS17のSimulatorのインストールに失敗する時の対処法(Failed with HTTP status 400: bad request)

# 概要
Xcode15のインストール後、iOS17のSimulatorのインストールが求められますが、以下のエラーによりインストールに失敗する事象に遭遇したため、その解決策を残します。

`Failed with HTTP status 400: bad request`
# 結論
手動でiOS17 Simulatorをインストールすることで解決出来るようです。

# 手順
1. developerサイトより、iOS17 Simulatorをダウンロードします。  
developerサイトからダウンロードするか、以下リンクよりダウンロードすることが出来ます。
https://download.developer.apple.com/Developer_Tools/iOS_17_Simulator_Runtime/iOS_17_Simulator_Runtime.dmg
1. iOS_17_Simulator_Runtime.dmgがインストールされたディレクトリで以下を実行します。
`xcrun simctl runtime add iOS_17_Simulator_Runtime.dmg`

# 参考
https://developer.apple.com/forums/thread/737648  

https://stackoverflow.com/questions/77133646/ios-17-0-simulator-21a328-failed-with-http-status-400-bad-request
NeosVR コンパイラ その5

# 概要
NeosVRのオブジェクトを外部で生成するコンパイラを開発した。
練習問題、やってみた。

# 練習問題
nasaのapiを叩いて取得した今日の画像を表示するオブジェクトを生成せよ。

# 方針
xhrでapiを叩く。

# 写真

![2023-09-20 01.41.43.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/53ff50ed-c05c-4ad5-df0e-7ffc351c6b69.jpeg)


# 俺コード

```
new FrooxEngine.StaticTexture2D
new FrooxEngine.UnlitMaterial
new FrooxEngine.MeshRenderer
new FrooxEngine.QuadMesh
FrooxEngine.StaticTexture2D.Data.URL.Data = "@" + NasaApi.url
FrooxEngine.UnlitMaterial.Data.Texture.Data = FrooxEngine.StaticTexture2D.Data.ID
FrooxEngine.MeshRenderer.Data.Materials.Data[0].Data = FrooxEngine.UnlitMaterial.Data.ID
FrooxEngine.MeshRenderer.Data.Mesh.Data = FrooxEngine.QuadMesh.Data.ID
add FrooxEngine.StaticTexture2D
add FrooxEngine.UnlitMaterial
add FrooxEngine.MeshRenderer
add FrooxEngine.QuadMesh

```

# 成果物

https://embed.plnkr.co/plunk/q8RUzPgUfKG5esc9

# 実行確認の手順。

- 上のページで生成されたjsonを、メモ帳で「nasaapi0.json」で保存する。

- NeosVRを起動して、セッションに入る。
- ファイルブラウザを開いて、「nasaapi0.json」をダブルクリックする。
- 画像が表示されれば、成功です。

以上。
Rails7でdestroyが効かない

メモ

サンプルなどで記事を削除する際に使用する機能がつかえなかったので。

* Rails5の書き方

```ruby
<%= link_to '削除', board ,method: :delete, class: "btn btn-outline-dark" %>
```

* Raisl7の書き方

```ruby
<%= link_to '削除', board ,method: :post, 
  data: {
    turbo_method: :delete,
    turbo_confirm: "Are you sure?"
}, class: "btn btn-outline-dark" %>
```

旧バージョンではJQueryを使ってたけど、新バージョンでは使うJSライブラリが変わったとかなんとか。

書き方を変えても削除できず、showのページがでてしまう。
メソッドがGETで送られてしまうとかなんとか。

参考ページの一番下に合った方法で試すと削除できた！

application.html.erbに下記を追記

```ruby
<%= javascript_include_tag "turbo", type: "module" %>
```

たぶんこのgemなどは事前にインストールが必要っぽい。

```gem
# Use JavaScript with ESM import maps [https://github.com/rails/importmap-rails]
gem "importmap-rails"

# Hotwire's SPA-like page accelerator [https://turbo.hotwired.dev]
gem "turbo-rails"

# Hotwire's modest JavaScript framework [https://stimulus.hotwired.dev]
gem "stimulus-rails"

```

## 参考ページ
[Guide v7.0.3.1 “link_to “Destroy” “turbo_method: :delete” doesnt works / Ubuntu 22.04](https://discuss.rubyonrails.org/t/guide-v7-0-3-1-link-to-destroy-turbo-method-delete-doesnt-works-ubuntu-22-04/81326/9)
【kintone/javascript】利用者ごとに採番された管理番号を利用したい

# はじめに
自動採番処理はプラグインを始め色々ありますが、担当者ごとに採番値を発番する必要があったので備忘録として残しておきます。

単独でプラグインを購入するのは勿体ない、、、
なんとか自作できないか、、、

という方向けに共有です。

```javascript:autonumbering.js
(function() {
    "use strict";

    // 管理番号を自動採番します。
    // <仕様>
    // アプリ内の過去レコードから最も大きな採番値を取得し+1した番号をセットします。
    // 管理番号の接頭辞は「従業員ID」の情報を付与します。「従業員ID」が設定されていない場合はユーザーIDを設定します。
    // 
    // <前提条件>
    // ・採番値をセットする「文字列」フィールドが設定されていること　※本サンプルでは"管理番号"というフィールドを想定
    // ・「ユーザー選択」フィールドが設定されていること　※本サンプルでは"担当者"というフィールドコードを想定
    // ・「数値」フィールドが設定されていること　※本サンプルでは"採番値"というフィールドコードを想定
    // ・kintoneアカウントの「従業員ID」が設定されていること
    // ・レコード新規作成イベントで動作します
    kintone.events.on(["app.record.create.show"], (event) => {

        // ログインユーザー情報を取得
        const user = kintone.getLoginUser();

        // 検索条件
        let params = {
            app: '{targetAppID}', //アプリID
            fields: ['担当者', '採番値'],
            query: '担当者 in ("' + user.code + '") order by 採番値 desc limit 1' //1件だけ取れれば良いのでlimit1
        };

        // 現在表示しているレコードを取得
        const record = event.record;

        // 検索処理
        return getMaxNumberRecord(params)
                .then(function(maxCount){
                    // 管理番号に値を設定
                    record.管理番号.value = user.employeeNumber ?  user.employeeNumber + "-" + String(maxCount + 1) : user.id + "-" + String(maxCount + 1);
                    record.採番値.value = Number(maxCount + 1);
                    return event;
                });

    });

    async function getMaxNumberRecord (params) {
        return await kintone.api(kintone.api.url('/k/v1/records.json', true), 'GET', params).then( function(resp) {
            const searchResults = resp.records;
            let maxCount = 1;
            for (var i = 0; i < searchResults.length; i++) {
                if (searchResults[i].採番値.value) {
                    maxCount = Number(searchResults[i].採番値.value);
                    break;
                }
            }

            return maxCount;
        }).catch(function(error) {
            alert(error);
        });
    }

})();
```

kintoneカスタマイズのノウハウをためていきます（予定）
https://github.com/koguren/kintoneJSSample
子トリガーをデプロイしてデータをnpsp__Allocation__cからOpportunitiesにロールアップしようとすると、エラーが発生します。



+ [子トリガーをデプロイしてデータをnpsp__Allocation__cからOpportunitiesにロールアップしようとすると、エラーが発生します。](https://trailhead.salesforce.com/en/trailblazer-community/feed/0D54S00000De1Y0)


+ [Active: Apex Trigger dlrs_OpportunityLineItemTrigger has not been deployed. Click Manage Child Trigger and try again.](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000BrfmR)

:::note
Missing Child Trigger

You’ve probably tried to save a new DLRS and you get an error that looks something like this. “Active: Apex Trigger dlrs_contactTrigger has not been deployed. Click Manage Child Trigger and try again.”

If you are using the Custom Metadata you wont even see the Deploy Child Trigger button until the DLRS record is saved so you might be a bit confused on how do you save if there isn’t even a way to deploy! The easy fix to this is UNCHECK the active box, save the DLRS, deploy the child trigger then edit the DLRS and recheck the active box.

https://dandonin.com/2017/10/19/troubleshooting-dlrs-101/
:::

+ [Invalid cross reference id error generated when saving campaign member record](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007Dgpuw)

:::note alert
dlrs_CampaignTrigger: execution of AfterUpdate caused by: System.DmlException: Update failed. First exception on row 0 with id 0032w00000X2RxmAAF; first error: INVALID_CROSS_REFERENCE_KEY, invalid cross reference id: [] (dlrs) Trigger.dlrs_CampaignTrigger: line 7, column 1
:::

+ [Flow Failure due to DLRS Trigger - Invalid Field](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000FSUzC)

:::note alert
Error element Update_Account_Name (FlowRecordUpdate).  The flow tried to update these records: 5004w00002Kkd0VAAR. This error occurred: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY: dlrs_CaseTrigger: execution of AfterUpdate caused by: System.SObjectException: Invalid field ActivityDate for Case (dlrs) Trigger.dlrs_CaseTrigger: line 7, column 1. 
:::

:::note
Old thread but I ran into this problem as well. I think this is the relevant GitHub issue: https://github.com/SFDO-Community/declarative-lookup-rollup-summaries/issues/1203

I posted more details there, but the summary of my workaround was to bypass the problematic Flow(s) when Case status = 'merged'. 
:::

+ [DLRS Trigger Not Deploying?](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007FU7rD)

:::note
Seems like a Winter 24 issue but making the change on the custom metadata record fixed it.

https://issues.salesforce.com/issue/a028c00000uXYtiAAG
:::

+ [上記２つと同じ質問Manage Child Trigger not Working in Sandbox](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007H96II)

:::note
Please check this article.

https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007FT4kL

https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007FU7rD
:::
Liferay LXC-SMのBasic認証について

Basic認証を追加する場合、下記の手順をご参考ください。

### 1.環境対応の設定ファイル：liferay.confに下記のコードを追加

```
auth_basic "Authentication Required";
auth_basic_user_file /var/www/html/.htpasswd;
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1189220/20a62076-9877-4676-b228-70fa8859f8c7.png)

### 2.環境対応の設定ファイル：.htpasswdにユーザー名とエンコードされたパスワードを追加

```
[username]:[エンコードされたパスワード]
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1189220/2ffad5e5-96c9-bea1-518f-324485ab2e07.png)

### 3.パスワードのエンコード生成方法：

3.1 オンラインツールを使う
https://www.luft.co.jp/cgi/htpasswd.php

3.2 コマンドラインで生成：

```
XXX/webserver/configs/dev/public > htpasswd -c .htpasswd [username]                                                                                                        
New password:
Re-type new password:
Adding password for user [username]
xxx/webserver/configs/dev/public > cat .htpasswd                                                                                                                      
[username]:$apr1$334Op$MU33STdpHu.Vj2g/tLGTn1
```

## 参考記事
https://www.javadrive.jp/apache/allow/index4.html
【AWS Batch】エラー「exec format error」の原因と解決方法

# 概要
ECRにイメージをプッシュして、AWS Batchのジョブからコマンドを実行すると`exec format error`になりました。本記事ではその原因と解決方法を記載します。

# エラー内容

AWS Batchのコマンドに、試しに`["pwd"]`をジョブに入れて実行しました。
しかし、ログを見ると以下のエラーになりました。

```
	exec /bin/pwd: exec format error
```

このエラーは、コンテナイメージが実行しようとしているバイナリまたはコマンドの実行形式が正しくない場合に発生するよう。コンテナイメージがEC2インスタンスの実行環境と互換性がないっぽい。

# 原因
`docker inspect`を実行してDockerイメージの中身を見てみる 

```
 "Architecture": "arm64",
        "Variant": "v8",
        "Os": "linux",
```

`"Architecture"`フィールドが`"arm64"`であることは、コンテナイメージがARM64アーキテクチャ向けにビルドされた、ということ。

AWS Batchがデフォルトで提供するコンピューティング環境（Amazon EC2インスタンス）のアーキテクチャは、`amd64（x86_64）`らしい。そのため、Dockerのアーキテクチャと異なるのでエラーになっていた、というわけです。`amd64`アーキテクチャ向けのコンテナイメージを実行することを前提としているのです。

また、自分はMac M1チップを使ってDockerイメージをビルドしていました。M1はArmアーキテクチャのプロセッサを利用しているので、そこで不整合が起きていたのです。

# 解決方法

コンテナイメージもARM64アーキテクチャ向けにビルドされている必要があります。
以下でビルドしたら、上述のエラーがなくなりました。

```
docker build -t sample-image . --platform amd64
```
SQLを速くするために学んだこと

以前のアカウントがどこかへいってしまったので作り直しをしました。
最近業務でSQLを触る機会が多く、少し勉強をしたのでメモ書き程度ですが書いてみました。

## サブクエリはINよりもEXISTSを使用する

```sql
-- 遅い
SELECT * 
FROM ClassA
WHERE id IN (SELECT id FROM ClassB);

-- 速い
SELECT *
FROM CLASSA A
WHERE EXISTS
	(SELECT *
		FROM ClassB B
		WHERE A.id = B.id);
```

- idにindexが貼られていればClassBは見に行かずインデックスを参照するのみで済む
- EXISTSは1行でも一致する行を見つけるとここで検索を打ち切るから全検索にならない

## サブクエリよりも結合を使う

```sql
SELECT A.id, A.name
FROM ClassA A
INNER JOIN ClassB B
ON A.id = B.id
```

- どちららかのindexが必ず効いてくる


## ソートを回避する
GROUP BY、ORDER BY、DISTINCTなどソートが発生するものは注意が必要になる

### 重複を気にしなくていい場合はUNIONの代わりにUNION ALLを使うようにする

```sql
SELECT *
FROM ClassA
UNION ALL
SELECT * FROM ClassB
```

### DISTINCT(重複を省く)をEXISTSで代用する

```sql
-- 遅い
SELECT DISTINCT I.no
FROM Items I 
INNER JOIN SalesHistory SH ON I.no = SH.no

-- 速い
SELECT I.no
FROM Items I 
WHERE EXISTS (
	SELECT * FROM SalesHistory SH
	WHERE I.no = SH.no
)
```

### MAX/MINでINDEXを使う

```sql
-- indexを利用していない
SELECT MAX(item)
FROM Items;

-- indexを利用している
SELECT MAX(item_no)
FROM Items;
```

- item_noは主キーなのでより効果的にindexを使用できている

#### WHERE句出かけるものはHAVING句に書かない

以下のSQLはどちらも同じ結果になるが、後者の方が速い

```sql
-- 遅い
SELECT sales_date, SUM(quanitity)
FROM SalesHistory
GROUP BY sales_date
HAVING sale_date = '2023-09-01';

-- 速い
SELECT sales_date, SUM(quanitity)
FROM SalesHistory
WHERE sales_date = '2023-09-01'
GROUP BY sales_date;
```

- GROUP BYはWHEREで指定された後に行うのでなるべくレコード数を絞り込んだ方がいい
- WHEREでindexをを利用できる


## indexを正しく使おう
indexを貼ってはいるものの、理解した上で使わないと上手く使えていないこともある

### 加工を行なっている
計算式を使っている場合、左辺ではなく右辺で計算するようにする

```
-- indexを利用していない
SELECT *
FROM SomeTable
WHERE col_1 * 3 > 100;

-- indexを利用している
SELECT *
FROM SomeTable
WHERE col_1 > 100 / 3;
```

### NULLが存在する
基本的にNULLが存在しているカラムには、indexを貼るべきではないと考えている
以下は応急処置程度で考えるといい

```
-- index利用していない
SELECT *
FROM SomeTable
WHERE col_1 IS NOT NULL

-- indexを利用している
SELECT *
FROM SomeTable
WHERE col_1 > 0;
```

### 否定系を使っている
以下のような否定系にはindexが効かない

* <>
* !=
* NOT IN

### 複合indexの順番を間違えている
col_1,clo_2,clo_3の順番にindexが貼られているとする

```sql
-- indexを利用していない
SELECT *
FROM SomeTable
WHERE col_2 = 30
AND clo_1 = 10
AND clo_3 = 30;

SELECT *
FROM SomeTable
WHERE col_1 = 10
AND clo_3 = 20;

SELECT *
FROM SomeTable
WHERE col_2 = 30
AND clo_3 = 30;

-- indexを利用している
SELECT *
FROM SomeTable
WHERE col_1 = 10
AND clo_2 = 20
AND clo_3 = 30;

SELECT *
FROM SomeTable
WHERE col_1 = 10
AND clo_2 = 20;
```


## 感想
EXISTSは知ってはいたもののどうゆう挙動するのかあまりわかっていないので使っていなかった。サブクエリをする上ではEXISTSを意識してみようと思う。
ソートには負荷がかかるのは知っていたが、GROUP BYなど結構よく使う。
INDEXについて今までINDEXついているものを検索に使おうと心がけていたが、順番や否定系には使えないことは学びだった。
業務でかなりのレコード数があるテーブルでSQLを書くときに、重くて取得できないことがよくある。こうした小さな工夫の組み合わせでパフォーマンス向上させられるといいなと思うので、また勉強してみようと思う。


参考書籍：　[達人に学ぶSQL徹底指南書 第2版 初級者で終わりたくないあなたへ](https://amzn.asia/d/hxXWH0V)
フィッシングサイトか確認するのにマウスオーバーで出てくるステータスバーのURLを確認するのはNG

フィッシングサイトかどうか確認するのに、マウスオーバーをしてステータスバー（ブラウザの下のほうにでてくるやつ）を確認するという方法があるようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3533089/95ec08e8-d947-7448-8d5e-cc2e2edd5088.png)

javascriptを勉強しているうちに、「あれ？この方法ってもしかしたら」と思って、chatGPTさんに聞いてみました。

> <a href=... タグで、マウスオーバーの時にブラウザのフッター付近に表示されるリンク先と、実際にクリックしたときに飛ぶ先を違うようにjavascriptでできますか？

あっさり答えてくれました。

> はい、JavaScriptを使用して、マウスオーバー時とクリック時に異なるリンク先を設定できます。以下は、それを実現するためのサンプルコードです。

```
<!DOCTYPE html>
<html>
<head>
  <title>リンク先切り替え</title>
</head>
<body>
  <a href="#" id="myLink">マウスオーバーまたはクリックしてください</a>

  <script>
    // マウスオーバー時のリンク先
    var hoverLink = "https://www.example.com/hover-page";

    // クリック時のリンク先
    var clickLink = "https://www.example.com/click-page";

    var myLink = document.getElementById("myLink");

    myLink.addEventListener("mouseover", function() {
      myLink.setAttribute("href", hoverLink);
    });

    myLink.addEventListener("click", function(event) {
      event.preventDefault(); // デフォルトのクリック動作を無効化
      window.location.href = clickLink; // クリック時のリンク先に遷移
    });
  </script>
</body>
</html>
```

マウスオーバーで出てくるURLを、クリックの瞬間に別のURLにすり替えてしまうjavascriptでした。簡便な方法なので重宝している人も多いと思いますが、やはりメールなどのURLはクリックしない、を徹底したほうがよさそうです。
NextAuthでパスワード認証を実装する上での注意点

# はじめに
NextAuthでCredentials Providerを使ってDBでユーザーを管理しながらパスワード認証を実装するといくつか注意点があります。

# 注意点
## セッション管理にDBが使えない
一番の注意点としては「セッション管理」にDBが使えないことです。
adapter（例：PrismaAdapter等）を設定すると、デフォルトでSession Strategyが`database`にされるので注意が必要です。
ここで、`strategy`が`database`のままだと`Credentials`で認証した場合、`session`情報が取得できなくなります（嫌がらせ？）。
また、ここが混乱ポイントなのですが、セッション管理にDBが使えない＝ユーザー管理にDBが使えないではないです。
あくまでも、セッション管理にDBが使えなくなるだけでadapterが設定されている以上、ユーザー情報はDBに永続化できます。
また、これに伴い、公式で作れと言われている`Session`テーブルは使われないので作る必要はありません。

## ユーザー登録
ユーザー登録（及びメールアドレス到達確認やパスワードリセット）は独自実装する必要があります。
他のプロバイダーと組み合わせて実装する場合は他のプロバイダーで登録されたEメールアドレスでは登録できないようにするか、メール受信確認が完了するまではサービスでの変更権限を絶対に与えないようにしてください。
最悪、アカウントが乗っ取られる可能性があります。

## ユーザー情報の更新時
これは、パスワード認証(Credentials Provider)の注意点というかJWTを使う上での注意点ですが、ユーザー情報が更新されたときには、session.update()を呼び出した後に、`jwt` コールバックの `update` トリガーで情報を詰めなおす必要があります。これをやらないと次回ログインするまで情報が更新されません。
また、この場合、`user` 引数にDBの情報は入ってこないため、自分でDBから情報を取得する必要があります。

## sessionコールバックではtoken引数を使う
sessionコールバックはめちゃくちゃ呼ばれるので、独自にデータを追加する場合は毎回DBからデータを取得するのではなく、JWTの情報を活用するように `token` 引数の値を詰めた方がいいです。

# 実装例

```typescript:/app/api/auth/[...nextauth]/route.ts
import NextAuth, { NextAuthOptions } from 'next-auth';
import { PrismaAdapter } from '@next-auth/prisma-adapter';
import CredentialsProvider from 'next-auth/providers/credentials';
import bcrypt from 'bcrypt';

import prisma from '@/app/prismaClient';

export const authOptions: NextAuthOptions = {
  adapter: PrismaAdapter(prisma),
  secret: process.env.NEXTAUTH_SECRET,
  session: {
    strategy: 'jwt',
  },
  providers: [
    CredentialsProvider({
      name: 'Password',
      credentials: {
        email: { label: 'Eメールアドレス', type: 'text' },
        password: { label: 'Password', type: 'password' },
      },
      async authorize(credentials) {
        if (!credentials) return null;

        const { email, password } = credentials;
        const user = await prisma.user.findUnique({ where: { email } });

        if (!user || !user.password) return null;

        const isPasswordValid = await bcrypt.compare(password, user.password);

        return isPasswordValid ? user : null;
      },
    }),
  ],
  callbacks: {
    async jwt({ token, trigger, user }) {
      if (trigger === 'signIn') {
        token.role = user.role;
        token.emailVerified = user.emailVerified ? user.emailVerified : null;
      }

      if (trigger === 'update') {
        const dbData = await prisma.user.findUnique({
          where: { id: token.sub },
        });

        if (dbData === null) return token;
        token.name = dbData.name;
        token.email = dbData.email;
        token.picture = dbData.image;
        token.role = dbData.role;
        token.emailVerified = dbData.emailVerified
      }
      return token;
    },
    async session({ session, token }) {
      if (session?.user?.email === undefined || !session.user.email)
        return session;
      session.user.id = token.sub ? token.sub : '';
      session.user.emailVerified = token.emailVerified;
      session.user.role = token.role;
      return session;
    },
  },
};

const handler = NextAuth(authOptions);

export { handler as GET, handler as POST };

```
Windows11の日本語化設定をPowerShellで行う

## はじめに

Windows11 の日本語化設定をPowerShellで行います。
Azure上のVMではデフォルトで言語が英語となっているため、主にそのVMの日本語化に使用します。


## 使用環境

使用環境は以下になります。
関係あるのはOSとPowerShellのバージョンくらいだと思います。

- Azure
- VMサイズ : Standard D2_v5
- OS : Windows11 Enterprise,version 22H2 - x64 Gen2
- PowerShell version : 5.1.22621.963


## PowerShellのコマンド

```PowerShell:PowerShell
#日本語の言語パックインストール
Install-Language ja-JP -CopyToSettings

#表示言語を日本語に変更する
Set-systemPreferredUILanguage ja-JP

#UIの言語を日本語で上書きします
Set-WinUILanguageOverride -Language ja-JP

#時刻/日付の形式をWindowsの言語と同じにします
Set-WinCultureFromLanguageListOptOut -OptOut $False

#タイムゾーンを東京にします
Set-TimeZone -id "Tokyo Standard Time"

#ロケーションを日本にします
Set-WinHomeLocation -GeoId 0x7A

#システムロケールを日本にします
Set-WinSystemLocale -SystemLocale ja-JP

#ユーザーが使用する言語を日本語にします
Set-WinUserLanguageList -LanguageList ja-JP,en-US -Force

#入力する言語を日本語で上書きします
Set-WinDefaultInputMethodOverride -InputTip "0411:00000411"

#ようこそ画面と新しいユーザーの設定をコピーします
Copy-UserInternationalSettingsToSystem -welcomescreen $true -newuser $true

#サーバーを再起動します
Restart-Computer 
```

「Install-Language」のコマンドはクライアントOSでのみ使用可能です（2023年2月）
「Copy-UserInternationalSettingsToSystem」のコマンドはWindows11でのみ使用可能です（2023年2月）


## コマンドの実行

対象のVMにRDP接続してPowerShellを実行することも可能です。  
今回は時短の為、Azure Portalから対象のVMにPowerShellを実行します。

![](https://storage.googleapis.com/zenn-user-upload/8b92cf1b6ef8-20230227.png)

1. Azure Portalで対象のVMを選択します
2. 左のメニューから「実行コマンド」を選択します
3. 「RunPowerShellScript」を選択します
4. コードエディタに上記のPowerShellを貼り付けます
5. 「実行」を選択します

![](https://storage.googleapis.com/zenn-user-upload/462a73d671cd-20230227.png)

- 実行完了すると上記画面が出てきます。
- 時間は15分程で終了しました。


## まとめ、所感

- Windows11では日本語化設定をPowerShellで行うことが可能
- 時間は15分程度で終わる
- AVDのイメージ作成の際に便利
- PowerShellを流している間は他の作業ができるため便利
- サーバーOSでも同じコマンドが使えるようになって欲しい


## 参考

この記事を作成するにあたって参考にしたサイトは以下になります。


https://learn.microsoft.com/en-us/powershell/module/languagepackmanagement/?view=windowsserver2022-ps

https://learn.microsoft.com/en-us/powershell/module/international/copy-userinternationalsettingstosystem?view=windowsserver2022-ps

https://www.cloudou.net/virtual-machines/vm005/

https://dev.classmethod.jp/articles/windowsserver2019_to_japanese/
Passengerで複数のRubyのバージョンに対応する

## 環境
- Ubuntu20.4 + Vagrant
- Ruby2.6.0
- Apache2.4.41
- Passenger6.0.18

## はじめに

Apache2 ＋ Passengerの環境で、異なるRubyのバージョンで作られた複数のWebアプリを、共存させて動作させる方法について書きました。もう少し詳しく言えば、Ruby2.7で作られたWebアプリと、Ruby2.6で作られたWebアプリとを、Passengerで共存させる環境の作り方についてということです。

## 内容

#### Passengerのバージョンを確認する

Passengerが複数のRubyバージョンに対応できるようになったのは、Passenger4.0.0以降です。まずは、既存のPassengerのバージョンを確認します。

```
$passenger-config --version
```

Passengerがインストールされているはずなのに、「コマンドがありません」というエラーがメッセージが表示される場合は、パスが切れていない可能性があります。その場合は、自力でコマンドがある場所を探して、絶対パス付きでコマンドを流すことになります。

```
$sudo find / -name "passenger-config*"
```

Redmineがインストールされている環境の場合、Redmineをインストールしたときに、一緒に、Passengerもインクルードされてインストールされている模様です。この辺は要注意です。

```
$/var/www/redmine-4.2.10/vendor/bin/passenger-config --version
Phusion Passenger(R) 6.0.18
```

#### PassengerDefaultRubyディテクティブの設定

Passengerをインストールしたとき、Apache2.confあたりで、つぎのようにPassengerのモジュールを取り込む設定をしているはずです。

PassengerDefaultRubyディテクティブで、利用されるRubyのバージョンを指定しています。ここで設定するRubyのバージョンはグローバルに反映されます。

グローバル値にRuby2.7を設定すれば、Ruby2.7のバージョンでしか使えないのかといえば、それができるようになります。

```/etc/apache2/apache2.conf
<IfModule mod_passenger.c>
  PassengerDefaultRuby /usr/bin/ruby2.7
</IfModule>
```

#### PassengerRubyディテクティブの設定

グローバル値を設定した後、仮想端末（VirtualHost）単位に、PassengerRubyディテクティブでRuby2.7以外のバージョンを設定することができます。設定したバージョンは、仮想端末（VirtualHost）単位で反映されるようになります。つまり、グローバル値でRubyのバージョンを一旦指定するが、その後に読み込まれた、ローカル値がグローバル値を上書きするといったイメージです。

Apache2.confの中のLoadModule passenger_module ディテクティブで、mod_passenger.so
を取り込む設定をしています。mod_passenger.soはグローバルに設定したRubyのバージョン専用のモジュールなのかと思いがちだが、そのようなことはなく、仮想端末単位で設定したRubyのバージョンにも対応しています。

PassengerRubyディテクティブで、仮想端末（VirtualHost）単位に使いたいRubyのバージョンを指定します。ここでは、Ruby2.6.0を指定しています。つまり、mod_passenger.soは、Rubyのバージョンが何であろうが、共通で使えるモジュールだということです。

```/etc/apache/sites-available/hoge.conf
Listen 8000
<VirtualHost *:8000>
    PassengerRuby /usr/local/rbenv/versions/2.6.0/bin/ruby
</VirtualHost>
```

仮想端末（VirtualHost）ごとに異なるポート番号を指定して、接続先を切り分ける必要があるため、ポート番号に8000番を指定しています。デフォルトの80番は他のWebアプリで使っているため、80番と重複しなければ何でもいいことになります。また、Listenディテクティブの設定は、本当は、/etc/apache2/port.confの中にまとめて記述した方がいいでしょう。

PassengerRubyディテクティブで設定するRubyのパスを調べるコマンドです。どちらのコマンドを使ってもOKです。

```
$passenger-config about ruby-command
$passenger-config --ruby-command
```

#### Rubyのバージョンを切り替える

仮想端末（VirtualHost）でWebアプリが入っているディレクトリに移動して、動作させたいRubyのバージョンを切り変えます。

```
$rbenv local 2.6.0
```

#### 動作確認

ブラウザのURLでポート番号8000を指定すれば、Ruby2.6.0版のWebアプリが動作します。

```
http://IPアドレス:8000
```

## 備考

**PassengerDefaultRuby**の詳細
https://www.phusionpassenger.com/library/config/apache/reference/#passengerdefaultruby

**PassengerRuby**の詳細
https://www.phusionpassenger.com/library/config/apache/reference/#passengerruby
python3.11にpipでscikit-learnをインストールしてコード実行したらエラー発生

# はじめに
python3.9で実験していたscikit-learnを使ったpythonのコードをpython3.11で動かしてみようと思いたち、まずはpipでscikit-learnをインストール。
```
macos$ pip3.11 install scikit-learn
```
おそらく最新版のscikit-learnがインストールされた。


# こんなエラーが発生(抜粋)
この状態で件のコードを実行してみると、以下のようなエラーメッセージが出て実行できず
```
ValueError: node array from the pickle has an incompatible dtype:
```
ソースコードを書き直さなきゃ行けないのかな、と思いつつ、先人の知恵を探しにgoogle検索を…


# 対応策を発見
[参考URL](https://discuss.streamlit.io/t/valueerror-node-array-from-the-pickle-has-an-incompatible-dtype/46682,"URL")によると、ダウングレードせよ、とのこと。
```
macos$ pip3.11 install scikit-learn==1.2.2
```
この対応にてとりあえず使えるようになった。しかし、いずれソースコードの見直しは必要なことには代わりはない

# 最後に
qiita-cliがかなり便利なので、思わず作業メモを投稿
Salesforce Edge Network

[まとめページに戻る](https://qiita.com/Keiji_otsubo/items/60afc2a8d211b6f7d89f)
[まとめN～Z](https://qiita.com/Keiji_otsubo/items/92f92bb9f668ca9688be)



+ [Salesforce Edge Network のアクティベーション後にサイトゲストユーザーからファイルまたは添付ファイルを作成するときにエラーが発生しました](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007IeMdQ)
In the flow 'Redemption Flow for Inner Circle', we can't find all the properties for the element Decision Table Outcome.


よくわからんエラー。チェックロジックのバグ？

+ [Error in Set Up a Redemption Process module with Flow config](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000PeJD7)
+ [Create a Flow and Run the Redemption](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007GHQiE)
+ [Error Message with Create a Flow and Run the Redemption trailhead challenge](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000JfOld)
+ [Problems in Trailhead with the challenge Create a Flow and Run the Redemption](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007I7Ijk)
エンコードってなにしてんだ#1.5


そもそも

エンコードシステムで実施していることの具体的な内容とはいったいどのようなものなのだろうか

今回検証している動画のエンコードアプリケーションでは24fpsの動画を取り込ませている
動画の簡単な仕組みとしてはパラパラ漫画と同じで、微妙に異なる連続する画像のつながりであるが
今回の場合では1秒間に24枚の画像を使用したパラパラ漫画ということになる

動画の場合はこれらのフレームに対して

・1フレーム内でのデータを圧縮→1枚の画像を圧縮
・連続するフレーム内でデータを圧縮

という二種類の圧縮方法を実施して動画のサイズを軽くしている

前者の画像の圧縮に関してはドット絵の方式と同じで
例えばドットの横一列のデータが
「黒黒黒黒青青青青赤赤赤赤」と並んでいた際に
これを
「黒4、青4、赤4」というデータにして圧縮するという内容である
これを1枚の画像単位で実施して1枚当たりの容量を軽くしている


後者に関しては
連続するフレームの差分のみを保存するというやり方をとっている。
例えば、固定カメラで動物が走っている動画があったとする
そうした時、背景はそのままに動きのある動物がいるセルのみを保存することで
背景分軽くなるという仕組みになっている。

但し注意点としてこれらのエンコードを実施した際
ビットレートは軽量化に伴い悪くなる。
これは1ピクセルに割り当てられた情報が減ったためによるもので
画質の劣化は避けては通れないものになっている
なお、動画を再生する媒体によってはある程度の画像の劣化が気にならないものもある。
※画面サイズがでかければでかいほど劣化が目立つ

動画のエンコードの場合
１，フレームの枚数を増やして画質を落とす
２，フレームの枚数を減らして画質をあげる
という動画によっての対応があり、
動きが大事な動画なのか、画質が大事なのかで使い分けが可能
また、動きの多い動画に関しては動きの差分元となるキーフレームを細かい感覚で入れることで
差分元の枚数が増え、圧縮量は減るが動画の動きが滑らかになる。
また動画再生の際シークバーを動かした際のプレビューはこのキーフレームをもとにしているため、
動画の再生においてもメリットとなる
（Youtubeのシークバーなども動画によって異なる感覚でシークがある）

これらの前提知識をもとに次回以降確認作業を実施していきたい。
メソッド

### 文字列が持つ特殊能力
具体例を挙げて説明していきます。
```python
>>> address = 'Tokyo,Japan'
```
'Tokyo,Japan'という文字列にaddressという変数名を付けてみました。
addressは文字列型のデータですが、実は文字列型は自分専用の関数をたくさん持っています。

例えば、文字列型は自分自身を特定の文字列で区切る「split」という関数を持っています。これは、文字列型専用の関数なので、今までと少し書き方が違います。
```python
>>> address.split(',')
['Tokyo','Japan']
```
変数名(address)に続けて、ドット(.)を1つ書き、文字列型が専用に持っている関数の名前を書きます。変数名に続けて書くドットは、日本語では「～の」に相当すると考えると分かりやすいです。splitという関数は、文字列型データの持ち物なので、変数名に続けてドットで区切って書くことによって表現しています。また、引数では「何で区切るか？」を指定しています。


|address.split(',')|
|:-:|
|《 文字列型データ(address) 》 の 《 関数(split) 》 + 引数|

このように、あるデータ型が専用に持っている関数のことを、特にメソッドと呼ぶ。

メソッドを呼び出した結果、もとの文字列が'Tokyo'と'Japan'という2つの文字列に分解さてたのが分かります。結果を1つにまとめるため、splitメソッドの戻り値はリスト型になっています。

次は、変数addressのデータをアルファベットのo(オー)で区切ってみます。
```python
>>> address.split('o')
['T','ky',',Japan']
```
oは2か所で見つかるので全体では3つに分割されます。
### 引数のないメソッド
次に引数のないメソッドを紹介します。
upperメソッドは、すべての文字列を大文字にした新しい文字列を返します。
```python
>>> address.upper()
'TOKYO,JAPAN'
```
upperメソッドは引数を持ちません。引数を持たない関数やメソッドを呼び出すときも、丸括弧を省略することはできません。
watsonx.ai の LLM を Watson Machine Learning SDK から使用してみた

## 初めに

以前 wataonx.aiのLLMをcurl、およびPythonからしようしてみた記事を記載しましたが、今回は、Python SDKを使用してLLMを使用してみたので、ご紹介します。

（過去の記事）
**・watsonx.ai の LLMモデル をcurlから使用してみた**
https://qiita.com/ac_qiita/items/66f6f0eb1d2cec896271

**・watsonx.ai の LLMモデル をpythonから使用してみた**
https://qiita.com/ac_qiita/items/b9a481de3c562ed08eba


## Python SDKを使用してLLMでの実行

### 1.SDKライブラリのインストール
pipを使用して、SDKライブラリのインストールを行います。
```
$ pip install ibm-watson-machine-learning
```

### 2. Coding
SDKのマニュアル(https://ibm.github.io/watson-machine-learning-sdk/foundation_models.html)を参照し、コードを作成します。
以下に文章を要約するサンプルを示します。
```summary.py
# Import Libraries
from ibm_watson_machine_learning.foundation_models import Model
from ibm_watson_machine_learning.metanames import GenTextParamsMetaNames as GenParams
from ibm_watson_machine_learning.foundation_models.utils.enums import ModelTypes, DecodingMethods

# Model Parameter Setting
generate_params = {
    GenParams.DECODING_METHOD: "greedy",
    GenParams.MAX_NEW_TOKENS: 1024,
    GenParams.REPETITION_PENALTY: 1
}

# Create Model
model = Model(
    model_id=ModelTypes.MPT_7B_INSTRUCT2,
    params=generate_params,
    credentials={
        "apikey": "xxxxx", #apikeyはご使用環境のものに置き換えてください
        "url": "https://us-south.ml.cloud.ibm.com"
    },
    project_id="xxxxxx" ##project_idはご使用の環境のものに置き換えてください。
    )

# Summarize by using model
q = """簡潔に要約をしてください

入力:
遠足に出かけた11歳から17歳の少年たちと25歳のサッカー・コーチは6月23日、大 雨で増水した洞窟から出られなくなった。タイ内外から集まったダイバー約90人などが捜索に当た り、英国人ダイバー2人によって7月2日夜に発見された。地元のチェンライ県知事やタイ海軍特殊部隊が中心となった救助本部は当初、水が引くか、あるいは少年たちが 潜水技術を習得するまで時間をかけて脱出させるつもりだった が、雨季による水位上昇と洞窟内の酸素低下の進行が懸念され、8日か ら3日連続の救出作戦が敢行された。
ダイバーたちに前後を支えられ、水路内に張り巡らされたガイドロープをたどりながら、潜水経験のない少年たちは脱出 した。8日に最初の4人、9日に4人、10日に残る5人が脱出し、ただちに近くのチェンライ市内の病院に搬送 された。2週間以上洞窟に閉じ込められていたことを思えば、全員驚くほど心身ともに元気だという。\\n少年たちとコーチは レントゲンや血液検査などを受けた。少なくとも7日間は、経過観察のために入院を続けるという。
洞窟内の水を飲み、鳥やコウモリの排泄物に接触した可能性のある13人は、病原体に感染しているおそれがあるため隔離されてい る。家族とはガラス越しに再会したという。\\n食べ物のほとんどない洞窟内で2週間以上を過ごした少年たちは体重を大幅に落とし、空腹を訴えていた。救出後は好物の豚肉のご飯やパン、チョコレートなどを希望したが、しばらく は流動食が続くという。
さらに、外界の光に目が慣れるまでの数日は、サングラスをかける必要がある。

要約:
"""

generated_response = model.generate(prompt=q)
print(generated_response['results'][0]['generated_text'])

```

### 3. コードの実行
作成したコードを実行します。
上記コードの実行結果を下記に示します。
```
$ python summary.py

(出力結果）
- 少年たちとコーチは洞窟から出られなくなった6月23日に、ダイバー約90人などが集まった。
- 英国人ダイバー2人によって7月2日夜に発見された。
- 地元の知事やタイ海軌特殊部隊が中心となった救助本部は、少年たちが潜水技術を習得するまで時間をかけて脱出させるつもりだったが、雨季による水位上昇と洞窟内の酸素低下の進行が懸念され、8日か ら3日連続の救出作戦が敢行された。
- ダイバーたちに前後を支えられ、水路内に張り巡らされたガイドロープをたどりながら、潜水経験のない少年たちは脱出した。
- 8日に最初の4人、9日に4人、10日に残る5人が脱出し、ただちに近くの病院に搬送された。
- 少年たちとコーチはレントゲンや血液検査などを受けた。少なくとも7日間は、経過観察のために入院を続けるという。
- 洞窟内の水を飲み、鳥やコウモリの排泄物に接触した可能性のある13人は、病原体に感染しているおそれがあるため隔離されてい る。家族とはガラス越しに再会したという。
- 食べ物のほとんどない洞窟内で2週間以上を過ごした
```
登記所備付地図データのコンバーターを魔改造

# はじめに

法務省登記所備付地図データの地図XML形式はそのままではGISソフトなどで描画することが出来ないため、GeoJSON形式に変換するコンバーターがデジタル庁から公開されています。

https://www.digital.go.jp/news/4b7250a3-3fcf-4b83-8d52-4bb131e1ba9d

https://github.com/digital-go-jp/mojxml2geojson

# デジタル庁コンバーターの機能

デジタル庁コンバーターの機能はXML形式からGeoJSON形式に変換するものですが、G空間情報センターから配布されている大量のファイルをシェルスクリプトで一括処理をする時に、痒い所に手が届かない部分があります。

個人的に足りないと感じた機能は次のものです。

1. GeoJSONファイルが出力されるディレクトリがXMLファイルと同一のディレクトリになってしまう
1. 配布されているデータはZIPファイルになっているので、別途XMLファイルに展開(unzip)する必要がある

# コンバーターの魔改造

デジタル庁のリポジトリをフォークしたリポジトリで機能追加を行いました。

https://github.com/tkhrmeme/mojxml2geojson

## 1.出力先ディレクトリを指定するオプション

コマンドラインオプションで -o / --output を付加することで出力先のディレクトリを指定します。

```mojxml2geojson -o outputDirectory ./mojmap.xml```
```mojxml2geojson --outout outputDirectory ./mojmap.xml```

上記のように指定すると ```outputDirectory/mojmap.geojson``` が生成されます。

## 2.ZIPファイルを自動展開

XMLファイルを圧縮したZIPファイルを指定すると、一時ディレクトリに自動でXMLファイルを展開し、そこからGeoJSONファイルを生成します。一時ディレクトリと展開されたXMLファイルは変換終了後に削除されます。

```mojxml2geojson -o outputDirectory ./mojmap.zip```

一時ディレクトリの操作には [tempfileモジュール](https://docs.python.org/ja/3/library/tempfile.html)を、.zipファイルの展開には [zipfileモジュール](https://docs.python.org/ja/3/library/zipfile.html)を使用しました。

```Python
import zipfile
import tempfile

with tempfile.TemporaryDirectory() as tmp_dir_name:
    path_tmp_dir = pathlib.Path(tmp_dir_name)

    # zipファイルを展開する
    with zipfile.ZipFile(zip_file) as zf:
        # ファイル名のリストを取り出す
        zf_names = zf.namelist()

        # 一時ディレクトリ内に展開
        zf.extractall(path_tmp_dir)
```

実際の処理は GitHubのリポジトリで公開しています。

https://github.com/tkhrmeme/mojxml2geojson/blob/develop/src/mojxml2geojson/core.py

# 使い方

G空間情報センターから[大分県日田市のデータ](https://www.geospatial.jp/ckan/dataset/houmusyouchizu-2023-1-1928)をダウンロードします。2023年版のファイルは *44204-3207-2023.zip* となります。

*44204-3207-2023.zip* を **unzip** すると *44204-3207-2023* というディレクトリが出来ます。

*44204-3207-2023*ディレクトリ内に展開されたzipファイルから、outputディレクトリへ geojsonファイルを生成するには以下のようなコマンドで処理できます。

```shell
% ls 44204-3207-2023/*.zip | xargs -n 1 -I{} mojxml2geojson -o output {}
```

# 注意

G空間情報センターで公開されているファイルは xmlファイルを一つずつ圧縮してzipファイルにし、さらにそれら複数のzipファイルを一つのzipファイルにまとめるという構成になっています。現在のバージョンではこの構成には対応していないので、ダウンロードしたzipファイルを一度展開する必要があります。

# 参考リンク

https://qiita.com/tkhrmeme/items/871be20533ff024be0d4
VRでロボットプログラミング入門

ロボットプログラミングやってみたいけど、ロボット持ってないし・・・
という方にお薦めの環境です
https://vr.vex.com/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199447/19eeb9b2-7213-e58b-fe08-8503129d9d8a.png)
無料で簡単に始められます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199447/ca2d0340-551b-adad-ef03-274f11dc5c3e.png)
無料でも十分楽しめるコースがたくさん使えます
適当なコース（プレイグラウンド）を選んでみます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199447/701f430f-cfba-ac0b-b02e-fd6b9efea646.png)
？？あれ？？こんな感じでVR？？
右下のカメラマークをクリックすると視点が変わります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199447/9aa3fbe0-0eb4-c240-4b2b-78ff42d64ca1.png)
おお！！これこれ！！！VR！！！
このロボットにスクラッチ的なプログラミングして動かせます
早速やってみましょう！！！
コースの周囲に赤い枠があるので、
前進して、赤い枠を見つけたら、回転する
というようなプログラムにします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199447/9ff2e15c-cd30-e1e0-8d96-94ed8abb149c.png)
こんな感じかな？
実行！！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199447/43370845-689f-b90e-5050-7c110fe747ef.png)
おおお！！
動いた！！！
回転角が90度では、同じ動きを繰り返してしまう！！ので少し変更
ブロックにぶつかって壊しまくります
楽しい！！

もっとやってみたくなったら
左上のチュートリアルや、学習ガイド、サンプルプログラムを参照
チュートリアルは、英語の動画ですが、やさしい聞き取りやすい発音の子供向けのものなので、なんとかなると思います
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199447/0cc810f1-1c97-52d5-ff67-3d7b073b345d.png)
これで、楽しんで、実物のロボットが欲しくなったら、パーツを集めてロボットを作りましょう
VRでロボットを動かしていると、どんなパーツが必要なのか、イメージがつくので部品集めも自分でできるようになりそうです
ちなみに使用言語も選べます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199447/74dcbf83-2ea7-ce71-3d21-7df886eba597.png)
通常、自動的に日本語になるようですが、チュートリアルは英語なので、ブロックの名称などがわかりにくいときは、使用言語を Ebglish に変更しましょう
Javaで「切り上げ/切捨て/四捨五入を取得する」の動作を確認してみた

# 概要

Javaで「切り上げ/切捨て/四捨五入を取得する」の動作を確認してみました。以下のページを参考にしました。

https://www.javadrive.jp/start/math/index7.html

# 実装

以下のファイルを作成しました。
```JSample7_1.java
class JSample7_1{
  public static void main(String[] args){
    System.out.println("Math.ceil(1.34) = " + Math.ceil(1.34));
    System.out.println("Math.ceil(-0.23) = " + Math.ceil(-0.23));
    System.out.println("Math.ceil(3.89) = " + Math.ceil(-3.89));

    System.out.println("-- --");

    System.out.println("Math.floor(1.34) = " + Math.floor(1.34));
    System.out.println("Math.floor(-0.23) = " + Math.floor(-0.23));
    System.out.println("Math.floor(-3.89) = " + Math.floor(-3.89));

    System.out.println("-- --");

    System.out.println("Math.round(4.49) = " + Math.round(4.49));
    System.out.println("Math.round(4.5) = " + Math.round(4.5));
  }
}
```

以下のコマンドを実行しました。
```
$ javac JSample7_1.java 
$ java JSample7_1 
Math.ceil(1.34) = 2.0
Math.ceil(-0.23) = -0.0
Math.ceil(3.89) = -3.0
-- --
Math.floor(1.34) = 1.0
Math.floor(-0.23) = -1.0
Math.floor(-3.89) = -4.0
-- --
Math.round(4.49) = 4
Math.round(4.5) = 5
```

# まとめ
何かの役に立てばと。
【CSS】border色は指定しなくてもcolorを継承する

🌻ボーダー色は指定しなくても
　colorと同じ色になります💡

文字色(color)とborder色を同じ色にしたい場合、
border色の指定は省略してOKです！

勝手にcolorを継承してくれます！

👇詳しくは画像&Codepen参照
https://codepen.io/tomok7/pen/YzdELaN

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2525847/0ab937c5-7357-302e-5d50-7324a9290861.png)
MongoDB Atlasの接続エラーがGoogle DNSの設定で解決した話

## 環境
- Windows11 WSL2 Ubuntu 20.04
- Mongoose@5 を使用

## エラーの発生状況
- WebAppのデプロイに伴い、ローカルのMongoDBからMongoDB Atlasへの移行作業をしていた。
- Atlas上でクラスターの作成が完了し、Database Access、Network Access（0.0.0.0/0）の設定が完了した。
- 作成したクラスターのConnectをクリック -> Driversを選択 -> <b>適当なバージョンのMongoDBをインストール（e.g. npm install mongodb@4.1）</b>-> URIをコピー -> 次のように記述した上で、nodemon app.jsとしてサーバを起動。

```javascript:app.js
// 省略（実際にはdotenvで管理）
const dbUrl = 'mongodb+srv://<username>:<password>@~~~~.mongodb.net/?retryWrites=true&w=majority&appName=AtlasApp';
mongoose.connect(dbUrl,
    {
        useNewUrlParser: true,
        useUnifiedTopology: true,
        useCreateIndex: true,
        useFindAndModify: false
    })
    .then(() => {
        console.log('MongoDB connection ok!');
    })
    .catch(err => {
        console.log('MongoDB connection err!');
        console.log(err);
    });
```

- エラー発生
```bash:bash
MongoDB connection err!
Error: querySrv ETIMEOUT ~~~~.mongodb.net
// 省略
```

## Google DNSを設定して解決
- Windowsの設定 -> ネットワークとインターネット -> プロパティ
- DNSサーバの割り当てを編集する。
  - IPv4
    (優先) 8.8.8.8
    (代替) 8.8.4.4
  - IPv6
    (優先) 2001:4860:4860::8888
    (代替) 2001:4860:4860::8844

## 参考

https://www.mongodb.com/community/forums/t/why-mongodb-connection-gives-etimeout-error-with-expressjs/213715/5

https://totoro-niisan.com/google-public-dns

## 備考
先程のようにした場合、クラスター内の<b>test</b>というDatabase内に、Collectionが作成されていくが、
```javascript:app.js
const dbUrl = 'mongodb+srv://<username>:<password>@~~~~.mongodb.net/?retryWrites=true&w=majority&appName=AtlasApp';
```

このようにパスを追記した場合、クラスター内の<b>hogehoge</b>というDatabase内に、Collectionが作成されていくことになる（e.g. sessions, users）。
```javascript:app.js
const dbUrl = 'mongodb+srv://<username>:<password>@~~~~.mongodb.net/hogehoge?retryWrites=true&w=majority&appName=AtlasApp';
```
（mongosh の show databases の表示が Atlas でいう Database に対応し、mongosh の show collections の表示が Atlas でいう Collection に対応するイメージ？Atlas のクラスターは、mongod --dbpash {path} の {path} に相当するイメージ？）
2023/9/20主にITとかセキュリティの記事

Google検索のWebexの偽広告用いるサイバー攻撃を確認、注意を(9/18)
https://news.mynavi.jp/techplus/article/20230918-2771773/

WebP画像の処理で発見されたゼロデイ脆弱性、「Edge 109」にもセキュリティパッチ(9/18)
https://forest.watch.impress.co.jp/docs/news/1532183.html

iPhoneを乗っ取るマルウェア「Pegasus」、ロシア人ジャーナリストを攻撃(9/18)
https://news.mynavi.jp/techplus/article/20230918-2772569/

ラスベガスの有名カジノ、たった10分の通話からハッキングされる(9/18)
https://www.gizmodo.jp/2023/09/casino-hacked-with-a-10-minute-phone-call.html
https://news.livedoor.com/article/detail/25010189/

SQLインジェクションによる認証回避の練習問題について考えてみました(9/18)
https://qiita.com/akebi_mh/items/a78ef4bff9b201f1713c

MacやLinuxで使う「ncurses」に重要な脆弱性、Microsoftが報告(9/18)
https://news.mynavi.jp/techplus/article/20230918-2772625/

JPKI　個人情報保護、収集は誤解(9/18)
https://www.nikkei.com/article/DGKKZO74530850X10C23A9TL9000/

人工知能が大きな脅威をもたらす可能性についてDeepMindの共同創設者が語る(9/18)
https://gigazine.net/news/20230918-ai-threatens/

「即戦力を」サイバー犯罪捜査官の募集、京都府警が初の中途採用(9/18)
https://news.yahoo.co.jp/articles/1b37bdc03b1e7ce7f8f6a7d5a2d971640911f999

【山形】大石田新そばまつり予約サイトで一時32人分の個人情報漏洩(9/17)
https://www.fnn.jp/articles/-/587626

あふれる情報と向き合う“情報的健康”のススメ(9/18)
https://it.impress.co.jp/articles/-/25364

自社における個人情報取り扱いルールの見直しを(9/17)
https://www.risktaisaku.com/articles/-/83152

韓国政府、情報セキュリティ市場に1000億円投資…2027年には3兆円規模に拡大(9/18)
https://www.afpbb.com/articles/-/3482015?cx_part=top_category&cx_position=4

北朝鮮のハッカーがロシア拠点の取引所を利用して盗まれた仮想通貨を洗浄(9/18)
https://nextmoney.jp/?p=61047

代表者がいないのに自律推進、仮想通貨運営から生まれた組織形態「DAO」(9/19)
https://xtech.nikkei.com/atcl/nxt/column/18/01679/073100124/

Webサイトの改ざん被害、原因のacmailerの脆弱性をさくらインターネットが警告(9/19)
https://xtech.nikkei.com/atcl/nxt/column/18/00598/021300233/

2024年度概算要求でデジタルに1.3兆円規模、デジタル庁一括計上分は5670億円に(9/19)
https://xtech.nikkei.com/atcl/nxt/column/18/00001/08404/
Why We Deploy Ubiquiti

Ubiquiti is a brand that offers a range of networking equipment, including access points, routers, switches, and other networking devices. Ubiquiti is often deployed in various settings, including homes, offices, and public spaces. Due to its reliability, ease of use, and cost-effectiveness.
![Raid-Server.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3561334/63d3366e-8d65-59ae-e7f1-2f53acef22f7.jpeg)


Here are some reasons why we deploy Ubiquiti and organizations may choose to deploy Ubiquiti:

Cost-Effective: Ubiquiti offers affordable networking solutions that provide good value for the money. Making it an attractive option for organizations with limited budgets.
Scalability: Ubiquiti devices are sketching for easily scalable, allowing organizations to easily add additional access points or other networking equipment as needed.
Reliable Performance: Ubiquiti equipment is for its reliable performance and uptime, making it a popular choice for organizations that require a stable network.
Ease of Management: Ubiquiti’s user-friendly management interface allows administrators to easily configure and manage their network devices.
Security: Ubiquiti’s networking devices come with built-in security features, such as firewall and VPN capabilities, which can help protect against cyber threats.
Overall, Ubiquiti’s combination of affordability, scalability, reliability, ease of management, and security features make it an attractive option for organizations looking to deploy a networking solution.