OmniAICreator/Qiita-1.07M huggingface dataset:
【Flutter】GestureDetectorで、「子Widget&背面のWidget」へのイベント伝播の設定

# はじめに

GestureDetectorは、あるWidgetにおけるユーザーの画面操作(タップ、スワイプなど)を検知するWidgetです。
GestureDetectorで検知したいWidgetは、コーディング方法が2種類あります。

```dart:(1)GestureDetectorのchildプロパティに設定する
GestureDetector(
  child: WidgetXXX(),
);
```

```dart:(2)Stackを使って、GestureDetectorを重ねる
Stack(children: [
  WidgetXXX(),
  GestureDetector(),
]);
```

さて、以上のようにした場合、WidgetXXX()がElevatedButton()である時を考えます。
(有り得ないケースですが、説明のためにそうします。)

GestureDetectorのonTapプロパティでタップを検知するようにした、としましょう。
この時、ElevatedButtonをタップすると、どのような挙動になるでしょうか？

- GestureDetectorのみ反応して、ElevatedButtonは反応しない？
- GestureDetectorは反応せず、ElevatedButtonのみ反応する？
- GestureDetector, ElevatedButtonどちらも反応する？

この際の挙動を規定するのが、**behaviorプロパティ**です。

### 注意

以降、ソースコードに記載されている英語が登場します。
併せて、日本語訳を載せていますが、分かりやすいよう意訳しています。
もし間違っていたら指摘ください。

# behaviorプロパティ

> How this gesture detector should behave during hit testing.

ユーザーが画面に対して何らかの操作(タップ, スワイプなど)をした際に、
このGestureDetectorがどのように動作するか？を規定します。

### 設定値の種類

behaviorプロパティには、**enum HitTestBehavior**を設定します。
以降では、このenum型のメンバ＆その挙動を示します。

#### deferToChild

> Targets that defer to their children receive events within their bounds only if one of their children is hit by the hit test.

子Widgetに委ねるターゲットは、子Widgetのいずれかがヒットテストでヒットした場合のみ、その境界内でイベントを受け取ります。
<font color="DarkGray">上手く訳せませんでした。。良い和訳を教えて下さい。。</font>

##### (1)の場合

- GestureDetectorは反応しません。
- ElevatedButtonは反応します。

##### (2)の場合

- GestureDetectorは反応しません。
- ElevatedButtonは反応します。

#### opaque

> Opaque targets can be hit by hit tests, causing them to both receive events within their bounds and prevent targets visually behind them from also receiving events. 

不透明なターゲットは、ヒットテストによって、その境界内でイベントを受信し、その背後にあるターゲットがイベントを受信するのを視覚的に防止することができます。
<font color="DarkGray">上手く訳せませんでした。。良い和訳を教えて下さい。。</font>

##### (1)の場合

- GestureDetectorは反応しません。
- ElevatedButtonは反応します。

##### (2)の場合

- GestureDetectorは反応します。
- ElevatedButtonは反応しません。

#### translucent

> Translucent targets both receive events within their bounds and permit targets visually behind them to also receive events.

半透明のターゲットは、その境界内でイベントを受信し、視覚的にその背後にあるターゲットもイベントを受信することを許可します。
<font color="DarkGray">上手く訳せませんでした。。良い和訳を教えて下さい。。</font>

##### (1)の場合

- GestureDetectorは反応しません。
- ElevatedButtonは反応します。

##### (2)の場合

- GestureDetectorは反応します。
- ElevatedButtonは反応しません。

### デフォルト値

> This defaults to [HitTestBehavior.deferToChild] if [child] is not null and [HitTestBehavior.translucent] if child is null.

- childがnullでない場合、HitTestBehavior.deferToChild
- childがnullの場合、HitTestBehavior.translucent


# おわりに

うまく和訳できない英文ばかりでしたが、各設定値での挙動は分かったので、意義はあったと思ってます。
誰かのお役に立てれば幸いです。
では。
webview_flutterでページが表示されないときに確認すること


<br/>
まず前提としてエラーは出ていないけどなぜかページは表示されないという状態を想定しています。
# 解決方法

解決方法はシンプルです。
WebViewにjavascriptModeをしっかり指定することです。

``` Dart
class MyWebView extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return Expanded(child: 
    WebView(
      initialUrl:'https://example.com',
      javascriptMode: JavascriptMode.unrestricted,
    )
    );
  }
}
```
【RSpec】ActiveRecordを継承しないクラスでFactoryBotを作成したい

##initialize_with
Rubyの任意のクラスでFactoryBotを作成したいときは```initialize_with```を使う。

```ruby
# user_info.rb
class UserInfo
  attr_accessor :hoge

  def initialize(hoge)
    @hoge = hoge
  end
end

# factories.rb
factory :user_info do
  hoge { Fuga.new }

  initialize_with { new(hoge) }
end

build(:user_info).hoge #Fugaクラスのインスタンスが返る
```

####注意
**create(:user_info)**すると下記のエラーが出る。

```
NoMethodError:
  undefined method save!
```

##参考

https://github.com/thoughtbot/factory_bot/blob/main/GETTING_STARTED.md
Visual Studio プロジェクトの削除を邪魔するやつを一発で殺す

Visual Studio 2019でも2022でもプロジェクトを一回開くと何分か削除できなくて毎回ブロックしてるプロセス探すのが面倒だったんで、バッチファイル起動するだけで握ってるプロセスを殺すやつを作ったので備忘録。

# バッチファイル
テキストファイル作って以下のコードを貼り付けて拡張子 `bat` または `cmd` で保存

```bat
@echo off
for /f "usebackq" %%S in (`tasklist ^| find "PerfWatson2.exe" /c`) do set COUNT=%%S
for /l %%I in (1,1,%COUNT%) do ( taskkill /f /im "PerfWatson2.exe" /t )

for /f "usebackq" %%S in (`tasklist ^| find "copilot-agent-win.exe" /c`) do set COUNT=%%S
for /l %%I in (1,1,%COUNT%) do ( taskkill /f /im "copilot-agent-win.exe" /t )

echo Execution is complete.
timeout /t 1 /nobreak >nul
```

#解説
VSプロジェクトの削除をブロックしているプロセス（実行ファイル名）は `PerfWatson2.exe` なので、これを追いやれば削除はできるようになる。
開いて閉じてを繰り返すとその分だけ生まれるので、その数だけ実行すればいい


|行|説明|
|-|-|
|1|実行時にコマンドを表示させなくする|
|2|起動中のタスクから `PerfWatson2.exe` を探して起動している数をCOUNTに入れる|
|3|COUNTの数だけプロセスを殺すコマンドを実行する|
|4|実行が完了したと使用者に伝える（ただの文字出力なのでなくてもいい）|
|5|1秒だけ待機 （なくてもいい）|
ECSのawsvpcモードでPORTSが入らない

# ECSのネットワークモードについて
ECS(on EC2)のネットワークモードはhost,bridge,awsvpcの3種類がある。

コンテナのネットワークモードをawsvpcにすることによってホスト跨ぎの通信ができ、またセキュリティグループの設定も可能なので推奨方法。

# awsvpcモードを使おうとした
使おうとしたが、はまった
症状としては、
・EC2からタスク定義で指定したポートからアクセスできない
・EC2からdocker psで確認すると、PORTSにポート番号が入っていない

```
[ec2-user@ip-10-0-0-76 ~]$ docker ps
CONTAINER ID   IMAGE
        COMMAND                  CREATED          STATUS
PORTS     NAMES
63fde9618005   731221110857.dkr.ecr.ap-northeast-1.amazonaws.com/prod-ecr:1eeb0d9   "/bin/sh -c 'cd /usr…"   5 minutes ago    Up 5 minutes
          ecs-prod-a-task-9-prod-a-task-98e39bb29694b6e32400
7b7735d14db3   amazon/amazon-ecs-pause:0.1.0
        "/pause"                 6 minutes ago    Up 6 minutes
          ecs-prod-a-task-9-internalecspause-9a9da0c7ee828e8fe901
c3013cbeedce   amazon/amazon-ecs-agent:latest
        "/agent"                 17 minutes ago   Up 17 minutes (healthy) 
```

# 解決方法
1. タスク定義を作成する。ポートはコンテナのポートのみ指定(することしかできない)
2. LBを作成し、ターゲットグループを空にしておく(作成したリスナー・ターゲットグループは使わないが、無いと先に進めないので作成する)
3. 作成したリスナーとターゲットグループを削除する
4. ECSにてサービスを作成し、その中でリスナーとターゲットグループを新規作成する。こうすることで2で作成したLBに新規にリスナーとターゲットグループが紐づき、ターゲットグループにコンテナ(のENI)が紐づけされる

# ポート周りの設定について
LBに80で受けてコンテナの8000ポートに飛ばす場合

|対象  |ポート |設定タイミング  |
|---|---|---|
|Dockerfile|8000 | 環境変数等でセット |
|タスク定義|8000 | タスク定義作成時 |
|EC2のセキュリティグループ |解放しない |-  |
|コンテナのセキュリティグループ  |8000  |サービス作成時など  |
|ALBのセキュリティグループ  |80  |ALB作成時など  |
|コンテナのターゲットグループの登録ポート  |8000  |サービス作成時※  |
|ALBのリスナー  |80  |サービス作成時※  |

※リスナーとターゲットグループはALB作成時にも無いと先に進めないが、最終的にサービス内で作成したものを使う。
80番ポートをALBの受け側に使いたい場合、ALB作成時に作った80番ポートのリスナーをサービス作成前に削除する必要がある。

下記はサービス内でのLB関係ポートの設定部分

～コンテナのターゲットグループの登録ポート～
![スクリーンショット 2022-01-18 202528.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246479/ff4cb97f-1d79-1ebb-3c31-f66bc56f0e8f.png)


～ALBのリスナー～
![スクリーンショット 2022-01-18 202613.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246479/e6627dcc-58d9-3100-b55f-526310f18f06.png)



# 補足
awsvpcモードは推奨されている割にまとまった手順の情報が少なく、かなりはまったので。
なお、サービスが正常に起動してもPORTSにはポート情報は入らない。
これはawsvpcモードではコンテナはEC2とは独立したENIのポートを使っているため。

# 参考

https://www.titanwolf.org/Network/q/6e3c2c2b-eadb-44cd-8d7a-f6ac82e1daca/y
[Stripe Updates] Stripeで発行する請求書・領収書などのPDFで、ロゴやブランドカラーの設定ができるようになりました

StripeのInvoicingやBillingなどで送付・ダウンロードできる請求・領収書PDFファイルに、ブランドカラーやロゴ画像の設定ができるようになりました。

https://twitter.com/stripe/status/1468988906137952260

https://note.com/iwasakiyoshiteru/n/na4770474d528

# ロゴ画像・ブランドカラーの設定方法

PDFに表示するロゴ画像・ブランドカラーは、CheckoutやPayment Linksなどに設定しているものと同じものが表示されます。

ダッシュボードの、[設定 > ブランディング](https://dashboard.stripe.com/settings/branding)から、「ロゴ」と「ブランドカラー」を設定しましょう。

![スクリーンショット 0004-01-18 20.06.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/b0edc309-afc4-4fd9-fb35-4dc6c4ce564b.png)

カラーの設定は、RGBやカラーピッカーでの指定も可能です。

![スクリーンショット 0004-01-18 20.06.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/fb6d7506-fdac-70a2-4d02-375056e6381d.png)


# PDFの表示を確認する

「ロゴ」と「ブランドカラー」の設定が終われば、カスタマイズは完了です。

設定画面でもプレビューができますが、請求書作成画面や実際にテスト環境を利用して決済を行うことでも、表示を確認することができます。

![スクリーンショット 0004-01-18 20.09.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/487e1eb7-f51d-43ac-ba32-5f2d5bd79a02.png)

# 関連ドキュメント

https://stripe.com/docs/receipts

https://stripe.com/docs/payments/no-code

https://stripe.com/docs/invoicing/customize

# [PR] Stripe開発者向け情報をQiitaにて配信中！
2021年12月よりQiitaにて、Stripe開発者のためのブログ記事更新を開始しました。

- [Stripe Updates]：開発者向けStripeアップデート紹介・解説
- ユースケース別のStripe製品や実装サンプルの紹介
- Stripeと外部サービス・OSSとの連携方法やTipsの紹介
- 初心者向けのチュートリアル(予定)

など、Stripeを利用してオンラインビジネスを始める方法について随時更新してまいります。

-> [Stripe Organizationsをフォローして最新情報をQiitaで受け取る](https://qiita.com/organizations/stripe)
[AWS] S3+CloudFront に Deploy する buildspec(CodeBuild)


AWS で SPA などの静的コンテンツを公開する際、`S3` + `CloudFront` という構成がよくある形。

その構成でデプロイする場合、 `S3` にファイルを配置して `CloudFront` のキャッシュを削除する必要があるが、
`CodeDeploy` は `S3` へのデプロイに対応しておらず、
`CodePipeline` は `S3` へのファイル配置は可能であるものの `CloudFront` のキャッシュ削除が出来ない。
`CodeBuild` で実施するのがベターと考えた。

というわけで、そのための `buildspec` が以下。

## buildspec
```yaml:buildspec.yml
version: 0.2

phases:
  pre_build:
    commands:
      - echo "# Deoloyment Info"
      - echo "S3_BUCKET_NAME = ${S3_BUCKET_NAME}"
      - echo "CLOUDFRONT_ID  = ${CLOUDFRONT_ID}"
      - echo "CLOUDFONT_INVALIDATION_PATHS = ${CLOUDFONT_INVALIDATION_PATHS}"
  # build:
  #   commands:
  #     # - command
  post_build:
    commands:
      - echo "# Build completed on `date`"
      - ls -la
      - echo "# Update S3-Objects ..."
      - aws s3 sync ./ s3://${S3_BUCKET_NAME} --exact-timestamps
      - sleep 10
      - echo "# Invalidate CloudFront-Cache"
      - RESPONSE=`aws cloudfront create-invalidation --distribution-id "${CLOUDFRONT_ID}" --paths ${CLOUDFONT_INVALIDATION_PATHS}`
      - INVALIDATION_ID=`echo ${RESPONSE} | jq -r '.Invalidation.Id'`
      - echo "Invalidation.Id = ${INVALIDATION_ID}"
      - STATUS="";
        while [ "${STATUS,,}" != "completed" ]; do
          sleep 5;
          RESPONSE=`aws cloudfront get-invalidation --distribution-id "${CLOUDFRONT_ID}" --id "${INVALIDATION_ID}"`;
          STATUS=`echo ${RESPONSE} | jq -r '.Invalidation.Status'`;
          echo "status = ${STATUS}";
        done
      - echo "# Remove Old S3-Objects"
      - aws s3 sync ./ s3://${S3_BUCKET_NAME} --delete
```

### 処理概要
1. ファイルを `aws s3 sync` で S3 バケットにコピー。追加/更新のみ。
2. CloudFront の キャッシュを削除。
3. 不要になったファイルを `aws s3 sync --delete` で S3 バケットから削除。

### 前提
* S3 に配置するファイル群は CodeBuild 内のデフォルトディレクトリに存在する前提。  
  そうでない場合は `aws s3 sync` のコピー元を変更する。  

### CodeBuild 環境変数
* `S3_BUCKET_NAME`  ... ファイルのデプロイ先となる S3 バケット名。
* `CLOUDFRONT_ID`   ... AWSが自動生成する CloudFront ID。13文字くらいのランダム文字列。
* `CLOUDFONT_INVALIDATION_PATHS`  ... キャッシュ削除の対象とするパス。スペース区切りで複数指定可。

### CodeBuild の IAM-Role Policy

CodeBuild の IAM-Role に付与するポリシー。

```json:IAM-Policy
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "s3",
            "Effect": "Allow",
            "Resource": [
                "arn:aws:s3:::<BUCKET_NAME>",
                "arn:aws:s3:::<BUCKET_NAME>/*"
            ],
            "Action": [
                "s3:Get*",
                "s3:List*",
                "s3:PutObject",
                "s3:CopyObject",
                "s3:DeleteObject"
            ]
        },
        {
            "Sid": "cloudfront",
            "Effect": "Allow",
            "Resource": [
                "arn:aws:cloudfront::<ACCOUNT_ID>:distribution/<CLOUDFRONT_ID>"
            ],
            "Action": [
                "cloudfront:*Invalidation"
            ]
        }
    ]
}
```

S3に対するアクションはもう少し減らせる。
[AWSナレッジセンターのこちらの記事](https://aws.amazon.com/jp/premiumsupport/knowledge-center/s3-access-denied-listobjects-sync/) では `s3 sync` のためには、`ListObjectsV2` `CopyObject` `GetObject` `PutObject` が必要と書いているが、 `--delete` を使用する場合は `DeleteObject` も必要。
早くやってれば良かったと言う話

#気づくのが遅かった勉強法
去年からPaizaやProgate、ドットインストールでプログラミング（Python）を勉強し始めて、ただ何も考えずに進めていった。
#その結果どうなったか
知識は詰め込めたけど、アウトプットが出来ない。動画の通りに打つことは出来るが、オリジナルでは難しい。
##出来ると言えば
それで出来るようになったのは、簡単なコードだけ。（繰り返しや条件分岐）
それも、１文や２文だけ。

#今思うこと
学習しながら、アウトプットしていけば良かったと思う。

#現在の状況
PythonはPaizaの９.クラスまで進行。「Pythonで作るゲーム開発入門講座」と言う本に載っているサンプルコードをアレンジして、オリジナルのものを作っています。
Pythonで日本の新型コロナ患者情報取得

#環境
`Win10`
`Python 3.8.10`
・`requests==2.25.1`
・`pandas==1.3.1`

#実装
```py
import requests as rq
import pandas as pd

url = 'https://covid19-japan-web-api.vercel.app/api/v1/positives?prefecture={0}'

prefectures = ['北海道','青森県','岩手県','宮城県','秋田県','山形県','福島県','茨城県','栃木県','群馬県','埼玉県','千葉県','東京都','神奈川県','新潟県','富山県','石川県','福井県','山梨県','長野県','岐阜県','静岡県','愛知県','三重県','滋賀県','京都府','大阪府','兵庫県','奈良県','和歌山県','鳥取県','島根県','岡山県','広島県','山口県','徳島県','香川県','愛媛県','高知県','福岡県','佐賀県','長崎県','熊本県','大分県','宮崎県','鹿児島県','沖縄県']

out_dataframe = pd.DataFrame()
for p in prefectures:
    tmp_url = url.format(p)
    response  = rq.get(tmp_url)
    if response.status_code == 200:
        dataframe_body = pd.DataFrame(response.json())
        out_dataframe = out_dataframe.append(dataframe_body, ignore_index=True)
out_dataframe.to_csv('result.csv', mode='w', encoding='utf-8')
```

#参考
https://requests-docs-ja.readthedocs.io/en/latest/

https://utokyo-ipp.github.io/7/7-1.html
GTMの追加設定でJSの挙動に不具合が出たとき

### 前提条件
- すでにGTMを埋め込んでいる動作検証済みのサイト
- GTM計測管理画面に設定を追加した場合

### 挙動
- モーダルやスムーススクロールなどクリックで発火するJS関連が動かない

## 原因
クリックイベントIDを設定したソースコードを消したり、GTM自体を消して
問題切り分けをすると管理画面にてクリックイベントの追加設定時に
「タグの配信を待つ 2000ミリ秒」
にチェックが入っていたからでした。
（秒数は変更できます）

この設定をオフにしてみると問題なくクリックイベントも計測できJSの挙動も解決しました。

設定の本来の目的は
> オプションをオンにすると、このトリガーが設定されているすべてのタグの配信が完了するか、または指定したタイムアウト時間が経過するか、どちらか早い方が発生するまでフォームの送信を遅らせることができます。この設定をオフにすると、処理が遅いタグについては、フォームの送信によって次のページが読み込まれるまでに配信が間に合わない場合があります。
引用元: https://support.google.com/tagmanager/answer/7679217?hl=ja

とのことなので配信を遅らせないと計測できない場合のみ設定すると良い項目かと思います。

GTMの設定でサイト自体のJSに影響が出たのは今回が初めてでした。
無駄な計測数値を残さない配慮として本番設定の反映タイミングを公開直前に行うこともあるので、できるだけ本番設定と同じ状態でテスト検証する時間は確保しないとけないですね。
uuidgen コマンドをちょっとだけ便利にする

開発でユニークな識別子が必要な場面が時々あり、そのような場面で [Universally Unique Identifier - UUID](https://ja.wikipedia.org/wiki/UUID) を使うことが多いです。

## tl;dr

`uuidgen` に以下のような、エイリアスを設定して、UUID を簡単にペーストできるようにしてます。

```zsh
alias uuidgen='uuidgen | tr "[:upper:]" "[:lower:]" | tr -d "\n" >/dev/stderr | pbcopy'
```

## uuidgen コマンド

macOS には `uuidgen` というコマンドがあり、UUID が必要な場面で使っています。

```zsh
$ uuidgen
B2907FAD-2DCC-49AC-9178-8206876A6175
```

基本的にはこのように大文字の出力されるのですが、私個人は小文字での表記になれているので、小文字を使いたいところ。また、出力された文字列をいちいち選択してコピーするのも面倒。

## エイリアス設定

という訳で、以下のようなエイリアスを設定しています。

```zsh
alias uuidgen='uuidgen | tr "[:upper:]" "[:lower:]" | tr -d "\n" >/dev/stderr | pbcopy'
```

`uuidgen` した内容をパイプで渡しながら、小文字変換したり (`tr "[:upper:]" "[:lower:]"`)、末尾改行なくしたり (`tr -d "\n"`) して、クリップボードに格納します (`pbcopy`) 。

ちょっとだけ工夫したのは、結果を `stderr` にも出力するようにしているところ。

```zsh
alias uuidgen='uuidgen | tr "[:upper:]" "[:lower:]" | tr -d "\n" | pbcopy'
```

でもやりたいことは実現できるのですが、結果がターミナルに表示されなくなり、ペーストするまでどんな UUID が得られたのか分かりません。

なので、 `stderr` に出力することもよって結果もターミナル上で確認できるようにしています。

## 使い方

標準で用意されている `uuidgen` を上書きしているので、単に `uuidgen` と実行すれば良いだけです。

```zsh
$ uuidgen
2df3da7d-287b-4301-ad0f-b07607f01b4b
```

ちなみに私個人は `.zshrc` で

```zsh
setopt magic_equal_subst
```

を指定しているので、 `=uuidgen` で元の `uuidgen` を実行できるようにしています。

```zsh
$ =uuidgen
E34C966D-7BF1-4CBD-B989-C638302104F3
```

## 追記 2021.11.22

zsh / bash なら `tee` コマンドを使っても同様のことができるようです。

```zsh
alias uuidgen='uuidgen | tr "[:upper:]" "[:lower:]" | tr -d "\n" | tee >(pbcopy)'
```

`stderr` に余計な出力しないので、こちらの方がよいかもしれません。

参考 : [コマンドの結果を画面とパイプの両方に渡す方法](http://liosk.blog103.fc2.com/blog-entry-215.html)

## 追記

- macOS Monterey 12.0.1 で動作確認しました。
- linux では `pbcopy` コマンドありませんが、[似たようなことは可能みたいです](https://ostechnix.com/how-to-use-pbcopy-and-pbpaste-commands-on-linux/)。
- windows の場合、私ならおそらく [WSL](https://docs.microsoft.com/ja-jp/windows/wsl/install) 使います。
【Ruby】if,else　真偽値による条件を組み合わせて処理

※初心者向け
※アウトプット練習の為

開発環境
rails 6.0.4.4
ruby 2.6.5

##概要
指定された数値の範囲による条件と真偽値による条件を組み合わせて処理を行うプログラムを実装。

##問題内容
以下の要件を満たす in1to10メソッドを実装しましょう。

**・第一引数のnumが1以上かつ10以下の範囲であればTrueを出力すること**
**・第二引数のoutside_modeがTrueの場合は、第一引数numが条件範囲外でもTrueを出力すること**
**・それ以外はFalseを出力すること**

##雛形

```ruby
def in1to10(num, outside_mode)
  # ここに条件式を記述する
end

# 呼び出し例
in1to10(5,false)
in1to10(11,false) 
in1to10(11,true) 
```

**出力例**
in1to10(5,false) →True
in1to10(11,false) →False
in1to10(11,true) →True


**ヒント**
 **論理演算子**
論理演算子とは、式の「真（True）」と「偽（False）」の確認や演算を行う際に用いられる演算子（記号、符号）のことです。以下のように条件分岐を実装する際、条件式に複数の条件を組み合わせるために用いられます。

```ruby
if ( 【複数の条件が含まれる条件式】 )

end
```
複数の条件式を組み合わせた複雑な条件式を記述するために論理演算子**&&**と**||**を使います。

条件式aと条件式bを組み合わせる場合は以下のように記述します。

```ruby

# aもbもtrueの場合にtrue
a && b 

# aかbのどちらかがtrueの場合にtrue
a || b 
```

なおRubyの論理演算子では、左辺から右辺に条件式を評価します。もし式全体の評価が確定した場合は、その時点で残りの評価を行いません。

したがって、上の例で言えば、a **&&** bにおいてaがfalseの時点で全体がfalseと確定するため、bの判定は行いません。また、a **||** bでは、aがtrueの時点で全体がtrueと確定するため、bの判定は行いません。

##解答

```ruby
def in1to10(num, outside_mode)
  if (num >= 1 && num <= 10) || outside_mode
    puts "True"
  else
    puts "False"
  end
end

# 呼び出し例
in1to10(5,false)
in1to10(11,false)
in1to10(11,true)
```
##解説
2行目では、論理演算子&&と||を用いて条件式を記述しています。

(num >= 1 && num <= 10)|| outside_modeとは、
numが1以上かつnumが10以下、または、outside_modeがtrueの場合「True」と出力されます。それ以外であれば「False」と出力される条件です。

```ruby
def in1to10(num, outside_mode)
  if (num >= 1 && num <= 10) || outside_mode
    puts "True"
  else
    puts "False"
  end
end

in1to10(5,false)
in1to10(11,false)
in1to10(11,true)
```

問題文の出力例の条件で当てはめてみます。

```ruby
in1to10(5,false) →True
```

num=5により(num >= 1 && num <= 10)の条件に当てはまるので、この時点で出力結果が「True」となります。そのため、outside_modeがtrueまたはfalseのいずれかであっても、出力結果は変わりません。

```ruby
in1to10(11,false) →False
```

num=11により(num >= 1 && num <= 10)の条件には当てはまりません。また、outside_modeがfalseなので、出力結果は「False」となります。

```ruby
in1to10(11,true) →True
```
num=11により(num >= 1 && num <= 10)の条件には当てはまりません。しかし、第二引数のoutside_modeがtrueなので、出力結果は「True」となります。
指定した相関係数になるデータ行列の生成

以下の関数 gendat2 は，相関係数が r となる n × 2 行列を求める。

r = np.corrcoef(x.T)[0,1]


```python
import numpy as np
from scipy.linalg import eigvals, inv, svd, cholesky
from scipy import random
from scipy.stats import zscore

def gendat2(n, r):
  r = np.array([[1, r], [r, 1]])
  if any(eigvals(r) <= 0):
    raise Exception("'r' is not positive definite.")
  x = random.randn(n, size[0])
  x = zscore(x, ddof=1)
  r2 = np.corrcoef(x.T)
  solver2 = inv(r2)
  vec, val, junk = svd(r2, full_matrices=False)
  coeff = solver2 @ (np.sqrt(val) * vec)
  z = x @ coeff @ cholesky(r)
  return z
```




相関係数が 0.5 になる 10 × 2 データ行列


```python
x = gendat2(10, 0.5)
np.corrcoef(x.T)[0,1]

```




    0.4999999999999999



相関係数が 0.63 になる 1000 × 2 データ行列


```python
x = gendat2(1000, 0.63)
X = x[:, 0]
Y = x[:, 1]
coeff = np.corrcoef(X, Y)[0,1]
```
図に描いてみる。

```python
import matplotlib.pyplot as plt
plt.figure(figsize=(5,5))
plt.title("correlation coefficient = {0:.3f}".format(coeff))
plt.scatter(X, Y)
# plt.xlim([0, 1])
# plt.ylim([0, 1])
plt.grid()
plt.show()
```


    
![output_6_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1653782/4cec1a0b-0612-728d-b436-e2a5cedad927.png)
【Q&A】言語を極めるってどこまで？？



>・言語はツールであり、　(表現が変わっても原則は変わりません)
・適材適所で色々な言語を使いこなす
　（原則を理解　→→　　設計　→→上流へ移るのが必要）
・フレームワーク（変化はすごく速い
・インフラからOSやネットワーク等の理解

>→<b>結果として、、、『ビジネスやアウトプットの質や安定性にコミット』</b>

ことが出来るエンジニアの方が好ましいのは当然




##✖言語に固執したり、客観的な判断が出来ない
Javaが最適でないところにまでJavaを使おうとしたり
Java以外の言語を勉強することを拒否


組み込み系などのニッチなトコについては
尖がってずっとエンジニアとしていくのもあり



##★重要なことは「楽しむこと」
しっくりくる言語を見つけて、
それを極めるのが一番

いろいろな言語に手を出して
その言語の考え方を学んでおくとよいと思います。
家電手帳アプリで動く家電の非公式リスト

#はじめに
2022年になりました。今年もよろしくお願いします。
初売りで新たに家電を購入した方も多いと思います。
我が家でもアイリスオーヤマの電気圧力鍋KPC-MA4が導入され、充実した食生活となっています。
保育園に迎えに行く間に「ほったらかしにしておくとできている」というのが良い点だそうです。
さて、新たな家電を購入すると付いてくるのが取り扱い説明書。
もちろん、家電手帳アプリでデジタル管理できます。この電気圧力鍋も型番の部分を撮影するだけで簡単に登録できました。
また、iPhone用の家電手帳アプリは、IoT家電、スマート家電をスマホからリモコン操作することができます。
今回は、この家電手帳アプリで操作できたIoT家電の非公式リストを公開します。
私の周りにあるものなので、ほんの一部です。

#どんな機器が操作できるのか
・テレビ（レグザ、ソニー、パナソニック、シャープ）
・照明（ECHONET Lite対応、IKEAトロードフリ）
・エアコン（ECHONET Lite対応）
・扇風機（Dyson Link対応機器）
・ロボット掃除機（ルンバ、ブラーバの一部）
・空気清浄機（ECHONET Lite対応）
・電動ブラインド（IKEAフィルトゥール、カドリリ）
詳しくは<a href="https://inetcore.com/kadentecho/support_remoteControl/index.html">こちら</a>


#非公式リスト（2022年1月時点）
|種類|機器名|コメント|
|---|---|---|
|固定回線||フレッツ光などインターネットに接続できる回線|
|Wi-Fiルーター|NetGear RBR350|Wi-Fiルーターならなんでもいいですが、IoT機器の多くは、2.4GHzにしか対応していない機種があるので2.4/5GHz両方に対応しているものがいいです|
|テレビ|シャープ LC-50W30|LAN/Wi-Fiに対応しているテレビで、公式アプリがあるもの|
|エアコン|パナソニック CS-X407C2-W|無線アダプタCF-TA9が必要、公式アプリがあるもの|
|エアコン|パナソニック CS-J229C-W|無線アダプタCF-TA9が必要、公式アプリがあるもの|
|エアコン|<a href="https://panasonic.jp/aircon/p-db/CF-TA9.html">パナソニック 無線アダプタ CF-TA9</a>|上記エアコンごとに必要。Wi-Fi内蔵機種では不要|
|エアコン|<a href="https://panasonic.jp/aircon/p-db/CF-TC7B.html">パナソニック　　無線ゲートウェイ CF-TC7B</a>|CF-TA9を複数台接続可能|
|エアコン|ダイキン |Wi-Fi内蔵のものは簡単につながります|
|照明|<a href="https://www.ikea.com/jp/ja/p/tradfri-gateway-white-50337815/">IKEAトロードフリゲートウェイ</a>|はじめての方は、ゲートウェイとLED電球のセットがお勧め|
|照明|<a href="トロードフリ">IKEA LED電球（E26口金）</a>||
|照明|コイズミ|ECHONET Lite対応|
|扇風機|Dyson HP03|||
|扇風機|Dyson HP07|||
|ロボット掃除機|ルンバ e5||
|ロボット掃除機|ルンバ i3||
|空気清浄機|シャープ||
|電動ブラインド|<a href="https://www.ikea.com/jp/ja/p/fyrtur-block-out-roller-blind-wireless-battery-operated-grey-20408201/">IKEA フィルトゥール</a>|マンションなどの一般的なカーテンレールにつける場合は、TOSOカーテンレール取付金具が便利でした（ホームセンターで400円くらい）|

#おわり
今回ご紹介したような市販の家電を操作できるので、iPhoneのオートメーションアプリと一緒に使うと手作業だったルーティーンが自動化できます。例えば、21時になったら子供部屋の温度を暖かくするとか。照明を消すとか。メーカーの枠を超えて操作できます。
「何があれば使えるの？」とよく聞かれることが多いので、記事にしてみました。


※個人としての見解です。メーカー名や商品名は、各社の各国における商標または登録商標です。
Golden テストがCIで実行すると失敗する場合の対策法


Flutter で便利な　Goldenテスト、これをGitHub Actions等のCIで実行すると、失敗してしまうことがあります。
ローカルの環境では成功するのに何故、、、？と頭を悩ましました。

この問題の解決法について解説します。

##課題##

Goldenテストがローカルの環境では成功するが、
GitHub Actions等のCIで実行すると失敗してしまう。

##解決法##
Goldenを生成したOSとCIで実行するOSを揃える。

Goldenを生成したPCのOSがMac OSの最新版ならば、
CIの実行環境のOSもMac OSの最新版にする。

##解説##
CIの失敗はオペレーションシステムによって、生成されるGolden(スクリーンショット)が微妙に異なることが原因で発生します。
こちら、公式で言及されています。

>Golden tests may be executed locally on Linux, MacOS, and Windows platforms. All reference images can be found at Flutter Gold baselines. Some tests may have multiple golden masters for a given test, to account for rendering differences across platforms. The parameter set for each image is listed in each image digest to differentiate renderings.

引用元
https://github.com/flutter/flutter/wiki/Writing-a-golden-file-test-for-package:flutter#adding-a-new-golden-file-test

また、同じMacでもOSのバージョン違いで失敗する場合があるようです。

参考
https://github.com/flutter/flutter/issues/56383

なので、CIの設定ファイルにて、実行するOSを合わせることで、
同じGoldenが生成され、テストが無事成功します。

##まとめ##
Goldenテストがローカルの環境では成功するが、
GitHub Actions等のCIで実行すると失敗してしまう場合、
Goldenを生成したOSとCIで実行するOSを揃えることで、想定通りの実行結果となります。

GitHub Actionsで指定するOSはLinuxが多いと思うので、
多くの人がハマってしまうのではないでしょうか。

ぜひこの方法で対策してみてください。

##参考##

https://stackoverflow.com/questions/57876611/flutter-golden-tests-failing-on-ci
３次元で描写した図を動画で保存する


先日、[「なぜディープラーニングするのか？を自分なりに調べてみた件」](https://qiita.com/tan0ry0shiny/items/e0d4233de1e59c4d4c03)を投稿させて頂きましたが、初投稿のテストも兼ねていました。今回から少しずつ詳細に書いていければと思います。

#今回の目的
TensorFlowで学習したモデルを3次元空間に描写します。

#やった事
ANDゲートを単純パーセプトロンで実装しました。重みは自動微分で機械的に求められます。詳細は以下のColabのリンクからご覧下さい。

[Colab: ニューラルネットワークでANDゲートを解く.ipynb](https://colab.research.google.com/drive/1HyYvulakETtZgVWiibYoAICY8A6V2epX?usp=sharing)

モデルを作った後、0から1までの入力に対して出力を3次元空間にプロットしてみました。実際にプロットしてみたらマウスでグリグリ動かして良く見てみたくなったので、アニメーションを保存してみました。本当はColab上でマウスでグリグリしたかったのですが、出来ませんでした。ご存じの方がいらっしゃいましたら教えて頂けると嬉しいです！

https://twitter.com/Ry0355318773/status/1483330742746681344?s=20

#参考
今回はこちらの記事を参考に作成しました。
これはQiitaの記事に動画をアップする時に参考にさせて頂きました。

https://qiita.com/akameco/items/6ff78b0918e96f871f57

#感想
今回、初めて0から3次元空間にプロットしました。3次元の情報の理解に苦しんだりしましたが、その分理解が深まりました。今回の資料には載せていませんが、XORゲートの実装の際、ハマってしまいました。気付けばなんてことないんですが、unit数の違いで描写される形状が変わります。原因が分からず数時間浪費してしまいましたorz

#関連
[なぜディープラーニングするのか？を自分なりに調べてみた件](https://qiita.com/tan0ry0shiny/items/e0d4233de1e59c4d4c03)
[なぜディープラーニングをするのか？について調べてみた件2（ロジスティック回帰）](https://qiita.com/tan0ry0shiny/items/343ebe8ed5840603abc8)
[勾配降下法を可視化したい件](https://qiita.com/tan0ry0shiny/items/112a28aef0d5913337f0)
【リンク集】Webサイト(URL)やファイルの安全性確認ができるサイト

Webサイト(URL)やファイル、メールの安全性確認ができるサイトをまとめました。
※各サービスの利用規約等を確認し、利用が適切か判断したうえでご利用ください。

* **[aguse](https://www.aguse.jp/)**: URL,メール
 aguseの企画、開発、運営は[アグスネット株式会社](https://www.aguse.jp/company/)が行っています。
* **[HYBRID ANALISYS](https://www.hybrid-analysis.com/?lang=ja)**: URL,ファイル
* **[VirusTotal](https://www.virustotal.com/gui/home/upload)**: URL,ファイル
はじめてのJest

# そもそもJestとは？

### 一番人気なJSのテストフレームワーク
[https://2020.stateofjs.com/en-US/technologies/testing/](https://2020.stateofjs.com/en-US/technologies/testing/)

### なぜ人気なのか

> 筆者がJestを選ぶ一番の理由は、依存が少なく高機能であることです。

↓こちら参照
[https://www.codegrid.net/articles/2017-jest-1/](https://www.codegrid.net/articles/2017-jest-1/)
テストランナー、アサーション、モックが全て含まれている。
カバレッジも見ることができるらしい。　

# インストール方法は？

公式からパクリ

```php
npm i jest @types/jest ts-jest -D
```

- `jest`
    - jestフレームワーク（これが普通jestと呼ばれるもの）
- `@types/jest`
    - [https://www.npmjs.com/package/@types/jest](https://www.npmjs.com/package/@types/jest)
    - テストファイルの型チェックをする場合は必要
- `ts-jest`
    - Jest用のTypeScriptプリプロセッサ
    - Jestはその場でTypeScriptをトランスパイルすることができるようになる
    - Babelを使っている場合は不要

# 設定方法は？

jest.config.jsファイルで設定する

```jsx
module.exports = {
  "roots": [
    "<rootDir>/src"
  ],
  "testMatch": [
    "**/__tests__/**/*.+(ts|tsx|js)",
    "**/?(*.)+(spec|test).+(ts|tsx|js)"
  ],
  "transform": {
    "^.+\\.(ts|tsx)$": "ts-jest"
  },
}
```

- roots：
    - テストファイルを配置するディレクトリ
    - テストドキュメントではプロジェクトのsrcフォルダに設定することを非常におすすめしている
    - デフォルトで設定されていた`<rootDir>/test`はcdkのテストファイルをおくディレクトリ
- testMatch：
    - テストファイル名にマッチする正規表現文字列の配列
- transform：
    - 正規表現でマッチしたファイルに対してts-jestを使うように指示
    - `"^.+\\.(ts|tsx)$": "ts-jest"` これだとts/tsxファイルでts-jestを使う

# 実行方法は？

package.jsonのスクリプトに以下を追加すると、`npm run test` で実行できる

```
"scripts": {
  "test": "jest"
},
```

`npm run test --watch`でwatchモードも可

# テストファイルはどこにおけば良い？

大きく2パターンある

1. srcディレクトリにおく
    公式がおすすめしているパターン

    メリット：テストがあるかすぐ確認できる？
    デメリット：個人的にプロジェクトとテストのディレクトリは分けたいかも、、
    
    ```jsx
    └──src 
        ├── fuga
        ├── fuga.test
        ├── hoge  
        └── hoge.test 
    
    ```
    
2. testディレクトリにおく
メリット：スッキリしている気がする。
デメリット：テストファイルからテスト対象ファイルをimportするときにpathが長くなる

公式がおすすめしているパターンじゃないですけど、なにか不都合なことがあるんでしょうか？
私がよく使うLambdaの場合はsrcに入れるとテストファイルまでデプロイされるのでこっち？👀

```jsx
├──src 
│   ├── fuga
│   └── hoge
│   
└──test
		 ├── fuga
		 └── hoge
```

# 何をテストするの？テストの単位は？

まず、前提としてテストのカバレッジを100%にする必要はない。

テストの対象となるのは、大雑把に言うと

- なんかやばそうなところ
- 将来変更が入りそうなところ
- リファクタしたいところ

↓の記事が大変参考になりました。
[https://qiita.com/jnchito/items/2a5d3e15761fd413657a](https://qiita.com/jnchito/items/2a5d3e15761fd413657a)

> **「テストコードがない状態だとリファクタリングできないし、リファクタリングできない状況でコードレビューしても無駄なので、まずはテストコードを書いて下さい」**
> 

肝に銘じます。

基本的にユニットテストなので、テストの単位は関数やメソッドになる。
インテグレーションテストを書くこともできる。

# 参考

[https://typescript-jp.gitbook.io/deep-dive/intro-1/jest](https://typescript-jp.gitbook.io/deep-dive/intro-1/jest)
[https://dackdive.hateblo.jp/entry/2019/04/15/000000](https://dackdive.hateblo.jp/entry/2019/04/15/000000)
[https://t-yng.jp/post/tsc-and-babel](https://t-yng.jp/post/tsc-and-babel)
django-import-exportにてpythonで作成した日本語を含むcsvのインポートの際のエラーと応急対策

# 問題

主題の通り、pythonで作成した日本語を含むcsv(utf-8)で読み込ませると以下のようなエラーが起こる場合がある

Imported file has a wrong encoding: 'cp932' codec can't decode byte 0xef in position 0: illegal multibyte sequence

いろいろ文字コードを変えてみたが同様のエラーが発生

# 対策

もっと良い方法があるとは思いますが、以下に自分が実践した応急的な対策を紹介します

## csv書き込みの際はutf-8(BOM付き)

pythonにてcsvを作成する際

```python
with open(csv_path, 'w', encoding="utf_8_sig") as f:
    writer = csv.writer(f)
    writer.writerows(records)
```

と、このようにencodingをutf-8(BOM付きのほうが良い)に指定

Windowsにてエクセルで読み込む際BOM付きでしか正常に読み込まれない

utf-8の場合、BOM付きは'_sig'をつけるようです

BOMに関しては[こちら](https://www.techs-s.com/media/show/7)を参照してください

## .xlsxで保存

作成したcsvをエクセルで起動し .xlsxファイルで保存します

## インポート

django-import-exportで xlsx をインポート

# 環境

Python 3.9.7

Django 3.1.2

django-import-export 2.7.1
Google Colabをローカルランタイムに接続する

#何のため？

個人的にGoogle colabで気に入っているのは、
・GitHubとの連携が半端なく良い
・何より見やすい
という点です。

しかし本格的に使用する際に、
・ローカルのファイルをGdriveにアップロードする必要がある
・12時間経過すると自動的に落ちてしまう
・メモリが不足することがある
などの不便が生じます。

そこで、Google Colabをローカルで使用する方法について紹介します。


#手順1
コマンドプロンプトに以下を入力し、Jupyter notebookをダウンロードします。

```
pip install jupyter notebook
```


#手順2
Colabが提供している拡張機能をインストールします。

```
pip install jupyter_http_over_ws
```


#手順3
ローカルのJupyter notebookを起動します。コマンドプロンプトに下の呪文を入力
。

```
jupyter notebook --NotebookApp.allow_origin='https://colab.research.google.com' --port=8888 --NotebookApp.port_retries=0 --NotebookApp.iopub_data_rate_limit 10000000
```


#手順4
コマンドプロンプトに表示されるバックエンドURLをコピーします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620139/84f44104-3b33-0955-28e1-51a9241e981f.png)


#手順5
Google Colabの「ローカルランタイムに接続」をクリックし、バックエンドURLのところにペーストします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620139/7e154cf7-5bea-7784-b141-4beba9df5cd5.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620139/db12108c-f3ad-25fd-167b-9f92ad03f036.png)

これでめでたく、Google Colabがローカルに接続されます。



#ローカルで使用する場合の注意点

・パスはローカルのものを参照することとなります。Windowsの場合には、Shiftキーを押しながらファイル（あるいはフォルダ）を右クリックすると、ファイルのパスをコピーすることができます。実際にはコピペしたものの前に"r"をつけて使います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620139/68feeaa6-fcd2-4f07-d4d2-3f9fdfc0f20d.png)

```
path = r"C:\Users\ykita\.jupyter\jupyter_notebook_config.py"
```

また、!lsなどのlinuxコマンドは使えません。!pip installはできます。インストール先はローカル環境となります。


#Anacondaとの連携はできますか？

Anacondaで環境構築している場合も大丈夫です。Anaconda promptから先ほどのコマンドを入れればColabに接続できます。便利！


では、楽しいColab lifeを！！
CSSとSCSSの違い

# 1. はじめに

Ruby on Railsでコントローラーとか作ったら出てくる`コントローラー名.scss`ってなんだってなりますよね。
`application.css`との違いってなんだろって思ったと思います。
そんなみんなの助けになればな！っと思ってこの記事を書きます。

# 2.　CSSとSCSSの違い

***CSS***も***SCSS***のどちらもデザインをするために使う言語です。

`この2つ(CSSとSCSS)の違いってわかりますか？`

名前が違うくらいだろって思いますよね。
自分も最初はそのくらいだろって思ってましたが、実は結構違います。

---
備考
***セレクター***は***タグ***、***class名***、***id名***のことを指します。
***プロパティ***は***background-color***、***text-align***などのを指します。
***値***は ***#000000*** や ***100%*** などのプロパティを数値のことを指します。

プロパティや値が他に何があるのかを詳しく知りたい人はここの下のリンクから飛んで(backgroud-sizeなどで)検索してみてください！
[MDNサイト](https://developer.mozilla.org/ja/docs/Web)
***↑ ここからサイトへ飛びます***

---


`CSSとは文字の大きさや背景の色、画像の配置を指定します`
コードの書き方では、

```css:index.css

セレクタ1　{
  プロパティ: 値;
}

セレクタ2　{
  プロパティ: 値;
}

```

のように記述します。
　

`SCSSとは簡単に言ってしまえば、CSSの上位互換です`
コードの書き方では、

```scss:index.scss

セレクタ1　{
  プロパティ: 値;
  セレクタ2 {
    プロパティ: 値;
  }
}

セレクタ3 {
  プロパティ: 値;
}

```

のように記述をします。
さらに、`CSSのような記述の仕方もできます。`


### 1.　HTMLを記述していきます。

```erb:index.html.erb

<!DOCTYPE html>
<html>
  <head>
    <title>Pra</title>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>
    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>

  <body>
    <div class="test"><br>
      <a href="#">テストです</a>
    </div>
  </body>
</html>

```

これを記述するとWebサイト上ではこういう風になります。

![スクリーンショット 2021-11-28 23.31.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1803665/329fb688-c9d7-978c-b02d-a5109380295b.png)
では、ここから***CSS***で記述したパターンと***SCSS***で記述をした2つのパターンで見てみましょう。

### 2.　CSSで記述します

```css:index.css

.test {
  margin: 40px;
}
a {
  padding: 10px 20px;
  color: #000000; #黒色で表示
}

```

![スクリーンショット 2021-11-28 23.40.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1803665/e692e9de-ff96-4314-1ea7-04e687596a78.png)

### 3. SCSSで記述します

```scss:index.scss

.test {
  margin: 40px;
  a {
     padding: 10px 20px;
     color: #ff0000;　　#赤色で表示
  }
}

```

![スクリーンショット 2021-11-28 23.41.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1803665/d58883df-27c4-9da6-05c9-bca7a0f1e03e.png)
２つの画像を見ての通り`記述の仕方`が違うだけで、デザインの表示は同じです。
scssなら`どれがどこを指定しているのかのわかりやすさが段違いです。`

```css:index.css

a{
  background: #939393;
}

a:hover {
  background: #939393:
　 opacity:0.7;
}

```

CSSでは、このように書かなければいけないのですが、`SCSS`なら


```scss:index.scss

a{
　　background: #939393;
  &:hover {
  　　background: #939393:
　   opacity:0.7;
 }

```

のように行を減らすことに加えて ***aと書かずに&*** だけで済ませることができte便利です。

# 3．これで以上です！
みなさんここまでお疲れ様でした！
CSSとSCSSを使いこなしてより良いデザインをしていきましょう。
GAS: ContactApp.getContact(emailaddress).getFullName()で名前が取得できない件（驚愕の解決法！）

GAS（Google Apps Script）で、他のアカウントでは調子よく使えていた、自分（アクティブユーザー）のフルネームを取得するスクリプトが、なぜか作りたての新しいGSuiteアカウントで動かなかった。
スクリプトは以下の通り。

``` JS
function helloDialog(){
  var emailaddress = Session.getActiveUser(); // アクティブユーザーのメアドを取得
  var fullname = ContactsApp.getContact(emailaddress).getFullName(); // メアドから連絡先を取得し、フルネームを取得

  var ui = SpreadsheetApp.getUi(); // UIを作成
  ui.alert("Your full name is " + fullname); // アラートボックスを表示
}
```

以上はGoogleスプレッドシートのスクリプトだが、他でも応用が効くと思われる。
スプレッドシートでダイアログを表示する場合、スプレッドシート画面を表示しないと、ダイアログが「OK」を待っている状態で、スクリプトエディターの画面上は延々「実行中」になるので注意。

さて、旧アカウントで調子よく動いていたスクリプトを、新アカウントで動作させると、スクリプトエディター上に以下のメッセージが表示された。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107571/84e359ad-4288-f2c4-2fa2-d2424a160147.png)

```
Type Error: Cannot read property 'getFulName' of null
```

これは、```ContactApp.getContact()```メソッドが```null```を返し、```null```の```getFullName()```プロパティを取得しようとして怒られている状態だと思われる。

いろいろ調べたら、以下の解決法に至った。
（参考にしたブログ記事は別の問題の別の解決法だったので引用しない）

(1) GoogleアカウントにログインしたChromeブラウザーから、「連絡先」アプリ（Googleコンタクト）を起動する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107571/6e9743f0-87db-0dac-7df6-1b37029ed892.png)
(2) デタラメの宛先でいいから1件登録する（苗字＝foo、名前＝bar、メアド＝foobar@example.comとかでいい）

これだけで、なぜか成功する。
なんじゃそりゃーー！

ContactsAppオブジェクトというのは連絡先アプリのオブジェクトで、宛先が1件もない状態ではこれが取得できないから、nullが返るようだ。

この連絡先アプリというの、ぼくは初めて知ったのだが、旧アカウントで見てみると、過去やりとりしたメアドがめっちゃ入ってるので、だから新アカウントも社会生活したら自然に直ってたかもしれない。
（あるいは旧アカウントは携帯アプリとシンクしたから連絡先がいっぱい入ってるのかもしれない。よく分からない）

QiitaにGASの記事をいくつか書いてるので暇な人は見てください。
もっともカンタンな記事はこちら。

https://qiita.com/query1000/items/3b5491b96f3fd749c70c
Android Gradle: デフォルトの buildType / productFlavor を指定する

Android Studio で Gradle プロジェクトを開いたとき、なにも指定がなければ、buildType / productFlavor を辞書順で並べたときの先頭の組が選択されます。

初期選択したい buildType / productFlavor があれば isDefault を設定します。

* Android Gradle Plugin 7.0.4 で確認しています

# 設定

`app/build.gradle.kts`

```kotlin
android {
    // ...
    buildTypes {
        getByName("debug") {
            isDefault = true
            // ...
        }
        register("release") {
            // ...
        }
    }
    productFlavors {
        register("develop") {
            isDefault = true
            // ...
        }
        register("alpha") {
            // ...
        }
        register("production") {
            // ...
        }
    }
    // ...
}
```

デフォルトの buildType / productFlavor を指定するには [ApplicationBuildType#isDefault]( https://developer.android.com/reference/tools/gradle-api/7.0/com/android/build/api/dsl/ApplicationBuildType#isDefault:kotlin.Boolean) と [ApplicationProductFlavor#isDefault](https://developer.android.com/reference/tools/gradle-api/7.0/com/android/build/api/dsl/ApplicationProductFlavor#isDefault:kotlin.Boolean) を設定します。

上記設定であれば、`developDebug` がデフォルトとして選択されるようになります。

buildType が debug, release であり、productFlavor が alpha, develop, production であれば、Build Variant は以下のように辞書順で並びます。

* buildType: debug -> release
* productFlavor: alpha -> develop -> production
* Build Variant: alphaDebug -> alphaRelease -> developDebug -> developRelease -> productionDebug -> productionRelease

isDefault の設定がなければ、先頭の `alphaDebug` がデフォルトで選択されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17931/a59c668c-0d24-54f2-b2cd-d99b9450e3d4.png)

# 参考

https://proandroiddev.com/android-set-a-default-build-type-flavor-a1cdcd1c15fa
【Project Euler】Problem 38: 倍数の連結でパンデジタル

* 本記事は[ProjectEuler](https://projecteuler.net/about)の「100番以下の問題の説明は記載可能」という規定に基づいて回答のヒントが書かれていますので、自分である程度考えてみてから読まれることをお勧めします。

### 問題 38. 倍数の連結でパンデジタル

原文 [Problem 38: Pandigital multiples](https://projecteuler.net/problem=38)

**問題の要約：以下の例のように$n>1$に$1,2,3, \dots$掛けたものを連結した9桁のパンデジタル数の最大値を求めよ**

```math 
192 \times 1 = 192 \\
192 \times 2 = 384 \\
192 \times 3 = 576 \\
192 384 576 \rightarrow パンデジタル数　\\ \\
9 \times 1 = 9 \\
9 \times 2 = 18 \\
9 \times 3 = 27 \\
9 \times 4 = 36 \\
9 \times 5 = 45 \\
918273645 \rightarrow パンデジタル数　\\ \\
```

[Problem 32: パンデジタル数の積](https://qiita.com/masa0599/items/9fc76beaa3d654a72472)ではitertools.permutationsを使いました。今回も同様ですが最大値だけを求めれば良いので大きい順に生成します。permutationsは「 [iterable に応じた辞書式順序で出力されます](https://docs.python.org/ja/3/library/itertools.html#itertools.permutations)」とのことなので元の文字列を"987654321"します。もし最大値だけでなくすべての答えを見たければ最後のbreakを消せばOKです。

```python
from itertools import permutations

def PanProd(pans):
  for prds in [pans[:i] for i in range(1,4+1)]: # left substring of pans
    n, j = int(prds), 2
    while len(prds) < len(pans):  # concating the multiples 
      prds += str(n*j)
      j += 1
    if prds == pans:   # check prod concat equals to original pans
      return n
  return 0

# generate pandigital numbers in decending order
for pans in permutations("987654321"):  
  pans = ''.join(pans)
  n = PanProd(pans)
  if n > 0:
    print(f"Answer: {pans} n={n}")
    break
```

（開発環境：Google Colab）
【Project Euler】Problem 37: 切り捨て可能素数

* 本記事は[ProjectEuler](https://projecteuler.net/about)の「100番以下の問題の説明は記載可能」という規定に基づいて回答のヒントが書かれていますので、自分である程度考えてみてから読まれることをお勧めします。

### 問題 37：切り捨て可能素数

原文 [Problem 37: Truncatable primes](https://projecteuler.net/problem=37)

**問題の要約：11個しかない左切り捨て可能かつ右切り捨て可能素数の合計を求めよ**

[切り捨て可能素数(Wikipedia)](https://ja.wikipedia.org/wiki/%E5%88%87%E3%82%8A%E6%8D%A8%E3%81%A6%E5%8F%AF%E8%83%BD%E7%B4%A0%E6%95%B0)に説明があります。左右どちらの数字を消していっても素数になる数のことです。上限が書いてありませんが11個しかないということなので11個見つかった時点で終了します。

```python
from sympy import isprime, nextprime
def isTruncPrime(n):
  tl=tr = str(n)
  if len(tl)<=1: return False    # exclude 2,3,5,7
  for i in range(len(str(n))-1):
    tl, tr = tl[1:], tr[:-1]
    if not isprime(int(tl)) or not isprime(int(tr)): return False
  return True

tps, p = [], 7
while len(tps)<11:
  p = nextprime(p)
  if isTruncPrime(p):
    tps.append(p)
print(f"Answer: {sum(tps)}, ({tps})")
```

（開発環境：Google Colab）
Pythonをターミナルで正しく表示させる

[議題]
 myapp.pyというPythonファイルの結果を、ターミナルで表示させようと、
いつものように「% python myapp.py」と書いたら、


```
 % python myapp.py
Non-ASCII character '\xe3' in file myapp.py on line 1, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details
```
 というエラーが出現。 どうやって解決させる?


[原因]
　エンコーディング認識の違いによって python がソースコードを正しく解釈できなかったため。
ソースコードのエンコーディング方式を指定しないと、ソースコードが正確に解釈されないため、このようなエラーが出る。

　これは、Pythonのバージョンの違いで起こる。
私の場合、Python 2.7 の環境で、このエラーが起こってしまった。
Python 3.x ではデフォルトで、UTF-8 エンコーディングとしてソースファイルを認識するため、エラーは出にくいと考えられる。


[解決策]
 Python に 、UTF-8 としてエンコーディング形式を指定し、ソースコードを正しく認識させる。

```
# coding: utf-8
```
 上記の一行を、Pythonファイルの１行目に記述する！
(ーー　なお、#　はつけたまま記述する ーー）


[参考資料]
https://python.keicode.com/devenv/encoding.php
【Project Euler】Problem 35: 循環素数

* 本記事は[ProjectEuler](https://projecteuler.net/about)の「100番以下の問題の説明は記載可能」という規定に基づいて回答のヒントが書かれていますので、自分である程度考えてみてから読まれることをお勧めします。

### 問題 35：循環素数

原文 [Problem 35: Circular primes](https://projecteuler.net/problem=35)

**問題の要約：$p<10^6$の素数で桁を循環させたすべての数も素数になるものの合計を求めよ**

まずはそのまま$p<10^6$のすべての素数で循環素数のチェックをして数えます。

```python
from sympy import nextprime, isprime

def isCircularPrime(pstr):
  for i in range(len(pstr)-1):
    pstr = pstr[1:]+pstr[0]   # rotate one digit
    if not isprime(int(pstr)):
      return False
  return True

N = 10**6
nCirPrime, p = 0, 1
while p < N:
  p = nextprime(p)
  pstr = str(p)
  if isCircularPrime(pstr): 
    nCirPrime += 1
print(f"Answer is {nCirPrime}")
```

今回の答えはこれでいいのですが、これは循環したものを重複して数えています。[Circular prime(Wikipedia)](https://en.wikipedia.org/wiki/Circular_prime)によれば（日本語はないのが寂しいですが、、、）$p<10^6$の循環素数は19個しかないとのことなので重複を除いたすべての循環素数を出力するプログラムも作りました。

```python
from sympy import nextprime, isprime

def CirPrimeList(pstr):
  ret = set({int(pstr)})
  for i in range(len(pstr)-1):
    pstr = pstr[1:]+pstr[0]   # rotate one digit
    if not isprime(int(pstr)):
      return set()
    ret.add(int(pstr))
  return ret

N = 10**6
cpset = set()
CirPrime, p = [], 1
while p < N:
  p = nextprime(p)
  if p in cpset: continue
  pstr = str(p)
  cps = CirPrimeList(pstr)
  if len(cps )>0:
    CirPrime += [p]
    cpset |= cps

print(f"Answer {len(CirPrime)}, {CirPrime}")
#Answer 19, [2, 3, 5, 7, 11, 13, 17, 37, 79, 113, 197, 199, 337, 1193, 3779, 11939, 19937, 193939, 199933]
```
（開発環境：Google Colab）
ServiceNow error Workflow Validation / unattached transition(s)

以下のエラーがWorkflow実行時に出た。

This workflow contains 2 unattached transition(s). Unattached transitions cause the workflow to hang and never complete. In the workflow version form, select the cited activity from the Workflow Activities related list.  In the From: Workflow Transition related list, delete any transition that does not have a To reference.

これの解消法として、
Workflow Activities　の関連リストにあるWorkflow Transitionの中身にカラ参照レコードが存在するので、該当するレコードを削除すると動作するようになる。
Excel 3D Mapsでデータが追加できないエラー解消方法(予約語が問題のケース)

#0.はじめに
Excelに3D Mapsという、地図上にデータをマッピングできる機能があります。
使ってみたところデータの追加でつまづき、検索しても自分の場合は解決に至らなかったので、ここに解決方法の一つとして残しておきます。

#1.エラー内容
Excelから3D Mapsにデータを追加しようとしたら、
「3D Maps でエラーが発生しました。直前の操作をもう一度お試しください。」
というエラーが出ました。

#2.原因と解消方法
データ項目名('key2'という名称にしていました)が予約後と重複していたことが原因でした。
なお、単なる'key'であれば問題ないようです。'key1'もダメです。

データ項目名を変更する(例えば'key項目'などにする)ことでデータが追加可能になりました。
ちなみにエラーメッセージから、アプリの一時的な問題かな？と思ったため、解消に苦労しました。

#3.どの項目名がエラーの原因か確認する方法
データを選択し、
[挿入]、[ピボットテーブル] の順にクリック。
[ピボットテーブルの作成] ダイアログ ボックスで [このデータをデータ モデルに追加する] チェック ボックスをオンにします。

項目名が予約語と重複していてエラーの原因になっている場合、
「データモデルからデータを取得できませんでした。エラーメッセージは次のとおりです:
‘テーブル1’ ディメンションには無効な名前のメンバー プロパティが含まれています。’key1’は予約語の1つです。」
という表示が出るので、どの項目名が問題になっているかがわかります。


#4.解決に向けて考えたこと
以降は直接エラー解消には関係ありませんが、解決に向けて考えたことを書いておきます。

##3D Mapsへのデータ追加は、どこにデータ追加されるのか？
データを選択し、
[挿入]タブ→[3Dマップ]→[選択したデータを3D Mapsに追加]
の手順でデータを追加しますが、このデータはどこに追加されるのか？を考えました。

結論として、
[PowerPivot]タブ→[管理]
から表示されるPower Pivot for Excelに追加されることがわかりました。
今回はエラーのため、ここにデータが追加されないことが問題でした。

##Power Pivot for Excelにデータを追加するにはどうすればよいか？

Microsoftのサポートサイト
[Excel でデータ モデルを作成する](https://support.microsoft.com/ja-jp/office/excel-%E3%81%A7%E3%83%87%E3%83%BC%E3%82%BF-%E3%83%A2%E3%83%87%E3%83%AB%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B-87e7a54c-87dc-488e-9410-5c75dbcb0f7b)
の「既存の関連しないデータをデータ モデルに追加する」によると、Power Pivot for Excelにデータを追加する方法は2つあるそうです。

1つ目の
[PowerPivot]、[データ モデルに追加] の順にクリックします。
ではエラーが出るのでダメ。

リンク内2つ目の（上記方法と同じ）
[挿入]、[ピボットテーブル] の順にクリックし、[ピボットテーブルの作成] ダイアログ ボックスで [このデータをデータ モデルに追加する] チェック ボックスをオンにします。
を試したところ、予約語でひっかかっていることが判明しました。

#5.おわりに
他にどのような単語が予約語になっているか知りたくて、予約語一覧を探してみましたが適切なサイトが見当たりませんでした。
どなたかご存じの方がおられたら教えてください。
Seleniumでループが上手く回らない時の対処法

# スクレイピングを実装していたらエラーメッセージが出た！
Seleniumをpythonを使用して実装していたら以下のようなエラーメッセージが表示された。
解決までに時間がかかってしまったので参考になればと思い投稿します。

```
selenium.common.exceptions.StaleElementReferenceException: Message: stale element reference: element is
not attached to the page document
```
 
# 前提条件
Python 3.7.12
selenium
Chrome

######手順
dockerで環境を用意
↓
pythonで目的のサイトのスクレイピング処理を実装
↓
それをループで処理する。

# エラーの出たコード
```python:sample.py
data = [1,2,3,4,5]
for i in data:
    driver.find_element_by_xpath("目的のxpath").click()
    driver.find_element_by_xpath("xpath").send_keys(i)

    driver.implicitly_wait(10) # 秒
    driver.find_element_by_xpath("xpath").click()  

    driver.implicitly_wait(10) # 秒
    driver.find_element_by_xpath("xpath").click()  
```

# ループに成功したコード
```python:sample.py
#追加
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

data = [1,2,3,4,5]
for i in data:
    driver.find_element_by_xpath("目的のxpath").click()
    driver.find_element_by_xpath("xpath").send_keys(i)

    #driver.implicitly_wait(10)
    element = WebDriverWait(driver, 30).until(EC.visibility_of_element_located((By.XPATH, "xpath")))
    driver.find_element_by_xpath("xpath").click()  

    driver.implicitly_wait(10) 
    driver.find_element_by_xpath("xpath").click()  
    time.sleep(10)
```
######ポイント
エラーの出たコードでも２回ほどループは成功していました。
element is　not attached to the page documentのエラーメッセージが出た場合、エラーの出たページの要素を調べましょう。
もし要素と自分の記述したコードに差異がなければseleniumを安定動作させるようにコードを記述しましょう！

# seleniumを安定動作させるために必要な待機処理
######暗黙的な待機

```
driver.implicitly_wait()# 秒
```

このメソッドは
指定した要素が見つかるまでの待ち時間を設定出来ます

######明示的な待機
```
WebDriverWait.until()
```
このメソッドは任意のhtmlが特定の状態になるまで待機します。
今回指定したvisibility_of_element_locatedは
ページ上の指定した要素が表示されるまで待機します。

######time.sleep
```
time.sleep()# 秒
```
こちらはプログラムを一時停止するメソッドです。
ただしこちらのメソッドは停止したからといって必ずプログラムが動くというわけではありません。
最終手段として考えましょう。

######ポイント
ループが正常に動かない場合暗黙的な待機を試してください。
それでも動かない場合には明示的な待機を
最終的にtime.sleepを使用してください。

# 参考
https://tanuhack.com/stable-selenium/
https://www.seleniumqref.com/api/python/time_set/Python_implicitly_wait.html
[Ruby] Integerクラスのabsメソッド

学習したことのアウトプットとして

## absメソッド
Rubyの組み込みライブラリ
対象となる数値に対してabsメソッドを実行すると絶対値を取得することができる。すなわち`正の数の場合はそのままだが、負の数の場合は符号を取って正の数にした数値`が取得できる。

```ruby
num = 5.abs
#=> 5

num = (-5).abs
#=> 5
```

[absメソッドのリファレンス](https://docs.ruby-lang.org/ja/latest/method/Integer/i/abs.html)

以上。

※補足等ありましたらコメントいただけると幸いです。
AtCoder Beginner Contest 016をやった(Java)

AtCoder Beginner Contest 016をやった。
[C](https://atcoder.jp/contests/abc016/tasks/abc016_3)問題の解き方が知りたいです。
図に書いて大まかにどのようなこと言っているのかは理解できますが、実装的に同実装すればタイムアウト起きないのか知りたく。

##[A](https://atcoder.jp/contests/abc016/tasks/abc016_1)
問題文に与えられたとおりに実装すれば答えが出ます。

```Java
import java.util.*;
 
public class Main {
    public static void main(String[] args) throws Exception {
        Scanner scan = new Scanner(System.in);
        System.out.println(scan.nextInt() % scan.nextInt() == 0 ? "YES" : "NO");
    }
}
```

##[B](https://atcoder.jp/contests/abc016/tasks/abc016_2)
問題文に記載の通り出力
両方当てはまるパターン、片方ずつ当てはまるパターン、Nothingみたいな感じでやると綺麗に実装できる

```Java
import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        Scanner scan = new Scanner(System.in);
        int A = scan.nextInt();
        int B = scan.nextInt();
        int C = scan.nextInt();
        if(A + B == C && A - B == C){
            System.out.println("?");    
        } else if(A + B == C){
            System.out.println("+");
        } else if(A - B == C){
            System.out.println("-");
        } else {
            System.out.println("!");
        }
    }
}
```
【備忘録】VSCodeでコードユニペット（Python）を登録する

#目的
Pythonのプログラムを書く際にお約束の文言を毎回入力するの面倒なので，コードユニペットに登録してしまおうというヤツ
##こんな感じに
『shebang』って打とうとすると．．．
![スクリーンショット 2022-01-18 16.17.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2430126/c15745e2-306b-91cd-f91e-7105064c9492.png)
予測候補が表示されて
![スクリーンショット 2022-01-18 16.18.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2430126/41be681c-9fa1-ed4e-483e-8a2b358f5d81.png)
シバンが入力される
同様に『main』って打とうとすると．．．
![スクリーンショット 2022-01-18 16.20.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2430126/4ab9931d-b977-baf0-0351-9253d14e1249.png)
予測候補が表示されて
![スクリーンショット 2022-01-18 16.21.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2430126/36d617b6-990e-dca2-4a63-317014c49b07.png)
↑が入力される

**まぁ便利！！**

##実際に登録してみる
1. VSCodeの基本設定からユーザユニペットを選択
![スクリーンショット 2022-01-18 16.03.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2430126/678aac53-071d-bab4-d953-2bc7581cf35f.png)
1. 『Python』を選択（デフォルトであるはずなので，新しく作る必要はない）
![スクリーンショット 2022-01-18 16.31.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2430126/c5061937-55be-9612-6b62-cb6f09851b1b.png)
1. そうしたら，jsonファイルが開かれてこんな内容が書かれているはず
![スクリーンショット 2022-01-18 16.34.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2430126/7d15fd03-7f13-ba96-41d3-4364900d6069.png)
1. ここに，下の内容を追記する __※既にある『{ }』内に記載すること！！__

    ```json:python.json
	"main":{
		"prefix": "main",
		"body": [
			"if __name__ == '__main__':",
			"    ${1:pass}"
		],
		"description": "main"
	},
	"shebang":{
		"prefix": "shebang",
		"body": [
			"#!/usr/bin/env python3",
			"# coding: utf-8"
		]
	}
    ```

1. 最終的に，自分のpython.jsonファイルはこんな感じの内容になった

```json:python.json
{
	// Place your snippets for python here. Each snippet is defined under a snippet name and has a prefix, body and 
	// description. The prefix is what is used to trigger the snippet and the body will be expanded and inserted. Possible variables are:
	// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders. Placeholders with the 
	// same ids are connected.
	// Example:
	// "Print to console": {
	// 	"prefix": "log",
	// 	"body": [
	// 		"console.log('$1');",
	// 		"$2"
	// 	],
	// 	"description": "Log output to console"
	// }

	"main":{
		"prefix": "main",
		"body": [
			"if __name__ == '__main__':",
			"    ${1:pass}"
		],
		"description": "main"
	},
	"shebang":{
		"prefix": "shebang",
		"body": [
			"#!/usr/bin/env python3",
			"# coding: utf-8"
		]
	}
}