OmniAICreator/Qiita-1.07M huggingface dataset:
【React】useStateとuseRefの違い 【初心者にも分かりやすく】

## はじめに
恥ずかしながら実業務をしてる際に、題目の「useStateとuseRefの違い」
を答えることができなかったので今回はまとめさせて頂きます。

~~文法覚えただけなのほんまに良くない~~

## useStateとは
`useState`とは、関数コンポーネントの`state`を保持したり、更新したりするためのフックになります。
`useState`はReactのコンポーネントの状態管理に使用されており`state`が変更されると**再レンダリング**されます。

```jsx:App.js
import { useState } from 'react'
import './App.css'

function App() {
  const [count,setCount] = useState(0) 

  const handleClick = () => {
    setCount(prev => prev + 1)
  }

  return (
  <>
    <h1>useState</h1>
    <button onClick={handleClick}>count is {count}</button>
  </>
  )
}

export default App
```
上記のコードでボタンをクリックしていくとcountが増えていく簡易的なページが作成されます。

```jsx
 const [count,setCount] = useState(0) 
```
こちらは第１引数に現在の値と、第２引数に更新関数を返しています。
`count`には`useState`の引数が初期値として格納されます。

## useRefとは
`useRef`は、DOMを参照して要素にアクセスするためのフックになります。
また、DOMの参照に使われることが多いですがReactコンポーネント内の値に対して参照を作成するために使用することも可能です。

こちらもサンプルコードで使い方を説明します。

```jsx:App.js
import { useRef } from "react";
import "./App.css";

function App() {
  const ref = useRef(null);

  const handleRef = () => {
    console.log(ref);
    console.log("input", ref.current);
    console.log("value", ref.current.value);
    console.log("width", ref.current.offsetWidth);
  };

  return (
    <div className="App">
      <h1>hello react</h1>
      <input type="text" ref={ref}></input>
      <button onClick={handleRef}>useRef</button>
    </div>
  );
}

export default App;

```
コードについて一部説明します。

```js
 const ref = useRef(null);
```
上記は初期値がnullの、inputを参照を`ref`変数に保持するコードになります。
そしてボタンをクリックして`handleRef`を発火させると...

![スクリーンショット 2023-08-02 1.44.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636995/3aa6e4c8-2be4-532f-7372-733a0313f8fc.png)


上記の出力の通りに通りに、DOM要素にアクセスしていることがわかるかなと思います。

また、`useRef`について補足するとRefオブジェクト`({current: initialValue})`を生成してその値をメモ化しているのが実態になります。

## そんで、結局違いはどこなの？
`state`は変更されると再レンダリングされますが、同じく値を保持できる`ref`の値を変更しても再レンダリングがトリガーされないというところが最大の違いです！

概要として`useState`はコンポーネント内での状態管理に使用し、`useRef`はDOM要素への参照や値の保存に使用されると覚えれば大枠が理解できるかなと思います。

## 参照
https://www.udemy.com/course/react-complete-guide

https://qiita.com/kim_t0814/items/0b27cd5c507a21c95e45#usestate

https://qiita.com/cheez921/items/9a5659f4b94662b4fd1e
【書評】作って学ぶ Next.js/React Webサイト構築

https://ebisu.com/next-react-website/

# 概要
「2023年、新たに学びたいJavaScriptフロントエンドフレームワークはなんだろう？」
と考えると、多くの人はReactが候補に上がるのではないかなと思います。

この本ではReactを学びたい人向け、もっというと、 **Web制作の仕事をしていて、Reactを勉強したい人向け** のReact入門本です🔰

ハンズオン形式で、一冊を通してHeadlessCMSブログ（Next.js + microCMS）を制作する内容です。

（Web制作の仕事はHTML, CSS, jQueryを使用した静的なWebサイト制作やWordPressなどを想定）



# 対象となる読者

**「HTML, CSS, JavaScriptの基本的なことはだいたいわかる」** という人がちょうど良さそうに感じました。

逆に今現在仕事でReactを書いている人がNext.jsを勉強するために使うには物足りないと思います。



# この本の方針(?)

1. JavaScriptを学ぶ
2. Reactを学ぶ
3. Next.jsを学ぶ

という順序で学習するのが **本来の（自然な）学習のロードマップ** だと前置きした上で、**「Next.jsから勉強したらいいんじゃないか？」** と説明されています。


**Next.jsからReactの勉強を開始する良さ** について 下記の3つ が挙げられていました。

- Reactの環境構築が簡単
- サイト構築が簡単（ルーティングなど）
- SSGやSSRを手軽に試すことができる



# 「この本の方針」についての所感
この本の方針について、率直にいいなと思いました。

私は前職でWeb制作会社に勤務しながら、以下のような本来?の自然?な学習のロードマップで学習をしました🚶

- JavaScriptの基本文法を学ぶ
- React
  - コンポーネント設計
  - StateやProps
  - 主要なHooksの使い方
  - ReactでのCSS
  - create-react-appでアプリを作成
- グローバル状態管理ツール（Reduxとか）
- FirebaseやVercelにデプロイ

ざっくり上げるだけでも **Next.jsを勉強するまでに色んなステップを踏む必要があった** 感じがします。

Web制作の現場にいて今後ヘッドレスCMSで実装をする予定がある人にとってのつまずきそうなこと（環境構築, State, Props, Hooks, Reduxなど）をあまり使用せずに、コンポーネント設計やCSSの閉じたスコープ、ルーティングなどのメリットを享受できるNext.jsから学習に入るのは、理にかなっている印象を受けました。

（結局は上記の「つまずきそうなこと」は学ぶ必要がありますが…！）

# この本で学べること

- コンポーネント設計
- CSS Modules
- 記事取得API
- Next.js
  - ルーティング、動的ルーティング
  - Next.js特有のコンポーネントの役割（Image, Link, Layout, etc）
  - getStaticProps, getStaticPaths
- React
  - DOM, JSX, classはclassName使うなど、本書を進める上での基礎知識
  - Hooks（useState, useRef, useEffect）
- microCMSで記事やAPIを作成する
- etc

私がこの本を読んだ2022年時点ではAppRouterについては触れられていませんでしたが、ダウンロードデータで対応がされたとのことです。

> 「Next.js 13 対応ガイド」を更新しました。［2023年7月11日］
✅ Next.js 13で本書を進める方法
✅ App Routerへ移行する方法
をまとめていますので、ダウンロードデータでご確認ください。

書籍WEBサイト（https://ebisu.com/next-react-website/） より




# この本で学べないこと

- Reactの基本的な部分（状態管理、コンポーネント設計、Hooks、ルーティング）
- グローバルな状態管理ツール（Redux, etc）
- TypeScript
- CSS
- デプロイ、テスト
- etc

Next.js + microCMSでブログを作成しながら学ぶのがテーマのため、多くのことをすっ飛ばしています。

そのため上記は **「学べないこと」** ではなく **「学ばないこと」** であって、それがこの本の良さなのかなと思いました。



# 感想

Web制作会社で働きながら「モダンなJSフレームワーク使って仕事したいな〜」と思っていた時期があった自分にとってはとても刺さる内容でした。

説明が丁寧にされているので、 **初めてReact触る人でもすんなり進めることができそう＆ハンズオンで作成するブログがいい感じで楽しさを感じられそう** なので、これからReactを勉強したいWeb制作会社のコーダーの人などにおすすめしたい書籍です。

以下、書籍Webサイトです。


https://ebisu.com/next-react-website/
【React】エイリアスの設定よる簡潔なインポート

# エイリアスとは？
エイリアスは、長いファイルパスを短くするために使用されるショートカットのようなもので、ファイルの絶対パスを簡単に参照するための方法。@が用いられる。

# 設定手順
- react-app-rewiredパッケージをインストール
```
npm install react-app-rewired react-app-rewire-alias --save-dev
```

- config-overrides.tsに以下のコードを追加
```ts:config-overrides.ts
const { alias } = require('react-app-rewire-alias');

module.exports = function override(config) {
  alias({
    '@': './src',
  })(config);

  return config;
};
```

- tsconfig-pathsパッケージをインストール
```
npm install tsconfig-paths --save-dev
```

- tsconfig.jsonに以下の設定を追加
```json:tsconfig.json
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
    }
  },
}
```

- tsconfig-pathsを使ってTypeScriptでconfig-overrides.tsを実行できるように、package.jsonのscriptsを次のように変更。
```json:package.json
"scripts": {
  "start": "react-app-rewired start",
  "build": "react-app-rewired build",
  "test": "react-app-rewired test",
  "eject": "react-scripts eject",
  "start:ts": "ts-node -r tsconfig-paths/register config-overrides.ts",
  "build:ts": "ts-node -r tsconfig-paths/register config-overrides.ts"
},
```

- 以下のコマンドでTypeScript版の設定が適用
```
npm install ts-node --save-dev

npm run start:ts
```


これで@で./srcまでを省略して表すことができるようになる。
phpで応用情報のバブルソートをコード化した

# 概要
応用情報の問題を解いている時にバブルソートの問題を見つけたので、それをプログラムで書いてみました。

# バブルソートとは？
隣り合う数字を比較し、昇順の場合は左側の数字が大きければ順番を入れ替えます。降順の場合は右側の数字が大きければ順番を入れ替えます。


応用情報問題 https://www.ap-siken.com/s/kakomon/04_aki/q6.html




# 完成コード

```php
<?php
$a = ["2", "1", "0"];

for($i = 0; $i <= count($a) - 1 ; $i++){

for($j = count($a) - 1 ; $j >= $i + 1 ; $j--){

if($a[$j] < $a[$j - 1]){
    $w = $a[$j];
    $a[$j] = $a[$j - 1];
    $a[$j - 1] = $w;
}

    }
    echo $a[$i];
}
?>

```

配列はarrayでも上記のような書き方でも可です。


応用情報では大文字のAですが、こちらは小文字で書いてます。特に意味はありません。

# 解説

```php
<?php
$a = ["2", "1", "0"];

for($i = 0; $i <= count($a) - 1 ; $i++){

for($j = count($a) - 1 ; $j >= $i + 1 ; $j--){

```
今回の問題の
初期値0、増分1、終値n-1
ここのnは配列の要素数を表しています。
それぞれiとjに割り当てています。


for文のiは要素数を割り当てます。
もちろんプログラムなので0からです。
配列に値を入れると0=>[2]、1=>[1]、2=>[0]となります

jは要素数を表す変数であり、初期値はn、増分は-1、終値はi+1となります。

# if文

```php
if($a[$j] < $a[$j - 1]){
    $w = $a[$j];
    $a[$j] = $a[$j - 1];
    $a[$j - 1] = $w;
}
```
if文で順番を変えるコードを書きます。

プログラムは人間みたいに、すぐに順番を変えることができません。

一度別の変数に値を入れておく必要があります。
仮に
＄j = 1とします

今回は$ｗに ＄a[＄j]
を挿入します。

$jが1で、＄a[1]になるので、
＄a[＄j]  = 1です。

こちらは＄a[0]なので
＄a[＄j - 1]= 2です。



if文の右側をすべて数字にすると
＄w = 1;

＄a[$j] = 2

＄a[$j - 1] = 1
こうなります。
逆になりました。

これでaの中身が上書きされます。

それで順番通りになるわけです。


# 結論

ムズイ！でも理解できれば楽しいですね。
この問題を理解するのに1日費やしましたが、いい経験でした。


間違ってたらごめんなさい！
linuxファイルシステムについて調べてみた

## ファイルシステムとは

+ 記憶装置をファイル形式で管理するために用いられるOSの機能の一つ
+ ファイルシステムがないと、データを読み出す際に「586732セクタを取ってきて」のような指示をしなければならない
+ 　ファイルシステムは、「どこにどのデータがあるか」、「空き容量はどのくらいあるのか」など全てのデータを管理している


## ファイルシステム構成

+ スーパーブロック
…… 下記の４つの領域がどこにどのくらいの容量で保存されているかを管理する領域。HDDの先頭に配置する。

+ ユーザーデータ領域
…… ユーザーが作成したデータを記録しておくための領域

+ inode管理領域（inodeテーブル）
…… ファイル、ディレクトリのメタ情報を管理する。また、ユーザデータが管理されているブロック情報も管理する領域

+ ディレクトリデータ領域
…… ディレクトリが管理するファイル名をinode番号と紐づけて管理する領域

+ 空きデータ管理領域
…… inode管理領域、ディレクトリデータ領域、ユーザーデータ領域で、未使用の領域を管理する領域

## inodeとは
+ ファイル・ディレクトリ１つごとに作成される。
+ ファイルを管理するメタデータのこと。
+ 高画質の画像や動画であるとファイルサイズが1ブロックに収まらないため複数ブロックを参照する必要がある
+ inodeは、数に限りがあるため、全て使うと、ファイルを作成できなくなる。詳しくは、下記資料を参照してください。

https://blog.amedama.jp/entry/2018/04/21/133823

### inodeにおけるメタデータとは
メタデータとして下記のものが挙げられる

+ inode番号
…… inodeを識別するためのユニークな識別番号

+ 作成時間
…… ファイル及びディレクトリが作成された時間

+ ファイルの被リンク数
…… ファイルをリンク先としているファイルの数
+ 最終更新時間
…… ファイルの最終更新時間
+ ユーザデータのポインタ（ブロック番号）
…… ユーザーが作成した実データがどこにあるかを示すデータ
+ ファイルのパーミッション情報
…… ファイルの権限情報
+ ファイル所有者名
…… ファイルを所有するユーザー名
+ ファイル所有者の所属グループ
…… ファイルを所有するグループ名

##ディレクトリデータ領域
ディレクト内のファイル名とそのファイルのinode番号を紐づけた状態で管理する領域

## 実際の挙動

Hello Worldと記述されたfile1.txtを　catコマンドで出力する場合の挙動は下の図のようになる

１.ディレクトリデータ領域から、ファイル名と紐づいているinode番号を取得
２.inode領域に取得したinode番号を探す
３.inode番号に紐づく、ブロック番号を取得
４.取得したブロック番号を参照
５.出力

![inode.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580067/7ee10976-0afe-2a84-b8dc-5a6d06ff24e0.png)

## 参考資料
https://monoist.itmedia.co.jp/mn/articles/1003/02/news112.html

https://qiita.com/kamihork/items/fbcd116a631324aae05d

https://www.youtube.com/watch?v=XyUFp1SQEic
桁数を揃えて適切にソートする(SPSS Modeler データ加工逆引き2-13)

# 桁数を揃えて適切にソートする

![スクリーンショット 2023-07-24 13.25.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/404a2cc9-1614-6c5d-e75c-bb35d17790c6.png)


## 1.想定される利用目的

・グラフや表でカテゴリが意図する並び順になっていない場合の補正

## 2.サンプルストリームのダウンロード

https://github.com/yoichiro0903n/blue/raw/main/sort.str

## 3.サンプルストリームの説明

![スクリーンショット 2023-07-24 13.28.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/493c7f92-0fad-ba0c-d34d-76d4a0bc705d.png)

a.入力するデータは以下の通りです。この時点でIDは意図通りに並んでいます。

![スクリーンショット 2023-07-24 13.53.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/d45cb03e-9e40-249f-661a-7a72bdaed724.png)


#### ソートができない状況を確認する

b.[線グラフ]ノードを実行します。A1とA2の間にA11とA12が配置されています。
![スクリーンショット 2023-07-24 13.54.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/5dbdcb6a-736b-e443-44e2-5964eb9fc9ba.png)

c.[ソート]ノードを編集します。念の為強制的にIDで昇順ソートします。
![スクリーンショット 2023-07-24 13.55.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/17a93d80-ea11-047b-bf32-7b018c33ab4b.png)

[テーブル]ノードを実行します。A2が2行目でなく５行目に表示されます。Modelerが文字コード順でソートしているためです。
![スクリーンショット 2023-07-24 13.56.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/10de2fb9-748e-6883-4fab-1f9593ef85bb.png)

#### 桁数を揃えてソート可能にする

d.[置換]ノードを編集します。
![スクリーンショット 2023-07-24 14.00.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/b5f03f0d-35d6-cb09-1902-40870de58698.png)

置換[条件]はIDが2文字であるとします。式ビルダを起動して文字列関数から該当関数を探します。
![スクリーンショット 2023-07-24 14.01.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/10ff1061-30b7-5cce-5da8-b5176b98b3c1.png)

[置換値]は関数Substring（N文字目,文字数　,フィールド名）を利用して、1文字目と2文字目を指定し、その間に0を　[><]を利用して配置します。

e.先のcと同じソートを利用します。

[テーブル]ノードを実行します。
![スクリーンショット 2023-07-24 14.07.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/d014b958-66d4-1f04-c90e-3d9ad1e7e394.png)

#### 注意事項

クラスター分析によって、2桁以上のクラスターを利用すると同じ処理を行う必要があります。

![スクリーンショット 2023-07-24 14.12.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/6b928d00-6d79-ab7f-8100-4078fc5e2482.png)


## 4.参考情報

#### 文字列からN文字目を指定する

https://qiita.com/416nishimaki/items/61cc9ab8685f8559bd3c

#### 文字列を結合する

https://qiita.com/416nishimaki/items/35b99152c0f324316792

#### SPSS Modeler ノードリファレンス目次

https://qiita.com/416nishimaki/private/503037195081d3323eee

#### SPSS Modeler 逆引きストリーム集（データ加工）

https://qiita.com/416nishimaki/private/4bf813e6cba84b2a1008
serverless != 利用した分だけ料金を支払う

serverless != 利用した分だけ料金を支払う

aws でOpenSearch collectionとKafka clusterそれぞれ１個を作成し、１か月放置すると、＄1200＋の料金が発生しました。
いずれもawsがあっちこっちのserviceに入れているのserverlessを利用したけど。
一般人にとっては結構高額な料金ですから、EMR on EC2のように、auto-terminationを設定できれば助かりますね。

・OpenSearch
collection を作るだけ、最低でも4 OCUsの料金、月＄700発生しそうです。

・Kafka
Clusterの起動時間単位で課金しているようです。744 * 0.75 = $558.00


Ref.
・OpenSearch
https://aws.amazon.com/opensearch-service/pricing/
https://repost.aws/questions/QUPxlXCMbVSdqLvCqQcW-lMw/clarification-on-opensearch-serverless-pricing

・Kafka
https://aws.amazon.com/msk/pricing/
aws-sdk-go Dynamodb PutItem Err: ValidationException について

# はじめに
初投稿になるので何か指摘等あればよろしくお願いします。

# このエラーについて (ValidationException)
Local環境でsamを利用してAPI経由でLambdaからDockerで建てたLocalのDynamodbにアクセスしている状況です。
Tableはaws-cliで作成し、lambdaからPutItemした時に起きたエラーです。

[AWSの公式](https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/Programming.Errors.html)によると、
> このエラーは、必須パラメータが指定されていない、値が範囲外である、データ型が一致しない、などいくつかの理由で発生します。エラーメッセージに、エラーを引き起こしたリクエストの特定部分に関する詳細が含まれています。

# 結論
Goの構造体の値がエクスポートされておらず、定義されていない状態でした。
なのでデータ型が一致せずにエラーが出たということです。

Dynamodbの項目が小文字から始まる場合、構造体のtagを指定することで解決できます。
(そもそも、項目を小文字から始めるのがよくないかも)


```go
type Item struct {
	Id string `dynamodbav:"id"`
	Name string `dynamodbav:"name"`
}

item := Item{
	Id: "0001",
	Name: "John",
}
```

# コード
```bash
aws dynamodb \
--region ap-northeast-1 \
--endpoint-url http://dynamodb:8000 \
create-table \
--table-name SampleTable \
--attribute-definitions \
AttributeName=id,AttributeType=S \
AttributeName=name,AttributeType=S \
--key-schema \
AttributeName=id,KeyType=HASH \
AttributeName=name,KeyType=RANGE \
--billing-mode PAY_PER_REQUEST
```
```go
// aws-sdk-go-v1
// Connect dynamodb session
session := session.Must(session.NewSessionWithOptions(session.Options{
	SharedConfigState: session.SharedConfigEnable,
}))

db := dynamodb.New(session, aws.NewConfig().WithRegion("ap-northeast-1").WithEndpoint("http://dynamodb:8000"))

type Item struct {
	id string
	name string
}

item := Item{
	id: "0001",
	name: "John",
}

av, err := dynamodbattribute.MarshalMap(item)
if err != nil {
	return err
}

_, err = db.PutItem(&dynamodb.PutItemInput{
	TableName: aws.String("SampleTable"),
	Item: av,
})
if err != nil {
	return err
}
```

# 最後に
とても初歩的なことだったんですが、あまり記事がなかったので誰かの早期解決に繋がれば幸いです。

# 参考文献
https://go-tour-jp.appspot.com/basics/3

https://docs.aws.amazon.com/sdk-for-go/api/service/dynamodb/dynamodbattribute/#pkg-overview

https://stackoverflow.com/questions/59140779/dynamodbattribute-marshalmap-returns-empty-map
Google ColabでOpenAI Whisperを使って自動文字起こしを実現する

# はじめに

OpenAI WhisperをGoogle Colab(無料版)のGPUを使って実行すると、Macbook Pro M1 (8 core)と比較してどの程度速くなるのか確認してみました。[Macbook Pro M1の結果は、以前投稿したこちらの記事](https://qiita.com/vfuji/items/72083b8e64d8a509be67)をご参照下さい。

Google Colab(無料版)の注意事項などについては、[Google Colabのよくある質問](https://research.google.com/colaboratory/faq.html?hl=ja)にまとまっています。`リソースは保証型ではなく、無制限でもありません。使用量の上限が状況におうじて変動します。`との記載があります。よって、この記事の結果は、測定した時の結果に過ぎず、同じ結果が得られる保証はない、ということをご理解下さい。

結果は、3分26秒のオーディオファイルをモデル large-v2を使って計測すると約5倍速いという結果になりました。
Google Colab GPU T4だと1分51秒でした。Macbook Pro M1では、large-v2で9分55秒かかったので、1/5の時間で実行できたことになります。

GPUのすごいを実感した検証結果となりました。ローカルにGPUの実行環境を用意する手間を考えると、メリットだけではないと思いますが、Google Colab環境での実行であれば10分程度でサクッと実行できるようになります。

# 利用した環境

- Google Colaboratory with GPU T4ランタイム

# 環境準備

## Google Colabを開く

GitHubに[サンプル](https://github.com/fujitake/qiita-articles/blob/main/whisper.ipynb)を用意したので開いて下さい。GPU T4のランタイムに接続する前提で開きます。

## Google Driveにファイルを保存

Google Driveを開き、マイドライブの下に適当なディレクトリを用意します。ここでは、whisp1/smallの下にaudioファイルをアップロードしました。

![img01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1557529/1081250d-1c16-9b7c-fbd7-add060ffe1d8.png)

## Whisperのインストール

Google Colabでは `!コマンド`にてLinuxコマンドが実行できます。

```sh
!pip3 install -U openai-whisper
```

```sh
!sudo apt update && sudo apt install ffmpeg
```

## Google ColabランタイムからGoogle Driveをマウント

Google ColabランタイムからGoogle Driveをマウントします。

![img02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1557529/b5eb5504-5a6d-30b4-7a31-310502ec4f0d.png)

Connect to Google Drive(もしくは日本語表示されたボタン)をクリックします。

![img03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1557529/801f043a-d98f-3eda-eb9c-211758433514.png)

`!ls /content/drive/MyDrive`にてアップロードしたファイルにアクセスできることを確認して下さい。

## Whisperの実行

whisper実行コマンドは下記のようになります。ファイル名とパスは適宜修正して下さい。実行時の現在ディレクトリに結果が出力されます。

```sh
!whisper /content/drive/MyDrive/whisp1/small/audio1454496418.m4a --language Japanese --device cuda --model small
```


# 処理時間の計測結果

下記のようにlanguage optionで言語を指定し、さらにmodel optionでモデルを指定しています。前後に`date`を入れることで処理時間を測定しました。

Google Colabは共有リソースの構成だと思います。リソース利用状況などによって、処理時間にばらつきが出ることがあると思いますが、概算比較でどの程度速くなるのか、を確認できれば十分と考えていますので、一度ずつしか測定していません。

CPUでの処理実行コマンド
`!date; whisper audio1454496418.m4a --language Japanese --model small; date`

CPUでの処理結果

|ファイル種別|ファイルサイズ|audio/movie尺|モデル|処理時間|
|---|---:|---:|:---:|---:|
|audio (m4a)|3.3MB|3分26秒|small|0分56秒|

GPUでの処理実行コマンド
`!date; whisper /content/drive/MyDrive/whisp1/small/audio1454496418.m4a --language Japanese --device cuda --model small; date`

GPUでの処理結果

|ファイル種別|ファイルサイズ|audio/movie尺|モデル|処理時間|
|---|---:|---:|:---:|---:|
|audio (m4a)|3.3MB|3分26秒|small|0分32秒|
|audio (m4a)|3.3MB|3分26秒|medium|1分20秒|
|audio (m4a)|3.3MB|3分26秒|large-v2|1分51秒|
lolipopグラフ作成例_作業記録

過去に作成したlolipopグラフのスクリプトを保管するメモ。


```{r setup, include=FALSE}
library(tidyverse)
```


```{r}
#　ベクトル作成（値は適当）
value1 <- c(1.57,3.47,6.05,11.84,1.82,3.35,5.49,9.76,1.52,3.51,6.29,14.46)
value2 <- c(1.72,4.61,9.02,13.09,1.95,4.00,7.29,8.93,1.67,4.79,9.82,20.73)

# カテゴリ列定義
sex <- c("all","all","all","all","Male","Male","Male","Male","Female","Female","Female","Female") 
x <- c("65-69","70-74","75-79","80+","65-69,Male","70-74,Male","75-79,Male","80+,Male","65-69,Female","70-74,Female","75-79,Female","80+,Female")

# dataframe作成
dat <- data.frame(
  x, #年齢階級
  value1, 
  value2,
  sex #性別グループ
  ) %>%
  rowwise() %>% 
  mutate( mymean = mean(c(value1,value2) )) %>% 
  mutate(x=factor(x, x))

```
ggplotを使用してロリポップグラフを作成
```{r}
ggplot(dat) +
  geom_segment( aes(x=x, xend=x, y=value1, yend=value2) ) +
  geom_point( aes(x=x, y=value1), color="tomato", alpha=0.8,size=3 ) +
  geom_point( aes(x=x, y=value2), color="darkgreen", alpha=0.8, size=3 ) +
  labs(color = "value1")+
  coord_flip()+
  theme(
    legend.position = "none",
    panel.border = element_blank(),
    text=element_text(size=15)
  ) +
  xlab("Group") +
  ylab("Incident rate")+
  facet_wrap(~group, ncol=0, scale="free_y")
```


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349193/0a60ee16-4652-9f42-c061-7e0927861903.png)
MySQL関連エラー

touch /usr/local/var/mysql/[マシン名].local.pidでファイルを作成後、`mysql.server start`を実行。
するとエラーが出ました。

` .rm: /tmp/mysql.sock: Permission denied
2023-08-01T17:12:33.6NZ mysqld_safe Fatal error: Can't remove the socket file:
/tmp/mysql.sock.
Please remove the file manually and start /usr/local/Cellar/mysql/8.0.33_3/bin/mysqld_safe again;
mysqld daemon not started
 ERROR! The server quit without updating PID file (/usr/local/var/mysql/joshu.local.pid). `

エラー分通りに以下の実行しました。
``` 
sudo rm /tmp/mysql.sock
```

```
/usr/local/Cellar/mysql/8.0.33_3/bin/mysqld_safe
```

上記実行後は、`control + z` で停止できます。

そして、ログインすると問題なく動きました。
```
mysql -u root
```
AWSのサブネットについて

AWSサービスの「サブネット」について勉強をしたので自身の理解・復習また文章力の向上のためアウトプットさせていただきます。

<h1>はじめに</h1>

<h3>サブネットとは</h3>
クラウド内のIPアドレスを小さなグループに分割する仕組み。これによりネットワークを管理しやすくし、セキュリティを強化できます。VPC内で複数のサブネットを作成し、各サブネットにはネットワーク(EC2など)が割り当てます。
「パブリックサブネット」はインターネットへのアクセスが可能で、「プライベートサブネット」は外部からのアクセスは保護されます。このように違う役割や用途に応じて区別することができる。

上記の説明の「パブリックサブネット」と「プライベートサブネット」を図に表しました。

<h1>全体図</h1>
*分かりやすくするために「リージョン」と「アベイラビリティーゾーン」は省いています。



![サブネット.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3523101/10fe0eab-8782-7ee6-2c4e-1473249646fc.png)


<h3>全体図より</h3>
・パブリックサブネット:EC2
・プライベートサブネット:RDS(データベース)
パブリックサブネットにはユーザーがインターネットゲートウェイを通してEC2にアクセス出来る設定をしているのでユーザーはアクセス可能ですが、プライベートサブネットのRDSには「EC2からのみ」参照出来るように設定しているのでユーザーはアクセスすることが出来ないので大切なデータや情報などを保護出来ます。
デフォルトで2種類のサブネットが存在しているのではなく「ルートテーブル」でインターネット接続の許可をするorしないで用途によって区別する事が出来ます。

<h1>サブネットの各種設定</h1>

<h3>アベイラビリティーゾーン</h3>
アベイラビリティーゾーンは、複数のデータセンターが集まったものを表します。サーバーなどを運用する際は、複数のアベイラビリティーゾーンにサーバーを配置することでリスクを分散できる。
例:日本には関東、関西にアベイラビリティーゾーンがあり、それぞれにサーバーを配置すると、もし関西のデータセンターに問題があっても、関東のデータセンター上のサーバーは動作しているので、サービスの中断を防ぐことができます。

<h3>ルートテーブル</h3>
VPC内の通信設定やインターネット接続などの外部への接続設定は、ルートテーブルで設定できます。適切なルートテーブルを設定することで、VPC内のサブネットに対する通信やインターネットからのアクセスが可能になります。ルートテーブルを適切に管理することで、VPC内のネットワーク通信がスムーズに行なえます。

<h3>自動割り当てIP 設定の変更</h3>
この設定を有効にすると、サブネット内で起動するEC2にはデフォルトでパブリックIPアドレスが割り当てられます。ただし、EC2を起動する際の設定次第で、パブリックIPアドレスの割り当てを無効にすることもできます。つまり、必要に応じてパブリックIPアドレスを有効または無効にできます。

<h3>サブネットの共有</h3>
VPCのサブネットは共有が可能です。
例:新しく顧客になったのサブネットに対して操作を共有できます。また他のユーザーが自分のサブネットも共有できるようになります。

<h1>思ったこと</h1>

今回はサブネットの勉強内容について書かせて頂きました。
IPアドレスを用途別に分割することによりネットワークを管理しやすくなりますし、アクセスの制限なども設定できることからセキュリティを強化出来ます。また複数のアベイラビリティーゾーンに配置することにより問題が合った際はサービス中断などのトラブルを防ぐなどとても便利かつサービスの提供に重要なものだなと感じました。
反対に理解が薄く知識不足の場合は重大なトラブルになるので基礎だからこそ今回の勉強にてしっかり勉強をし理解の必要性を感じました。

最後まで読んでいただいた方、ありがとうございました。
Depth推定のMiDaS v3.1やーる（Windows11、Python3.10）

# はじめに

私のお気に入りのガジェットraytrekのノートPCでMiDaS v3.1やっていきまーす

https://github.com/isl-org/MiDaS

# 開発環境
- Windows 11 PC（i7-12700H、RAM 16GB、RTX3060 Laptop 6GB）
- Python 3.10.11
- PyTorch 1.13.0
- CUDA Toolkit 11.7

https://twitter.com/sotongshi/status/1636564258677981184?s=20

# 導入

1．クローンします

2．CUDA Toolkit 11.7のインストール
https://developer.nvidia.com/cuda-11-7-0-download-archive?target_os=Windows&target_arch=x86_64&target_version=11&target_type=exe_network

3．PyTorchのインストール

https://pytorch.org/

~~~
pip install torch==1.13.0+cu117 torchvision==0.14.0+cu117 torchaudio==0.13.0 --extra-index-url https://download.pytorch.org/whl/cu117
~~~

4．requirements.txtを作成しインストール

~~~requirements.txt
numpy==1.23.4
opencv-python==4.6.0.66
imutils==0.5.4
timm==0.6.12
einops==0.6.0
~~~

~~~
pip install -r requirements.txt
~~~

5．MiDaS-master\weightsにdpt_beit_large_512.ptを置きます


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63863/e0d1e657-97e5-28f9-84cf-81a65249670e.png)

6．実行しましょう！

ファイルから

~~~
python run.py --model_type dpt_beit_large_512 --input_path input --output_path output
~~~

|input|output|
|:--|:--|
|![bus.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63863/069a39ad-0823-8f4d-0924-153950223eee.jpeg)|![bus-dpt_beit_large_512.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63863/846cce33-1a02-7b89-ebb1-795f7f07e2a1.png)|

ウェブカメラから

~~~
python run.py --model_type dpt_beit_large_512 --side
~~~

ESCで終了します。

https://twitter.com/sotongshi/status/1686422027790651392?s=20

2FPSくらい。

お疲れ様でした。
ICLR2023の枝刈り論文 (1)

# 概要

この記事では、[ICLR2023](https://iclr.cc/)の枝刈り論文を紹介します。[^1]

[^1]: 画像や数式は論文から引用しています。

# DFPC: Data flow driven pruning of coupled channels without data.

https://openreview.net/forum?id=mhnHqRqcjYU

- 概要：DFPC. データ無し枝刈りで枝分かれネットワークに対応
- 新規性：枝分かれに対応したSaliency(チャネル毎の重要度)を求める。
- キモ：Algorithm1で計算する。
- 評価：ResNetで実験した。


# Globally Optimal Training of Neural Networks with Threshold Activation Functions

https://openreview.net/forum?id=_9k5kTgyHT

- 概要：Threshold activation (ReLU6など) 付きのネットワークの学習方法
- 新規性：Threshold activation付きのネットワークの最適解を学習する方法を与えた。
- キモ：重み正則化付きLASSOで学習する。(15)式のように変換して最適化する。


# Bit-Pruning: A Sparse Multiplication-Less Dot-Product

https://openreview.net/forum?id=YUDiZcZTI8

- 概要：Bit-Pruning. 積を使わないDNN処理
- 研究機関：DENSO
- 新規性：積を2進数表現を和に変換する前後で枝刈りしたときに2進数表現の電力効率が良かった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2448931/e6457221-0fcb-50d7-7003-b8fff2921929.png)


# NTK-SAP: Improving neural network pruning by aligning training dynamics

https://openreview.net/forum?id=-5EWhW_4qWP

- 概要：NTK-SAP. Foresight pruning (学習前枝刈り)
- 新規性：NASで使われているNeural Target Kernelを用いた枝刈り
- キモ：最適化では収束速度はHessianの最大・最小だけではなく固有値の分布に依存することを参考にして、NTKの条件数ではなく固有値スプクトラムに注目した。固有値スペクトラムをトレースノルムで近似して解いた。
- 評価：ResNet等でSNIP, SynFlow等と比較した。


# Trainability Preserving Neural Pruning

https://openreview.net/forum?id=AZFvpnnewr

- 概要：Filter枝刈りの改良
- 新規性：DNNのTrainabilityを保存する初めてのFilter枝刈り。
  (枝刈りするとTrainabilityが下がる。Trainabilityが下がると学習率を小さくしないと収束しなくなるので、収束が遅くなり精度が下がる)
- キモ：グラム行列が小さいフィルタは0に行くように枝刈りする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2448931/dae4ce97-9cce-30a1-4640-82028001368a.png)
- 評価：学習率を。0.01と0.001で変えて、ありなしで実験した。
AWS上でEC2を使ったDocker環境の構築　Part2

# はじめに
前回の記事までで、Ubuntuのサーバーが出来た。
当記事では、Docker Engineをインストールするところまで行う。

# 目次
1. Docker Engineのインストール
1. Docker Engineがインストールされていることの確認

## Docker Engineのインストール
Ubuntuのパッケージに含まれているDocker Engineではなく、Docker公式から提供されている最新版を使用。

[Docker Engineのインストール概要](https://docs.docker.com/install)

[1] パッケージをアップデートする
下記のコマンドを入力して、Ubuntuのパッケージをアップデートする。
```
$ sudo apt-get update
```

[2]必要なパッケージをインストールする
Docker Engineの実行に必要なパッケージをインストールする。
```
$ sudo apt-get -y install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
```

[3]DockerのオフィシャルGPGキーを追加する
DockerオフィシャルサイトのGPGキーをダウンロードし、登録しておく。

:::note info
GPGキーはファイルが改ざんされていないことを確認するために使われる鍵のファイルです。
:::

```
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
```

[4]Dockerダウンロードサイトをaptリポジトリに追加する
Dockerの公式サイトからDocker Engineをダウンロードできるよう、Dockerダウンロードサイトをaptリポジトリに追加する。
```
$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linus/ubuntu \
  $(lsb_release -cs) \
  stable"
```

[5]Docker Engine一式をインストールする
まずはパッケージをアップデートする。
```
$ sudo apt-get update
```
次に、Docker Engineほか一式をインストールする。
```
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
```

[6]ubuntuユーザでdockerを利用できるようにする
Ubuntuの場合、デフォルトではrootユーザしかdockerを利用できない。
rootユーザに切り替えるのは煩雑のため、次のコマンドを入力し、ubuntuユーザでもDockerを利用できるようにしておく。
```
$ sudo gpasswd -a ubuntu docker
```

[7]ログオフする
一旦切断し、SSHで再接続する。
```
$ exit
```

## Dockerの確認
以上でインストールは完了。
Docker Engineをインストールすると、「docker」というコマンドが使えるようになる。
dockerコマンドに「--version」というオプションをつけると、バージョン番号が表示される。
次のようなメッセージが表示されれば、Docker Engineがインストールされている。
```
$ docker --version
Docker version 24.0.5, build ced0996
```

:::note info
バージョン番号は執筆した時点のもの
:::

# まとめ
これで、UbuntuのサーバをAWS上に構築し、さらにDocker環境を構築することができた。
これから当環境を使ってDockerを学んでいこうと思う。

# 参考文献
この記事は以下の情報を参考にして執筆しました。

・[さわって学ぶクラウドインフラ　docker基礎からのコンテナ構築](https://www.amazon.co.jp/%E3%81%95%E3%82%8F%E3%81%A3%E3%81%A6%E5%AD%A6%E3%81%B6%E3%82%AF%E3%83%A9%E3%82%A6%E3%83%89%E3%82%A4%E3%83%B3%E3%83%95%E3%83%A9-docker%E5%9F%BA%E7%A4%8E%E3%81%8B%E3%82%89%E3%81%AE%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E6%A7%8B%E7%AF%89-%E5%A4%A7%E6%BE%A4-%E6%96%87%E5%AD%9D/dp/4296106422?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=docker%E5%9F%BA%E7%A4%8E%E3%81%8B%E3%82%89%E3%81%AE%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E6%A7%8B%E7%AF%89&qid=1623188221&s=books&sr=1-1&linkCode=sl1&tag=infranote-22&linkId=0af07033c1b663ab6279d327681c5eee&language=ja_JP&ref_=as_li_ss_tl)

# 過去記事
・[AWS上でEC2を使ったDocker環境の構築](https://qiita.com/morimori8304/items/8e5b09ee2b2d2724db3b)
複数のGitアカウントを使い分ける

# 概要
SESで働いていたり副業で別の会社に所属したりしているとその先々でgitアカウントの作成を求められることがあります。PCはもちろん自前です。そうなると同じPCから別のgitアカウントでpushしたりしないといけません。当記事はその設定方法です。(*macで動作確認してます)

# 手順
ここから具体的な手順です。
1. キーペアを作ってgithubに登録
1. ~/.ssh/configに接続の設定を追加
1. 疎通確認
1. gitアカウントの切り替えコマンドを作成

## キーペアを作ってgithubに登録
このステップはgithubに詳細があるのでそちらを参考にしてください。
https://docs.github.com/ja/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account?platform=mac

ターミナルでssh接続するためのキーを作成します。
`-f`はファイル名を指定するオプションです。
```
$ ssh-keygen -f ~/.ssh/git_main
```
これで`~/.ssh`フォルダ配下に`git_main`と`git_main.pub`というファイルが生成されたと思います。
次に公開鍵をgithubに登録していきます。
まずは以下のコマンドで公開鍵の中身をクリップボードにコピーします
```
$ pbcopy < ~/.ssh/git_main.pub
```
コピーできたらgithubの画面に行きます。
アイコン > `setting` > `SSH and GPC keys` > `New SSH　key`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/749155/3311d8e3-652f-8554-c90e-492f36a6e290.png)

![スクリーンショット 2023-08-02 0.55.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/749155/5120b13f-6c15-9420-0741-93073fff3ccd.png)
必要事項を入力したら`Add SSH key`をクリック。
これでssh keyの登録ができました。

## ~/.ssh/configに接続の設定を追加
ssh接続の情報を登録していきます。
```
$ vi ~/.ssh/config
```

```
# Gitメインアカウントのssh情報
Host github
  HostName github.com
  IdentityFile ~/.ssh/git_main
  User git
  Port 22
  TCPKeepAlive yes
  IdentitiesOnly yes
```
入力できたら`esc` > `:wq` で抜けます

## 疎通確認
```
# githubのところはconfigに設定したHostです。
$ ssh github
PTY allocation request failed on channel 0
Hi #{ユーザー名}! You've successfully authenticated, but GitHub does not provide shell access.
Connection to github.com closed.
$
```
sshコマンドを打って上記のようなメッセージが表示されればssh接続成功です。

## gitアカウントの切り替えコマンドを作成
```
$ vi ~/.bashrc
```
```
# gitアカウントを切り替える
function gitmain() {
  git config --global user.name "ユーザー名"
  git config --global user.email "メールアドレス"
  source ~/.bashrc
}
```
入力できたら`esc` > `:wq` で抜けます
```
$ source ~/.bashrc
```
編集を読み込みます。

これで作業は終了です。記事の中では1つのアカウントしか設定していませんが、これをアカウント分追加することでアカウントの切り替えが簡単にできます。
以下のコマンドを打つとgitアカウントが切り替わります。
```
$ gitmain # functionに設定した関数名です
```
アカウントが切り替わったかは以下のコマンドで確認してください。
```
$ git config user.name
$ git confit user.email
```

# 追記 2023/9/27
cloneコマンド
```
$ git clone {設定したHost}:リポジトリURL
```

# 最後に
間違っている箇所を見つけたり、わからない箇所がありましたらコメントください。
僕の勤めている会社です。ご興味あれば是非。

https://www.ses.gigooo.com/
rails newからgit pushまで（SSH接続）

# 目的

SSH接続で最初のPushをする方法のメモ


# やったこと
新しいアプリを作り、Pushしようと思ったらユーザー名とパスワードではできなかった...。
SSH接続だとできるらしいので、やる。


### railsアプリの作成
環境構築は一通り終わっているので
以下でrailsアプリを作成します。
```shell:cmd
rails new test
```

### リポジトリの作成

https://github.com/

上記から、リポジトリを作成します。
今回は、「test」という名前でリポジトリ名以外はデフォルトで作成しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693325/589fd76c-1eed-e703-f024-8a3d82e5f619.png)

### SSH公開鍵の登録
以下のコマンドを入力してカギを作成します。
```shell:cmd
ssh-keygen -t ed25519 -f .ssh/ed25519 -C " "
```

GitHubで、アカウントの「setting」→「SSH keys and GPG keys」→「New SSH Key」を開き、
できた鍵ペアKeyの `.pub` がついている方の中身をKeyに貼り付けます。
※鍵ペアは `C:\Users\【ユーザー名】\.ssh` の中にある
※タイトルは任意
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693325/f78b66ad-d0eb-4eae-262a-5b1e6e0a57d3.png)
↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693325/70edf1f6-901b-9bac-6c92-f52f451b5ba4.png)

「Add SSH Key」を押して、公開鍵を追加します。


### Push
以下のコマンドで、Pushします。

```shell:cmd
git init                       // 自動で実行されるが一応初期化
git add -A                     // ステージエリアに全てのファイルを追加
git commit -m "first commit"   // commit
git branch -M main　　　　　　　// 現在のブランチ名をmainに変更
git remote add git@github.com:${GitHubのユーザ名}/${リポジトリ名}.git
                               // リモートレポジトリの登録
git push -u origin master      // Push
```

# 余談
進捗は毎日生やそうね。
Windows PowerShell に複数行を貼り付けようとすると警告が出る

### 背景

競プロをVisual Studio環境で解いていると、ある時期からコンソール（Windows PowerShell）に改行を含むテキストをペーストをすると以下の警告が出るようになった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1199864/8e4292d9-f1c9-7b9f-fb5f-d8d620047a0d.png)


下記サイト曰くどこかのリリースタイミングで改行を含んだ文字列をペーストする際に警告が表示されるようになったらしい。
https://loumo.jp/archives/25767

実際に自分の環境ではWin11にアップグレードしたタイミングで警告が表示されるようになり、邪魔なので設定変更して警告を非表示にした。

### 設定手順
1. Windows PowerShellの設定を表示する
    以下のようにWindows PowerShellを起動して、「設定」をクリック。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1199864/a74ceeb3-0467-1b25-cea1-72b228635520.png)

2. 下のほうにある「JSONファイルを開く」を選択し、設定ファイルを開く
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1199864/65fde3df-a003-b1a0-79aa-650b6661b871.png)

3. JSONファイルを任意のエディターで開く

4. 設定値を記載しているところで以下のように「multiLinePasteWarning」の設定を追加し、falseを設定する。
    ```json
    "copyFormatting": "none",
    "multiLinePasteWarning": false,
    "copyOnSelect": false,
    ```
    こんな感じ。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1199864/a3cb607b-b460-035a-5005-d8de34a63967.png)


**これで毎回の警告表示から解放されました！**

<br><br>
<br>


以下はブログというか吐き出し。

> 仕事で落ち込みまくったので、メンタルのリセットがてら久々に記事を書いた。
> 自分の市場価値が低いことを痛感させられたので、もっと技術勉強と発信をしていこうと思った。
> Notionに溜めまくっている備忘も整理して、定期的に発信しようと思う。
"Pythonのforループ内でリストを更新する時の注意点：上書きと追加の違い"

Pythonでループ内でリストを更新する際には注意が必要です。特に、上書き(=)と追加(extend)の違いは重要です。次の2つのコードスニペットを考えてみましょう。

1つ目のコードスニペット:

```python:ex1.py
for i in range(5):
    # iの2乗の値をリストに格納
    squares = [i ** 2]
    print(squares)
```
2つ目のコードスニペット:


```python:ex2.py
squares = []
for i in range(5):
    # iの2乗の値をリストに追加
    squares.extend([i ** 2])
    print(squares)
```

これらのコードは、ループの各ステップで数値の2乗を計算し、それをsquaresリストに格納しようとしています。しかし、これらの振る舞いは全く異なります。

1つ目のコードでは、ループの各ステップで新しい2乗の数値が計算され、それが新しいリストとしてsquaresに上書きされます。その結果、squaresにはループの各ステップで新しく生成されるリスト（つまり、1つの2乗の数値だけを持つ）が上書きされていきます。

一方、2つ目のコードでは、ループの各ステップで新しい2乗の数値が計算され、それがsquaresリストに追加されていきます。extendメソッドを用いているため、squaresにはループの各ステップで計算された2乗の数値がすべて格納され、リストが順次拡張されていきます。

これらの違いを理解することで、Pythonでリストを更新する際の予期しない挙動を防ぐことができます。
サイトのファビコンの取得方法


## 取得方法

以下のURLにファビコンを取得したいサイトのドメインまたはURLを末尾に追記するとファビコンが別のタブで表示されます。

```
http://www.google.com/s2/favicons?domain=ファビコンを取得したいサイトのURL
```
ファビコンのサイズは16x16ですが、表示されたタブのURL末尾の`size=`の値を変更することで別のサイズを取得できます。

```
https://t2.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=ファビコンを取得したいサイトのURL&size=64

```

上記の場合には64x64が表示されます。
プロトコルで関数にデフォルト引数を指定する方法(Swift)

## はじめに

プロトコルで関数にデフォルト引数を指定しようとすると、以下のビルドエラーが発生します。

```swift:LoggerProtocol.swift
protocol LoggerProtocol {
    // ✅
    func debug(_ message: String, file: String, function: String, line: Int, column: Int)

    // ❌: Default argument not permitted in a protocol method
    func debug(_ message: String, file: String = #file, function: String = #function, line: Int = #line, column: Int = #column)
}
```

しかしログ出力のたびに `#file` や `#function` を渡すのは非常に手間です。
実はデフォルト引数を指定する方法があるので紹介します。

## 環境

- OS：macOS Ventura 13.4.1
- Xcode：14.3.1 (14E300c)
- Swift：5.8.1

## プロトコルで関数にデフォルト引数を指定する方法

プロトコルをextensionで拡張することで、関数にデフォルト引数を指定できます。

```diff_swift:LoggerProtocol.swift
protocol LoggerProtocol {
    func debug(_ message: String, file: String, function: String, line: Int, column: Int)
}

+ extension LoggerProtocol {
+     func debug(_ message: String, file: String = #file, function: String = #function, line: Int = #line, column: Int = #column) {
+         debug(message, file: file, function: function, line: line, column: column)
+     } 
+ }
```

プロトコルに準拠したクラスを実装します。

```diff_swift:Logger.swift
+ final class Logger {
+     static let shared = Logger()
+ 
+     private init() {}
+ }
+ 
+ extension Logger: LoggerProtocol {
+     func debug(_ message: String, file: String, function: String, line: Int, column: Int) {
+         print("\(file).\(function):\(line):\(column) - \(message)")
+     }
+ }
```

実際に引数を省略して呼び出せることを確認します。

```swift
let logger: some LoggerProtocol = Logger.shared
logger.debug("Hello, Swift!")
```

無事に呼び出すことができました。

```
main.swift.Page_Contents:24:13 - Hello, Swift!
```

## おわりに

今までプロトコルの関数にデフォルト引数を指定できないと思っていたので、 [Twitterで教えていただき](https://twitter.com/omochimetaru/status/1686339551470768129) 本当に感謝です。

## 参考リンク

- https://twitter.com/the_uhooi/status/1686276951521267712
- [Update logger by uhooi · Pull Request #372 · uhooi/UhooiPicBook](https://github.com/uhooi/UhooiPicBook/pull/372)
CSSの優先度には気をつけようの話

### Laravel-adminでadmin画面を作成中・・・
ということで、本日はHTMLでフロントを作成していました。
色変えたり、文字を揃えたり、gridを調節したり、、、。

Laravel-adminを使用しており、
admin画面はBootstrapがガンガンついています。

デフォでも綺麗につくれるのですが、
微妙なカスタマイズを行う必要がありまして、、、

### BootstrapがかかっているところにCSSが追加できない！！
Bootstrapがかかっているところにはstyle属性をつけてもCSSがつかないんですね、、、
知らなかった、、、
悩むこと1時間ほど、、、、、

## CSSには優先度とやらがあるらしい！
ということを知ったのでした。
参考　http://creator.aainc.co.jp/archives/4947

importantつけたらimportantになるのね、CSSちゃんかしこい。

優先順位について理解する余力がなかったので、
解決策として、Bootstrap.cssを直接編集する荒技（？）を取りました。
コメントアウト残しといたからだいじょぶだいじょぶ

### まとめ
直接Bootstrapファイルを修正することで、大体は解決しましたが、
同じクラス（foreach文で作成）に対して別々のCSSの付け方は分からず、、、
ぐすん。

未だ、JSの問題が残っているので、明日解決してやるぞい

```
<script src="https://code.jquery.com/jquery.min.js"></script>

<script>
    $(document).ready(function() {
        $('#search_button').click(function() {
            $('.box-body').slideToggle(); // toggleメソッドで表示・非表示を切り替える
        });
    });
</script>

clickでbox-bodyが、slideToggleするけど一瞬で元に戻る（泣
```
ちょっと動くから逆におもろい。
preventDefaultが怪しいと睨んでいるのじゃ。

ってことで、
さくらみこちゃんも５周年を迎えたことだし、
おじさん頑張っちゃうぞぉ！

おわり。
Nest.js TypeORMとDBの接続設定について

## 開発環境での手順

1. Docker等でDBを作成
2. 以下コマンドでライブラリをインストール

    ```bash
    npm i typeorm@0.2.45 @nestjs/typeorm@8.0.2 pg
    ```

3. src/entities/○○.entity.tsを作成し記述
4. ormconfig.jsに接続情報を記載

    ```bash
    module.exports = {
        type: 'postgres',
        host: 'localhost',
        port: 5432,
        username: 'postgres',
        password: 'postgres',
        database: 'postgres',
        autoLoadEntities: true,
        entities: ['dist/entities/*.entity.js'],
        migrations: ['dist/migrations/*.js'],
        cli: {
        entitiesDir: 'src/entities',
            migrationsDir: 'src/migrations',
        },
    }
    ```

5. src/app.module.tsにtypeOrmの設定を記載

    ```bash
    import { Module } from '@nestjs/common';
    import { TypeOrmModule } from '@nestjs/typeorm';

    @Module({
      imports: [TypeOrmModule.forRoot()],
    })
    export class AppModule {}
    ```

1. 下記コマンドを実行

    ```bash
    # migrationファイルを作成
    npx typeorm migration:generate -n Create○○

    # distディレクトリにコンパイルさせるため一度ローカルでrun
    npm run start:dev

    # typeormのmigrationを実行
    npx typeorm migrations:run
    ```

1. pgAdminなどで確認
![typeOrm実行後のDB.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/781232/f7b92e80-e654-8060-84f8-a8487f2a5fb6.jpeg)
@State #SwiftUIの修飾子に関して簡単にアウトプットしてみる

## はじめに
今後、何回かに分けて@〜と表現されるSwiftUI特有の修飾子についてアウトプットしていく。
前提として、これら修飾子の付いたキーワードは`プロパティラッパー`などと呼ばれる。
プロパティラッパーとは、ものすごく簡単にいうと、`値の数を増やす・減らす・確認するなどを簡単にできる機能`みたいなニュアンスである。また、その値の変更に伴って、自動的に画面描画（画面の更新）をしてくれる便利な機能も存在する。

## @Stateの詳細
- @Stateはプロパティラッパーの一つで、状態を管理するために使われる
- 値が更新されたらViewが自動的にリロード（再描画）される
- structの中で値を変更できる
- @Stateは親Viewとその配下の子Viewでしかアクセスできないため、private修飾子を付与し、外部からアクセスできないようにするのが好ましい。というか、それが暗黙のルール。
## ソースコード
```swift:Swift
// Textの下にボタンがあり、ボタンを押すと、Textのテキストが変化する。で挙動を確認する。
struct ContentView: View {
    @State private text = "Hello"

    // Textの下にボタンを配置。ボタンを押すとTextのテキストが変化する。
    var body: some View {
        VStack {
            Text(text)

            Button("ボタン") {
                // ボタンが押され、textには"こんにちは"が代入される。
                // 代入、つまり、値を更新されるのでViewは再描画される。
                text = "こんにちは"
            }
        }
    }
}

```

## おわりに
間違い等ありましたらコメント欄にてご指摘ください！

## 参考記事
- [SwiftUIドキュメント](https://developer.apple.com/documentation/swiftui/)
- [カピ通信](https://capibara1969.com/)
- [iOS-Docs](https://ios-docs.dev/)

## 開発環境
- Xcode-14.3
- Swift version 5.8
フィッシャーの判別分析

# 2クラス分類の場合
### 問題設定
2つのクラス$C_1$と$C_2$に帰属するデータ$\rm{\boldsymbol{x}_i}$があるとき、うまく境界線を引いてデータをクラスごとに分割したい。
言い換えると、D次元のベクトル$\rm{\boldsymbol{w}}$で
```math
\rm{\boldsymbol{y}_i} = \rm{\boldsymbol{w}}^T\rm{\boldsymbol{x}_i}
```
のようにデータ$\rm{\boldsymbol{x}_i}$を$\rm{\boldsymbol{y}_i}$に投影した(線形変換に相当)とき、それぞれのデータの投影先がクラスごとにまとまりかつ別のクラスのデータどうしが混ざらないようにしたい。

### 線形変換wが満たすべき条件
上で述べたような、投影した後のデータがクラスごとにまとまっているための条件は、以下の2つとする。
#### ①投影先で、各クラスの平均どうしが離れている
各クラスの平均ベクトルをそれぞれ$\mathrm{\boldsymbol{m}_1}$, $\mathrm{\boldsymbol{m}_2}$とすると、平均間の偏差は、
```math
\mathrm{\boldsymbol{w}^T\boldsymbol{m}_1-\boldsymbol{w}^T\boldsymbol{m}_2 =\boldsymbol{w}^T(\boldsymbol{m}_1-\boldsymbol{m}_2)}
```
とあらわされる。後の計算のため二次形式であらわすと
```math
\begin{align*}
&
\mathrm{\boldsymbol{w}^T(\boldsymbol{m}_1-\boldsymbol{m}_2)(\boldsymbol{m}_1-\boldsymbol{m}_2)^T\boldsymbol{w}}\\
&=\mathrm{\boldsymbol{w}}^TS_B\mathrm{\boldsymbol{w}}
\end{align*}
```
となり、特に**クラス間分散共分散行列**$S_B$を
```math
S_B = \mathrm{(\boldsymbol{m}_1-\boldsymbol{m}_2)(\boldsymbol{m}_1-\boldsymbol{m}_2)^T}
```
と定義した。
#### ②投影先で、各クラスのばらつきが少ない
投影先での、クラス$C_k$内での分散は
```math
\begin{align*}
&
\sum_{x_i\in C_1}(\mathrm{\boldsymbol{w}^T\boldsymbol{x}_i-\boldsymbol{w}^T\boldsymbol{m}_1})^2+\sum_{x_i\in C_2}(\mathrm{\boldsymbol{w}^T\boldsymbol{x}_i-\boldsymbol{w}^T\boldsymbol{m}_2)^2} \\
&= \sum_{k=1,\ 2}\sum_{x_i\in C_k}\mathrm{\boldsymbol{w}^T(\boldsymbol{x}_i-\boldsymbol{m}_k)(\boldsymbol{x}_i-\boldsymbol{m}_k)^T\boldsymbol{w}}\\
&=\mathrm{\boldsymbol{w}^T}S_W\mathrm{\boldsymbol{w}}
\end{align*}
```
とあらわされる。特に**クラス内分散共分散行列**$S_W$を
```math
\begin{align*}
S_W &= \sum_{x_i\in C_1}\mathrm{(\boldsymbol{x}_i-\boldsymbol{m}_1)(\boldsymbol{x}_i-\boldsymbol{m}_1)^T} +\sum_{x_i\in C_2}\mathrm{(\boldsymbol{x}_i-\boldsymbol{m}_2)(\boldsymbol{x}_i-\boldsymbol{m}_2)^T}\\
&=\sum_{k=1,\ 2}\sum_{x_i\in C_k}\mathrm{(\boldsymbol{x}_i-\boldsymbol{m}_k)(\boldsymbol{x}_i-\boldsymbol{m}_k)^T}
\end{align*}
```
と定義した。
#### 評価関数
以上の①と②をまとめて評価したい。具体的には
```math
\begin{align*}
J(\boldsymbol{w}) &= \frac{\text{クラス間平均の偏差の二乗}}{\text{各クラス内の偏差二乗和}} \\
&= \frac{\mathrm{\boldsymbol{w}}^TS_B\mathrm{\boldsymbol{w}}}{\mathrm{\boldsymbol{w}}^TS_W\mathrm{\boldsymbol{w}}}
\end{align*}
```
を最大にする$\mathrm{\boldsymbol{w}}$をもとめることになる(以後、$\mathrm{\boldsymbol{w}}$の大きさを1として考える)。$J(\mathrm{\boldsymbol{w}})$が最大となるとき、
```math
\frac{\partial J(\mathrm{\boldsymbol{w}})}{\partial \mathrm{\boldsymbol{w}}} =0
```
が成り立ち、変形すると(省略)
```math
\mathrm{\boldsymbol{w}} \propto S_W^{-1}(\mathrm{\boldsymbol{m}_1-\boldsymbol{m}_2})
```
と計算される。
### 固有値問題の解としてのw
$\mathrm{\boldsymbol{w}}$は、行列$S_W^{-1}S_B$の固有ベクトルである。証明は~~とんちみたいなものなので~~省略。
【Kaggle】初心者がKaggleをGoogleColaboratory上で実行したら躓いた話

# はじめに
今回、初投稿ということで


「KaggleをGoogleColaboratory上で実行したら躓いた話」をしたいと思います。

この記事が、私のようなKaggle初心者の助けになれば幸いです。

# Kaggleとは
Kaggleは、データサイエンスおよび機械学習のコンペティションプラットフォームです。
![Kaggle](https://zeeshanusmani.com/wp-content/uploads/2019/10/Kaggle3.png)
[Kaggle(https://www.kaggle.com/)](https://www.kaggle.com/)

データサイエンティストや機械学習エンジニアがデータセットを提供し、解析や予測モデルの作成に取り組むことができます。ユーザーは共同でプロジェクトに参加したり、スコアを競い合ったりしながら、問題解決能力を向上させることができます。

また、Kaggleは知識共有のプラットフォームとしても機能し、豊富なデータセットやノートブック、コンペのソリューションなどが利用可能です。



現在（2023/08/01）、私は以下のコンペに参加しています。

##### [Google Research - Identify Contrails to Reduce Global Warming](https://www.kaggle.com/competitions/google-research-identify-contrails-reduce-global-warming?rvi=1)

このコンペの概要は以下になります。

>飛行機雲は航空機の排気から生じる氷の結晶の雲で、地球温暖化に寄与します。研究者はモデルでコントレイルの発生と温暖化を予測し、衛星画像で検証したいと考えています。この競技は飛行機雲モデルの精度向上を目指し、航空会社が飛行機雲の発生を避けて気候変動の影響を減らす手助けをします。飛行機雲の発生回避は航空産業にとって持続可能な解決策の1つであり、確実な検証によりパイロットと航空会社に信頼性のある対策を提供します。


概要を理解した後は、早速モデルの開発をしていきます。

今回は初めてのsubmitということもあり、先駆者のコードからデータの前処理や学習モデル、提出方法などを学んでから実装に移りました。

実装にはGithubとの連携を考えて、GoogleColaboratoryで行うことにしました。

（この時点では面倒でVScodeにGPUの設定をしていませんでした。初めからVScodeで環境を構築していれば…）

# GoogleColaboratoryとは
![GoogleColaboratory](https://su-gi-rx.com/wp-content/uploads/2020/06/py796.png)
[GoogleColaboratory](https://colab.research.google.com/?hl=ja)

Google Colaboratory（通称：Google Colab）は、Googleが提供するクラウドベースのJupyterノートブック環境です。

無料で利用でき、Pythonを含む複数のプログラミング言語をサポートしています。データサイエンスや機械学習のタスクを実行し、GPUやTPUなどの高性能なリソースを利用して、共同編集や共有も容易に行えます。

ローカル環境に高性能なCPUやGPUがない人はぜひ利用してみてください。



加えて、Git-hubとの連携も数十秒で完了します。

Kaggleなどのデータの加工や、モデルの検証を繰り返し行う場合は、バージョン管理が容易なGit-hubと連携することをお勧めします。

https://github.co.jp/





# 問題

Google ColaboとGithubと連携して、早速モデルの開発に身を乗り出しました。

どうやら、KaggleにてデータセットをダウンロードできるAPIが提供されているとのこと。

以下のブログを参考にして、KaggleからGoogle Colaboにデータセットをダウンロードしました。


https://dreamer-uma.com/kaggle-api-colab/

しかし、何時までたっても処理が終わりません。

これはおかしいと思い、処理結果を見ると

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3523467/28d421c4-a3fc-075a-af0a-d2fafa5ad75f.png)


### 残り時間1時間22分？？？

どうやら、私が住んでいる学生寮の底辺Wi-Fiが主な原因のようです。

他にも、今回のコンペで提供されるデータセットの大部分がRGBの画像ということもあり、データ量が膨大になっていると考えられます。

これまずいと思い、対策手段を調べていると

>GoogleColabは90分、もしくは12時間経過するとランタイムが強制的に終了する


という追い打ちをかけるような情報を発見しました。

このダウンロード速度でも比較的速い方なので、酷いときはダウンロードだけで
半日が終わるなんてことも十分あり得ます。

例え、データセットをダウンロードしたとしても、モデルの学習時にランタイムが終了しては意味がありません。


上記の理由から、KaggleでGoogle Colaboratoryの使用を中止することにしました。

# 最後に

Kaggleのデータセットはtitanicなどのテーブルデータから、今回のような画像データや音声データなどデータの種類は多岐にわたり、それに応じてデータ量も変化します。

そのため、住んでいる場所の回線の性能が悪いと、今回のような事態が発生してしまいます。


これまで、E資格の提出課題や大学の授業などでAnacondaばかりを使用していたこともあり

環境構築とは無縁の生活を送っていましたが、そのツケが回ってきたように思えます。

幸い、回線以外のローカル環境は悪くない性能なので、大人しくHDDにデータセットをダウンロードしてVScodeでモデルを実行したいと思います。
【初心者向け】UnityでTimelineのAnimated Valuesの値が見れないときの対応方法Ⅱ

UnityでTimelineのAnimated Valuesの値が見れないときⅡの対応方法です。

# ここにグラフがあったはずなのに表示されていない
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506075/b0713268-cce0-1b0a-ad52-4e9c87d9959d.png" width="640"/>

# AnimationTrackの横にあるグラフボタンを押せばよい!
![anim.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506075/60881ed2-eef6-6fa0-9b76-05cce83b3ce5.gif)

以上！
Internet Explorerを使わずにブラウザでOracle Forms 10gまたは11gにアクセスする方法

![Oracle.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3486144/53af8413-39aa-d1ee-9c52-4593c2255bca.jpeg)

Internet Explorerが使われなくなり、ブラウザからOracle Forms 10gや11gにアクセスすることがますます難しくなってきました。

これらのバージョンのOracle FormsはJavaアプレットか、FSALのようなスタンドアローンのJavaベースのランチャーに依存しているからです。IEのEOLは、主要なブラウザがセキュリティ上の問題から、Javaプラグインを含むNPAPIプラグインのサポートをやめ、最新のHTML5を採用する傾向に続いている。

IEの無効化によって、Oracle Formアプリケーションへのアクセスを維持する必要がある企業のワークフローに大きな変化が生じ、MicrosoftのEdgeとEnterprise Mode Site List（EMSL）が必要になりますが、このプロセスにはいくつかの欠陥が考えられます。

# Internet Explorer ModeとOracle Formsの問題
マイクロソフトがInternet Explorerのサポート終了を発表した際、Edgeには引き続き "Internet Explorer" モードを搭載すると表明しましたが、これはユーザー・エクスペリエンスを損なうものです。これによって、Javaプラグインを使用してブラウザ上でOracle Formsを実行できるようになりますが、ユーザー・エクスペリエンスは失われます。

例えば：
・Enterprise Environmentでは、Internet Explorerモードはデフォルトでは有効になっていません。これは、各ユーザーのEdgeブラウザー設定で、URLパターンに基づいて手動で有効にする必要があります。

・Oracle Formsを含むWebページを実行する唯一の方法は、まずEdgeでOracle FormsのURLを実行することです。ユーザーは手動でEdgeのメニューから「その他のツール」を選択する必要があります。その後、「Internet Explorer モードで再読み込み」をクリックして、Internet Explorerモードでアプリケーションを再読み込みする必要があります。これでOracle Formsアプリケーションは正常に実行されます。

・エンドユーザーがFormsアプリケーションを終了するか、エラー(FRM-92103、FRM-93652など)で終了させられた後、再びURLを実行してFormsに戻ろうとすると、ユーザーは再び空白のページを体験し、Internet Explorerモードでページを再読み込みするステップをやり直さなければなりません。

そのため、面倒な作業となるだけでなく、インターネット・エクスプローラーに欠陥がある可能性があるため、セキュリティ上の問題につながる可能性もある。__さらに、この方法ではJavaのローカルインストール、定期的なセキュリティメンテナンス、ライセンスが必要になる。__

# Oracle Formsにアクセスする別の方法
CheerpJは、ミッションクリティカルなJavaアプリケーションとアプレット（Oracle Forms 6i、10g、11g、12cを含む）へのアクセスを、Internet Explorerのサポート終了後も最新化し、維持するための[エンタープライズ・グレード・ソリューションです。](https://leaningtech.com/cheerpj/)

ローカルにJavaをインストールすることなく、Javaアプレットやアプリケーションを最新のブラウザ上で実行できるようにするだけで、Oracle Formsを完全に維持することができます。__CheerpJはプレゼンテーション層でのみ動作し、HTML5でJavaクライアントを効果的にエミュレートします。これは、データベース、サーバーサイドのロジック、Oracle Formsビルダーを使ったクライアントサイドのビルドなど、Oracle Formsアプリケーションの他のすべてが維持されることを意味します。__

CheerpJは、ChromeとEdgeで利用可能なブラウザ拡張機能として、または先行コンバータとして使用することができます。

# CheerpJ Applet Runner
[CheerpJ Applet Runner](https://leaningtech.com/cheerpj-applet-runner/)は、JavaプラグインやインストールなしでJavaアプレットを実行するためのChromeとEdge用のブラウザ拡張機能です。これにより、Chrome、Edge、Firefox、Safari、またはその他の最新のブラウザでOracle Formsにアクセスできるようになり、最新のITアーキテクチャで社内またはサードパーティのOracle Formsを使い続けることができます。

CheerpJ Applet Runnerは、エンタープライズ環境で使用することができ、Microsoftベースのエンタープライズ・アーキテクチャ上のEdgeやChrome上でGlobal Policy Objectsを介して展開することができます。

# CheerpJ AOT
**CheerpJ ahead-of-time**コンパイラーは、Oracle Forms アプレットや FSAL を含む Java アプレットやアプリケーションを HTML5 (WebAssembly や JavaScript) に変換できる開発ツールです。

CheerpJまたはCheerpJ Applet Runnerのいずれかを使用することで、組織は完全に書き直すことなく、Oracle Formsベースのアプリケーションへのアクセスを維持することができます。

Enterprise Oracle FormsアーキテクチャへのCheerpJの統合は非常に簡単で、Proof of Conceptsは通常は数日、完全な統合は数週間で完了します。CheerpJは、オリジナルのOracle Formsアプリケーションと共有できるHTTPサーバー以外に、サーバーサイドのインフラを必要としないため、ランニングコストは最小限です。

CheerpJの詳細については、[Webサイト](https://leaningtech.com/cheerpj/)をご覧ください！

[個人情報保護方針](https://leaningtech.com/privacy-policy/)をご覧ください。

[引用元](https://leaningtech.com/how-to-access-oracle-forms-10g-or-11g-in-the-browser-without-internet-explorer/)