OmniAICreator/Qiita-1.07M huggingface dataset:
なんとなくでReactでMaterial UI(MUI)のDateTimePickerを使ってみた

# はじめに
まず、この記事を書いている私がReact、MUI歴３ヶ月ちょっとの半端者です。
そのため、フィーリングで書いている部分が多々あります。
間違っている部分があるかもしれませんがとにかく実装するため調べてわかったことを書き記します。
# やりたかったこと
[調整さん](https://chouseisan.com/)みたいなものを作りたかった。
その中でカレンダーを押したら、選択した日時が入力されるっていう機能を実装しようと調べ始めた。
# DayPicker,TimePicker
カレンダーや時計のコンポーネントを使用して日時を決まった形式で出力してくれるコンポーネントの総称。
ライブラリとして公開されているものが「なんちゃらDayPicker」みたいな名前で公開されている。

まず、このPickerという名前にたどり着かなくてやりたいことを実現するためのコンポーネント探すのに苦労した。

MUIの他にも公開されているものはあるが、CSSを書きたくなかったのと他の部分で既にMUIを使っていたのでMUIのDateTimePickerを使うことにした。
# MUIのDateTimePicker
英語だけど[チュートリアル](https://mui.com/x/react-date-pickers/getting-started/)はある。
チュートリアルを見ると、表示とかはやるけど実際に現在時刻の表示や日時を出力するときのフォーマットは別のライブラリに任せてる感じかな？ってなった。

# 実際に使ったやつ
チュートリアルではないけどカレンダーを常に表示できないかなあ〜ってことで探してたら、[staticモード](https://mui.com/x/react-date-pickers/date-time-picker/#static-mode)を見つけた。

じゃあ、これを使おうと試行錯誤した結果以下のようなコードに落ち着いた。
```react:calender.js
import React, { useState } from 'react';
import { StaticDateTimePicker, LocalizationProvider } from '@mui/x-date-pickers/';
import { Box, TextField } from '@mui/material/';
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
import { useRecoilState } from 'recoil';
import format from 'date-fns/format';
import { ja } from 'date-fns/locale';
import { formValueState, selectedDayState } from '../../../recoil/state';

const PickDayCalendar = () => {
  const [value, setValue] = useState(); //カレンダーの中で値を保持しておくためのstate
  const [selectedDates, setSelectedDates] = useRecoilState(selectedDayState);
      const [values, setValues] = useRecoilState(formValueState); //今回はあんまり関係ない裏でゴニョゴニョstate

  const handleChange = (v) => {
    setSelectedDates(selectedDates ? selectedDates+'\n'+format(v, 'yyyy-MM-dd HH:mm') : format(v, 'yyyy-MM-dd HH:mm'));
    const newValues = {
      ...values,
      proposed_at: selectedDates.split('\n'),
    };
    setValues(newValues);
  };

  return (
    <Box>
      <LocalizationProvider adapterLocale={ja} dateAdapter={AdapterDateFns}
        localeText={{
          previousMonth: '前月を表示',
          nextMonth: '次月を表示',
        }}>
        <StaticDateTimePicker
          displayStaticWrapperAs="mobile"
          openTo="day"
          toolbarTitle="日付選択"
          toolbarFormat="MM月dd日"
          disablePast={true}
          value={value}
          onChange={(v)=>{
            setValue(v);
          }}
          onAccept={handleChange}
          renderInput={(params) => <TextField {...params} />}
        />
      </LocalizationProvider>
    </Box>
  );
};

export default PickDayCalendar;

```

絶対無駄はあるけどこの形に落ち着いた。
recoil使ってますが、この辺はuseStateで置き換えれると思う。

# 軽く説明
コードに色々書いていますが、重要なPickerのパラメータです。
- displayStaticWrapperAs
モバイル版にするかPC版にするか。PC版にするとAMとPMの表記が飛び出しまくって治せなかったのでモバイル版を使ってます。
- disablePast
過去の日程を選択できないようにするパラメータ。
- onAccept
OKボタンを押したときに実行される関数を入れるところ。

この３つが個人的には見つけにくくて辛かった。
あとは説明が下手なので自分で調べてください。
[props](https://mui.com/x/api/date-pickers/static-date-time-picker/#props)の説明を日本語訳して読んだり、[stackoverflow](https://stackoverflow.com/)とかで調べたらわかるかも。

# 結論
MUIはCSSとかわからなくてもなんとなくで使えるのが強み。デザインをもっと調整したいなって思ったらsxのパラメータとかいじればできるっぽいし万能すごい（小並感）。

少しでも私のコードが誰かの参考になりますように
正規表現を使うバリデーション

# 2.6 format
このヘルパーは、withオプションで```与えられた正規表現と属性の値がマッチ```するかどうかを検証します。
```rb
class Product < ApplicationRecord
  validates :legacy_code, format: { with: /\A[a-zA-Z]+\z/,
    message: "英文字のみが使えます" }
end
```
```:without```オプションを使うと、```指定の属性にマッチしない正規表現を指定することもできます。```

デフォルトのエラーメッセージは「```is invalid```」です。
### 出典
https://railsguides.jp/active_record_validations.html#:~:text=2.6%20format,is%20invalid%E3%80%8D%E3%81%A7%E3%81%99%E3%80%82

# 感想
正規表現が大変だった。
pgAdminでテーブルが表示できないトラブルシューティング

## 環境
pgAdmin4 v3 (Windows10)
psql (PostgreSQL) 12.10 (Ubuntu 12.10-1.pgdg20.04+1)

## 内容
pgAdminからPostgreSQLに接続して、テーブルを表示しようとするとエラーが表示されて、表示ができませんでした。
```エラー内容
error fetching sql for script column rel.relhasoides does not exit
```

このようなエラーも表示されます。
![無題1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94029/ed652db4-e94d-6048-42f3-a087dba65518.png)

エラーの内容は、**relhasoides**という名前のカラムが存在しませんというエラーです。いろいろとググってみたところ、サーバー側のPostgreSQLのバージョンに対して、pgAdminのバージョンが古いと、このようなエラーが表示されるようです。

relhasoidsという名前のカラムは、**pg_class**というシステムカタログに、以前は存在していたが、削除されたという過去を持っています。バージョン11までは存在していたが、バージョン12から削除されています。

エラーが出るということは、現状のpgAdmin4 v3は、バージョン12以降に対応していないということなので、バージョンを上げる必要があります。どのバージョンから対応しているのかについては、ぐぐっても情報が見つからなかったため、手っ取り早く、最新版をインストールすることにしました。2022年1月30日時点での最新版は、pgAdmin4 v6.19です。



## ダウンロード
PostgreSQLの公式サイトです。
https://www.postgresql.org/

下記をクリックしてダウンロードします。
![無題2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94029/ffbcccc1-817c-7ed7-e0ab-9cfe9e4ab7ef.png)

## pg_classの確認
pg_classカタログにrelhasoidsカラムは本当に存在しないのか、次のコマンドで確認することができます。\dは、テーブルの列一覧を取得するコマンドです。

```psql
\d pg_class
```

pg_classを直接表示させても確認ができます。
```psql
select * from pg_class
```
これまで気にしていなかった命名規則について考えてみる

## はじめに
プログラミングにおいて命名規則というものが存在する。
明確なルールとまではいかないそうだが、ある程度こういう場合はこのように書くなどの法則があるそう
実際にコードを書いていて、変数名だったりクラスの作り方だったりで書き方に迷う場合があったので調べて今の理解なりにまとめてみます。

## 命名規則とは
変数名などコンピュータプログラムのソースコード上で開発者が名付ける識別名についての決まりごと。
言語仕様や開発環境などによって定められているものと、ソフトウェア開発を行う組織やチームが内部的に定めるものがある。
その中でよく使われる`スネークケース`や`キャメルケース`、`ケバブケース`について少しまとめていく。

### 命名規則がなぜ必要か
クラス名やメソッド名、関数名、定数名、変数名など、プログラム上で定義して扱う対象に名前を付ける機会は多くあるが、
複数人で開発を行う場合などにそれぞれが異なる考え方や基準で名前を付けると、互いのコードの可読性や視認性が損なわれ、開発効率や保守性の悪化につながる。
また名前の衝突や使い回しなどでバグが生じることもある。

そこで、名前の付け方に一貫したルールを設け、これに従って識別名を命名するようにするのが命名規則である。
よく定義された命名規則に従うと、対象の意味や機能、使い方などが名前からある程度推測できるようになり、コード自体がドキュメントの役割を果たすようになる。
検索や置換、ツールによる自動化なども行いやすくなり、デバッグや修正、追加開発の効率も向上する。

どのような規則を定めるかはプログラミング言語や開発環境の制約、組織やメンバーの考え方や方針によって様々であり、必ずしも良し悪しや優劣を論じられるものではなく、規格化された標準などがあるわけでもない。
言語やフレームワークによっては仕様上定められている命名規則が存在する場合もある。

### キャメルケース【camelCase】
英語の複合語や、フレーズ（句）や文を一語に繋げて表記する際、“JavaScript” のように各構成語の先頭を大文字にする方式を「キャメルケース」（camel case）という。
大文字部分が上に出っ張っているのをラクダ（camel）のこぶに例えた呼称である。

このうち、“getDate” のように先頭は小文字とする方式を「ローワーキャメルケース」、
“GetWindow” のように先頭も大文字とする方式を「アッパーキャメルケース」あるいは「パスカルケース」という。

### スネークケース【snake_case】
単語の間をアンダーバーでつなぐ命名規則。DBなどで扱われる値に使用されることが多い。
大文字がなく、長く一連なりに文字が続く様を地を這う蛇（snake）になぞらているとのこと。

### ケバブケース【kebab-case】
単語の間をハイフンでつなぐ命名規則。HTMLではclass名であったり、ファイル名などでよく使われる。

## どのケースを採用すべきか
現場によってどのケースが採用されているかはまちまちなことが多いとのこと。
一般的には下記のような感じで採用されることが多いそう。
```
キャメルケース　→　プログラミングでの関数や変数
スネークケース　→　DBなどで扱う値
ケバブケース　→　HTMLのclass名
```

可読性だったりバグだったり考えることがたくさんありますね。
もっと理解を深めて良いコードを書けるように精進していきます。
企業会計の基本と損益分岐点

# 売上高を求める
営業利益率は営業利益÷売上高で求めることができる。
営業利益率は16%にしたい。
問題文を読みながら計算式を立てる。

```0.16=(x-2,100)÷x```

#### 0.16
目標の16％を表す

#### x-2,100
xは目標の売上高
2,100は```営業費用が前年度と同額```と書いてある。

これらで計算すると営業利益を表すことができる。

# 計算すると
xは2500になる。
つまり
利益率を１６％にした時の売上高は2500になるので
目標前の売上高から引くと増加分を求めることができる。

300

# 営業利益を求める
売上高を上げずに営業利益を抑えて利益率を16％にする問題

### テキストの解答方法
前年度と目標の表を作ってどう変化しているのかを整理している。

* 売上高を上げないので```２２００```
* 今回は営業利益をどれくらい抑えるかを求めるので```y```
* 利益は営業利益はわからないので```(2200-y)```
* 利益率は```１６％```にする

### 利益率を求める計算式で求める
0.16=(2200-y)/2200
で計算できる。

### 削減額を求める
yが```１８４８```これが１６％にした時の営業費用になる。
どれくらい削減するかを求められているので
これで前年度の営業費用からひく。
すると```２５２```になる

# 固定費の削減額を求める
問題文に関係式が書かれているのでそれを参考にとく。

#### 変化の表を作成する
* 売上高は2200
* 変動費は```売上高は変化しないものとしないもの```と書いてあるので1100
* 安全余裕率が２０％になった時の固定費を求めるので```x```
* 限界利益率は売上高と変動率が変わらないので```50%```
* 損益分岐点売上高は```x/0.5```
* 安全余裕率は```２０％```

### 安全余裕率を２０％にした時の固定費を求める。
固定費＝(売上高-売上高*安全余裕率）*限界利益率
になる。
xは８８０になる。
つまり削減後の固定費が880になる。

### 削減額を求める
削減前と削減後の固定費を引くと削減額がもとまる。
１２０になる。

# 安全余裕率を上げた後の他商品の安全余裕率を求める
前の問題で求めた削減額120を他商品の固定費に回すそうだ。
その時の安全余裕率を求める。

### 変化の表を作成する
* 売上高は800が1000に上がる
* 変動費は```売上高が上がったのでその倍率分あがる```。
    1000/800=1.25　1.25倍になるので400*1.25=```500```になる
* 固定費は```製品zの固定費に追加する```ので```４００```になる。
* 損益分岐点売上高は計算して```800```

### 安全余裕率を求める
安全余裕率は計算式を使って0.2になる。
２０％

# 値引きなしで販売した場合の営業利益率を求める
１２％割引しなかったほうの売上高は同じだった。
そうすると１２％分の売上個数は減少している。
なので売上高の変動費も下がる。

### 変動費を求める
変動費は個数が減少しているので1100*(1-0.12)=968

### 営業利益率を求める
営業利益を求める
売上高-(固定費+変動費)で２３２になる。

営業利益/売上高で0.1054...になる。

少数第一を四捨五入して整数にするので0.105になり10.5%になる。
１０％になる。

# 感想
計算の過程を文字起こしするのは疲れた。
しかし整理された。
計算方法も知れてよかった。

# 出典
https://gihyo.jp/book/2022/978-4-297-12377-2
Flutter ボタンのonPressedをnullにしてるのにボタンが非活性にならない時

# はじめに
ボタンを非活性にする方法として`onPressed`に`null`を渡す方法があります。

https://hiyoko-programming.com/1457/

が、、、

**`null`を渡してもボタンの色が灰色に変わらないやんけーーー！！！**
という事態に陥って、ちょっとハマってしまったのでここに記録したいと思います！

# 三項演算子の位置が間違っていた。。

```dart
 ElevatedButton(
      onPressed: () {
        _inProgress ? null : decidePosition();
       },
        child: const Text('次へ！'),
      ),
```

特定の処理（今回の場合`decidePosition()`）をしている最中に`_inProgress`が`true`の時`null`を渡し、ボタンが連打できないように非活性にしたかったです。
しかし、👆のコードでは非活性になりませんでした。。。

なぜだ？？？？と思ったが、めっちゃうっかりミスしてました！

```dart
ElevatedButton(
  onPressed: null,
  child: const Text('次へ！'),
)
```

👆の場合は非活性になり、しっかりボタンの色が灰色に変化します。
ということは、、、、

```dart
ElevatedButton(
        onPressed: _inProgress
           ? null
           : () => decidePosition(),
        child: const Text('次へ！'),
     ),
```

これで無事`_inProgress`が`true`の時ボタンを非活性にし灰色に変化させることができました。。。:sweat_smile:
macOS に rvm をインストールする

macOS に `rvm` (Ruby Version Manager) のインストール方法を記述します。
※ `rvm` とは、`ruby` バージョンの切り替えソフトウェアです。

## 環境

- macOS Ventura バージョン 13.1

## Install GPG keys

- `GPG` (GNU Privacy Guard) パッケージのインストールします。

```sh
brew install gpg
```

- `rvm` インストールパッケージの検証に使用する `GPG` キーをインストールします。

```sh
gpg --keyserver keyserver.ubuntu.com --recv-key 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
```

※ [公式ページ](https://rvm.io/rvm/install) に書いてあるコマンドを使うとエラーになります。
`gpg: 鍵サーバからの受信に失敗しました: Server indicated a failure`

## Install ruby and rails

- `ruby` と `rails` をインストールします。

```sh
curl -sSL https://get.rvm.io | bash -s stable --rails
```

## RVM Commands

- `rvm` の更新をします。

```sh
rvm get stable
```

- インストールされている `ruby` バージョンの一覧を確認します。

```sh
rvm list
```

- `ruby` をインストールします。 (例 v3.0.2)

```sh
rvm install ruby-3.0.2
```

- 利用する `ruby` バージョンを切り替えます。 (例 v3.0.2)

```sh
rvm use 3.0.2
```
rails + tailwind でherokuにデプロイするとエラーになる

# 概要
タイトルのままだが、rails + tailwindcss使ってherokuデプロイ時にエラーになる。
ちなみにローカルでは正常に動く。

# 前提
## バージョン
- Rails 7.0
- tailwindcss 3.2.4

## エラー内容
```
remote:        rake aborted!
remote:        SassC::SyntaxError: Error: Function rgb is missing argument $green.
remote:                on line 1 of stdin
remote:        >> dden]){--tw-divide-opacity:1;border-color:rgb(229 231 235/var(--tw-divide-op
remote:           ------------------------------------------^
```

# 解決方法
```rb:config/environments/production.rb
# 追記 or 書き換え
config.assets.css_compressor = nil
```

# 原因
sassc-railsとtailwindcss-railsが干渉してるっぽい。

参考サイトはこちら。
https://stackoverflow.com/questions/70662382/couldnt-deploy-rails-tailwind-on-heroku
検索キーワード：`tailwind heroku deploy SassC::SyntaxError`


エラー内容もほぼ同じだった。。
【WPF】Enum を Attribute に設定した値に変換する汎用的な Converter を作った

# 課題
Enum を定義して、それを一覧等に表示する際、Enum の値をそのまま使えない事はままある。例えば、プロジェクトの制約で Enum に日本語を使ってはいけない場合や、Enum 値を数字から始めたいが、数字から始まる文字列は使えないため、別の名称で定義している場合等だ。その場合、変換用のメソッドと変換後の値の表示用プロパティ等を新たに用意したりするのだが、私の場合、変換に関しては、Attirubte の設定と Enum の拡張メソッドの作成で解決することが多い。
```C#
    public enum Apple
    {
        [Description("ふじ")]
        Fuji,
        [Description("紅玉")]
        Kogyoku,
        [Description("陸奥")]
        Mutsu,
        [Description("23号ふじ")]
        Fuji23,
        [Description("47号紅玉")]
        Kogyoku47,
    }
```
```C#
    public static class EnumsExtensions
    {
        // Enum の拡張メソッド。自身に設定されている Description Attribute の値を返す
        public static string GetDescription(this Enum value)
        {
            var field = value.GetType().GetField(value.ToString());
            // field が null になることは無いが、警告回避のために null 条件演算子を使用
            var attr = field?.GetCustomAttribute(typeof(DescriptionAttribute)) as DescriptionAttribute;
            return attr?.Description ?? string.Empty;
        }
    }
```

これは結構便利だが、一覧等に Bind して表示する場合に、表示用の string プロパティを用意しなければならないという問題を抱えていた。この表示用プロパティは、Entity が巨大だと結構邪魔になっていた。また、表示用プロパティの代わりに Convereter を利用する方法もあるが、Enum 型の数だけ用意しなければならないのでは無いかと考え、今まで表示用プロパティを新たに設ける形で対応していた。

# 解決方法
上記の課題に対して、汎用的な Converter を用意できないかと考えて、次のようなものを作ってみた。
```C#
using System;
using System.Globalization;
using System.Windows.Data;
using System.Windows.Markup;

namespace EnumConverter.ViewModels
{
    public class EnumToDescriptionConverter : MarkupExtension, IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            => value?.GetType().IsEnum ?? false
                ? ((Enum)value).GetDescription()
                : string.Empty;

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => null;

        public override object ProvideValue(IServiceProvider serviceProvider) => this;
    }
}
```
```xml
<DataGridTextColumn Width="100" Binding="{Binding Apple, Converter={vm:EnumToDescriptionConverter}}" />
```

# 終わりに
この Converter により、表示用プロパティから解放されました。


# 更新履歴
2023/01/31:
@albireo 様から指摘を受けてコードを修正しました。ありがとうございます。例外処理の部分を削除し、拡張メソッドの書き方を修正しました。
チーズはどこへ消えた?の感想

# 内容について
「チーズはどこへ消えた？」を読んだ感想をメモするついでに初記事を投稿しようという意図を含む記事です。

# チーズはどこへ消えた？について
ビジネス本です。
みんなが絶対に読むべき本としてよく取り上げられている本です。
ページ数は少なく、１時間ほどで読み終わります。

[チーズはどこへ消えた？](https://www.amazon.co.jp/%E3%83%81%E3%83%BC%E3%82%BA%E3%81%AF%E3%81%A9%E3%81%93%E3%81%B8%E6%B6%88%E3%81%88%E3%81%9F-%E3%82%B9%E3%83%9A%E3%83%B3%E3%82%B5%E3%83%BC-%E3%82%B8%E3%83%A7%E3%83%B3%E3%82%BD%E3%83%B3/dp/459403019X)

# 感想
この本の内容は身の回りに起きた変化に対してどうかネガティブにならないで欲しいという祈りの本だと思いました。
「変化」の極端な例を挙げると以下になります。
- 付き合ってる人と別れてしまった
- 家が火事になってしまった
- 家族が亡くなってしまった

相当辛いと思います。
但し、僻んでいても前には進めません。
この変化を一生引きずってしまっては、人生の最後まで楽しい瞬間に出会えなくなるかもしれません。
 
では、上記で挙げた変化が起こらないという可能性はあるでしょうか。
 
残念ながら、答えはNOになるでしょう。
挙げた例は極端に思いますが、毎日、世界中の誰かの周りで起きていることだと思います。
 
正直ネガティブにならないわけがないと思います。
しかし、何が言いたいかというと、
 
**この変化は必ずしも起こらないということではなく、変化は予測できるということです。**
 
もちろん全く予想できない変化はありますが、それは滅多にないかと思います。
大体のことは一生懸命考えれば予測できる可能性があり、予測したくないことに対して無意識に考えないようにしているケースもあると思います。
予測すれば、変化する可能性のある事柄に対して、喰い止めることができたり、変化に対応する準備ができるかもしれません。
変化を予測することで未来に対する行動を起こさなければならないという気持ちになるのです。
 
この本の中で、変化に対してネガティブになり、長い間引きずってしまうある登場人物がいます。
読んでいる時、誰だってそのようになってしまう可能性はあると思いましたし、どうか頑張って乗り越えて欲しいと思いました。
但し、この本の内容にはその登場人物が乗り越える姿などは描かれておらず、その者の結末は分かりません。
 
その者を動かす方法について考えましたが、この物語一通り読んで説得された気になりました。
何が言いたいかというと、それほど簡単に人は変わらないし、変化に対応しろなんて乱暴に伝えても多分何も変わらないでしょう。
私がこの本を読んで受け取った答えとして、まさに今読んでいる
**この本を読ませる**
という方法を教えてもらったのかなと思いました。
身の回りの変化に対応できない方に対して、どうか乗り越えて欲しく、自分の言葉で考え方を変えさせるのが難しいと思った時に、この本をそっとおすすめしようかと思いました。

　 
以上、完全なポエムでした

# 最後に
チーズ消えないで〜〜〜〜〜！！！！！
jQueryのjqXHRをconsole.logするとUncaught TypeErrorが出る

jQueryの$.ajaxメソッドでデータ取得/更新の際にエラーが発生した際のエラーハンドリングについて記述します。

# `fail()`の引数オブジェクトからエラー情報を取得する
最初にNG例です。  
$.ajax()実行時にエラーとなった場合に呼び出される`fail()`の第一引数である`jqXHR`オブジェクト[^1]にHTTPステータスコードとエラーメッセージが格納されているので、それらを参照します。

## コード(NG例)

```javascript
$.ajax({
  // 省略
}).done(() => {
  // Ajaxリクエストが成功した場合の処理
}).fail((jqXHR, textStatus, errorThrown) => {
  // Ajaxリクエストが失敗した場合の処理
  const httpCode = jqXHR.status; // HTTPステータスコード
  const errorMessage = jqXHR.responseText.error.message.value;
  console.log(`Status Code: ${httpCode}, Message: ${errorMessage}`); // エラーレスポンス
});
```

上記のコードを実行するとエラーが発生しました。

## 実行結果
```console
Uncaught TypeError: Cannot read properties of undefined (reading 'message')
```
# どうすればエラー情報を取得できるのか
## 結論
レスポンスの`Content-Type`に沿った内容で`jqHXR`オブジェクトにアクセスすれば良いです。

## コード
```javascript
$.ajax({
  // 省略
}).done(() => {
  // Ajaxリクエストが成功した場合の処理
}).fail((jqXHR, textStatus, errorThrown) => {
  // Ajaxリクエストが失敗した場合の処理
  const httpCode = jqXHR.status; // HTTPステータスコード
  const errorMessage = jqXHR.responseJson.error.message.value;
  console.log(`Status Code: ${httpCode}, Message: ${errorMessage}`); // エラーレスポンス
});
```

## 実行結果
```console
Status Code: 403, Message: このページのセキュリティ検証は無効であり、破損している可能性があります。Web ブラウザーの [戻る] ボタンをクリックしてから、操作を再度行ってください。
```

# 結論に至るまでの試行錯誤
`responseJson`プロパティの存在を知るまでは[^2]、`$.parseJSON()`でパースしてからエラー情報を取得しようと下記のように実装していました。
処理結果は`responseJson`から取得するのと変わりませんが、冗長になってしまっていました。


## コード(該当処理のみ抜粋)
```javascript
const errorMessage = $.parseJSON(jqXHR.responseText).error.message.value;
```

## 実行結果
```console
Status Code: 403, Message: このページのセキュリティ検証は無効であり、破損している可能性があります。Web ブラウザーの [戻る] ボタンをクリックしてから、操作を再度行ってください。
```



[^1]: [jqXHRオブジェクトとは](https://js.studio-kingdom.com/jquery/ajax/ajax#3)
[^2]: リファレンスはちゃんと読もうと思いました。
実践Rustプログラミング入門でつまづいたところ【随時更新】

# はじめに

実践Rustプログラミング入門

https://www.amazon.co.jp/%E5%AE%9F%E8%B7%B5Rust%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E5%85%A5%E9%96%80-%E5%88%9D%E7%94%B0-%E7%9B%B4%E4%B9%9F/dp/4798061700/ref=sr_1_10?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=U3SBF9B29CLT&keywords=rust&qid=1675058031&sprefix=rus%2Caps%2C158&sr=8-10

をやっていて書籍通りに動かなかったところをまとめていきます
この記事は現在更新中です。7章、8章は飛ばしています

# Chapter4

## no method named `about` found for struct `clap::Arg`エラー

`about`でエラーがでてしまった

https://stackoverflow.com/questions/71408192/migrating-clap-rs-from-3-beta-to-3-stable-error-no-method-named-about-found

この記事によると`3系`で書き方が変わったよう

サンプルリポジトリのコードが更新されていたのでこちらを利用した

https://github.com/forcia/rustbook/blob/master/ch04/4-1/samplecli-builder/src/main.rs

## unresolved import `clap::Clap`

3系で変わった

https://github.com/forcia/rustbook/blob/master/ch04/4-1/samplecli-derivemacro/src/main.rs

また`clap`のバージョンを以下に変更した

```toml:Cargo.toml
clap = { version="3.0.0", features=["derive"] }
```

# Chapter5

## sqliteを導入した際にエラー

以下のエラーが発生してしまう

```
error: failed to select a version for `libsqlite3-sys`.
    ... required by package `rusqlite v0.28.0`
    ... which satisfies dependency `rusqlite = "^0.28"` of package `r2d2_sqlite v0.21.0`
    ... which satisfies dependency `r2d2_sqlite = "^0.21.0"` of package `rust-todo-web-app v0.1.0 (/app)`
versions that meet the requirements `^0.25.0` are: 0.25.2, 0.25.1, 0.25.0

the package `libsqlite3-sys` links to the native library `sqlite3`, but it conflicts with a previous package which links to `sqlite3` as well:
package `libsqlite3-sys v0.18.0`
    ... which satisfies dependency `libsqlite3-sys = "^0.18.0"` of package `rusqlite v0.23.0`
    ... which satisfies dependency `rusqlite = "^0.23"` of package `rust-todo-web-app v0.1.0 (/app)`
Only one package in the dependency graph may specify the same links value. This helps ensure that only one copy of a native library is linked in the final binary. Try to adjust your dependencies so that only one package uses the links ='libsqlite3-sys' value. For more information, see https://doc.rust-lang.org/cargo/reference/resolver.html#links.

failed to select a version for `libsqlite3-sys` which could resolve this conflict
```

Cargo.tomlを以下にした

```toml:Cargo.toml
rusqlite = { version = "0.25.3", features=["bundled"] }
r2d2 = "0.8.9"
r2d2_sqlite = "0.18.0"
```

# Chapter6

### npm run startでerror: error:0308010c:digital envelope routines::unsupported

以下の環境変数を設定する

```
$ export NODE_OPTIONS=--openssl-legacy-provider

# gitにpushできなくなったので以下を実行した
$ unset NODE_OPTIONS
```

Nodeが最新だったので17にもしました

```
$ n stable
$ n # node 17にする
```

# おわりに

書籍の学習が終わり次第書きます
DateオブジェクトのgetFullYear() メソッドで6桁の数字が返ってくる

vueの画面を作成していたときに、
DateオブジェクトのgetFullYear メソッドの使い方に慣れず
苦戦したことがありましたので、メモ程度に書きたいと思います！

# 目次
　[事象説明](#事象説明)
　[間違ってた原因](#間違ってた原因)
　[解決策](#解決策)
　[まとめ](#まとめ)

## 事象説明
#### getFullYear メソッドについて

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Date/getFullYear

#### 勘違い
getFullYearメソッドという名称から
Year（年）が返ってくるのだから数字４桁の戻り値であることを期待していました。
6桁でも返ってくる事象があり、処理の連携がうまくいかないバグがありました。。。

・6桁で返ってきたときに入力していたコード
```.ts:sample1.ts
const testDate = new Date('202301') //2023年1月1日の情報をもつオブジェクトを作成したつもり
console.log(testDate.getFullYear())
========
コンソール出力
202301
```


## 間違ってた原因
Dateオブジェクトのコンストラクタの引数である日時文字列の形式がよろしくなかったこと。

コンストラクタの引数が文字列の６桁の場合、６桁年としてオブジェクトが生成されてしまいます。
上記の例では202301年1月1日として生成されていました。

・参考

https://cercopes-z.com/JavaScript/Object-Date-js.html#date-format


## 解決策
単に2023年1月1日として生成したいのであれば、
以下の生成方法があります。

```.ts:sample2.ts
//2023年1月1日として生成
const testDate = new Date('2023-01') 
console.log(testDate.getFullYear())
========
コンソール出力
2023
```

## まとめ
年は常に4桁であるという勘違いから生じました。
コンストラクタ引数の仕様を正しく理解しながらプログラムを作っていきたいと思います！
Googleフォームの回答の分析にはQUERY関数を使おう

## はじめに

皆さん、Googleフォームとスプレッドシートを連携させて、
フォームからの回答をスプレッドシート上で簡単に分析できることはご存じですよね？

本記事はフォームとスプレッドシートを連携させて、回答内容を分析しようとしたときのことを記事にします。


## フォームとスプレッドシートの連携手順について
※既に連携方法がご存じの方は読み飛ばしてください

フォームとスプレッドシートの連携手順を記載します。
連携をさせるとフォームで回答した内容がスプレッドシートに1回答1レコードとして追加されるようになります。
それによってスプレッドシートで関数を用いれば簡単に回答の集計や分析を行うことが出来ます。

【連携手順】
まず、[Googleフォーム](https://docs.google.com/forms/)にアクセスします。
上のプラスマークから新規作成できます。

これで新しく作成された空っぽのフォームが表示されます。

次に、[回答]タブから [スプレッドシートにリンク] をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1739387/7ccc235d-6779-14f6-8df7-f9e4e506a685.png)

[回答の送信先を選択]というウィンドウが表示されるので
「新しいスプレッドシートを作成」にチェックが入っていることを確認し、[作成]をクリックします。

もし、ここで既にスプレッドシートを作成していて、そちらに連携させたい場合は
下の「既存のスプレッドシートを選択」にチェックを入れ、連携させたいスプレッドシートを選択します。

これで回答の連携先のスプレッドシートの準備が完了しました。
では実際に質問項目を作成し、送信してみます。

質問項目の作成方法については割愛しますが、非常に簡単にアンケートや投票、テストなどが作成可能で
感覚的に作れますので、どなたでも簡単に作成することが出来ます。

完成したフォームはこんな感じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1739387/666a860b-a745-c3e3-6edd-dcdfc3818b00.png)

早速、「豚骨」「バリカタ」で送信します。

![スクリーンショット_20230127_172128.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1739387/8e7332f4-4858-7635-87cc-94a4475d96ba.png)
スプレッドシート側には「タイムスタンプ」とGoogleフォーム側で設定した質問がカラムとして表示されます。
そして、回答した内容が連携されたことが確認できます。

## スプレッドシートでの分析

ある程度回答が集まったところでD2セルに以下の数式を入れたとします。
```
=IF(B2="豚骨",IF(C2="バリカタ","気が合うや～ん","豚骨ならバリカタやろ！"),IF(B2="","回答待ち","そっち派か…"))
```
![スクリーンショット_20230130_110109.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1739387/93c5faff-dd59-b982-f6c2-6058f66a32ec.png)

好きなラーメンが豚骨ラーメン且つ麺の固さがバリカタだった場合「気が合うや～ん」という文言を表示し、
好きなラーメンが豚骨ラーメンで麺の固さがバリカタ以外だった場合は「豚骨ならバリカタやろ！」という文言を表示し、
好きなラーメンが豚骨ラーメン以外だった場合は「そっち派か…」という文言を表示し、
また回答がない行に対して分かりやすく回答待ちと表示させる数式をD2に入れ、D列全体にコピーします。
こうすることで回答があった場合にすぐに分析が出来る！

と思いきや、新しい回答があった場合スプレッドシートは以下のようにD6に数式が入っていない状態になります。
![スクリーンショット_20230130_111328.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1739387/54f45f78-0149-20a9-67bf-05e5f8b5cd37.png)

Googleフォーム上で回答があった場合、スプレッドシートには回答された行が**追加**となるので
せっかく入力した数式も意味をなさなくなってしまいます。

結論として、フォームからの回答が入力されていくシートには数式など入れない方が良いかと思います。

## QUERY関数について

もし、フォームの回答に対して数式を追加したい場合はQUERY関数を使って別シートにデータを抽出することをオススメします。

QUERY関数はスプレッドシート独自の関数になっており、SQLのSELECT文のような形でデータを抽出することが可能です。

### 使い方

別シートを作成し、A1に以下の数式を入力します。
```
=QUERY('フォームの回答'!A:C,"SELECT * ")
```
![スクリーンショット_20230130_114541.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1739387/cc46e9fa-e6a8-8300-14c7-59c2ae00f293.png)
これで回答があったシートの情報を表示することが出来ました。

そもそも不要な列や行を表示させたくない場合はQUERY関数をクエリを変更することで抽出条件を変更できます。
```
=QUERY('フォームの回答'!A:C,"SELECT B,C WHERE B = '豚骨'")
```
![スクリーンショット_20230130_115517.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1739387/73e8b47f-4462-56ea-4155-2faafd435856.png)



これでD列に分析するための数式を追加すれば、フォームから新しい回答が来ても問題なく計算することが出来ます。
![スクリーンショット_20230130_135812.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1739387/e0f7d17a-8930-e7c0-2edd-168810ba6349.png)

## まとめ
今回はフォームとの連携においてQUERY関数を紹介させていただきましたが、
QUERY関数は非常に便利な関数なのでスプレッドシートを使うことが多い方は是非使ってみてください。
HTMLでWebサイトを公開する

# 概要
[GitHub Pages](https://docs.github.com/ja/pages/getting-started-with-github-pages/about-github-pages)という無料のサービスを利用して、HTMLでサイトを公開するための手順を説明。

# 手順

#### 1. GitHubアカウント作成

[GitHubサイト](https://github.co.jp)右上の`サインアップ`をクリック
![github1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694762/9c5c8476-e526-875c-8ba5-b4796bfa9415.png)
Username / Email address / Passwordを入力し、`Create account`をクリック
![github2.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694762/43bf8318-dadc-497a-2db3-b75295624db5.jpeg)


#### 2. リポジトリ作成

GitHubログイン後、`＋ボタン→New repository`からリポジトリを作成。
![github3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694762/71b8ecc2-475b-c869-513e-38478d33bdd6.png)
Repository nameを`アカウント名.github.io`、公開設定をPublicにして、`Create Repository`をクリック。
![github.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694762/d49d68e9-28a2-0134-931e-9a8b1d5ab487.png)

#### 3. HTMLファイルのアップロード

2で作成したリポジトリから、`Add file→Create new file`でファイル作成ページに移動。
![スクリーンショット 2023-01-30 140407.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694762/8d5d7444-8c4f-3fca-b2e5-b3b5bf87c0a6.png)
ファイル名を`index.html`、Edit new fileに中身を記述。
![スクリーンショット 2023-01-30 140650.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694762/bde34ef0-4967-7bcc-abe1-8d8886d9b09d.png)
```index.html
<html>
    <head>
        <meta charset="utf-8">
        <title>タイトル</title>
    </head>
    <body>
        本文
    </body>
</html>
```

#### 4. 公開設定
`リポジトリ→Settings→Pages`で、`Your site is live at https://[アカウント名].github.io/`と表示されているか確認。このURLが公開サイトとなっている。
![github4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694762/8000e143-ce77-fe30-d3af-37348eb92c31.png)

# エディタ
Windowsデフォルトのメモ帳アプリでも編集可能だが、[VSCode](https://azure.microsoft.com/ja-jp/products/visual-studio-code)がおすすめ。Microsoft社が提供する無償のコードエディタ。
以下のサイトからダウンロード可能。

https://azure.microsoft.com/ja-jp/products/visual-studio-code

VSCodeの特徴としては以下の通り。
* エディタ画面が見やすい
* プレビュー表示機能あり
* GUI形式のGit操作
vscode, wsl2, aws sam の設定メモ

:::note info
VSCode のインストール
:::

https://azure.microsoft.com/ja-jp/products/visual-studio-code

:::note info
VSCode の日本語化
:::

https://marketplace.visualstudio.com/items?itemName=MS-CEINTL.vscode-language-pack-ja

:::note info
VSCode で MarkdownのPreviewを表示する方法
:::

Ctl + Shift + v 

:::note info
Qiita のチートシート
:::

https://qiita.com/Qiita/items/c686397e4a0f4f11683d

:::note info
VSCode で Qiita の Markdown にする拡張機能
:::

https://marketplace.visualstudio.com/items?itemName=ryokat3.vscode-qiita-markdown-preview


:::note info
VSCode の日本語化拡張機能
:::

https://marketplace.visualstudio.com/items?itemName=MS-CEINTL.vscode-language-pack-ja


:::note info
WSL の基本的なコマンド
:::

https://learn.microsoft.com/ja-jp/windows/wsl/basic-commands


:::note info
Windows11 WSL2でDockerの環境を構築する
:::

https://zenn.dev/kkj/articles/ca83f4b5d13e68



:::note info
Linux(Ubuntu-20.04)環境にhomebrewをインストールする
:::

https://confrage.jp/linuxubuntu-20-04%e7%92%b0%e5%a2%83%e3%81%abhomebrew%e3%82%92%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab%e3%81%99%e3%82%8b/


:::note info
WSL2(Ubuntu)へのAWS SAM CLIのインストール
:::

https://confrage.jp/wsl2ubuntu%E3%81%B8%E3%81%AEaws-sam-cli%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB/
連立微分方程式の数値解析

# 制御入力のあるシステム


制御入力$u(t)$がある線形システムの挙動をシミュレーションすることを考える。
このとき、式（１）の連立微分方程式を解けばよい。
```math
\dfrac{dx}{dt} = Ax+Bu \\
```
```math
y=Cx
\tag{1}
```

# 実装

```python
import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt
import seaborn

def func(x,t,A,B,u):
    x = x.reshape(x.shape[0],1)
    u = u.reshape(u.shape[0],1)
    dxdt = np.zeros_like(x)
    dxdt = A@x+B@u
    dxdt = dxdt.reshape(-1,)
    return dxdt

def state_space_equation(x_now,t_now,t_next,u_now):
    x_init = x_now
    t = np.linspace(t_now,t_next,100)
    u = u_now

    A = np.array([[-1,0,0],[0,-1,0],[0,0,-1]])
    B = np.array([[1,0,0],[0,1,0],[0,0,1]])
    C = np.array([[1,0,0],[0,1,0],[0,0,1]])

    x = odeint(func,x_init,t,args=(A,B,u))
    y = np.array(C)@x.T
    y = y.T
    t = t.reshape(t.shape[0],1)
    return x,y,t

def system():
    t_s,t_f,dt = 0,10,1e-1
    time = np.arange(t_s, t_f, dt)

    x_now = np.array([10,5,2])
    u_now = np.array([0,0,0])

    for i,t_now in enumerate(time):
        t_next = t_now + dt
        x,y,t = state_space_equation(x_now,t_now,t_next,u_now)
        
        u_now = np.array([0,0,0])-y[-1,:]
        x_now = x[-1,:]
        
        if i == 0:
            obs_x = x
            obs_y = y
            obs_t = t
        else:
            obs_x = np.concatenate([obs_x,x],axis=0)
            obs_y = np.concatenate([obs_y,y],axis=0)
            obs_t = np.concatenate([obs_t,t],axis=0)
    return obs_x,obs_y,obs_t

def savefig(t,sol,pngfn):
    plt.figure()
    for i in range(sol.shape[1]):
        plt.plot(t,sol[:,i])
    plt.savefig(pngfn)
    plt.close()

def savecsv(t,x,y,csvfn):
    sol = np.concatenate([t,x,y],axis=1)
    np.savetxt(csvfn, sol, delimiter=',')

x,y,t = system()
pngfn = "scenario_1.png"
savefig(t,y,pngfn)
csvfn = "scenario_1.csv"
savecsv(t,x,y,csvfn)

```
github actionsでmainブランチにマージされたタイミングでリリースノート作成・タグ付けを自動化

# 背景
週に一回リリース作業があり、その際のリリースノート作成とタグ付けを手動でやっていた。
この作業を自動化すべくワークフローを作った。

# 作ったワークフロー
``` yaml
name: Release

on:
  pull_request:
    types: [closed]
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest
    if: github.event.pull_request.merged == true
    steps:
      - name: Checkout code
        uses: actions/checkout@v3
      - name: Release
        id: release
        uses: actions/create-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          tag_name: ${{ github.event.pull_request.title }}
          release_name: ${{ github.event.pull_request.title }}
          body: ${{ github.event.pull_request.body }}
          draft: false
          prerelease: false
```

## 実行タイミング
``` yaml
on:
  pull_request:
    types: [closed]
    branches:
      - main
```
こう書くことでmainブランチに対するプルリクがクローズされたタイミングで実行される。
今回はmainブランチにマージされたタイミングで実行させたいので合わせて下記のように条件を記載。

``` yaml
jobs:
  build:
    runs-on: ubuntu-latest
    if: github.event.pull_request.merged == true
```
他に同じようなことしてる類似記事だとこの条件書いてないことが多かったので気をつけるべし。
mainブランチにマージされたタイミングで実行したい場合は、
PRがクローズされた時、かつPRがマージされた場合というように条件を組み合わせて表現しないと実現できない。

## リリースノート作成、タグ付け
``` yaml
steps:
      - name: Checkout code
        uses: actions/checkout@v3
      - name: Release
        id: release
        uses: actions/create-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          tag_name: ${{ github.event.pull_request.title }}
          release_name: ${{ github.event.pull_request.title }}
          body: ${{ github.event.pull_request.body }}
          draft: false
          prerelease: false
```
タグ名とリリースノートのタイトルはPRタイトルから、
リリースノートのボディ部分はPRのボディから取得させる。

create-releaseの詳細は↓

https://github.com/actions/create-release


## 実際動かすとこんな感じ

PR作ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2893271/338e8107-caa1-1e82-f043-021d3337ac85.png)

タイトルにつけたいtag名、ボディにリリースノートに載せたい内容書く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2893271/384df71f-8ca5-4660-c44e-ad1d1b0988b4.png)

PRマージしたらワークフローが走り出し
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2893271/cb6f7948-657a-1532-5314-ea27bd1a6f64.png)

リリースノートとタグが自動で作られるぞ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2893271/13c1be8a-96d8-d490-b166-4e77db09eb79.png)
20230130


misFortune.html
```
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

</body>
</html>
```

greatFortune.html
```
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>占い</title>
</head>
<body>
<h1>ラッキー</h1>
</body>
</html>
```


```
package com.example.demo;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class Fortune {
	@RequestMapping("/fortune")
	public String start() {
		double fn = Math.random();
		if (fn >= 0.7) {
			return "greatFortune.html";
		} else {
			return "misFortune.html";

		}
	}
}
```
Oracle Cloud Infrastructure AI サービス Vision を使ってカスタム・イメージ分類モデルを作成する

# OCI AIサービス & OCI Vision とは ?

オラクル・クラウドが提供する [**OCI AIサービス**](https://www.oracle.com/jp/artificial-intelligence/ai-services/) のひとつに Vision という画像ベースのコンテンツ分析サービスがあります。開発者は、APIコールを実行して、事前学習済みのモデルをアプリケーションに簡単に統合したり、特定のユースケースに合わせてカスタム・トレーニング・モデルを作成したりすることができます。こうした画像認識技術は色々なユースケースに応用が利くことは既に皆さんご承知の通りだと思います。
Vision サービスは API はもちろんこと、ユーザー・インタフェースも提供していますので、機械学習やプログラミングに不慣れな方でも簡単にサービスを利用していただけるものになっています。


Vision サービスでは二つの機械学習モデルを利用することができます。
1. 事前トレーニング済みモデル  
    + 「オブジェクト検出」人、車、木、犬など、画像内のオブジェクトの位置を検出します。出力には、見つかった各オブジェクトの境界ボックスの座標が含まれます。
    + 「画像分類」画像内のシーンベースの特徴とオブジェクトを分類します。
1. カスタムモデル
データセットに基づいてモデルをトレーニングするようにVisionに指示することで、機器・製品の欠陥品の検出、自社商品のSKUによる分類、ロゴの不正使用など不適切なコンテンツの検出等々、シナリオに適したカスタム・モデルを作成できます。

    + 「カスタム・オブジェクト検出」イメージ内のオブジェクトとその場所を検出するモデルを作成します。出力には、信頼度スコアと、見つかった各オブジェクトの境界ボックスの座標が含まれます。
    + 「カスタム・イメージ分類」イメージ内のシーンベースのフィーチャとオブジェクトを分類するためのモデルを作成します。出力は、各分類の信頼度スコアを返します。

# OCI Vision を使ったカスタム・イメージ分類

そして、ここからが本題ですが、上記「カスタム・イメージ分類」のモデル作成を、APIベースでやってみました。

https://github.com/oracle-japan/oci-ai-vision-lemon-quality

[https://github.com/robotduinom/lemon_dataset](https://github.com/robotduinom/lemon_dataset) で提供されているレモンの品質管理画像を使って、レモンを "good", "bad", "empty (カメラに写り込んでない)" に分類します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/544382/0d2239de-94ea-cabf-0c31-f397bc61ca4c.png)
今回のお題で扱った画像ファイルは 2000 枚を超えていて、ユーザー・インタフェースから全部ラベリング（分類のタグ付け）するのはちょっとしんどいので、この部分を API で実施して自動化するのと、どうせなのでデータのオブジェクト・ストレージへのアップロードから分析（モデルを使った画像分類作業）までを Jupyter Notebook ベースで作成しました。

ちなみにこのラベル付けの作業自体は、OCI Vision ではなくて、[**OCI Data Labeling**](https://www.oracle.com/jp/artificial-intelligence/data-labeling/) という別のサービスとなっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/544382/1fa2a7aa-9fdc-b5d4-4515-203f5e32cb4a.png)
上図のような UIでコンソールからもラベル付けの作業が行えます。今回は Jupyter Notebook から OCI SDK for Python を使って Data Labeling による画像へのラベル付け作業と、このラベル付けされたデータセットを使った Vision によるカスタムモデルの作成までの一連の処理を行っています。

最終的に Jupyter Notebook では、こんな感じでランダムに選んだ画像データを信頼度とともに分類して表示します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/544382/1b4d1b7c-4fb5-853c-b24b-042bc9636ccc.png)
トレーニング結果については、下の画像のようにコンソールから確認できますし、APIを使ってモデルの詳細情報を取得することもできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/544382/0f81053e-6a8b-e7f6-7d63-70bdff474432.png)

# まとめ

ということで、OCI Vision の「事前トレーニング済みモデル 」と「カスタムモデル」を使いこなせば、かなり広範囲のユースケースに対して Time to Value なソリューションを提供できるのではないでしょうか。カスタムモデルの作成も**ラベル付けしたデータを渡しさえすれば、あとは OCI Vision 側でモデルの作成作業を全部やってくれる**ので、機械学習のハードルをぐっと低くしてくれるものだと思います。是非お試し下さい！
React、async、awaitを使用してapiを叩き初期表示を取得する

reactで一覧ページのapiを呼び出しasync、await初期値をを使用し初期値を呼び出し保存するまでをまとめました。

処理の流れ
①useEffectを使用してページ遷移した最初に一覧データ取得のAPIを呼び出す。
②呼び出したデータをuseState(一覧データを保管する)に格納する。
③エラーの場合エラーコード毎に処理を記述する。

```
useEffect(() => {
        //ローディング開始
        setIsLoading(true);
        async function fetchData() {
            try {
                //正常にデータ取得された時の処理
                const response = await axios.get('apiのurlを記述');
                let posts_arr;
                //stringをjsonに変更
                posts_arr = JSON.parse(response.data);
                //一覧データに格納
                setPosts(posts_arr.data);
            } catch (e) {
　　　　　　　　//エラーの場合エラーコード毎に処理を記述する。
　　　　　　　　　今回はコンソールにエラー内容とエラー番号を出力しているが
　　　　　　　　　実務では実際の処理を記述する
                if (e.response.status === 400) {
                    console.log(e)
                    console.log("400")
                } else if (e.response.status === 401) {
                    console.log(e)
                    console.log("401")
                } else if (e.response.status === 422) {
                    console.log(e)
                    console.log("400")
                } else if (e.response.status === 403) {
                    console.log(e)
                    console.log("403")
                } else if (e.response.status === 404) {
                    console.log(e)
                    console.log("404")
                } else if (e.response.status === 500) {
                    console.log(e)
                    console.log("500")
                } else {
                    console.log(e)
                    console.log("例外")
                }
            }
        }
        fetchData();
    }, []);
boost replace

## 概要
全て置き換える

## include
`boost/algorithm/string/replace.hpp`

## Exmaple
```c++
    // 破壊的な変更を行うバージョン
    {
        std::string s = "Hello Jane, Hello World!";

        // 全ての"Hello"を"Goodbye"に置き換える
        boost::algorithm::replace_all(s, "Hello", "Goodbye");
        boost::algorithm::replace_all(s, "Goodbye", "Goodbye1");
        std::cout << s << std::endl;
    }

    // コピーを返すバージョン
    {
        const std::string s = "Hello Jane, Hello World!";

        const std::string result = boost::algorithm::replace_all_copy(s, "Hello", "Goodbye");
        std::cout << result << std::endl;
    }

    // 先頭、最後
    {
        string str1 = "Hello  Dolly, Hello World! Hello World!";
        boost::algorithm::replace_all(str1, "Hello", "Bye");
        std::cout << str1 << std::endl;
        boost::algorithm::replace_first(str1, "Bye", "Bye1");
        std::cout << str1 << std::endl;
        boost::algorithm::replace_last(str1, "Bye", "Bye1");
        std::cout << str1 << std::endl;
    }
```
直感 Deep Learningのソースコード置き換え

# はじめに
2018年に出版された直感Deep　Leaningを2023年現在写経しているとエラーになる箇所があったため記録として残しておく。

# 環境
Python: 3.10.9
gensim: 4.3.0
h5py: 3.8.0
keras: 2.11.0
matplotlib: 3.6.3
nltk: 3.8.1
numpy: 1.24.1
Pillow: 9.4.0
scikit-learn: 1.2.1
tensorboard: 2.11.2
tensorflow: 2.11.0

# 置き換え
pad_sequencesをimport、または使おうとした時にエラーになる。
旧
```python
from keras.preprocessing import sequence
.
.
hoge = sequence.pad_sequences(...)
```
新
```python
from tensorflow.keras.utils import pad_sequences
.
.
hoge = pad_sequences(...)
```
または
旧
```python
from keras.preprocessing.sequence import pad_sequences
```
新
```python
from tensorflow.keras.utils import pad_sequences
```

旧
```python
from keras.preprocessing.image import load_img
```
新
```python
from tensorflow.keras.utils import load_img
```
旧
```python
from keras.preprocessing.image import img_to_array
```
新
```python
from tensorflow.keras.utils import img_to_array
```

モジュールのimportでエラーになる。
(別の章では新のほうのimportをしているので一貫性がないように感じる)
旧
```python
from keras.layers.embeddings import Embedding
```
新
```python
from keras.layers import Embedding
```
旧
```python
from keras.layers.recurrent import LSTM
```
新
```python
from keras.layers import LSTM
```
旧
```python
from keras.engine.topology import Layer
```
新
```python
from keras.layers import Layer
```

Kerasのgradientsが非推奨になってエラーを出すようになっている。
TensorflowのGradientTapeを使えという内容も出力されるがとりあえず通して動きを見たいということであれば以下を入れることで動かすことは可能。
```python
import tensorflow as tf
tf.compat.v1.disable_eager_execution()
```

TensorflowのVariableが`+=`をサポートしていないというエラーが出てきたのでその際は正攻法で修正した。
旧
```python
loss += hoge
```
新
```python
loss = loss + hoge
```

# 終わりに
本書で一部写経していない章もあるので実際には他にもエラーになる箇所があるかもしれない。
JestとVue.jsでsetIntervalやsetTimeoutのテストを書く

# はじめに
```setInterval```を使ったポーリングのテストを書こうとした時に、なかなか動くテストを書けずに詰まりました。

# テストしたいコード
今回テストしたかったのは、下のようなコードです。
5分ごとに```testFunction()```が呼ばれるようになっています。
```javascript:component.js
const Comp = {
    // ...
    created() {
        setInterval(this.testFunction, 300000);
    },
    // ...
    methods: {
        testFunction() {
            console.log("foo");
        }
    }
}
```
# 動いたテストコード
最終的に動いたのは、```jest.spyOn()```でモック関数を作成する方法でした。
```javascript:component.test.js
import { expect, describe, test } from "@jest/globals";
import { shallowMount } from "@vue/test-utils";
import Comp from "/.../...";

describe("ポーリング", () => {
    test("ポーリングのメソッドが５分ごとに呼ばれている", () => {
        // testFunction()をspyOnでモックする
        const spyTestFunction = jest.spyOn(Comp.methods, "testFunction");
        // タイマーモックを有効にする
        jest.useFakeTimers();
        // マウント
        shallowMount(Comp);
        // 10分時間を進める
        jest.advanceTimersByTime(600000);
        // 2回呼ばれているか
        expect(spyTestFunction).toHaveBeenCalledTimes(2);
    });
});
```
### 各コードのはたらき
まず、```jest.spyOn()```でモック関数を書いています。
spyOnは、メソッド自体を上書きしているのではなく、テストでもメソッドを呼ぶために名前付けするような働きをしているようです。
```javascript
const spyTestFunction = jest.spyOn(Comp.methods, "testFunction");
```
テスト内で時間を自由に操作できるように、フェイクタイマーを有効化します。
```javascript
jest.useFakeTimers();
```
ms単位で時間を好きに進めることができます。
```javascript
jest.advanceTimersByTime(600000);
```
# 動かなかったテストコード
動かなかった方もついでに載せておきます。
こちらは、```jest.fn　()```を使ってモック関数を作り、マウンティングオプションを使ってメソッドを乗っ取ろうとしましたが、うまくいきませんでした。
```javascript:component.test.js
import { expect, describe, test } from "@jest/globals";
import { shallowMount } from "@vue/test-utils";
import Comp from "/.../...";

describe("ポーリング", () => {
    test("ポーリングのメソッドが５分ごとに呼ばれている", () => {
        jest.useFakeTimers();

        // モック関数を作成してモックしようとしたけど
        const mockTestFunction = jest.fn(() => {});
        
        shallowMount(Comp, {
            // どうやらこれではモックが効かないらしい
            global: {
                mocks: { testFunction: mockTestFunction } 
            }
        }

        jest.advanceTimersByTime(600000);
        expect(spyAjaxFetchNotification).toHaveBeenCalledTimes(2);
    }
}
```
メソッドはインスタンスではないから、mockとしてかましても動かないのかなと思っています。

# 終わりに
なんで前者は動いて後者は動いていないのか分かっていません。
jest、奥が深いです。
# 参考記事
https://deltice.github.io/jest/docs/ja/timer-mocks.html

https://stackoverflow.com/questions/63876092/mocking-setinterval-in-created-hook-vue-js
クラスのフィールドをコンストラクト時に配列として初期化する

自分メモ。
クラスのフィールドをコンストラクト時に配列化したい場合の書き方。
C#はフィールドの初期化時にフィールドを参照できないが、メソッドとして参照してあげる。
```
class Hoge {
  ...
  private int value1;
  private int value2;
  private int value3;
  private int value4;
  private int value5;

  private IEnumerator<int> Values()
  {
      yield return this.value1;
      yield return this.value2;
      yield return this.value3;
      yield return this.value4;
      yield return this.value5;
  }
}

```
【若手向け】1on1ミーティングで大事な5つのポイント

# はじめに
社会人歴が3,4年超えたあたりになると後輩が増えてきて「育成される側」から「育成する側」へとなってきている方も多いのではないでしょうか？僕は最近、新卒の後輩と1on1をする立場になったことで、「**そういえば、1on1ってどうやってやるんだ**？」と1on1実施側としての知識がないことに気づきました。
そこで今回は組織運営、後輩育成には欠かせなくなってきている「**1on1ミーティング**」について以下の書籍で学んだことを記事にします。

https://www.diamond.co.jp/book/9784478069783.html

この記事を読む方は**これからリーダーとして活躍していく**！という方が多いと思うので、以前投稿した以下の記事もあわせて読んでみてください！

https://qiita.com/m_saito_ari/items/366f6850d5c1cf39c3ec

# 1on1ミーティングって？
最近はどこの企業も導入しているので、説明不要かもしれませんが、
1on1ミーティング(以降は1on1と記載)は定期的に時間を作り、部下と上司の間で行う1対1の対話のことです。
報告や目標設定を行う**面談**とは異なり、**部下の成長や気づきの支援**を行うのが目的のため、業務の会話に限らず、時にはプライベートな会話をすることも多いです。

# 1on1で大事なポイント5つ
## 1.部下に話してもらおう
>**面談を部下のための時間にするために、まず大事なことは「部下に十分に話をしてもらうこと」です。
なぜなら、1on1は部下の行動や経験学習を深めることを目的としていて、そのためには、部下は自分の経験を詳細に思い出して、言葉にして、深く内省することが必要だからです。**

1on1の目的は**部下の行動や経験学習を深めること**であって、上司の確認したいことを聞く時間ではないということが重要なポイントですね。上司が状況把握をするための場ではなく、部下が話している内容をうまく深堀して**内省に導く**ことが1on1において重要です。

## 2.部下の言葉の先取りや話の遮りはやめよう
>**部下「鈴木さんは、今回の案件を任せるに十分な経験と能力があります。ただ・・・、一緒に働く周囲のメンバーとぶつかりがちで・・・」
上司「誰とぶつかっているんです？」**

このような会話って結構ありがちですよね、一見問題なさそうに見えますが、部下の「ぶつかりがち」という**言葉だけに過剰反応**し、上司が**事実確認したい**がゆえに「誰とぶつかっているんです？」と聞いてしまっています。
確かに話の文脈的には部下は対人関係が課題と思っていそうですが、部下はまだ本質的な問題点については言及していません。
そんな中で上司が言葉を先取りしてしまうことは危険です。
なぜなら、上司と異なる見立てを部下が持っていたとしたら、部下はそれを言いづらくなってしまうからです。

もう一度1on1の目的を思い出してください。「**部下の成長と気づきの支援**」が目的ですよね。上司が現場の把握をすることではありません。

上司が**言葉を先取り**して誘導してしまうのは、部下の成長には繋がらず、1on1の意義を果たせていないと言えます。
こういった際には**ニュートラルな返答**が大事です。
言葉の**オウム返し**(「ぶつかりがち…ですか？」)をしたり、**相槌を打つだけ**などです。
ニュートラルな返答をすることで部下の経験を詳細に思い出させ、言葉にさせることが大事です。


## 3.1on1の目的は部下の成長
部下の抱えている問題に対して、**経験豊富な上司であれば難なく解決できる方法を持ち合わせている**かもしれません。
でも、助言したい気持ちはグッとこらえましょう。
助言をすれば、解決はするかもしれません。
しかし、それでは部下の学びが浅いままで終わるだけでなく、上司からの指示に沿って行動する「**考えない部下**」を育成することになりかねません。

何度も言いますが、1on1の目的は「**部下の成長と気づきの支援**」です。
安易な助言は部下の成長機会を奪うことになりかねません。

## 4.部下の意見は極力否定しない
>**注意していただきたいのは、否定が常にNGではないということです。ただ、上手に否定しないと、いつの間にか部下は上司かの指示を待つようになりかねません。上司依存になると、部下は考えなくなり、学びが深まりません。**

1on1は基本的に上司と部下で行いますが、一般的に上司は部下に対して評価権限を持っています。
加えて、異動や業務アサインの影響力もあるわけです。

そうすると、部下は上司に嫌われるような発言は避けます。
具体的には**上司の発言に対して否定したり、意見する**ことは避けるわけですね。
つまり、上司が自分の意見を言いすぎると本音を話しづらくなってしまうということです。
1on1において、上司は傾聴が求められるってことですね。

部下の意見に対しては否定ではなく、**ニュートラルな返答**を上手く使って、部下の考えを引き出すことが重要です。

## 5.問題の対処法は上司が示さない
>**対話を進めることで問題の本質が見えてきました。しかし、次の行動＝問題への対処法について、部下より先に上司が示してしまってはいけません。部下が自ら思いついて行動に移すことが大切です。このように対話によって考えを深め、主体的に問題解決の方法にたどりつくことが部下の成長につながるからです。**

部下が考えた方法は上手くいかないかもしれませんが、それはまた次の1on1で振り返り、上手くいかなかった理由を考えればよいのです。
上司はそれに寄り添い、支援することで徐々に部下の学びが深くなり、考え、行動し、主体的に活動する部下へと成長させることができます。


# おわりに
いかがだったでしょうか？
1on1を「してもらっていた側」から「する側」に変わるにあたって大事なポイントを書かせていただきました。
内容を理解ができても、実際に1on1時に行うのは難しいものかもしれません…
ぜひ5つのポイントを覚えて頂き、徐々に身に着けて組織運営や後輩育成に役立ててください！

また、今回紹介したのは書籍のほんの一部ですので、ぜひご自身でも読んでみてください！！
pythonでoracle-dbにつなぐ

### インストール

    pip install cx_Oracle


### エラーが出たとき

    error: Microsoft Visual C++ 14.0 or greater is required. Get it with "Microsoft C++ Build Tools": https://visualstudio.microsoft.com/visual-cpp-build-tools/

下記記事で解決

https://tech.nkhn37.net/python-pip-install-error-microsoft-visual-c-14/

★★「MSVC v140」にチェックを入れるのがポイントかな


### selectの例

    import cx_Oracle
    tns = "(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.1.1)(PORT=1521)))(CONNECT_DATA=(SID=orcl)(SERVER=DEDICATED)))"
    conn = cx_Oracle.connect('id', 'pass', tns)
    cur = conn.cursor()
    cur.execute("select * from table1 where id like 'hoge%'")
    res = cur.fetchall()
    print(res)
    cur.close()
    conn.close()


### updateの例

    import cx_Oracle
    tns = "(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.1.1)(PORT=1521)))(CONNECT_DATA=(SID=orcl)(SERVER=DEDICATED)))"
    conn = cx_Oracle.connect('id', 'pass', tns)
    cur = conn.cursor()
    cur.execute("update table1 set field2=0 where id like 'hoge%'")
    conn.commit()
    cur.close()
    conn.close()
Ruby if文, unless文についてまとめました2

こちらの続きとして書きます。

https://qiita.com/ta--i/items/a16aa2780e3849b21338


# 条件分岐処理
ifからunlessに書き換える例を3つ挙げてみました。


## ifからunlessに書き換える例1

```ruby
if 100 == 10
  puts "同じ数字です"
else
  puts "違う数字です"
end
```

上記if文をunless文で書き換えると次のようになります。

```ruby
unless 100 == 10
  puts "違う数字です"
else
  puts "同じ数字です"
end
```

## ifからunlessに書き換える例2

```ruby
if 100 + 10 > 0
  puts "0より大きい数字です"
else
  puts "0より小さい数字です"
end
```

上記if文をunless文で書き換えると次のようになります。

```ruby
unless 100 + 10 <= 0
  puts "0より大きい数字です"
else
  puts "0より小さい数字です"
end
```

## ifからunlessに書き換える例3

```ruby
if a + b > 0
  puts "計算結果は0より大きいです"
end
```
上記if文をunless文で書き換えると次のようになります。

```ruby
unless a + b <= 0
  puts "計算結果は0より大きいです"
end
```

「a + b が0より大きい」という条件がfalseだった場合、「計算結果は0より大きいです」と文字列が表示されます。
つまり、「a + b が0より大きくないとき」に文字列が表示されるということです。
では、下記のように書くと、a + bの計算結果が0だった場合どうなるでしょう？
```ruby
unless a + b < 0
  puts "計算結果は0より大きいです"
end
```
これは、「a + b が0より小さい」という条件式がfalseのとき、文字列が表示されます。
つまり「a + b が0より小さくないとき」に文字列が表示されます。
a + bが0だった場合でも、「a + b が0より小さい」という条件式がfalseとなってしまい、文字列が表示されます。
a + bが0以上のときにfalseになる条件式に変更しないといけません。
そのため、　<=　を使用します。
Ruby if文, unless文についてまとめました1

# 条件分岐処理

## if文
「もし〇〇だったら□□をする」という処理をします。

```ruby
if 条件式
  処理1（条件式がtrueのときに実行）
else
  処理2（条件式がfalseのときに実行）
end
```
if文は、条件式が「正しい」か「正しくないか」で実行する処理を分岐させています。<br>
***「正しい」 = true***<br>
***「正しくないか」 = false***<br>
条件式が正しい（true）なら、処理1を実行。
条件式が正しくない（false）なら、処理2を実行。<br>


## unless文
「もし〇〇だったら□□をする」という処理をします。
unless文はif文と反対で、条件式が「偽(false)」の時に処理が実行されます。
unless文にelsif を指定することはできないです。

公式リファレンスを参考にしました。
https://docs.ruby-lang.org/ja/latest/doc/spec=2fcontrol.html#unless

```ruby
unless 条件式
  処理1（条件式がfalseのときに実行）
else
  処理2（条件式がtrueのときに実行）
end
```
unless文は、if文と同様に条件式が「正しい」か「正しくないか」で実行する処理を分岐させています。<br>
***「正しい」 = true***<br>
***「正しくないか」 = false***<br>
条件式が正しくない（false）なら、処理1を実行。
条件式が正しい（true）なら、処理2を実行。

続きです。

https://qiita.com/ta--i/items/a3182f5dc80237ad4d29
SVG周りの座標変換まとめ

座標変換を理解するために、次のようなDOM構造を考えます。
（複雑さを排除するため、x と y（または width と height）は同じ値にしています）

```tsx
export function Component() {
  return (
    <div style={{ margin: 100 }}>
      <svg width={200} height={200} viewBox="0 0 400 400">
        <g transform="translate(100, 100)"></g>
      </svg>
    </div>
  );
}
```

このDOM構造には、いくつかの座標系が存在します。
これら座標系間の変換にはどの行列を使えば良いかについては、次の図を見ることでわかります。
（図の数値は x 座標を表します）

![ctm.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59884/7dafa224-0faa-63cc-34dc-ad916210f184.png)

## 例

たとえば、座標系 D の点 (150, 150) を座標系 B の点に変換するときは、次のように実装します。

```tsx
const p = new DOMPoint(150, 150);
const m = g.getCTM()!;
const q = p.matrixTransform(m);
console.log(q.x); //=> 125
```

`g.getCTM()` や `svg.getScreenCTM()` の評価値は `DOMMatrix` オブジェクト（または `null`）です。
`DOMMatrix` オブジェクトは `.inverse()` メソッドを持ちます。
これは逆行列を返すメソッドです。これを利用することで、座標系 B から座標系 D への変換などが可能になります。
次のように実装します。

```tsx
const p = new DOMPoint(125, 125);
const m = g.getCTM()!.inverse();
const q = p.matrixTransform(m);
console.log(q.x); //=> 150
```

座標系 D から座標系 C に変換するときは次のように実装します。

```tsx
const p = new DOMPoint(300, 300);
const m1 = g.getCTM()!;
const q = p.matrixTransform(m1);
const m2 = svg.getCTM()!.inverse();
const r = q.matrixTransform(m2);
console.log(r.x); //=> 400
```

次のように、変換行列同士の積を取り、その行列を適用することもできます。

```tsx
const p = new DOMPoint(300, 300);
const m = (() => {
  const m1 = g.getCTM()!;
  const m2 = svg.getCTM()!.inverse();
  return m2.multiply(m1);
})();
const q = p.matrixTransform(m);
console.log(q.x); //=> 400
```