OmniAICreator/Qiita-1.07M huggingface dataset:
JSONPの404は捕捉できない

クロスオリジンでAjax通信をする場合に使うJSONP。
アクセス先のステータスコードが400系や500系などの場合、エラーとして捕捉できず無限に待ち続ける状態になる。

```javascript
// jQuery使用
$.ajax({
  url: '//example.com/api/',
  type: 'GET',
  dataType: 'jsonp',
})
.done(function(){
  // 当然ここは実行されない
})
.fail(function(){
  // ここも実行されない！
});
```
## なぜか
JSONPの原理を考えてみれば、当然といえば当然である。
- コールバック関数を定義
- scriptタグにアクセスポイントのURLを埋め込む
- アクセスポイントのリソースは、JavaScriptファイルとして読込・実行され、用意しておいたコールバック関数が実行される

ここで、scriptタグで読み込む先が404とか500であった場合、読み込むべきリソースが無いのであるから、
当然ながら用意されたコールバック関数は実行されない。
response bodyに中身が入っていても、クライアント（ブラウザ）によってそれは無視される。

XHRと違って、JavaScriptはアクセスポイントへのリクエストを取り扱っているわけではない。
JSONPのアクセスでは、JavaScriptは、scriptタグを生成してコールバック関数の実行を指を咥えて待っているだけなのだ。後のリクエストはブラウザが勝手にやっているに過ぎない。

jQueryのドキュメントにも、エラーハンドリングできない旨は書いてある。
https://api.jquery.com/jquery.ajax/
settingsのerrorプロパティ
> Note: This handler is not called for cross-domain script and cross-domain JSONP requests.


## どうするのか
iframeを使ってアクセスポイントの中身を探る方法もあるようだが、
サーバがそれなりに素早く正常値を返してくれるのが期待できるのであれば、
timeoutを設定することで良いのではないか。
```javascript
// jQuery使用
$.ajax({
  url: '//example.com/api/',
  type: 'GET',
  dataType: 'jsonp',
  timeout: 2000,
})
.done(function(){
  // 当然ここは実行されない
})
.fail(function(){
  // アクセスできない場合は、2秒後にこれが実行される
  // 正常にレスポンスが返ってきても場合でも、2秒以上かかってしまうと実行されてしまうのだが
});
```
JSONP自体は、本質的にJavaScriptに備わっているわけではない裏技的仕組みなので、エラー時にどうするかの真っ当な仕組みは用意されていないということだ。

timeoutでお茶を濁すような方法を紹介したが、
この辺の処理を厳密にやるべき案件なのであれば、JSONPなど使用せず、
同一オリジンでAPI提供するようにするか、`Access-Control-Allow-Origin`ヘッダーを付けるなど、インフラ側・サーバ側にちゃんと対応してもらおう。
何でもかんでもフロントエンドに吸収させようとしないでくれ。
簡単にWeb APIを使ってラーメン屋の情報を出そう!!

# WebAPIを使って街中のラーメン屋の情報を取得してみる。

## 環境
OS:Windows 10
言語:Python 3.10
対象WebAPl:ホットペッパーグルメリサーチAPI
<a href="http://webservice.recruit.co.jp/"><img src="http://webservice.recruit.co.jp/banner/hotpepper-s.gif" alt="ホットペッパー Webサービス" width="135" height="17" border="0" title="ホットペッパー Webサービス"></a>


### 今回使うモジュールは、
・Json,requests,random

### 流れとして
 1．requestsでラーメン屋の情報を取得する。
 2．Jsonファイルを辞書として読み込ませる。
 3．ランダムで一軒表示させる。

# まず1，2をやってみる。
```
import json
import requests

gourmet='http://webservice.recruit.co.jp/hotpepper/gourmet/v1/'
APIKEY = apikey   #自分で取得してね。
genre = 'G013'    #ラーメン
middleid = 'Y505' #札幌、大通
url = gourmet + "?key=" + APIKEY + '&middle_area='+ middleid +'&genre=' + genre +'&format=json'
#jsonを用いて書くためフォーマットをjsonにしておく。

l = requests.get(url)       #getで情報を取得
lunch = json.loads(l.text)  #jsonファイルを辞書として読み込む
print(lunch)                #出力する。
```

###  実行結果
```
{'results': {'api_version': '1.26', 'results_available': 14, 'results_returned': '10', 'results_start': 1, 'shop':
 [{'access': 'JR札幌駅/地下鉄南北線・東豊線 さっぽろ駅 徒歩2分', 'address': '北海道札幌市北区北７条西２丁目20\u3000東京建物札幌ビルB1F',
 'band': '不可', 'barrier_free': 'なし', 'budget': {'average': '1000円', 'code': 'B011', 'name': '1001～1500円'}, 
'budget_memo': '油そば・台湾まぜそば・坦々麺\u3000680円～', 'capacity': 20, 'card': '利用不可', 'catch': '札幌駅北口にオープン！', 
'charter': '貸切不可', 'child': 'お子様連れOK', 'close': '土、日、祝 日',
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~　割愛　~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```
凄い情報が出てきた!!
### レスポンスフィールドを参考にして必要な情報を絞ってみる

###### ramen.py(一部)
```
l = requests.get(url)       
lunch = json.loads(l.text)　
print(lunch['results']['shop'][0]['name'])      #shopフィールドの 0 番に入っているお店の名前
print(lunch['results']['shop'][0]['open'])      #shopフィールドの 0 番に入っているお店の営業日時
print(lunch['results']['shop'][0]['address'])   #shopフィールドの 0 番に入っているお店の場所
```

### 実行結果
```
まぜそば専門店 麺や太郎
月～金、祝前日: 11:30～16:0017:00～21:30
北海道札幌市北区北７条西２丁目20　東京建物札幌ビルB1F
```
やった上手くいった!!

# 最後はランダムに一軒だけ表示させる。
#### ramen.py(一部)
```
import json
import requests
import random

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~　省略　~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

cou=len(lunch['results']['shop'])                  #軒数をlenで割り出す。
num=random.randrange(0,cou-1)                      #random関数で0から軒数-1の値をnumにいれる。

print(lunch['results']['shop'][num]['name'])      #shopフィールドの num 番に入っているお店の名前
print(lunch['results']['shop'][num]['open'])      #shopフィールドの num 番に入っているお店の営業日時
print(lunch['results']['shop'][num]['address'])   #shopフィールドの num 番に入っているお店の場所
```
### 実行結果

```
ラーメン ねるら
月、水、土: 11:30～22:00 （料理L.O. 21:30）火、木、金: 11:30～16:30 （料理L.O. 16:00）祝日、祝前日: 11:30～18:00 （料理L.O. 17:30）
北海道札幌市中央区南１条西９－１－３
市電中央区役所前駅から徒歩3分。駅を降りて、南1条通を東に進む。2つ目の信号の先の曲がり角を左に曲がった右手です。
```

よし、さっきの実行結果と今回の実行結果に出てきたお店が違うぞ～!!
これでラーメン屋スクリプト完成だ～～!!
EFIパーティションを吹き飛ばしたときにやること(Windows w/ Arch Linux)

最近Arch Linuxのインストール中に`# rm -r /boot/*`をよくやらかすので対処方法を記録しておきます。

## 環境
- EFIブート
- /boot にEFIパーティションがマウントされている
- /boot/grub/ にGRUBがインストールされている
- Arch Linux
- Windows 10

## 手順

#### Windows REを用意する
- 別のWindows PCで「回復ドライブ」を実行してUSBメモリにイメージを書き込む
- [Windowsのインストールディスク](https://www.microsoft.com/ja-jp/software-download/windows10ISO)で代用する(重い・遅い)
- なんとかして回復パーティションを起動する(望み薄)

#### Windows REのコマンドプロンプトでコマンドを実行する
```
> dir C: # ターゲットとなるWindows環境がC:にマウントされていることを確認する(されていなかったらdiskpartでassign)
> diskpart

--- DiskPart ここから ---

> list disk       # ディスクのリストを確認する
> sel disk 0      # EFIパーティションがあるディスクを選択
> list part       # パーティションのリストを確認する
> sel part 1      # EFIパーティションを選択
> assign letter=a # ドライブレターを割り当て(いまどきFDドライブがついたPCを使っている場合はH:あたりに割り当てる)
> exit

--- DiskPart ここまで ---

> mkdir A:\EFI\Microsoft\Boot                            # ブートローダーを格納するディレクトリを作る
> xcopy /s C:\Windows\Boot\EFI\*.* G:\EFI\Microsoft\Boot # ブートローダーの基本データをコピー
> cd G:\EFI\Microsoft\Boot                               # ブートローダーのディレクトリに移動
> bcdedit /createstore BCD
> bcdedit /store BCD  /create {bootmgr} /d "Windows Boot Manager"
> bcdedit /store BCD /create /d "Windows 10" /application osloader # ここでGUID(UUID)が表示される。選択して右クリックでコピー
> bcdedit /store BCD /set {bootmgr} default {<GUIDをここに挿入>}
> bcdedit /store BCD /set {bootmgr} path \EFI\Microsoft\Boot\bootmgfw.efi
> bcdedit /store BCD /set {default} device partition=c:
> bcdedit /store BCD /set {default} osdevice partition=c:
> bcdedit /store BCD /set {default} path \Windows\System32\winload.efi
> bcdedit /store BCD /set {default} systemroot \Windows
> exit # 終了
```

#### 起動確認
BIOS(UEFI?)の起動メニューを表示して`Windows Boot Manager`を選択して起動を実行する。

#### GRUBの設定
無事起動が確認できたらLinuxに戻る。
以下を実行。
```
$ sudo grub-mkconfig # 30_os_proberあたりを見てWidows Boot Managerが認識されていることを確認する。
$ sudo grub-mkconfig -o /boot/grub/grub.cfg # 設定ファイルを書き込み
```

#### 最終確認
再起動してLinux、Windows両方を起動できることを確認する。

## 参考
- [Windows OS Hub - How to Restore Deleted EFI System Partition in Windows 10?](http://woshub.com/how-to-repair-deleted-efi-partition-in-windows-7/)
query構文を用いてPHPでSQL操作(テーブル作成と削除、SQLエラーの表示)

・query構文を用いてPHPでSQL操作(テーブル作成と削除、SQLエラーの表示)
●query構文
`DB接続インスタンス->query("SQL操作");`
※SQL操作・・・create, drop, delete, insert, update等
●テーブル作成
`DB接続インスタンス->query("create table テーブル名(カラム名 カラム型, ...)");`
●テーブル削除
`DB接続インスタンス->query("drop table if exists テーブル名");`
●SQLのエラーの表示
`echo DB接続インスタンス->error;`

例)
```
<?php
$db = new mysqli("localhost:8889", "root", "root", "mydb");
$db->query("drop table if exists test");
$success = $db->query("create table test(id INT)");
if ($success) {
    echo "テーブルを削除後、作成しました";
} else {
    echo "SQLが正常に動作しませんでした";
    echo $db->error;
}
?>
```

補足画像)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2596732/18539d55-bf37-f18e-f2cd-b502481288cb.png)
laravel + vue 開発まで

### 環境
mac, mamp にて行いました。



# -- 開発開始までの流れ --
+ laravel プロジェクトの作成
+ laravel/ui インストール
+ vue のスカフォールドを作成
+ vue（vue cli）のバージョン確認
+ Vue CLI のインストール（必要であれば）
+ Vue Router のインストール（必要であれば）
+ 「vulnerabilities〜」と出たら
+ 各パッケージのインストール
+ 「npm run dev 」の実行




## laravel プロジェクトの作成
バージョン指定なし
```
composer create-project laravel/laravel プロジェクト名
```
バージョン指定あり
```
composer create-project --prefer-dist "laravel/laravel=6.*" プロジェクト名
```
「--prefer-dist」って何？ て方はこちら↓
> composer の–prefer-distってよく使うけど何してる？
https://kin29.info/composer-%E3%81%AE-prefer-dist%E3%81%A3%E3%81%A6%E3%82%88%E3%81%8F%E4%BD%BF%E3%81%86%E3%81%91%E3%81%A9%E4%BD%95%E3%81%97%E3%81%A6%E3%82%8B%EF%BC%9F/

cd コマンドで移動後、インストールされたか確認
```
cd プロジェクト名
php artisan --version
```



## laravel/ui インストール
バージョン指定なし
```
composer require laravel/ui --dev
```
バージョン指定あり
```
composer require laravel/ui "1.x" --dev
```
「--dev」は開発時にのみ使うオプション
>https://pointsandlines.jp/server-side/php/composer-require-dev

「laravel/ui」って何？ て方はこちら↓

>Laravel6からデフォルトで入っているモダンフロントエンドフレームワーク(Vue、React等)をLaravelで使う事ができるライブラリの事です。
 http://www.code-magagine.com/?p=10606



## vue のスカフォールド（建設現場で使う足場のこと）を作成
laravel/ui を使い、スカフォールドの作成
```
php artisan ui vue
```



## vue（vue cli）のバージョン確認
```
vue --version
```
もし下記のようにエラーが出たら
```
vue: command not found
```
このようにする
```
export PATH=$PATH:/Users/ユーザー名/.npm-global/bin
```
> Vue CLIをインストール後vue: command not foundになる
https://qiita.com/kinokon/items/f8801d764b875115c350

vue のバージョン（インストールされたか）確認し以下のようにバージョンが確認されたらOK
```
@vue/cli 5.0.4
```



## Vue CLI のインストール（必要であれば）
（使わないことも多いですがあらかじめインストールしておきます）
```
npm install -g @vue/cli
```
「-g」はグローバル
「@」-> npmでは、「@」と「/」の間にユーザーネーム(or 組織名)を入れて名前空間とし、その後ろにモジュール名をつける
> 
https://mass-min.com/archives/1018
> vue cli でできること
https://prograshi.com/language/vue-js/how-to-use-vue-cli/



## Vue Router のインストール（必要であれば）
まず、package.json の確認
```json
"dependencies": {
    "vue-router": "^4.0.14"
}
```
なければ以下の手順でインストール

vue でルーティングを行う際、必要となります
バージョン指定なし
```
npm install --save vue-router
```
バージョン指定あり
```
npm install vue-router@4
```
エラーが出たらこちら
peerは「同等」の意味らしい
```
npm install vue-router --save --legacy-peer-deps
```
>https://qiita.com/koh97222/items/c46d1ef2a63b92bb6c15

force は強制的の意味
```
npm install --save vue-router --force
```

## 「vulnerabilities・・・？」 
「脆弱性があるで」って意味らしいです。もし出たら下記のコマンドを打ちましょう
いいかんじにしてくれます
```
npm audit fix --force
```
まじめな人はこちらか
>https://overworker.hatenablog.jp/entry/2020/10/18/234904

こちらで
>https://zenn.dev/feb19/articles/907990aaf95b81



## 各パッケージのインストール
```
npm install
```
>npm（パッケージ管理ツール）の基礎を解説！
https://agency-star.co.jp/column/npm

## 「npm run dev 」の実行
最後に以下のコマンドを実行

```
npm run dev
```



-----
以上です
Redux入門 その１ Reduxとは

Reduxを勉強したので備忘録としてまとめました。
目次としては以下の順で書いていこうと思います。
* Redux入門 その１ Reduxとは ← いまここ
* Redux入門 その2 Actionsについて
* Redux入門 その3 Reducersについて
* Redux入門 その4 Storesについて
* Redux入門 その5 非同期処理用ライブラリ redux-thunk

## Reduxとは
ReduxはReactJSが扱うstate(状態)を管理するためのフレームワークです。
Reactではstateの管理するデータフローにFluxを提案しています。
ReduxはFluxの概念を拡張して設計されています。

## Fluxデータフローとは
* データフロー設計の１つ
* データが常に１方向に流れる
* イベントによってデータが変化(イベント駆動)

Fluxを説明するために以下の画像がよく使われています。
![fluxデータフロー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/472716/1c135e41-ed7a-6cca-9973-2915b2d072cf.png)
* Store: アプリケーション全体のデータとビジネスロジック(必ずActionによってデータを更新する)
* View: React等のコンポーネント
* Action: View等から発火されて作られるイベント
* Dispatcher: 全てのアクションを受けてStoreにイベントを発火する

## Fluxのいいところ
全データのオペレーションがDispatcherに集約されている点です。
Dispatcherにはデータを処理する関数が登録されていて、
その処理で変更された値がStoreに格納されるので状態変更の予測が容易になるというメリットがあります。

## なぜReduxを使うのか？
* stateの見通しをよくするため
* どこからでもstateを参照、変更可能にするため(propsのバケツリレーetc...)
* モジュールを疎結合にするため
* テストを簡単にすることができるため
* データ更新に制約が生まれるので品質が上がる

## Reduxのデータフロー
ReduxはFluxの概念を拡張して設計しています。
Reduxでは以下の要素が存在しています。
* Action
* ActionCreator
* Store
* State
* Reducer

以下の図を用いてReduxの要素について説明します。
![Reduxデータフロー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/472716/79674f71-0b1f-fc57-d032-c2389608812e.png)

### Action
Actionは「何をする」といった情報をもったオブジェクトです。
Actionはtypeプロパティを必ず持っていて、「何をする」ために必要な情報を渡すことも可能。
```
{
  type: SETNAME,
  payload: 'Taro',
}
```

### ActionCreator
ActionCreatorはActionを作成するためのメソッドです。
```
function setName(name) {
  return {
    type: SETNAME,
    name: name,
  }
}
```

### Dispatch
ActionCreatorで作成したActionをDispatchを用いてStoreに送ります。
```
dispatch(setName('Taro'));
```

### Store
Storeはデータの状態(State)を保持している場所です。

### State
Stateはアプリケーションでの状態を表しています。

### Reducer
ReducerはActionとStateから新しいStateを作成して返すメソッドです。
Reducerのメソッドは副作用を起こさないpureな関数でなければならず、
Aというstateに対して毎回必ずBというstateを返すような関数でなければなりません。

Reducerの実装は、actionのtypeに応じて処理を書く事になります。
```
type Person {
  name: string,
  age: number,
}

function PersonReducer(state = initialState, action) {
  switch (action.type) {
    case SETNAME:
      return {
        name: action.payload,
        age: state.age,
      };
    case INIT:
      return {
        name: '',
        age: 0,
      }
  }
}
```

## 最後に
Reduxとは〜各要素についての説明をさせて頂きました。
windowsでubuntu環境作成

windowsでubuntu環境を作成したメモです。

## 1.Ubuntuのアプリ取得
最初にubuntuのアプリを取得します
windowsのアプリストアからubuntuのアプリを持ってきます。

https://www.microsoft.com/ja-jp/p/ubuntu/9nblggh4msv6#activetab=pivot:overviewtab


## 2.wsl（Windows Subsystem for Linux）のインストール
ubuntuのアプリだけでは動かないので
wslのインストールをします

https://docs.microsoft.com/ja-jp/windows/wsl/install

PowerShellを管理者権限で起動して
wsl --install
と打ち込んでインストールします。
インストールしたらPCを再起動すると適用されます

私は行った際にpowershellを管理者権限で起動していなかったの
管理者権限が必要ですと言われてしまいました。

## 3.wsl（Windows Subsystem for Linux）の有効化
コントロールパネル→プログラム→Windowsの機能の有効化または無効化から
Windows Subsystem for Linuxを有効にして完了です。
以下のパソコン工房のリンクで詳しく解説されていたのを参考にしました。

https://www.pc-koubou.jp/magazine/21475


自分の環境では「Windows Subsystem for Linux」が「Linux用Windowsサブシステム」と表示されていて
有効化するのに手間取りましたが以下のサイトを参考にさせて頂いて解決しました。

https://qiita.com/taraka/items/0b5919ac8ee02d81f7ff


### 終わり
MySQLのSELECTを理解するLIMITとORDER_BYの使い方

SQL文をたまに使うけどまるで身についてる気がしない寺です。
基本の基から自分で言語化できるかどうかのために書き留めています。

何分初学者ですので変なこと書いてたりする可能性はありますのでツッコミ等お願いいたします。

<!--more-->

### 前回のあらすじ
前回はSELECT文のうちカラムの指定とWHEREを使った取得条件指定を学びました。

https://qiita.com/Terralien/items/a7a0a459ba7e7accf887

数日空いたため軽く忘れてたので復習になりました（自画自賛）

## SELECT文
SELECT文はSQLのDMLのうち、データを取得する用途で使うのでした。

:::note
SQLにはDDL、DML、DCLの3つの種類があります。
そのうちDMLには`SELECT`, `INSERT`. `UPDATE`, `DELETE`の4つがあり、役割はそれぞれ取得・追加・更新・削除となります。
:::

SELECT文のうちカラム指定とWHEREについては前回学びましたので、LIMIT句とORDE BY句による順序の指定を学びます。

SQLの環境については色々ありますが、既に準備された仮想環境内で好き勝手できる[Envader](https://envader.plus)を利用します。

### LIMIT句の使い方
LIMITの役割は行数の上限を指定することです。
これを指定しないと全てのテーブル内容が出力されて見づらくなってしまいます。

取得行数を5行に

```sql
 SELECT * FROM テーブル名 LIMIT 5;
```

:::note warn
LIMIT句は標準SQLではないため、全てのRDBMSで使えるわけではないようです。
:::

OFFSET句でどの位置からデータを取得するか指定できますが、省略して数字だけも指定できます。

`SELECT カラム名 [, 複数指定する際のカラム名 ...] FROM テーブル名 LIMIT [OFFSET,] カウント数 `

10行目から3行取得

```sql
 SELECT * FROM テーブル名 LIMIT 10,3;
```

### ORDER BY
データを昇順降順に並び替えるときに使用します。
指定しなければ昇順（ASC）です。

指定する場合は、ASCが昇順、DESCは降順となります。

```sql
SELECT * FROM テーブル名 ORDER BY id ASC;
```

### ORDER BY で並び替えた後LIMITで行数指定する

テーブル名`evaluation`から`store_id`を基準に降順に並び替え5行を上限とし取得

```sql
select * from  evaluation order by store_id desc limit 5;
+------+---------+----------+---------+
| id   | user_id | store_id | star_id |
+------+---------+----------+---------+
|  240 |      21 |       50 |       2 |
|  431 |      10 |       50 |       4 |
|   21 |      35 |       50 |       4 |
| 1221 |      50 |       50 |       5 |
|  438 |      22 |       50 |       5 |
+------+---------+----------+---------+
```

コード引用：[MySQL SELECTの基本②](https://envader.plus/course/2/scenario/1038/ex)


以上がORDER BYとLIMITの使い方となります。

## 学んだこと
* LIMITは取得上限を指定する
* ORDER BYは昇順・降順並び替え

前回と合わせてSELECT文の仕組みを理解しました。
SQL文はたまにしか触らないので一週間も間があくと簡単な文法すら一旦手が止まってしまいます。

SQLは手を動かしてなんぼとのことでしたので、今後は100本、200本と言わず手を動かして瞬時に打てるようにしていきたいとおもいます。

なにかオススメ教材ご存じの方教えていただけるとありがたいです。

## 参考資料
https://dev.mysql.com/doc/refman/5.6/ja/limit-optimization.html

https://xn--t8j3bz04sl3w.xyz/mysql/limit-tukaikata/6744/

https://envader.plus/course

https://www.dbonline.jp/sqlite/select/index10.html
日本語GPT-2で 'Tokenizer class T5Tokenizer does not exist or is not currently' と怒られた

日本語GPT-2をfine-tuningしようとしたら怒られたので、メモ。

## 環境
GCPのCompute Engineで、`Deep Learning on Linux`イメージを使いました。
```:構成
Python3.8
Transformers==4.18.0.dev0
PyTroch==1.11.0+cu113
datasets==2.0.0

OS: Debian
GPU: Tesla K80
CUDA: 11.4
```

## 起こったこと
[rinna/japanese-gpt2-small](https://huggingface.co/rinna/japanese-gpt2-small)を自前のデータでfine-tuningしようと、[run_clm.py](https://github.com/huggingface/transformers/tree/main/examples/pytorch/language-modeling)を走らせたところ、以下の様に怒られました。
```:run_clm.py
ValueError: Tokenizer class T5Tokenizer does not exist or is not currently imported.
```
んなこと言われても...と思い、色々やりました。

## 解決
sentencepieceを入れたら解決しました。
```:Bash
pip install setencepiece
```

ちゃんと依存関係調べてからやろうねっていう教訓でした。
確認不足で時間食ってしまった....

## まとめ
つまり、以下が必要っぽいです。

```:Bash
pip install git+https://github.com/huggingface/transformers.git
pip install datasets
pip install sklearn
pip install sentencepiece
pip install torch                   #GPU環境では公式ドキュメント要確認
```
MAMPにおけるMySQLiを用いたDB接続(PHP)

・MAMPにおけるDB接続
●使うコード
`$mysqli = new mysqli("ホスト名", "ユーザー名", "パスワード", "データベース名");`
※データベース名は自分で作成したDB名を書く
※PHP公式ドキュメントは以下のページ
https://www.php.net/manual/ja/mysqli.quickstart.connections.php

●MAMP情報(ホスト名、ユーザー名、パスワードの取得）
手順1
![1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2596732/36522334-1f58-ed32-8e30-677e53653e5c.jpeg)

手順2
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2596732/59549367-e189-855e-b02a-859f9d8e7ece.png)


例)
```
<?php
$mysqli = new mysqli("localhost:8889", "root", "root", "mydb");
?>
```
現在の技術(2022/03/27)

どの技術が楽しいか知る為に上辺だけ触りまくった期間でした。仕事ではphp、wordpress、cakeを触ってます。現在go, rustが楽しいと気付いたので転職活動中。
趣味勉強。ご飯食べてる時はawsサミットを見ながら、目が疲れて休憩中はヨガをしながらセキュリティの音声配信を聞きながら、21時就寝5時起き毎日16時間はプログラミングの勉強してると思います、幸せです。疲れて効率が悪い事に目を背けていたので、アウトプット始めます。

# 2022/03/27時点(プログラミング歴2年3ヶ月)  
  
100満点(主観)  
php: 60  
python: 40  
ruby: 5  
go: 50  
rust: 50  
haskell: 5  
c++: 15  
javascript: 55  
typescript: 51  
solidity: 20  
html: 70  
css: 60  
  
nodejs: 40  
react: 40  
nextjs: 38  
nestjs: 20  
vuejs: 20  
svelte: 18  
cake: 60  
laravel: 35  
django: 55  
flask: 50  
fastapi: 20  
rails: 3  
actix_web: 45  
rocket: 40  
yew: 10  
flutter: 5  
reactnative: 30  
  
mysql: 60  
postgresql: 50  
mongodb: 40  
redis: 35  
  
aws: 40  
gcp: 30  
  
ブロックチェーン: 50  
機械学習: 30  
docker: 60  
kubernetes: 25  
istio: 15  
envoy: 20  
fluentd: 10  
grpc: 30  
graphql: 50  
  
wordpress: 60  
contentful: 30
ReagentからMUIのDatePickerを使おうとしてハマった

ReagentからMUI (旧Material-UI) のDatePickerを使おうとしてハマったのでメモ。

https://mui.com/components/date-picker/#basic-usage

上記のサンプルをreagentで書く。

```Clojure
(ns views
  (:require
   [re-frame.core :as re-frame]
   [reagent.core :as reagent]
   ["@mui/material" :as mui]
   ["@mui/lab" :as mui-lab]))

(defn basic-date-picker []
  (let [val (reagent/atom nil)]
    (fn []
      [:> mui-lab/LocalizationProvider {:date-adapter mui-lab/AdapterDateFns}
       [:> mui-lab/DatePicker {:label        "Basic example"
                               :value        @val
                               :on-change    #(reset! val %)
                               :render-input (fn [^js params]
                                               (reagent/create-element mui/TextField params))}]])))
```

これを実行する。

```
react.development.js:221 Warning: Failed prop type: The prop `dateAdapter` is marked as required in `LocalizationProvider`, but its value is `undefined`.
    at LocalizationProvider (http://localhost:8280/js/compiled/cljs-runtime/module$node_modules$$mui$lab$node$LocalizationProvider$LocalizationProvider.js:1:470)
・・・

react-dom.development.js:11341 Uncaught TypeError: Utils is not a constructor
    at eval (LocalizationProvider.js:39)

・・・
```

エラー出力され表示できない。
試しにAdapterDateFnsを覗いてみると…

```Clojure
(println mui-lab/AdapterDateFns)  ; ==> nil
```

うまく参照できてなかったもよう。
requireの方法を変えたら解決した。

```diff
+   ["@mui/lab/AdapterDateFns$default" :as AdapterDateFns]

-      [:> mui-lab/LocalizationProvider {:date-adapter mui-lab/AdapterDateFns}
+      [:> mui-lab/LocalizationProvider {:date-adapter AdapterDateFns}
```

https://shadow-cljs.github.io/docs/UsersGuide.html#_using_npm_packages

[こちら](https://qiita.com/lagenorhynque/items/38537fa91300e0ac0070)の記事のサンプルのように:defaultでもいける。

```Clojure
["@mui/lab/AdapterDateFns" :default AdapterDateFns]
```
minsdkversion 19 とコンソールに表示された!

## FlutterでAndroidのbuildしたら久しぶりにエラーにハマった!

解決法

以下のサイトを参考にする

https://www.mechengjp.com/%E3%80%90flutter%E3%82%A8%E3%83%A9%E3%83%BC%E8%A7%A3%E6%B1%BA%E6%B3%95%E3%80%91uses-sdkminsdkversion-16-cannot-be-smaller-than-version-19-declared-in-library-%E3%81%A8%E3%81%84%E3%81%86%E3%82%A8/

https://developer.android.com/studio/build/multidex?hl=ja

**build.gradleを修正**

app/src/build.gradle

```
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
    localPropertiesFile.withReader('UTF-8') { reader ->
        localProperties.load(reader)
    }
}

def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
    throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}

def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
    flutterVersionCode = '1'
}

def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
    flutterVersionName = '1.0'
}

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'com.google.gms.google-services'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"

android {
    compileSdkVersion flutter.compileSdkVersion

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    kotlinOptions {
        jvmTarget = '1.8'
    }

    sourceSets {
        main.java.srcDirs += 'src/main/kotlin'
    }

    defaultConfig {
        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
        applicationId "com.example.finstagram"
        minSdkVersion 19 // 追加
        targetSdkVersion 31 //28だと警告が出てくる!
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
        multiDexEnabled true // 追加
    }

    buildTypes {
        release {
            // TODO: Add your own signing config for the release build.
            // Signing with the debug keys for now, so `flutter run --release` works.
            signingConfig signingConfigs.debug
        }
    }
}

flutter {
    source '../..'
}

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation platform('com.google.firebase:firebase-bom:29.2.1') // 追加
    implementation 'com.google.firebase:firebase-analytics' // 追加
    implementation "androidx.multidex:multidex:2.0.1" // 追加
}

```
VScodeでユーザスニペットを登録する手順

**VScodeのスニペット登録手順**

PC:macOS Monterey12.3
vscode:バージョン: 1.65.2


1. ⌘+shift+p にて settings と入力して、"基本設定：設定（JSON）"を開く
2. 以下を入力する

<pre>
    "[markdown]": {                        //対応する言語を入力,以下は各種パラメータ
    "editor.wordWrap": "on",
    "editor.quickSuggestions": true,       //入力中に自動的に表示するかどうか
    "editor.snippetSuggestions": "top",
    }
</pre>

3. ⌘+shift+p にて snippet と入力して、"基本設定：ユーザスニペットの構成"をクリック（（設定>ユーザスニペットでもOK））
4. つづけて、markdown と入力して、markdown.json をクリック
5. 以下の書式で入力する

<pre>
  "スニペット名": {
    "prefix": "呼び出し名",
    "body": "入力される文字"
  }
</pre>


⌘+shift+p にて insert snippet でもユーザスニペットに登録されている


参考：
https://qiita.com/c6tower/items/048c614a77a8f4311d71
https://code.visualstudio.com/docs/editor/userdefinedsnippets
PHP 変数展開 文の中に変数を入れ込む

##  使用用途
- PHPで文の中に変数の値を出力したい際に使う

## 変数展開

``` php:変数展開のコード
<?php
$value = "hogehoge";
echo "これは{$value}です";
```

``` php:出力結果
これはhogehogeです
```

## その他の出力方法
#### .（ドット）を使用するコード

``` php:.（ドット）を使用するコード
<?php
$value = "hogehoge";
echo "これは" . $value . "です";
```

``` php:出力結果
これはhogehogeです
```

#### ダブルクオートを使用するコード
``` php:.（ドット）を使用するコード
<?php
$value = "hogehoge";
echo "これは$valueです";
```

``` php:出力結果
これはhogehogeです
```


## シングルクオートの際の注意
:::note warn
警告
シングルクオートで囲うと変数名がそのまま表示される
:::

``` php:.（ドット）を使用するコード
<?php
$value = "hogehoge";
echo 'これは$valueです';
```

``` php:出力結果
これは$valueです
```
cpprestsdkとEigenを併用するとBDCSVD.hでコンパイルエラー（C4002/C3861）が発生する

cpprestsdkとEigenを使用している環境で、コンパイルしようとすると次のエラーが出ました。
```console
C4002	関数に似たマクロ呼び出し 'U' の引数が多すぎます	BDCSVD.h	1087
C4002	関数に似たマクロ呼び出し 'U' の引数が多すぎます	BDCSVD.h	1089
C3861	'Li': 識別子が見つかりませんでした	BDCSVD.h	1089
C3861	'Ln': 識別子が見つかりませんでした	BDCSVD.h	1087
```

検索してみると似たようなエラーを発見。

https://forum.kde.org/viewtopic.php?f=74&t=142940

同じくBDCSVD.hでC4002を引いているようです。
これによると、cpprestsdkで使用している`U`というマクロ（[参照](https://github.com/microsoft/cpprestsdk/blob/master/Release/include/cpprest/details/basic_types.h#L87)）とEigenで使用している`U`というマクロ（[参照](https://eigen.tuxfamily.org/dox/BDCSVD_8h_source.html)）が競合しているようです。

具体的には、BDCSVD.hよりも先にcpprestsdk側の`U`が定義されてしまうと、コンパイルエラーになってしまうようです。

応急処置でこのように解決しました。
```C++:BDCSVD.h
#ifdef U
#define EIGEN_INTERNAL_U_PROTECTOR U
#undef U
#endif

// 元のソースコード

#ifdef EIGEN_INTERNAL_U_PROTECTOR
#define U EIGEN_INTERNAL_U_PROTECTOR
#undef EIGEN_INTERNAL_U_PROTECTOR
#endif
```

BDCSVD.hの最初と最後に上記のようなコードを追記します。
これで`U`を一旦別のマクロに避難させておき、コード終端で再び`U`にdefineします。
こうすることでコンパイルエラーは出なくなりました。
既に開いているEdgeを、WebDriverで操作する（C#）



:::note info
ブラウザ操作の自動化をしたい、と言っても、ブラウザを開く初手からすべて自動化するのは、それはそれでかったるい。ある程度、手でブラウザをたどった後に、部分的に処理を自動化したい、という場面の方が多い。その場合、既に開いてあるEdgeを、拾って、自動操作する、ということがやりたい。
:::

必要なのは２点。

# その１：Egde起動時に２つの指定

コマンドプロンプトから
--remote-debugging-port
--user-data-dir
を指定してEdgeを起動する。（そして、そのEgdeで望む手動操作をしておく）

```
"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" --remote-debugging-port=9222 --user-data-dir="C:\myTestEdgeProfile" "www.yahoo.co.jp"
```

# その２：ソース中、オプション指定

EdgeDriveを生成する際のOptionにて、DebuggerAddress を指定する

```
var options = new EdgeOptions();
options.DebuggerAddress = "127.0.0.1:9222";
var driver = new EdgeDriver(options);
```

# ソース

```csharp:EdgeDriver_2.cs
//c:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe /reference:WebDriver.dll /target:exe EdgeDriver_2.cs

using OpenQA.Selenium;
using OpenQA.Selenium.Edge;
using System.Threading;

namespace EdgeDriver_2
{
	class Program
	{
		static void Main(string[] args)
		{
			var options = new EdgeOptions();
			options.DebuggerAddress = "127.0.0.1:9222";
			var driver = new EdgeDriver(options);
			try
			{
				//driver.Url = "https://www.yahoo.co.jp";
				var elements = driver.FindElements(By.XPath("//DIV/H1/SPAN"));
				foreach (var e in elements){
					System.Console.WriteLine("-> " + (e.Text));
				}
			}
			finally
			{
				//driver.Quit();
			}
		}
	}
}
```

# 実行画面

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107418/0840dd57-a9e1-562e-166e-02d1beefb910.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107418/d37e129b-6f12-51c9-1ead-65ae381ead55.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107418/97911996-469d-7a06-d37b-1d5d0af68af6.png)



# 参考

https://qiita.com/santarou6/items/fa1cba6fb347b2dd8f88
Raspberry Pi 4でBBC Microエミュレータb-emをビルドする

「Raspberry Pi 4でBBC Microエミュレータb-emをビルドする」(主に自分用の)備忘です。Pi OSでは、liballegro5-dev (Allegro5)が入らないか、入ってビルドが通っても、b-emが起動しなかった覚えがあり、それが今回の発端です。また、network-managerを削除して、netplanに任せるのも(b-emに限りませんが)ポイントです。

## 目標地点
b-em
⇔ qterminal
⇔ lubuntu (ガワだけ。ディスプレイマネージャと気分の問題)
⇔ Raspberry Pi 4
⇔ netplan (重要)
⇔ xrdp
⇔ リモートデスクトップ接続
⇔ Windows 10
* https://github.com/stardot/b-em

## 手順

1. Raspberry Pi Imager の設定欄にネットワーク回りや初期ユーザー等を書く
2. Ubuntu Server 64bitを指定し、SDカードに焼く
3. まだ抜かない。network-configを確認する。1.で書いた内容が反映されている
4. ラズパイにSDカードを入れる。起動する
5. 手元のterminalからnmapして存在を確かめる。この時点ではまだDHCPと思う
6. 22番でsshする。適宜ポートを変える。ユーザーを追加、sudo付与する
7. お好みでtcp bbrなどする
8. 再起動する
9. ラズパイ実機でログインする(設定変更に伴うネットワーク切断があり得るため)
10. /etc/hostsのテンプレートファイルを(必要なら127.0.0.1等に)直す
11. /etc/netplan/50-cloud-init.yamlにいろいろ追記する
12. audo apt update apt upgrade && sudo apt install lubuntu-desktop && apt remove network-manager
13. sudo netplan apply && ip addr
14. 再起動する
15. 設定が適切なら実機を離れて手元のterminalに戻ってOK
16. sudo apt install xrdp build-essential automake liballegro5-dev && sudo systemctl enable xrdp
16. 再起動する。うまくいけばここでxrdpできる。qterminal等を立ち上げる
17. 適当なディレクトリ、例、/home/hoge/neko/emu/をmkdir -p && cdする
18. git clone https://github.com/stardot/b-em.git
19. cd b-em
20. ./autogen.sh
21. ./configure
22. make
23. ./b-emで起動する
24. GTKからwarningが出るようなら、sudo apt install packagekit-gtk3-module libcanberra-gtk-module
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159724/d511d01d-f4c3-ece0-7f53-88c905181903.png)
以上です。幸せです(*'▽')
「Worker with pid xxx was terminated due to signal 9」と出たとき

## 現象、問題
Dockerの上でGunicornを使ったアプリケーションを起動してようとしたが以下のようなエラーが出てアプリケーションが動かない

```
[2022-03-27 05:58:17 +0000] [18] [WARNING] Worker with pid 224 was terminated due to signal 9
```

## 解決方法
Dockerのメモリー割当を増やすことでwarningは出なくなり、アプリケーションも動くようになりました。
他にも、ワーカー数を減らしてみることでメモリー使用量を減らしてアプリケーションを起動することができるかもしれません。

## 参考
https://stackoverflow.com/questions/67637004/gunicorn-worker-terminated-with-signal-9

こちらの記事の回答では、MLモデルの読み込みに時間がかかっていたため以下のようにタイムアウト時間を伸ばすことで解決すると書いてあります。メモリーを増やしてみてもダメなときは試してみると良いかもです。

```
gunicorn main:app --workers 1 --worker-class uvicorn.workers.UvicornWorker --bind 0.0.0.0:8443 --timeout 600
```
Minix 2.0.4 をQEMUで使うときのコツ

ゴチャゴチャ読みたくない場合は http://p1437140-ipoe.ipoe.ocn.ne.jp:63873/minixsmp/ から `minix204.qcow2.xz` をダウンロードし解凍し， `qemu-system-i386 -machine pc -cpu pentium3-v1 -accel kvm -smp sockets=1 -m 2048M -net user -net nic,model=pcnet -drive discard=unmap,detect-zeroes=unmap,if=ide,file=minix204.qcow2 -boot c`で起動して下さい。VirtualBoxで動かしたい場合[Minix 2のネットワークをVirtualBoxで動かしてみた](https://qiita.com/nsan/items/2d1cd59d7c977be4ae4e)を見るほうがよい。

[Minix 3は2より遅くなっている](https://qiita.com/kakinaguru_zo/items/4235913789540ceeedfc)ことや，Minix 3のソースコードのあまりの大量さに圧倒されたので，http://minix1.woodhull.com/pub/demos-2.0/VMWarePlayer/ からハードディスクイメージを持ってきて使おうとすると，幾つか問題がありすぐには使えないのでその対応法です。

# フロッピーは使えない
QEMUのフロッピーエミュレーションと相性が悪いらしくて，[MINIX2 を VirtualBox で動かしてみた](https://qiita.com/nobuh/items/67fb79613425f46fa9ca) に従ってフロッピーディスクイメージを作って起動しようとしても起動しない…

# イメージファイル形式の変更
イメージの形式がVMWare用なので `qemu-img convert -f vmdk -O raw -S 512 -o preallocation=off mx204d0.vmdk minix204.img` などとしてQEMUが読める形式に変換する。ここではディスクイメージがそのままファイルになっている「生」形式にした。「生」形式だと`losetup`と`mount`コマンドでLinuxからminixディスクのファイルを操作できる。qcow2形式にしたほうふぁファイルサイズが小さくなるが，LinuxホストOSからminixファイルを操作するために`qemu-nbd`を使う必要がある。

# Minixディスクイメージ内のファイル操作
ディスクイメージがLinuxの上にあるとして， rootで `losetup -P -f minix204.img; mount /dev/loop0p7 /mnt` などとするとMinixの/usrがLinuxの/mntから見えるようになる。

# キーボード配置がアメリカ配列になっている
`cp /usr/lib/keymaps/japanese.map /etc/keymap` してから再起動する。

# `hostaddr -h`がバグっていて起動しない
仮想マシンにAMD Lanceイーサネットカードを与えて起動すると， `/usr/etc/rc` 内の `hostaddr -h` がハングアップして起動しない。対応法としては，仮想マシンをネットワークカード無しで起動（`-net none`をQEMUオプションに入れる）して， `/usr/etc/rc` 内の `hostaddr -h` を含む`if`節をまるごと削除するとよい。

# ネットワークカードが使えない
`rtl8139` のMinixドライバはバグっていてMinixがpanicする。QEMUからEthernet Express Proを仮想マシンに付けてもMinixは認識しない。結局 AMD Lanceイーサネットカード（QEMUのオプション `-net nic,model=pcnet`）しか使えるものがない。しかし，これもMinix 2.0.4のドライバがバグっていて，[Minix 2のネットワークをVirtualBoxで動かしてみた](https://qiita.com/nsan/items/2d1cd59d7c977be4ae4e)の手順でドライバを修正する必要がある。
[iOS] ライブラリについてCocoaPods, Carthage, SwiftPMの対応状況を調査してみた

# はじめに

前提環境：
Xcode 13.2.1

参考記事：
[iOSのパッケージ管理ツールはどれが良いのか？](https://zenn.dev/ynug/articles/ios-package-management-tool)

↑の記事に記載されているとおり、ライブラリ管理ツールとしては、

- CocoaPods
- Carthage
- Swift Package Manager (SwiftPM)

の選択肢があり、それぞれメリット・デメリットがあります。

ツール選定の判断基準としては、ライブラリの対応状況も関係してくると思います。
そこで、ライブラリの対応状況をざっくり調査してみました。

ライブラリの選定は、私が実務で使ったことがあるモノ ＋ 今後使ってみたいモノです。
すなわち独断と偏見が入ってます。:sweat_smile:

# 調査結果（2022年3月27日時点）

| ライブラリ | Version | CocoaPods | Carthage | SwiftPM |
|:-:|:-:|:-:|:-:|:-:|
| [Alamofire](https://github.com/Alamofire/Alamofire) | 5.5.0 | ◯ | ◯ | ◯ |
| [AnyFormatKit](https://github.com/luximetr/AnyFormatKit) | 2.5.2 | ◯ | × | ◯ |
| [Charts](https://github.com/danielgindi/Charts) | 4.0.2 | ◯ | ◯ | ◯ |
| [DifferenceKit](https://github.com/ra1028/DifferenceKit) | 1.2.0 | ◯ | ◯ | ◯ |
| [Firebase](https://github.com/firebase/firebase-ios-sdk) | 8.14.0 | ◯ | △Beta | ◯ |
| [GoogleMaps](https://developers.google.com/maps/documentation/ios-sdk/config) | 6.1.1 | ◯ | ◯ |  × |
| [Kingfisher](https://github.com/onevcat/Kingfisher) | 7.2.0 | ◯ | ◯ | ◯ |
| [KeychainAccess](https://github.com/kishikawakatsumi/KeychainAccess) | 4.2.2 | ◯ | ◯ | ◯ |
| [Lottie](https://github.com/airbnb/lottie-ios) | 3.3.0 | ◯ | ◯ | ◯ |
| [Moya](https://github.com/Moya/Moya) | 15.0.0 | ◯ | ◯ | ◯ |
| [OHHTTPStubs](https://github.com/AliSoftware/OHHTTPStubs) | 9.1.0 | ◯ | ◯ | ◯ |
| [R.swift](https://github.com/mac-cain13/R.swift) | 6.1.0 | ◯ | × | × |
| [Reachability.swift](https://github.com/ashleymills/Reachability.swift) | 5.1.0 | ◯ | ◯ | ◯ |
| [RealmSwift](https://github.com/realm/realm-swift) | 10.24.2 | ◯ | ◯ | ◯ |
| [RxSwift](https://github.com/ReactiveX/RxSwift) | 6.5.0 | ◯ | ◯ | ◯ |
| [SkeletonView](https://github.com/Juanpe/SkeletonView) | 1.29.2 | ◯ | ◯ | ◯ |
| [SwiftLint](https://github.com/realm/SwiftLint) | 0.47.0 | ◯ | × | × |
| [SwiftyJSON](https://github.com/SwiftyJSON/SwiftyJSON) | 5.0.0 | ◯ | ◯ | ◯ |
| [SVProgressHUD](https://github.com/SVProgressHUD/SVProgressHUD) | 2.2.5 | ◯ | ◯ | × |
| [Toast-Swift](https://github.com/scalessec/Toast-Swift) | 5.0.1 | ◯ | ◯ | ◯ |

# 私見

CocoaPodsはビルドが遅い難点がありますが、面倒がなくて安心感があります…
じゃんけんプログラムをJavaScriptで書く

私が通っているスクールで、じゃんけんプログラム書いてこい！っていう課題が出たので、ついでに記事にします。もっとこうした方がきれいに書けるよ！記事として読みやすいよ！等ありましたら、是非コメントお願いします。
スクールHP↓
[SUNABACO](https://sunabaco.com/)

# じゃんけんプログラム
自分の手をエディターに入力すると、コンピュータの手に対し、勝ちか負けを判定し、コンソールに出力する。

## 条件整理
1. 自分の手を決める
1. 相手の手を決める
等確率かつランダムでグー、チョキ、パーを出力する。
1. 自分の手と相手の手を比べ、勝敗を決める
勝ちのパターン、負けのパターン、引き分けのパターンで条件分岐。
1. 1~3をまとめる


### 実際に解いてみる
<ol><li> 自分の手を決める。

とりあえず、、、
```js
const yourHand === "グー"
```
<li> 相手の手を決める

```Math.random()```で0以上1未満の乱数を発生させることができるらしい。今回はこれを利用する。
(https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Math/random)
出力された乱数のうち、
- 1/3未満で"グー"
- 1/3以上3/2未満で"チョキ"
- 2/3以上1未満で"パー"

で出力されるようにする。
``` js
let oponentHand = Math.random();

if (opponentHand < 1 / 3) {
  opponentHand = "グー";
} else if (opponentHand < 3 / 2) {
  opponentHand = "チョキ";
} else if (opponentHand < 1) {
  opponentHand = "パー";
}
```
<li> 自分の手と相手の手を比べ、勝敗を決める

``` js
  if (yourHand === oponentHand) {
    console.log("引き分け");
  } else if (oponentHand === "グー") {
    if (yourHand === "パー") {
      console.log("あなたの勝ち！");
    } else {
      console.log("あなたの負け！");
    }
  } else if (oponentHand === "チョキ") {
    if (yourHand === "グー") {
      console.log("あなたの勝ち！");
    } else {
      console.log("あなたの負け！");
    }
  } else if (oponentHand === "パー") {
    if (yourHand === "チョキ") {
      console.log("あなたの勝ち!");
    } else {
      console.log("あなたの負け");
    }
  }
};
```

<li> 1~3をまとめる

 最後に上記のコードを一つの関数にまとめて完成。1で定義した変数yourHandはjankenFunの引数として書き換えた。

```js
const jankenFun = (yourHand) => {
  let oponentHand = Math.random();
  if (oponentHand < 1/3) {
    oponentHand = "グー";
    console.log(oponentHand,"相手の手");
  } else if (oponentHand < 2/3) {
    oponentHand = "チョキ";
    console.log(oponentHand,"相手の手");
  } else if (oponentHand < 1) {
    oponentHand = "パー";
    console.log(oponentHand,"相手の手");
  }
  if (yourHand === oponentHand) {
    console.log("引き分け");
  } else if (oponentHand === "グー") {
    if (yourHand === "パー") {
      console.log("あなたの勝ち！");
    } else {
      console.log("あなたの負け！");
    }
  } else if (oponentHand === "チョキ") {
    if (yourHand === "グー") {
      console.log("あなたの勝ち！");
    } else {
      console.log("あなたの負け！");
    }
  } else if (oponentHand === "パー") {
    if (yourHand === "チョキ") {
      console.log("あなたの勝ち!");
    } else {
      console.log("あなたの負け");
    }
  }
};
// 引数に自分の手を入力

jankenFun("グー");
```
カスタムコントロールのイベントをプロパティウィンドウで非表示にしようとして躓いたこと

# はじめに

カスタムコントロールをControlを継承して作成しました。
デザイナーに対応させようとしたのですが、Controlのプロパティやイベントがプロパティウィンドウにたくさん表示されます。
![無題の画像4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317334/4bddf2c6-be31-6258-36aa-4b3a1a3502e9.png)

このコントロールには殆どの項目は不要なので表示したくありません。

# やったこと
以下のページを参考に、プロパティを表示しないようにするのは成功しました。

https://codehero.jp/c%23/7054408/propertygrid-hide-base-class-properties-how

1. ControlDesignerクラスを継承したMyControlDesignerクラスを作成する
2. PreFilterPropertiesメソッドをオーバーライドする
    1. 基底クラスControlDesignerのPreFilterProperiesを呼ぶ
    2. 引数のIDictionaryからプロパティ名をキーとしてPropertyDescriptorを取得する
    3. 2のPropertyDescriptorから、属性Browsable(false)を追加した新しいPropertyDescriptorを作成する
    4. 作成したPropertyDescriptorを、プロパティ名をキーとして引数のIDictionaryに設定する
3. カスタムコントロールの属性としてMyControlDesignerクラスを指定する

これをイベントについても行おうとして以下のコードを作成しました。
アクションカテゴリの、ClickからMouseDoubleClickまでを非表示にしようとしています。

```c#:
		protected override void PreFilterEvents(IDictionary events)
		{
			// PreFilterEventsをオーバーライドする場合は必須
			base.PreFilterEvents(events);

			// 隠したいイベントの名前を追加する
			string[] eventsToHide = {
				"Click", "DoubleClick", "MouseCaptureChanged", "MouseClick", "MouseDoubleClick",
			};

			foreach (string eventname in eventsToHide)
			{
				var ev = (EventDescriptor)events[eventname];
				if (ev != null)
				{
					AttributeCollection runtimeAttributes = ev.Attributes;

					// 元の属性数より1個多く確保して、そこに元のをコピー（後ろが1個空く）
					Attribute[] attrs = new Attribute[runtimeAttributes.Count + 1];
					runtimeAttributes.CopyTo(attrs, 0);

					// 一番後ろに属性追加
					attrs[runtimeAttributes.Count] = new BrowsableAttribute(false);

					// 新しいイベント記述子を作成して、元のイベントを置き換える
					ev = TypeDescriptor.CreateEvent(this.GetType(), eventname, ev.EventType, attrs);
					events[eventname] = ev;
				}
			}
		}
```

# 上手く動かない！
動かしてみると、非表示ではなく黒塗りになってしまいました。
![無題の画像2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317334/1833855f-6667-8370-638a-22cf15ae8131.png)

再描画させると黒塗り部分がメッセージに変わりますが、
![無題の画像3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317334/8fb61335-ab17-83f0-c088-cd7a07569569.png)

プロパティ表示に切り替えてイベント表示に戻そうとするとVisual Studioが落ちます。
これは困った……。

# 解決
よくよく見ていて、ひっかかることが。
CreateEventの第一引数のthis.GetType()。**this！？**

```c#:
ev = TypeDescriptor.CreateEvent(this.GetType(), eventname, ev.EventType, attrs);
```

Microsoft Docsによると、ここはコンポーネントの型を指定するそうです。

https://docs.microsoft.com/ja-jp/dotnet/api/system.componentmodel.typedescriptor.createevent?view=net-6.0#system-componentmodel-typedescriptor-createevent(system-type-system-string-system-type-system-attribute())

thisってMyControlDesignerのインスタンスだよね。
EventPropertyのComponentTypeじゃないの？

```diff_c_sharp
- ev = TypeDescriptor.CreateEvent(this.GetType(), eventname, ev.EventType, attrs);
+ ev = TypeDescriptor.CreateEvent(ev.ComponentType, eventname, ev.EventType, attrs);
```

おお、上手くいきました！
ClickからMouseDoubleClickまで非表示になっています。
![無題の画像.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317334/d3defaf3-05ca-9fbd-fecd-b11e3c86614f.png)

# 終わりに
調べてもあまり情報が出てこなかったので書いてみました。
読みづらかったらすみません。
改善点やツッコミ処等があればご指摘お願いします。
ManagementConsoleへのサインイン時にリージョンを固定する

# 調査理由
サインインする度に右上から東京(ap-northeast-1)に変更するのが手間。

# 変更方法
設定とかは無くて、リージョン指定つきのサインイン画面を開けばよかった。

``` ルートユーザー
https://signin.aws.amazon.com/console/?region=ap-northeast-1
```

``` IAMユーザー
https://Your_Account_ID_OR_ALIAS.signin.aws.amazon.com/console/?region=ap-northeast-1
```

# 結論
上のURLだとサインイン済みでもサインインページに飛ばされちゃう問題があった。
ブックマークしておくならコンソールのURLがいいかもしれない。
```
https://console.aws.amazon.com/console/home?region=ap-northeast-1
```

# 参考
- https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/console_account-alias.html#AboutAccountAlias
- https://qiita.com/qt6hy/items/3539bc2fc7caef0d0755#%E3%81%8A%E5%8B%A7%E3%82%81%E3%81%AE-%E3%83%AD%E3%82%B0%E3%82%A4%E3%83%B3url
- https://www.cotegg.com/blog/?p=2618
GitHub から binary file をインストールする

githubページからインストールするには、releasesページを参照。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534442/44db6925-d040-b8a7-5dc6-b5a72809ed52.png)


コマンドライン上でインストールしたいのであれば、上記のページのリンクを使用して cURLでインストールすれば良い。

```sh
curl -L https://github.com/itamae-kitchen/mitamae/releases/download/v1.12.9/mitamae-x86_64-darwin.tar.gz 
\  | tar xvz
```


## おまけ① sha256 hash の取得方法

インストールしたファイルの、sha256 hash code を取得する方法は以下。

```sh
 curl -L https://github.com/itamae-kitchen/mitamae/releases/download/v1.12.9/mitamae-x86_64-darwin.tar.gz
\  | shasum -a 256  
```

## おまけ② `インストール && 解凍 && pathを通す`方法

以下のスクリプトが参考になりそう。
https://github.com/k0kubun/dotfiles/blob/master/bin/setup
【Golang】ローカルのIPアドレスを取得する【複数NIC対応】

> Go 言語（以下 Golang）で作成したアプリを実行しているマシンの**ローカル IP アドレスが知りたい**。
>
> 複数の NIC（ネットワークカード）がある場合でも、外部からアクセス可能な方の IP アドレスが知りたい。

[「"golang" ローカルのIPアドレスを取得する」でググって](https://www.google.com/search?q=%22golang%22+%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E3%81%AEIP%E3%82%A2%E3%83%89%E3%83%AC%E3%82%B9%E3%82%92%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B)も、タイトルからわかるドンピシャの記事がなかったので、自分のググラビリティとして。

## TL; DR <sub><sup><sub><sup>（今北産業）</sup></sub></sup></sub>

```go
import "net"

// GetOutboundIP returns the outbound IP address of this machine.
func GetOutboundIP() (string, error) {
	// net.Dial で一度外部にアクセスして、使用したネットワークカードの
	// 情報を取得する。アクセス先は、存在する IP アドレスであれば
	// 8.8.8.8 でなくても構わない。
	conn, err := net.Dial("udp", "8.8.8.8:80")
	if err != nil {
		return "", err
	}

	defer conn.Close()

	// 使用しているネットワークカードのローカル IP を取得
	localAddr := conn.LocalAddr().(*net.UDPAddr)

	return localAddr.IP.String(), nil
}
```

- [オンラインで動作をみる](https://go.dev/play/p/Ob2dnt5uBln) @ Go Playground
- 参考文献:
    - [コメント](https://stackoverflow.com/a/37382208/8367711) | "How do I get the local IP address in Go?" @ StackOverflow
Seabornのclustermapによるクラスタリング後の結果行列の取得方法

Seabornの`clustermap`関数によるクラスタリング後の結果行列を取得する方法の備忘録

# clustermap関数の仕様

[公式ドキュメント](https://seaborn.pydata.org/generated/seaborn.clustermap.html)によると、clustermapは戻り値として**ClusterGrid**オブジェクトを返す。クラスタリング後に並び替えられた行・列インデックス情報はClusterGridオブジェクトの`dendrogram_row.reordered_ind`、`dendrogram_col.reordered_ind`のプロパティから取得できる。以下にアヤメ(iris)データセットを利用したコード例を記載する。

```python:クラスタリング後の行・列インデックス取得例
import seaborn as sns

iris = sns.load_dataset("iris")
species = iris.pop("species")
iris = iris[:10] # テスト確認用にデータ削減

g = sns.clustermap(iris, figsize=(10, 4))
print("> Original data")
print("rows = ", list(iris.index))
print("columns = ", list(iris.columns))
print("> Clustering data")
print("rows = ", g.dendrogram_row.reordered_ind)
print("columns = ", g.dendrogram_col.reordered_ind)
```
**コード実行の出力結果・図**
```text
> Original data
rows =  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
columns =  ['sepal_length', 'sepal_width', 'petal_length', 'petal_width']
> Clustering data
rows =  [5, 7, 0, 4, 8, 1, 9, 6, 2, 3]
columns =  [2, 3, 0, 1]
```
![clustermap_iris.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138429/494e4664-24e0-34a0-0ee3-73636b296b88.png)
出力結果・図からクラスタリング後に並び替えられた行・列の各インデックス情報を正しく取得できていることが確認できる。

# クラスタリング後の結果行列取得

クラスタリング後に並び替えられた行・列インデックス情報を元に、下記コードでクラスタリング後の結果行列を取得できることを確認できた。

```python
import seaborn as sns

iris = sns.load_dataset("iris")
species = iris.pop("species")
iris = iris[:10]

g = sns.clustermap(iris[:10], figsize=(10, 4))
reordered_index = iris.index[g.dendrogram_row.reordered_ind]
reordered_columns = iris.columns[g.dendrogram_col.reordered_ind]

clustered_iris = iris.loc[reordered_index, reordered_columns]
print(clustered_iris)
```
```text:出力結果
   petal_length  petal_width  sepal_length  sepal_width
5           1.7          0.4           5.4          3.9
7           1.5          0.2           5.0          3.4
0           1.4          0.2           5.1          3.5
4           1.4          0.2           5.0          3.6
8           1.4          0.2           4.4          2.9
1           1.4          0.2           4.9          3.0
9           1.5          0.1           4.9          3.1
6           1.4          0.3           4.6          3.4
2           1.3          0.2           4.7          3.2
3           1.5          0.2           4.6          3.1
```
![clustermap_iris.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138429/494e4664-24e0-34a0-0ee3-73636b296b88.png)
CarrierwaveとMiniMagickで画像アップロードの実現

## はじめに
自作PF作成中に結構時間を要してしまったので今後のためにまとめる


## 環境と前提
M1 Mac 
Rails 6.1.4.7
Ruby 3.1.0
MacにImageMagicが入っていることが前提

## Image Magicが入っていることを確認
下記のコマンドを使用してimagemagickが入っていれば問題ないです
何も表示されなければ入っていません
```shell:terminal
$ brew list | grep imagemagic
```
入っていなければこちらのコマンドで入れてください
```sehll:terminal
$ brew install imagemagick
```


## Carrierwave

```rb
  gem 'carrierwave', '~> 2.0'
  gem 'mini_magick'
  
  bundle install
```
```rb:terminal
# アップローダークラスを作成
# app/uploaders/image_uploader.rbを生成
rails g uploader image # 関連するカラム名
```
```rb:app/models/photo.rb
# 画像カラムにアプローダークラスをマウント
# ImageUploaderは生成したファイルのクラス名
mount_uploader :image, ImageUploader
```

## MiniMagickを使えるようにする

```rb:app/uploaders/image_uploader.rb
# 3行目のコメントアウトを外す
include CarrierWave::MiniMagick
```
```rb:全ての画像をリサイズする
# コメントアウト外すだけでOK サイズはお好みで
# Process files as they are uploaded:
process resize_to_fit: [200, 200]
```
```rb:リサイズバージョンを作成する
# Create different versions of your uploaded files:
# 追記する
  version :small do
    process resize_to_fit: [55, 55]
  end
```

```rb:許容する拡張子の設定
# Add an allowlist of extensions which are allowed to be uploaded.
# For images you might use something like this:
# コメントアウト外すだけでOK
def extension_allowlist
  %w(jpg jpeg gif png)
end
```

## view側で使用する際
自分はdeviseを使っているので`current_user`でユーザー情報を取得できます
ここは自分のアプリに合わせてください

```html
<!-- 基本 -->
<%= image_tag current_user.class名_url %>

<!-- 小さめアイコンの表示 上で作成したリサイズバージョンを使えます-->
<%= image_tag current_user.image_url(:small) %>
```

## gitの管理対象外にする
```rb
public/uploads/
```

## デフォルト画像を設定する
default.jpgというファイル名でapp/assets/images内に適当な画像ファイルを置く
```rb:app/uploaders/image_uploader.rb
# Provide a default URL as a default if there hasn't been a file uploaded:
def default_url(*args) # コメントアウトを外す
 #   # For Rails 3.1+ asset pipeline compatibility:
 #   # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_'))
   "default.jpg" # 書き加える
 #   "/images/fallback/" + [version_name, "default.png"].compact.join('_')
end # コメントアウトを外す
```

## 参考

https://qiita.com/wonder_boooy/items/1510f8750d1282693148

https://scrapbox.io/rails-beginners/CarrierWave%E3%81%A7%E7%94%BB%E5%83%8F%E3%82%A2%E3%83%83%E3%83%97%E3%83%AD%E3%83%BC%E3%83%89%E3%81%97%E3%81%A6%E3%81%84%E3%81%AA%E3%81%84%E5%A0%B4%E5%90%88%E3%81%AE%E3%83%87%E3%83%95%E3%82%A9%E3%83%AB%E3%83%88%E7%94%BB%E5%83%8F%E3%82%92%E8%A8%AD%E5%AE%9A%E3%81%99%E3%82%8B

https://fukatsu.tech/install-imagemagick
Firebase cli の使い方

インストール (Ubuntu 21.10 で確認）
　

```bash
sudo curl -sL https://firebase.tools | bash
```

バージョンの確認

```text
$ firebase --version
10.5.0
```

Login

```bash
firebase login
```

Logout

```bash
firebase logout
```

プロジェクトのリスト

```bash
firebase projects:list
```
Scalaの勉強はじめました 4 〜オブジェクトとクラス②〜

## はじめに
N予備校の「Scala基礎」「Scala応用」コースを受講しています。
「オブジェクトとクラス」でざっくりまとめたことを少し後悔してます。

## トレイトとミックスイン
トレイト(振る舞い）を継承することをミックスインという

:::note
複数のトレイトを1つのクラスやトレイトにミックスインできる。
直接インスタンス化はできない。
クラスパラメータ(コンストラクタ引数)を取ることができない。
:::

`trait`で定義されるメソッドは、必ずしも実装する必要がない

```scala
class PaperCup extends Paper with Fillable with Disposable
```

クラスを同じやり方で複数継承はできないので注意。

### super

```scala
class Class2 extends TraitB with TraitC {
  override def greet(): Unit = super[TraitB].greet()
}
```

継承やミックスインで利用している型を指定して自身のインスタンスを呼び出す。
`super`キーワードは、自分の親クラスやミックスインしているトレイトを指す。

### 自分型アノテーション
クラスやトレイトの中で自分自身の型にアノテーション(情報の付加、補足)を記述できる

```scala
trait Greeter {
  def greet(): Unit
}

trait Robot {
  // 自分型アノテーション
  self: Greeter =>

  def start(): Unit = greet()
  override final def toString = "Robot"
}
```

## オブザーバーパターン
:::note
特定のオブジェクトの状態を監視するオブジェクトを用意して、イベント発生時にその変更を受け取って処理できるように実装する
:::

```scala
trait Listener {
  // 変化があった時に通知する => リスナー
  def changed(newValue: Int): Unit
}

object Observable {
  // 監視対象のオブジェクト
  private var num = 0
  private var listeners = Seq[Listener]()

  def increment(): Unit = {
    num = num + 1
    // 変化があったことを通知する
    listeners.foreach(l => l.changed(num))
  }

  def addListener(listener: Listener) = listeners = listeners :+ listener
}
// インスタンス
Observable.addListener(new Listener {
  override def changed(newValue: Int): Unit = println(s"${newValue} に変わったよ")
})
```

## JavaBeans
:::note
状態を持ち、 setで値を変更でき、 get で 属性を取得できる データクラス
:::

セッター・ゲッターっていうやつ。

```scala
import scala.beans.BeanProperty

class Movie {

  @BeanProperty
  var id: Long = _

  @BeanProperty
  var fileName: String = _

  @BeanProperty
  var time: String = _

  @BeanProperty
  var filePath: String = _

  @BeanProperty
  var media: Media = _  
}
```

`@BeanProperty`
型やメンバーなどに特別な意味をあたえることができる仕組み
`var`の変数に対してこのアノテーションを与えると、コンパイラが自動で `get${変数}`と`set${変数}`のメソッドを追加してくれる。


## まとめ
クラスやオブジェクト、今回はトレイトなど、オブジェクト指向の仕組みがたくさんあって、一度にはなかなか覚えられそうにない感じがします。