OmniAICreator/Qiita-1.07M huggingface dataset:
【pythonista】Google Map APIを使わずに座標を取得する方法

#きっかけ

GoogleMapのナビに業を煮やし
Yahooカーナビの検索能力に困惑していたため

他にもショートカットやPythonistaで作っている方がいましたが
イマイチ理解出来なかったので強引に座標データを取得する事を決意
(API使用料も払えないしね…)

#いきなりですがコードです

```python
#!python3

# ↓候補には上がりませんが最初からインストールされていました
from bs4 import BeautifulSoup

import urllib.request
import webbrowser
import appex

if not appex.is_running_extension():

	print('oh no!')

else:

	# グーグルマップの共有より短縮URLを取得
	src_url = appex.get_url()
	# 短縮URLより通常のURLを取得
	response = urllib.request.urlopen(src_url)
	# ↓よく分かんないけと参考サイトのをコピペ状態
	query = urllib.parse.parse_qs(response.url)
	
	# URLにftidの文字列が含まれていた場合
	if ('ftid' in query):
		
		# htmlを取得
		html = response.read()
		# ↓ここもよくわからないけど整形してるらしい
		root = BeautifulSoup(html,'html5lib')
		
		# html内に存在する@を起点に座標データを取得
		# 調べた限りでは2箇所に座標データが存在してましたが楽に取得できる方を設定
		(lat, lon) = str(root).split('@')[2].split('\\')[0].split(',')[0:2]
	
	# ftidの文字列がなかった場合
	else:
		
		# ↓参考サイトのをコピペかつ手抜き化
		(lat, lon) = query['https://www.google.com/maps?q'][0].split(',')

	# YahooカーナビへのURL(?)に座標データを設定	
	yahoo = 'yjcarnavi://navi/select?lat=%s&lon=%s' % (lat, lon)
	
	# Yahooカーナビ起動！
	webbrowser.open(yahoo)
```

#書く事なし

コメントに書いたのでもう思い浮かびません
Pythonistaの設定などは他で調べて下さい(力尽きました)

##参考サイト
[ひとりぶろぐ:iOSのGoogleマップとYahoo!カーナビ等の地図アプリを連携させる方法](http://hitoriblog.com/?p=56332)
【Vue.js】コンポーネント超入門

#はじめに
最近、Vue.jsを使って自学用にWEBアプリを作成しているのですが、
そこでコンポーネントを使った実装をする機会がありました。

今回はその中で得たコンポーネントの概念的な基礎知識や
コンポーネント間のデータのやりとりについて書いていきます。
#コンポーネントとは
コンポーネントとは、ある特定の機能を保有した再利用可能な「部品」を指し、
Vue.jsでは「再利用可能なVueインスタンス」と定義できます。

また、コンポーネントを組み合わせてWEBアプリケーションを構築する開発を
「コンポーネント指向開発」と呼びます。

最近のフロントエンドの開発ではこの手法が主流になってきています。

#コンポーネントを使うメリット
先ほど「コンポーネント指向開発がモダンフロントエンド開発手法のスタンダード」
と書きましたが、そこにはやはり理由があります。

コンポーネント指向が採用される最大の理由は、
「再利用性が高い」という点です。

従来の開発手法では、同じUIパーツを複数ページに実装する場合、
同一コードを何度も書く必要がありました。

しかし、コンポーネントを使用すると、
機能ごとにコンポーネントとして分割した部品を再利用できます。
そのため開発スピードの向上が期待できるのです。

また、機能が分かれていることからメンテナンス性も高まり、
これらのメリットはより大規模な開発を行う際に実感できます。
#親コンポーネントと子コンポーネント
コンポーネントには大きく分けて２つの種類があります。
それは「取り込む側のコンポーネント」と「取り込まれる側のコンポーネント」です。

そして、Vue.jsでは取り込む側を「親コンポーネント」、
取り込まれる側を「子コンポーネント」と呼びます。
#親子間のデータのやりとり
Vue.jsでは親子間のデータのやりとりをpropsとemitで実現します。

props：親から子に渡されるデータ
emit：子から親に渡されるデータ

propsとemitの具体的な書き方については後日別記事で整理します。



#参考資料
[書籍「たった1日で基本が身に付く！Vue.js超入門」](https://www.amazon.co.jp/たった1日で基本が身に付く！-Vue-js-超入門-石亀-広大-ebook/dp/B089LDYFV1)
GoogleAnalyticsとBigQueryで行動観察

:::note warn
この記事はGoogle Analytics 4ではなく、Universal Analyticsを対象としています。
:::

## 課題

Google Analytics(UA)にはユーザーごとの行動を分析できるユーザーエクスプローラーという機能がありますが、ヒット数の多いプロパティでは動作が重くなってしまうため安定した利用が難しい状態です。

例えば以下のようなエラーが頻発することもあります。
![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3134373638392f33393436343862652d373430342d313164622d383630612d6266383330636261313535352e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147689/3cac2b3b-547f-dd94-b94f-0ec3cceed95e.png)
というわけでユーザーエクスプローラーで実施していたuidベースの行動観察をBigQueryでのクエリ発行で代替してみます。

## カスタムディメンションにuidをセット

Google Analyticsのヒットにuidを紐づけるため、フロントエンド側でdataLayer配列に一意のuidをセットします。

```javascript
var dataLayer = dataLayer || [];
dataLayer.push({
  uid: '1234567890abcdefg'
});
```
GTM側でこの値を拾いページビューヒット・イベントヒットにuidを紐付けることになります。

なお、dataLayer変数はOptimizeのターゲティング条件としても利用できるため、Optimize関連のタグより上部の位置で記述することをおすすめします。

## SQLで抽出
やっていることは単純で、ヒット時間・ページパス・ヒットタイプ・イベントカテゴリ・イベントアクション・イベントラベルと「カスタムディメンションにセットしたをuid」を抽出しているだけです。

```sql
WITH
  raw_data AS(
  SELECT
    DATETIME(TIMESTAMP_SECONDS(visitStartTime + CAST((hits.time / 1000) AS int64)),
      'Asia/Tokyo')AS time,
    page.pagePath,
    hits.type,
    hits.eventInfo.eventCategory,
    hits.eventInfo.eventAction,
    hits.eventInfo.eventLabel,
    (
    SELECT
      MAX(
      IF
        (index=1,
          value,
          NULL))
    FROM
      UNNEST(hits.customDimensions)) AS uid
  FROM
    `projectName.datasetName.ga_sessions_*`,
    UNNEST(hits) AS hits
  WHERE
    _table_suffix BETWEEN "20210101"
    AND "20210101" )
SELECT
  * EXCEPT (uid)
FROM
  raw_data
WHERE
  uid IN ("1234567890abcdefg")
ORDER BY
  time DESC
```
※`index=1`の箇所はGoogle Analytics側で設定している当該カスタムディメンションのインデックス番号を指定します。


このクエリはユーザーエクスプローラーで言うところのページビューとイベントを抽出しているイメージですね。

![スクリーンショット 2021-05-05 17.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147689/94cb0931-5fcc-1966-466c-ef4fd794bc34.png)

目標設定をしていたりeコマーストラッキングしている場合には、それらも併せて抽出するといいと思います。

## 抽出結果

表データとして時系列の行動ログを抽出することができました。
![スクリーンショット 2021-05-04 12.46.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147689/a549f901-50c3-8cf1-b400-66b6901e8f76.png)
SQLなので、カスタムディメンションやカスタムメトリクスの値、セッション番号等も柔軟にカラム追加することができます。 

ユーザーエクスプローラーではページパスを確認するためには都度アコーディオンを開く必要がありますが、BigQueryでは表形式になるため一覧性が高くなると思います。

※BigQueryのWEB UIでは1度に200行しか表示できないため、クエリ結果が見づらい場合にはGoogleスプレッドシートへのエクスポートをおすすめします。

## GA4でも同じことをしたい
GA4でも「分析ハブ」の中にGUIとしてのユーザーエクスプローラーはありますが、今回のようにSQLベースでも抽出できるようにしたいと考えています。
ただ、自動イベントの`page_view`のユーザープロパティに対してuidをセットできないことがあったりで、対応策がまだ思いつかない状態です。

## 運用してみた感想

今回の方法にてCS問い合わせの追跡調査やユーザー理解(定性分析)のための行動分析を実施していますが、GAのGUIからBigQueryに切り替えることで確実にスピード感が上がりました。（ディスカッション → 画面を見ながらの検証 の繰り返しをテンポよく進められるようになりました）

Google Analytics（ヒット数の多いプロパティ）を使う場合、カスタムセグメントの作成に2分、ユーザーエクスプローラー側で当該セグメントのログを表示させるのに2分以上かかることもありますが、BigQueryであればGUIの操作が不要でクエリの結果も20秒以内には返却されます。カスタムセグメントの作成をWHERE句に置き換えられることもメリットの一つだと思います。そして各クエリがコード化・モジュール化されることで分析の再現性も高まりますし、バージョン管理も可能になります。

ユーザーエクスプローラーに限らずカスタムレポートでもそうですが、GUIではなくSQLの方がレスポンスが速いだけでなく他者への展開も楽になる(敷居が下がる)のではないかと思いました。
[メモ] sticky & Intersection Observer & opacityの併用はchromeでバグるっぽい


- position: sticky　(by css)
-> スクロールして画面上部で固定。弟要素が上にかぶさる

- Intersection Observer (by js)
-> 画面表示領域内への出入りでアニメーション用のクラス追加・削除

- opacity (by css)
-> Intersection Observerに伴うクラスによって表示/非表示アニメーション

の3点を組み合わせると、

上へのスクロールはできるけど、下へのスクロールができなくなる。
（上へのスクロールは通常だけど、下へスクロールは弟要素が画面下でバウンスして戻ってくる）
なんでだろう……。

どれか2個までの組み合わせなら動くんだけどな～。
この3つになると動かない…

↓書いたもの（一部省略）

```vue:parent.vue
<template>
  <div class="l-page">
    <section class="list">
      <Widgets-component
        v-for = "item in items"
        :item = "item"
        class = "item"
        :key = "item.id"
        :ref = "'item'"
      />
    </section>
  </div>
</template>

<script>
export default {
  data() {
    return {
      items: [//**省略**//]
    }
  },
  updated() {
    let targets = [];
    this.$refs.item.forEach(el => targets.push(el.$el));

    const observer = new IntersectionObserver((entries) => {
      let className_active = 'is-show';
      entries.forEach((entry) => {
        if (entry.intersectionRatio >= 0.8) {
          entry.target.classList.add(className_active);
        } else {
          entry.target.classList.remove(className_active);
        }
      });
    }, {
      root: null,
      rootMargin: '0px',
      threshold: 1   
    });

    targets.forEach((target) => {
      observer.observe(target);
    });

  }

}
</script>

<style lang="scss" scoped>
.list {
  height: 100%;
  overflow-y: auto;
  scroll-snap-type: y mandatory;
}
.item {
  position: sticky;
  top: 0;
  height: 82vh;
  scroll-snap-align: start;
  scroll-snap-stop: always;
}
.disc-item::v-deep {
  .item-body, .item-footer {
    opacity: 0;
    transition: opacity 600ms ease;
  }
  &.is-show {
    .item-body, .item-footer{
      opacity: 1;
    }
  }
}
</style>

```


```vue:child.vue
<template>
  <div>
    <div class="item-thumb">
      <img :src="item.images.url" />
    </div>
    <div class="item-body">
      some body element
    </div>
    <div class="item-footer">
      some footer element
    </div>
  </div>
</template>

<script>
export default {
  props: {
    item: { type: Object }
  }
}
</script>
```

ちなみにopacityじゃなくて、backgroundだと普通に動くんだよな～。
なんか別の理由かな～。


```vue:parent.vue
<style lang="scss" scoped>
.disc-item::v-deep {
  .item-body, .item-footer {
    background: red;
  }
  &.is-show {
    .item-body, .item-footer{
      background: blue;
    }
  }
}
</style>

```
キーボード配列エミュレータ紅皿での「゛゜小」キーの実現

#１．はじめに
　かな入力とは、キーボードに刻印されたかな文字に基づき、日本語を入力することをいいます。そして、ローマ字入力とは、読みに対応するローマ字綴りをキーボードなどから入力することをいいます。角川アスキー総研の2015年度の調査によれば、ローマ字入力のシェアは93.1％と圧倒的なのですが、これはひとえに学習コストの少なさによるとおもいます。なお、同調査におけるカナ入力のシェアは5.1％です。そして、親指シフト入力のシェアは1.2％です。

#２．各モードの学習コストの評価。
##１．１．ローマ字モードの学習コスト
　ローマ字入力にて必要なキーは、単打「-wertyuiopasdfghjklzvbnm,.」の２５キーであり、シフトは不要です。

##１．２．カナ入力の学習コスト
　カナ入力にて必要なキーは、単打の 
  「ヌフアウエオヤユヨワホヘー
　　タテイスカンナニラセ゛゜
　　チトシハキクマノリレケム
　　ツサソヒコミモネルメロ」
　の４８キーと、シフト打鍵の「ァゥェォャュョヲィッ、。」の１２キーの併せて６０キーです。
　シフトによる拗音の学習コストをゼロと仮定すると、学習に要するのは５１キーです。

##１．３．親指シフト(NICOLA)の学習コスト
　そして、親指シフト(NICOLA)にて必要なキーは、単打の
　「．かたこさらちくつ，゛
　　うしてけせはときいん
　  ひすふへめそねほ」の２９キーと、
　左親指シフトの
　「ぁえりゃれぱぢぐづぴ
　　をあなゅもばどぎぽ
　　ぅ－ろやぃぷぞぺぼ」の２８キーであり、うち濁音キーを除くと１８キーです。
　右親指シフトの
　「がだござよにるまぇ゜
　　ゔじでげぜみおのょっ
　　びずぶべぬゆむわぉ」の２９キーであり、うち濁音キーを除くと１５キーです。
　
　シフト打鍵のうち半分弱は、単打の濁音なので、この学習コストを０とすると、学習を要するのは３モードの６２キーです。
　このように、各入力方式の学習コストが高いほど、シェアは低くなることがわかります。

#１．４．スマートフォンのフリック入力
　ここでスマートフォンのフリック入力を検討します。スマートフォンのフリック入力は、大変によく出来ています。
　５０音のうち子音部分を１０キーで選択したのち、母音の選択キーが５つ現れるというものです。
　そして、濁音・半濁音・拗音は、「゛゜小」キーにより順次選択可能です。
　ユーザから見えているキーは、各子音キー１０と、記号キーと「゛゜小」キーを含めて合計１２キーです。母音の選択キーが現れた後を考えても１７キーです。このように、スマートフォンの入力方式では、学習コストを少なくすることに注意が払われています。

![フリック入力.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266273/2e2512db-9910-9476-0f99-a20d03dd41ee.png)

　ここでは、親指シフト入力の学習コストを低くするための措置として、「゛゜小」キーを親指シフト方式のキーボード配列エミュレータに導入することを検討します。

#３．キーボード配列エミュレータ紅皿への「゛゜小」キーの実装
　親指シフト入力に、「゛゜小」キーを導入できた場合、拗音と半濁音を記憶していない状態でも、そこそこにタイプ可能となります。
　日本語の拗音は｢ァゥェォャュョィッ」の９キーであり、半濁音は「パピブペボ｣の５キーです。そして「゛゜小」キーは半濁点キーを代替可能です。よって、親指シフトの学習コストは３モードの４８キーとなり、キー数のみでいうとカナ入力の学習コストの５１キーを下回ります。

##３．１．設計方針
- キーボード配列エミュレータ紅皿(benizara)は、ローマ字モードで動作するものとします。OSのデフォルトがローマ字モードであるためです。
- 「゛゜小」キーを、紅皿では「修」キーと名付けます。紅皿において各種制御キーは一文字の漢字として表しているためです。

##３．２．動作
- (1) ローマ字モードにて最後に打鍵されたキーの表層文字を記憶します。
- (2) 最後に打鍵されたキーの表層文字に対応する拗音・半濁音・濁音の何れかを記憶します。

　なお、表層文字が拗音・半濁音・濁音自体ならば、次の拗音・半濁音・濁音を記憶します。例えば表層文字が「つ」ならば「っ」を、「っ」ならば「づ」を、「づ」ならば「つ」を記憶します。

- (3) 次に打鍵されたキーが「修」キーならば、記憶していた表層文字をBackspaceで消去して、記憶していた拗音・半濁音・濁音の何れかを出力します。そして、出力した表層文字と、これに対応する次の拗音・半濁音・濁音を記憶して、次のキーの打鍵を待ちます。
　なお、次に打鍵されたキーが「修」キー以外ならば、(1)に戻ります。

- 従来の濁点キー「゛」や半濁点キー「゜」も、上記のロジックを微修正することで実装可能です。

#４．結果
- 従来は、IMEが濁音や半濁音に関する処理を行っていたため、ローマ字モードで動作する紅皿では、平仮名キーの押下後の濁音キーによる濁音の付加はできませんでした。しかし、紅皿に上記のような処理機能を加えることにより、清音を濁音や半濁音に変えるほか、濁音を半濁音に変えたり、濁音を拗音に変えることが可能です。

#５．今後の課題
- 今回導入した技術は、清音を打鍵したのち、半濁音や拗音や濁音に修正するものでした。これに限られず、同時打鍵によって半濁音や拗音を出力することを検討致したくおもいます。
Rubyの条件分岐について

Rubyの条件分岐はifで表し構文は次のようになります。

```
if 条件1
  #条件1が真の場合に実行したい処理
elsif 条件２
  #条件2が真の場合に実行したい処理
elsif 条件３
  #条件3が真の場合に実行したい処理
else
  #それ以外の処理
end
```
elsifは任意の数だけ書くことができます。
elsifやelseは不要な場合は省略することができます。

例として
テストの点数scoreによって、通知表の成績をターミナルに出力するプログラムを書きます。
90点以上 A
80点以上 B
60点以上 C
60点未満 D
と出力されるようにします。

```ruby

score = 90
if score >= 90
  puts 'A'
elsif score >= 80
  puts 'B'
elsif score >= 60
  puts 'C'
else
  puts 'D'
end
```
これをターミナルで実行すると

```
testoMacBook-Air:~ test$ ruby if.rb
A
```
scoreは９０なのでAが出力されました。
もしscore=59などにした場合は６０点未満なのでDが出力されます。
DisplayPortスリープ問題をお手製アプリで回避してみた

# 概要
DisplayPortスリープ問題とやらに有効な策が取れずにいたので、自作アプリで対処しました。

# 本文

## アプリ概要
- Windowsフォームアプリ
- saveボタンを押すと、ウィンドウ情報を保存する
- restoreボタンを押すと、save時と位置情報が違う場合は復元する

### 起動時
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282159/e69a083b-489a-aee1-1365-cb0386ce7671.png)
味気ない・・・

### save時
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282159/51e64bf2-3bfb-c609-a6c4-847aebfc542b.png)
復元候補をずらっと表示します。プロセス名とウィンドウタイトルを出してます。

### restore時
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282159/664d5bd6-6714-3c9d-76de-681905ac2796.png)
ウィンドウ位置・サイズが変わっていた場合は復元を試みて、行末に結果を付加しています。

## 既知の未解決問題点

- 管理者権限で動いているウィンドウを復元するには、アプリも管理者権限じゃないとだめみたいです。（当然といえば当然なんでしょうか）
- 一部のアプリは復元できないようです。私の愛用しているアプリに「壁カレ」というのがあるのですが、これは復元に失敗します。ウィンドウの形態が特殊なのでそのせいだとは思いますが、できれば復元できるようにしたいところです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282159/fb2af5f7-f372-e6e7-b88a-f8c851c0311e.png)
- 単独exeファイルで動くようにしたいのですが、そのようなビルド設定をしても、うまくいかずにいます・・・自分で使う分には別にいいのですが、ほかの人の需要があるかもしれないなどと妄想すると少し残念です。
- 起動している覚えがないのに、復元候補に電卓が出てきます。たいした問題ではないですがもやもやします。

## ソースコード
https://github.com/kumanobori/WindowPositionRestorer

## 今後
WindowsUpdateで根本解決したら、このコードは無用になります。
そうなるまでは、未解決問題点を改良できればなーとか思ってます。
思ったように動くかわからないまま書いたのでテストコードどころじゃなかったです。拡張するならテストコードとかちゃんと整備したいです。
単一exeファイルにできれば知り合いとかに使ってみてもらうとかありえそうなので、そこをなんとかしたいです。

## チラシの裏

### デビュー作です
WindowsFormアプリ初めて作りました。
コンソールアプリでもよかったんですけど、フォームにウィンドウ情報覚えさせておくのが楽かなと思ってこうなりました。

### ポエムな開発経緯
- DisplayPortスリープ問題は今後のWindowsUpdateで解決される問題らしい
  - が、それがいつになるかわからないし、そもそも私の環境はDisplayPortじゃなくてHDMIなので、ほんとに解決するかも疑わしい
- ウィンドウ位置復元のフリーソフトは探すと見つかるけど、探した限りでは「仮想デスクトップ未対応」と来た
- じゃあ自分で何とかするか・・・？と、仮想デスクトップ対応をどうするかという視点で、雑に探してみる
  - 「仮想デスクトップ」という単語だと99.9%リモートのVDIでヒットしてしまい、むきー。となる
  - apiとかそのへんのキーワードを加えて、[SylphyHorn](https://www.microsoft.com/ja-jp/p/sylphyhorn/9nblggh58t01? activetab=pivot:overviewtab) 作者さまの [VirtualDesktop](https://github.com/Grabacr07/VirtualDesktop) を見つける
  - おお、これを使えば仮想デスクトップ対応のウィンドウ位置復元ができるのね？と思い込む
- 幸いC#は一応書ける
- インストールなしで動くVSCODEでなんとかしようと思い立ってみる
  - VirtualDesktopがapp.manifest設定やらデバッグなし実行が必要やらで、うんともすんとも動かない
  - manifestやらなんやら試してみたけどうまくいかず、諦めてVisualStudio Communityをインストール
  - VirtualDesktopはあっさり動いた。
  - VSCODEはあくまでエディタで、素人がどうにかできるとは思うなってことか・・・
- 想像では、VirtualDesktopの機能で、`getVirtualDesktops().foreach(getWindows())` みたいな感じで仮想デスクトップごとにアプリ情報を取っていく・・・のだと思っていた
  - が、そんな機能は見当たらなかった（最初に見とけって話か・・・）
- ぐぐりながら「ウィンドウすべてを取得」をしてみて、「それを保存」「それを復元」してみた
  - やってみたところ、仮想デスクトップとか関係なしに復元できてしまった
  - （公開されているウィンドウ復元ソフトが仮想デスクトップ非対応なのは何故・・・？）
- そんな疑問を残しつつ、自分の要求は、VirtualDesktopを使わずとも古来の機能で満たせるらしい
- ひとまず自分は少し幸せになれた

# 追記

## 05/15
比較的邪魔にならないであろうタスクトレイ常駐版を作りました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282159/7d5fbae8-13ac-c272-3e78-6b3c16a05fdd.png)
CSSで途中線が切れているボックスを描く

友人から初めてサイトのコーディング依頼を受けて喜んでいたら
凄く悩むところがあったので、友人への恨みとスキルアップの喜びを
込めて記事に残しておきます。

友人から届いたサイトデザインの一部
![スクリーンショット 2021-05-09 21.42.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633008/791e14d2-c0fe-dd6f-2cde-299a419f9f84.png)

なんだ普通のボックスやん！簡単、簡単
、、、、
![スクリーンショット 2021-05-09 21.42.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633008/55c0ddd7-902e-4e2e-fded-d8157710ffea.png)

なんか途中で切れてるんですけど
そこから半日格闘！！

正しいやり方かどうかはわかりませんが、以下のような方法でできました。

```index.html
          <div class="contact-form-box contact-form-centerbox">
            <div class="flex contact-form-address">
              <p>
                500 Terry Francois St.<br />
                San Francisco<br />CA 94158
              </p>
            </div>
          </div>
```

```style.css
.flex {
  display: flex;
  justify-content: center;
  align-items: center;
}
.contact-form-box{
  max-width: 320px;
  width: calc(100%/3);
  height: 300px;
}
.contact-form-address{
  /* ここで枠線の高さを変えている */
  height: 90%;
  width: 100%;
  box-sizing: border-box;
  border-right: 1px solid;
  border-left: 1px solid;
}
.contact-form-address{
  height: 90%;
  width: 100%;
  box-sizing: border-box;
  border-right: 1px solid;
  border-left: 1px solid;
}
```

結果
（SNSのアイコンが違うのは見なかった事に）
![スクリーンショット 2021-05-09 21.56.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633008/489c792a-897a-c3a5-c8b9-9475c01f9a1a.png)

positin:absolute;
top:-10px;
とか色々試したんですがうまくいかず、この方法でなんとかできました。
他に何か良い方法があればご教授いただきたいです。

ここまで読んでいただきありがとうございました。
CircleCI上でFlaskの疎通確認する方法

# 目的
- タイトル通り
- CI上のコンテナでflask実行環境を作成し、curlコマンドを実行、疎通が取れること。

# 失敗例
- config.yml

```yaml

# flaskの実行環境整備など(省略)

      - run:
          command: python server/app.py
          # background: trueにしないと次のstepに進まない。
          background: true
      - run: curl http://127.0.0.1:5000/

```

- 結果(失敗)
![CircleCI_flask_failed.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1159336/ab3fa729-e400-d9dc-69bc-35784627670e.png)



# 成功例
- config.yml

```yaml
      - run:
          command: python server/app.py
          background: true
      - run: sleep 10
      - run: curl http://127.0.0.1:5000/

```

- 結果(成功)
![CircleCI_flask_success.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1159336/faf1c39b-933d-fed8-3932-9b887314aaeb.png)



# 原因
`Build was canceled`が原因。
ただし、このメッセージで調べても有用な情報が見つからない(エラーの範囲が広すぎるので)
失敗例ではflaskのサーバーが立ち上がる前に次のコマンドが実施されているように見えたので、
遅延してみたところうまくいった。

本当のところの原因は不明だがとりあえず最低限動いたのでOK(滅茶苦茶ハマった)

---

(これは実行回数が多いことで筆者の頭と同様におかしくなってしまったCIrcleCI)
![CircleCI_flask_success_view.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1159336/74334689-c2f1-75d7-9754-3804e23f723d.png)
vim終了時にアンドゥファイル削除スクリプト

vimにて、プログラム修正などをやり直したいときが頻繁に発生する。
それは当然のことだろうし、他の人も例外はないだろう。

そして、やり直しをしやすいように、私は`mbbill/undotree`と言うプラグインを使っている。
それはさておき、現在のバッファを裏に回し、他のファイルを修正後に、バッファを戻した場合、やり直しが出来ずに困っていた。
そのため、アンドゥファイルを生成することに決めた。

ということで、またもや壁にぶち当たる。
以下、その壁の壊し方。

## アンドゥファイル生存期間
アンドゥファイルが生成された状態のままでは、生成された状態までやり直しをすることができる。
しかし、私はファイルを開き直した場合、やり直しはそこから始まる状態になって欲しい。
そして、バッファを切り替えた場合もやり直しは有効化を保持したままになって欲しい。

vim本体を終了したときに限り、アンドゥファイルを削除してくれればいいと思っていた。
プラグインでそこまで細かい制御が出来るように見えず、仕方ないため、自作することにした。

## vim終了時にアンドゥファイル削除
何のことはなく、ほんの数行で完成する。
(故に、当然のように完成までに数時間費やしたのは内緒だ)
そして、未完成でもある。

```vim:vimrc
augroup quitcmd
	autocmd!
	autocmd VimLeave * call s:CleanupStuff()
augroup END
function! s:CleanupStuff()
	let l:undoFileName=expand('%:p')
	if ( has('win32') || has('win64') )
		let l:undo_fileName = substitute(l:undoFileName, '\\', "%", "g")
		let l:undo_fileName = substitute(l:undo_fileName, ':', "%", "g")
	else
		let l:undo_fileName = substitute(l:undoFileName, '\/', "%", "g")
	end
	let l:deleteUndoFile=&undodir . "/" . l:undo_fileName
	call delete(l:deleteUndoFile)
endfunction
```

終了時の動作として、`VimLeave`から関数を呼び出す。
その関数内で、"アンドゥファイル生成場所＋ファイル名"の組み合わせでフルPathファイル名を作り出してからファイル削除の手順を踏んだ。

### ある程度詳細な解説
関数内の解説

* 1段目：`let l:undoFileName=expand('%:p')`
開いているファイルのフルPathを含むファイル名を抜き出す。


* 2段目：`let l:undo_fileName = substitute(l:undoFileName, '\/', "%", "g")`　←Mac用
上記のファイル名からスラッシュでのディレクトリ区切りをパーセント記号に置き換える。
Windowsの場合は、2行で処理をしており、円記号とコロン記号をパーセント記号に置き換えている。
この2行が無ければ、vimが生成するアンドゥファイル名に合致してくれない。


* 3段目：`let l:deleteUndoFile=&undodir . "/" . l:undo_fileName`
上記の置き換えは、アンドゥファイル名のためだった。そのため、今回新たにアンドゥファイル生成場所のPathを先頭に追加し、改めてフルPathを作り上げた。


* 4段目：`call delete(l:deleteUndoFile)`
実際のファイル削除実施。


## 感想
作ってみれば何てことは無いが、ないと困っていた。
ないから我慢して使っていたが、やっぱり我慢できない。
こんな時に取り組めるだけの知識を持っているというのは一歩を踏み出しやすい。
ちょっとした思い込みで時間を無駄遣いしてしまったが、知識があるというのは新しい世界への扉を見つけやすいと言うことでもある。
やはり、勉強以上に重要なことはないし、知識のみが人間であることを証明する。
今後もぼそぼそ新しい扉を開いていける人間になりたい。

### 今後
リンクファイルなどにより、実態ファイルを開いていない場合、削除できないようだ。
アンドゥファイルは、実態ファイル名で生成するようで、対処できないぞ・・・う〜む。
今後はそれを改善していきたい。


* もう一つ。
致命的なのは、複数ファイルをタブで開いておき、編集したファイル以外のタブを開いた状態でvim本体を終了した場合、アンドゥファイル削除がなされない。
これは非常に困る。
終了検知の方法が間違っている？
そう思い調べたが、通常のvimエディタでは対応できないようだな。


* もう一つ。
`xolox/vim-session`プラグインでセッション管理をしているのだが、これからセッションを再起動させた場合もアンドゥファイル削除をせずに再起動が終わる。
困る。
vim終了後に、セッションを開けば良いのかもしれないが、煩わしい。
上記通り、他のタブを開いた状態でvim本体を終了した場合も目的のアンドゥファイルを削除しないため、vim本体の終了方法にも気を遣う必要が出てくる。
困った。


* もう一つ。
バッファを閉じた(`:bd`)場合もアンドゥファイル削除はしてくれない。
さらに、上記通り目的のバッファをアクティブにせずにvim本体を終了した場合も目的のアンドゥファイルを削除しないため、致命的なスクリプトを作ったことになる。
何とかして対処したい・・・。
非常に困った。


今後のさらなる追加機能。
バッファを裏に回してもスワップファイルを維持したままにする。
これで、私の環境は完璧に近づくだろう。

私の最後の感想：新しい扉を開けることは出来なかった。

以上。
<!-- vim:set ts=4 sts=4 sw=4 tw=0: -->
Djangoで画像などのstaticファイルの読み込み

<h3>staticフォルダを用意</h3>
プロジェクト配下にstaticフォルダを用意し、その下にアプリ名でフォルダを作成
<h3>settings.pyを編集</h3>

```python:settings.py
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static'),
] 
```

<h3>htmlファイルにて読み込で使用</h3>

```html:html
{% load static %}
<figure class="figure">
        <img class="figure-img img-fluid rounded" src="{% static 'mysite/img1.jpg' %}">
        <figcaption class="figure-caption text-center small">写真の説明</figcaption>
</figure>
```

{% static 'アプリ名/img1.jpg' %}でリソースのpathを取得することができる
python-Ev3devの使い方

**限定公開から全体公開に移行しました。
この記事は、2019年に作成したものです。**

---

今回は「python-ev3Dev」の使い方について紹介します。


# 前提条件

- vscodeがインストールされている。
- vscodeに「[ev3dev-browser](https://marketplace.visualstudio.com/items?itemName=ev3dev.ev3dev-browser)」の拡張機能がインストールされている。
- vscodeに「LEGO MINDOSTORMS EV3 MicroPython」の拡張機能がインストールされている。

- ev3 とpcをUSBケーブルで接続。

# セットアップ
まずはEV3でpythonが使えるようにをセットアップしていきます。


1 まず初めにvscodeを開いてExplorerの中の 「EV3DEV DEVICE BROWSER」をクリック。


 ![スクリーンショット 2021-05-09 19.08.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422338/21f017fc-5c05-5a26-3986-95ccda946b2f.png)

2 「click here to connect to a device」をクリック。

![スクリーンショット 2021-05-09 19.10.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422338/e1bee988-2ffb-2522-c6ca-a92be5e141ff.png)

3 上のウィンドウからev3devをクリック。

![スクリーンショット 2021-05-09 19.10.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422338/9e8d30ec-fb3d-5a96-8557-dbbfe58d9f9f.png)

4 クリックできたら下のの画像のような緑色になるまで待ちます。

![スクリーンショット 2021-05-09 19.11.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422338/e600a2ec-aa6a-756a-e0bb-c6d63c5b27cc.png)



ここまででEV3との接続は完了。



# 実際に作成して見よう！

まずはmicroPythonの拡張機能が入っていると下画像のような①のタブがあると思うのでそこをクリック。そのあと「Create a new project」を選択し新しいプロジェクトを作成します。
![スクリーンショット 2021-05-09 21.12.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422338/39820ff6-e46b-6e32-535b-c83c3fcd85e7.png)

上の方にポップアップウィンドウが出てくるのでそこにプロジェクトの名前を入れる。(英語ならなんでもOK!)



![スクリーンショット 2021-05-09 21.14.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422338/d05e2ef1-2a0f-a598-1425-ff3dc728d1ad.png)
名前を入れたら、適当な場所に保存する。

するとVScode上に以下のようなフォルダが作成されるので「main.py」をクリック。

![スクリーンショット 2021-05-09 21.14.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422338/84f817c8-9860-a310-ac99-4ba118e9bd6d.png)

以下のような画面が出ればプログラムを書くことができます！！


![スクリーンショット 2021-05-09 21.16.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422338/0c7a2b97-b7c0-430d-5e33-e32e20242117.png)



# プログラムの説明


1~8行目まではev3でpythonを使うためのインポートなので消さないようにしましょう！


試しに以下のプログラムを入力してでモーターを回してみましょう！

```python
brick.sound.beep() #ビープ音を鳴らす。

a_motor = Motor(Port.A) # ポートAのモーターを「a_motor」変数に入れる。

a_motor.reset_angle(0) # 累積回転角度をリセット

a_motor.run_target(30,180,Stop.COAST,True) # run_target(速度,目標角度,惰性走行,目標角度まで待機)

```



## 実行方法


`F5`または上タブの`Run/StartDebugging`で実行できます。


もっと詳細なプログラムはこちら↓
[EV3 MicroPython](https://legoedu.jp/_pdf/news_20190830.pdf)
京セラプログラミングコンテスト2021（AtCoder Beginner Contest 200）

##[A - Century](https://atcoder.jp/contests/abc200/tasks/abc200_a)

O(1)

```C++:C++
#include <bits/stdc++.h>
 
#define rep(i,n) for(int i=0; i<(n); ++i)
#define fixed_setprecision(n) fixed << setprecision((n))
#define execution_time(ti) printf("Execution Time: %.4lf sec\n", 1.0 * (clock() - ti) / CLOCKS_PER_SEC);
#define pai 3.1415926535897932384
#define NUM_MAX 2e18
#define NUM_MIN -1e9
 
using namespace std;
using ll = long long;
using P = pair<int,int>;
template<class T> inline bool chmax(T& a, T b){ if(a<b){ a=b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b){ if(a>b){ a=b; return 1; } return 0; }
 
int main() {
    int N;
    cin >> N;
 
    cout << (N-1)/100 + 1 << endl;
 
    return 0;
}
```

##[B - 200th ABC-200](https://atcoder.jp/contests/abc200/tasks/abc200_b)

O(N)

```C++:C++
#include <bits/stdc++.h>
 
#define rep(i,n) for(int i=0; i<(n); ++i)
#define fixed_setprecision(n) fixed << setprecision((n))
#define execution_time(ti) printf("Execution Time: %.4lf sec\n", 1.0 * (clock() - ti) / CLOCKS_PER_SEC);
#define pai 3.1415926535897932384
#define NUM_MAX 2e18
#define NUM_MIN -1e9
 
using namespace std;
using ll = long long;
using P = pair<int,int>;
template<class T> inline bool chmax(T& a, T b){ if(a<b){ a=b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b){ if(a>b){ a=b; return 1; } return 0; }
 
int main() {
    ll N, K;
    cin >> N >> K;
 
    rep(i, K){
        if(N%200==0){
            N = N / 200;
        }else{
            N = N * 1000 + 200;
        }
    }
    cout << N << endl;
 
    return 0;
}
```

##[C - Ringo's Favorite Numbers 2](https://atcoder.jp/contests/abc200/tasks/abc200_c)

O(N)
200で割った余りが同じ数字は減算を行うと200の倍数になります。
その組み合わせの数を計算する問題です。

```C++:C++
#include <bits/stdc++.h>
 
#define rep(i,n) for(int i=0; i<(n); ++i)
#define fixed_setprecision(n) fixed << setprecision((n))
#define execution_time(ti) printf("Execution Time: %.4lf sec\n", 1.0 * (clock() - ti) / CLOCKS_PER_SEC);
#define pai 3.1415926535897932384
#define NUM_MAX 2e18
#define NUM_MIN -1e9
 
using namespace std;
using ll = long long;
using P = pair<int,int>;
template<class T> inline bool chmax(T& a, T b){ if(a<b){ a=b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b){ if(a>b){ a=b; return 1; } return 0; }
 
void solve(ll N, map<ll, ll> m){
    ll res=0;
    for(int i=0; i<200; i++){
        if(m[i]<2) continue;
        res += ((m[i]-1) * m[i]) / 2;
    }
    cout << res << endl;
}
 
int main() {
    ll N;
    cin >> N;
    map<ll, ll> m;
    rep(i, N){
        ll t;
        cin >> t;
        m[t%200]++;
    }
    solve(N, m);
 
    return 0;
}
```
pythonのfor文は本当に遅い？ (今日のPython Day9)

#0. はじめに
　「Pythonのforループは遅い」とよく(?)言われるそうですが、本当に遅いのか疑問に思いました。もちろん記事を書いている当人が初心者なので複雑なことをしてない(というかできない)だけかもしれません。今回は初心者でもfor文とその処理時間を出力することができる問題を作成しました。最後まで読んでいただけるとありがたいです。

#1. 問題
　1から10,000までの整数を1つずつ出力するプログラムを作成してください。また処理の最後に実行時間を出力するようにしてください。なお実行時間を出力する方法が分からない人はヒントを参考にしてください。

#2. ヒント
　[【Python】処理にかかる時間を計測して表示](https://qiita.com/mitsu4310)という記事が分かりやすくよくまとまっているように感じました。この記事を参考に問題を解いてください。

#3. 解答例

```python
import time

START_TIME = time.time()
for i in range(1, 100001):
    print(i)
    i += 1
lag = time.time() - START_TIME
print(f"実行時間は{round(lag, 3)}秒です。")
```

#4. 解説
　まず数の出力にはfor文を用いました。今回は1から10,000までの数を出力したかったのでrange()関数の中身(これを引数と言います) は1, 10001としました。range(10000)とすると0から9,999までの数が出力されてしまうからです。次に、先ほど紹介した記事に書かれていたように処理時間は「処理を終えた時間」から「処理を始めた時間」を引くことで求めました。今回の解答例ではそれに加えて処理時間の小数第3位以下を(個人的に)四捨五入したかったのでround()関数を用いました。これはなくても構いません。　
　肝心の処理時間ですが、なんと**0.091秒**。自分はとてもはやいと思いました。

追記 (2021/05/10)
　@dfghdfdjftyfghvgjhk様がコメントに書いてくださったようにprint()関数にかなり時間がかかっています。自分としては0.505秒も0.016秒もどっちも早いと思ってしまうのですが。
　for文そのものが遅いというよりは複雑な処理を何万回も実行すれば当然のことながら遅くなる(という事を伝えたかった。伝わった？)。


#5. まとめ
・自然数を1つずつ表示するにはfor i in range()を用いる。
(↑ただしwhileでも同じことはできます。)
・処理時間は「処理を終えた時間」から「処理を始めた時間」を引いて求める。
・小数の四捨五入にはround()関数を用いる。

#6. おまけトーク
　[Pycharm](https://www.jetbrains.com/ja-jp/pycharm/)というIDEを用いると簡単に外部モジュールをimportできるのですが、importする様子を見たいがためにわざわざシェルを使っています。あれってプログラムしている感じがあって個人的には好きなんですよね。私だけですかね？最後まで読んでいただき本当にありがとうございます。

# 参考文献
[【Python】処理にかかる時間を計測して表示](https://qiita.com/mitsu4310)
【TypeScript】TypeScript の 型キャスト

#型キャスト ( Type Casting ) とは
* Type Assertion（型アサーション）とも呼びます
* TypeScriptによって推論された型を、上書きできます
    * 方法①：`<T>`を前につけて型を指定
    * 方法②：`as T`キーワードで型を指定

##DOM要素を取得する例

*  TypeScriptはHTMLコードに解析までできないので、"id" が pタグに設定されているかどうかは判定できません

```ts
// pタグを取得
const pTag = document.querySelector('p'); // HTML paragraph Element || null であることを認識できている

 // TypeScriptはidがpタグに設定されているかどうかは判定できない
const paragraph = document.getElementById('output');

// TypeScriptは id = user-input が inputであることを判定できない
const userInputElement = document.getElementById('user-input')! ; // HTMLElement
```

* そこで、input の value を設定したい場合など、特定のタグのための処理を行いたい場合、 タグが存在することを示し、型キャストでタグの種類を明示する必要があります

###タグが存在することを示す方法
* `!`でinputが存在する（nullではない）ことを示す事ができます
    * しかしこのままでは、constの型はHTMLエレメントで、ありHTMLinputであることは不明です

#型キャストの2種類の方法
* 方法①：`<HTMLInputElement>`を前につける
    * `const userInputElement = <HTMLInputElement>document.getElementById("user-input”)!;`
* 方法②：`as`キーワードで型を指定
    * `userInputElement as HTMLInputElement`


```ts
//型キャスト①<HTMLInputElement>を前につける

const userInputElement = <HTMLInputElement>document.getElementById("user-input")!; // HTMLInputElement

//型キャスト②asキーワードで型を指定
//inputタグの存在に確証がある場合は!をつける

const userInputElement = document.getElementById( // HTMLInputElement
    'user-input',
)! as HTMLInputElement ;
```

```ts
//型キャスト②asキーワードで型を指定
//nullではないことに確証がない場合

const userInputElement = document.getElementById( 'user-input' ) ;

if (userInputElement) {
  (userInputElement as HTMLInputElement).value = 'こんにちは';
}
```
「中心極限定理」シミュレーション（二項分布）

東京大学出版会から出版されている「[統計学入門(基礎統計学Ⅰ)](https://www.amazon.co.jp/%E7%B5%B1%E8%A8%88%E5%AD%A6%E5%85%A5%E9%96%80-%E5%9F%BA%E7%A4%8E%E7%B5%B1%E8%A8%88%E5%AD%A6%E2%85%A0-%E6%9D%B1%E4%BA%AC%E5%A4%A7%E5%AD%A6%E6%95%99%E9%A4%8A%E5%AD%A6%E9%83%A8%E7%B5%B1%E8%A8%88%E5%AD%A6%E6%95%99%E5%AE%A4/dp/4130420658)」で解説されている「中心極限定理」について、コンピューター・シミュレーションしている結果が掲載されています。
※ 「大数の法則」のシミュレーションは[こちら](https://qiita.com/sin-nakamura/items/ad819584e4e9588bb566)を参照ください。
書籍では二項分布と指数分布によるシミュレーション結果が掲載されていますが、今回は二項分布についてシミュレーションしてみたので掲載しておきます。

### ■ Pythonサンプルコード
```
# 統計学入門(東京大学出版会)の「中心極限定理」シミュレーション
# [0,1)の乱数を発生させ、0.1未満なら成功(1)、0.1以上なら失敗(0)とする。
# 繰り返し回数n(5,10,20,30,50,100)の二項乱数を250個生成し、標準化した確率分布が
# 正規分布に法則収束するかシミュレーションする。
import numpy as np
import pandas as pd

n_list = [5, 10, 20, 30, 50, 100] # ベルヌーイ試行の回数(n)
N = 250 # 試行回数
p = 0.1 # ベルヌーイ試行の成功確率
z = np.array([]) # 標準化後の確率変数値の格納用リスト
E_list, V_list = [], [] # 平均値、分散の格納用リスト
E_t_list, V_t_list = [], [] # 期待値(理論値)、分散(理論値)の格納用リスト
x = {} # データ可視化用ディクショナリ

for n in n_list:
    r_n = np.random.rand(N, n) # 250×n の一様分布を生成
    r_n = np.vectorize(lambda x: 1 if x<p else 0)(r_n)
    r = np.sum(r_n, axis=1)
    E = np.sum(r)/N # 平均値
    V = np.sum((r-r.mean())*(r-r.mean()))/N # 分散
    E_t = n*p # 期待値(理論値)
    V_t = n*p*(1-p) # 分散(理論値)
    #z = (r-E_t)/np.sqrt(V_t) # 標準化(理論値)
    z = (r-E)/np.sqrt(V) # 標準化
    
    E_list.append(E)
    E_t_list.append(E_t)
    V_list.append(V)
    V_t_list.append(V_t)
    x[n] = z

fig, axes = plt.subplots(3, 2, figsize=(10, 8), sharex=True, sharey=False)

# グラフ出力
for ax, n in zip(axes.ravel(), n_list):
    ax.set_title('Distribution after standardization - Bi('+str(n)+','+str(p)+')', fontsize = 10)
    ax.set_xlabel('Random variable(Z)')
    ax.set_ylabel('Frequency')
    ax.set_xlim(-4, 4)
    ax.grid()
    ax.hist(x[n], bins=40)
fig.suptitle('Central limit theorem - Simulation', fontsize = 14)
fig.tight_layout()
plt.show()

# 平均、分散出力
E_V = []
E_V.append(E_list)
E_V.append(E_t_list)
E_V.append(V_list)
E_V.append(V_t_list)
df = pd.DataFrame(E_V, columns=n_list, index=['平均','平均(理論値)','分散','分散(理論値)'])
display(df)
```
### ■ 結果
＜二項分布の場合の実験結果＞
![img.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693077/6c404c0f-bc9c-407b-619f-f07cebf7da2a.png)
＜平均と分散＞
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693077/329a6243-7a2a-3a69-6feb-001075c1e5c7.png)
### ■ まとめ
繰り返し回数を5回→10回→・・・→100回と増加させるに従い、正規分布のような形状になっていくことが確認できました。書籍に倣い平均と分散も出力させましたが、こちらもほぼ理論値と等しい値がでています。確率論としては数学的に証明されている定理ですが、二項分布を模したデータからも実際に正規分布が得られることも感覚として理解できました。
Go言語入門 --Hello Worldまで--

# はじめに
最近Go言語へ入門したので学んだことを記憶の整理を兼ねて書く。この記事ではGoでHello Worldができるまでを書く。windows、linuxなどのMacOS以外の環境での動作は確認していないが、同様の方法で進められるように書いた。
# 環境
MacOS BigSur 11.2.3で行った。
# 使用方法
Goは他にも幾つかあるかもしれないが、[Playground](https://play.golang.org/)を使う方法とGoをインストールしてを使う方法がある。Playgroundはプログラムの作成と実行ができるwebアプリケーションであり、簡単なコードを試したいときなどに使うのが便利である。この記事では後者の方法で導入を行い、Hello Worldを行う(PlayGroundは開いてrunするとできる)。
# インストール
GoはMacを使っているのであれば`brew install go`でインストールできるが、今回はwindowsやlinuxでも同様の手法で行えるように[公式サイト](https://golang.org/dl/)からダウンロードしてインストールを行う。バージョンに拘りがなければFeatured downloadsから自分の環境に合わせたものをクリックするとダウンロードが行える。インストーラーではインストール先などが聞かれるが、通常はそのまま進めてインストールを行なって良い。インストールができたら、ターミナルなどから`go version`と行いインストールしたGOのバージョンが出たら成功(既にターミナルを開いていたのであれば再起動する必要がある)。
goコマンドがわからないと出たら、zshを使っている場合は

```
echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.zshrc
source ~/.zhsrc
```
bashを使っている場合は

```
echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc
source ~/.bashrc
```
とターミナルから実行することで問題なく使える(GOROOTと言うものを設定している)。linuxでは`$HOME/.profile`または`/etc/profile`に

```
export PATH=$PATH:/usr/local/go/bin
```
を追加すると良いらしい。インストールについてわからないことがあれば[ここ](https://golang.org/doc/install)を参照すると良い。
# Hello Worldするコードを書く。
適当なテキストエディタで任意の場所に以下のようなソースコードを記述する。

``` go:hello.go
package main

import (
    "fmt"
)

func main() {
    fmt.Prinrln("Hello World")
}
```
記述したら、コードを保存した場所で以下のコマンドを打つ

```
go run hello.go
```
そうすると、Hello Worldと出力される。インタプリタ言語のように動いているように感じるが、`go run`はコンパイルと実行を連続して行うコマンドであり、インタプリタのように感じるのはコンパイルの高速さゆえの錯覚のためである。もちろんコンパイルだけを行うこともできて、その場合は`go build hello.go`と入力することでネイティブコードのプログラムファイルを生成することができる。このファイルはMacOSでは`hello`というコマンドプログラム、windowsであれば`hello.exe`である。これらのプログラムの実行は`./hello`や`hello`と入力することでできる。
1カ月で統計検定2級に合格した話

# 目次
* はじめに
* 勉強方法
* 結果
* その他

# はじめに
## 目的
*  統計検定2級を受ける目的
 * E資格に受かったが、数学部分の点数は想定より低かったため、数学周りの知識を固めたい
 * データ分析のコンペに参加する際、EDA段階は特に統計学知識が問われるため
* Qittaに残す目的
    * 2級を受ける予定の誰かのため
    * 復習ノート
    
## 目標
* 2021年5月27日に統計検定2級合格
(コロナの中で筆者はいつでも受けられるCBT方式を利用していた)

## 統計検定2級とは
> 大学基礎課程（１・２年次学部共通）で習得すべきことについて検定を行います。
(1) 現状についての問題の発見、その解決のためのデータの収集
(2) 仮説の構築と検証を行える統計力
(3) 新知見獲得の契機を見出すという統計的問題解決力
について試験します。

## 現状
* 社会人5年目、エンジニア職、データサイエンティストを目指して努力中
* G検定・E資格取得済み
* 経済の大学院卒だったので数式にアレルギーはないが、結構時間経ったので大分忘れた(´;ω;｀)

# 勉強方法
* 1冊か2冊の統計学の本を読む
    * 同じく統計検定2級を受けたい同期と週一ペースで輪読会を行い、以下の本を一通り読みました。
        * 意味がわかる統計学（ベレ出版）
    * 筆者は以下の本も読みました。この本はほぼ統計学入門の定番の本です。
        * はじめての統計学（日本経済新聞出版社）
    * 基礎問題を沢山解きたい方に、以下の本もおすすめです。
        * 統計学演習（培風館）
* 統計検定2級公式問題集を解いてみる
    * 受かるために、やはり公式問題集を解くのは何よりです。
    * 筆者は2015～2017年のを自分で購入し、 2018～2019年のが期間限定でネット公開されており、以下のサイトから取得できます。
        * [統計検定2級過去問2018～2019](https://www.toukei-kentei.jp/info/challengetk/challengekako/)
    * 解く順番はお任せですが、筆者は古い方から解いてきました。
* 公式問題集で出た知識ポイントは関連動画で補完
    * 最近統計学を紹介するYouTubeチャンネルが増え、動画の質も結構いいです。
    * 以下のチャンネルがおすすめ
        * 統計チャンネル
            * 統計学の基礎を全50話の動画でまとめ、知識ポイントの解説だけでなく、本番に近い例題も取り上げています
        * Yuya.K_ASN
            * 統計チャンネルで知識ポイントをカバーできていない所はこのチャネルで補完。このチャンネルは難しい公式の覚え方や理解方法などもよく解説しています。
* 統計Webは参考程度
    * 統計Webを読み切ることをお勧めする方は多いと思いますが。私はあえてしていないです。読破するには結構時間かかります。試験範囲の確認やキーワードの意味調べだけに参考させていただきました。
    
# 結果
* 無事に受かりました。

# 受けてみた感想
* 過去問と比べ、とにかく一問につき文章が長いです。長い文章から有効な情報をピックアップする必要があります。
* とにかく時間は足りないです。パッと見て、解き方に思いつかない問題は飛ばし、最後に解いたほうがいいと思いました。
* 丸暗記は禁物。式の意味やそれぞれの検定の方法の意味を理解する必要があります。

# その他
* お世話になったサイトの紹介
    * [知識0から統計検定2級取得を目指した話](https://qiita.com/akiyoshi_sasaki/items/8e4d7895f2647e22b5f9)
        * 記事の書き方（流れ）を参考させていただきました。
* 最後まで読み込んでいただき、ありがとうございます。皆さんも無事に受かるようにお祈りします。
一緒に頑張りましょう！
React、Next.jsなぜページ遷移にはaタグではなく、Linkを使うのか

***next.jsではなぜaタグではなくLinkを使うのかを先輩エンジニアに教えてもらったので備忘録***
---

結論から言うと、

- ***ページの読み込みを早くするため***
- ***reactの状態変化を維持したままページ遷移を行うため***
 
説明すると、
***aタグはサーバーから別のページを取得する***リンク
***Linkタグは同一ページ内で見た目だけ変更***するリンク出そう。

Linkタグで同一ページ内で一部分だけ変更する場合、
サーバーとの通信が省略されるのでページの読み込みが格段に早くなる。

そして、ページが更新されてしまった場合reactの状態（state）がリセットされてしまうけど、
Linkタグで同一ページ内で一部分だけ変更する場合、状態（state）が維持されたまま次のページに移動できる。

と言うことみたいです。
Dockerfileを使用したJenkinsのインストール

今回はDockerfileを作成してJenkinsを起動してみたいと思います。
Dockerfileとは独自のDockerイメージを作成する事が可能となるファイルです。
1つのDockerfileを用意することで、複数のサーバーに同様の設定を行うことが可能なので、互換性等に悩まされることがなくなります。

#Dockerfile作成
まずは、Dockerfileを格納するディレクトリを作成します。
作成しましたら、Dockerfileの作成を行います。

```
mkdir <ディレクトリ名>
cd <ディレクトリ名>
vi Dockerfile
```

Dockerfileの中身を以下の通りに作成します。

```
# ベースイメージ
FROM jenkins:<タグ>
# インストールしたいプラグインを指定したい場合
USER root
COPY plugins.txt /usr/share/jenkins/plugins.txt
RUN /usr/local/bin/plugins.sh /usr/share/jenkins/plugins.txt
USER jenkins
```

プラグインを指定する場合の`plugins.txt`ファイルは、`<プラグイン名>:<バージョン>`という形式で記載します。

#Dockerfileのビルドと起動
Dockerfileの作成が完了しましたら、ビルドを実行します。
`Successfully built`と表示されれば完了です。

```
docker build -t <任意のイメージ名> .
```

ビルド完了後、以下のコマンドを実行します。

```
docker run -p 8080:8080 -p 50000:50000 -v <設定保存先パス>/jenkins_home:/var/jenkins_home -d <ビルド時に指定したイメージ名>
```

上記コマンド実行後、しばらくしてから`http://<サーバーIP>:8080`にアクセス出来れば完了です。
なお、私の環境の場合、どうやっても何故かディレクトリのマウントがうまくいかない(マウント対象ディレクトリのオーナーを正しく変更しているのにPermission deniedで弾かれたりエラーが大量発生したり...)ので、もし対処方法が見つかればいずれ共有しようと思います。
2021年5月版 GCP入門 ～登録編～ 

#0. 目次
前座はいいよって方は登録だけ見てください
[1. 挨拶](#1-挨拶)
[2. そもそも何それ](#2-そもそも何それ)
[3. 登録](#3-登録)
[4. 次回予定](#4-次回予定)

#1. 挨拶
はじめましての方ははじめまして。けこです。
今回はGCPをやらず嫌いしていた私が重い腰を上げてGCPを触り得た知見を皆様に共有したいと思います。

####1.1. 対象読者
- GCPをやらないとなーとは思ってるけど触れるようになりたい人
- GCPがちんぷんかんぷんで猫の手も借りたい人

できる限り簡単に、画像も交えて解説していきます。

#2. そもそも何それ
GCPはGoogleの提供するクラウドサービスです。類似サービスとしてはAWSやAzureが有名です。
クラウドサービス全般に言えることですが使ったぶんだけ課金が発生します。逆に使わなければ課金は発生しません。
危険かどうかは人によります。ずぼらな人は危険です。

・向いてる人
- 簡単にサービスを始めたい。VMを触りたい人
- ドメインやネットワーク、バックエンド関連も全部Googleにおまかせしたい人
- 自分は几帳面な自信がある人
マメな人なら知らないうちに課金されていた…！なんてことも起こりにくいです。

・向いてない人
- トイレの電気が点けっぱの人
- 汚部屋の人
- 興味がない人
残念ながらずぼらな人は向いてません。諦めましょう。

GCPではVMを始め、Google Map関連API, 機械学習API等魅力的なサービスが多く展開されています。
AWSやAzureに詳しくないので比較はしません。その辺りは他の方の記事を御覧ください。
ちなみに私はGoogle Maps API目的でGCPをはじめました。
お前のせいでめっちゃ請求きたんやけどってなっても責任は取れません。

#3. 登録
登録といってもGCPとググって必要情報を入力するだけです。URLはこちら（https://cloud.google.com/）
必要情報は
- Googleアカウント
- 電話番号
- クレジットカード
です。
こんな画面が出てくると思います。無料で開始を押しましょう。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123137/b29890d7-7df3-d1c2-17a3-9f466ed8faf3.png)

次は電話番号をよこせと言われます。画像右にチラリと書いていますが、我々が有料版にしない限り課金されることはありません。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123137/cc681451-5f76-3cf6-ddee-a6e11b3c91a9.png)

最後にクレジットカード情報を入力すれば登録完了です。簡単ですね。個人の方はちゃんとアカウントの種類を変えておきましょう。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123137/1e6e7a19-824e-a844-02a5-3304e8102a2b.png)

#4. 次回予定
次はGCPの基礎、プロジェクトについて説明します。
https://qiita.com/kekouhei/items/c208d6a2e89425c2bda5
最後まで見ていただきありがとうございました。
【JavaScript】filterメソッドについて超簡略化して整理してみた

#はじめに
Vue.jsを使ったアプリケーションを作成していると、
filterメソッドを利用する場面に遭遇しました。

今回はそこで学んだことを自身の備忘録も兼ねて簡単に整理しておきます。

#filterメソッドとは
filterメソッドは、JavaScriptの配列に用意されているメソッドです。
既存の配列から条件に合致した要素だけを抽出して新しい配列を作成するために使用します。

#filterメソッドの使い方

アロー関数を用いた基本形は以下の通りです。

```
絞り込み対象の配列.filter( 引数 => 条件式 );

// 条件式がtrueであればデータは残され、falseの場合は除去される
```

実際に6以上の値のみを抽出するfilterメソッドを書いてみました。

```js:
var dataList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

var result = dataList.filter(data => data >= 6);

console.log(result);

// 出力結果
// [6, 7, 8, 9, 10]
```

今回の記事は本質的な部分を削ぎ落とし、超簡略化した内容になっています。
filterメソッドは3つの引数を受け取ることができ...というように
まだまだ整理すべきことはあるのですが、それはまた別の機会に譲ります。

#参考資料
[MDN Web Docs Array.prototype.filter()」](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/filter)
[書籍「たった1日で基本が身に付く！Vue.js超入門」](https://www.amazon.co.jp/たった1日で基本が身に付く！-Vue-js-超入門-石亀-広大-ebook/dp/B089LDYFV1)
AngularでDrag&Dropの実装

記載日：2021/5/9
AngularでのDrag＆Dropの実装について、忘れないように記載します。

## 目的
　AngularでDrag＆Dropを実装する。

## 環境
　Angular：11.2.13
　Angular CLI：11.2.12
　Node js：10.19.0
　OS：Ubuntu

## 目次
　１．シンプルなDrag＆Drop
　２．入替の起こるDrag＆Drop

## 作業
### １．シンプルなDrag＆Drop
※スマホ非対応
・Drag＆Dropしたいエレメントに対して、draggableプロパティを有効化。（html）
　　`draggable="true"`
・Drag＆Dropしたいエレメントに対して、dragstartやdragendなどの使いたいdragdropイベントを記載。（html）
・上記dragdropイベントで発火するメソッドを記載。（typescript）

[ソースコードはこちら](https://github.com/middle-aged-rookie-programmer/angular-trying/tree/master/src/app/dragdrop/firststep)
[動きの確認はこちら](
https://middle-aged-rookie-programmer.github.io/angular-trying/)

### ２．入替の起こるDrag＆Drop
※スマホ非対応
「１．シンプルなDrag＆Drop」に、以下を追加。
・Drag＆Dropしたいエレメントの操作性を高めるために、styleに`display: block;`を記載。（html）
・入替を起こすために、
　　dragstartメソッドで、ドラッグしたエレメント情報を取得。
　　dropメソッドで、ドロップエリアのエレメント情報を取得。その後、２つのエレメント情報をもとに、配列の入替を実施。

[ソースコードはこちら](https://github.com/middle-aged-rookie-programmer/angular-trying/tree/master/src/app/dragdrop/secondstep)
[動きの確認はこちら](https://middle-aged-rookie-programmer.github.io/angular-trying/)

## 参考にさせて頂いたサイト
https://developer.mozilla.org/ja/docs/Web/API/HTML_Drag_and_Drop_API/Drag_operations
https://developer.mozilla.org/ja/docs/Web/API/HTML_Drag_and_Drop_API
【AWS】通信プロトコルについて

#プログラミング勉強日記
2021年5月9日

#通信のルール
　インターネット通信のときにメールやWebアクセスなど目的によって通信方法が変わる。

　例えば、メールの設定をするときにはPOPとSMTPにIPアドレスのような設定をすることがある。(送信メールサーバーがSMTPサーバーで、受信メールサーバーがPOP・IMAPサーバー)　SMTPはSimple Mail Transfer Protocolでメールの送信プロトコル。POPはPost Office Protocolでメール受信のプロトコル。このようにメールの送受信するときにはWebとは違うプロトコルを使っている。このプロトコルでの送受信をするためのサーバーのIPアドレスをメーラーに設定している。

　HTTP(Hyper Text Transfer Protocol)はHTML(Hyper Text Markup Language)で書かれた文書などの情報をやりとりするときに使われるプロトコル。

#OSI参照モデル
　OSI参照モデルは通信プロトコルを性質や送信対象に応じて7つの層に分けている規約。


| 層 | 名称 | 規格（プロトコル） | 概要 | 利用例 |
|:--:|:--:|:--:|:---:|:--:|:--:|
| 7層 | アプリケーション層 | HTTP,FTP,DNS,SMTP,POPなど | 個々のアプリケーション | www,メール |
| 6層 | プレゼンテーション層 | SMTP,FTP,Telnetなど | データの表現形式 | HTML |
| 5層 | セッション層 | TLS,NetBIOSなど | 通信手段 | HTTPS | 
| 4層 | トランスポート層 | TCP,UDP,NetWare/IPなど | エンド間の通信制御 | TCP,UDP |
| 3層 | ネットワーク層 | IP,ARP,RARP,ICMPなど | データを送る相手を決め最適な経路で送信 | IP |
| 2層 | データリンク層 | PPP,Ethernetなど | 隣接する機器同士の通信を実現 | Ethernet |
| 1層 | 物理層 | RS-232,UTP,無線 | 物理的な接続、電気信号 | UTPケーブル,光ファイバーケーブル |

##アプリケーション層
　Webアプリケーションなどの通信サービスの通信方法を規定する。アプリケーション層はOutlookやChromeのようなアプリケーションを実行するときの通信を実施するもの。Webアプリケーションの通信サービスが実現できるように固有の規定を定義している。この中でアプリケーションごとにプロトコルが細分化されている。(メールソフトウェア用プロトコルはPOP/SMTP, Webブラウザ用プロトコルはHTTP/HTTPSなど)

##プレゼンテーション層
　文字を送受信するときに文字コードや暗号などを規定する。要するに、文字の送り方を決めている。送信側と受信側で形式が異なっても世界中でWebサイトが表示されるのはプレゼンテーション層があるため。

##セッション層
　セッション(アプリケーション間での一連の通信処理の継続)の仕方を規定する。

##トランスポート層
　最初にWebサイトにアクセスの通信を許可する(セッションを開始するときの信頼確立)や、到着順序や確認などを実施する。

##ネットワーク層
　IPアドレスを利用したルーティング方法を規定する。

##データリング層
　MACアドレスによるノード間の通信方法を規定する。

#物理層
　ビット単位によるコンピュータ間の物理的なデータのやりとりを規定する。
Docker環境でmysqlを二つ立ち上げる方法 

テスト環境と本番環境でDBを分けたいときがあります
そんな時にDockerでDBを二つ立ち上げる方法について記載します

## Docker file
まずは結論

```
version: "3.8"

services:
    app:
        build: ./your/app/dockerfile
        depends_on:
            - mysql
            - test_mysql
        command: execute command
        ports:
            - '8000:8000'
            - '8080:8080'
    mysql:
        build: ./your/mysql/image/path
        environment:
            MYSQL_DATABASE: your_db
            MYSQL_USER: user
            MYSQL_PASSWORD: password
            MYSQL_ROOT_PASSWORD: password
        ports:
            - "3306:3306"
            - "33060:33060"
        volumes:
            - mysql-data:/var/lib/mysql:cached
    phpmyadmin:
        image: phpmyadmin/phpmyadmin
        environment:
            - PMA_ARBITRARY=1
            - PMA_HOST=mysql
            - PMA_USER=user
            - PMA_PASSWORD=password
        depends_on:
            - mysql
        links:
            - mysql
        ports:
            - 8090:80
        volumes:
            - /sessions
            - ./tools/phpMyAdmin/php.ini:/usr/local/etc/php/php.ini
    test_mysql:
        build: ./your/test/mysql/image/path
        environment:
            MYSQL_DATABASE: your_test_db
            MYSQL_USER: user
            MYSQL_PASSWORD: password
            MYSQL_ROOT_PASSWORD: password
        ports:
            - "3307:3306"
        volumes:
            - test-mysql-data:/var/lib/mysql:cached
    test_phpmyadmin:
        image: phpmyadmin/phpmyadmin
        environment:
            - PMA_ARBITRARY=1
            - PMA_HOST=test_mysql
            - PMA_USER=user
            - PMA_PASSWORD=password
        depends_on:
            - test_mysql
        links:
            - test_mysql
        ports:
            - 8091:80
        volumes:
            - /sessions
            - ./tools/phpMyAdmin/php.ini:/usr/local/etc/php/php.ini
volumes:
    mysql-data:
    test-mysql-data:
```

### 実行方法
#### 注意点
すでにある環境が立ち上げ済みで、dockerファイルを追記していたら、以下のコマンドで、既存のDBデータをすべて消して再度イメージをビルドしなおさないと私の環境ではエラーになりました

**絶対に本番環境ではやらないでください。**データがすべて消えます


```
//イメージとデータの削除
docker-compose down --rmi all --volumes
//ビルド
docker-compose build --no-cache
//コンテナ立ち上げ
docker-composer up
```

本番環境：http://localhost:8090/
テスト環境：http://localhost:8091/
で二つphpMyAdminが立ち上がっていると思います
質問や間違いがあればコメントからお願いします！

##　宣伝
ツイッターもやってます
技術や製品開発に関する事などを呟いてますので、フォローお願いします
https://twitter.com/wkyIghw8MlLpyJE
【VMware】ゲストOSからホストOSへpingが通らないときの対処法

# ゲストOS→ホストOSにpingが通らない
## 環境
* ホストOS：windows10, IPアドレス：192.168.3.6
* ゲストOS：VMware Workstation 16 PlayerでCentOS7の仮想サーバ, IPアドレス：192.168.3.100

## 問題
ホストOS→ゲストOSへのpingは通るが、ゲストOS→ホストOSへのpingが通らない

## 原因
ホストOS側のファイアウォール(FW)

##対処法  
【１】コントロールパネル → システムとセキュリティ → WindowsDefender ファイアウォール → 詳細設定 → 受信の規則 →「仮想マシンの監視（エコー要求ICMpv４受信）」を有効化<br>（下図のようになっていればOK）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/748917/6de7a36b-4c39-2756-d2d3-18d8afa098e9.png)

【２】
①コントロールパネル → システムとセキュリティ → WindowsDefender ファイアウォール →WindowsDefender ファイアウォールの有効化または無効化 → 許可されたアプリの一覧にあるアプリも含め、すべての着信接続をブロックするのチェックを外す<br>（下図のようになっていればOK）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/748917/8eec4e06-a73a-a6a5-016f-bb9a9c66ba62.png)

②コントロールパネル → システムとセキュリティ → WindowsDefender ファイアウォール → WindowsDefender ファイアウォールを介したアプリまたは機能を許可 → VMware Authd Service(プライベート)のプライベートにチェックがある<br>（下図のようになっていればOK）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/748917/28a0576a-88c9-ed9c-1bc8-55af488989f0.png)
Variable is not assignable (missing __block type specifier)　ブロック構文内での自動変数編集時のエラー

# エラー内容
<!-- 発端や概要を記載 -->
Objective-Cにおいて、ブロック構文内で参照する自動変数を編集しようとすると、以下のエラーが出る。
・Variable is not assignable (missing __block type specifier)

<!-- 各チャプター -->
# エラーの出るコード
```Objective-C
//自動変数
int value = 0;
//ブロックの記述
int(^getDouble)(int)=^(int a){
    //Variable is not assignable (missing __block type specifier)が発生
    value += a*2;
    return value;
};
```

# 解消方法
<!-- タイトルとアンカー名を編集 -->
自動変数にブロック指定子(__block)をつける。

# 修正コード
```Objective-C
//自動変数
__block int value = 0;
//ブロックの記述
int(^getDouble)(int)=^(int a){
    //エラーが解消
    value += a*2;
    return value;
};
```


# 参考文献
- [Block構文での自動変数アクセス](http://soho-college.com/ioschool/block%E6%A7%8B%E6%96%87%E3%81%A7%E3%81%AE%E8%87%AA%E5%8B%95%E5%A4%89%E6%95%B0%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9/)
初学者向けエラーとの戦い方

#はじめに

ここ最近、何度もエラーと遭遇するうちにエラーとの向き合い方が非常に良くなってきたなと感じることが多くなってきました。エラーとの向き合い方を改めて自分の中で整理したくこの記事をまとめました。

# エラーとの向き合い方（気持ち面）
エラーがでたとき、皆さんはどう思いますか？
「げっ、エラーだ」、「は〜まじか」、そんなふうに声が出てしまうかもしれません。
私も学生時代に始めてプログラミングを学んだときは、発狂しそうな場面に何度も遭遇しました。(笑)でも、社会人になって、転職目的でまた勉強しはじめてわかったことがあります。
それは、、、、、
<br>
**「エラーは失敗する方法が判明した成功」であるということです。**

まず大前提にエラーは実はとてもありがたい存在であることを認識すべきです。もしエラーなき不具合があったとして、気付けずにリリースすれば、お客様に損害を与えてしまうことだってありえます。エラーが発生することは、そうしたさらなる事故を防ぐという超ありがたい存在なのです。

とはいえ、初学者さんでリリースを想定してアプリを作られる方はあまりいないかと思います。なのでなかなか想像しづらいですよね、、（私もそうです）。でも、エラーって初学者の方が成長するための、とても優秀な教材なんです！！！！


エラーが発生したら、まずその原因を調べますよね？その過程で、今まで書いた文法が正しいかどうか再復習できますし、自分のエラーパターンを把握することができますし、もしかしするとエラーによって新しい知識を得ることができるかもしれません。

結局のところ、エラーは実は敵ではない！って言うことなんです！

でもいくら敵ではなくともエラーは解消したい、そんな気持ちはきっとあるはず。
そこに関しては次の章で解説します。

#エラーの倒し方（気持ち＋技術編）

###気持ち編
エラーを倒すにあたって、絶対に必要なマインドがあります。それは、、、、
**「俺なら絶対にできる」と考えることです!!!**

うさんくせ〜〜〜〜と思うかもしれません。でも、恐ろしいまでにこの気持ちの有無で結果は大きく変わるのです。私の場合、よくぶつぶつと「できる、絶対できる、どうだ！（エンターポチっ、エラー）」を繰り返し作業すると、だいたいエラーを倒せます。

なぜこの気持ちを持つとエラーを倒せるのか、それはナチュラルに「できるはずのことができない」と脳が錯覚し、「ということは、できるまでやるか」となるからです。最初からできないと思うと、脳が効率を求めて「できないならやっても無駄！」と考え、結局挫折するか、サボってしまいます。
けれど、**「できるはず」と錯覚した脳は、できるまであらゆる仮説を立てて、実行に移そうとします。**

ちなみに科学的根拠は全然知りませんが、効果は抜群です（笑）

###技術編

技術については、私もプロではないゆえ、偉そうなことは言えませんが私なりの考えをまとめていきます

まず、エラー原因は**全てログの中に答えがある**ということです。
これはおそらく真理だと思います（笑）絶対にログをみれば答えは書いてあるはずです。（あるいはまんま、画面にエラーがでているかもしれませんが）

わかりませんと言う前にログを見て、怪しい部分をググって、情報を追っていくだけで、8割のことはわかります。もちろん、残りの2割のどうしても分からない部分は、プロのエンジニアに聞くなり頼ってもいいかもしれませんね。でも、まずはログを見て、情報を集めて、なんとなくあたりをつける、、、とやっていくだけでだいぶ違うかな〜と思います。

ちなみに、分からないままずーーと作業するのも効率悪いので、完全に手が止まって15分したら、誰かに聞くといいかもしれません！

#おわりに
初心者が偉そうにエラーについて語りました。ただ上記のことを実践した結果、プロエンジニアの方にも自走力が高いですねとお褒めの言葉も頂けたりしたので、決して間違ってはいないかな〜なんて思います！
是非試してみてください

**皆さんのエラー向き合い論もぜひ知りたいのでどしどしコメントください！！！！**