OmniAICreator/Qiita-1.07M huggingface dataset:
laravel学んで2か月で自サービスを開発した話 Part1

# 概要

今まではスロットや掲示板、ネタ登録サイトなどを作ってみたけれど、自分自身で一つのサービスを作りたいと思い決意  
せっかくlaravelを学んだので、laravelで開発したい  
ポートフォリオにも使えるしね！

# 何を作るか?
ECサイトや予約サイト、マッチングアプリなど、laravelでできるサービスは多岐にある。  
しかし、選択肢が多いってことは、それだけ迷ってしまうということ、自サービスの方向性が定まらないまま、yahooニュースを見て現実逃避をする。  
![genjitsu_touhi.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2281946/ecfe987c-24bd-6267-40c0-0a8bc1fe75db.png)  
そして、たどり着いたのがこの記事  

https://news.yahoo.co.jp/articles/43d9b12fe338fd9f7193b48e4590d1caacb0f486

#### 世の中にはこの胡蝶蘭のように、使われてポイされる花が数多くある。
### youtuberではないけれど、胡蝶蘭を救いたい・・・
### というか、捨てるくらいならワイにくれよ！
![dada_koneru_man.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2281946/668030ba-66aa-8690-d0bb-93e73b45695b.png)
### せや！胡蝶蘭を処分したい人と、花がなくても胡蝶蘭を育てない人をつなぐサービスを作ればいいじゃんか！！
~~そしてワイも胡蝶蘭が欲しい~~

# 要件定義
### 目的
ユーザーが処分したい花を出品して、別のユーザーが交渉して取引を成立させる
ジモティーのようなイメージ
### ユーザー側の流れ
- 新規登録→ログイン (laravel Breezeライブラリを使用)
- 商品を出品 (画像登録のために、InterventionImageライブラリを使用)
- 別のユーザーがその商品に取引希望を出す
- 双方に取引成立メールを自動送信 (sendgridを利用)
- 取引はユーザー同士が直接対面して取引するか、宅配便での取引をする (直接取引の場所を表示するためにgooglemapあれば便利だなあ)

### サイト管理者側の流れ
もちろんユーザーだけに任せるとトラブルに発展する可能性もあるので、管理者を追加して円滑な取引の手助けをする。  
そのために必要な機能が
- ユーザーの編集　削除を行う機能
- 退会後のトラブルに対処するために、退会ユーザーをデータベースに保存する機能
- 不適切な商品を凍結する機能

あとはユーザーと管理者の画面を分けるためにマルチログイン機能も必要か

最低限必要な機能はこんな感じ

### 開発環境
- PHP 8.1.2
- Laravel Framework 8.83.1
- mysql 5.6.50
- tailwindcss 3.0.0
- xampp 3.3.0

## 想定した導線
### ユーザー側
![スクリーンショット (1634).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2281946/09f07bf0-2905-d6fe-6cfc-a878de768d84.png)
### 管理者側
![スクリーンショット (1633).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2281946/907d2eef-9836-cbac-7baf-c18606decaed.png)



### 最低限のデータベース構成

管理者テーブル
ユーザーテーブル
商品テーブル
違反商品テーブル

とりあえず完成イメージはついたので、今後の開発記録を載せていきます。
EMM ってなに？

## 勉強前イメージ

なんだっけ・・・？わすれた

## 調査

### EMM とは

Enterprise Mobility Management の略で、
社内で使用するスマホなどのスマートデバイスやモバイル端末を総合的に管理するシステムのことを指します。
モバイルデバイスなどは、持ち運びも便利なことからパソコン端末より置き忘れや盗難に会うことが多くなります。
そのため機密情報の漏洩のリスクが上がります。
EMMを導入することで各デバイスのコントロールを効率的に安全に行うことが出来ます。

### EMMを構成する要素

EMMを構成する要素には3つあります。
それぞれ以下になります。

#### MDM

Mobile Device Management の略で、モバイルデバイスを管理するEMMのメイン機能になります。
MDMは管理に特化した機能です。
MDMの機能には以下のようなものがあります。

- 管理している端末のユーザ管理
- 紛失・盗難時にロック・データの削除を実施
- アプリ・OSの一括アップデート

#### MAM

Mobile Application Management の略で、業務で使用するアプリケーションを管理する機能になります。
主な機能は以下になります。

- データ通信の暗号化
- 業務で利用するアプリケーションの管理

#### MCM

Mobile Contents Management の略で、業務に必要なコンテンツを管理する機能になります。
主な機能は以下になります。

- 社内のコンテンツにアクセスする際の通信環境の構築
- データの保存の制御
- アクセス権限の管理

### まとめると

- MDM : デバイスの管理
- MAM : アプリケーションの管理
- MCM : コンテンツの管理

## 勉強後イメージ

BYODでも使えるって書いてあった。

## 参考

- [EMMとは？MDMやMAMとの違いもわかりやすく解説！](https://it-trend.jp/mdm/article/160-0005)
- [EMM（エンタープライズモビリティ管理）とは？仕組みやメリットデメリットについて徹底解説](https://cybersecurity-jp.com/security-measures/34509)
Rails コメント削除機能

## 開発環境
Mac
Ruby 2.6.5
Rails 6.1.3.2

## 問題が起きたコード
```posts_controller.rb
def destroy
@comment=Comment.find_by(params[:id])
@comment.destroy
flash[:notice] = 'コメントを削除しました'
    redirect_to("/posts/#{params[:post_id]}")
 end
```
find_byメソッドで返ってくる結果は、最初にヒットした1件なので上のコードのままだとコメントを削除すると古い順から削除されてしまう。
下の記事が参考になりました。
[【Rails】コメント削除機能の実装（備忘録）](https://qiita.com/miya1221/items/88a8751da147bcaa7be5)
```posts_controller.rb
def destroy
    current_user.comments.find(params[:id]).destroy!
    flash[:notice] = 'コメントを削除しました'
    redirect_to("/posts/#{params[:post_id]}")
  end
```
これでcommentコントローラーのdestroyアクションに、投稿したidを紐づけて削除できるようになります。
```posts/show.html.erb
 <% @comments.each do |c| %>
 <div>
 <%= c.content %>
<% if c.user_id == @current_user.id %>
 <%= link_to("削除", "/comments/#{c.id}/destroy") %>
 <% end %>
 <% end %>
 </div>
```
１行目・・要素を一つずつ取得してcに代入する。
４行目、５行目・・コメントしている人のidと今利用している人のidが同じ時に削除できるようにする
```config/routes.rb
resources :posts do
    resources :comments, only: %i[create destroy]
  end
```
参考記事
[【Rails】コメント削除機能の実装（備忘録）](https://qiita.com/miya1221/items/88a8751da147bcaa7be5)
[[Rails]コメント削除機能の実装でハマってしまったので一応解決策を。](https://qiita.com/Jwataru/items/a8e0120dd32761d70bfa)[]()
【Botpress】日本語入力をAPIにGET値で渡す方法

チャットボットのBotpressを使用していて、ユーザー入力の内容をAPIに渡したいケースがありますが、日本語の内容をそのまま渡そうとするとエラーになったので、解決方法を調べました。

# Call APIのエラー

Call APIを使用して対話からのユーザー入力をGET値としてAPIに渡します。
ここでは天気の情報を返すAPIを例として使います。

![Screen Shot 2022-02-26 at 18.18.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1641177/5ad67141-c692-0ebb-dc12-67bc407a7aed.png)

以下は対話エミュレーターの表示。
ユーザーが「今日の大阪の天気」を聴いたのに対してエラーを返しています。

![Screen Shot 2022-02-26 at 21.15.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1641177/fbcb5bee-80b5-de01-556b-dd4c541a988c.png)

ログを確認すると、「UNESCAPED CHARACTERS」のエラーが出力されていました。どうやらGET値として設定する前にURLエンコードをする必要があるようです。

![Screen Shot 2022-02-26 at 21.15.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1641177/a40ebb32-baed-1cb6-eec4-05fe23c8083e.png)

# 対処法

フックを使って入力をURLエンコードしてeventに保存しておきます。
Call API実行時にeventを参照してGET値に設定します。

Botpress studioの左メニューの「code editor」から「Hooks」を選び、フックを新規作成します。フックには「event.payload.text」をURLエンコードしてから「web ContextString」として「event.state.user」に保存するコードを登録します。

![Screen Shot 2022-02-27 at 21.28.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1641177/44db6467-69e4-2378-e4be-862d67b0cf19.png)

次はCall APIのGET値を修正します。
「event.state.user.web ContextString」をGET値に指定します。

![Screen Shot 2022-02-26 at 18.03.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1641177/8258fa0b-196b-18fd-9c8e-4afe5dcf4093.png)

対話エミュレーターを実行すると、APIが正しいレスポンスを返していることがわかります。

![Screen Shot 2022-02-26 at 21.21.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1641177/702070dc-753e-2cd8-29f2-43715d005fec.png)
Azure Synapse Analyticsのアクセス監査ログをONにする設定

**DBサーバーの監査のところに監査を有効に設定する。**
![SynapseAnalyticsの監査ログON設定01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2547888/8315b9ce-9a3e-628f-59b5-ba6aac23ed72.png)

**DBアクセス監査ログは指定したストレージにxelファイルとして記録される。**
**xelファイルはSSMSで開くことが可能。**
![SynapseAnalyticsの監査ログON設定02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2547888/7c826a41-520e-37ed-a1eb-1dd0de060ec4.png)
Tinderを簡単に自動化してみた

### はじめに

**コードは読めても女性の心を読めない**@t_mojamojaです。

みなさんは彼女がいますでしょうか？僕は残念ながらいません。ましてや最近はいないことに危機感も感じることがなくなりました。

そこで女性との付き合いもプログラミングもアウトプットが大事ということで、自分に発破をかけるためにTinderをインストールしました。

しかし、初めてみたもののなかなかマッチングしません。
一応課金もしていいねを無制限にできるようにしましたが、結局あまりマッチングしませんでした。

調べてみたところ、Tinderでマッチする確率は **0.5%** だそうです。しかし、個人的な感覚としてはもっと低いと思っています。

Tinderでマッチする確率が低い原因は大きく分けて2つあります。

1つは**男性ユーザーが圧倒的に多いため**です。これはどのマッチングアプリでも共通の問題だとおもいます。

2つ目は**見た目で判断される場合が非常に多いこと**です。Tinderではその印象が特に強いです。

僕は高身長イケメンでもなんでもないのでよりマッチングする確率が低いのかと思われます。(自分の有利な市場で勝負すればいいのでは？ということは一旦気にしないでださい)

しかし、この確率の壁を越えることはできませんが、**試行回数を増やし、マッチングの回数を上げること**はできます。

そこで私はコードは読めるため**いいねを自動化**してとにかく試行回数を増やすことを考えました。

### 実装方法
https://qiita.com/Fulltea/items/fe4d4214552476c28e88

こちらにAPIを利用する方法がありましたが、今回の記事ではこの方法を利用していません。

理由は2つあります。

1つはFacebookとの連携が必要であり、私はすでに電話番号での登録を行なっていたため。

2つ目はAPIだとメッセージも自動化できてしまい、**女性に対しての誠意を欠いているため**です。

以上2つの理由でとりあえずLIKEだけを自動化しようと試みました。

そこで利用したのがディベロッパーツールのコンソールです。
TinderにはネイティブアプリだけでなくWebアプリでも提供されているのでそちらを利用しました。
![スクリーンショット 2022-02-27 21.55.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/612338/aabc20a4-9f19-2bad-d199-31ffa820c0df.png)
上記の部分に以下のコードを入力します。

```js:tinder.js
setInterval(
 function(){
 const buttons = document.getElementsByClassName("button Lts($ls-s) Z(0) 
 CenterAlign Mx(a) Cur(p) Tt(u) Bdrs(50%) P(0) Fw($semibold) focus-button-style 
 Bxsh($bxsh-btn) Expand Trstf(e) Trsdu($normal) Wc($transform) Pe(a) Scale(1.1):h 
 Scale(.9):a Bgc($c-like-green):a");
 buttons[0].click()
},1000)
```

`setInterval`は第一引数に無名関数を渡しており、第二引数に時間の間隔の値を渡しています。
また、取得しているクラスはTinderのいいねボタンになります。そして`click`によって取得した要素をクリックすることができます。

これによって1秒ごとに自動でいいねをしてくれます。

### 終わりに

この自動化で試行回数が格段に増加し、マッチングの回数も漸増していきました🎉
ここからは自分のコミュニケーション力が試されるので精進していきます🔥

### では皆さん次はTinderの画面で会いましょう👋
PowerAutomateDesktop: タグ別の自己記事目次 [automated]

# 概要
タグ別での自己記事の目次です。
Power Automate にて定期更新をしています。

# [PowerAutomateDesktop: Power Fx なら、月末日取得が楽々になってる](https://qiita.com/baku2san/items/53db1245293410379d62)
投稿日: 2024/12/9 
tips, PowerAutomateDesktop, PowerFx

# [PowerAutomateDesktop: OCR機能:Windows OCR で日本語テキストを見つける場合は、半角空白を挟め](https://qiita.com/baku2san/items/24919a07d6c1b198e250)
投稿日: 2024/8/6 
OCR, PowerPlatform, PowerAutomateDesktop

# [PowerAutomateDesktop: テーブル使ってなくても、テーブルで取れるんですね](https://qiita.com/baku2san/items/b5efaf57e521b32eeaaf)
投稿日: 2024/5/29 
PowerPlatform, PowerAutomateDesktop

# [PAD: SharePoint Lists への SQL を利用した User 追加や更新時は、SiteUsers の Id を利用する](https://qiita.com/baku2san/items/c559ab7bfd1731900c7b)
投稿日: 2023/2/15 (更新日: 2023/2/21)
SQL, PowerAutomateDesktop, SharePointLists, SiteUsers

# [PAD: ドラッグ＆ドロップを使ってShareやOneDriveへアップロード](https://qiita.com/baku2san/items/79981cdb279481862397)
投稿日: 2022/1/12 
SharePoint, OneDrive, drag&drop, PowerAutomateDesktop

# [PAD: Excel の 変換 *.xls から *.xlsx](https://qiita.com/baku2san/items/01adccbff94156133ef0)
投稿日: 2022/1/11 
Excel, PowerAutomateDesktop

# [Power Automate Desktop: ポップアップウィンドウの操作の仕方](https://qiita.com/baku2san/items/6eab9a892240fd909d5a)
投稿日: 2021/11/13 
popup, PowerAutomateDesktop

# [PAD: ドラッグ＆ドロップでの自動化](https://qiita.com/baku2san/items/364800f0d9bc8f76f440)
投稿日: 2021/11/4 
drag&drop, PowerAutomateDesktop

# [PAD: Excel からデータ取得する際はやっぱりSQLですね](https://qiita.com/baku2san/items/be6d0a256c3afa7fc3ec)
投稿日: 2021/10/13 
SQL, Excel, PowerAutomateDesktop

# [Power Automate Desktop: 値の存在が不明な場合のフィルター方法](https://qiita.com/baku2san/items/bde621c4f50c39d10fa2)
投稿日: 2021/10/5 
list, PowerAutomateDesktop

# [Power Automate Desktop: null を利用する方法](https://qiita.com/baku2san/items/73ff9ccebd4d35a20eb2)
投稿日: 2021/10/5 (更新日: 2021/10/13)
JSON, NULL, PowerAutomateDesktop

# [PAD: あるフォルダの最新ファイルを開く](https://qiita.com/baku2san/items/aefbbe238699076b5f65)
投稿日: 2021/9/27 
初心者, RPA, PowerAutomateDesktop

# [Power Automate Desktop: 「Web ページのダウンロード リンクをクリックする」が動かない](https://qiita.com/baku2san/items/b666a41a2daa55e71658)
投稿日: 2021/9/9 
Edge, PowerAutomateDesktop

# [Power Automate Desktop (無償) のフローを共有する](https://qiita.com/baku2san/items/be89e206a6280cb84406)
投稿日: 2021/8/21 (更新日: 2021/8/22)
Robin, PowerAutomate, PowerAutomateDesktop
【SpringBoot】内包TomcatとApacheを連携する

SpringBootでは内包TomcatのAppサーバ、Webサーバを使用してJarファイル単体で動かすことが可能です（Gradle設定が必要）
ですが、TomcatのWebサーバでは機能性、安定性に不安が残るため、Apacheを使用したい場合があります。
### 内包Tomcatの設定
`@Value`ではローカルでTomcatのWebサーバを使用するようにymlで環境を分けております。
`@Override`でcustomizeメソッドの設定を変更しております。
設定内容の説明についてはコメントの通り。
```java:TomcatCustomizer.java
@Component
public class TomcatCustomizer implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {

	@Value("${data.protcol}")
	private String protcol;
    private static final Logger logger = LoggerFactory.getLogger(TomcatCustomizer.class);

	@Override
    public void customize(TomcatServletWebServerFactory factory) {
		if(protcol.equals("AJP")) {
			logger.info("Tomcat protocol：AJP");
	    	try{
	            InetAddress address = InetAddress.getByName("127.0.0.1");
		    	factory.setAddress(address); //ローカルを指定
		        factory.setProtocol("AJP/1.3"); //AJPを使用
		        factory.setPort(8009); //ポートを8009番で受付
		        factory.getTomcatConnectorCustomizers()
		        .add(c -> c.setProperty("secretRequired", "false")); //シークレットキーをFalseに変更
	    	}catch(Exception e) {
	    		//Tomcat編集エラー処理
	    	}
    	}else {
			logger.info("Tomcat protocol：HTTP");
    	}
   	}
}
```

### Apacheの設定
Tomcatの設定に合わせプロトコルをAJP、ポートを8009に設定する
```apache:/etc/httpd/conf/httpd.conf
ProxyPass / ajp://localhost:8009/
````
WindowsでNVIDIAのGPUを使ってTensorflowを使う

## 必要なNVIDIAのソフト
- [CUDA Toolkit](https://developer.nvidia.com/cuda-toolkit)
- [cuDNN](https://developer.nvidia.com/cudnn)
会員登録必須

## Pythonの環境構築
Pythonを[公式サイト](https://www.python.org/)からインストール
仮想環境を作成するために、PowerShellでプロジェクトのフォルダへ移動して以下のコマンドを実行
```
py -m venv .venv
```
以下のコマンドを実行すると仮想環境に入る（プロンプトの前に「(.venv)」が追加されていれば成功）
```
.\.venv\Scripts\Activate.ps1
```
仮想環境に必要なライブラリをインストール
```
py -m pip install tensorflow scikit-learn keras numpy pandas
```
pythonファイルを実行
```
python .\sample.py
```
以下のコマンドを実行すると仮想環境から出る
```
deactivate
```

## エラーの対処法
```
W tensorflow/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'cudnn64_8.dll'; dlerror: cudnn64_8.dll not found
```
以上のエラーが出たときは、cuDNNのファイルをCUDAのフォルダへすべてコピペする。具体的には、`C:\Program Files\NVIDIA\CUDNN\v8.3\bin`のフォルダ内のファイルを全てコピーし、`C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.6\bin`のファルダ内でペーストする。バージョンは適宜読み替えてください。
TypeScriptの基本的な型

# 自己紹介
現在都内の企業でWebエンジニアのインターン生としてお世話になっている大学２年生です！
インターンや個人開発で学んだことや苦労したことを記事にしています！
よろしくお願いします🙇🏻‍♂️

# はじめに
今回は最近勉強しているTypeScriptの型についてアウトプットしていこうと思います！

# boolean型,number型,string型
```typescript
//boolean型
let bool: boolean = true;

//number型
let number: number = 0;

//string型
let string: string = "string";
```

# Array型
```typescript
//Array型
let arr1: number[] = [1, 2, 3];
let arr2: string[] = ["A", "B", "C"];
//配列の中の方が混合している場合
let arr3: (string | number | boolean)[] = [0, "A", true];
//二次元配列
let arr4: number[][] = [
  [0, 1, 2],
  [3, 4, 5],
];
```
# tuple型
```typescript
//tuple型
//tuple型は型推論では表示されない
//arr3は順番までは定義できないがtuple型では順番も定義できる
let arr5: [string, number, boolean] = ["A", 0, true];
```
# any型
```typescript
//any型
//どんな型を入れてもエラーにならないので極力any型を使わないように開発を進めていく
let arr6: any;
```
# unknown型
```typescript
//unknown型
//下記のままだと変数numberUnknownの型がわからないから足し算できないかもしれないと判断される
let numberUnknown: unknown = 0;
// let sumUnknown = numberUnknown + 10;←エラーになる
//typeofを使って特定の型であることを確認しながらコードを実行させることを"タイプガード"という
if (typeof numberUnknown === "number") {
  let sumUnknown = numberUnknown + 10;
}
```
# void型
```typescript
//void型
//返す値が存在しないときに記述する型
const returnNothing = (): void => {};
```
# never型
never型についてのわかりやすい記事がありましたのでそちらを参考にしてみてください

https://qiita.com/irico/items/e1f96c642ed0a5a53742

# null型、undefind型
```typescript
//null型、undefind型
let Null: null = null;
let Undefinded: undefined = undefined;
```
# オブジェクト型
```typescript
//オブジェクト型
let obj: {
name: string;
} = {
  name: "Yusuke",
};
```
# 型エイリアス(Type Aliases)
```typescript
//型エイリアス(Type Aliases)
//typeの先頭は大文字
type Profile = {
  name: string;
  age: number;
  email: string;
};
const myProfile: Profile = {
  name: "Yusuke",
  age: 20,
  email: "test.com",
};
//１度型を作ってしまえばtypeofで使いまわせる
type Profile2 = typeof myProfile;
```
# 交差型(intersection型)
```typescript
//交差型(intersection型)
type Name = {
  firstName: string;
  lastName: string;
};
type Age = {
  age: number;
};
const myprofile: Name & Age = {
  firstName: "優介",
  lastName: "飯嶋",
  age: 20,
};
```
# 共用体型(union型)
```typescript
//共用体型(union型)
let value: number | string = 0;
value = "hoge";

```
# Literal型
```typescript
//string型
let holiday: "土" | "日" = "日";
// holiday = "月";←エラー

//number型
let month: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 = 1;
// month = 13;←エラー

//boolean型
let TRUE: true = true;
// TRUE = false;←エラー
```
# 列挙型(enum型)
```typescript
//number型
//最初の要素は0から始まるが最初の要素に任意の値を代入することで変更できる
enum Months {
  January = 1, //1
  February, //2
  March, //3
  April, //4
  May, //5
  June, //6
  July, //7
  August, //8
  September, //9
  October, //10
  November, //11
  December, //12
}
console.log(Months.January); //1
//string型
enum Ages {
  Me = "20歳",
  Brother = "15歳",
  Mom = "45歳",
  Daddy = "50歳",
}
console.log(Ages.Brother); //15歳
```

:::note warn
間違っている箇所があれば、教えてくださるとありがたいです。
:::

# 終わりに
今回はTypeScriptの型について書いてみました！
これからもTypeScriptについて記事を書いていこうと思います！
ではいい一日を😎
Raspberry Pi Zero WH と Intel Neural Compute Stick 2を使って画像認識をする！

Raspberry Pi Zero WH と Intel Neural Compute Stick 2を使って画像認識をしたい！
これから更新していきます（2022/02/27)


#### 参考元
https://github.com/jacopomaroli/intel-neural-compute-stick-2-raspberry-pi-zero
MySQL備忘録

# CLIコマンド
## mysqld と mysqld_safe の違いについて
- `mysqld`と`mysqld_safe`のどちらもMySQLサーバーを起動させるためのコマンド
- `mysqld_safe`ではエラー発生時の再起動やロギングなどを行ってくれるのでこちらの使用が推奨されている
- 内部的には`mysqld_safe`が`mysqld`を起動している

参考:
[mysqldとmysqld_safeの関係](https://open-groove.net/mysql/mysqld-mysqldsafe/)
[mysqld_safe — MySQL サーバー起動スクリプト（公式ドキュメント）](https://dev.mysql.com/doc/refman/5.6/ja/mysqld-safe.html)


# ログイン
## アクセス拒否エラーを回避する（開発時）
1. 一度MySQLを停止する
   ```
   [root@mysql_test]# service mysqld stop
   ```

2. 権限スキップのオプションを付与して再起動する
   ```
   [root@mysql_test]# mysqld_safe --skip-grant-tables
   ```

3. rootユーザーでログインする
   ```
   [root@mysql_test]# mysql -u root
   ```

参考:
[MySQLインストール時に遭遇する「アクセス拒否エラー(Access denied for user ‘root’@’localhost’)」の対処](https://www.aiship.jp/knowhow/archives/28257)

# クエリ
## データベースを作成する
```
CREATE DATABASE (IF NOT EXISTS) db_name
```

参考:
[CREATE DATABASE 構文](https://dev.mysql.com/doc/refman/5.6/ja/create-database.html)
X11でのドラッグアンドドロップ実装メモ

およそ20年前の技術であるが、日本語情報が全然なかったのでメモがてらまとめた
動作は確認した(on Xubuntu 20.04)が完全に準拠してる保証はないのでご注意

別のアプリケーション（ソース、主にファイルマネージャーとか）から
ファイルを送られる（ターゲット）のアプリケーションを想定、
ソース側の説明は簡素化


# 参考文献

仕様: Drag-and-Drop Protocol for the X Window System
https://freedesktop.org/wiki/Specifications/XDND/

参考にした実装: SDLのソース（主にこの辺）
https://github.com/libsdl-org/SDL/blob/main/src/video/x11/SDL_x11events.c

# 実際の実装
[xdndfile.c](https://gist.github.com/dragoon2014/916945ae4b509c5c35d36135b09ec9b2)

# 処理の流れ

## Step 0: (ウィンドウ起動時)
起動時にXChangePropertyでXdndAwareを指定し、XDNDプロトコルをサポートすることをアナウンス
このときプロトコルバージョンも指定する

なおプロトコルバージョン5しか考慮していないので互換性に欠けるかもしれない

仕様上クライアントは3〜最新のすべてに対応しなければならない：
- バージョン5においてXdndFinishedの受け入れるフラグを立てる必要がある（逆に言うと以前では無視されるはず）
- バージョン4においてXdndProxyが実装されたがこれはソースに対してなのかターゲットに対してなのか不明


## Step 1: (ソースウィンドウ上でマウスを押す)
（ドラッグを始めるとソースでXdndSelectionの所有権を得る）

## Step 2: (マウス押したままターゲットウィンドウにカーソルが乗る、初回のみ)
ターゲットのウィンドウにドラッグしているマウスカーソルが入るとターゲットがXdndEnterメッセージを受け取る
メッセージにはドラッグされた種類（ファイルならtext/uri-listとか、テキストならTEXTとかUTF8_STRINGとか）が3つまで乗る
種類が4つ以上ある場合はメッセージには載せられないため、（「3つを超える」フラグが立って、種類自体は空）
XGetWindowPropertyでソースからXdndTypeListを取得する

手元の例として、thunarからファイルを持ってくると以下がメッセージに乗って来る

- text/uri-list

mousepadからテキストを持ってくると以下がWindowProperty経由で来る

- GTK_TEXT_BUFFER_CONTENTS
- application/x-gtk-text-buffer-rich-text
- UTF8_STRING
- COMPOUND_TEXT
- TEXT
- STRING
- text/plain;charset=utf-8
- text/plain


この時点でソースウィンドウIDと必要なタイプ（例えばファイルならtext/uri-list）が届いているかを保持する

## Step 3: (マウス押したままターゲットウィンドウ上でカーソルが動く度、ただしStep 4でメッセージを返さないと連続して来ない)
（ソースがXdndPositionメッセージでマウス座標とユーザが要求したアクションXdndAction〜を送る）

## Step 4および5: (Step 3に対して毎度ターゲットからソースへメッセージ)
ターゲットがXdndPositionメッセージを受け取り（Step 4）、
ドロップを受け入れる場合はXdndStatusメッセージにアクションと受け入れるフラグと長方形を送る（Step 5）
（アクションはいくつか種類があるがここではXdndActionCopyのみ扱う）
（なお長方形の使い方がよくわからない、指定すると毎度XdndPositionが来なくなるっぽいが広範囲を指定しても特に変化がない）

## Step 6: (Step 5に対して)
（ソースがXdndStatusメッセージを受け取る、（長方形がなかったり）長方形から出たら再度Step 3に進む）

## Step 7a:（マウスがターゲットウィンドウを離れる）
（ソースがXdndLeaveメッセージをターゲットに送る）

## Step 7b:（マウスがターゲットウィンドウ上でボタンを離す、受け入れるフラグが立っている）
（ソースがXdndDropメッセージをターゲットに送る）

## Step 7c:（マウスがターゲットウィンドウ上でボタンを離す、受け入れるフラグが立っていない）
（ソースがXdndLeaveメッセージをターゲットに送る）

## Step 7d:（マウスがターゲットウィンドウ上でボタンを離す、ソースがXdndStatusを受け取っていない）
（ソースがXdndLeaveメッセージをターゲットに送る）

## Step 8a: （ターゲットがXdndLeaveメッセージを受信）
ターゲットはキャッシュしたデータを捨てる

## Step 8b: （ターゲットがXdndDropメッセージを受信、それを受け入れる）
ターゲットはXdndSelectionとXdndDropに同梱されたタイムスタンプでXConvertSelectionを呼び出し、
SelectionNotifyイベントが届いた際にXGetWindowPropertyでデータを取得した後、
XdndFinishedをソースに送る（SelectionNotifyにはソースウィンドウIDが載ってないのでXdndEnterで収集した値を使う）

取得したデータ自体はtext/uri-listに則ったフォーマットになっている
（ローカルファイルであれば"file:///path/to/file\r\n"、複数なら連結される）

## Step 8c: （ターゲットがXdndDropメッセージを受信、それを受け入れない）
ターゲットはXdndFinishedをソースに送る（ソースはXdndLeaveとして扱う）

# 感想とか

リファレンスコードが全然見つからず、SDLのコードが大変参考になりました
（過去の経緯で仕方ないかもしれないが）Xlibが32bit値をlongで扱っているのですこし厄介でした
Pycharmでimport errorが表示される解決方法

djangoでimportしたら違うディレクトリでエラーがでる。

```
Root
  ∟ Projects
    __init__.py
    manage.py
      ∟ config
      ∟ main
          ∟ decorators
               __init__.py
               login.py
          ∟ utils
               __init__.py
               config.py
```

原因は、Source RootがRootになっているからなので、ProjectsをSourceRootにしてあげると解決します。

```
1. ディレクトリを右クリック
2. Mark Directory asを選択
3. Source Rootを選択
```
【Kotlin】YoutubeAPIで動画再生機能をAndroidアプリ内に実装する

AndroidにおけるYoutube再生について調べたので、とりあえず再生できるようになるまでのメモ。

## 準備
 - Google Cloud Platformでプロジェクトを作成する
 - Youtube Data API v3を有効にし、APIキーを取得する
 - [公式のページ](https://developers.google.com/youtube/android/player/downloads/)からライブラリをダウンロードして、libsフォルダ内のYouTubeAndroidPlayerApi.jarを自分のプロジェクトにインポートする（AndroidStudio上でlibsにペースト後、右クリックでAdd As Libraryを選択）
 - Android Manifestでインターネット通信を許可する

```xml
<uses-permission android:name="android.permission.INTERNET" />
```

 - AndroidXで作るので、[こちら](https://qiita.com/iKimishima/items/36ed4cc3595fa1cf1fb9#%E5%AF%BE%E5%87%A6%E6%B3%95-1)を参考にYoutubePlayerSupportFragmentをAndroidX対応にさせる（大変助かりました）


## レイアウト
とりあえず全画面再生
```activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".activity.MainActivity">

    <fragment
        android:name="com.google.android.youtube.player.YouTubePlayerSupportFragmentX"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/player_fragment" />

</androidx.constraintlayout.widget.ConstraintLayout>
```


## コード

```MainActivity.kt
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.google.android.youtube.player.YouTubeInitializationResult
import com.google.android.youtube.player.YouTubePlayer
import com.google.android.youtube.player.YouTubePlayerSupportFragmentX

class MainActivity : AppCompatActivity(), YouTubePlayer.OnInitializedListener{
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val youtubePlayerFragment = supportFragmentManager.findFragmentById(R.id.player_fragment) as YouTubePlayerSupportFragmentX
        youtubePlayerFragment.initialize("APIキー",this)

    }


    /**
     * initialize成功時に呼ばれる
     */
    override fun onInitializationSuccess(
        provider: YouTubePlayer.Provider?,
        player: YouTubePlayer?,
        wasRestored: Boolean
    ) {
        player?.loadVideo("videoID")
    }

    /**
     * initialize失敗時に呼ばれる
     */
    override fun onInitializationFailure(
        provider: YouTubePlayer.Provider?,
        error: YouTubeInitializationResult?
    ) {
        //なにかする予定
    }
}

```
※videoIDはYoutubeの動画URLの末尾の方にある「v=」以降の英文字列になります。


これでとりあえず再生できました。
SESから自社開発に転職した際のポイント

# はじめに
今年SESから自社開発への転職が決まりました！
ネットで検索してみると、SIer(SES)から自社開発へ転職する人が結構多いようなので、今回の転職を振り返ってポイントだったところを記事にして誰かの参考になればと思いました。

私の経歴としてはインフラエンジニアを4年、Webアプリエンジニアを3年経験しています。

SESから自社開発への転職は難しいと言われているようですが、所感としては確かに難しい面はあるものの、やり方次第ではないかなと感じました。今回はそのやり方を書いていきます。

# 転職活動に至った経緯
初めの頃はいろんな開発現場に行けるSESでの働き方も面白いと感じていたのですが、作っているのは顧客のサービスなので、自分が作ったと声高々には言えないんですよね。

何か自分で考えて作り上げたサービスというのを持ちたくて自社サービスを持っている企業への転職を考えるようになりました。

# 転職までの流れ
### ① 履歴書、職務経歴書の作成
この時点ではまだ応募先企業が決まっていないので、履歴書は志望理由以外を記載しました。
職務経歴書はその出来によって、書類選考が通るかどうかが決まる重要な書類なので、2週間程度かけて作りました。

### ② IT特化の転職サイトを2つ登録
通常の転職サイトだとIT業界以外の企業からもスカウトメールが大量に来るため、今回はIT特化の転職サイトに絞りました。

### ③ カジュアル面談
今までカジュアル面談はやったことがなかったので一部の企業でやってみました。
結果としては、選考を気にせずに聞きたいことを何でも聞けるので企業研究の一貫としては良かったと思います。

ただし、カジュアル面談を行ったからと言って、書類選考が通るとは限らないので、そこは注意が必要ですね。

### ④ スカウト、自分で検索した企業へ応募
スカウトを受けた企業は、書類選考が通りやすいため一社も漏らさずにチェックしました。
ただ、スカウトをもらった企業は8割方SIerまたはSESの企業でした・・・

後は、自社サービス、Web開発というワードで検索して自分で探していきました。
応募した企業の内訳は"スカウト"と"自分で検索"で半々といった感じです。10社程応募しました。

### ⑤ 書類選考
今回職務経歴書をだいぶ作り込んだおかげもあって、10社中8社書類選考が通りました。

### ⑥ コーディングテスト
半分以上の企業でコーディングテストがありました。
プログラミング言語は自由に選べて、内容としては競技プログラミングのような内容のものでした。

### ⑦ 複数回面接
今のご治世なので、リモート面接のところがほとんどでした。
面接のプラットフォームはZoomであったり、Google Meetであったり様々でした。

マイクやカメラの設定は事前にやっておくのがマナーなので、友達にカメラとマイクの調子は問題ないか見てもらいました。

### ⑧ 内定
3社内定を頂き、その中から総合的に判断して転職先を決めました。

# どういう人が求められやすいか
面接を受けて聞かれた内容から以下のような人が求められやすい傾向にありました。

### ・受け身でない自発的な人
自ら行った業務改善のエピソードや困難をどう乗り越えたかなど、普段の業務でただ言われたことをするのではなく、自分で考えて行動できるかが見られます。

特にSESだと受け身体制で仕事ができてしまうため、自社開発の働き方ができるかが先方が一番気にされているところのようでした。

### ・自ら学ぼうという意思のある人
今勉強中の技術であったり、勉強会の話などを聞かれたたため、業務以外でも学習している人なのか見られます。

自社開発だと即戦力を求められるため、自分の知らない領域もちゃんと自分で身につけていける人なのかがポイントなのでしょうね。

### ・論理的に説明できる人
例えば、過去の経歴から自分をアピールする時、数字を交えて説明ができるか、聞かれた質問に対して感覚的な回答ではなく、客観的に正しいと言える論理的な回答になっているかがポイントでした。

開発現場では論理的な説明を求められる場面が多々ありますから、論理的な思考ができる人なのかが大事なのでしょうね。

# ポイント
本題の今回の転職のポイントです。

内容としては、書類選考、試験対策、面接対策と、一般的な就活対策と変わらないのですが、それぞれ自社開発独自の特色があるのでご説明します。

### 職務経歴書を徹底して書き上げる
職務経歴書って今までの経歴を書くだけじゃないの？って思うかもしれませんが全然違います。
自分のアピール商材であり、自分を商品として捉えて相手が買いたくなるようにする言わば営業で自分を売り込むようなものです。

職務経歴書は履歴書と違ってフォーマットは決まってないので、職歴以外の内容も書いていいのです。
私の場合は、GitHubや過去参加または開催した勉強会の内容も載せました。
Webアプリ開発の経験は3年だけど、自分でもこれだけ勉強してるよ！っていうアピールに使っていましたね。

### コーディングテスト対策
普段競プロをやっていない人だと、いざこういうコードを書いてって言われても何から書こうってなってしまうと思います。
実際、自分がそうでした。競プロは過去にやったことがあるけど、最近は全然やってなかったから、いざ書いて！となるとちゃんと書けるか不安だったため、予めAtCoderの問題を解いて、簡単な対策をしました。

※実はコーディングテストの他にSPIを受けさせる企業もあったのですが、SPIの対策もやるとなると面接対策が全然出来ないと思い、今回SPIの対策はしませんでした。

### 面接対策
リモート面接だからカンペで対策できるんじゃない？というと、そうでもないです。
リモートと言ってもカメラはつけますから、カンペを読んで回答すると、普通に面接官にバレます。

また、事前に回答を用意していない質問は絶対来るので、自分なりの軸を事前に持っておいたほうがいいです。
矛盾した回答をしてしまうと、この人本当のこと言ってないなとか、軸がぶれていて信用できないなと思われてしまいます。

# これからの過ごし方
今回の転職で、自分の実力を示すようなものはエンジニアとして常に持っておいたほうがいいなとしみじみ思いました。

AtCoderをやっていて一定のランクを持っていたり、個人開発でWebサービスを作っていたら、それだけでアピールできることが増えますもんね。私はそういうものを残念ながら持っていなかったので、GitHubである程度のものは作っていることや勉強会に積極的に参加・開催していることでしか経歴以外でアピールできるものがありませんでした。

そのため、転職先が決まったからといって気を抜かずにプライベートでも今後次のような活動をしていこうと思いました。

- 競プロの参加
- テックブログまたはQiitaによる技術的アウトプット
- Webサービスの個人開発

# さいごに
ここまでご清聴頂き、ありがとうございました。

需要があれば、職歴、テスト、面接対策についてもっと詳しく書いた記事を書こうと思います。
また上記技術的アウトプットの一貫として、今後技術的な記事もあげていきますので、よろしくお願いします。
起業ってなんだろう

ふとそんなことを思ったので、興味にまかせて調べたことを、備忘録として残しておこうと思います。

起業とは事業を新しく起こすことであり、事業とは、生産や営利を目的とした経済活動とのこと。

そして営利（活動）とは財産上・金銭上の利益を得る目的をもって事を行うこと。

また、利益を得るには収入が必要で、その収入を得るための支出が発生し、それは次式で表現できます。

利益　＝　収入　−　支出

ここまでは個人レベルの話でしたが、ここからは事業としてみた場合の話をします。

では会社の・・・と言い始めようとしましたが、ところで会社っていったい何なのでしょうか。
【JavaScript関数ドリル】Lodash関数の実装【勉強用】_.initial関数 

# 【JavaScript関数ドリル】初級編の_.initial関数の実装のアウトプット

       
```javascript:_.initial関数の挙動
_.initial([1, 2, 3]);
// => [1, 2]
```
渡された配列の末尾を取り除いたものを返す
## _.initial関数の課題内容

https://youtu.be/xWrXHx8nT_4

## _.initial関数に取り組む前の状態
- 元の配列をコピーし、末尾をpopするだけで良さそう
## _.initial関数に取り組んだ後の状態
- スプレッド構文`(...array)`について、複数の配列をまとめて受け取るという使い方しか知らなかったので、コピーにも使えることがわかった
- 概ね解答と同じ書き方で、短時間で作成できた
- 2日ぶりにコードを書いただけでアロー関数の書き方も少し忘れていたので、やはり関数ドリルだけでも毎日取り組もうと思った


## _.initial関数の実装コード

```javascript:
const initial = (array) => {
    const popedArray = array.slice();
    popedArray.pop();
    return popedArray;
};

console.log(initial([1, 2, 3, 4, 5, 6]));
// => [1, 2, 3, 4, 5]
```



## _.initial関数の解答コード

```javascript:
function initial(array) {
  const copiedArray = [...array];
  copiedArray.pop();

  return copiedArray;
}

const numbers = [1, 2, 3];
console.log( initial(numbers) );
// => [1, 2]

console.log('number : ', numbers);
```
LeetCode: 779. K-th Symbol in Grammar

# はじめに
LeetCodeの 779. K-th Symbol in Grammarに関して、公式サイトにSolutionがなく、これについて解説している記事もなかったのと、解法が面白かったので書きます。
# 問題
## 公式サイトから問題のコピペ
We build a table of n rows (1-indexed). We start by writing 0 in the 1st row. Now in every subsequent row, we look at the previous row and replace each occurrence of 0 with 01, and each occurrence of 1 with 10.

For example, for n = 3, the 1st row is 0, the 2nd row is 01, and the 3rd row is 0110.
Given two integer n and k, return the kth (1-indexed) symbol in the nth row of a table of n rows.

 

Example 1:
```
Input: n = 1, k = 1
Output: 0
Explanation: row 1: 0
```

Example 2:
```
Input: n = 2, k = 1
Output: 0
Explanation: 
row 1: 0
row 2: 01
```

Example 3:
```
Input: n = 2, k = 2
Output: 1
Explanation: 
row 1: 0
row 2: 01
``` 

Constraints:
```
1 <= n <= 30
1 <= k <= 2n - 1
```

## 日本語での要約
初期値0で、0が01、1が10に置換されていく数列を考えます。下記がrow5まで求めたものです。
row1 : 0
row2 : 01
row3 : 0110
row4 : 01101001
row5 : 0110100110010110

今回の問題では、nとkが与えられ、row{n}の左からk番目の数字を返します。回答例はコピペのExampleを見てもらえればわかると思います。

# 考察
## シンプルな解法
まず純粋に上のようにrow nに至るまで数列を生成していく方法を考えます。その時の時間計算量は $O(2^n)$ です。制約条件はn<=30であることを考えるとこのアルゴリズムでは難しそうです。

## 再帰を用いた解法
### 分析
row5とrow4を比べます。
- row4 : 01101001
- row5 : 0110100110010110

row5を前半と後半で区切ると、
- row4 : 01101001
- row5 : 01101001 10010110

row5の前半がrow4と一致しており、row5の後半がrow4を反転したものと一致しています。  

row4とrow3に関しても、同じことが言えます。
- row3 : 0110
- row4 : 0110 1001

今回はこれを利用します。

### 定式化
これらの事象を定式化すると、

row{n}のk番目の数字は、
- $1<=k<=2^{n-2}$ の時、row{n-1}のk番目の数字と等しい
- $2^{n-2}<k<=2^{n-1}$ の時、row{n-1}のk番目の数字の反転と等しい


と言うことができます。これはまさしく再帰で解くことができます。これをコードに落とし込むことができれば解けます。時間計算量は$ O(n) $です。

### 解法コード

```python
class Solution:
    def kthGrammar(self, n: int, k: int) -> int:
        def calc(n,k):
            if n==1:return 0
            mid=2**(n-2)
            if k>mid: return 1-calc(n-1,k-mid)
            else: return calc(n-1,k)
        return calc(n,k)
```

# おわりに
LeetCodeに関する日本語の記事はまだまだ少ないのでこれから増やしていきたいですね。
PowerShell Tips

# 環境変数PATHを表示

```powershell
PS> $env:Path
```

https://qiita.com/gx3n-inue/items/00ee48996e973050a440

# which コマンドの代わり

## コマンドレット

python の場所を調べる場合
```powershell
PS> Get-Command python | Format-List

（略）
PS> gcm python | fl
```

https://qiita.com/Hiraku/items/e42bc5756157949a9742

## プロファイルの場所を確認

```powershell
PS> $profile
```

## プロファイルに登録
上述のコマンドレットを which 関数として登録する
```powershell
function which ($cmd) {
  Get-Command $cmd | Format-List
}
```
which コマンドが使用可能になる
```powershell
PS> which python
```
Tensorflowの自動微分を使用したfitting 

# 目的

今更だけどtensorflow2.0あんま使ったことなかったのでお試しにいくつかやっていく予定。1.~と比較してnumpyの値がそのまま使用できたりSessionが無くなったり結構pytorchっぽくなった模様。

本記事では簡単な 
```math
y = 2x + 1
```
回帰の重みw = 2, b = 1を自動微分によってfittingする

# 事前準備

以下のパッケージが必要

- tensorflow (2.0以上)
- matplotlib
- numpy (多分tensorflowが入れば自動で入る)

# データ作成

y = 2x + 1にちょこっとノイズを加えたdataset_y, dataset_yを作成する。

```python
n_sample = 100
dataset_x = np.random.rand(n_sample)
dataset_y = 2 * dataset_x + 1 + np.random.normal(0, 0.05, n_sample) # ちょこっとノイズ加える
```
plot結果はこんな感じ


![dataset.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1154503/7d6e46a3-85ca-f4c9-612a-ca0581098efd.png)

# 目的関数(重みパラメーター)の作成

傾きw, 切片bを定義。初期値はとりあえず0でいい。

```python
w = tf.Variable(np.zeros([1,1])) 
b = tf.Variable(np.zeros([1,1])) 
```

これで入力xに対して目的関数を
```python
y = w * x * b
```
で計算できる。pytorchと同じように普通に変数っぽく扱えてtensorの中身を確認できるのはめっちゃ便利になってる。

# 自動微分の計算

目的関数の傾きと切片を計算するためには計算したy(y = w * x + b)と真の値(datset_y)の誤差が最小になるようなw, bを探せば良いので

```math
w, b = argmin (y_{dataset}- w \times x_{dataset} + b )^2
```

となれば良い。
```math
loss = (y_{dataset}- w \times x_{dataset} + b )^2 
```
に対して以下の微分
```math
\frac{\delta loss }{\delta w} \\
\frac{\delta loss }{\delta b} \\
```

を計算して、lossが小さくなるようにw, bを更新していけば良い。


tensorflowでは自動微分ように`tf.GradientTape`というモジュールがある。
公式のドキュメントはここ[tf.GradientTape](https://www.tensorflow.org/api_docs/python/tf/GradientTape?hl=ja)

今回は上記のlossに対しての微分なのでコードは以下のようになる

```python
x = tf.constant(dataset_x)
with tf.GradientTape() as t:
    t.watch(x) # tf.constantはwatachが必要らしい
    y = w * x + b # object function
    loss = tf.reduce_sum(tf.multiply(y - dataset_y, y - dataset_y)) # loss function
# 元の入力テンソル w, b に対する loss の微分
dloss_dparams = t.gradient(loss, [w, b]) # 自動微分
w = tf.Variable(tf.subtract(w, dloss_dparams[0] * 0.001)) # 値の更新
b = tf.Variable(tf.subtract(b, dloss_dparams[1] * 0.001)) # 値の更新
```

x, bに対する微分は同時にやってくれるっぽい。`t.gradient`の結果は普通にlistで微分結果のtensorが入っていた。
`x = tf.constant(dataset_x)`はdataset_xはnumpy.arrayなので`tf.GradientTape`で扱えるようにtf.constantに変換した。

※せっかく`tf.Variable`はmutableなのにミュータブルっぽくない書き方になってしまっている。そもそも`tf.subtract`はtf.Tensorを返すので上記のコードのように重みを更新する際は使用しないっぽい。

実際の重みパラメーターの更新はtensorflowでは普通は`tf.optimizer`を使用するので後述する。

learning_rate = 0.001で100回学習したコードはこちら

```python
w = tf.Variable(np.zeros([1,1])) 
b = tf.Variable(np.zeros([1,1])) 
x = tf.constant(dataset_x)
loss_log = [] # lossの推移記録用
n_step = 100 # 学習回数
for i in range(n_step):
    with tf.GradientTape() as t:
        t.watch(x) # tf.constantはwatachが必要らしい
        y = w * x + b # object function
        loss = tf.reduce_sum(tf.multiply(y - dataset_y, y - dataset_y)) # loss function
    # 元の入力テンソル w, b に対する loss の微分
    dloss_dparams = t.gradient(loss, [w, b]) # 自動微分
    w = tf.Variable(tf.subtract(w, dloss_dparams[0] * 0.001)) # 値の更新
    b = tf.Variable(tf.subtract(b, dloss_dparams[1] * 0.001)) # 値の更新
    loss_log.append(loss)
```
Javaの同値性と同一性についてまとめてみた

Javaで同一性と同値性について調べてみたのでまとめてみました。

# 同値性と同一性の違い

配列、もしくは変数に同じ値かどうかを調べるのか、同じインスタンスで生成されたかどうかを調べるのか
が違います。

配列、もしくは変数に同じ値が入るかどうかを調べるのが同値性

同じインスタンスで生成されたかどうかを判定するのが同一性です。

ここでポイントになるのは、同値性は同じインスタンスで生成されているかいないかは関係ありません。インスタンスを仮にまたいだとしても、同じ値が格納されているのかどうかで判定します。

# 同値性と同一性はどうやって判定するのか

同値性は`equals`

同一性は`==`で判定します。

# サンプルコード

試しに同値性と同一性を判定してみましょう。

```Main.java
class Main {
    public static void main(String args[]){
        Integer a = 127;
        Integer b = 127;
        //変数aと変数bの同一性の判定をする
        Boolean judge = 
            a == b;
    
        System.out.println("同値性の判定" + a.equals(b));
        System.out.println("同一性の判定" + judge);
        System.out.print(a);
    }
}
```

このようにして`equals`と`==`を判定すると、出力結果は

```
同値性の判定true
同一性の判定true
```

となります。
同一性の判定ではa,bがtrueになるのはわかるのですが、IntegerはIntegerオブジェクトなので宣言して呼び出されているたびにインスタンスが生成されているはずなのです。しかし、同一性の判定でtrueになるのはなぜでしょうか。
それは、

```
「Java側が無駄にインスタンスを生成してメモリを無駄に食わないように、インスタンスを生成するということを開発者が宣言しない限り、ある程度までは同じインスタンスの値(同一性がある)という判定がされる」
```

からです。
この「ある程度」というところがポイントです。
この範囲は、
127までです。

試しに、変数aと変数bの値を128にしてみます。これまで通り考えるのであれば、同一性の判定は`true`になります。

```Main.java
class Main {
    public static void main(String args[]){
        Integer a = 128;
        Integer b = 128;
        //変数aと変数bの同一性の判定をする
        Boolean judge = 
            a == b;
    
        System.out.println("同値性の判定" + a.equals(b));
        System.out.println("同一性の判定" + judge);
        System.out.print(a);
    }
}
```

しかし、128に両方の変数の値が変わってしまうと

```
同値性の判定true
同一性の判定false
```

となります。
AWS Amplify + Ionic(Angular) で、AWSにデータを簡単に保存・取得する(2)

# はじめに
前回に引き続き、AWS上にWebアプリのデータを簡単に保存・取得する方法を考えていきます。
今回は、GraphQLスキーマーの編集をします。

# 関連ページ
https://qiita.com/too/items/fae2879ea36f00c3ae10
https://docs.amplify.aws/cli/graphql/authorization-rules/

# @authの設定
AWS Amplifyで作成した GraphQLのスキーマーは、初期状態では、ほぼ下記の様になっています。

```graphql:schema.graphql
# This "input" configures a global authorization rule to enable public access to
# all models in this schema. Learn more about authorization rules here: https://docs.amplify.aws/cli/graphql/authorization-rules
input AMPLIFY { globalAuthRule: AuthRule = { allow: public } } # FOR TESTING ONLY!

type Storage @model {
  id: ID!
  data: String!
}
```

この中に、気になる文言があります。

```
# This "input" configures a global authorization rule to enable public access to
# all models in this schema. Learn more about authorization rules here: https://docs.amplify.aws/cli/graphql/authorization-rules
input AMPLIFY { globalAuthRule: AuthRule = { allow: public } } # FOR TESTING ONLY!
```

``` FOR TESTING ONLY! ``` とは、気になる文言ですね。。。
上記の指示通り、```https://docs.amplify.aws/cli/graphql/authorization-rules/```で確認してみました。

なになに、、、。```input AMPLIFY { globalAuthRule: AuthRule = { allow: public } } # FOR TESTING ONLY!```が記述してあると、誰でもCreate/Read/Update/Deleteができる状態になります。


ということで、スキーマ定義を直していきます。

まず、上記の一文をコメントアウトします。

代わりに データモデルに対して、```@auth```でアクセス権を設定します。
今回の場合、誰でもアクセス可能としたいので、```allow:public```を設定します。

```graphql:schema.graphql
# This "input" configures a global authorization rule to enable public access to
# all models in this schema. Learn more about authorization rules here: https://docs.amplify.aws/cli/graphql/authorization-rules
# input AMPLIFY { globalAuthRule: AuthRule = { allow: public } } # FOR TESTING ONLY!

type Storage @model @auth(rules: [{ allow: public }]){
  id: ID!
  data: String!
}
```

上記修正後、```amplify push```を実施して、スキーマー設定を反映させます。

今回の場合、```@auth```を　```allow:pubic```にしましたが、
Cognitoを使ったユーザー認証を行なって、
自分のデータ以外アクセスできない様にしたい場合は、```allow:owner```を設定します。


以上です。
M5Stack-CoreInkにBLE経由で文字列を表示する(その3) <M5StickCをBLEClientにする>

[その2](https://qiita.com/sushisushiBoo/items/2a01d5098469e598afe1)の続き

# やりたいこと

### step3

 1. M5StickCをBLEClient（セントラル）として動作させる
   - 置く向きよってCoreInkに送る文字列を選択させる、またはボタンで選択
   - ボタン押下でscan、connect、write実行
 1. M5StickCをBLEClient(セントラル）として動作させる
   - CoreInkのボタン状態がオンならば、表示、ブザー鳴動させる（やらないかも）

# 参考
 - [M5StickC(ESP32)でダイソーのBluetoothシャッターを操作(1.0.4対応版)](https://lang-ship.com/blog/work/m5stickc-esp32-bluetooth-shutter-1-0-4/)
MySQL学習ならこれを作れ！！1分で作るテストデータ入り MySQL 学習環境(webGUIツール付き)

 # はじめに

mysqlを学習したいときに、mysqlサーバをたてたり、テストデータを用意するのはすごく大変です。
そこで、今回はmysql学習に最適なDockerを利用したテストデータ入りのmysql環境の構築方法についてご紹介します。

# 対象読者
- mysqlサーバーの立て方がわからない人
- Dockerについてあまりしらない人

今回利用するファイル郡はこちらのリポジトリで管理しています。

https://github.com/hgaiji/mysql-learning-docker

# 環境構築手順

## 事前準備
事前準備として、環境構築に必要となるパッケージのインストールをしておきましょう。
以下のURLよりインストールをおこない、gitやDockerコマンドが利用できる状態にしておいてください。
- Git

https://git-scm.com/downloads
- Docker

https://www.docker.com/get-started

## 手順
事前準備が終わったら、以下の手順に従って、環境構築を行います。

1. 該当リポジトリをcloneする
  ```shell
  $ git clone https://github.com/hgaiji/mysql-learning-docker
  ```
2. コンテナ環境起動

```shell
$ docker-compose up -d
```

これだけで完了です。
http://localhost:4040 にアクセスして、phpmyadminの画面が出力されれば成功です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308470/07009822-da93-3829-101f-b2f39e4cc36e.png)

## テストデータ確認方法
http://localhost:4040 にアクセスして、左のworldデータベースを選択すると、各テーブルの情報を確認することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308470/bc58aef9-fdbc-73cf-7555-4900c397833c.png)

また、 適当なテーブル(`city`)とかをクリックし、画面上部のSQLをクリックすると、SQL実行画面がでてきます。こちらに好きなSQLを実行することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308470/ac4919d4-4b0e-fd48-fed9-e80e9cc240ff.png)

データ内容

テストデータには[worldデータベース](https://dev.mysql.com/doc/index-other.html)を利用しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308470/18b9c24f-f702-e71d-a7d5-da85594981fb.png)

# 最後に

今回はdockerを利用してテストデータ入りのmysql環境構築について記載しました。
わからないことやこんな記事書いてほしいなどありましら、どしどしコメントお待ちしています。
streamlitを使用したアプリ公開方法

streamlitを使用したアプリ公開方法をメモとして記載する。

vscodeでコードを書き終えたらterminalで以下のように記載。

```
PS C:\Users\sn112> cd 開きたいファイル名
PS C:\Users\sn112\Python\webapi> git init
Initialized empty Git repository in C:/Users/sn112/Python/webapi/.git/
```
githubでリポジトリ作成後のURLをorigin以降に記載 ※()は不要
```
PS C:\Users\sn112\Python\webapi> git remote add origin （ex:https://github.com/～）
```

git add .でwebapi内すべてをコミットの対象にする。
　※git addと.の間にスペース必要
　※git add　●●.pyでファイルを指定することも可能。
git commit -m 'コメント'でコミット

795b131がコミットID,コミットを識別する
```
PS C:\Users\sn112\Python\webapi> git add .
PS C:\Users\sn112\Python\webapi> git commit -m '1st commit'
[master (root-commit) 795b131] 1st commit
```

pushでローカルリポジトリの変更内容をリモートリポジトリに送信
```
PS C:\Users\sn112\Python\webapi> git push origin master
```

githubに移動して確認して問題なければ公開完了。
【Lint】vscodeでpep8のチェックをする手順【Python】

Pythonのコードフォーマットツールについて紹介します。

# コードフォーマットツールとは
## autopep8
自動でPEP8スタイルガイドに準拠するようにするフォーマッタツールです。
`autopep8 --in-place <filename>`とコマンドを実行するとpep8に準拠したコードへ整形してくれます。
また、設定によりファイル保存時に整形するようにできます。

## flake8
Pythonのコードチェックツールです。
pep8などコーディング規約に違反したコードがないかチェックしてくれます。

# 設定方法
## 説明
今回はvscodeにてautopep8とflake8を設定する方法を紹介します。
flake8はコードチェックのみですが、autopep8は違反コードを自動修正してくれるので用途に応じて使い分けてください。
両方使用する人が多いです。

## vscodeへの設定
こちらを参考にすることでautopep8とflake8を設定できます。

http://trelab.info/visual-studio-code/python-vscode%E3%81%A7autopep8%E3%82%92%E9%81%A9%E7%94%A8%E3%81%99%E3%82%8B/

### クォーテーション(引用符)の統一
デフォルトのflake8ではファイル中の「シングルクォーテーション」、「ダブルクォーテーション」の混在をチェックできません。
チェックするためにはこちらを参考に「flake8-quotes」をインストールします。

https://dev.classmethod.jp/articles/flake8-plugins-and-format-tools/#toc-8

### settings.jsonの設定
さらに細かな設定は「settings.json」から設定することができます。
settings.jsonの場所はこちらを参考にしてください。

https://maku.blog/p/tfq2cnw/

---

例えば、インデントをスペース2つ分をコーディング規約として設定できます。

https://qiita.com/ksh-fthr/items/7cf8b5f2fde82d1c6bf7

#### 注意点
##### autopep8とflake8を両方使用している人向け
settings.jsonの「python.formatting.autopep8Args」と「python.linting.flake8Args」に設定した「--ignore=」のエラーコードが異なる場合、autopep8で自動整形してもflake8のエラー表示が消えず、二度手間のような状態になるので同じ値を推奨します。

###### 例

```json:settings.json
{
  "python.linting.flake8Enabled": true,
  "python.linting.flake8Args": [
    "--ignore=E111, E114, E402, E501"
  ],
  "python.formatting.provider": "autopep8",
  "python.formatting.autopep8Args": [
    "--ignore=E114, E402, E501"
  ],
  "[python]": {
    "editor.formatOnSave": true
  }
}
```

autopep8で自動整形後もflake8エラーの`E111`が表示され続ける。

# エラーコードの詳細
flake8等で表示されるpep8のエラーコードはこちらを参考にしてください。

https://qiita.com/KuruwiC/items/8e12704e338e532eb34a

# 参考
https://qiita.com/Sassy1123/items/bfb1ad0eaf1dfdd97dbc
firebaseでカウントアップさせる方法

firebaseでボタン押したらカウントアップするのを作っていたのだけど、realtimedatabaseを使う場合に
書き込みができるようになってるのは、避けた方が良さそうで、書き込みの権限をオープンにするのも問題があるので、まずルールを

```json:qiita.rules
{
  "rules": {
    ".read": true,".write": false
  }
}
```

これで書き込めなくなった。
取得方法はいくつもあるので割愛を

書き込み方法はfirebaseのfunctionsを利用しようと思う。

```javascript:qiita.js
const helloWorld = httpsCallable(functions, 'hello');
helloWorld();
```

こんな感じにhelloという関数を呼びたいとする。
（functions自体、データベースのアクセスをキーにできたりもするけど、今回は普通に通信を使う。）

```javascript:qiita.js
exports.hello = functions.https.onRequest((request, response) => {
	response.set('Access-Control-Allow-Origin', '*');
    const postsRef = admin.database().ref('count/no01');
    postsRef.set(admin.database.ServerValue.increment(1));
});
```

こんな感じで登録するのだけど、動かない。みたいな事がある。
その場合は、上部に

```javascript:qiita.js
const functions = require("firebase-functions");
const admin = require('firebase-admin')
admin.initializeApp()
```

を記載すると、動作する。
ServerValue.increment
が便利だけど、簡単なカウントアップ用のデータベースが完成した。

====追記

ここまでやって、連続で実行をすると、タイムアウトが発生する。しかも完了まで、結構時間がかかる。

onRequestで返し値を送らないといけないみたいだが、送らなくても勝手に返してくれてる時もあって、結構不便だった。

```javascript:qiita.js
const param = request.query.param;
res.status(200).send(param)
```

この戻り値で200を送ると、タイムアウトしないで、追える。


```javascript:qiita.js
exports.hello = functions.https.onRequest((request, response) => {
	response.set('Access-Control-Allow-Origin', '*');
    const postsRef = admin.database().ref('count/no01');
    postsRef.set(admin.database.ServerValue.increment(1));
    const param = request.query.param;
    res.status(200).send(param)
});
```

これで、今まで、数百ミリ秒処理が終わるのにかかっていたのが治った。10ミリ秒もなく処理が終わる
ConnectとLex連携する際、Lexの カスタムスロット の聞き取り精度を上げる方法

# はじめに
ConnectとLex連携する際、カスタムスロットのスロットをなかなか聞き取れなかったため、
聞き取りの精度を上げる方法について、記載します。

具体的には、Connectの電話番号に電話し、Lexが呼ばれた際、`ファミリーマート`と発話しましたが、聞き取ってくれませんでした。


ConnectとLex連携方法は、下記の記事を参考にしてください

https://qiita.com/holdout0521/items/3d81a9a5a9131d270d4d

# Lexのカスタムスロット

`スロット値に制限`を使用し、スロット値`ファミリーマート`を設定します。
![スクリーンショット 2022-02-27 18.27.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/996f0f38-18aa-5180-96ad-b455270901f0.png)



# 精度をあげる方法
精度をあげる方法は結論から言うと、Lexでの聞き取りを失敗した後、CloudWatchLogsで、Lexで使用しているLambdaのログを見て、Lexが聞き取った言葉をカスタムスロットに反映させることです。

上記で設定した`ファミリーマート`が聞き取れなかった場合、lexで使用しているLambdaのログを見てみましょう。

ちなみに、Logに出力するには、以下のように`event`を`print`等で出力するとよいです。

```py:Lexで使用しているLambda
def lambda_handler(event, context):
    print (event)
    return dispatch(event)
```

LexのLambdaへのレスポンス(eventのログ)は、以下のようになっておりました。
一部省略しています。

```json
{
    "requestAttributes": {
        "x-amz-lex:accept-content-types": "PlainText,SSML",
        "x-amz-lex:channels:platform": "Connect"
    },
    "sessionId": "afd73d30-683c-4ddf-97fc-10368b820b50",
    "inputTranscript": "ファミリー マート",
    "interpretations": [
        {
            "intent": {
                "slots": {
                    "destination": {
                        "shape": "Scalar",
                        "value": {
                            "originalValue": "ファミリー マート",
                            "resolvedValues": []
                        }
                    }
                },
                "confirmationState": "None",
                "name": "Reservation",
                "state": "InProgress"
            },
            "nluConfidence": 1
        },
        {
            "intent": {
                "slots": {},
                "confirmationState": "None",
                "name": "FallbackIntent",
                "state": "InProgress"
            }
        }
    ]
}
```

`inputTranscript`と`originalValue`が、`ファミリー マート`となっており、`ファミリー`と`マート`の間にスペースがあることが分かりました。

おそらく、聞き取った言葉を単語ごとに分けているため、`ファミリー`と`マート`の2つ単語を聞き取ったと推測されます。

# Lexが聞き取った言葉をカスタムスロットに反映
`ファミリー マート`をカスタムスロットに加えます。

![スクリーンショット 2022-02-27 18.40.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/2d8278a5-156e-7261-22dd-c41bccc91de6.png)

これで、Connectの電話番号に電話し、Lexが呼ばれた際、`ファミリーマート`と発話すると、しっかり聞き取ってくれました。

それでも、聞き取らない場合、もう一度ログを見て、カスタムスロットに反映させることで、どんどん聞き取り精度が向上します。

# 他の方法
あまりおすすめできませんが、カスタムスロットを`スロット値に制限`ではなく`値を展開（既定）`の方が聞き取り精度が良い場合もあるかもしれません。


![スクリーンショット 2022-02-27 18.47.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/6f84850d-e6d1-62ce-abf7-f4e458e8ab75.png)

私の感覚として、`スロット値に制限`の方が聞き取り精度が良い気がします。

# 組み込みスロットタイプについて
ちなみに、Amazonが用意している組み込みスロットタイプで、`AMAZON.Number`がありますが、`カスタムスロットの方が精度がよかったです。`



![スクリーンショット 2022-02-27 18.50.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/8654e24b-b090-7e21-2b10-90a142563d32.png)


想定している値が`0~9`の場合、カスタムスロットで10個作成をおすすめします。

ただ、想定している値が`0~100`だと、カスタムスロットで設定するのが大変なので、組み込みスロットタイプ`AMAZON.Number`を使用するしかないですね。

# 参考

https://docs.aws.amazon.com/ja_jp/lex/latest/dg/howitworks-builtins-slots.html

https://docs.aws.amazon.com/ja_jp/lex/latest/dg/howitworks-custom-slots.html
Goのmonorepoで共通処理を利用する方法

### はじめに
:::note warn
こちらの記事はzennからの転載となります。
:::

平下CTO@sweeepです。Go言語でのmicroservicesにおけるmonorepo構成と共通処理を利用する方法を解説します。monorepo構成での共通処理の利用を目的としています。
本記事の内容です。
* monorepoフォルダー構成
* utilsで共通処理
* 各microservice側での利用方法
* 実行結果

### monorepoフォルダー構成

monorepo直下にutilsとsrc、src下に各microserviceを配置します。GCP/AWSのデプロイ関連フォルダーもmonorepo直下に置くことが多いと思います。monorepo直下で一括管理し各microserviceのバージョン管理やデプロイの管理がラクになります。

```
.
└─ utils
|  ├── file
|  |   ├── file.go
|  |   └─ go.mod
...
└─ src
|  ├── aservice
|  |   ├── main.go
|  |   └─ go.mod
...
```

### utilsで共通処理の実装

共通処理をutils下にパッケージ名のフォルダー/パッケージ名.goで実装します（以下はfileパッケージのサンプル）。
```Go:utils/file/file.go
package file
...
func CheckFileSize(size int64) (int64, error) {
	if size > MaxSize { // MaxSizeより大きい場合はエラー
		return size, fmt.Errorf("size: %v error: %w", size, ErrFileSize)
	}
	return size, nil
}
```

以下のコマンドでパッケージフォルダー下移動し、モジュール化実施します。

```
$ cd /utils/file
$ go mod init
$ go mod tidy
```


### 各microservice側での利用方法

以下のコマンドで各microservice下へ移動し、モジュール初期化実施します。service下にmain.go配置が必要です。

```
$ cd /src/service
$ go mod init
```
すると、以下のようなgo.modファイルが作成されます。

```Go:src/service/go.mod
module github.com/hirac1220/go/go-monorepo/src/service

go 1.17
```

privateリポジトリのfileパッケージをインポートして利用するために、以下のように相対パスでreplace実施をgo.modに記述します。
```Go:src/service/go.mod
replace github.com/hirac1220/go/go-monorepo/utils/file => ../../utils/file
```

以下のコマンドを実行します。
```
$ go mod tidy
```

これでgo.modにfileパッケージを利用するための記述が追加され、準備ができました。
```Go:src/service/go.mod
module github.com/hirac1220/go/go-monorepo/src/service

go 1.17

replace github.com/hirac1220/go/go-monorepo/utils/file => ../../utils/file

require github.com/hirac1220/go/go-monorepo/utils/file v0.0.0-00010101000000-000000000000
```

利用する箇所でfileパッケージをインポートし、file.関数名で利用します。
```Go:src/service/main.go
package main

import (
	"log"
	"os"

	"github.com/hirac1220/go/go-monorepo/utils/file"
)

func main() {
	// ファイルサイズチェック
	f, _ := os.Open("../../sample/image.jpg") // ファイルオープン
	defer func() {
		_ = f.Close()
	}()

	fi, _ := f.Stat()
	size, err := file.CheckFileSize(fi.Size()) // ファイルサイズチェック
	if err != nil {
		log.Println(err)
	}
	log.Printf("size: %d", size)

}
```

### 実行結果

以下コマンドで各microservice下へ移動し、実行するとmain.goからfileパッケージ呼び出して結果が表示されました。
```
$ cd /src/service
$ go run main.go
2022/02/26 18:30:16 size: 2604
```


### まとめ
今回はGo言語でのmicroservicesにおけるmonorepo構成と共通処理を利用する方法を解説しました。
monorepoを利用することで、各microserviceのバージョン組合せを気にせず管理でき、またデプロイも各microservice毎ではなくmonorepo下を一括デプロイできます。そして、共通処理をutilsへまとめてパッケージ化することで、各microserviceで利用可能となります。

使用したサンプルはこちらのGitHubレポジトリにあります。

https://github.com/hirac1220/go-monorepo

ここまで読んでいただきありがとうございました！