OmniAICreator/Qiita-1.07M huggingface dataset:
実務未経験者が 情報セキュリティマネージメント に合格したよ


[実務未経験者が ITパスポートに合格したよ](https://qiita.com/selfstudymaster/items/024ceadd508430da9b59) に引き続き、今回は「情報セキュリティマネージメント編」です。
プログラマーでもエンジニアでもない私が「情報セキュリティマネージメント」に一発合格したので、Qiitaの練習も兼ねて記事を書いてみました。

### 私について
- Not プログラマー
- Not エンジニア
- Not プログラミングスクール
- 完全に独学のみです。エンジニア転職活動中の者です。

### 情報セキュリティマネージメント試験 とは
[情報セキュリティマネージメント試験](https://www.jitec.ipa.go.jp/1_11seido/sg.html)とは、IPA (独立行政法人 情報処理推進機構)が実施する「情報セキュリティマネジメントの計画・運用・評価・改善を通して組織の情報セキュリティ確保に貢献し、脅威から継続的に組織を守るための基本的なスキルを認定する国家試験」です。
〈共通キャリア・スキルフレームワーク（CCSF）レベル2相当〉

- 英語名は Information Security Management Examination 略して SG 通称 セキュマネ

- 試験区分一覧 
![image.png](https://www.jitec.ipa.go.jp/1_11seido/taikei.png)

午前試験と午後試験があります。両方で合格点(6割正解)取れないと不合格となります。
年2回実施されます。ITパスポートとは異なり、いつでも受験できるわけではない点が要注意です。

- 午前試験は短文の選択式問題のみ50問出題される(制限時間90分)
- 午後試験は長文の選択式問題が大問3つ出題される(制限時間90分)


### 情報セキュリティマネージメントを受験した経緯
未経験からのエンジニア転職に向けてIT資格をいくつか取得することにしました。
今春、基本情報技術者試験を受験したのですが、午後試験で落ちてしまいました...
IPAの資格は受験期間が年に1回もしくは2回と決められている資格も多いため、基本情報受験後の採点結果で落としたのを悟った時点で「すぐに受験申し込みのできる資格」を探し、保険として受験したのが情報セキュリティマネージメント取得の動機です。

### 試験対策
午前・午後、ともに過去問サイトで過去問を5年分ほど解きました。
ただし、午後試験対策をして気づきがありました。
基本情報技術者試験の午後試験は「長文問題で解答時間が足りなくなる」ことが知られていますが、この情報セキュリティマネージメントの午後試験も基本情報の午後と同等かあるいはそれ以上に「問題文を読んで解答しきるのにかなり時間がかかるな」と感じました。
そこで、

- 過去問は必ず時間を計って解く。大問1つに対して25分〜30分目安
- 問題のテーマは頻出されるので、過去問を多く解く事で「問題文のパターンに慣れることでパターン認識し、読解にかかる時間を減らすコツ」を覚える
- もし本番で大問1つ解くのに30分以上かかった時に備えて、過去問の演習でも、「大問1つ解くのに30分を超えてしまった場合は5分超過してでも解き切り、次の大問は超過時間分を差し引いた時間内で解き切る練習」をしておく。

これはかなり有効だったと思います。「情報セキュリティマネージメントはさすがに余裕だろう」と高を括って過去問対策をしなかったらおそらく落ちていた可能性は高かったと思われます。**1つの大問あたりの問題文自体が長く、設問数も多い**のです。

本番での正答率は午前が8割、午後が7割程度でしたが、合格することができました。


私は元々基本情報技術者試験の午前と午後の勉強もしており、基本情報の本番でも午前は8割弱、午後は5割強得点できていた(午後あと数点で落ちました...)のですが、情報セキュリティマネージメント試験の午前試験は基本情報・午前試験とは範囲が異なる(狭い)ゆえ「セキュマネ特有の出題もある」と考え、念のために過去問5年分ほどは解きました。実際に特有の問題はあると感じました。

午後試験に関しては前述の通り対策が必要、かつ有効だったと思います。
満点は取れなかったのですが、満点を目指す必要はないと思います。

ちなみに使用したテキストはこちらです。
[令和02年 イメージ＆クレバー方式でよくわかる 栢木先生の基本情報技術者教室 情報処理技術者試験](https://www.amazon.co.jp/dp/B0821W2G51/ref=cm_sw_r_tw_dp_P1JJQS2V9TTP0PC6KQ88)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/522165/209f153c-2dd7-c853-4d54-7fb23a68fda7.png)


合格点は6割と言われているので、「基本情報受験を予定してる方は基本情報・午前テキストを1冊購入し、理解しながら暗記しつつ、過去問を解きまくって正解率8割近くまでもっていく」
これが正攻法かつセオリーかと思います。
「情報セキュリティマネージメント試験」だけに照準を絞って受験される方は、それ専用のテキストも出版されているようなのでそちらでの対策の方が効率がいいかもしれません。
【忙しい人のための】Azureの基礎第4部【Azureのセキュリティ】

AzureについてMS Learnで勉強される場合、第4部は59分のラーニングパスになっています。
ここでは、自身の勉強の復習も兼ねて、MS Learn Azureの基礎第4部の要点をまとめておきますので、Azureの情報を素早く知りたいという方の参考になれば幸いです。
自身の勉強の力点を踏まえて記述するので、詳細な情報を得たい方はMS Learnにアクセスください。

本家様

https://docs.microsoft.com/ja-jp/learn/paths/az-900-describe-general-security-network-security-features/

第3部はこちら

https://qiita.com/enurinri/items/960e2fd90e5d5a896d10

第5部はこちら

https://qiita.com/enurinri/items/9d814e6a5f661d6bc3ba

# Azureによるセキュリティ脅威からの防御
## Azure Security Center
Azure Security Centerは、Azureとオンプレミスの両方で全てのサービスにわたってセキュリティ体制を可視化可能な監視サービス。
代表的な機能として、組織のセキュリティ体制の測定値である**セキュリティスコア**を提供。
また、**Azure Defender**を使えば

* 規制コンプライアンスで業界標準に基づいた評価
* セキュリティ関連の問題を管理者に通知するセキュリティアラート
* リソースセキュリティの検疫

を提供。

## Azure Sentinel
Azure Sentinelは、Microsoftのクラウドベースでの**SIEM**システム。
SIEMとは、複数のログ情報を統合してセキュリティデータを集計し、セキュリティ脅威の検出と脅威の対応に必要な追加機能を用意するもの。

主な機能の種類として、

* 大規模なクラウドデータの収集
* 以前に検出されなかった脅威の検出
* 人工知能による脅威の調査
* セキュリティインシデントへの迅速な対応

が存在。
Microsoftソリューションやその他のサービス及びアプリケーション、業界標準のデータソースへの接続に関するログ情報のような、セキュリティインシデントの分析に使用できる様々なデータソースをサポート。

脅威の検出の仕方として

* 組み込み分析：MSのセキュリティ専門家が設計したテンプレートを使用
* カスタム分析：環境内で特定の条件を検索するために作成するツール

が存在。
Azure Monitorプレイブックにより、脅威への対応を自動化。

## Azure Key Vault
Azure Key Vaultは、アプリケーションの機密情報を中央の１ヶ所に保存するための１元的なクラウドサービス。
シークレット(パスワードなど)・暗号化キー・SSL/TLS証明書の管理や、ハードウェアセキュリティモジュールによってサポートされているシークレットの保存が可能。

Key Vaultを利用する利点として

* アプリケーションのシークレットを一元管理
* シークレットとキーを安全に保存可能
* アクセスの管理と制御が可能
* その他のAzureサービスとの統合

が存在。

## Azure Dedicated Host
Azure Dedicated Hostは、Azure VMをホストする専用の物理サーバを提供するサービス。
専用の物理サーバ(専用ホスト)を利用することにより第三者のVMの影響を受けない。
他者とのハードウェア共有に関するコンプライアンス基準を満たすことも可能。

# Azureのネットワークに関するセキュリティ
前提として、セキュリティには

* 機密性：データへのアクセスは、権利を明示的に付与されたユーザのみが可能
* 整合性：データへの不正な変更を禁止
* 利用可能性：サービスの機能性を維持

の３要素を含む必要がある。

## Azure Firewall
Azure Firewallは、複数の仮想ネットワークを管理可能は**ファイアウォール**。
ファイアウォールとは、ネットワークの送受信を監視し、定義されたルールに基づいて、特定のトラフィックを許可またはブロックするネットワークセキュリティ装置。
Azure Firewallでは、アプリケーションルールとネットワークルールで仮想ネットワーク内のリソースを保護。
ネットワークセキュリティグループやAzure DDoS Protectionのサービスと組み合わせて防御を強化可能。

## Azure DDoS Protection
Azure DDoS Protectionは、**DDoS攻撃**からAzureリソースを保護するためのサービス。
DDoS攻撃とは、アプリケーションのサーバリソースを過剰に消費して使い尽くすことで、アプリケーションを遅延させたり、正当なユーザに対して応答不可能にしたりするサイバー攻撃手法。
MSのグローバルネットワークのスケールと弾力性があればDDoSは軽減可能。
サービスの可用性に影響が及ぶ前にAzureネットワークの境界でDDoS攻撃の可能性がありトラフィックは分析して破棄。

## ネットワークセキュリティグループ(NSG)
NSGは、Azure仮想ネットワーク内でAzureリソースによって送受信されるネットワークトラフックのフィルタ処理が可能になる、内部的なファイアウォール。
Vue.js を学習するための環境を作る

## なぜ作ろうと思ったか
数年前に一回勉強しようと思ったけどあまりできなかったので。。
改めて勉強するために環境を整えようと思いました。
前回は JavaScript で実装しようとしていましたが、今回は TypeScript で実装します。

## 環境
### OS
macOS Big Sur バージョン 11.0.1
### IDE
Atom 1.58.0
### 各種ツール等バージョン
nodebrew 1.1.0
node v14.17.6 LTS（2021/9/13現在）
npm 7.23.0

## Vue CLI のインストール
グローバルに vue-cli をインストール。

```
$ npm install -g @vue/cli
```

@vue/cli 4.5.13 がインストールされました。

**注意**

```
$ npm install -g vue-cli
```
このコマンドを実行すると vue-cli 2.9.6 がインストールされます。
create コマンドは Vue CLI 3系のみのコマンドになるのでこれでインストールすると使えないようです。
もしインストールしていたら

```
$ npm uninstall -g vue-cli
```
上記コマンドでアンインストールしておきましょう。

グローバルに何がインストールされているのか知りたいときは

```
$ npm list -g --depth=0
```

上記コマンドでグローバルにインストールされているパッケージがわかります。

## vue-cli でプロジェクトを作成
ターミナルを開いてプロジェクトを作成したいディレクトリに移動します。
*Git Bash ではうまく動かないのでターミナルを使ってください。*
*Windows ではコマンドプロンプトで動きます。*

```
$ vue create {プロジェクト名}
```
これで作成プロセスに入ります。

```
? Please pick a preset:
> Default ([Vue2] babel, eslint)
  Default (Vue 3) ([Vue 3] babel, eslint)
  Manually select features
```
コマンドを実行すると上記のように表示されます。
TypeScript で実装したい場合は一番下の
`Manually select features
`を選択します。
必要なものを選択できるのでスペースキーで選択していきます。
最後まで選択すると作成できます。

## Atom にインストールしたパッケージ
Vue.js と TypeScript で実装しやすいように以下のパッケージを Atom でインストールしました。

- atom-typescript
    - 以下は atom-typescript で必要になるパッケージ
    - linter
    - linter-ui-default
    - hyperclick
    - intentions
- language-vue

## 最後に
環境を作るところまでなのでここまでですが、
何か間違っているところなどありましたらご指摘ください。
[Ruby] 簡単例: Singleton(オブジェクト)


|本シリーズのトップページ|
|:--|
|[[Ruby] デザインパターンの簡潔サンプルコード集](https://qiita.com/robozushi10/items/b4a43ead438317578ec9)|

# 概要

Singleton の概念などは省略.
単に Ruby でどう書くかだけを書き残す.

## myclass.rb

singleton モジュールの取り込みによって、次が実現する
- new メソッドが非公開になる.
- クラスメソッド「instance」が定義される
- MyClass のインタンス変数には「instance」を使ってアクセスする

```ruby
#!/usr/bin/env ruby
# -*- encoding: utf-8 -*-
# singleton モジュールの取り込みによって、次が実現する
# - new メソッドが非公開になる.
# - クラスメソッド「instance」が定義される
# - MyClass のインタンス変数には「instance」を使ってアクセスする

require 'singleton'

class MyClass
  include Singleton   #!
  attr_accessor :a

  def initialize
    puts "initialize が呼び出されました"
    @a = 0
  end
end

if __FILE__ == $0

  o1 = MyClass.instance
  p o1.a    # => 0
  o1.a = 4  #! 書き込み
  p o1.a    # => 4

  o2 = MyClass.instance
  p o2.a    # => 4

  p MyClass.instance.a  # => 4
end

```


# 参考書籍

・Rubyによるデザインパターン

以上
SEO対策ではHTTPS対応、AMP、Json-ldなどもした方がいい

SEOに強いサイトを目指すのに、HTTPSやAMPやJson-ldなどがgoogleさんのオススメに入っているようです。



知らない人は是非、下記の記事で概要をチェックしてみてください。

 

https://portal-th.com/archives/417
SQL基礎学習

SQLについて、学習したことをアウトプットさせていただきます。
SQLを学ぶ上でハンズオンで勉強したいと思い、[こちらのサイト](https://erogamescape.dyndns.org/~ap2/ero/toukei_kaiseki/sql_for_erogamer_index.php)でSQLを実際に打ち込みながら勉強することができます。
インプットは、[こちら](https://www.youtube.com/watch?v=b2OjUaGBz7A&t=324s)の動画を参考にさせていただきました。

シリーズもので、引き続き勉強させていただこうと思います。

Select文　基本形

```sql
SELECT * FROM テーブル名 
```

*はワイルドカード、selectしたテーブル名は変更することができ、

```jsx
テーブル名 AS 変更したい名前
```

と記載することで、取得したレコードのColumn名を任意に変更できる。

取得する情報が多いと、サーバーに負荷をかけることになるので、LIMITを使用して取得情報を制限してあげると、処理が早くなる。

```sql
SELECT * FROM テーブル名 LIMIT 1000
# 1000行分のレコード取得に制限
```

テーブルを任意の複数選択する際は、

```sql
SELECT users AS 登録者情報, 
       brandfurigana AS ブランド名フリガナ, 
       url AS URL, 
       kind AS 種別
FROM brandlist;
```

と記載して、コンマ区切りで記載していく。

重複した値を削除したものを取得する際には

```sql
SELECT DISTINCT(game_genre)
FROM gamelist;
```

と記載して、distinctを使って重複を削除させることができる。

条件を指定して取得する　エロゲーのみの情報を取得する。

```sql
SELECT * 
FROM gamelist
WHERE erogame=TRUE;
```

AND両方満たすもの 　ゲーム得点の中央値が５０以上で　かつ　エロゲーの情報を取得する。

```sql
SELECT * 
FROM gamelist
WHERE median>=50 AND erogame=TRUE;
```

ORもしくは 　ゲーム得点の中央値が５０以上で　または　エロゲーの情報を取得する。

```sql
SELECT * 
FROM gamelist
WHERE median>=50 OR erogame=TRUE;
```

IN まとめて指定する　'エルドラド伝奇'と'星の傷痕'というゲーム名を取得

```sql
SELECT * 
FROM gamelist
WHERE gamename IN ('エルドラド伝奇', '星の傷痕');
```

NOT IN まとめて否定　'エルドラド伝奇'と'星の傷痕'以外のゲーム名を取得

```sql
SELECT * 
FROM gamelist
WHERE gamename NOT IN ('エルドラド伝奇', '星の傷痕');
```

LIKE あいまい検索　アから始まるゲーム名を取得

```sql
SELECT * 
FROM gamelist
WHERE gamename LIKE ('ア％')
```

IS NULL 空欄の情報を取得　空欄じゃないものは IS NOT NULL

```sql
SELECT * 
FROM gamelist
WHERE gamename IS NULL(IS NOT NULL)
```

ORDER BY 昇順並び替え　降順はDESCを使う

```sql
SELECT * 
FROM gamelist
ORDER BY カラム名　(DESC)
```
【初歩中の初歩】Ruby・if文を三項演算子でスマートに書いてみよう

今回はタイトルの通り、三項演算子について触れてみます。

文字列aとbが与えられていて、ふたつが一致すれば「Yes」、一致していなければ「No」と表示させるコードを考えてみます。
if文を使う場合のコードが下記のようになります。

```ruby:if文利用
a = gets
b = gets

if a==b
    print "Yes"
else
    print "No"
end
```

次に三項演算子を用いて書いた場合が下記になります。

```ruby:三項演算子利用
a = gets
b = gets

print a==b ? "Yes":"No"
```

「条件 ? 出力パターン1 : 出力パターン2」でif文がスマートに書けました！

ぜひ使ってみましょう★
実務未経験者が ITパスポートに合格したよ


プログラマーでもエンジニアでもない私がITパスポートに一発合格したので、Qiitaの練習も兼ねて記事を書いてみました。

### 私について
- Not プログラマー
- Not エンジニア
- Not プログラミングスクール
- 完全に独学のみです。エンジニア転職活動中の者です。

### ITパスポート とは
[ITパスポート](https://www.jitec.ipa.go.jp/1_11seido/ip.html)とは、IPA(独立行政法人 情報処理推進機構)が実施する情報処理技術者試験の一試験区分であり、「情報処理の促進に関する法律」に基づく国家試験です。

- 英語名は Information Technology Passport Examination 略して IP 通称 iパス

- 試験区分一覧 
![image.png](https://www.jitec.ipa.go.jp/1_11seido/taikei.png)


### ITパスポートを受験した経緯
未経験からのエンジニア転職に向けてIT資格をいくつか取得することにしました。
今春、基本情報技術者試験を受験したのですが、午後試験で落ちてしまいました...
IPAの資格は受験期間が年に1回もしくは2回と決められている資格も多いため、その時点ですぐに受験申し込みのできる資格を探して保険として受験したのがITパスポート取得の動機です。

### 試験対策
過去問サイトで過去問を5年分ほど解きました。
正答率8,9割だったので受験したらすんなりと受かりました。

元々基本情報技術者試験の午前と午後の勉強もしており、本番でも午前は8割弱、午後は5割強得点できていた(午後あと数点で落ちました...)ので、ITパスポートの問題は過去問も本番もわりと簡単だと感じました。
かと言って満点は取れなかったので、満点を目指す必要はないと思います。
ちなみに使用したテキストはこちらです
[令和02年 イメージ＆クレバー方式でよくわかる 栢木先生の基本情報技術者教室 情報処理技術者試験](https://www.amazon.co.jp/dp/B0821W2G51/ref=cm_sw_r_tw_dp_P1JJQS2V9TTP0PC6KQ88)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/522165/209f153c-2dd7-c853-4d54-7fb23a68fda7.png)


合格点は6割と言われているので、「基本情報の受講も視野に入れている方は、基本情報の午前テキストを1冊購入し、理解しながら暗記しつつ、過去問を解きまくって正解率8割近くまでもっていく」
これが正攻法かつセオリーかと思います。
ただし、「元から基本情報技術者試験の受験は視野に入れていない」という方でしたら、「ITパスポート用のテキスト」も出版されているようですので、そちらで対策された方が効率がいいかもしれません。


### 次回予告
ITパスポートは基本情報技術者試験と同じでCBT方式の試験(試験会場でPCを使って設問に答え回答する)のため、結果は即出ます(受験登録時に指定したメールアドレス宛に結果のご案内メールが届きます)
そのため、基本情報・午後試験を受験して即結果を知り落ちたことを悟った瞬間「情報セキュリティマネジメント試験」も申し込み、こちらも一発合格したので、次回は情報セキュリティマネジメント試験について書きたいと思います。
GASでWebAPIを公開・更新する方法

# WebAPIを公開する

`doGet(e)`や`doPost(e)`を実装し、`デプロイ＞新しいデプロイ`を押します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143255/a5de84dc-9bbe-d90e-ee95-11d36369a267.png" width=500>

この様なウィンドウが表示されるので、歯車アイコンを押します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143255/86c65288-b6d7-56c6-ef82-22a2a77769e3.png" width=500>


`ウェブアプリ`を押します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143255/a661e606-6fcb-bc2f-9975-135cb4d0a949.png" width=500>

説明やユーザを必要に応じ入力し`デプロイ`を押します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143255/c8f0cef7-8a78-edd2-f7d6-1da2bf8f0ec3.png" width=500>

続いて表示されるウィンドウの`ウェブアプリ＞URL`のコピーボタンを押しコピーします。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143255/e9b432e1-4c39-f095-a014-e0b057ef0a43.png" width=500>


コピーしたURLをブラウザに入力するとdoGet(e)内で取得したスプレッドシートの情報が表示されます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143255/087603c4-e23f-8318-f101-d0c166783f0d.png" width=500>


# WebAPIを更新する

コードを修正し保存した際には、デプロイを更新する必要があります。
`デプロイ＞デプロイを管理`を押します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143255/9e95b3c9-7056-7b1a-132e-2add6a6f335b.png" width=500>

編集（鉛筆アイコン）を押します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143255/e76049ae-b8b6-9a9e-50f8-467bc58552b4.png" width=500>


`バージョン`のセレクトボックスを押し`新しいバージョン`を選択します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143255/91cd6132-701a-24d1-2536-bba1256ff793.png" width=500>


続いて`デプロイ`を押します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143255/518c8ba3-4bed-4ce8-c42d-bebc14f45016.png" width=500>


これをすることで先程発行されたWebAPIアクセス時に行われる処理が更新されます。

## 注意

一度デプロイした後に再度`新しいデプロイ`をした場合、**WebAPIのURLが書き換わります。**

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143255/a5de84dc-9bbe-d90e-ee95-11d36369a267.png" width=500>

外部のアプリケーションからアクセスする場合はその都度URLを書き換える必要があります。URLを固定したままGASの開発を進めたい場合はバージョンアップで対応すると効率的でしょう。
上下左右のスワイプを検知させる (UISwipeGestureRecognizer)

#今回の内容
* 昨日の記事で書いた上下左右のスワイプを検知するようにする。

#コードと簡単解説

* 上下左右のスワイプを検知させるために、インスタンスを１つずつ作成します。
* 作成したインスタンスを１つずつ`.addGestureRecognizer(インスタンス)`します。

```Swift:
    override func viewDidLoad() {
        super.viewDidLoad()

        let downSwipeDetection = UISwipeGestureRecognizer(target: self, action: #selector(downScreenSwipe))
        downSwipeDetection.direction = .down
        view.addGestureRecognizer(downSwipeDetection)
        
        let leftSwipeDetection = UISwipeGestureRecognizer(target: self, action: #selector(leftScreenSwipe))
        leftSwipeDetection.direction = .left
        view.addGestureRecognizer(leftSwipeDetection)
        
        let rightSwipeDetection = UISwipeGestureRecognizer(target: self, action: #selector(rightScreenSwipe))
        rightSwipeDetection.direction = .right
        view.addGestureRecognizer(rightSwipeDetection)
        
        let upSwipeDetection = UISwipeGestureRecognizer(target: self, action: #selector(upScreenSwipe))
        upSwipeDetection.direction = .up
        view.addGestureRecognizer(upSwipeDetection)

    }

    @objc func downScreenSwipe(sender:UISwipeGestureRecognizer){
        
        //スワイプ検知時の処理
    }
    
    @objc func leftScreenSwipe(){
        
        //スワイプ検知時の処理 
    }
    
    @objc func rightScreenSwipe(){
        
        //スワイプ検知時の処理
    }
    
    @objc func upScreenSwipe(){
        
        //スワイプ検知時の処理
    }
```
# 終わり
ご指摘、ご質問などありましたら、コメントまでお願い致します。
Laravel 8でテキストを改行させ、埋め込まれたJSを実行させない方法。

```
<p>{!!  nl2br(e($post->body)) !!}</p>
```
e()で文字実態参照に変換。
nl2br()で改行コードを改行タグに変換。
{!! !!}でbrタグで改行させるようにする。（文字実体参照への変換を無効にする）
【初歩中の初歩】Rubyで最小値を取り出そう★

今回はRubyを用いて最小値を取り出す方法をまとめます。

nに正の整数が入力されるので、そこから最小値を取り出してみましょう。

```ruby:回答
array = []

5.times do
    array << gets.to_i
end

p array.min
```

解説

まずは空の配列を準備します。
今回はarrayメソッドを用います。

```ruby:解説
array = []
```

次に、実際に入力される正の整数を配列の中に入れていきます。
今回は数字が5つ与えられていると仮定しています。
「<<」は配列の末尾に勝手に追加してくれます。
今回は整数なので、「to_i」を足して、保存型をintegerにします。

```ruby:解説②
5.times do
    array << gets.to_i
end
```
最後に配列の中から最小値を取り出すので、「.min」をつけます
最大値を出したい時は「.max」にします。

以上です！
【numpy】3次元以上の配列を理解するため一列に並べてみる。

## はじめに

numpyやpytorchを使っていると、頻繁に3次元以上の配列に遭遇しますよね。
人間の頭では、3次元以上を想像するのはとても難しいです。

その一方で、どんな多次元配列でも、所詮はメモリ上に一列に並んでいます。
それを多次元配列を使って、我々がアクセスしているだけ、と考えればそれほど怖くなくなります。
これを意識すると、ブロードキャストとかも、直感的に理解できますし、
なぜブロードキャストできない場合があるのかも、理解できます。
（よくshapeが悪い！とエラーで怒られても、それほど焦らずに済みます。）

## メモリ配置

### まず1次元配列

```python
import numpy as np
np.random.rand(3)
# >> array([0.67531291, 0.39123613, 0.65122989])
```

1次元配列は、そのままの順番で一列に並びます。
基本ですが、一つ要素を移動すると、アドレスが一つずれます。

<img width=500 alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520396/551cd266-79c2-b22d-094e-167c49667e73.png">

### 2次元配列（行列）

```python
import numpy as np
np.random.rand(3,3)
# >> array([[0.23131406, 0.80539163, 0.72888864],
# >>        [0.30545592, 0.1298448 , 0.51332658],
# >>        [0.39577805, 0.27866544, 0.52592152]])
```

2次元配列は、まず横方向の要素がメモリ上に並べられ、
その次に、次の行のデータが並べられます。
添え字の最も右側をインクリメント(横移動)すると、アドレスが一つずれます。
添え字の右から２番目をインクリメント(縦移動)すると、アドレスが横要素の個数分ずれます。

<img width=500 alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520396/639250b8-ee3f-fdc2-ef29-2fb8b5aea32a.png">

### 3次元配列

```python
import numpy as np
np.random.rand(3,3,3)
# >> array([[[0.25302496, 0.42355715, 0.5267075 ],
# >>         [0.5960759 , 0.95850513, 0.95984181],
# >>         [0.87569986, 0.92117938, 0.50016966]],
# >> 
# >>        [[0.24515091, 0.87402237, 0.65732351],
# >>         [0.40590343, 0.27378174, 0.16059929],
# >>         [0.61030218, 0.97677065, 0.99856145]],
# >> 
# >>        [[0.96181558, 0.06190622, 0.57253151],
# >>         [0.21805162, 0.88300779, 0.77791324],
# >>         [0.455423  , 0.63827398, 0.90376446]]])
```

3次元配列は、このように並べられます。

添え字の最も右側をインクリメント(横移動)すると、アドレスが一つずれます。
添え字の右から２番目をインクリメント(縦移動)すると、アドレスが横要素の個数分ずれます。
添え字の右から３番目をインクリメントすると、アドレスが横要素x縦要素の個数分ずれます。

<img width=500 alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520396/62c5f384-d717-b0a3-70c4-d3d6e349a284.png">

このように、添え字が左に行くに従い、メモリを大きく移動します。

### 4次元配列

4次元以上も基本的には、同じ構成になります。
図示することは難しいですが、メモリ上は一列に並んでいるだけとなります。
よくあるデータ構造の例としては、以下のようなshapeのものがありますね。

```python
shape = (バッチ数, バッチサイズ, RGBチャネル数(3), 縦画素数, 横画素数)
# shape = (バッチ数, バッチサイズ, 縦画素数, 横画素数, RGBチャネル数(3)) # RGBの場所は一番右の場合もある
```

演算上、まとめて使う可能性のある成分は、右側の要素に置いておく方が、
メモリ上近くに並ぶため、計算上効率が良いです。

例えば、画素間でしかConvolutionをしない場合は、画素情報成分を右側に、
チャネル間でしかConvolutionをしない場合は、チャネル成分を右側に持ってきた方がよいです。

また、pytorchにreshape, view + contiguousがあるのは、ここら辺のメモリ配置が関係しています。

## 集約のaxisとの関係

numpyの集約(sumやmeanなど)するときに指定するaxisは、
axis=0の時には最も左側のメモリ的に遠い成分の添え字が集約されます。
(分かりやすさのため、keepdims=Trueにして演算した例を示します)

```python
A = np.random.rand(3,3,3)
A.shape
# >> (3, 3, 3)
A.sum(axis=0, keepdims=True).shape
# >> (1, 3, 3)
A.sum(axis=1, keepdims=True).shape
# >> (3, 1, 3)
```

## axisのない集約をどう計算するか

W.I.P.

## ブロードキャストについて

W.I.P.
Firebase Authenticationのユーザを一括削除する方法

Firebase Authenticationのユーザを一括削除できないか試してみました。

Firebase Authenticationのユーザ一覧が表示されている場所で、chromeのコンソールに下記のjsを入力すると順次削除してくれます。

```
const interval = setInterval(() => {
  if ($('.edit-account-button').length === 0) {
    clearInterval(interval)
  } else {
    $('.edit-account-button').first().click()
    $('button:contains("アカウントを削除")').click()
    $('.confirm-button').click()
  }
}, 1000)
```
[rails] nginx + unicorn + mysql (aws EC2 RDS) production環境立ち上げ時のメモ

#はじめに

初心者がRailsチュートリアルのやり方を~~無視~~アレンジして無謀にもAWSでデプロイしたためにエラー地獄にハマった軌跡をメモとして残しました。
（ミドルウェアもチュートリアルと変えてます。WEBサーバー：nginx + unicorn、DB：mysql（RDS））

#参考記事
「rails aws」で検索して上位に出てきた　[こちら](https://qiita.com/naoki_mochizuki/items/5a1757d222806cbe0cd1)の記事を参考(めちゃくちゃ助かりました。)


#環境
Rails 6.0.3
ruby 3.0.2
unicorn v6.0.0
nginx/1.20.1
mysql 8.0.2

#unicorn.rb
`listen`のパスを`{app_name}/tmp/unicorn.sock` に変更する(pidも同様)。[こちら](https://zenn.dev/noraworld/articles/deploy-rails-application-with-nginx-and-unicorn)にある通り、参考記事は古い記述になってるので上記の通り変更することでNginxとの接続が可能になるらしい。

#credentials.yml.enc
さらにRails5.2以降はsecret.ymlがcredentials.yml.encになったらしい。`{app_name}/`で以下を実行で編集＆master.key作成
（master.keyは`.gitignore`に入るのでproduction環境は手動で作成する必要があるらしい。unicorn起動時に意味のわからないエラーの原因の1つはこれでした。このあたりで結構ハマった...）


```bash
$ EDITOR="vi" bin/rails credentials:edit
```

ちなみにcredentials.yml.encは普通にvimで直接編集できないのでこの方法でやる必要があるらしいです。

#nginxの設定ファイル
デフォルトは`/etc/nginx/conf.d/default.conf`に作られるので`{app_name}.conf`に変更した後に以下の部分を変更。

```/etc/nginx/conf.d/rails.conf
upstream unicorn {
    server  unix:{app_name}/tmp/unicorn.sock;
}
```

#おわりに
これらの設定を見直した状態でunicorn、nginxなど再起動で無事サーバーが正常起動しました。終わってみれば、参考記事と現行バージョンの差異による設定ファイルの場所や書き方などの変更作業がエラー対処の大半の時間を費やしていた気がします。

#aws要素は？
aws特に関係ない話になってしまいましたが、DBをチュートリアルのpostgresからmysql(RDS)に変えた部分は大して影響ありませんでした（今のところ）。DB接続周りは`database.yml`でhostをRDSのエンドポイントにして、usernameとpassword変えたくらいで問題なかったはずです。VPCのセキュリティグループでRDSとEC2間のポートなどが適切に設定してあればこれくらいの変更でいけると思います。

#約15時間にわたる死闘の末
唐突に画面に映った`hello, world!`の文字列。ああ、そういえばRailsチュートリアル進めてたんだった…ここまで感動した`hello, world!`は初めてだよ。もう、ゴールしていいよね…？
![スクリーンショット 2021-09-12 23.28.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286945/2af5e4e3-b328-1b12-3af8-b69430bf25ee.png)

#参考記事
[【Ruby on Rails】unicornをNginx環境下で動かす時の設定方法](https://zenn.dev/noraworld/articles/deploy-rails-application-with-nginx-and-unicorn)
[【CentOS 7】Nginx + Unicorn で Rails アプリケーションを本番環境で立ち上げる方法](https://y-hilite.com/2857/)
[ActiveRecord::NoDatabaseErrorが出た時の対処法 \| Rails Ambassador ~Railsの伝道師~](https://rails-ambassador.herokuapp.com/debugs/NoDatabaseError)
[Nginxで「could not build server\_names\_hash\.\.\.」エラーが出た時の対処方法 \- Qiita](https://qiita.com/makaaso-tech/items/31bb05a529b2bbb180f7)
["The name org\.freedesktop\.PolicyKit1 was not provided by any \.service files"が表示されたら\.\.\. \- Qiita](https://qiita.com/kwsmkn/items/52c38a258cc58c854b5b)
[Rails5\.2から追加された credentials\.yml\.enc のキホン \- Qiita](https://qiita.com/NaokiIshimura/items/2a179f2ab910992c4d39#configmasterkey)
[MySQLのバージョンを5\.1から5\.7にしてRubyからMySQLに接続する際にlibmysqlclient\_ \| tackeyy\.com](https://tackeyy.com/blog/posts/fix-libmysqlclient-r-so-16-cannot-open)
[【Rails】Webサーバー「Unicorn」の基本情報と実装方法 \- AUTOVICE](https://www.autovice.jp/articles/146)
[【YAML】Railsのdatabase\.ymlについてなんとなく分かった気になっていた記法・意味まとめ \- Qiita](https://qiita.com/terufumi1122/items/b5678bae891ba9cf1e57)
【Unity】同じクラスのコンポーネントの実行順はアタッチした順の逆順になる説

色々あってこの仮説に至ったので検証してみました。

以下のコンポーネントをアタッチしてログの出力される順番を見てみます。
要約するとアタッチした順番でコンポーネントに番号が振られて、Awakeでその番号をログに出力する感じです。

```c#
using UnityEngine;

public class ComponentOrderTest : MonoBehaviour {

    public static int AllCount;

    public int count;

    void Reset() {
        count = AllCount;
        AllCount++;
    }

    void Awake() {
        print(name+":"+count);
    }

    [ContextMenu("AllCountReset")]
    public void AllCountReset() {
        AllCount = 0;
    }
}
```

まずは普通に一つのオブジェクトに５つのコンポーネントをアタッチしてみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283994/40056b30-999a-366f-42a7-7de98ece8104.png)
結果は以下です。アタッチした順の逆順で実行されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283994/b9111ddb-12fa-d5ac-901a-228c89053327.png)

次にインスペクター上の順番をD&Dで適当に並び替えて実行してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283994/dc951047-75bf-3c01-9a8f-43dbe6abe92b.png)
アタッチした順の逆順で実行されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283994/315e3654-ab14-e578-fe56-d150e9c12a1c.png)

次は複数のオブジェクトにまたがってアタッチしてみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283994/83dea6be-f8be-f3a9-ebde-ba80b6d8b49d.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283994/32e454f3-567d-8c31-4696-5c299fd0631b.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283994/7c4e5c5a-642b-fb8b-922d-dde828b063d6.png)
結果は以下です。オブジェクトをまたいでも、アタッチした順の逆順になりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283994/aa351dba-85a6-8c1b-68d1-6c973c6324b0.png)

次はコンポーネントを３つアタッチしたオブジェクトを３つに複製してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283994/715ee660-a429-772e-5ed1-f7bbc46415e3.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283994/73361f6e-6d3f-1874-9d77-fed4e231352d.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283994/570c24a6-7526-76e2-cfff-e8a5ac931e5b.png)
こうなりました。複製したオブジェクトは順番が入れ替わっています。
※オブジェクト名が出るようにコードをちょっといじりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283994/aa66700c-b3d0-e167-c584-140129557365.png)
考えられる可能性は、オブジェクトが複製されるときにアタッチした逆順でコンポーネントがコピーされて、順番が入れ替わるとかでしょうか。

最後にログの出力タイミングをUpdateにして、実行中にEnable/Disableを切り替えてみます。
![7bba6984-ff61-4864-a313-08fb501d042b.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283994/1355f49f-8c35-3ff8-2f4b-b5d10017804a.gif)
最後にEnableにしたコンポーネントが後で実行されるようになっていますね。

#検証結果
・基本的にはアタッチした順の逆順に実行される
・オブジェクトごと複製した場合は順番が入れ替わる
・実行中にEnable/Disableを切り替えた場合も順番が入れ替わる
Activity からの戻り値を取得する方法

## 環境

Android Studio で、Empty Compose Activity を使用して空のプロジェクトを作成しています。Empty Compose Activity は、Android Studio のバージョンである Arctic Fox をインストールすることで表れます。

## 実装

Activity の状態が STARTED になる前に、`registerForActivityResult` を使って `ActivityResultLauncher` を作成します。今回は、Activity からの文字列をただ単に標準出力に出力することにします。

```kotlin
class MainActivity : ComponentActivity() {
  private val startForResult =
    registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
      if (it.resultCode == Activity.RESULT_OK) {
        println(it.data?.getIntExtra("PENGUIN", 0))
      }
    }

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContent {
      Button(onClick = ::move) { Text("click me!") }
    }
  }

  private fun move() {
    val intent = Intent(this, SubActivity::class.java)
    startForResult.launch(intent)
  }
}
```

SubActivity は次のように実装します。

```kotlin
class SubActivity : ComponentActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContent {
      Button(onClick = ::move) { Text("click me!") }
    }
  }

  private fun move() {
    val intent = Intent().apply { putExtra("PENGUIN", 100) }
    setResult(Activity.RESULT_OK, intent)
    finish()
  }
}
```

## まとめ

`registerForActivityResult` を呼ぶタイミングに気をつけるだけで良さそうです。
[C#] 重み付きランダム要素選択

## やりたかったこと
pythonの[random.choices](https://docs.python.org/ja/3/library/random.html)のような重み付きのランダム要素選択をC#でもしたい。
~~車輪の再発明感がすごいが勉強になったのでヨシ!~~

## 仕様
重み(weights)の累積和を要素のコレクション(items)と紐づけ、乱数が累積和の値を超えた最初の要素を返却する仕様とした。

## ポイント
itemsとweightsの個数が合わない(割り当てられている重みが存在しない場合)は重みが0とみなせば当選することはないので、Zipメソッドが個数が少ない方に合わせて出力されることを利用して簡潔に書くことができる。

## コード

```csharp:WeightedRoulette.cs
using System;
using System.Collections.Generic;
using System.Linq;

namespace YourNamespace
{
    public class WeightedRoulette
    {
        private readonly Random _random;

        public WeightedRoulette(Random random = null)
        {
            _random = random ?? new Random();
        }

        public T Roll<T>(IEnumerable<T> items, IEnumerable<double> weights)
        {
            if (items is null) return default(T);

            if(weights is null) return items.First();

            double sum = 0d;

            // 累積和の計算が遅延実行されないようにToArrayする
            IEnumerable<double> cumlate = weights.Select(v => sum += Math.Max(0d, v)).ToArray();

            var roulette = items.Zip(cumlate, (s, c) => (s, c));

            double value = _random.NextDouble() * sum;

            return roulette.First(r => r.c >= value).s;
        }

        public int Roll(IEnumerable<double> weights) => Roll(Enumerable.Range(0, weights?.Count() ?? 1), weights);
    }
}
```
var と let でfor文の中で違い

ブロックスコープだとか、関数スコープとかで、言うけど、なんとなく一緒だと思ってたけど、明確にふるまいが違うのが、発生した。


```javascript:qiita.js
for(let i = 0 ; i < 10 ; i++){
console.log(i);
}
```
と

```javascript:qiita.js
for(var i = 0 ; i < 10 ; i++){
console.log(i);
}
```

は同じ。
1,2,3,4,5,6,7,8,9

これは、その時点でconsoleが発動されるので納得できる。
1ミリ秒でも後に実行されるもので確認してみる


```javascript:qiita.js
for(let i = 0 ; i < 10 ; i++){
setTimeout(()=>console.log(i),1)
}
```
は同じ。
1,2,3,4,5,6,7,8,9

```javascript:qiita.js
for(var i = 0 ; i < 10 ; i++){
setTimeout(()=>console.log(i),1)
}
```
は違う
10,10,10,10,10,10,10,10,10,10
これは、for文が終わった後に呼ばれるので、10になってる。



jQueryで、例えば、

```javascript:qiita.js
for(var i = 0 ; i < 10 ; i++){
$(".btn").eq(i).click(()=>{
//i番目がクリックされた事にしたいとしても
function(i);
})
}
```
ってしても、どれをクリックしてもfunction(10)が発動してしまう

```javascript:qiita.js
for(let i = 0 ; i < 10 ; i++){
$(".btn").eq(i).click(()=>{
//i番目がクリックされた事にしたいとしても
function(i);
})
}
```
ってすると、n番目をクリックしたらfunction(n)が発動する。

letの方が、自分としてもイメージ通りの動作をして、varがバグっぽい動作に感じるので、constやletを面倒でvarばっか使っていたのを、改善しなくちゃって思いました。
MRTKを使ってボタンを自分に向かせる

HoloLens 2 で [MRTK](https://docs.microsoft.com/en-us/windows/mixed-reality/mrtk-unity/) を使用してアプリを作成するときに、
ボタンを自分に向かせたいことがありました。
この方法のメモです。

# 結論

自分に向かせたい場合は、MRTK の [Billboard](https://docs.microsoft.com/en-us/dotnet/api/microsoft.mixedreality.toolkit.ui.billboard) を使用するだけです。
MRTK のドキュメントは下記です。
[Billboarding and tag-along - Mixed Reality | Microsoft Docs](https://docs.microsoft.com/en-us/windows/mixed-reality/design/billboarding-and-tag-along)

# 手順

## MRTKを使ったアプリの作成

HoloLens2 チュートリアルにある MRTK のチュートリアルをご確認ください。
[Initializing your project and deploying your first application - Mixed Reality | Microsoft Docs](https://docs.microsoft.com/en-us/windows/mixed-reality/develop/unity/tutorials/mr-learning-base-02)

## ボタンの追加

MRTK の PressableButtonHoloLens2Bar3H を Project から Hierarchy に配置します。
実行すると下図のように移動したときに、ボタンが自分の方を向いてくれません。
こうなると移動した後に操作がしづらいですね。

![スクリーンショット 2021-09-12 224730.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460904/006c88fd-c979-0feb-e821-ad1b9b846237.png)
![スクリーンショット 2021-09-12 224805.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460904/7166f4b9-3bfd-d242-ed59-2680d3cab926.png)


## Billboard の追加

Hierarchy の PressableButtonHoloLens2Bar3H を選択します。
Inspector の Add Component から Billboard を選択します。

![スクリーンショット 2021-09-12 230230.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460904/9069ec23-082c-cb6c-6039-041e218b9cc4.png)


実行すると下図のように移動したときに、ボタンが自分の方を向いてくれます。
（向いていることが変わったことが分かるように、ボタンの後ろに Cube を置いています）

![スクリーンショット 2021-09-12 225837.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460904/f26ab5ec-d884-2762-6e98-7d455337f137.png)
![スクリーンショット 2021-09-12 225859.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460904/4d9e0215-c5f3-35f6-be74-1d8486bc2b68.png)

# 最後に

MRTK 便利ですね。素晴らしい！
Billboard は Pivot Axis でオブジェクトが回転する軸を指定できます。
試してみてください。
AWS Amplify Mock APIのLocal DynamoDBへのアクセス方法

## はじめに

AWS Amplify Mock APIで起動しているローカルのDynamoDBにアクセスしたい。
AWS Amplifyを使って開発を行うのであれば、別でDynamoDB localを実行するようなことは避けたい。

2021年9月時点

## 接続情報

``` ts
{
  endpoint: "localhost:62224",
  region: "us-fake-1",
  accessKeyId: "fake",
  secretAccessKey: "fake",
}
```

- AWS SAMを利用してDocker経由でアクセスする場合

``` ts
{
  endpoint: "http://host.docker.internal:62224",
  region: "us-fake-1",
  accessKeyId: "fake",
  secretAccessKey: "fake",
}
```

接続時のTableNameは、「schema.graphql」指定のTable名 + "Table"となります。

## コメント

AWS SAMを使用してLambda関数作成時にDynamoDBに接続できなくてはまりました。

## 参考

[https://github.com/aws-amplify/amplify-cli/blob/24d8085325d435284b9c49a43592e61891fd72bc/packages/amplify-dynamodb-simulator/index.js](https://github.com/aws-amplify/amplify-cli/blob/24d8085325d435284b9c49a43592e61891fd72bc/packages/amplify-dynamodb-simulator/index.js)
Rails mapメソッドとchartkickでグラフを量産する

# はじめに
こんにちは。
Rails6アプリケーションでgem"chartkick"とmapメソッドを使って、対応するデータのグラフを自動的に量産する方法について解説します。
Rails5をお使いの方はchartkick導入時のコマンドが変わるらしいので[公式サイト](https://chartkick.com/)を参考にしてください。

# chartkickの導入
まず以下のようにgemfileにchartkickを追記します。

```ruby:gemfile.rb
gem "chartkick"
```
その後いつも通りbundle installします。
yarn addコマンドでWebpackerを走らせて依存オブジェクト（cahrtkick）の追加とインストールを行います。( [yarn add の解説](https://classic.yarnpkg.com/en/docs/cli/add) )

```zsh:terminal
bundle install
yarn add chartkick chart.js
```
最後に、javascript:app/javascript/packs/application.jsに以下を追記します。

```javascript:app/javascript/packs/application.js
import "chartkick/chart.js"
```
これでchartkickの導入は完了です。
この後mapメソッドで対応するデータのグラフを自動的に量産する方法を解説するので、「表示したいグラフは１つだけだよ！」という方は[chartkick公式サイト](https://chartkick.com/)を参考にした方が早いかもしれません。

# 前述　〜データの解説〜
本題に入る前に、グラフ挿入時のコードに出てくるモデルとそのカラム名について紹介します。


データモデルは以下の表の通り。
ExerciseモデルとRecordモデルは１対多のアソシエーションです。
グラフはRecordモデルのweightカラムとreps_countカラムの値をもとに算出されたRMカラムの値とdateカラムの日付で、紐づいたExerciseカラムの数だけ描画します。

|  　　Exercise 　　 | 　 　　Record 　　　 |
|:-------------|------------:|
| id  　　        | id          | 
| name         | exercise_id |
|              | weight      |
|              | reps_count  |
|              | RM          |
|              | date        |

# グラフの挿入

というわけで本題です。
mapメソッドを使って、対応するデータのグラフを自動的に量産する方法を解説します。

exerciseコントローラのindexアクション内でインスタンス変数にExerciseモデルの全てのデータを取得します。

```ruby:exercises_controller.rb
class ExercisesController < ApplicationController
  def index
    @exercises = Exercise.all
  end
end
```
取得したインスタンス変数のレコードの数だけmapメソッドで繰り返します。
mapメソッド内では名前とグラフを出力します。

```erb:exercises/index.html.erb
<h2>グラフページ</h2>
<% @exercises.map do |exercise| %>
  <br>
  <%= link_to exercise.name %>
  <% graph = Record.where(name_id: exercise.id).pluck(:date, :RM) %>
  <%= line_chart graph, min: 30, max: 45 %>
<% end %>
```

４行目で、名前(mapメソッドで繰り返されているexerciseのnameカラムの値)を出力。

５行目で、Recordモデルのname_idカラムの値とmapで繰り返されているexerciseのidの値が一致するレコードをwhereメソッドで取り出し、そのレコードのdateカラムとRMカラムの値をgraphという変数に配列形式で代入する。
graph = [:date, :RM]

６行目で、５行目で定義したgraph変数の値を使ってグラフを描画。
line_chartはchartkickのコマンドで折れ線グラフの描画を意味します。
オプション引数でグラフの縦軸(RM)の表示範囲を30〜45に定義。

※ インスタンス変数＠exercisesとmap内で繰り返されるexerciseのスペルミスにご注意ください。

これで http://localhost:3000/exercises/index にアクセスするとグラフが表示されます。
# 参考
今回は折れ線グラフを挿入しましたが、他の種類のグラフを挿入する場合
[chartkick公式サイト](https://chartkick.com/)を参考にしてください。


Twitterで日々の学習をアウトプットしています。
未熟者ですが、ご興味あれば覗いてやってください。[→Twitter](https://twitter.com/ishii_engneer)
Ruby 入門 [分割するメソッド]

#メソッドを定義する→呼び出す

```rb
def area
    puts 2 * 2
end
area
↪️4
```
メソッドを定義するには、defにつづいてメソッド名を書きく。defは後につづく名前のメソッドを定義する。
定義したメソッドは、メソッド名を書くことで呼び出す(実行する)ことができる。

```rb
def area
    2 * 2
end
puts area
↪️4
```
メソッドは最後の実行結果が戻り値として呼び出し元へ返る仕組み。areaメソッドの中でputsするのをやめて、計算した結果の整数オブジェクト(ここでは４)を戻り値として返すように変更した。

```rb
def area
    2 * 2
end
result = area ———area が戻り値 4 で置き換わって result = 4 となる 
puts result
↪️4
```
戻り値は変数に代入することもできる。
#メソッドへオブジェクトを渡す

###引数を使ってオブジェクトを渡せるメソッドを定義する

 ```rb
def area(x)————②引数の2をxへ代入
    x * x ————③2 × 2を計算し、戻り値4を返す
end
puts area(2) ————①メソッド呼び出し(引数は2)
↪️4
```
###メソッドを途中で終わらせる-return

```rb
def thanks_and_receipt
    puts "ありがとうございました。"
    return --------- ここでメソッドが終わる
    puts "こちら、レシートになります。" ————この行は実行されない
end

thanks_and_receipt
↪️ありがとうございました。
```
###retutnは戻り値を指定する機能もある。

```rb
def thanks_and_receipt(receipt)
    greeting = "ありがとうございました。"
    unless receipt ————receiptがfalseの時に次の行を実行
    　return greeting ——returnを実行し、変数greetingに代入されたオブジェクトを戻り値にする
    end
    greeting + "こちら、レシートになります。" ————“こちら、レシートになります。”を追加して
end　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　戻り値にする。

puts thanks_and_receipt(true)
↪️ ありがとうございました。こちら、レシートになります。
```
###引数を省略した時のデフォルト値

```rb
def order(item = "コーヒー") ————itemのデフォルト値に”コーヒー”を指定
    "#{item}をください"
end

puts order ————引数を省略して呼び出すと”コーヒーをください”が返される
puts order("カフェラテ")
puts order("モカ")
↪️コーヒーをください
カフェラテをください
モカをください
```
変数itemにデフォルト値である”コーヒー”が代入される。引数をした場合は使われない。

###引数の順番を変えられるキーワード引数

```rb
def order(item:, size:) ————引数名の後ろに:をつけるとキーワード引数になる
    "#{item}を#{size}サイズでください"
end

puts order(item: "カフェラテ",size: "ベンティ") —————引数を名前付きで指定できる
puts order(size: "ベンティ",item: "カフェラテ") —————引数の順番も変えられる

↪️カフェラテをベンティサイズでください
　  カフェラテをベンティサイズでください
```

###キーワード引数でのデフォルト値

```rb
def order(item:, size: "ショート") ————sizeのデフォルト値に”ショート”を設定
    "#{item}を#{size}サイズでください"
end

puts order(item: "カフェラテ") ————省略するとデフォルト値が使われる
puts order(item: "カフェラテ",size: "ベンティ")
↪️カフェラテをショートサイズでください
     カフェラテをベンティサイズでください
```
PHP で定数を使ってみる

##PHPで定数を使ってみた

ちなみに定数とは

>const キーワードか、 define() 関数を使うことで、定数を宣言することが出来ます。 define() を使えば任意の式を使って定数を定義できますが、 const キーワードを使う場合には、 次の段落で説明する制約があります。 定数が一度定義されると、 変更または未定義とすることはできません。
>>https://www.php.net/manual/ja/language.constants.syntax.php

みなさんPHPで定数って使ってますか？？
私は古いシステムを修正することが多いのですが、定数を使っているプログラムは非常に少ないです。（あくまで私の偏見ですが）

私は師匠に定数は積極的に使っていけと習ったので、プログラムの先頭には定数が並んでいる場合が多いです。

DBに保存される際にINT型で保存されるけれど、画面に出力される時は日本語で表示してね、といった文言は是非定数を使ってあらかじめ定義しておきたいですね。
例）曜日、旧暦、性別など

```php
<?php

//9月１２日（日）作成

const WEEK_ARRAY = array("日","月","火","水","木","金","土");
$week = date("w");
echo WEEK_ARRAY[$week];
//日

const MONTH_ARRAY = array("","睦月","如月","弥生","卯月","皐月","水無月","文月","葉月","長月","神無月","霜月","師走");
$month = date("n");
echo MONTH_ARRAY[$month];
//長月

const GENDER_ARRAY = array("その他","男","女");
$gender = 1;
echo GENDER_ARRAY[$gender];
//男

?>
```
上記のような例だとほぼ変わることはありませんが
例えば業務システムのステータスなどは仕様変更などで文言が変わることはよくある話だと思います。
仕様変更のたびに条件式を書いてある部分を探し出して書き直すといったことは非常にめんどくさいので、プログラムの先頭に定数で宣言しておけば修正も楽々できますね。

例）登録状況、評価表示、通貨など

```php
<?php

const REGIST_STATUS_ARRAY = array("未登録","仮登録","登録済","退会済");
$register = 1;
echo REGIST_STATUS_ARRAY[$register];
//仮登録

const EVAL_STATUS_ARRAY = array("","GOOD","NICE","GREAT","EXCELLENT");
$evaluation = 3;
echo EVAL_STATUS_ARRAY[$evaluation];
//GREAT

const MONNEY_TYPE_ARRAY = array("円","ドル","ウォン","","","");
$monney_type = 0;
echo MONNEY_TYPE_ARRAY[$monney_type];
//円

?>
```

これらはよく仕様変更や追加項目がありそうな部類だと思いますが、こうして定数でまとめておけば急な仕様変更や追加項目があっても対応が早そうですね♪
Ruby 入門 [組で扱う-ハッシュ]

#シンボル(symbol)とは
シンボルはコロン記号(:)から始める。日本語ではあまり使わない。
シンボルも文字列や整数と同じようにオブジェクトの種類の一つ。シンボルのクラス名はSymbol。

● to_sym
to_symメソッドは文字列からシンボルへ交換

● to_s
to_sメソッドはシンボルから文字列へ交換

ハッシュの書き方
Ruby超入門のP148に書いてある

#キーと値の組を追加・削除する

```rb:ハッシュへキーと値を追加する
menu = {coffe:300,cafe_latte:400}
menu[:mocha] = 400
p menu
↪️{:coffe=>300, :cafe_latte=>400, :mocha=>400}
```


```rb:存在しないキーを指定した時.
menu = {coffe:300,cafe_latte:400}
p menu[:tea]
↪️nil
```
ハッシュから存在しないキーを指定して値を取得しようとすると、nilが得られる。

```rb
menu = {coffe:300,cafe_latte:400}
menu.default = 0
p menu[:tea]
↪️0
```
存在しないキーを指定した時の値は、default=メソッドで設定することもできる。

###２つのハッシュを１つにまとめる
●merge
mergeメソッドは２つのハッシュを１つにまとめるときに使う。mergeメソッドは元のハッシュと、指定したハッシュを１つにまとめて新しいハッシュを作るメソッド。

```rb
coffee_menu = {coffee: 300, caffe_latte: 400}
tea_menu = {tea: 300,tea_latte: 400}
menu = coffee_menu.merge(tea_menu)

↪️{:coffee=>300, :caffe_latte=>400, :tea=>300, :tea_latte=>400}
```
#ハッシュからキーと値の組みを削除する
● delete

```rb
menu = {coffee: 300,caffe_latte: 400}
menu.delete(:caffe_latte)
p menu
↪️{:coffee=>300}
```

deleteメソッドはハッシュからキーと値の組を削除するときに使う。

```rb:ハッシュを繰り返し処理する

ハッシュ.each do |キーの変数,値の変数|
　繰り返し実行する処理
end

menu = {"コーヒ" => 300,"カフェラテ" => 400}
menu.each do |key, value|
    puts "#{key}は#{value}円です"
end
↪️コーヒは300円です
     カフェラテは400円です
```

###キーだけを処置したいとき
● each_key

```rb
each_keyメソッドはキーだけで繰り返し行うメソッドです。

menu = {"コーヒ" => 300,"カフェラテ" => 400}
menu.each_key do |key|
    puts key
end
↪️コーヒ
　  カフェラテ
```

同様に値だけを繰り返しするeach_valueメソッドもあります
AtCoderログ：0110 - ABC 218 に参加しました

この記事は 2021年09月11日(土)21:00-22:40 に開催された [AtCoder Beginner Contest 218 (ABC 218)](https://atcoder.jp/contests/abc218) に参加した記録です。

https://atcoder.jp/contests/abc218

# 結果
- 得点：300 (=100+200)
- 時間：10:20 (= 16:50 + 05:00 × 0)
- 順位：5984 / 8839
- パフォーマンス：277
- レーティング：380 → 366 (-14)
- 段級位：9級

![2021-09-11_abc218.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1589302/855997a7-2d6e-1d16-1f8d-d640d15df3af.png)

# 詳細
|問題|得点|時間|提出コード|復習|
|:--:|:--:|:--:|:--:|:--:|
|[ABC 218 A](https://atcoder.jp/contests/abc218/tasks/abc218_a)|100|02:49|[○](https://atcoder.jp/contests/abc218/submissions/25747766)|[AtCoderログ：0111](https://qiita.com/RoadLynton/items/7bc5783fb3c5f160e55a)|
|[ABC 218 B](https://atcoder.jp/contests/abc218/tasks/abc218_b)|200|10:20|[○](https://atcoder.jp/contests/abc218/submissions/25756543)|[AtCoderログ：0112](https://qiita.com/RoadLynton/items/5f8127d0fdaf8c135322)|
|[ABC 218 C](https://atcoder.jp/contests/abc218/tasks/abc218_c)|300|---|---|---|
|[ABC 218 D](https://atcoder.jp/contests/abc218/tasks/abc218_d)|400|---|---|---|
|[ABC 218 E](https://atcoder.jp/contests/abc218/tasks/abc218_e)|500|---|---|---|
|[ABC 218 F](https://atcoder.jp/contests/abc218/tasks/abc218_f)|600|---|---|---|
|[ABC 218 G](https://atcoder.jp/contests/abc218/tasks/abc218_g)|600|---|---|---|
|[ABC 218 H](https://atcoder.jp/contests/abc218/tasks/abc218_h)|600|---|---|---|

# 感想
- A, B まで完答できました。今回は不調でした。
- A は問題なく正解。
- B のは細かい文法を調べながら正解。
- 残りの時間は C と D を行ったり来たりして時間になってしまいました。
- レーティングは微減。まあ、妥当でしょう。
- このところちゃんとした問題を解けないでいるためか、勘が鈍った気がします。

# リンク
## 前後の記事
- 前の記事 → [AtCoderログ：0109 - ABC 138 C](https://qiita.com/RoadLynton/items/08a442f4052f7a86320b)
- 次の記事 → [AtCoderログ：0111 - ABC 218 A](https://qiita.com/RoadLynton/items/7bc5783fb3c5f160e55a)
LambdaからEC2でコマンドを実行[AWS Systems Manager]

Lambdaから、rubySDKを使いec2内にあるshスクリプトファイルを実行したい。

ec2インスタンスでコマンドを実行する方法として一番一般的なのは、
sshが挙げられると思うが、今回はAWS Systems Manager (旧称 SSM)を使って見ようと思う。

AWS Systems Managerは、
ec2にインストールされてるエージェント経由でコマンドを実行できるサービスらしい。


##準備
### Lambdaにポリシーをアタッチ
①AmazonSSMFullAccess
②AmazonEC2RoleforSSM
を与えた。

ざっくり与えすぎてるので精査する必要があり。
参考にしないで下さい。。


### EC2の準備
最近のversionのec2は最初からSSMエージェントがインストールされているらしいが、
古いEC2などの場合は手動でインストールする必要がある。
東京リージョンのAmazon Linux (x86_64)の場合
① EC2にエージェントをインストール

```sh
sudo yum install -y https://s3.ap-northeast-1.amazonaws.com/amazon-ssm-ap-northeast-1/latest/linux_amd64/amazon-ssm-agent.rpm
```

参考
https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/agent-install-al.html

② EC2にポリシーをアタッチ
EC2にくっついてるロールに「AmazonSSMManagedInstanceCore」ポリシーをアタッチする。



## 実装
以下のようになる。

```ruby
 ssm_client = Aws::SSM::Client.new( region: '****')
 command = 'sh /home/test.sh'
 resp    = ssm_client.send_command({ instance_ids: ["******"],
                                     document_name: "AWS-RunShellScript",
                                     comment: "Comment",
                                     parameters: {
                                     "commands" => [command]} })

```

send_commandの使い方は以下を参考
https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/SSM/Client.html#send_command-instance_method
Unityで字幕ファイルから音声合成で副音声を作る

# はじめに
英語の動画を見るときに、動画から翻訳された字幕を読むのがめんどくさいので、字幕ファイルを突っ込むといい感じのタイミングで読みあげてくれるシステムを作ってみましたので、開発メモを共有します。
<br>


<iframe width="560" height="400" src="https://www.youtube.com/embed/q7VH_dxy7E8" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>


# 動作環境
Windows10

# システム構成メモ
### ファイル選択ダイアログからSRTファイルを選択する

* Unity Standalone File Browser(Windows / Mac / Linux)

複数環境で手軽にダイアログを開くことができる。
自力で実装も試したが、こちらの方がかなり楽に実装できる。

https://github.com/gkngkc/UnityStandaloneFileBrowser

### 読み上げ用のテキストを生成する

正規表現を使って時刻と本文を分ける。

### 音声合成の声、音程、ピッチ、ボリュームを設定する
音声合成には、マルチプラットフォームで利用できて、パラメータも簡単に変更できるRT-Voice Proを選定した。

https://assetstore.unity.com/packages/tools/audio/rt-voice-pro-41068?locale=ja-JP

### 録音

AudioListenerから直接WAVファイルを作成する。

参考にしたのはこちら

https://akiiro.hatenablog.com/entry/2017/08/09/031237

* 雑音が混じるのでゲーム内の音だけを録音する必要あり。
* 直接mp3への変換は厳しそうなので、WAVを取得してから変換する。

### 元の動画に音声合成

Windows標準のフォトで元の音声を消してから、録音した音声を合成する。

# 最後に

作り終わってから気づきましたが、PlayStoreでも字幕ファイルの読み上げできるアプリが何個か出ているようでした…
java.time.Instant を Serializable にする

## はじめに

[こちらの記事](https://qiita.com/penguinshunya/items/e6b2fb25bcb269e7588d)では、kotlinx.datetime.Instant を Parcelable にする方法を書きました。今回は、java.time.Instant を Serializable にする方法を書きます。明示的に null に対応しなくていい分、こちらのほうが楽かもしれません。

## 実装

次のように実装します。

```kotlin
object InstantSerializer : KSerializer<Instant> {
  override val descriptor: SerialDescriptor
    get() = PrimitiveSerialDescriptor("Instant", PrimitiveKind.STRING)

  override fun deserialize(decoder: Decoder): Instant {
    return Instant.parse(decoder.decodeString())
  }

  override fun serialize(encoder: Encoder, value: Instant) {
    encoder.encodeString(value.toString())
  }
}
```

## 使用例

`?` を付けるだけで null に対応できます。

```kotlin
@Serializable
data class MyData(
  val instant1: @Serializable(with = InstantSerializer::class) Instant,
  val instant2: @Serializable(with = InstantSerializer::class) Instant?,
)

val input = MyData(Instant.now(), null)
val text = Json.encodeToString(input)
val output = Json.decodeFromString<MyData>(text)

println(text)   //=> {"instant1":"2021-09-12T13:48:15.956Z","instant2":null}
println(output) //=> MyData(instant1=2021-09-12T13:48:15.956Z, instant2=null)
```
S3バケットを作成してEC2と接続する【備忘録】

#はじめに
　前記事（[EC2サーバー構築の概要【備忘録】](https://qiita.com/namikis/items/9e7c71a1e920bd61d09c)）で作成したEC2インスタンスと、AWSストレージサービスであるS3をPHPで接続した時に調べたことの備忘録。
　AWSアカウントを作成し、EC2インスタンスのセットアップが完了していることが前提です。
　具体的な概要・用語についての記事であり、具体的な手順については割愛しています。

#目次
- 全体の流れ
- 項目別の詳細
- yumとrpm
- 参考文献

#全体の流れ
####S3セットアップ
1. S3バケット作成
1. IAMロール作成
1. EC2インスタンスにIAMロールを割り当て
1. エンドポイントの作成

####AWS SDK for PHP でS3に接続
5. PHPのバージョンアップ
6. Composerインストール
7. AWS SDK for PHPをインストール

#項目別の詳細
####S3バケット作成
　手順通りやればいいので割愛。
####IAMロール作成・IAMロールを割り当て
　IAM（Identity and Access Management）とは、AWSサービスへのアクセスを安全に行うためのAWSサービス。その機能の一つに、「限定されたアクセス権限を持つロールやユーザーの作成」がある。仮にアクセス情報が漏洩した場合、これらのIAMロール・IAMユーザーを認証に用いていれば、アクセス権限が限定されているため、被害を最小限に抑えられるという利点がある。

　また、IAMユーザーとIAMロールの違いは使用方法の違いにある。
　IAMユーザーは「アクセス権限を限定されたユーザー」という体でアクセスキーとシークレットキーを設定ファイルなどに記述して認証させるが、IAMロールはAWSコンソールからEC2インスタンスへの割り当て設定をすることで、いちいちキーを記述したりせず自動的に認証をさせることができる。
　今回は、EC2とS3の接続にはこのIAMロールを用いた。

####エンドポイントの作成
　IAMの件と同様、最大限「セキュアな通信」というものを実現させるために作られたシステム。
　AWSサービスの中で、EC2はVPC（仮想空間的なもの）内にあり、S3はVPC外にある。EC2がVPC外のサービスと通信をするためにはプライベートネットワークからインターネットへの接続を仲介させる必要があるが、エンドポイントを設定すると、その役割をエンドポイントが担ってくれる。これにより通信の際にインターネットを挟まずに済むため、「セキュアな通信」が可能となる。

####PHPのバージョンアップ
　AWSサービスとの接続にはAWS SDK for PHPを用いるが、これはPHP5.4に対応していない。しかしながら、yum install phpでPHPを入れると5.4が入ってしまう。
　この問題には「パッケージリポジトリ」と「yum」の概念が関係している。
　「yum install パッケージ 」は、「登録されたパッケージリポジトリ（色々なパッケージが入ってるフォルダ）から指定されたパッケージをインストールする」という指示を出す。そしてEC2にデフォルトで登録されているAmazon LinuxのパッケージリポジトリにはPHPは5.4しか入っていないため、このような不具合が起きる。

　そこで、PHP7.4が入っている外部リポジトリ「remi」を登録し、そこからインストールする。

```
sudo amazon-linux-extras install epel //amazon linuxリポジトリにepelを追加し、yumでインストールできるようにする
                                      //epel-release：remiを入れるために必要なパッケージ
sudo yum install epel-release         //epel-releaseをインストール

sudo rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm  //rpmコマンドでremiをインストール

sudo yum install -y php74 php74-php php74-php-fpm  //PHP7.4をインストール
sudo ln -s /usr/bin/php74 /usr/bin/php             //php74のシンボリックリンクを作成する（phpコマンドを使えるようにする）
```
備考：-UvhはオプションU（アップグレード）,v（詳細情報）,h（進行状況の表示）のまとめ書き。

####Composerをインストール
　AWS SDK for PHPはComposerからインストールするので、まずはComposerを入れる。
　今回はcurlコマンド（ファイルを転送するコマンド。引数にURLを指定することでファイルをダウンロードできる。-sSでエラーメッセージ以外の進捗状況を非表示にする）を用いる。

```
curl -sS https://getcomposer.org/installer | php  //Composerをインストール
```
####AWS SDK for PHPをインストール

```
php composer.phar require aws/aws-sdk-php  //AWS SDK for PHPをインストール
```

#yumとrpm
　個人的に気になった部分なので調べた。
　rpm（Redhat Package Manager）：Red Hat系のLinuxで用いられるパッケージマネージャ。以前はパッケージを入れる際に用いられていたが、依存関係を考慮するのが厄介になってきたため、リポジトリ内の依存関係にあるパッケージをすべてインストールするyumが作られた。現在はリポジトリ単位のパッケージ（remiなど）を入れる際に使われる。
　yumはrpmを基に作られているため、併用しても依存関係は崩れない。

#参考文献
[LaravelでAWS S3へ画像をアップロードする](https://qiita.com/nobu0717/items/51dfcecda90d3c5958b8)
[[AWS] VPCエンドポイント経由でEC2からS3へファイル転送](https://agohack.com/file-transfer-ec2-to-s3-via-vpc-endpoints/)
[Amazon S3 におけるエンドポイント](https://docs.aws.amazon.com/ja_jp/vpc/latest/privatelink/vpc-endpoints-s3.html)
[IAM ロール](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_roles.html)
[リポジトリ・yum・rpmについて](https://qiita.com/tatsuo-iriyama/items/04e101d056f235c2b9db)
[AWS SDK For PHPを使ってみた](https://blog.denet.co.jp/aws_sdk_for_php/)
【AtCoder】JavaとCOBOLで解き比べ。

こんばんは。

AtcoderをCOBOLで解く人は少ないようです。
自分はAtCoderの成績は全く振るいませんが、一応COBOL歴10年ちょいですので、解いてみました。久々にCOBOLを書くと、文法（IF文の構成）やお作法（8カラム目からじゃないと記述できない）を結構忘れており苦戦しました。プログラムを読むと書くとではやはり違うと実感しました。
でも自分の母国語だと思っているCOBOLで解くのは楽しかったです。

Atcoder　ABC-215のA問題を使用しました。
※少ないですが、COBOLで解いている方も数人はいらっしゃるようです。
　ただ、A問題は数人ですが、B,Cになると0人のようです。本格的な数学問題だと難しいのでしょうか。

###COBOL

```COBOL
        PROGRAM-ID.                      Main.
        DATA                             DIVISION.
        WORKING-STORAGE                  SECTION.

        01 ESU                             PIC X(15).
      
        PROCEDURE                        DIVISION.
      
        ACCEPT    ESU.
        IF ESU = 'Hello,World!' THEN
        DISPLAY 'AC'
        ELSE
        DISPLAY 'WA'
        END-IF.
        STOP RUN.      

```

###Java

```JAVA
import java.util.Scanner;
import java.util.Arrays;
import java.util.ArrayList;

public class Main{
public static void main(String args[]){
  Scanner sc = new Scanner(System.in);
  String s = sc.next();
  if(s.equals("Hello,World!")){
   System.out.println("AC");
  }else{
   System.out.println("WA");
  }

}
}

```


###COBOLの方が速い？

COBOLは、8ms、Javaですと100msでした。
数回試しましたがこの傾向にあります。
やはり事務処理言語としてCOBOLの高速性は事実なんですかね。

C問題は速度を試されることが多いので、COBOLで解いたらできたりするかな・・。
優れているなら、今後も技術として残っていってもいいのにね。