OmniAICreator/Qiita-1.07M huggingface dataset:
Databricks SQLの新たなクエリープロファイルでクエリーを深く理解しましょう！

[Get to Know Your Queries With the New Databricks SQL Query Profile\! \- The Databricks Blog](https://databricks.com/blog/2022/02/23/get-to-know-your-queries-with-the-new-databricks-sql-query-profile.html)の翻訳です。

:::note warn
本書は抄訳であり内容の正確性を保証するものではありません。正確な内容に関しては原文を参照ください。
:::

[Databricks SQL](https://databricks.com/jp/product/databricks-sql)は、DatabricksのレイクハウスプラットフォームにおけるSQLのファーストクラスサポートとデータウェアハウスの機能を提供し、レガシーなクラウドデータウェアハウスの一部のコストでより迅速に新たな洞察を発見、共有するための分析を可能とします。

この記事は、パフォーマンス、使いやすさ、ガバナンスに関する重要な機能をカバーするDatabricks SQLの記事シリーズの一部です。以前のブログ記事では、最新のユーザー体験の強化を説明しました。本記事では、ユーザーによるクエリー自身の理解、クエリーパフォーマンスの理解を支援する機能改善を説明します。

# 実行時のボトルネックを特定することでクエリーのスピードを改善する

Databricks SQLは自動でクエリーを高速化することに長けています。実際のところ我々は[世界記録](https://qiita.com/taka_yayoi/items/b9b25d2050685706a20b)を打ち立てました！これまでの技術革新があったとしても、クエリー実行の内部を検証する必要(例えば、予想以上にクエリーが遅い場合)はあります。だからこそ、クエリー実行の詳細と、計算リソースがどのように消費されているのかを確認できる詳細なメトリクスを提供する新機能のクエリープロファイルをご紹介できることを大変嬉しく思っています。このUIはデータベースを触っていた管理者には親しみやすいものになっています。
![](https://databricks.com/wp-content/uploads/2022/02/get-to-know-your-queries-with-the-new-databricks-blog-new-img-1.png)

クエリープロファイルには以下の機能が含まれています。

- クエリー実行の主要コンポーネントのブレークダウンと関連メトリクス：タスクに要した時間、処理された行数、メモリー消費量。
- 複数のグラフィカルな表現。これには、一覧して遅い処理を特定するための複合ツリービュー、クエリーのオペレーター間のデータフローを理解するためのグラフビューが含まれます。
- 一般的なクエリーの間違いを容易に発見するための機能(例えば、joinの爆発やフルテーブルスキャン)。
- クエリープロファイルのダウンロードや共有機能によるコラボレーションの改善。

クエリーを高速化する一般的な方法論は、まず最も時間を要しているクエリーオペレーターを特定するというものです。我々は分散システムと分散処理可能なオペレーターを取り扱っているので、オペレーターの正確な「処理時間」よりも、タスクの合計の処理時間に興味を持っています。
![](https://databricks.com/wp-content/uploads/2022/02/get-to-know-your-queries-with-the-new-databricks-blog-img-2.jpg)

上述した、あるTCP-Hクエリーのクエリープロファイルか、容易に最もコストを要しているオペレーターを特定することができます。この場合はテーブルlineitemのスキャンとなっています。二番目にコストを要しているのは別のテーブル(orders)のスキャンです。
![](https://databricks.com/wp-content/uploads/2022/02/get-to-know-your-queries-with-the-new-databricks-blog-img-3.jpg)

それぞれのクエリーオペレーターは多くの統計情報を持っています。スキャンオペレーターの場合、メトリクスには読み込まれたファイル、データの数、クラウドストレージの待ち時間やファイルの読み込み時間が含まれます。結果として、どのテーブルを最適化すべきか、あるいは、joinに改善する余地があるかという疑問に容易に回答することができるようになります。
![](https://databricks.com/wp-content/uploads/2022/02/get-to-know-your-queries-with-the-new-databricks-blog-img-4.png)

# クエリー履歴の大掃除

また我々は、クエリー履歴に小さいですが使いやすい改善をしたことを発表できて嬉しく思っています。それぞれのクエリーでアクセスできる詳細情報を増強しました。今では、クエリーのステータス、SQL文、処理時間のブレークダウンと最も重要な実行メトリクスのサマリーを参照することができます。
![](https://databricks.com/wp-content/uploads/2022/02/get-to-know-your-queries-with-the-new-databricks-blog-img-5.png)

SQLエディターとクエリー履歴を行ったり来たりすることがないようにするために、上述した全ての機能はSQLエディターから直接アクセスすることができます。

https://vimeo.com/680586244

クエリープロファイルはDatabricks SQLで利用することができます。[フリートライアル](https://databricks.com/jp/try-databricks)に申し込んでDatabricks SQLを使ってみてください。


### Databricks 無料トライアル

[Databricks 無料トライアル](https://databricks.com/jp/try-databricks)
4年目と2年目のエンジニアで対談してみた vol.2 ~未経験新人エンジニアの失敗あるある(?)~

# 目次
[1. この記事について](#1-この記事について)
[2. まず始めに](#2-まず始めに)
[3. コピペは悪だと思っていた話](#3-コピペは悪だと思っていた話)
[4. 作業効率の話](#4-作業効率の話)
[5. 第2回目対談まとめ](#5-第2回目対談まとめ)

# 1. この記事について
前回のvol.1「エンジニアになってからの成長を振り返る」に引き続き
今回のテーマは**失敗**です。
特に1年目のドキュメントに関する失敗にフォーカスして対談していこうと思います。
本日もＮ先輩、Ｉ後輩でお送りしますm(__)m
※前回の対談をまだご覧になっていない方は[こちら](https://qiita.com/inadadesu/items/d9ef70754778ce37e6f6)へ！


# 2. まず始めに
前回の対談でも少し触れましたが、N先輩、I後輩はともに未経験でこの業界に入りました。
最近では私たちの会社でも、文系出身、プログラミング未経験の採用が増加しており
もし同じような新人の方がいらっしゃれば、共感していただけたり、または失敗を未然に防ぐことにつながれば嬉しいなと思っています！
また、その上司や先輩にあたる方も「うちの部下もこんな考え方をしているのかな～」と思いながら読んでいただけると幸いです。
（あくまで私たちの失敗に基づくお話ですが。。。）

# 3. コピペは悪だと思っていた話
**I後輩：** お疲れ様です！
　　　  今日は失敗についてですね。
**N先輩：** お疲れ様です。そうだね！
　　　　I後輩は1年目の最初ってどんな仕事をしてたの？
**I後輩：** 私はまず画面設計書の作成を任されました！
　　　  その当時は設計書なんて書き方が分からないどころか、見たこともない状態でしたね。 
**N先輩：** まぁそうだよね(笑)
　　　　そこでは何か失敗はあった？
**I後輩：** はい、もちろんです(;^ω^)
　　　   その名も**コピペ封印事件**ですね。。
**N先輩：** コピペ封印とは。。。？
**I後輩：** 今思うとなんでそんな効率の悪いことをしたのかと思うのですが、
　　　 当時上司から既存の設計書をもらって、
　　　 それを参考にして作成するよう言われたのですが
　　　 設計書のテンプレから何もかも自作で作りなおして提出してしまいました(笑)
**N先輩：** おおお。なんでそんな手間を(゜゜)
**I後輩：** 学生時代、レポートを書く時に、ネットからコピペすると
　　　  めっちゃ怒られたじゃないですか(笑)
　　　  それ以来「コピペは悪！」「楽をしようとしている！けしからん！」という考え方が
         　　　  当たり前になっていました。
**N先輩：** なるほど。。。確かにレポートコピペは怒られたよね(笑)
　　　　でも仕事においてコピペは
　　　　　**・正確性を維持できる**
　　　　　**・作業効率のUP**
　　　　　**・楽できる(楽していいんだよ!(^^)!)**
　　　　と、良いことばかりなんだよ～！
**I後輩：** そうですね。。
　　　   その失敗のあと、上司に「clibor（クリボー）」というコピペツールを教えてもらい
　　　   今もずっと使っています。
**N先輩：** clibor使っている人多いよね、私も使ってます！
　　　　ドキュメント系だけでなく、コードにおいても**なるべくコピペするべし！** だね
[※clibor（クリボー）インストールはこちらからできます！](http://www.vector.co.jp/soft/winnt/util/se472890.html)
<h4>★POINT：正確性、効率性UPのためにコピペは有効活用すべし！！</h4>



# 4. 作業効率の話
**I後輩：** 作業効率でいうと最初は議事録を一つ書くのも
　　　 すごーく時間がかかってしまっていました。
　　  　タイピングもへたくそだったので
    　  　　ぐちゃぐちゃの議事メモから清書するのが大変でした。。
**N先輩：** 確かに1年目はそうだよね。
　　　　I後輩が1年目の時にも伝えたけど、やっぱり議事録を効率よく書く一番の方法は
　　　　**自分の中でフォーマットや書式を定める**ことかな？
**I後輩：** 確かにそれを実践するようになってから、議事録が書きやすくなりました。
　  　　**階層分けや見出しの記載方法を自分の中でルール化することで
　　　「どうやったら分かりやすく書けるだろう。。」と悩む時間がなくなりました！**
　　　エンジニアとは言えど、ドキュメント作成能力もどんどん身に付けていきたいですね。
<h4>★POINT：ドキュメント作成時は、自分の中で書式ルールを明確にしておくべし！！</h4>

# 5. 第2回目対談まとめ
よんでいただきありがとうございました！！
今回は「失敗」に関して対談しました。
実は対談の中で出てきた失敗はまだまだあるので、また記事にしようと思います！m(__)m
アプリケーションのタイムゾーンをどう扱うか？

# 課題
- 利用者のほとんどが日本人なので表示は日本時間に合わせたい
- DBやサーバーのタイムゾーンはUTCで入っている

# 考え方
DBにタイムゾーンオフセットをつけて保存すべきという考え方の人もいるが、
MySQLのdatetime型では入らない
そもそもタイムゾーンを考慮した時間というのは、表示側の都合であり、クライアント側が利用ユーザーの利用拠点に合わせて時間表示を切り替えてあげればいいのではないか？

# 結果
### APIのレスポンス
タイムゾーンをUTCに統一
ISO8601の拡張版を利用
タイムゾーンオフセット付き
`YYYY-MM-DD hh:mm:ss+mm:ss`　

### APIのリクエスト
ISO8601の拡張版を利用
タイムゾーンオフセット付き
`YYYY-MM-DD hh:mm:ss+mm:ss`　

### DBに保存する値
タイムゾーンをUTCに統一
ISO8601
`YYYY-MM-DD hh:mm:ss`

# 参考文献
https://www.m3tech.blog/entry/timezone-handling
【WordPressセキュリティ対策】投稿者アーカイブを無効化してWordPressのユーザ名を隠す方法

WordPressで構築したサイトのアクセスログを見ると、ページには表示させていないのに何故かログインアカウントでアタックされている場合があります。
これはWordPressが自動生成する投稿者アーカイブが有効になっているからです。攻撃者はこの機能を悪用して不正ログインを試みます。

## 投稿者アーカイブとは

投稿者アーカイブとは、WordPress が自動生成する投稿者ごとの投稿をまとめる機能のことです。
ちょっと技術的なことを言うと、テーマの`author.php`に規定されているページのことです。
初期状態のWordPressでは投稿者ごとに投稿者アーカイブが作成されます。そのため、WordPressのユーザー名が閲覧者にバレてしまい、大いなるセキュリティの穴となることがあります。

## 投稿者アーカイブを見る方法

WordPressサイトで、以下のようなURLにアクセスすると、対象ユーザーが作成した投稿の一覧ページが表示されます。

```
http://example.com/author/ユーザー名/
```

また、以下のように`?author=1`を付けてアクセスすると、ユーザーIDが1のユーザーの投稿者アーカイブにリダイレクトされます。
リダイレクト先のURLには管理者のユーザー名が含まれるので、WordPressのログインIDがわかってしまいます。

```
http://example.com/?author=1
```

## 投稿者アーカイブのURLの危険性

投稿者アーカイブのURL内に<span style="color: #d61b09">**ログインアカウント名が公開されている**</span>ことになります。
ユーザー名は管理画面のログインに必要となる重要なデータです。不正ログインを試みるには大きな手掛かりになります。あとはパスワードさえ突破すれば不正ログインに成功です。
ブルートフォースアタック（総当たり攻撃）という攻撃手法を用いて、手あたり次第パスワードを利用してログインを試されたら、簡単なパスワード「1111」「1234」「password」などではあっという間にログインされてしまいます。


ちなみに、投稿者のニックネームを設定していても変わりません。
ニックネームを設定していると、投稿ページをはじめとしたフロントページではユーザー名は表示されないので安心なのですが、投稿者アーカイブのURLに限っては、ニックネームで上書きされることはなくユーザー名のままとなります。

また、投稿ページやフロントページに投稿者アーカイブへのリンクを載せない場合もあるでしょう。
しかし、投稿者アーカイブが存在している以上、URLから直接アクセスされたらユーザー名はバレてしまいます。

## 投稿者アーカイブを無効化する

投稿者アーカイブは次のいずれかの方法で無効化することができます。

- author.phpを使用する方法
- functions.phpを使用する方法
- プラグインを使用する方法

今回は、「author.phpを使用する方法」と「functions.phpを使用する方法」を紹介します。

### functions.phpを使用する方法

`functions.php`を利用すると簡単に無効化することが出来ます。
適用しているテーマの`functions.php`に以下のコードを追加します。コピペでOKです。

```
add_filter( 'author_rewrite_rules', '__return_empty_array' );
function disable_author_archive() {
  if( preg_match( '#/author/.+#', $_SERVER['REQUEST_URI'] ) ){
    wp_redirect( esc_url( home_url( '/404.php' ) ) );
    exit;
  }
}
add_action('init', 'disable_author_archive');
```

上記のコードを`functions.php`に追加すると、<span style="color: #d86e00">**投稿者アーカイブにアクセスすると404エラーにリダイレクトされる**</span>ようになります。
これで、投稿者アーカイブが無効化されます。

リダイレクト先を404エラーから変更する場合には、`wp_redirect()`で指定しているURLを変更してください。
例えば、以下のように記述した場合には、投稿者アーカイブにアクセスするとトップページにリダイレクトされるようになります。

```
wp_redirect( esc_url( home_url('/') ) );
```

### author.phpを使用する方法

投稿者アーカイブのテンプレート`author.php`を使用して投稿者アーカイブを無効化する方法もあります。
適用しているテーマの`author.php`に以下のコードを追加します。コピペでOKです。<span style="color: #d86e00">**投稿者アーカイブにアクセスさせないようにすることで無効化する**</span>方法です。

```
add_filter( 'author_rewrite_rules', '__return_empty_array' );
```

テーマによっては`author.php`がない場合があります。
適用しているテーマに`author.php`がない場合には、`author.php`を作成してください。

## 最後に

ログインIDがバレても問題ない、そんなことよりパスワードを強化すべきだ、という意見もあります。
もちろん、パスワードを強化することも非常に重要です。
投稿者アーカイブを無効化したら不正ログインに防げる訳ではないので、セキュリティ強度の高いパスワードを設定することも併せて対応するようにしてください。

また、**投稿者アーカイブを無効化しても、WordPress標準のXMLサイトマップ機能で出力されるXMLサイトマップには、投稿者アーカイブのURLも含まれています。**
現時点では標準のXMLサイトマップ機能は細かい制御ができないため、投稿者アーカイブのURLだけ除外したりすることが出来ません。
<mark>**投稿者アーカイブを無効化する処理と一緒に、標準のXMLサイトマップ機能を無効化する処理も実装しておくのがお勧め**</mark>です。

標準のXMLサイトマップ機能を無効化する方法は、以下の記事で紹介しています。

> **[WordPress5.5で標準搭載されたXMLサイトマップ機能を無効化する方法](https://qiita.com/Taka96/items/ec3859e88153ed68edf1)**
WordPress5.5で標準搭載されたXMLサイトマップ機能を無効化する方法

WordPress5.5からXMLサイトマップを出力する機能が標準で追加されました。
Google XML Sitemapsとか別のプラグインを使ってXMLサイトマップを出力している場合が多いと思います。
そういったすでに使っている機能が重複しないよう、標準のXMLサイトマップ機能を無効にする方法をまとめておきます。

## 追加されたXMLサイトマップ機能

はじめに、新たに標準搭載されたXMLサイトマップ機能についての説明です。
XMLサイトマップ機能はWordPress5.5から自動で有効になっていて、`wp-sitemap.xml`というファイル名でアクセスできます。
`$ドメイン/wp-sitemap.xml`というURLにアクセスすると、下記のようなサイトマップが表示されます。

![xmlサイトマップ-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017333/8a25d874-dd67-556a-6ef5-84e9e5872579.png)

> **補足事項**
> `wp-sitemap.xml`は正確にはサイトマップインデックスファイルです。
> 固定ページや投稿、著者といった種類別に分割された別のサイトマップファイルへのリンクが一覧表示されます。


何の用意をしなくてもXMLサイトマップが出力されるので便利そうにも感じますが、
標準のXMLサイトマップ機能にはごく基本的な機能しかなく、例えば以下のようなカスタマイズは出来ません。

- 「このページはサイトマップに含めたくない」といったページやアーカイブ毎の指定ができない。
- `lastmod` や `changefreq`、`priority` といった要素を設定できない。

このような細かい制御もしたい場合には、現状ではプラグインでXMLサイトマップ機能を実装する必要があります。
プラグインを使用する場合には、機能が重複する標準のXMLサイトマップ機能は無効にしておきたいところです。
以下、無効化する方法について説明します。


## 標準のXMLサイトマップ機能を無効化する方法

標準のXMLサイトマップ機能を無効化するには、`functions.php`に下記コードを追記します。
```
add_filter( 'wp_sitemaps_enabled', '__return_false' );
```
上記のコードを追加後に`wp-sitemap.xml`にアクセスすると、<span style="color: #d86e00">**404ページとなりXMLサイトマップが表示されなくなります。**</span>

上記のコードでは、見た目上ではXMLサイトマップが見られなくなりますが、XMLサイトマップ機能は有効になっています。
以下のコードを追記すると<span style="color: #d86e00">**XMLサイトマップ機能自体を無効化する**</span>ことが出来ます。
```
remove_action( 'init', 'wp_sitemaps_get_server' );
```
上記のコードを追加後に`wp-sitemap.xml`にアクセスすると、404ではなくTOPページが表示されるようになります。

## 標準のXMLサイトマップ機能の危険性

標準のXMLサイトマップ機能で出力されるXMLサイトマップには、投稿者アーカイブのURLも含まれています。
投稿者アーカイブのURL内にログインアカウント名が含まれているため、<span style="color: #d61b09">**XMLサイトマップでログインアカウント名が公開されている**</span>ことになります。
現時点では標準のXMLサイトマップ機能は細かい制御ができないため、投稿者アーカイブのURLだけ除外したりすることが出来ません。

![xmlサイトマップ-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017333/9f52d825-559a-613c-3085-aef7967874fa.png)
![XMLサイトマップ-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017333/c4602f48-d8db-5357-ac9f-2fb8e0c5c52c.png)

ユーザー名は管理画面のログインに必要となる重要なデータです。不正ログインを試みるには大きな手掛かりになります。
あとはパスワードさえ突破すれば不正ログインに成功です。
<mark>**WordPressセキュリティ対策の観点からみても、標準のXMLサイトマップ機能は無効化しておいた方が良い**</mark>と思います。

ちなみに、**投稿者アーカイブにアクセスできないように無効化する処理を実装しても、標準のXMLサイトマップ機能では投稿者アーカイブのURLも含まれた情報が出力されてしまいます。**

## 参考

- [New XML Sitemaps Functionality in WordPress 5.5](https://make.wordpress.org/core/2020/07/22/new-xml-sitemaps-functionality-in-wordpress-5-5/)
受験談 AWS Certified Machine Learning - Specialty 認定

AWS Certified Machine Learning - Specialtyを受験しました。

受験される方の参考になりましたら。

# 前提
2021年
8月：SAA [(受験談)](https://qiita.com/h2m_kinoko/items/5179bcb73b6773771f79 "受験談 AWS Certified Solutions Architect – Associate 認定")
9月：SAP
11月：SOA [(受験談)](https://qiita.com/h2m_kinoko/items/0b05378d96f4246bbdd0 "受験談 AWS Certified SysOps Administrator - Associate 認定")
12月：SCS [(受験談)](https://qiita.com/h2m_kinoko/items/20f06a746ab15540cd37 "受験談 AWS Certified Security – Specialty 認定")
2022年
1月：DVA[(受験談)](https://qiita.com/h2m_kinoko/items/67ec0a97039570524574 "受験談 AWS Certified Developer - Associate 認定")
2月：MLS（←今回ココ）

SAA受験談に私のAWSの事前知識・経験が書いてありますが、業務等での経験はほぼゼロです。
また、機械学習という意味では、G検定を2020年に取得していますが、業務での機械学習などの経験はほぼゼロです。いずれも趣味レベルであれこれ触ってるくらいです。

# これまでの認定試験と違い感じたこと

上記の通り6つ目の認定試験でしたが、これまでの認定試験と明らかに違うなと感じた点が以下です。

#### AWSに特化した設問が少ない

感覚的に６割？７割？くらいは、AI/機械学習の知識があれば正解できる気がしました。

#### Udemyやkoiwa clubとの類似問題

65問中15問、20問くらい？は、見たことあるような問題でした。

#### １問あたりの問題にかかる時間が少ない

勉強中もそうでしたが、１問あたりにかかる時間が比較的少なくて済んだ印象です。問題文が短めのも多かったり、長くても他の認定試験と違い把握するまでにかかる時間が短くて済む印象です。

なので、少ない時間で多くの問題を繰り返し勉強できた気がします。

# 活用したもの

#### 公式サンプル問題

10問ではありますが、雰囲気や難易度をつかむには十分かなと思います。

https://aws.amazon.com/jp/certification/certified-machine-learning-specialty/

#### AWS BenchPrep認定試験練習

無料で模擬問題が20問受けられるので活用しないと損です。

https://amazonwebservices.benchprep.com/

#### koiwaclub

全20節。１節７問なので合計140問。
ひたすら繰り返しました。

https://aws.koiwaclub.com/

#### Udemy

本番想定の６５問が２セットあります。こちらもひたすら繰り返しました。
ただ、他の認定資格の講座と違い、正解の選択肢に関しては解説があるのですが、不正解の選択肢がなぜ不正解なのか？という解説がほとんどないので、迷った時になんでこっちはダメなんだろう？というのを調べるのに苦戦しました。

https://www.udemy.com/course/aws-30-b/


#### Googleスプレッドシート

チートシートです。SAA受験の時から作っているのでだいぶボリューム満載になってきています笑

# 実際の試験

上記にも書いてますが、既視問題が多かった印象とAWSに特化した問題が少なかったです。
個人的にはUdemyとkoiwa clubの問題を繰り返していれば合格ラインに達する気がしました。
一応AWSの他の認定試験とG検定の知識が余韻程度に残っている前提ではありますが、問題のパターン的には上記で十分網羅されていた感じです。

勉強しててちょっと苦戦したのは、Udemyとkoiwa clubで同じ問題でも回答が異なるものがいくつかあったことです。自分なりに調べて納得・理解したつもりなので、それはそれで勉強にはなりましたが結局最後までどっちが正解なの？というのもありました・・。

あと、特に以下3つは頻出サービスになるので、実際に一度はコンソールでポチポチしてイメージを沸かせてみました。理解せずとも操作すると「この単語ってどのサービスの話だったっけ？」というのが思い出しやすくなると思います。

- Sage Maker
- Kinesis
- Glue

# まとめ

SAA＋G検定直後のタイミングの人は、受けちゃってみるのもオススメな気がします。
画像分類モデルの学習・評価用データセットまとめ【機械学習】

先日、[異常検知モデル用のデータセット一覧](https://qiita.com/umapyoi/items/b5942e3fe379c6751b1e)を記事にしましたが、今回は、自分がよく学習や評価に使う画像分類モデル用のデータセットをまとめてみました。

画像分類データセットも（自分で画像を加工すれば）異常検知モデル用のデータセットとして使えるので、個人的には、けっこう重宝してます。


# 画像データセット一覧

### [ADFI](https://adfi.jp/ja/download/)
ノーコードでAI開発ができる無料ツール。サイトでは、異常検知用の画像データセットや画像認識用の画像データセットが無料公開されている。
外観検査や異物混入検査を想定した画像データセットや、路面検査や混雑検知などの画像データセットなど、様々な用途のデータセットがある。
サイトは日本語なのでわかりやすい。

https://adfi.jp/ja/download/


### [MVTec](https://www.mvtec.com/company/research/datasets/mvtec-ad)
論文のベンチマークとして、よく利用される異常検知用の画像データセット。

https://www.mvtec.com/company/research/datasets/mvtec-ad


### [CIFAR-10、CIFAR-100](https://www.cs.toronto.edu/~kriz/cifar.html)
非常に有名な画像データセット。画像サイズが小さい（32×32ピクセル）ので（計算時間が短くなるため）使いやすい。
CIFAR-10は10クラス。CIFAR-100は100クラス。

https://www.cs.toronto.edu/~kriz/cifar.html

### [ImageNet](https://image-net.org/download.php)
非常に有名な画像データセット。データサイズが大きすぎるのと、フルバージョンをダウンロードするためにはログインが必要なのが難点。
1000クラス。

https://image-net.org/download.php

### [MNIST](http://yann.lecun.com/exdb/mnist/)
非常に有名な手書きの数字（０～９）の画像データセット。28×28ピクセルのグレースケール画像なのでデータサイズも小さく、使い勝手が良い。
10クラス。

http://yann.lecun.com/exdb/mnist/

### [Fashion-MNIST](https://github.com/zalandoresearch/fashion-mnist)
MNISTと同じ条件（28×28ピクセルのグレースケール）の服や靴などの衣類の画像データセット。「MNISTだとタスクが簡単すぎる」という人向け。
10クラス。

https://github.com/zalandoresearch/fashion-mnist

### [Office-31](https://faculty.cc.gatech.edu/~judy/domainadapt/)
テレビや自転車などの家具や日用品の画像データセット。元々、Domain Adaptationタスク用に作られたデータセットのため、３つのドメイン（Amazon、DSLR、Webcam）に分かれている。
31クラス。

https://faculty.cc.gatech.edu/~judy/domainadapt/

### [Food-101](https://data.vision.ee.ethz.ch/cvl/datasets_extra/food-101/)
様々な料理の画像のデータセット。
101クラス。

https://data.vision.ee.ethz.ch/cvl/datasets_extra/food-101/

### [FoodX-251](https://github.com/karansikka1/iFood_2019)
様々な種類のパスタなど、分類の難しい料理の画像データセット。
251クラス。

https://github.com/karansikka1/iFood_2019
Blender起動時のウインドウ表示位置を制御する

Windowsのマルチモニタ環境でBlenderを使用している時に
以前は起動時に開くウインドウはプライマリモニタ内だったものが
2.9のある時からセカンダリモニタで開くことがあるようになっているようです

根本的な対策ではないのですが　対処法があったので記録しておきます。

# ショートカットの設定
Blenderをコマンドラインから起動する場合には起動時に設定を変更するオプションがあります

https://docs.blender.org/manual/en/latest/advanced/command_line/arguments.html

また、Windowsのショートカットのプロパティの「リンク先」の項目にこういったオプションを記述すると
コマンドプロンプトでオプションを記述して起動した時と同じ挙動になるようです

これを利用します。

## ウインドウを制御するオプション
上記のCommand Line Argumentsによると

> -p, --window-geometry<sx><sy><w><h>
> Open with lower left corner at <sx>, <sy> and width and height as <w>, <h>.

というオプションが書かれています。
これは
> -p 100 200 1200 800  

とオプションを記述するとディスプレイの左下基準に
横100pixel 上200pixelの位置に　幅1200 高さ800のウインドウを開く　という設定になります

どうやら　セカンダリモニターも含めた左下位置が基準になるようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/6ac1b021-7971-d0db-8779-a71655314181.png)
また面白いことに　複数のディスプレイにまたがるような左下位置とウインドウサイズを指定した場合には
半分以上入っているディスプレイでウインドウが開くようです。

ですので　Full-HDを上下に2枚の並べている私の環境ではショートカットをこのように設定しました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/79b0020d-fee9-5606-ffee-66e99828aa78.png)
実行ファイルのあるパスの後ろに半角スペースを空けて
> -p 0 600 1900 1200

と追記しています

さらに　-M と入れるとフルスクリーンで起動するようです。
## タスクバーとスタートメニューのショートカットの設定
アプリの起動はタスクバーからする場合も多いかと思うので
そちらの設定を変更してみます。
タスクバーに登録している項目は
> C:\Users\[ユーザー名]\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar

にショートカットが登録されているようです。
また、スタートメニューは
> C:\Users\[ユーザー名]\AppData\Roaming\Microsoft\Windows\Start Menu\Programs

の中にblenderフォルダがあってその中に同様にショートカットがあります
それぞれを上記のように　オプションを追記すれば狙った場所に起動できるのが確認できました

参考になれば幸いです。
BigQueryのGUIから空のテーブルを作成する

## やりたいこと
Google CloudのコンソールからBigQueryの空のテーブルを作成したい

## やり方

### Google Cloudのコンソールにアクセス
- Google Cloudにログインし、画面右上の「コンソール」からコンソールにアクセスします
![スクリーンショット 2022-02-23 20.08.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253501/311b568c-036d-7b8c-9742-73e04f982c1a.png)

### プロジェクトを選択もしくは空のプロジェクトを作成
- コンソールの「Google Cloud Platform」の文字の右にプロジェクト選択のプルダウンがあるのでクリック
![スクリーンショット 2022-02-23 20.08.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253501/ecb3d1f9-b17a-0fb6-5f8e-5820912e0d10.png)
- プロジェクト一覧のダイアログが開くので、既存のプロジェクトを選択もしくは新しいプロジェクトを作成
![スクリーンショット 2022-02-23 20.10.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253501/94a63b22-0e52-f6a4-8030-d423a58b1c79.png)

### BigQueryに接続する
- コンソール画面の左のパネルにあるBigQueryをクリックします
![スクリーンショット 2022-02-23 20.13.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253501/22b60f92-a3f6-3ed5-45a9-01699186bdda.png)
- BigQueryのワークスペース(?)が開きます
![スクリーンショット 2022-02-23 21.10.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253501/09ec7232-bb1c-1b01-af06-bdcf18beda6c.png)

### 空のデータセットを作成する
- テーブルが属するデータセット（リレーショナルDBでいうデータベース）を作成します。画面左の「エクスプローラ」でプロジェクトを選択し、「データセットを作成」をクリックします。
![スクリーンショット 2022-02-23 20.54.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253501/cd0d1b7c-7c53-ee03-6f69-6d7ba4cade2e.png)
- データセットIDを入力して保存します。
![スクリーンショット 2022-02-23 20.54.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253501/639b7064-03de-38d1-0946-24f1f1b50e97.png)

### テーブルを作成する
- エクスプローラのさきほどのプロジェクトの下にデータセットが表示されるので、そちらを選択して「テーブルを作成」をクリックします。
![スクリーンショット 2022-02-23 20.55.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253501/695abf5d-897a-4108-21d6-bf41a29e23fa.png)
- テーブル情報を入力して保存します。
![スクリーンショット 2022-02-23 20.56.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253501/5f7fffc1-49c8-a0f8-5802-abdf7a7a98d0.png)

## 参考
- [プロジェクトの作成](https://cloud.google.com/resource-manager/docs/creating-managing-projects?hl=ja#creating_a_project)
- [スキーマ定義を含む空のテーブルの作成](https://cloud.google.com/bigquery/docs/tables#creating_an_empty_table_with_a_schema_definition)
【超要約】ざっくりリーダブルコード

エンジニアの登竜本（？）であるリーダブルコードを読んだので、自分の言葉でまとめてみました。

https://www.oreilly.co.jp/books/9784873115658/

##### 対象者
* 自分
* リーダブルコードを未読で、ざっくり内容だけ把握したい方

##### 読んだ経緯
* 多くのエンジニアが読了していて薦めているので、「可読性」の指標になっていると考えた。
* その為この本に則ったコードを書けば大体の人が読みやすいと感じるコードを書けると思った。
* 今後の自身の開発や人のコードを読む際の意識点として取り入れるため。



# 表面上の改善点
### 理解しやすいコードとは
* 優れたコードとは「理解しやすいもの」、「他の人が見て最短時間で理解できるもの」。
（理解の定義：コードに変更を加えたり、バグを発見できる。他コードとの連携方法が理解できる）
:::note info
**ポイント　コードを理解するまでの時間の短さ＞コードの短さ**
:::

### 名前に情報を詰め込む
* 名前は短いコメント。
見ただけで情報が読み取れる名前をつける。（変数の目的や値を表す）
* 明確な単語選択。
* 具体的な名前をつける。
* 接尾辞、接頭辞を使い情報を追加。（inputByUser)
* あらかじめ長さを決めておく。
* 値の単位を入れる（start_ms など）
* プロジェクト内で一貫性を持たせる。
* 新しくプロジェクトに参画した人が意味を理解できるのか？


:::note info
**ポイント　意味の明確さ＞短さ**
:::

### 読み手に疑問を抱かせない
* 他の意味にとられる名前をつけない。
:::note warn
NG例
**filter**（選択するとも除外するとも受け取れる）
⭕️選択する→**select**  　除外する→**exclude**
:::

* 限界値の設定（max,min）は名前の前につける。
* 範囲の指定（first~last)(begin~end)

### 見た目を揃える
1. 一貫性のあるレイアウト（改行位置を揃える・重複排除）
1. 似ているコードはレイアウトを揃える
1. 関連するコードはまとめて１ブロックにする


* 見た目が美しいほうが当たり前に読みやすい。
* また、見た目が揃えば表面上だけでなく構造の改善にもつながる。
例：列を整列（縦のラインを揃える）→概要が把握しやすくなる。
　　コードを段落ごとに分割し段落ごとに概要コメント追加。

:::note info
**ポイント　（場合によっては）一貫性＞正しいスタイル**
:::

### コメントの目的を理解する
* コメントの目的は**書き手の意図を読み手に知らせる**こと。
* 全体像のコメントと機能要約コメントをする。
* 価値のないコメント…コードを見たらすぐにわかる内容。
* 価値のあるコメント…自分の考えの記録。（なぜこのやり方にしたのか、定数の値にまつわる背景　など）
* コメントの先頭で意味がわかるようにする。

| 例 | コメント内容 |
|:-:|:-:|
| TODO:  | あとで手を付ける  |
| FIXME:  | 既知の不具合があるコード  |
| HACK:  | あまり綺麗ではない解決策をしている  |
| XXX:  | 危険！大きな問題あり  |

### コメントの正確性と簡潔さ
* 曖昧な代名詞を避ける。（それ、これ、ここ　など）
* 関数の動作を正確に記述する。

# ループとロジックの単純化

### 制御フローを読みやすくする
* 条件式の書き方。
:::note info
ポイント
**左側：調査対象の式。変化する。**
**右側：比較対象の式。あまり変化しない。**
:::
* 条件は否定形よりも肯定形を使う。
:::note info
ポイント
**⭕️ if(a == b)**
**❌ if(a != b)**
:::
* 単純な条件を先に書く。
* ネストを浅くする。
（早めに返してネストを削除。失敗ケースをできるだけ早めに関数から返す。）

### 巨大な式を分割する
* コードの式が大きくなればなるほど理解が難しくなる。
* 説明変数を使って巨大な式を分割。
簡潔な名前で式を説明することでコードを文書化できる。
* 要約変数を使う。
（大きなコードの塊を小さな名前に変える）

### 変数
* 変数が多いと追跡が困難になるので、むやみに増やさない。
* スコープを小さくする。
（スコープが大きいと把握に時間がかかる）
* メソッドをできるだけstaticにする。
（メンバ変数と関係ないことがすぐわかる為）


# コードの再構成

### 無関係の下位問題を抽出する
* 関数やコードブロックをみて「コードの高レベルの目標が何か」を考える。
* 関数は小さく独立していれば機能追加がしやすい


### １度にひとつのことを
* タスクが個別に完結しているコードのほうが理解しやすい。
* タスクをできるだけ異なる関数に分割する。
* コードをリファクタリング。
①そこで行われているタスクを列挙。
②別の関数やクラスに分割できるタスクを見つける。

### コードに思いをこめる
* 自分より知識が少ない人でも理解できる簡単な言葉で説明する能力が必要。
* 簡単な言葉でロジックを明確に説明できるようになる。
* 問題や設計をうまく言語化できない場合→自分の中で詳細が明確になっていない。

### 短いコードを書く
* できるだけコードを書かない。
* 過剰に機能を実装しようとしていないか？を見直す。
* コードをできるだけ小さく軽量に。
（重複コードの削除、未使用のコードや無用機能の削除、プロジェクトをサブプロジェクトに分割、コードの重量を意識する）
* ライブラリを有効活用する。
（どんなことができそうかを感じ取れる程度の認識でOK。）


# 選択テーマ

### テストと読みやすさ
* テストコードの可読性と保守性をあげる。
* エラーメッセージを読みやすくする。
* 適切な入力値を選択。入力値の単純化。
* １つの機能に対して複数のテスト。
（別々の方向からバグを見つける）
* テスト機能にもテスト内容を表した名前をつけるべき。
（テストするクラス、関数、状況やバグがすぐに理解できるとよい）
* やりすぎない。
（あくまで本物のコードの読みやすさが第一優先）

### 実践が大事
* 実際にやってみる。
* 他の人に読んでもらう。
* 当たり前にできるようにする。
* 続けることが大事。



他人にも自分にも優しいコードをかけるよう実践します。
Java Silver SE11 10章

# Java Silver SE11 10章
[黒本](https://www.amazon.co.jp/gp/product/4295007625/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1)をもとに学んだことをアウトプットしていきます。
主に問題を解いていて、間違えた箇所もしくは知らなかった内容になります。

## 例外処理
例外が発生したときに、「どのように対処するか」を記述した処理のこと。
Javaでは```try-catch(-finally)```構文で記述する。
```tryブロック```：例外が発生する可能性のある処理
```catchブロック```：例外が発生した時の処理
```finallyブロック```：例外発生の有無に関わらず実行したい処理(省略可能)
例外が発生した時、tryブロックの以降の処理を実行せず、catchブロックに移行される。

### ルール

* try-catch-fianllyの順番は変更できない、変更した場合コンパイルエラーになる
* tryブロックとfinallyブロックは1つのみ、catchブロックは複数記述可能
* catchブロックでreturnしても、戻る前にfinallyブロックが必ず実行される

```java:構文
try {
  // 例外が発生する可能性のある処理
} catch (例外クラス型 変数名) {
  // 例外が発生した時の処理
}

try {
  // 例外が発生する可能性のある処理
} catch (例外クラス型 変数名) {
  // 例外が発生した時の処理
} finally {
  // 例外発生の有無に関わらず実行したい処理
}
```

```java:例題
public class Main {

	public static void main(String[] args) {
		try {
			int array[] = {};
			array[0] = 10;
			System.out.println("finish");
		} catch (ArrayIndexOutOfBoundsException e) {
			System.out.println("error"); 
		}
	}
}
// 結果
// error
```


### 例外
プログラムが対処できるトラブルを```例外```という。
例外は、```検査例外```と```非検査例外```に分かれる。

* 検査例外
  * 例外処理を記述したかどうかコンパイラが検査する例外のこと
  * Exceptionクラスのサブクラスは、RuntimeExceptionとそのサブクラスを除いて、全て```検査例外```に該当する
  * ```try-catch```しているか、```throws句```で宣言している必要がある

* 非検査例外
  * 例外処理を記述したかどうかコンパイラが検査しない例外のこと
  * Exceptionクラスのサブクラスではあるが、```RuntimeExceptionとそのサブクラス```は```非検査例外```として扱われる
  * ```try-catch```と```throws句```はする必要がない (記述は可能)

#### 例外クラス
問題で出題された例外クラスをまとめる。

| 例外クラス | 内容 |
|:---------|:----|
| ArrayIndexOutOfBoundsException | 配列の要素外に対するアクセス  |
| StringOutOfBoundsException | 文字列の範囲外に対するアクセス  |
| IndexOutOfBoundsException  | 配列や文字列、コレクションの範囲外であることを表す。また上記２つのスーパークラスに該当する |
| NullPointerException | nullに対してメソッドを呼び出そうとしている  |
| ClassCastException  | 継承関係や実現関係にないクラスをキャストしようとしている |

### エラー
プログラムが対処できない事態を```エラー```という。
プログラムからは回復不可能なトラブルが発生したことを指している。
例：メモリ不足、読み書きの権限がない、ネットワーク接続できない　など

* Errorクラスがあり、主にサブクラスが使用される
  * OutOfMemoryError, NoClassDefFoundError, StackOverflowError など
  * エラーに分類されるには、Errorを継承する必要がある
* try-catch, throwsを宣言する必要はない
  * プログラムで対処することを求められていないから
  * キャッチして処理をすることは可能


### その他　例題

```java:例題1
public class Main {
	public static void main(String[] args) {
		System.out.println(test(null));
	}

	private static String test(Object obj) {
		try {
			System.out.println(obj.toString());
		} catch (NullPointerException e) {
			return "A";
		} finally {
			System.out.println("B");
		}
		return "C";
	}
}
// 結果
// B A
// catchブロックでreturnしても、戻る前にfinallyブロックが必ず実行される
```


```java:例題2
public class Main {
	public static void main(String[] args) {
		try {
			try {
				String[]array = {"A", "B", "C"};
				System.out.println(array[3]);
			} catch (ArrayIndexOutOfBoundsException e) {
				System.out.println("D");
			} finally {
				System.out.println("E");
			}
		} catch (ArrayIndexOutOfBoundsException e) {
			System.out.println("F");
		} finally {
			System.out.println("G");
		}
	}
}
// 結果
// D E G
```
Laravelとdocker よく打つコマンド

コマンドいちいちぐぐるのめんどいので、自分用メモ
# Laravel
## キャッシュクリア 
```
php artisan cache:clear &&
php artisan config:clear &&
php artisan route:clear &&
php artisan view:clear &&
php artisan clear-compiled &&
php artisan optimize &&
rm -f bootstrap/cache/config.php &&
composer dump-autoload 
```
## make model
```
php artisan make:model Writer -mc
```

## make controller
```
php artisan admin:make GenreController --model=App\\Genre
```
## make migration
```
php artisan make:migration create_brands_table -mc
```
## migration 1つだけ実行
```
php artisan migrate:refresh --step=1 --path=/database/migrations/2022_08_14_222951_create_follow_users_table.php
```

## 開発環境のみ
```
php artisan migrate:refresh
```

## add column
```
php artisan make:migration add_closed_flg_to_schools_table --table=schools
```
```
$table->string('closed_flg')->nullable()->after('city_id');
```

## migration 1つだけ実行
```
php artisan migrate:refresh --step=1 --path=/database/migrations/2022_08_14_222951_create_follow_users_table.php
```
## seeder
```
php artisan db:seed
php artisan db:seed --force
php artisan db:seed --class=TimelineSeeder
```

# Laravel admin
## make controller
```
php artisan admin:make PlanController --model=\App\\Models\\Plan
```
```
php artisan admin:make UserController --model=App\User
```

# docker

## ビルド
```
docker-compose build
docker-compose up -d --build
```
## ログイン
```
docker exec -it container_name bash
```
## DocumentRoot書き換え
```
vim /etc/apache2/sites-available/000-default.conf
/etc/init.d/apache2 restart
```
## docker起動時DB接続できない時
```
alter user 'root'@'%' identified with mysql_native_password by 'root';
```
https://motomotosukiyaki.com/mysql-from-php-server-requested-authentication-method-unknown-to-the-client
## sql通す
```
mysql -u root -proot db_name < /usr/local/etc/mysql.sql
```

## コンテナ作成
```
docker run -i -t -d -v /Users/mirei_hayase/git/:/home/git --name container_name -p 8080:80 -p 3300:3306 --privileged centos:centos7 /sbin/init
```
【個人開発】教員向け授業計画作成サービスを作ってみた。

# はじめに
![teaching_plan.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1185943/ca1828d9-c3fc-75a4-95a4-e25738e5939c.png)

こんにちは、まさやんです。

■運営サービス一部
https://smart-wordpress.com
業界特化、スマートなWordPressテーマ販売サイト『SMART WP』

【今回作成したサービス】
https://teachingplan.msy-a.com/

今回は、以前Laravel＋Vue.jsで作成した**授業計画（指導案）作成サービス**をご紹介したいと思います。

# 要件概要
### ○導入
日々多忙な教員にとって毎回の授業内容（指導案）を**スピーディー**に作成することはとても重要になります。

特に、教育実習生や教員になったばかりの先生は、授業の経験値がなく、毎時間授業の計画を考えることは大きな負担です。自分自身の教育実習に行った経験、教員の友人からのヒアリングから間違いないと思います。

授業計画を効率的に作成することは、**授業の質**に関わり、それは授業を受ける**子どもたちの成長**にも関わってきます。

### ○そもそも？（問題点）
世の中にタスク管理アプリはたくさんありますが、
「**指導案を作成する**」ことに特化したサービスはありません。現場の先生方は、**効率的に**指導案を作成することができていません。

### ○なぜなら？（問題点の裏付け）
指導案を作るために、紙やWordの雛形に毎回書き込んでいるのが現場の現状です。
（ひと昔前の教育実習生は、手書きで書いた指導案がボツになり、指導教官に目の前で破り捨てられ、書き直しさせられたなんて話も…）

### ○だから？（課題）
そのため、WEBサービスを利用し、
「**効率的に指導案を作成するべき**」だと考えます。

### ○そこで！（改善策）
**効率的に指導案が作成できるサービス**があったらどうだろうか？と考えサービスを作成しました。

# サービス概要
### 1.授業を登録
ユーザー登録後にマイページから授業を登録します。
単元名、日付、時限、本時の目標を登録します。
<a href="https://gyazo.com/722a18c82be7c5363598a38cea8c3c5c"><img src="https://i.gyazo.com/722a18c82be7c5363598a38cea8c3c5c.gif" alt="Image from Gyazo" width="1000"/></a>

### 2.授業の詳細を登録
授業詳細画面で、授業計画を作成していきます。
デフォルトで、「導入」、「展開」、「まとめ」の構成になっています。
追加ボタンを押してタスクを追加していきます。
<a href="https://gyazo.com/05f677d987f92ada1e83ebb080db8d07"><img src="https://i.gyazo.com/05f677d987f92ada1e83ebb080db8d07.gif" alt="Image from Gyazo" width="1000"/></a>

### 3.タスクの注意事項を確認
タスクにはそれぞれ、学習活動、時間、留意点が登録できます。
今回は、サクッと授業計画を作ることが目的なので最低限のものだけにしました。
<a href="https://gyazo.com/b209db7804f81347b8625a00403011ed"><img src="https://i.gyazo.com/b209db7804f81347b8625a00403011ed.gif" alt="Image from Gyazo" width="446"/></a>


# 使用技術
- PHP 7.4.12
- Laravel 5.8.38
- JavaScript
- Vue.js 2.5.17
### CSSフレームワーク
- Bootstrap
### フロントライブラリ
- jQuery
- axios
- lodash 
- chart.js
- vue-chartjs
- vuedraggable
### テスト
- PHPUnit
- mocha

# テーブル設計
![スクリーンショット 2022-02-25 19.09.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1185943/939b4a64-5a35-da0a-8fcc-4fde4d3c1229.png)


# 工夫した点
### 非同期処理でユーザビリティを上げる
Vue.jsでaxiosを使用し、タスクの登録・削除を行なっています。
非同期で処理を行うことでサクサク動き、ユーザーにストレスを与えないようにしました。

### ドラッグ＆ドロップで直感的な操作
タスクをドラッグ＆ドロップで移動できるようにしました。
vuedraggableを使って、ドラッグ＆ドロップされるたびに、タスクの並び順を非同期通信で書き換えています。
授業の計画を変更したい場合にも、直感的に変更できます。
<a href="https://gyazo.com/023e269ce6cae899c12e03635a070dca"><img src="https://i.gyazo.com/023e269ce6cae899c12e03635a070dca.gif" alt="Image from Gyazo" width="1000"/></a>

### 授業の時間配分をグラフで可視化
「導入」、「展開」、「まとめ」の時間配分を円グラフで可視化しています。
vue-chartjsを使用し、タスクを登録・削除・移動したときにリアルタイムでグラフが描画されます。
<a href="https://gyazo.com/c7f4da8da2d0acdfddc1069ad21d7336"><img src="https://i.gyazo.com/c7f4da8da2d0acdfddc1069ad21d7336.gif" alt="Image from Gyazo" width="1000"/></a>

# おわりに
最後までお読みいただきありがとうございました！
ITには社会の問題を解決する力があると思っています。
これからも学んで色んな問題を解決できたらと思います。
それでは！
日本語でコメントを書くと怒ってくれるESLintのプラグインを作ってみた

# 概要

日本語での**コメント**や**変数や関数の宣言**を指摘してくれるeslintのプラグインを作成してみました。

チーム内で日本語が得意でない方がいらっしゃったりで、できるだけ全員が理解できる言語でコメントや関数名等を書く必要がある場合は助けになるカモです...😇？

下記でソースコード等を確認いただく事ができます。

https://github.com/K-Sato1995/eslint-plugin-no-jp

https://www.npmjs.com/package/eslint-plugin-no-jp

## ESLintに指摘される例👎

```jsx
// 日本語のコメントを書いているとLintに怒られる
const greeting = () => {
    return "Hello"
}
```

## ESLintに指摘されない例👍

```jsx
// Gotta stick to English
const greeting = () => {
    return "Hello"
}
```

# 使い方

eslintのpluginなのでお手元のeslintの設定ファイルで下記を追加して頂くだけです。(詳細はRepoのREADMEに記載しています)

```jsx
{
    "plugins": [
        "eslint-plugin-no-jp"
    ],
    "rules": [
        "no-jp/no-jp-identifier": 2, // 日本語の関数や変数を認めない
        "no-jp/no-jp-comment": 2 // 日本語でのコメントを認めない
    ]
} 
```

eslintでは`0 ~ 2` はそれぞれ下記の様な意味を持つので、上記の数字を`1` にすることでコードベースの段階的な移行も可能です。

- `0` : ルールを適用しない
- `1` : warn
- `2` : error

# ESLintプラグインの作り方

公式のドキュメントが非常にわかりやすく、下記のドキュメントに沿っていくだけで作成が可能です。

プロジェクトのセットアップ方法からテスト方法まで説明してくれています。

https://eslint.org/docs/developer-guide/

# その他参考にしたページ

- [ESLint: Working with Rules](https://eslint.org/docs/developer-guide/working-with-rules)
    - プラグインの肝となる実際のルールに関してはこちらでとてもわかり易く説明されていました。
- [ESLint: Selectors](https://eslint.org/docs/developer-guide/selectors)
    - AST中で使用したいNodeを参照する為のselectorsに関してはこちらで確認していました。
- [AST Explorer](https://astexplorer.net/)
    - ESLintはEspreeをパーサーとして使用していますが、いちいち手元で生成等していたら面倒ですので、こちらのサイトは非常に便利でした。

# 余談

今までCI/CDは[Travis CI](https://travis-ci.org/) や[CircleCI](https://circleci.com/)を使っていたのですが、今更GitHub Actionsを使用してみました。

GitHubで完結しますし、設定もわかりやすく、ドキュメントも豊富でとてもよかったです🥰
JSONとdict型の相互変換(Python)

元々[Scrapbox](https://scrapbox.io/Mijinko/JSON%E3%81%A8dict%E5%9E%8B%E7%9B%B8%E4%BA%92%E5%A4%89%E6%8F%9B(Python) "JSONとdict型相互変換(Python)")に書いていた内容。
dict型変数の中身をファイルに書き出したい時などに重宝します。

## JSONからdict型へ
### .jsonファイルから読み込んでdict（辞書）型変数に変換
```python
import json
dir = "読み込み先ファイルパス"
encoding = "utf-8"	# 読み込むファイルのエンコードによって適宜変える。
with open(dir, mode="rt", encoding="utf-8") as f:
	data = json.load(f)		# JSONのファイル内容をdictに変換する。
```

### JSON形式の文字列からdict型変数に変換
```python
import json
s = '{"name":"太郎", "value": 100}'	# 読み込む文字列
data = json.loads(s)				# sをdictに変換
```

## dict型からJSONへ
### dict型変数からJSONに変換して保存
```python
import json
dir = "書き込み先ファイルパス"
data = {"name":"太郎", "value": 100}	# 任意のdict型変数
with open(dir, mode="wt", encoding="utf-8") as f:
	json.dump(data, f, ensure_ascii=False, indent=2)
```
- `ensure_ascii`の値をFalseにしないと、asciiにある文字以外はエンコードされてしまう。
- `indent`の値は任意で。
  - `2`とすると半角スペース2個でインデントする。

### dict型変数からJSON形式の文字列に変換
```python
import json
data = {"name":"太郎", "value": 100}	# 任意のdict型変数
s = json.dumps(data, ensure_ascii=False, indent=2)	# JSON形式の文字列に変換
```

# 参考
- [【Python】JSONの読書き｜dump、dumpsの違い | なしブロ](https://nashiza-blog.com/2020/08/16/python-json/)
- [【Python入門】JSON形式データの扱い方 - Qiita](https://qiita.com/Morio/items/7538a939cc441367070d)
ベルマンフォード法

[最短経路問題](https://qiita.com/sibata_yuna/items/9d3f03288422c96af632)

[問題](https://atcoder.jp/contests/abc061/tasks/abc061_d)　:　[動作確認済み](https://atcoder.jp/contests/abc061/submissions/29761003)

(条件) 
N 頂点と M 辺からなる有向グラフ
頂点 1 から N を目指す

(ポイント)
(無向グラフなら)永遠に値を小さくできる

未到達の点も含めて1ループごとにすべての辺を更新する

頂点数ループすると一周する

```c++
using ll = long long;
const ll INF = 1LL << 50;    

int main(void) {
    int N, M;
    cin >> N >> M;
    const int NMAX = 1000; //制約
    const int MMAX = 2000;
    int a[MMAX], b[MMAX]; //頂点 a[i] → b[i]
    ll c[MMAX]; //重み

    for (int i = 0; i < M; ++i) {
        cin >> a[i] >> b[i] >> c[i];
        //c[i] = -c[i]; //最大値を求める場合
    }

    ll dist[NMAX];

    for (int i = 0; i < N; ++i)  dist[i] = INF;
 
    dist[0] = 0;

    //1ループごとにすべての辺を更新する。
    for (int loop = 0; loop < N - 1; ++ loop) {
        for (int i = 0; i < M; ++i) {
             if (dist[a[i] - 1] == INF) continue; 

             if (dist[b[i] - 1] > dist[a[i] - 1] + c[i]) { 
             dist[b[i] - 1] = dist[a[i] - 1] + c[i];
             }
         }
     }
    ll ans = dist[N - 1]; // 最短経路


    bool negative[NMAX]; // 負の経路判定

    for (int i = 0; i < N; ++i) {
        negative[i] = false;
    }
    //もう1周loopさせ、同じ点を通れば負のループが存在する。
    for (int loop = 0; loop < N ; ++ loop) {
        for (int i = 0; i < M; ++i) {
            if (dist[a[i] - 1] == INF) continue;

            if (dist[b[i] - 1] > dist[a[i] - 1] + c[i]) {
                dist[b[i] - 1] = dist[a[i] - 1] + c[i];
                negative[b[i] - 1] = true;
            }
    
            if (negative[a[i] - 1] == true) {
                negative[b[i] - 1] = true;
            }
        }
    }


     if (negative[N - 1])//負の経路なら
         cout << "inf" << endl;
     else
         cout << -ans << endl;

     return 0;
 }
```
aws Lightsail Redmine インスタンスによるチケットシステムの構築

# 最終形

![AWS Networking (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2164727/d433272b-4295-8de0-6cfc-fea66c72240a.png)

# Lightsail Redmine インスタンスを生成する

- インスタンスロケーション: 東京、ゾーンA (ap-northeast-1a)
- プラットフォーム: Linux
- 設計図: Redmine 4.2.3-38
- インスタンスプラン: 3.5 USD

これで http 接続により Redmine が利用可能になります。インスタンスの起動待ち時間を除くと、１、２分の作業で構築完了です。

# 静的 IP をアタッチする

ネットワーキング > 静的 IP の作成

# DNS (Route53) にて サブドメイン で 静的IP をポイントする



# Let's Encrypt SSL 証明書をインストールする

[こちらの一次情報](https://aws.amazon.com/jp/premiumsupport/knowledge-center/lightsail-bitnami-wildcard-ssl-cert/)に従ってインストールします。

一次情報上の「方法１」の「アプローチA」に従って設定を行いましたが、その前にサービスを停止しておきました。

```
$ sudo /opt/bitnami/ctlscript.sh stop
Stoping services..
$
``` 

「6. SSL 証明書と証明書キーファイルを、Web サーバーが現在読み取っている場所にリンクします。」が完了すると、https 通信が可能になります。

# 動作確認

サービス起動

```
$ sudo /opt/bitnami/ctlscript.sh start
Starting services..
$ 
```

ブラウザから https でアクセスする

![スクリーンショット 0004-02-25 19.13.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2164727/875a1746-6fa2-046d-c0d6-24b39ebf1bc6.png)

# 証明書の自動更新を設定する

一次情報の「7. 証明書の自動更新を設定します。」に従って設定しましたので、日次で証明書の自動更新を行なってくれるはずです。実行結果は明日確認してみます。

## 構築時点

```
$ pwd
/opt/bitnami/apache2/conf/bitnami/certs
$ ls -ltr
total 8
-rw-rw-r-- 1 bitnami root 1679 Jan  8 08:42 server.key.old
-rw-rw-r-- 1 bitnami root  981 Jan  8 08:42 server.crt.old
lrwxrwxrwx 1 root    root   52 Feb 25 08:17 server.key -> /opt/bitnami/letsencrypt/certificates/demoru.net.key
lrwxrwxrwx 1 root    root   52 Feb 25 08:18 server.crt -> /opt/bitnami/letsencrypt/certificates/demoru.net.crt
$ 
```

## 24 時間経過後

ちょっと勘違いしていたのですが　/var/log/letsencrypt.log を確認したところ、cron自体は動いていて

```
The certificate expires in 89 days, the number of days defined to perform the renewal is 30: no renewal.
```

と出力されていましたので、おそらく 4/25 頃に証明書が更新されるはずです。

## 4月25日

```
Todo
```

# http 通信を許可しない

Lightsail インスタンスの [ネットワーキング] タブにある IPv4ファイアウォール と IPv6ファイアウォール で 80番ポートをふさぎました。

# メール通知

Redmine は自分に関連する投稿があった場合にメールで通知を受け取ることができます。これである程度チケットの動きが分かりますので、Redmine 上でチケット検索する頻度を下げることができ、とても便利です。

## Amazon SES SMTP認証情報を取得する

[こちらの一次情報](https://docs.aws.amazon.com/ja_jp/ses/latest/dg/smtp-credentials.html) に従い、以下を取得します。

- SMTP ユーザー名
- SMTP パスワード

## Redmine の config に SMTP認証情報を設定する

[こちらの一次情報](https://redmine.jp/faq/general/mail_notification/) の「login認証を行なっているSMTPサーバ(mail.example.com)を使用する場合」に従い設定します。

## メール通知をテストする

上記の一次情報にある「メール通知のテスト」に従いテストメールを送信します。

こちらの環境では 554 エラーが発生していましたが、[こちらの一次情報](https://aws.amazon.com/jp/premiumsupport/knowledge-center/ses-554-400-message-rejected-error/)に従い対応しました。

# 成果物

[https://rm.demoru.net](https://rm.demoru.net)

# 組織

[unremoted.com](https://unremoted.com)
Git管理下のパス名は英語にしましょう

## 起こったこと

VSCodeを使って開発している時に、GitのGUIからファイルをステージングしようとしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139677/8f098ad5-30c2-da2a-b2fc-2d6bdcb34639.png)
↑の「+」ボタンを押して。
そしたら以下のようなエラーが出ました。

```bash
fatal: /path/to/src/App.tsx: '/path/to/src/App.tsx' is outside repository at '/path/to/repository'
```

あれ？？
何もしてないのに壊れたぞ？

## 原因

ググると、同様のエラーメッセージが出る原因は様々あるみたいです。
僕の場合は、**ステージングしようとしたファイルのパスに日本語が含まれていた**ことが原因でした。

## 解決方法

### 1. パスに日本語が含まれないように半角英数字に統一する

根本解決したい場合はこちらが望ましいです。
ただし、既存のレポジトリでこれをしようとするとややこしい場合があります。（名前を変更しようとしたら更にエラーが、など）

### 2. コマンドラインからステージングする

ターミナルから `git add` すると今回のエラーは出ません。

## まとめ

特にGitで管理する場合は、**ディレクトリやファイルの名前は英語にしましょう**。
40 代おっさん GASのCalendarAppクラスについて学ぶ

## 本記事ついて

本記事は プログラミング初学者の私が学習していく中でわからない単語や概要をなるべくわかりやすい様にまとめたものです。
もし誤りなどありましたらコメントにてお知らせいただけるとありがたいです。

## CalendarApp

CalendarAppとは
Calendarサービスの最上位に位置するトップレベルオブジェクト

CalendarAppクラスの主なメンバー
|メンバー|戻り値|説明|
|--------|-----|----|
|createCalender(name,options)|Calender|新しいカレンダーnameを作成する|
|getAllCalenders()|Calender[]|ユーザーが所有または閲覧しているすべてのカレンダーを取得する|
|getAllOwnedCalenders()|Calender[]|ユーザーが所有しているすべてのカレンダーを取得する|
|getCalenderById(id)|Calender|idでカレンダーを取得する|
|getCalendersByName(name)|Calender[]|カレンダー名nameのすべてのでカレンダーを取得する|
|getDefaultCalender()|Calender|ユーザーのデフォルトカレンダーを取得する|

### カレンダーを取得する

カレンダーを取得する方法
・カレンダーIDで取得
・デフォルトカレンダーを取得
・所有または閲覧しているカレンダーを取得

GoogleカレンダーもほかのGoogleアプリケーション同様に一意できまるIDが付与されている。
IDは右側にある３点リーダーアイコンからオーバーフローメニューを開き、設定と共有を選択
設定画面の左側メニューからカレンダー統合をクリックするとカレンダーIDが確認できる。

ユーザーのデフォルトカレンダーであれば、ユーザーのGoogleアカウントのアドレス自体がカレンダーIDに、
別カレンダーであれば「×××××××××××@group.calendar.google.com」になる。

カレンダーIDを用いてカレンダーを取得するには
getCalendarByIdメソッドを使用

構文

```javascript
CalendarApp.getCalendarById(カレンダーID)
```

ユーザーデフォルトカレンダーであれば
getDefaultCalenderメソッドを使用

構文

```javascript
CalendarApp.getDefaultCalendar()
```

お試し

```javascript
function tosiki() {
  const id = '************@group.calendar.google.com';
  const calendar = CalendarApp.getCalendarById(id);
  console.log(calendar.getName());

  const defaultCalendar = CalendarApp.getDefaultCalendar();
  console.log(defaultCalendar.getName());
}
```

### アクセス可能なカレンダーを配列で取得する

アクセス可能なカレンダーを取得するには

getAllOwnedCalendersメソッド

構文

```javascript
CalendarApp.getAllOwnedCalenders()
```

getAllCalendersメソッド

構文

```javascript
CalendarApp.getAllCalenders()
```

＊戻り値は配列となります。

お試し

```javascript
function tosiki() {
  const calendars = CalendarApp.getAllCalendars();

  for (const calendar of calendars) {
    console.log(calendar.getName());
  }
}
```

### カレンダーを作成する

カレンダーを作成するには
createCalenderメソッドを使う

構文

```javascript
CalendarApp.createCalender(タイトル[ ,オプション])
```

オプションはオブジェクト形式で指定できる。
timeZoneのデフォルト値がUTCになっているので日本のタイムゾーン（Asia/Tokyo）に設定するにはオプション設定が必要

createCalenderメソッドのオプション
|オプション|型|説明|
|---------|---|---|
|timeZone|String|カレンダーのタイムゾーン（デフォルト：UTC|
|color|String|16進数の色の文字列(#RRGGBB)またはEnum CalendarApp.Colorsの値を指定|
|hidden|Boolean|カレンダーがリストで非表示になっているか(デフォルト:false)|
|selected|Boolean|カレンダーが選択されているかどうか(デフォルトはtrue)|

カレンダーのイベントの表示・非表示の動作は、selectedが担っていると言うことになる。

お試し

```javascript
function tosiki() {
  const name = 'テストカレンダー';
  const options = {
    timeZone: 'Asia/Tokyo',
    color: CalendarApp.Color.INDIGO
  };

  CalendarApp.createCalendar(name, options);
}
```

## 参考資料

<https://www.amazon.co.jp/%E8%A9%B3%E8%A7%A3-Google-Apps-Script%E5%AE%8C%E5%85%A8%E5%85%A5%E9%96%80-%E7%AC%AC3%E7%89%88/dp/4798064742>
ボタンをpointer-events: autoとしている時のカーソルのアイコンを指定する

## 方法
- cursor: hoge !important;として, cssのスタイルの優先順位を上げることで, cursorのスタイルを設定可能

```
<button style: 'pointer-events: auto; 
cursor: default !important;'>
  ボタン
</button>
```

## 参考
- https://developer.mozilla.org/ja/docs/Web/CSS/cursor
- https://developer.mozilla.org/ja/docs/Web/CSS/pointer-events
ローカル環境で gyazo サーバを立ち上げる

# はじめに
画面キャプチャを簡単に取得して、それを他者と共有するのに [Gyazo](https://gyazo.com/) を利用するのは便利だと思います。しかしキャプチャされる画像が自分の預かり知らないサーバにアップロードされるので、キャプチャした画像を他者と共有しないのであれば、サーバをローカルで立ち上げたいと考えることもあるかもしれません。ここではその方法について紹介したいと思います。

正直なところ、単なる画面キャプチャなので、OS の機能でやってしまえばいいじゃんという話でもありますが、それはそれとして。

情報漏えい防止のために、社内 Gyazo サーバを立ち上げたい場合にも同じ方法が使えると思います。

# 環境
* Windows 8.1（10以降でもできると思います。単に環境がないだけです）
* Visual Studio 2019 Community
* Oracle VM VirtualBox
* Ubuntu-20.04.3

[Gyazowin](https://github.com/gyazo/Gyazowin) をビルドし直す必要がありますので、Visual Studio Community を Windows にインストールしておきます。私の環境は Windows 8.1 でしたので、最新版の 2022 は利用できませんでした。そのため 2019 をインストールしています。

VirtualBox 内で Ubuntu が動いていて、docker が利用可能な状態にセットアップされていることが前提となります。

# 手順
## 設定内容
| 項目 | 値 |
| --- | --- |
| ドメイン名 | gyazo.local |
| 待受ポート | 8888 |

# サーバの準備
## gyazo サーバの起動
[gyazoサーバのDocker環境](https://github.com/nekoya/docker-gyazo)が用意されていますので、こちらを利用させてもらいます。

```bash
docker run -d --name gyazo -p 8888:80 -e GYAZO_HOST=http://gyazo.local nekoya/gyazo
```

## nginx の設定
gyazo サーバを 80 番ポートで待ち受ければ楽なのですが、その場合 Ubuntu で他の web サーバを立ち上げた時に不便なので、nginx で gyazo.local 宛に来たものをポート 8888 番に転送するようにします。

```bash
sudo vi /etc/nginx/sites-available/gyazo
```
```:/etc/nginx/sites-available/gyazo
server {
    listen 80;
    server_name upload.gyazo.local;
    access_log  /var/log/nginx/gyazo.log;
    location ~ / {
        proxy_pass http://localhost:8888;
    }
}

server {
    listen 80;
    server_name gyazo.local;
    access_log  /var/log/nginx/gyazo.log;
    location ~ / {
        proxy_pass http://localhost:8888;
    }
}
```

```bash
sudo ln -s /etc/nginx/sites-available/gyazo /etc/nginx/sites-enabled/gyazo
sudo systemctl restart nginx
```

## gyazo クライアントの準備
**1. Visual Studio Community を起動**
**2. 新しいプロジェクトの作成 を選択**
**3. プロジェクト名を gyazowin として作成**
**4. [Gyazowin](https://github.com/gyazo/Gyazowin) の入手**
**5. %HOMEPATH%\source\repos\gyazowin\gyazowin に gyazowin フォルダの中身をすべてコピー**
**6. gyazowin.cpp の編集**
サーバのドメイン名とCGIファイルのパス名を以下のように変更します。
```cpp
	const TCHAR* UPLOAD_SERVER	= _T("upload.gyazo.local");
	const TCHAR* UPLOAD_PATH	= _T("/gyazo/upload.cgi");
```
**7. ビルド→ソリューションのビルドを選択してビルド**

## VirtualBox の設定変更
設定→ネットワークから`高度`をクリックして、`ポートフォワーディング`ボタンを押します。以下のようにルールを追加して OK を押下します。ゲストIPはお使いのVMのIPアドレスを記載してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42436/38bf8fe1-8173-9c8c-9a2f-cfe55feb1d29.png)

**8. hostsファイルの編集**
Windowメニューを右クリックして `コマンドプロンプト(管理者)` を選択します。コマンドプロンプトから notepad を起動して hosts ファイルを開きます。
```
notepad drivers\etc\hosts
```

以下を記入して保存します。
```:hosts
127.0.0.1	gyazo.local     upload.gyazo.local
```



## テスト
%HOMEPATH%\source\repos\gyazowin\gyazowin\Debub\gyazowin.exe をダブルクリックしてみましょう。以下のように `http://gyazo.local/data/012356.png` のようなURLで表示されれば成功です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42436/d3608888-7ee0-2ebc-64d4-5f6374e769fb.png)

# 参考サイト
* [プライベートGYAZOサービスの構築](https://mistymagich.wordpress.com/2016/05/10/private_gyazo/)
new + saveメソッドとcreateメソッドは返り値が違うよという話



# 発生した不具合
２つの違いに気がつくこととなった契機、
**「新規投稿時にcreateメソッドの成否で条件分岐をさせると全て成功判定となってしまう」**
ということについて説明します。
### 想定していた挙動
新規プロトタイプを作成するため、フォームへ情報を入力し、コントローラーにてDBへの情報登録を行おうという場面です。
新規登録が成功すればroot_pathへ、バリデーションにより失敗すれば新規投稿ページへ遷移するというものです。
以下に２通り描いてみました。

### ①new+saveメソッド
実に馴染み深い記述ですね。

```ruby:prototypes_controller.rb
   def create
     @prototype = Prototype.new(prototype_params)
      if @prototype.save
        redirect_to root_path
      else
        render new_prototype_path
      end
   end
```
まずはじめに、フォームで入力された値を取得し、@prototypeに代入しています。
次にif文の条件式にて、DBへの保存がうまくいけばトップページへ、失敗すれば新規投稿画面へリダイレクトします。
こちらの記述では、想定通りの挙動を確認できます。




### ②createメソッド
それではcreateメソッドで記述をした場合はどうなるでしょうか？


```ruby:prototypes_controller.rb
    def create
      if Prototype.create(prototype_params)
        redirect_to root_path
      else
        render new_prototype_path
      end
    end
```
こちらはcreateメソッドを用いて、DBへ保存できたらトップページへ、失敗したら新規投稿画面へのリダイレクトしようというものです。
一見new+saveメソッドの時と代わりなさそうですね。

ですがこの記述、**新規投稿画面で何も入力せずにフォームから情報を送った場合にもトップページへリダイレクトする(= if文でtrue判定）** という不具合が起こってします。
本来であればバリデーションに引っかかるためDBへ保存できず、createメソッドが失敗し新規投稿画面へリダイレクトするはずです。

一体どういうことでしょうか？

    

# 実は返り値が異なる

実際何が起こっているのか、みんな大好きbinding.pryを用いて確認してみました。
何も入力せず新規投稿ボタンを押し、createアクションの最初で処理を止めた状態です。
(def createの直下です）




```ruby:ターミナル・①new+saveメソッドの場合
[1] pry(<PrototypesController>)> @prototype = Prototype.new(prototype_params)  
=> <Prototype:0x00007fe4375c1520 id: nil, title: "", catch_copy: "", concept: "", user_id: 1, created_at: nil, updated_at: nil>
[2] pry(<PrototypesController>)> @prototype.save
   (0.4ms)  BEGIN
  ↳ (pry):6:in `create'
  User Load (0.6ms)  SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
  ↳ (pry):6:in `create'
   (0.3ms)  ROLLBACK
  ↳ (pry):6:in `create'
=> false
```





```ruby:ターミナル・②createメソッドの場合
  [7] pry(<PrototypesController>)> Prototype.create(prototype_params)
   (0.3ms)  BEGIN
  ↳ (pry):11:in `create'
  User Load (0.5ms)  SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
  ↳ (pry):11:in `create'
   (0.3ms)  ROLLBACK
  ↳ (pry):11:in `create'
=> <Prototype:0x00007fe436ef9260 id: nil, title: "", catch_copy: "", concept: "", user_id: 1, created_at: nil, updated_at: nil>
```
両者の実行結果を見比べると一目瞭然です。（一番下の行）
①のnew+saveメソッドの場合は最終的な戻り値として**false**を返しています。
もちろんバリデーションに弾かれているので、DBへの保存はされていません。

ですが、②の場合falseが返ってきているわけではありません。
実は**インスタンスを返り値としている**んですね。
なのでif文の条件分岐においてtrue判定となり、DBへ保存できていないのにトップページへ遷移してしまっていました。


### 結論

**・saveメソッドは戻り値としてT/Fを返すが、createメソッドはインスタンスを返すのでtrue判定になっていた。**


お恥ずかしながら、普段返り値を意識しないまま記述をしてしまっていたので、今後は気をつけたいと思います。
AppleStoreConnectApiでアップロードしたときにFORBIDDEN.REQUIRED_AGREEMENTS_MISSING_OR_EXPIREDが出たときのお話

### 前提：
使用するアカウントは、2つのAppleDeveloperProgramに所属している。

### 環境：
A社(自社)のAppleDeveloperProgram(Admin権限)
B社(客先)のAppleDeveloperProgram(Admin権限)　

### 運用
開発環境に関わるものはA社(自社)
本番環境に関わるものはB社(客先)
として、証明書などを管理している。


### 何が起きたのか
BitriseでAppleStoreConnectにアップロードするフローがあるのだが、
FORBIDDEN.REQUIRED_AGREEMENTS_MISSING_OR_EXPIREDで転けていた。

本番環境系は全てB社のAppleDeveloperProgramにて管理していて、アップロード用のAppleStoreConnectApiKeyの作成もB社側で
行っていたので、「はて？なんでだ？」という感じで、作成したKeyの権限や他の証明書などを確認した。
しかし、いずれも期限切れなどは起こしていなかった。


### 何が原因だったのか
自社側のAppleDeveloperProgramのライセンス更新がされていなかったがたのがどうやら原因だったらしい。

この辺ブラックボックスでよかわからないけど、最初に所属したのが親になるのか、はたまたipa作る際に、何かしらのA社側の情報が紛れている？(可能性があるのかもしれない)とそうなるのか・・・・・・。
IPsecのIKEパケットは届くのにESPパケットが届かない

# はじめに
タイトルにある事象が発生したので備忘録として残します。
ネットワークの基本的な知識はあっても、IPsecの知識が抜けていたりするとこういうことが起きます。。。

# 前提
この記事でIPsecと言っているのは、**ESPトンネルモード**を指します。

この記事でIPsecの解説はしません。
IPsecについては以下の記事が参考なるのでリンクを載せておきます。
[【図解】初心者に分かりやすいIPsecの仕組みとシーケンス～パケットフォーマット,DPD(keepalive)について～](https://milestone-of-se.nesuke.com/nw-basic/ipsec/ipsec-summary/)

# 結論
長々と書くこともないので、いきなり結論に入ります。

ファイアウォール（以下、FW）で以下の通信のみ許可する設定になっていました。
|プロトコル|ポート番号|
|--|--|
|ICMP|フルオープン|
|TCP|フルオープン|
|UDP|フルオープン|

この設定の場合、IKEはUDPなのでFWを通過しますが、ESPはUDPでもTCPでもない（IPのプロトコル番号50）のでFWを通過できません。
その結果、SAは確立できるけどデータが送れないという事象が発生してしまいます。
ICMPは許可されているのでpingは通ります。
FWの設定でESPを許可したらIPsecで問題なく通信できるようになりました。

# おわりに
ESPパケットだけはじかれることから、FWの設定だと気付くのに時間はかからないと思いますが、事前にFWの設定を確認しておくのは大事だなと感じました。
【PowerPoint】指定名Shapeの表示/非表示を切り替えて擬似的にスライドに余白設定する【VBA】

PowerPointにはどうやら図形の印刷をしない設定がないっぽい

なので下図の様に余白を図形で作って印刷時に表示しないようにして対処してみた。


下図の様に余白を図形を作り、`"shp余白"`と命名。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281933/621e6173-dba1-1924-fd57-37cd127aae79.png)

作り方は四角形2つを重ねて、図形の結合から「型抜き」する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281933/84da2ae8-ba08-4dd3-6889-e5807ecd31e8.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281933/d6c9788e-d612-d290-02ca-c4f6a00b105f.png)


### 作った余白を全スライドに複製する

``` vb 
Sub ppShape複製()

  ActivePresentation.Slides(1).Shapes("shp余白").Copy

  Dim sld As PowerPoint.Slide
  Dim shp As PowerPoint.Shape
  
  For Each sld In ActivePresentation.Slides
    sld.Shapes.Paste
  Next

End Sub
```

### 余白の表示切替をする

``` vb
Sub pp余白の表示切替()
  Const shpName = "shp余白"
  Static v
  v = ActivePresentation.Slides(1).Shapes(shpName).Visible
  Call ppShape非表示にする(shpName, Not (v))
  
End Sub

Sub ppShape非表示にする(shpName As String, Is表示する As Boolean)
  
  Dim sld As PowerPoint.Slide
  Dim shp As PowerPoint.Shape
  
  For Each sld In ActivePresentation.Slides
    For Each shp In sld.Shapes
      If shp.Name = shpName Then
        shp.Visible = Is表示する
        Exit For
      End If
    Next
  Next

End Sub
```


### 印刷時に余白を非表示にする

Excelと違って印刷イベントがないのでpdf出力マクロに図形の非表示プロシージャを入れておく。

https://qiita.com/taleau/items/c51804017995eb7a5c46