OmniAICreator/Qiita-1.07M huggingface dataset:
Windows／Macで本当によく使うショートカットキー

## はじめに

会社のPCがWindowsで、家のPCがMac。
ショートカット一覧の記事はすでにたくさんありますが、自分がよく使うものだけ抜粋してまとめました。

## ショートカット一覧
（ショートカットじゃないものも含まれてます）


|  やりたいこと  |  Windows  |Mac|備考 |
| ---- | ---- |---- |---- |
|  アプリを切替え  |  Alt + Tab  | command ＋ Tab| |
|  デスクトップを表示  |  Win + D  | command + F3| |
|  画面をロック  |  Win + L  |command + control + Q | 離席したい時|
|  デベロッパーツールを表示  |  Ctrl + Shift + I  もしくは　F12 |command + option + I ||
|  ブラウザのスーパーリロード  |  Ctrl + F5 |command ＋ R （Chrome、Safari、Opera） ||
|  シークレットモードで表示  |  Ctrl + Shift + N  | command + shift + N||
|  ファイルやフォルダーの名前を編集  |  F2 （→保存せずに終了する時は　Esc）| クリック + return||
|  範囲を指定してプリントスクリーン  |  Win + Shift + S | shift ＋command ＋ 4||
|  クリップボードの履歴を表示  |  Win + V  |Finder→「編集」→「クリップボードを表示」||
|  ページの一番下へ  |  Ctrl + End |command + ↓ ||
|  ページの一番上へ  |  Ctrl + Home |command + ↑||
|  タスクマネージャーを起動  |  Ctrl + Shift + Esc  | command + Option + Esc|アプリが反応しなくなった時など|

## 終わりに
家のMacでもうっかりWindowsの方法で指が動いたりして（逆もあり）
うまく切替えできるようになりたい…！
【Rails】Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

## 開発環境
Rails６.1.4
Ruby３.0.1
macOS Monterey 12.2.1

<br>

## エラー内容

gem（rinku）を```bundle install```しようとしたら、いきなりエラーが発生してインストールできなくなった🤯

```terminal:terminal
Installing rinku 2.0.6 with native extensions
Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

current directory: /Users/apple/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/rinku-2.0.6/ext/rinku
/Users/apple/.rbenv/versions/3.0.1/bin/ruby -I /Users/apple/.rbenv/versions/3.0.1/lib/ruby/3.0.0 -r
./siteconf20220416-552-xpdj2a.rb extconf.rb
creating Makefile

current directory: /Users/apple/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/rinku-2.0.6/ext/rinku
make DESTDIR\= clean
xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at:
/Library/Developer/CommandLineTools/usr/bin/xcrun

current directory: /Users/apple/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/rinku-2.0.6/ext/rinku
make DESTDIR\=
xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at:
/Library/Developer/CommandLineTools/usr/bin/xcrun

make failed, exit code 1

Gem files will remain installed in /Users/apple/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/rinku-2.0.6 for
inspection.
Results logged to
/Users/apple/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/extensions/x86_64-darwin-20/3.0.0/rinku-2.0.6/gem_make.out

〜省略〜

An error occurred while installing rinku (2.0.6), and Bundler cannot continue.

```

<br>

## 解決方法
[こちらの記事](https://qiita.com/kooohei/items/6aada548eeb785dd2c91)を参考にさせていただき、下記を実行
```terminal:terminal
% xcode-select --install
```
ポップアップが出てくるので、同意してインストール✅

<br>

インストールが終わった後、再度```bundle install```すると無事できました〜🎉


<br>


## 原因
macOSアップデート後に出ることが多いらしいです。

## 最後に
```Gem::Ext::BuildError: ERROR: Failed to build gem native extension.```の解決法に関する記事が少なく、かなり苦戦したため本記事を執筆しました！
この記事が多くの悩める方に届けば幸いです🌱
新人プログラマの方におすすめしたい技術書5選

この記事は「新人プログラマ応援 - みんなで新人を育てよう！」イベントの参加記事です。

https://qiita.com/official-events/3f21c92121aa125807b4

# はじめに

この春から3年目になったので、今まで読んだ技術書のうち特に**入門書としておすすめしたい本5冊**を（独断と偏見で）まとめました！

# ネットワーク: 「３分間ネットワーク基礎講座」

https://www.amazon.co.jp/dp/4774143731

ネットワークの各階層を、物理層から順番に解説した本です。1単元が短く、説明も対話形式なのですらすら読めると思います。

入社したては「ネットワーク、HTTP以外何も知らない :fearful: 」状態だったので、会議中にいつでも開けるように手元に置いていました。

姉妹本もおすすめです。

https://www.amazon.co.jp/dp/4774157376

https://www.amazon.co.jp/dp/4774138630

# 実装: 「リーダブルコード」

https://www.amazon.co.jp/dp/4873115655

「**コードは他の人が最短時間で理解するように書かなければならない**」をスローガンに、読みづらい/誤解されるコードを改良する方法を紹介しています。

実装したら立ち止まって「実装を知らない人がこの名前を見たらどんな機能を想像するかな？」と考えるクセがつきました。

# API設計: 「Web API the good parts」

https://www.amazon.co.jp/dp/4873116864

「利用者が使いやすいAPIを設計するには？」を解説した本です。URI、メソッド、ステータスコードにどのような意味を込めるべきかのお作法がまとめられています。API設計の話し合いでも引用されます。

# チーム開発: 「レガシーコードからの脱却」

https://www.amazon.co.jp/dp/4873118867

コードを価値の高い状態に保つための取り組みについてまとめた本です。
「なぜPRはすぐマージしたほうがいいの？」「なぜストーリーは短いほうがいいの？」など、OJTで初めてチーム開発に参加したときの疑問に答えてくれました。

# 設計: 「UNIXという考え方」

https://www.amazon.co.jp/dp/4274064069

UNIXコマンドの美学についてまとめた本です。全体を通じて、たくさんの機能を持ったツールを1つ作るより、単機能のツールを組み合わせるほうが上手くいくことを伝えています。

システムに自前機能を足したい欲求にかられたときは、この本を思い出して「他との組み合わせで代用できないか？」と考えるようにしています。

# 番外編

入門向け技術書ではありませんが、おすすめしたい本をあと2冊紹介します。

## コンテナの歴史？: 「コンテナ物語」

https://www.amazon.co.jp/dp/B07Z4DNFG7

「コンテナ」といっても、Dockerではなく荷物を詰める箱のほうの話です。コンテナで流通革命を起こしたマクリーン社の盛衰を描いたノンフィクション小説です。

荷物の形を統一することで港が自動化、大規模化した点や、業界の規格統一で独自規格の先駆者がかえって不利になるところ等、(ITの)コンテナで起きている歴史と鏡写しになっていると感じました。

## 個人的イチ押し: 「Go言語でつくるインタプリタ」

https://www.amazon.co.jp/dp/4873118220

1冊かけて、オリジナルのプログラミング言語を1から作る方法を紹介しています。この本の写経で**Go言語を覚え、プログラミング言語の動作原理を学び、テスト駆動開発(TDD)を知りました**。一石三鳥の本です！

通読するには3週間ほどかかりました[^1]が、長期休暇等時間があるときに挑戦してみてはいかがでしょうか？

# おわりに

以上、おすすめしたい本5(+2)選でした。今後も本を読んで新しい考え方を身に着けていきたいと思います。
最後までお読みいただきありがとうございました！

[^1]: この本は、~~無限に時間がある~~学生時代の夏休みに読みました。
JavaScriptのmatchメソッドでマッチした文字列を取得する際のエラー回避

# 前提
JSで文字列の一部をパターン指定で抽出する際、matchメソッドを用いる。
このmatchメソッドの返り値は以下の2通り。
- マッチした場合 : `Array`
- マッチしなかった場合 : `null`

参考：[String.prototype.match() - JavaScript - MDN Web Docs](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/match)

# やりたいこと
マッチ結果の配列ではなく、該当した文字列を直接取得したい。
とりあえず次のようなコードを書いた。

```javascript
const result = 'abc123XYZ'.match(/[0-9]{3}/)[0] // '123'
```

しかし、文字列の中に指定パターンが存在せずマッチしなかった場合、null[0]のような形になってしまい、エラーになる。
```TypeError: Cannot read properties of null```


# 正直な記述
matchメソッドの返り値を一度仮の変数に格納し、ifで分岐する

```javascript
const temp = 'abc123XYZ'.match(/[0-9]{3}/)
let result
if (temp) {
  result = temp[0]
} 
```

この解決方法はあんまりイケてない。
何度も使う場合には関数にして呼び出せばまだよいかもしれないが。

また、三項演算子を使うにしても、同じmatchメソッドを2度行うような形になってしまう。

そこで今回はよりスマートな記述方法は無いかなと考えてみた。


# 解決方法
## 01: オプショナルチェーン
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Optional_chaining

```javascript
const resultMatched = 'abc123XYZ'.match(/[0-9]{3}/)?.[0] // '123'
const resultUnmatched = 'abcXYZ'.match(/[0-9]{3}/)?.[0] // undefined
```

メリットは、ワンライナーで記述できる上、可読性を考えてもまあまあ。
また、キャプチャグループを使って抽出したい場合も添え字を[1], [2]と変えれば対応できる。

## 02: Null合体演算子
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator

```javascript
const [resultMatched] = 'abc123XYZ'.match(/[0-9]{3}/) ?? [] // '123'
const [resultUnmatched] = 'abcXYZ'.match(/[0-9]{3}/) ?? [] // undefined
``` 

オプショナルチェーンを使うよりも若干読みづらい？同じくらいか？
キャプチャグループを使う場合は`[, result]`のように書く必要がある。
※読み手が左辺の宣言時点で認識できるよ、という言い分はあるかも？


# 最後に
ES20xxの新機能としてこれらの手法を知ってはいたものの、初めて実際にコードとして書くことができた。
その他もっと分かりやすいやり方がないかは検討します。
【SQL】内部結合と外部結合のこと

内部結合や外部結合について学んだことを備忘録として書き留めます。<br>
# 前提のテーブル

##### usersテーブル
| id | name | message_id |
|:-:|:-:|:-:|
| 1 | hoge | 2 |
| 2 | huga | 3 |
| 3 | foo | NULL |
| 4 | var | 1 |
| 5 | piyo | 2 |

##### messagesテーブル
| id | content |
|:-:|:-:|
| 1 | おはよう |
| 2 | こんにちは |
| 3 | こんばんは |
| 4 | おばんです |

# 内部結合

##### SQL実行
内部結合にはINNER JOINを使います。
```SELECT * FROM users INNER JOIN messages ON users.message_id = messages.id;```


| id | name | messages_id | id | content |
|:-:|:-:|:-:|:-:|:-:|
| 1 | hoge | 2 | 2 | こんにちは |
| 2 | huga | 3 | 3 | こんばんは |
| 4 | var | 1 | 1 | おはよう | 
| 5 | piyo | 2 | 2 | こんにちは |

この時、テーブル内のINNER JOINの条件に一致しないレコード（この場合、usersテーブルのid:3のレコード）は削除されます。

内部結合をすることで一つのテーブルになっているので
```SELECT users.id, users.name, messages.content FROM users INNER JOIN messages ON users.message_id = messages.id;```

| id | name | content |
|:-:|:-:|:-:|
| 1 | hoge | こんにちは |
| 2 | huga | こんばんは |
| 4 | var | おはよう |
| 5 | piyo | こんにちは　|

こういった様に必要な要素だけのわかりやすいテーブルを出力することができます。

# 外部結合
外部結合はLEFT(RIGHT) OUTER JOINを使います。

左外部結合、右外部結合があり、
どちらのテーブルを主として結合するかによって使い分けます。

そして前述の内部結合と違い、
一致しないレコードは削除されず、その対応する値が無い場合にはNULLが入ります。
#### 左外部結合

```SELECT * FROM users LEFT OUTER JOIN messages ON users.message_id = messages.ID;```

| id | name | message_id | id | content |
|:-:|:-:|:-:|:-:|:-:|
| 1 | hoge | 2 | 2 | こんにちは |
| 2 | huga | 3 | 3 | こんばんは |
| 3 | foo | NULL | NULL | NULL |
| 4 | var | 1 | 1 | おはよう |
| 5 | piyo | 2 | 2 | こんにちは |

内部結合では削除されてしまうレコードも利用する必要がある場合はこちらを使うイメージです。

#### 右外部結合

 ```SELECT * FROM users RIGHT OUTER JOIN messages ON users.message_id = messages.ID;```

| id | name | massage_id | id | content |
|:-:|:-:|:-:|:-:|:-:|
| 1 | hoge | 2 | 2 | こんにちは |
| 2 | huga | 3 | 3 | こんばんは |
| 4 | var | 1 | 1 | おはよう | 
| 5 | piyo | 2 | 2 | こんにちは |
| NULL | NULL | NULL | 4 | おばんです |

このように内部結合、左外部結合とは違い、
右側に結合するテーブルの値を主としてSELECT文を出力することができます。

## 締め
<br>
これらを使い分けて、楽しいSQLライフを送りましょう！

<br>
<br>
令和4年春基本情報技術者試験 不合格になったけどサイコー！なお話

基本情報技術者試験午前試験で落ちてしまったので、試験を受けてみての振り返りを書いていこうと思います。

## 勉強した期間と使用した教材
週５日の頻度で１時間~2時間位を約３ヶ月間。
午前勉強の参考書はキタミ式の本を使い、１ヶ月目で読み終わっていた。
２ヶ月目から３ヶ月目に関しては基本情報試験過去問道場を直近４年分（８回)と基本情報技術者パーフェクトラーニング過去問題集を行なっていました。

## 試験の結果
80問のうち48問の60%正解で合格ですが、100％換算で56.25％の不合格。
合格まであと2問足りないという結果で終わりました。

ストラテジ系が70％
マネジメント系60%
テクノロジ系50%でした。

## 試験を受けてみての感想
令和2年からCBT方式に変わり、試験内容の情報を公に出来なくなリました。
その為詳しい事は言えませんが、個人的には聞いた事ない単語が多く、聞いてた話と少し違うぞ?という状況に陥りました。

過去問と参考書の内容を一語一句理解していれば60点はなんとかなると数字だと思うのですが、この1,2点で不合格になったのは惜しい様で大きな壁だなぁと凄く感じました。
もし、もう一度受験するなら参考書を丸々読み直して過去問10年分解くと思います。

試験をリベンジするかはもう少し考えますが、学べた事も多くありました。

## 基本情報技術者試験を通して良かった事
勉強習慣とITの基本的な知識が前より身についた事。
特に勉強習慣については大きい収穫だと思っていて、試験が終わっても毎日勉強する習慣は変わらないと思っています。

まぁ習慣代に7500円払ったと思えば安いものですよね？（と思いたい）

悔しいけど受かる人が一定数いる以上、努力不足でしかないと認めるしかないです！
気を取り直して、これからも勉強頑張ろうと思います。

基本情報落ちたけどサイコー！なお話でした！
Javaプログラミングにおけるストリーム



## ストリーム (プログラミング)とは
メモリ領域やファイル、ネットワークに記載・格納されたデータを読み取る、  
反対にそれらにデータを書き込むためのオブジェクトや、そのための機能を持つデータ型。  
接続や切断、書き込みや読み込みなどを簡易な操作で行える。  

## InputStream／OutputStream
Javaのストリームオブジェクトで
データをバイナリ形式で読み取り／書き込みを行う。  

必ずしもバイナリデータをやり取りするわけではなく、  
FileOutputStreamなど、ファイルへの文字の書き込みをバイナリで行う事もできる。  

## バッファリング
ストリームオブジェクトがストリーム処理を、  
一定のデータ量でまとめて行う事で、処理性能を上げられる機能。  
バッファリングをしない場合、ストリームは１バイトずつ行われるが、  
バッファリングをすることで、ストリームを最大1024バイトずつ行える。  
Javaでは、BufferedOutputStreamクラスがバッファリング機能を提供している。  

## Writer／Reader
Javaのストリームオブジェクトで
文字列データの形式で読み取り／書き込みを行う。  

## PrintWriter
サーブレットがクライアントにデータ本文を送るためのストリームオブジェクト。  
Writer抽象クラスの具象クラス。  
コンテンツタイプに設定されている文字セットを使ってエンコーディングする。    
デフォルトの文字セットは「ISO-8859-1(Latin1)」で、日本語が文字化けするため、  
「setContentType」メソッド又は「setCharacterEncoding」メソッドで文字コードを設定する必要がある。

https://www.javadrive.jp/servlet/response/index3.html

二つのメソッドはsetCharacterEncoding() は引数に文字コードのみを指定するのに対して、setContentType() は引数にMIME形式とともに文字コードを指定する違いがある。  

MIMEタイプは、WEBサーバーとWEBブラウザの間でデータの形式を指定する方法。  
人間やアプリケーションの拡張子のようなもの。  
以下のようなものがある。 

https://www.tohoho-web.com/wwwxx015.htm

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2527601/82560453-7636-8d37-eb22-d1f811aa8f2e.png)
next.jsでpages配下にstyleファイルがあるとビルドに失敗する時の対処法

## 概要
page 内に style.ts ファイルを配置する形で開発をしていて、 build 時に以下のようなエラーが起きたので対処法をメモしておきます。
(style.ts　には styled-components で定義したスタイルがある)

```terminal
Build optimization failed: found page without a React Component as default export in 
pages/s/create/index.style
```

![スクリーンショット 2022-04-16 13.41.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442365/af220174-60d9-2e68-12ba-8cf908e9789e.png)



## 対処法

どうやらデフォルトの設定だと、pages 配下にある `'tsx', 'ts', 'jsx', 'js'` ファイルが page として認識されるようです。
そこで next.config.js の pageExtensions を以下のように上書きする事で style ファイルをページ対象外に設定する事が出来ます。

```next.config.js
module.exports = {
  pageExtensions: ['jsx', 'tsx'],
}
```

## 参考にした記事

next.config.js: Custom Page Extensions | Next.js
https://nextjs.org/docs/api-reference/next.config.js/custom-page-extensions#including-non-page-files-in-the-pages-directory
Storybookでちょっとしたスタイルを当てたいときはDecoratorsを使う

## この記事の概要

Storybookを使っている中で「余白を広げたい」「このコンポーネントのときだけ背景色が欲しい」といった場面はあると思います。
今回はReact + Storybookで上記を実現する書き方を記事にしました。

また、新人プログラマ応援イベントに投稿する記事でもあります。

https://qiita.com/official-events/3f21c92121aa125807b4

## Decoratorsとは

公式ドキュメントはこちらです。（左のナビゲーションから、React以外での書き方にも飛べます）

https://storybook.js.org/docs/react/writing-stories/decorators

マークアップを追加したり、`ThemeProvider`などを通じてスタイルを与えたりといった使い方ができます。

:::note warn
理屈の上では複雑なレイアウトやスタイルも当てられますが、まず間違い無くややこしくなります。
あくまで「コンポーネントカタログとして少しだけ見やすくする」ような使い方が良いと思います。
:::

## 使い方

### 個別のコンポーネントにスタイルを当てる

通常のStoryは以下のようなコードです。

```javascript:Button.stories.jsx
    import React from 'react';
    import { Button } from './Button';

    export default {
      title: 'Button',
      component: Button,
    };

    const Template = (args) => <Button {...args} />;

    export const Primary = Template.bind({});
```

Decoratorsを追加すると、Storyをwrapしてスタイルを当てられます。

```diff_javascript:Button.stories.jsx（Decorators追加後）
    import React from 'react';
    import { Button } from './Button';

    export default {
      title: 'Button',
      component: Button,
    };

    const Template = (args) => <Button {...args} />;

    export const Primary = Template.bind({});
+   Primary.decorators = [
+     (Story) => (
+       <div style={{ margin: '3em' }}>
+         <Story />
+       </div>
+     ),
+   ];
```

### Storybook全体にスタイルを当てる

個別の`stories`ではなく、`.storybook/preview.js`を変更します。

[インストール用のドキュメント](https://storybook.js.org/docs/react/get-started/install)に沿って`npx sb init`を実行していたとすると、`preview.js`は以下のようになっていると思います。

```javascript:.storybook/preview.js
  export const parameters = {
    actions: { argTypesRegex: '^on[A-Z].*' },
    controls: {
      matchers: {
        color: /(background|color)$/i,
        date: /Date$/,
      },
    },
  }
```

先ほどとほぼ同じ書き方ですが、このように変わります。

```diff_javascript:.storybook/preview.js
+ import React from 'react';

+ export const decorators = [
+   (Story) => (
+     <div style={{ margin: '3em' }}>
+       <Story />
+     </div>
+   ),
+ ];

  export const parameters = {
    actions: { argTypesRegex: '^on[A-Z].*' },
    controls: {
      matchers: {
        color: /(background|color)$/i,
        date: /Date$/,
      },
    },
  }
```

Storybook内に`reset.css`的な役割のスタイルを定義するのにも使えるでしょう。

---

最後まで読んでくださってありがとうございます！
Twitterでも情報を発信しているので、良かったらフォローお願いします！

https://twitter.com/xrxoxcxox
「ゼロからVue3を」Vue3+vite+ElementPlusで環境構築

# 概要
今回はVue.jsのデフォルトバージョンになる「Vue3」を用いて、ゼロから一つの管理システムを作ると思います。
UIフレームワークについて、Vue3バージョンのVuetifyはリリースされてないから、ElementPlusにします。
Typescriptは「型宣言」なので、エラーやバグを未然に防止できるし、開発効率も上がります。
viteの起動が非常に早い～

- 個人ブログ：[https://r-ataka.github.io/](https://r-ataka.github.io/)

# 環境
Node.jsとnpmバージョン
```
node v14.17.1
npm 6.14.13
```
# create viteでプロジェクト作成
参考：[公式サイト](https://ja.vitejs.dev/guide/#%E6%9C%80%E5%88%9D%E3%81%AE-vite-%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%82%92%E7%94%9F%E6%88%90%E3%81%99%E3%82%8B)
`npm -v`でnpmのバージョンを確認する
下記のコマンドで、プロジェクト作成
```sh
# npm 6.x 
# npm create viteバージョン プロジェクト名 --template テンプレート
npm create vite@latest mtool --template vue-ts
# npm 7+ は追加で 2 つのダッシュが必要:
npm create vite@latest my-vue-app -- --template vue
```

プロジェクトのmtoolが作成されました。
下記はコマンドを実行した結果
```
npx: installed 6 in 3.147s
Scaffolding project in C:\files\workspaces\vue3\mtool...
Done. Now run:
  cd mtool
  npm install
  npm run dev
```
次のコマンドにより初期化
```sh
# プロジェクトのフォルダーに移動する
cd mtool
# ライブラリをインストールする
npm install
# Vueを動かす
npm run dev
# npm run devの結果、ブラウザーにURLを開く
  vite v2.9.1 dev server running at:

  > Local: http://localhost:3000/
  > Network: use `--host` to expose

  ready in 227ms.
```
![viteapp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2606053/5cc783b9-b124-1968-b3bf-53272d8aeda7.png)

# ElementPlus
上記の手順により、Vue3が起動しました。
次はUIフレームワークのElementPlusを導入する。
参考：[公式サイト](https://element-plus.org/en-US/guide/quickstart.html#on-demand-import)

## インストール
```sh
# cd <プロジェクトのフォルダー>
npm install element-plus --save
```
### フルインポート
バンドルサイズをあまり気にしない場合は、フルインポートを使用する方が便利です。
参考:[公式サイト](https://element-plus.org/en-US/guide/quickstart.html#usage)
### 配置(オートインポート)
先ずは二つのプラグインをインストールする
```sh
# `components.d.ts`が作成されて、自動インポートのコンポーネントはこちらに宣言されます。
npm install -D unplugin-vue-components unplugin-auto-import
```
次は`vite.config.ts`を編集する
```vite.config.ts
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'

export default {
  plugins: [
    // ...
    AutoImport({
      resolvers: [ElementPlusResolver()],
    }),
    Components({
      resolvers: [ElementPlusResolver()],
    }),
  ],
}
```
### 使い方
```test.vue
<template>
  <el-button type="primary">
    ボタンです
  </el-button>
</template>
```
## icon
### インストールと配置
ElementPlusのiconとオートインポートのプラグインをインストールする
```sh
npm install @element-plus/icons-vue
npm i -D unplugin-icons
```
`vite.config.ts`を編集する
```vite.config.ts
import Icons from 'unplugin-icons/vite'

export default defineConfig({
  plugins: [
    // ...
    Icons({ compiler: 'vue3' }),
  ],
})
```
### 使い方
```test.vue
<template>
  <el-button type="primary">
    <el-icon size="22" color="#ff0000"><Expand /></el-icon>test
  </el-button>
</template>
<script setup lang="ts">
import { Expand } from '@element-plus/icons-vue'
</script>
```
## 結果
![viteapp2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2606053/d4c099bc-eb5e-2b00-7f94-673c28f6156a.png)
Puppeteer で button を click しても効かないときに試したこと

現場でWebスクレイピングする機会がありました。
pupteer を使っていくなかで詰まったことがあったので、もし同じ状況で詰まっている人がいれば、参考になるかもしれません。

今回``click()``メソッドが期待する動作をしなかったので、その時の状況と解決策を書いていきます。

## 開発環境
- Windows10 version: 21H2
- Node.js   version: v16.14.1
- Puppeteer version: 5.5.0

## 原因
- セレクタが間違っている
- ブラウザを開いているが、``--window-size``に問題がありクリックするボタンが表示されていない
- クリックする要素が表示される前に``click()``が実行されてしまっている
- なぜか``click()``が使えない　※後述します。

おそらくクリックが効かない原因のほとんどは、該当すると思います。
期待する動作にならないなら、まずはこのあたりをしっかり確認すると解決するかもしれません。

### セレクタが間違っている
まず最初に確認してみましょう。
ここが間違っていると、どんなに他の原因を探っても解決しません。

クリックに限りませんが、Webスクレイピングでうまく要素を取得できない場合は、だいたいセレクタに問題があると思います。
``console.log``などを仕込んで、ちゃんとボタンを指定できているか確認しましょう。

### ブラウザを開いているが、``--window-size``に問題がありクリックするボタンが表示されていない
今回私が詰まった原因です。
ほとんどのサイトがレスポンシブ対応しているので、Puppeteer で開いているブラウザのサイズはしっかり確認しておきましょう。

Puppeteer では、ブラウザの設定を下記の方法で設定できます。
``headless: false``は、ブラウザをヘッドレスモードで実行するかどうかを設定します。

デフォルトでは``true``となっているので、ブラウザが開けているか、要素をクリックできているか、ページ遷移の状況などを確認するために、開発時には``false``と設定するとよいでしょう。
```javascript:(例) item.js
 const browser = await puppeteer.launch({
   headless: false,
   ignoreHTTPSErrors: true,
   args: [`--window-size=1920,1080`],
   defaultViewport: {
     width: 1920,
     height: 1080
   }
 });
```
その他のオプションの設定は、ドキュメントを参考に設定してみてください。
[Puppeteer](https://pptr.dev/#?product=Puppeteer&version=v13.5.2&show=api-puppeteerlaunchoptions)

### クリックする要素が表示される前に``click()``が実行されてしまっている
Puppeteer には、多くの``waitFor``メソッドがあります。

``waitForSelector()``や``waitForTimeout()``を使って、クリックしたい要素が出現するまで、プログラムの実行を止めましょう。
期待する値がとれない場合や、期待する動作をしない場合は``waitFor``が不足している可能性もあります。

### なぜか``click()``が使えない
調べたところ、**Puppeteer で開いたブラウザに、要素が表示されていない場合、エラーになる**ことがあるようです。
つまり、``click()``メソッドは、開いたブラウザに、要素（ここではボタン）が表示されるまでスクロールなどをしないといけないようです。

例えば、ページネーションのボタンをクリックしたいとき、多くのサイトがページ下部に設置されていると思います。
そのため Puppeteer でブラウザを開いただけだと、ページネーションのボタンが表示されていないと判定され、「クリックする要素が見つからない」というエラーが出るのだと思います。
（私の環境だと発生しました）

ではどうすればいいのか？

私は下記の方法を使って解決しました。
```javascript:(例) item.js
// ページが表示されるまで待つ
await page.waitForSelector(ITEM_PAGE_QUERY);
// ボタン要素を取得する
const nextPageButton = await page.$(NEXT_PAGE_QUERY);
await nextPageButton .evaluate(b => b.click());
```
``evaluate()``メソッドを使用する方法です。
stackoverflow の下記の質問がよくまとまっているので、参考にするとよいでしょう。
[Puppeteer in NodeJS reports 'Error: Node is either not visible or not an HTMLElement'](https://stackoverflow.com/questions/51857070/puppeteer-in-nodejs-reports-error-node-is-either-not-visible-or-not-an-htmlele)

## まとめ
- セレクタが間違っていないか確認する
- 開いているブラウザサイズに問題がないか確認する
- クリックする要素が表示される前に実行していないか確認する
- ``evaluate(b => b.click());``を使ってみる

Puppeteer クリックで詰まっている人の参考になると嬉しいです！
また、間違っている情報などありましたら、ご指摘いただけると幸いです。
Vuetifyをインストールするとエラーが出た!

## Vue2.6をマニュアルでインストールした時に起きた現象!
最初から、Vuerouter、Vuexをインストールして、Vuetifyをインストールすると、Component name "Home" should always be multi-word  というエラーが出た!

設定を追加するとnpm run serveできた!

vue.config.js
```javascript
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  lintOnSave: false, // 追加
  transpileDependencies: [
    'vuetify'
  ]
})
```

![スクリーンショット 2022-04-16 13.26.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2303722/a9676c7b-ff5e-7276-b1f2-fe63b27c970e.png)

**以前はこんなこと起きなかったような?**
VB.NETで改行

VB.NETの現場でコードの途中で改行する場合に` _`を行末に入れて改行をするのをよく見かけたが、使わなくてもC#程自由ではないけれど、そこそこ改行できるのでまとめてみた。
基本的に演算子の直後に改行が可能。
空行は含められない。

## 引数
`(`、`,`の後、`)`の前で改行が可能　

```vb:
Private Sub Main()
    Dim name = GetFullName(
                           "John",
                           "Doe"
                          )  
End Sub

Private Function GetFullName(
                             ByVal firstName As String,
                             ByVal lastName As String
                             ) As String

    Return firstName & " " & lastName As String
End Function
 
```

## 配列
`{`、`,`の後、`}`の前で改行が可能
```vb
Dim names() = {
               "John",
               "Doe"
               }
```

## 代入
`=`の後に改行が可能

```vb
Dim name =
    "John Doe"

Dim age As Integer =
    30
```

## 四則演算、文字列の結合
算術演算子や`&`の後に改行が可能
```vb
Dim age = 30 +
    1
Dim name = "John" 
name &=
    " " &
    "Doe"

```


## 条件式
比較演算子や論理演算子の後に改行が可能
`Not`の後は改行できない

```vb
Dim name = "John Doe"
Dim age = 30

If name <> 
    "" AndAlso
   age >=
   20 Then

    Console.WriteLine(name)
End If
```

## For Each
`In`の前後で改行が可能
```vb
Dim names = {"Jone", "Jane"}
For Each name
         In
         names

    Console.WriteLine(name)
Next
```

## プロパティ、メッソド
`.`の後に改行が可能
```vb
Dim john As New Person("John", "Doe", 30)
Console.WriteLine(john.
                  FullName)

Console.WriteLine(john.
                  Age.
                  ToString())
```

## LINQ クエリ式
```vb
Dim people As New List(Of Person)({New Person("John", "Doe", 30), New Person("Jane", "Doe", 20)})

Dim FullNameList = From
                        person
                        In
                        people
                    Where
                         person.Age >=
                         20 AndAlso
                         person.LastName =
                         "Doe"
                     Select
                         person.FullName
```
容量無制限Dropboxで容量無制限Imgurを作る

<p class="codepen" data-height="720" data-default-tab="result" data-slug-hash="dyJQOrR" data-user="04" style="height: 720px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/04/pen/dyJQOrR">
  Dropbox</a> by John Doe (<a href="https://codepen.io/04">@04</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>


https://forest.watch.impress.co.jp/docs/news/1403040.html

Dropboxが容量無制限になったので実質容量無制限の画像共有サイト作ってみました
ファイルをアップロードして、共有リンクを作成できます。

```javascript
async function uploadFile(file) {
  const now = new Date()
    .toLocaleString("sv")
    .replace(" ", "_")
    .replaceAll(":", "_");
  const path = "/" + now + "-" + file.name.replace(/[^\x00-\x7F]/g, "");
  await fetch("https://content.dropboxapi.com/2/files/upload", {
    body: file,
    method: "POST",
    headers: {
      "Content-Type": "application/octet-stream",
      "Dropbox-API-Arg": JSON.stringify({ path }),
      Authorization: "Bearer " + TOEKN
    }
  });
  const res = await fetch(
    "https://api.dropboxapi.com/2/sharing/create_shared_link_with_settings",
    {
      body: JSON.stringify({
        path,
        settings: {
          access: "viewer",
          allow_download: true,
          audience: "public"
        }
      }),
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: "Bearer " + TOEKN
      }
    }
  ).then((r) => r.json());
  return res.url
    .replace("www.dropbox.com", "dl.dropboxusercontent.com")
    .replace(/\?dl=0$/, "");
}
```

### アクセストークンの作り方

#### リンクを開きます
[https://www.dropbox.com/login?cont=https%3A%2F%2Fwww.dropbox.com%2Fdevelopers%2Fapps%3F_tk%3Dpilot_lp%26_ad%3Dtopbar4%26_camp%3Dmyapps](https://www.dropbox.com/login?cont=https%3A%2F%2Fwww.dropbox.com%2Fdevelopers%2Fapps%3F_tk%3Dpilot_lp%26_ad%3Dtopbar4%26_camp%3Dmyapps)

#### アプリを作成し、Permissionsにチェックをいれます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/50a4ebf6-481e-ce76-719c-ed89cbae5687.png)

#### Settingsでアクセストークンを生成する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208363/b0b3ccb0-d133-bd2f-cbdd-9bf303347596.png)
ESP32-WROOM-32DでEEPROMを使う

# 概要
同様のページは多くあるものの、データの保存について図で説明したものが見つからなかったので投稿した。
(一度理解してもしばらくすると忘れてしまうので。。。)
ESP32のEEPROMの仕組みについては詳しく調べていないので省略。
Flashに疑似EEPROMとして使えるような領域を確保してデータを保存しているらしい。

# 実行環境
MCU：LOLIN D32
IDE：Arduino IDE 1.8.19

よく使われているESP32-DevkitCの在庫がなかったため、LOLIN D32で代用。
回路はほぼ同じなので、同じ設定とプログラムで動作するはず。

# 参考サイト
https://web.is.tokushima-u.ac.jp/wp/blog/2019/03/09/esp32-arduino-eeprom%E3%82%92%E4%BD%BF%E3%81%86/

# サンプルコード
リセットするたびにシリアルで出力される数値が1ずつ増えるプログラム。
EEPROMの初期化を行わずに読み出しをしているので0以外の値からスタートする可能性があるが、
見た目的にわかりやすいのでこのように書いた。
char変数はシリアル通信で送るとASCIIコードとして認識されるので、わかりやすいよう明示的に10進数で出力している。

```c++
#include <EEPROM.h>
int a;
float b;
char c;

void setup() {
  /* 初期設定 */
  Serial.begin(115200);
  EEPROM.begin(9);  //(4+4+1)バイト

  /* EEPROM読み出し */
  EEPROM.get(0, a);
  EEPROM.get(4, b);
  EEPROM.get(8, c);

  /* 読み出した内容を出力 */
  Serial.println(a);
  Serial.println(b);
  Serial.println(c, DEC);

  /* 値を変更 */
  a += 1;
  b += 1.0;
  c += 1;

  /* EEPROM書き込み */
  EEPROM.put(0, a);  //書き込み内容を設定
  EEPROM.put(4, b);  //書き込み内容を設定
  EEPROM.put(8, c);  //書き込み内容を設定
  EEPROM.commit();   //EEPROMに書き込み
}

void loop() {

}
```

# 解説
## データ保存のイメージ図
今回はArduinoでよく使うint型、float型、char型を保存した。
データを保存したときのイメージは下のようになる。
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321914/3c26b48f-1325-2013-1e1e-e0e282603dcd.png)
例えば、下の文はEEPROMのアドレス0からint型(=4バイト)のデータを保存する、という意味になる。(aはint型で定義されているため)

```c++
  EEPROM.put(0, a);
```

別データの保存場所と被ってしまうとデータの一部が壊れてしまうため、私はエクセル等で表にして視覚的に管理している。
また変数型のデータサイズはマイコンの型式によって異なるため、ほかのArduinoからプログラムをコピペする際は注意する。

Flash容量に余裕があるのであれば、絶対に被らないようにアドレスを8バイト以上離して保存するのも有効。
その場合は間の空白部分も含めて```EEPROM.begin```で領域確保が必要。

## 配列からEEPROMに書き込む
詳細は参考サイトを参照。
配列の数だけ領域を確保する必要がある。
pythonのライブラリの方が実行が早い！？(timeライブラリ)

「pythonのライブラリを使用した方が、計算時間が早くなる」というのを聞いたことがあります。
簡単なコードで、ライブラリを用いた方が計算時間が早いのかどうか検証したいと思います。
timeライブラリを使って、計算時間を計測します。
```
# 必要なモジュールをインポートする。
import time 
import numpy as np
```
「1~10001の合計値を計算する」という内容で計算時間を比較したいと思います。
```
# 1~10001の値が入った配列を用意
number = np.arange(1,10001)

# 合計値を計算する
s = 0
for i in range( len(number) ):
    s += number[i]
```
実際に時間を測ってみます。
```
start = time.time()

for i in range( len(number) ):
    s += number[i]

end = time.time()

execution_time = end-start
```
実行時間は、スペックなどで左右されますが、$6.6×10^{-3}$かかりました。

次にpythonのsum関数を使って同様の計算を行います。
```
# 合計値を計算する
number.sum()
```
実際に時間を測ってみます。
```
start = time.time()
number.sum()
end = time.time()

execution_time = end-start
```
実行時間は、$4.4×10^{-4}$でした。
ライブラリを用いた方が14倍くらい早いです。
PythonをGlue3.0で実行する方法

# はじめに
AWS GlueでPythonを動かそうと思い「Python Shell script editor」をポチッと選択してみたら、なんとGlueのバージョンが選べず、Glue3.0ではなく1.0で動かすしかなかった。
Glueバージョンを選択したうえでPythonを動かす方法を見つけたので共有します。

と言ってもめっちゃ簡単な話なので簡潔にお話しします。

# 今回の問題
GlueStudioのJobsメニューでPythonジョブを作ろうとすると、「Python Shell script editor」を選びたくなる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599140/dedafade-6792-8ec9-7dd6-8ca3373d6e3f.png)

実際に作ってみると、Glue versionが空になっている。この場合、実際にはGlue1.0が動くらしい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599140/89577d10-c259-edf5-7120-8b858122b0db.png)

ジョブの詳細を見てみると、Python3.6になっている。ここは変更不可。Glue2.0以降はPython3.7になる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599140/fcbb4fee-3925-f5aa-77f7-d0bff1469b85.png)


# 解決策
「Visual with a source and target」を選択してジョブを作成する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599140/b5407a73-4ed5-744c-8e36-19b1f005729b.png)

「Create」をクリックすると以下画面になるので、「Script」をクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599140/76235512-e5ad-16e2-9c8b-53c517ef90b2.png)

何やらエラーが出ているしScriptがロックされているが、臆せず「Edit Script」をクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599140/bd176031-45fd-dd81-deed-14fdccf9392e.png)

visual modeからscript-only modeに変更するともう後戻りはできないよ！という旨のメッセージが出るが、「Confirm」をクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599140/2c061e8f-3a9f-e299-56e1-43107b9fbe35.png)

Pythonコードが書けるようになる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599140/00be3f6c-e5ce-12f7-a893-ed0d782ea184.png)

Glueバージョンも0.9～3.0で選べる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599140/6ee0125a-4a8f-a91d-2271-620f743890a9.png)


# さいごに
Glue3.0でPythonを動かしたいときにちょっと迷ったので共有でした。
なんで「Python Shell script editor」でGlueのバージョン選べないのか分からないですが、、。
javaScriptでimport/exportするにはサーバーを立ち上げる必要があるなんて知らなかった話

# ことのはじめ

https://qiita.com/hideya670/items/57395a4edde5923c5c9f

以前にゲームの設計をして別のクラスを呼び出そうとした｡
progateとかでjavaScriptで別のクラスを読み込むにはimport/exportを使えば良いと習ったのでその通りにしたが`Unexpected token 'export'`とエラーを吐かれた｡

## そもそものjavaScriptの仕様
タイトルにもあるように､javaScriptでimport/exportをするには
* ローカルサーバーとかでもいいからサーバーを立ててそこにjavaScriptファイルを置く
* import/exportするファイルはHTMLで`<script src="jsファイルのurl" type="module"></script>`と書く必要がある

## 私がとった方法
参考にしたサイトではvscodeの`live server`を使っていたが
私はxamppを使ってサーバーを立てた

参考
--
https://hothukurou.com/blog/post-2851

https://qiita.com/TakamiChie/items/4d92c7e80a9d4cce0178
Vue.jsでelで指定したidの要素の子要素にさらにelで指定したidがある時

例えば下記の様に二つのvueコンポーネントを登録したjsファイルがある
```like.js

Vue.component('like-component', require('./components/Like.vue').default);

const like = new Vue({
    el: '#like',
});
```
```star.js

Vue.component('star-component', require('../components/Star.vue').default);


const star = new Vue({
    el: '#star',
    
});

```

これらを一つのテンプレートで下記の様に読み込むとする
```app.blade.php
<section class="p-evaluation id="like">
         <!-- いいね処理したりするコンポーネント -->
         <like-component></like-component>

         <div class="card" id="star">
　　　　　　　　　　　　　　　　　　　　　　　　　<p class="card-title">商品名</p>
            <star-component></star-component>
　　　　　　　　　　　　　　　　　　　　　　　　<p　class="card-comment">コメント</p>
         </div>
</section>


```
これだと子要素の方のstar-componentは読み込まれずエラーになる。
正確には読み込まれてるが、親要素がコンパイルされた時にも子要素の部分が処理されてるのが
原因？
# [<font color="#333">解決策</font>](#-2.解決策)
子要素のコンポーネントにv-preを記述

```app.blade.php
<section class="p-evaluation id="like">
         <!-- いいね処理したりするコンポーネント -->
         <like-component></like-component>

         <div class="card" id="star">
　　　　　　　　　　　　　　　　　　　　　　　　　<p class="card-title">商品名</p>
　　　　　　　　　　　　　　　　　　　　　　　　　<!-- v-preを追加 -->
            <star-component v-pre></star-component>
　　　　　　　　　　　　　　　　　　　　　　　　<p　class="card-comment">コメント</p>
         </div>
</section>
```

これでOK。
意外とあっさり。
オブジェクトとクラスをjavaScriptとpythonで比べる


<h5>紛らわしいので、記事にして、アウトプットしておく。</h5>

<h2>クラスandインスタンス化</h2>

<h4>javaScript</h4>

```javascript
class Person {
  run() {
    console.log('run');
  }
}
const person = new Person();
person.run();
```

<h4>python</h4>

```python
class Person(object):
    def run(self):
        print("run")

person = Person()
person.run()
```

<h2>__init__とconstructor</h2>

<h4>javaScript</h4>

```javascript
class Person {
  constructor(name) {
    this.name = name;
  }
  run() {
    console.log(this.name);
    console.log('run');
  }
}
const person = new Person('Mike');
person.run();
```

<h4>python</h4>

```python
class Person(object):
    def __init__(self, name):
        self.name = name
    def run(self):
        print(self.name)
        print("run")

person = Person('Mike')
person.run()
```

<h2>継承</h2>

<h4>javaScript</h4>

```javascript
class Person {
  constructor(name) {
    this.name = name;
  }
  run() {
    console.log(this.name);
    console.log('run');
  }
}

class newPerson extends Person {
  talk() {
    console.log('talk');
  }
}

const new_person = new newPerson('Mike');
new_person.run();
new_person.talk();
```

<h4>python</h4>

```python
class Person(object):
    def __init__(self, name):
        self.name = name
    def run(self):
        print(self.name)
        print("run")

class newPerson(Person):
    def talk(self):
        print("talk")

new_person = newPerson("Mike")
new_person.run()
new_person.talk()
```

<h2>オーバーライド/super()</h2>

<h4>javaScript</h4>

```javascript
class Person {
  constructor(name) {
    this.name = name;
  }
}

class newPerson extends Person {
  constructor(name, age, gender) {
    super(name);
    this.age = age;
    this.gender = gender;
  }

  year() {
    console.log(this.name + this.age);
  }

  sex() {
    console.log(this.gender);
  }
}

const new_person = new newPerson('Mike', '18', 'man');
new_person.year();
new_person.sex();
```

<h4>python</h4>

```python
class Person(object):
    def __init__(self, name):
        self.name = name

class newPerson(Person):
    def __init__(self, name, age, gender):
        super().__init__(name)
        self.age = age
        self.gender = gender

    def year(self):
        print(self.name + self.age)

    def sex(self):
        print(self.gender)

new_person = newPerson("Mike", "18","man")
new_person.year()
new_person.sex()
```
【エラー対応】General error: 1215 Cannot add foreign key constraint【Laravel】

MySQLの外部キー制約を追加する際にエラーが出ました。
```
General error: 1215 Cannot add foreign key constraint
```
解決するのに30分程度も使ってしまったので、、、、対処方法をここにまとめます。

（環境：PHP8.0/Laravel/MySQL）

## 確認①：型の不一致

データ型があっていないと、同様のエラーが出ます。

- idの片側にunsignedがついている
- smaillintとtinyintをつなげようとしている

データ型を合わせるために、外部キーに指定するidを修正してみましょう。


## 確認②：Migrationファイルの順番は正しいか

今回のエラーの原因はこちらでした。

Laravelでは、CREATE TABLEを使わずにPHPで定義されたファイルを作成・実行して、MySQLにテーブルを作ります。
このとき、CREATE TABLEされる実行順は、日付の古い順になります。まだ生成されていないテーブルにリレーションを貼ろうとするとエラーになってしまうんです、、。

今回は解決方法として、ファイル名を変更（YYYY_MM_DD）して、順番を整理しました。
```
php artisan migrate:fresh
```
で、問題なく通りました。

## まとめ

```
General error: 1215 Cannot add foreign key constraint
```
今回のエラーが起きたら確認すること。

- データ型はあっているか
- migrationファイルの順番は正しいか

この記事が、誰かのエラー解消の時間削減につながれば幸いです...。
同一form内の押すボタンによってaction内容を変更する

## 概要
編集ページを作っている際に同じformタグ内に複数submitボタンが欲しい場合があったので、同一フォーム内で押すボタンによって、actionの内容を変更する方法を記載する

展開しやすいようにjQueryなどは使わず、素のJavaScriptで記載します。

## 実装イメージ

今回は同一ページ内に以下のようにbuttonタグを配置して、押したボタンによって指定のurlを叩くといった動作をさせます。

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308656/dabd8da7-0244-ba51-4e52-167392785485.png">

## 完成ソース

```html
<form method="POST" id="punchForm" action="/work-start">
  <button onclick=submitClick() data-action="/work-start">出勤</button>
  <button onclick=submitClick() data-action="/break-start">休憩開始</button>
  <button onclick=submitClick() data-action="/break-end">休憩終了</button>
  <button onclick=submitClick() data-action="/work-end">退勤</button>
</form>

<script>
function submitClick(){
    let elm       = event.target;
    let actionUrl = elm.getAttribute("data-action");
    document.getElementById("punchForm").action = actionUrl;
}
</script>
```

## 解説

まずはfromタグを作ります。
■ method
 呼び出すactionのリクエストに応じて指定します。今回はPOSTにしてます。
■ id
 どのformのactonを変更するのかJS側で指定する必要があるので、任意の名前をつけます
■ action
 書き換えるので、空欄でも大丈夫です。
```html
<form method="POST" id="punchForm" action="/work-start">
</form>
```

次にbuttonタグ
■ onclick
ボタンが押された時に指定のJSのメソッドを呼び出すようにするので、任意のメソッド名をつけます
■ data-action
ボタンを押した時に発動してほしいactionのURLを指定します。
ちなみにhtmlは「data-任意名」でカスタム属性が作れるので、data-actionというタグは私が勝手に命名したもので、任意の名称をつけても構いません。
[カスタム属性とは?](https://developer.mozilla.org/ja/docs/Web/HTML/Global_attributes/data-*)

```html
<form method="POST" id="punchForm" action="/work-start">
  <button onclick=submitClick() data-action="/work-start">出勤</button>
</form>
```

■ JavaScript
JSはまとめて下記のような動きになっています。
```javascript
function submitClick(){
    // クリックされた要素を取得
    let elm       = event.target;

    // クリックされた要素の中で、指定された属性の値を取得
    let actionUrl = elm.getAttribute("data-action");

    //　指定したidのaction属性の値を書き換える
    document.getElementById("punchForm").action = actionUrl;
}
```

以上となります。
参考になれば幸いです。
Rと統計 -その１ (平均、分散、標準偏差)-

# Rと統計 -その１ (平均、分散、標準偏差)-
本投稿は、統計に関連したRのコードをまとめたものになります。
(自分自身の備忘録の意味も込めて。。。)
なお、統計の詳しい概念や知識、Rの基本的なコードやその他のコードはあまり載せていませんので、他の投稿等でご覧いただけたらと思います。
今回は、平均、分散、標準偏差の3つをまとめていきます。

## 0. はじめに

### 使用する関数
今回使用する関数は以下の通りです。
・sum()：総和を求める
・length()：データの個数を求める
・mean()：平均を求める
・var()：分散を求める
・sd()：標準偏差を求める
・sqrt()：平方根をとる


### 使用するデータ

今回取り組むにあたって、以下のような架空の統計のテストの結果を使用します。

|受験番号|点数(10点満点)|
|:---:|:---:|
|1|5|
|2|9|
|3|10|
|4|2|
|5|7|
|6|8|
|7|1|
|8|5|
|9|4|
|10|3|

上記の統計テスト(statistics test)の結果を`stat_test`というオブジェクトに格納します。
```r
stat_test <- c(5,9,10,2,7,8,1,5,4,3)
stat_test
```

```:出力
 [1]  5  9 10  2  7  8  1  5  4  3
```

## 1. 平均
では、「0. はじめに」にある統計テストの結果の平均をRで求めてみましょう。
2通りのやり方を載せます。

### 方法① 関数sum()と関数length()を使う
まず初めは、`平均　＝　総和　/ データの個数`という平均の基本的な概念をそのままコードにします。
総和は関数`sum()`を、データの個数は関数`length()`を使用します。
それぞれの関数の括弧内にオブジェクト名を記入して、実行すればOKです。
今回は、`stat_test`オブジェクトの名前を記入します。
計算したものを`average1`というオブジェクトに格納してみます。
```r
average1 <- sum(stat_test) / length(stat_test)
average1
```
```:出力
 [1] 5.4
```
`5.4`という結果が得られました。

### 方法② 関数mean()を使う
もう１つの方法として、関数`mean()`を使うことができます。
関数`mean()`を使って計算したものを`average2`というオブジェクトに格納してみます。

```r
average2 <- mean(stat_test)
average2
```

```:出力
 [1] 5.4
```

`average1`と`average2`どちらも同じ出力になりました。

## 2.分散
続いて、分散(variance)を見ていきます。
分散は、ばらつきを表す指標です。
求め方としては、`(各データの値　- 平均)`を2乗し、それらを全て足したものを、`（データの個数 - 1）` で割ります。

`データの個数` で割ったものは分散、`（データの個数 - 1）` で割ったものは不偏分散といいます（統計学においては不偏分散が使われることが多く，不偏分散を単に分散と呼ぶことが多いようです）。

```r
variance1 <- sum((stat_test - average1)^2) / (length(stat_test) - 1)
variance1
```

```:出力
[1] 9.155556
```

Rでは、関数`var()`を使えば簡単に計算することができます。
計算結果を`variance`というオブジェクトに格納します。

```r
variance2 <- var(stat_test)
variance2
```

```:出力
 [1] 9.155556
```

## 3.標準偏差
最後に標準偏差(standard deviation; SD)を見ていきます。
標準偏差も分散同様、ばらつきを表す指標です。
分散は、「2乗したもの」の総和でした。
標準偏差は分散の平方根をとったものになります。
Rでは、関数`sd()`を使用します。
この関数を使って計算したものを`sd1`というオブジェクトに格納します。

```r
sd1 <- sd(stat_test)
sd1
```
```:出力
 [1] 3.025815
```

別の方法としては、平方根をとる関数`sqrt()`を使うことができます。
関数`sqrt()`に分散の値を入れたら、OKです。
この関数を使って計算したものを`sd2`というオブジェクトに格納します。

```r
sd2 <- sqrt(variance2)
sd2
```
```:出力
 [1] 3.025815
```

同じ結果になりました。

## 参考
次のURLや書籍を参考にさせていただきました。
ありがとうございます。
より学びが深まると思いますので、良かったらご覧ください。

・[【R言語】平均と分散と標準偏差](https://note.com/eiko_dokusho/n/n1564e6045e34)
・[Rで学ぶ統計学入門](https://www.amazon.co.jp/R%E3%81%A7%E5%AD%A6%E3%81%B6%E7%B5%B1%E8%A8%88%E5%AD%A6%E5%85%A5%E9%96%80-%E5%B6%8B%E7%94%B0-%E6%AD%A3%E5%92%8C/dp/4807908596/ref=sr_1_1?crid=MJNSOMSMXOWB&keywords=r%E3%81%A7%E5%AD%A6%E3%81%B6%E7%B5%B1%E8%A8%88%E5%AD%A6%E5%85%A5%E9%96%80&qid=1650076524&sprefix=R%E3%81%A7%E5%AD%A6%E3%81%B6%2Caps%2C202&sr=8-1)
Mac キーボードショートカットキー（自作）登録方法

[公式の記事](https://support.apple.com/ja-jp/guide/mac-help/mchlp2271/mac)
1. システム環境設定>キーボード>アプリケーションを選択
2. 「＋」選択
![スクリーンショット 2022-04-16 11.34.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670884/edc0fffc-03eb-b6d4-d01f-011eafbc757a.png)
3. ショートカットのタイトルとコマンドを入力し「追加」を選択して完了
知らなきゃヤバい メタバース

## メタバースについて

<iframe src="https://docs.google.com/presentation/d/1bJJBIn2qjEIVgHMDX01tAAPcJMQyclb6I-b-jEHPwiM/embed?start=false&loop=false&delayms=3000" frameborder="0" width="500" height="569" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true"></iframe>
[Docker][Java] Java プロセスのコンテナで jstat が採れない


docker コンテナで動かしている Java プロセスの jstat を採る話。

以下のように実行してみると。。

```
$ docker exec -t --user 1000 {container-id} jstat -gc 1
```

こんなエラーになりました。

```
sun.jvmstat.monitor.MonitorException: 1 not found
        at jdk.internal.jvmstat/sun.jvmstat.perfdata.monitor.protocol.local.PerfDataBuffer.<init>(PerfDataBuffer.java:84)
        at jdk.internal.jvmstat/sun.jvmstat.perfdata.monitor.protocol.local.LocalMonitoredVm.<init>(LocalMonitoredVm.java:68)
        at jdk.internal.jvmstat/sun.jvmstat.perfdata.monitor.protocol.local.MonitoredHostProvider.getMonitoredVm(MonitoredHostProvider.java:77)
        at jdk.jcmd/sun.tools.jstat.Jstat.logSamples(Jstat.java:107)
        at jdk.jcmd/sun.tools.jstat.Jstat.main(Jstat.java:70)
Caused by: java.lang.IllegalArgumentException: Could not map vmid to user Name
        at java.base/jdk.internal.perf.Perf.attach(Native Method)
        at java.base/jdk.internal.perf.Perf.attachImpl(Perf.java:272)
        at java.base/jdk.internal.perf.Perf.attach(Perf.java:202)
        at jdk.internal.jvmstat/sun.jvmstat.perfdata.monitor.protocol.local.PerfDataBuffer.<init>(PerfDataBuffer.java:64)
```

PID 1 がないというのだけど、java プロセスは確かに PID=1 で動いてる。。？

エラーメッセージで調べてみると、以下のような記事が見つかった。

jdk6u23 で jps/jstat が動作しないあるある
https://tksmd.hatenablog.com/entry/20110119/p1


jps、jstat は `/tmp/hsperfdata_{ユーザ名}` というディレクトリを見て対象プロセスの情報を得るので、`/tmp` の部分がプロパティで変更されてるとうまく動かないというものでした。

試してみると、Java の調査コマンドで確かに jps、jstat が動きません。

- ×  `jps`
- ×  `jstat -gc 1`
- 〇  `jstack 1`
- 〇  `jmap -histo:live 1`
- 〇  `jcmd 1 GC.heap_info`

ただし、記事にあるように `/tmp` の部分は変更されていません。

`hsperfdata` ディレクトリは Java プロセス起動時に作られるとあるのに、該当のディレクトリができていません。


どうやら、`hsperfdata_{ユーザ名}` とあるように、実行ユーザの UID に対するユーザがないと対象のディレクトリが作られないようですね。

docker 実行時に実行ユーザの UID だけ指定してユーザを切り替えていたのがダメだったようです。

```
$ docker exec -t --user 1000 {container-id} id
uid=1000 gid=0(root) groups=0(root)  ★UIDに対するユーザがいない
```

というわけで、Java コンテナの起動スクリプト(entrypoint.sh) 内で UID に対するユーザを作るようにしてみました。

```entrypoint.sh
UID=${UID:-1000}
useradd -m -u ${UID} myuser
```

実行ユーザが設定できています。

```
$ docker exec -t --user 1000 {container-id} id
uid=1000(myuser) gid=0(root) groups=0(root)
```

`hsperfdata` ディレクトリも作られるようになりました。

```
$ docker exec -t --user 1000 {container-id} ls -1 /tmp
hsperfdata_myuser
  :
```

これで、無事 jstat が採れるようになりました。

```
$ docker exec -t --user 1000 {container-id} jstat -gc 1
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT    CGC    CGCT     GCT
 0.0   5120.0  0.0   5120.0 74752.0  10240.0   431104.0   65111.7   75264.0 72714.0 10240.0 9118.1     35    3.934   0      0.000   8      0.397    4.331
```


// EOF
AI-102用備忘録

これから受けてくるのでとりとめなくまとめてみました。

責任あるAIの原則
公平性の原則　fairness
プライバシーとセキュリティの原則
透明性の原則　transparency

英単語
recognize	認識する
taxonomy	分類学
cognitive	認知
intent	意図
utterance	発話
carousel	水平方向の

Azure Cognitive Search Indexer対象のデータソース
・Azure Data Lake Gen2
・Azure Table Storage
・Azure Cosmos DB

QnA Maker Serviceのコマンドラインツールとか
LUDown	　.luファイルの解析、JSON形式でナレッジベースを生成
Chatdown	　Bot Framework Emulatorで使用。.chat→.transcript
LUISGen	　typescript等を生成
ngrok	　WebからローカルPCに直接メッセージを転送。デバッグとかに使用。

QnAナレッジベースのエクスポート
.tsv/.xlsxのファイル形式に対応している。

Speech Recognizer　…　音声をテキストに変換
Speech Synthesizer  …　音声を合成してテキスト読み上げ
Audio Data Stream　…　音声合成とかに使用

Face APIのいろいろな属性
https://docs.microsoft.com/ja-jp/azure/cognitive-services/face/concepts/face-detection

FaceAttributes パラメータのアクセサリー属性　…　メガネとかマスクとか
FaceLandmarksパラメータ　…　瞳孔や鼻の先端など。27個ある。

顔認証　…　１対１マッチング
顔識別　…　１体ｎマッチング

ボットの公開
・Azure App Service
・Azure Functions

ボットの構成ファイル
C#　　	　…　appsettings.json
Javascript 　…　 .env
Java　 	　…　 application.properties
Python 　    …　 config.py

他のボットのタスクを実行できる　…　スキル。スキルマニフェストが必要。
他のボットをスキルとして呼び出すことができる　…　スキルコンシューマー

Direct Line	 …　クライアントアプリとボット間の通信
Direct Line Speech 	 …　ボットと音声で対話できる。

ボットフレームワークSDK のリッチカード
アダプティブカード　…　テキスト／音声／画像／ボタン等カスタマイズ可能
ヒーローカード　…　画像
サムネイルカード　…　サムネイル
レシートカード　…　領収書
アニメーションカード　…　短い動画、アニメーションgif
ビデオカード　…　動画を再生
オーディオカード　…　オーディオファイルを再生
サインインカード　…　ボットがユーザーのサインインを要求

完全修飾コンテナイメージ名
mcr.microsoft.com …　MCRはMicrosoft Container Registry

Azure Cognitive Search REST API
GET
https://[service name].search.windows.net/indexes/[index name]/docs/suggest?[query parameters]  
  Content-Type: application/json  
  api-key: [admin or query key]   
POST
https://[service name].search.windows.net/indexes/[index name]/docs/suggest?api-version=[api-version]  
  Content-Type: application/json  
  api-key: [admin or query key]  

シノニムマップ　…　用語を関連付け、マップされた用語を含むようにクエリを展開するリソース。
・大文字小文字は区別されない
・Azure Portalではなく、Azure Cognitive Search REST APIなどのプログラムで作成


言語検出のコンフィデンススコア　…　0-1

Video Analyzer for mediaのコンテンツモデル
・ブランド
・人物　…　有名人
・言語　…　業界用語とか
品質の高いコードとは？

# 品質とは？
品質には、外部品質と内部品質がある。
そして、プログラムの品質は、内部品質のことを指し、品質が悪いと修正や拡張のコストが高くなります。
|    | 説明  |
| ---- | ---- |
|  外部品質  |  ユーザーに見える要素で、仕様どおりに動く、バグがない、高速に動作する等  |
|  内部品質  |  ユーザーに見えない要素で、保守性や柔軟性、可読性、一貫性等  |

# 品質の高いコードとは？
擬集度と結合度がその指標になり、擬集度が高く、結合度が低いコードが品質が高いコードとなります。

|    | 品質高い |品質低い |
| ---- | ---- |---- |
|  擬集度  |  高い  |低い |
|  結合度  |  低い  | 高い|
# 擬集度
モジュール内の機能のまとまりの程度を示すもの

## 高凝集はなぜいいのか？
凝集度の高いシステムでは、コードの読みやすさと再利用の容易さが増し、複雑さが管理可能な程度に抑えられます。

## 低擬集だと？
- まとまりがなく、モジュールでやっていることを理解しづらく、読みにくい
- 色々な関心ごとがあり、変更の可能性が上がる。そして、条件分岐などが発生し、可読性、保守性が下がる

## 凝集度の程度

|    | 説明 |品質 |
| ---- | ---- |---- |
|  偶発的擬集 |  適当に処理をまとめた関数  |最悪 |
|  論理的凝集  |  IF文で実行を切り分けるているなど、論理的に似ている処理をまとめた関数  | |
|  時間的凝集  |  実行順に意味はなく、特定の時間における処理がまとまった関数  | |
|  手順的擬集  |  実行順に意味があり、特定の時間おける処理がまとまった関数  | |
|  通信的擬集  |  実行順に意味があり、同じ値を使う関数  | |
|  逐次的擬集  |  実行順に意味があり、手順間で値を受け渡し使う関数  | |
|  機能的擬集  |  単一の機能の関数  | 最良|

# 結合度
モジュール間の相互依存性の程度を示すもの

## 結合度が低いとなにがいい？
- モジュール間の結合の数が少ないほうが、構造がシンプルになり、可読性が増す
- モジュールを使う時に知っておくべき知識が少ないほど、モジュールの用途が理解しやすく使いやすいモジュールになります

## 結合度の程度

|    | 説明 |品質 |
| ---- | ---- |---- |
|  内部結合 |  他の関数と外部宣言されていない値で結合されている  |最悪 |
|  共通結合  |  共通のグローバル変数と結合されている  | |
|  外部結合  |  パブリック変数で結合されている  | |
|  制御結合  |  利用する側はフラグなどを渡し、それを使って条件分岐する結合がされている  | |
|  スタンプ結合  |  オブジェクトや構造体を渡すことで結合されている  | |
|  データ結合  |  スカラー値を渡すことで結合されている  | |
|  メッセージ結合  |  値の受け渡しをしない  | 最良|

# コードレビューにおいても活かされる
擬集度と結合度は、品質の高いコードの指標です。
コードレビューの際にその指標を踏まえ、コメントすることで、より品質の高いコードへの証明となり、説得力が増します。
|    | コメント例 |コメント種類 |
| ---- | ---- |---- |
|  ASIS|  モジュールを分けた方が、読みやすくなると思います。  |感覚的なコメント |
|  TOBE  |  論理的擬集になるので、モジュールを分けましょう。その方が擬集度が上がり、可読性が増します。  | 論理的なコメント|

# 参考資料
https://speakerdeck.com/sonatard/coheision-coupling
https://note.com/cyberz_cto/n/n26f535d6c575#E0aBe
PythonのDocker公式イメージからLANG=C.UTF-8の環境変数が削除された

uWSGI で動かしているアプリケーションが、最新の Docker イメージでビルドしたときに `UnicodeDecodeError: 'ascii' codec can't decode byte...` のエラーで動かなくなったのでメモ。

## 更新（2022/4/21）

該当 issue を見てみたら [revert されていた](https://github.com/docker-library/python/pull/570#issuecomment-1103181181)ので、今は今まで通り使えそう。

## 要約

以前は Python3 側にバグがあり、環境変数 `LANG=C.UTF-8` を指定しないと動かなかったみたいだが、現在は修正されているため最新の Docker イメージではこれが削除された模様。

https://github.com/docker-library/python/pull/570

しかしながら、この環境変数をいくつかのライブラリは見ていたようで、上記 issue には今回の変更による[悲鳴](https://github.com/docker-library/python/pull/570#issuecomment-1100274060)が寄せられている。

影響を受けるライブラリの1つが、私も使っている uWSGI で、日本語の文字（非 ascii 文字）を扱おうとすると `UnicodeDecodeError` が出てしまった。

Dockerfile なり何なりで環境変数 `LANG=C.UTF-8` を指定すれば動くので workaround としてはそれで良さそう。 Python 側のバグが直っている以上、再び公式イメージに `ENV LANG C.UTF-8` が戻ってくることはなさそうなので、ライブラリ側での根本解決を待つ（もしくは貢献する）方針かな。
pythonのEXE化時のパスについて

# pyinstaller使用時のpathについて
pyinstallerで実行ファイル化すると、動作としてテンポラリフォルダ(_MEI*****というフォルダ)に解凍し、そこで実行する挙動になっています。

pyinstallerを使用して一つの実行ファイル化するときに、画像や設定等のファイルを参照する方法は２つあります。
実行ファイルがそれぞれ `C:\python\`にあるとします。
1．実行ファイルと同じフォルダに置いて参照する
2．ファイルを内蔵して参照する

### 1.実行ファイルと同じフォルダに置いて参照する場合
```get_path.py
import sys
import os
get_path =  os.path.dirname(sys.argv[0])
※必要によって　.replace("\\" ,"/")　を追加
print("get_path=",get_path)   #get_dir= C:\python
```
### 2.ファイルを内蔵して参照する場合
実際はテンポラリフォルダ内を参照することになるので、そのパスを取得します。

```temp_path.exe
import sys
import os
temp_path = os.path.dirname(os.path.abspath(__file__))
print("temp_path=",temp_path)    #temp_path= C:\windows\temp\_MEI*****
※実行ファイル化した後での出力の結果です。パスはあくまで例です。
```
とりあえずこんな感じでできます。
コードを書く際、内蔵するか否か、最初に決めておかないといけないですね。
そういう意味では、最初の設計はやはり大事です。