OmniAICreator/Qiita-1.07M huggingface dataset:
マッシュアップする

# マッシュアップとは

>　マッシュアップ（英: Mashup）とは2つ以上の曲から片方はボーカルトラック、もう片方は伴奏トラックを取り出して、それらをもともとあった曲のようにミックスし重ねて一つにした音楽の手法である。バスタードポップ (bastard pop) とも言う。

[マッシュアップ　出典: フリー百科事典『ウィキペディア（Wikipedia）』](https://ja.wikipedia.org/wiki/%E3%83%9E%E3%83%83%E3%82%B7%E3%83%A5%E3%82%A2%E3%83%83%E3%83%97)


# マッシュアップする
librosaでHarmonic/Percussive Sound Separationっていう手法で打楽器とそれ以外を分けれるらしいからそれ使う


```python:

import librosa
import soundfile as sf
import pydub
from pydub import AudioSegment

motoneta_path = "motoneta.mp3"

drum_neta_path = "drum_neta.mp3"
drum_only_path_wav = "drum_only.wav"
drum_only_path = "drum_only.mp3"

# librosaでドラムパート抜き出し
y, sr   = librosa.load(drum_neta_path)
y_h, y_p = librosa.effects.hpss(y)

# librosaかませるだけで2倍速になるから0.5倍速にして保存
# 原因はわからない、チュートリアルどおりやってんのに　訳わかんない
y_pp = librosa.effects.time_stretch(y_p, 0.5)
sf.write(path_wav, y_pp, 48000)

# ドラムパート音源をmp3化（wavサイズでかいから）
p = pydub.AudioSegment.from_wav(path_wav)
p.export(drum_only_path, format="mp3")

# ここからマッシュアップ
# 元ネタ音源とドラムぬきだし音源を読み込む
m3 = AudioSegment.from_file(motoneta_path, format="mp3")
p3 = AudioSegment.from_file(drum_only_path, format="mp3")


# 元ネタ音源とドラムぬきだし音源のBPMを取る
y_m3, sr_m3   = librosa.load(motoneta_path)
tempo_m3, beat_frames_m3 = librosa.beat.beat_track(y=y_m3, sr=sr_m3)

y_p3, sr_p3   = librosa.load(drum_only_path)
tempo_p3, beat_frames_p3 = librosa.beat.beat_track(y=y_p3, sr=sr_p3)

# 早い方にBPMを合わせる（遅い方に合わせるとバグるから）
if tempo_m3 < tempo_p3:
    speed = tempo_p3/tempo_m3
    m3 = m3.speedup(playback_speed=tempo_p3/tempo_m3, crossfade=0)
elif tempo_m3 > tempo_p3:
    speed = tempo_m3/tempo_p3
    p3 = p3.speedup(playback_speed=speed, crossfade=0)

# 重ねて出力
m3 = m3.overlay(p3, 0)
m3.export("mu.mp3", format="mp3")

```

おしまい

リファクタしてから動かしてないからバグるかも（結果が良くなかったからなんか綺麗にする気もない）
処理も全然簡略化もできると思うんだけどこれも結果が良くなかったからやる気でない

# 聞いてみた

ゴミもいいところ、13秒くらいからドラム音源重なってくる

https://soundcloud.com/bjack_mijilme/python-mashup

元ネタは金曜ロードショー

ドラム音源はこれ

https://www.youtube.com/watch?v=yGoxa1TkRuQ

# 今後の展開

あんま希望持てない

やるならスネアやバスの音の位置からジャストに合わせるとかやれるかもしれないけどあんまやる気にならない

ネタとしてはpydubのsilence.detect_leading_silence使うと先頭の無音削れるらしいからこの辺使っていく

# お気持ち

結構調査時間かかった割に全然良くない、librosaが思った通りに動かない
[py2rb] for のスコープ

# はじめに
移植やってます
# for (Python)
```python
for item in (1, 10, 2):
    if item is not None:
        break
print(item)
```
見た瞬間、`item`って未定義？と思いましたが、ちゃんと数値を返します。
# for (Ruby)
```ruby
for item in [1, 10, 2]
  break if !!item
end
puts item

item = [3, 10, 2].find{ !!_1 }
puts item
```
`Ruby`はそんなことないだろうと思っていましたが、ちゃんと数値を返します。
普段、`for`って使用しませんので思い込みでした。
# メモ
+ Python の for を学習した
+ 道のりは遠そう
自前IPv6 Kubernetesで苦しむ

本記事は、
[AWS Containers Advent Calendar 2021](https://qiita.com/advent-calendar/2021/aws-containers)の14日目になる記事です。

## 結論：IPv6だけでEKSを動かすにはまだ早い。もう少し待とう。

今は、[github issue](https://github.com/aws/containers-roadmap/issues/835) を Subscribe してお待ちください。

「おことわり： 本記事をみても、IPv4 の世界に乗り出す、IPv6だけのEKSは未サポート。Coming Soonらしいのでもう少し待とう」 ということになる。

## 何がたりないのか

コンテナ界隈でIPv6をいじっているという皆様はどんな世界にお暮らしでしょうか。IPv6アクセスのほうがもはや多くなったモバイルOS界隈？ IPv4もIPv6も同様に投資されている、モバイルキャリアむけシステム界隈？ それとも。。。？ いずれにせよ IPv4 でコンテナを触っていることの無理感がかなり増えている昨今ではないでしょうか。少なくとも私はそのひとりです。

コンテナ界隈では巨大なコンテナホストにコンテナを詰めるだけ詰める世界があり、そこで host network をつかわない世界があります。
そこは、外界はいざしらず、コンテナ輸送船団内というか、Cluster内部ではIPv6を使いたい世界になります。

しかし、世の中まだまだ IPv4 前提だし、IPv6 が普通になるには時間がかかりそうです。
そんなわけで必要なのは、
```「Pod が IPv6 アドレスを利用しつつ、IPv4 エンドポイントにルーティングできるように、単一インターフェイス構成で IPv6 サポートを有効にする」``` ことでしょう。

AWS reInvent2021の、Deep Dive on Amazon EKS セッションではこんな発表がありましたが、こんな世界です。

![Deep_Dive_on_Amazon_EKS.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35274/00aa80e4-917f-1f68-a3d6-2ea7ea049f32.jpeg)

おおっと、もしかしてリリースされたのか！ と 思いましたがいやちょっとまて。執筆時点では、Coming Soon だった。つまり、まだ楽には使えないってことだ。

https://github.com/aws/containers-roadmap/issues/835

というわけで、このように宣言しなければなるまい。
「おことわり： 本記事をみても、IPv4 の世界に乗り出す、IPv6だけのEKSは未サポート。Coming Soonらしいのでもう少し待とう」 ということになる。

## そろってきたピースの整理

### 2021.7 VPC CNI plugin v1.9でノードあたりのIPアドレス数が16倍に。

https://aws.amazon.com/jp/about-aws/whats-new/2021/07/amazon-vpc-cni-plugin-increases-pods-per-node-limits/

[AvailableIpPerENI](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-eni.html#AvailableIpPerENI) を参照すると、ENIあたりのIPアドレス数は、よく使われる c5.large でもIPv4とIPｖ６それぞれに10ずつもあります。さらに、ネットワークインターフェイスに個々のセカンダリ IPv4 アドレスを割り当てる代わりに、/28（16 IP アドレス）IPv4 アドレスプレフィックスを割り当てることができるようになり、これにより、ノード 1 台に配置可能な Pod 数が大幅に向上（16倍！）しました。

https://aws.amazon.com/jp/blogs/news/amazon-vpc-cni-increases-pods-per-node-limits/

こうなると、俄然ためしたくなります。そしてこの機能、IPv6 でも使えるんです。

### 2021.11 VPCにIPv6 only subnetができ、NAT64がでた

https://aws.amazon.com/jp/about-aws/whats-new/2021/11/amazon-virtual-private-cloud-ipv6-subnets-ec2-instances/

https://aws.amazon.com/jp/about-aws/whats-new/2021/11/aws-nat64-dns64-communication-ipv6-ipv4-services/



## おわりに

完全な IPv6 だけの世界は無理でも、
コンテナネットワークでIPv6を動かすことで、解決する未来があります。

Private IPv4 が組織内で枯渇し、
RFC6890 で定義されたShared Address Space「100.64.0.0/10」 までアドホックにくいちらかし、かといって一旦割り当ててたアドレス回収もできずにいるようなカオスな組織でも何の問題もない世界は目の前です。

今は、[github issue](https://github.com/aws/containers-roadmap/issues/835) を Subscribe して待ちましょう。

そして、コンテナなんて矮小な話じゃたりねーよ、という方。
[IPv6 on AWS](https://d1.awsstatic.com/whitepapers/IPv6-on-AWS.pdf) というホワイトペーパーがあります。

JAWSの山口さんによる解説記事があります。日本語で読めます。おすすめです。

https://shimakaze.hatenablog.com/entry/2021/12/03/200611

### おまけ。。手でやるなら

気楽に試すだけなら、IoTならIPv6あたりまえだし、
[k0s(もうすぐ。マージ待ち)](https://github.com/k0sproject/k0s/pull/1292) と
[k3s(対応してない）](https://github.com/k3s-io/k3s/issues/2123)
どちらかで行けるやろ！ とおもったのですが甘かったようです。

最後に手でやるならUbuntuでやった記事がこれ。

https://github.com/sgryphon/kubernetes-ipv6
最短でDrupal開発環境（お試し環境）を手に入れる2021

この記事はDrupal Advent Calendar 2021の記事です。
Drupal Meetup Tokyo の中の人の一人です。

最近[DrupalPod](https://github.com/shaal/DrupalPod)を言うものを知りました。これはGitpod上にDDEVでDrupal環境を構築するものでした。

...なんのことだかよくわからないと思うので簡単に説明します。

## Gitpodとは

クラウド開発環境。ブラウザやローカルのアプリ（Visual Studio CodeやPHPStorm）から開発が可能な環境を提供するサービス。無料プランあり

## **DDEVとは**

CLIツール。DockerのDrupal向けラッパーで他に[Lando](https://lando.dev/)や[Docksal](https://docksal.io/)などがある。実態はDrupal向けにカスタマイズされたdocker-composeといくつかの開発ツールを含むDrupal開発環境をサクッと構築できる優れもの。Drupalist達の血と汗と涙の結晶

## DrupalPodとは

このGitpodとDDEVを組み合わせて、Gitpodアカウントが開設済みであればワンクリックですぐに開発が始められる。いろいろ引数を渡せるようになっているので、Drupalモジュールのプロジェクトページからボタンリンクから、モジュールを試すことができたりブラウザ拡張をインストールするとissueページからパッチを当てた状態などで起動してプロジェクトへのコントリビュートが簡単に始められるようです。

![Issueページからブラウザ拡張でインスタンスを起動するところ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4319/66b9133a-508c-b74e-b1ef-49834e20741a.png)


### サンプル（要Gitpodアカウント）

以下のリンクから環境が起動します。
※使わなくなったらインスタンスを止めるのを忘れずに！

[https://gitpod.io/#DP_PROJECT_NAME=project_browser,DP_ISSUE_FORK=,DP_ISSUE_BRANCH=,DP_PROJECT_TYPE=project_module,DP_MODULE_VERSION=1.0.x,DP_CORE_VERSION=9.3.x,DP_OLIVERO=1,DP_PATCH_FILE=,DP_INSTALL_PROFILE=standard/https://github.com/shaal/DrupalPod](https://gitpod.io/#DP_PROJECT_NAME=project_browser,DP_ISSUE_FORK=,DP_ISSUE_BRANCH=,DP_PROJECT_TYPE=project_module,DP_MODULE_VERSION=1.0.x,DP_CORE_VERSION=9.3.x,DP_OLIVERO=1,DP_PATCH_FILE=,DP_INSTALL_PROFILE=standard/https://github.com/shaal/DrupalPod)

## まとめ

Dockerの登場により開発環境の構築はかなり楽になりましたが、Drupalの経験が無いエンジニアが環境構築するのはそれなりに手間なので、ベストプラクティスに近い環境がクリックひとつで手に入るのはよいですね。
AnimeGAN2-PyTorch　写真をアニメにする

AnimeGANv2に、かわいいトレーニング済みモデルが出てきて、
しかも、Torch-Hubでモデルをダウンロードできるようになって、使いやすくなった。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/017daec4-3931-d6df-0392-ab10902719cd.png", width=310> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/fc37e963-8530-3711-d1cf-356bfdff1fe2.png", width=300>
なにせ、以下のコードだけで写真をアニメ風に変換できる。

```python
from PIL import Image
import torch

model = torch.hub.load("bryandlee/animegan2-pytorch:main", "generator", pretrained="face_paint_512_v2")
face2paint = torch.hub.load("bryandlee/animegan2-pytorch:main", "face2paint", size=512)

img = Image.open(input_image_path).convert("RGB")
out = face2paint(model, img)
```
事前トレーニング済みの重みには2021/12現在以下のバリエーションがある。

|face_paint_512_v2|celeba_distill|face_paint_512_v1|paprika|
|---|---|---|---|
|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/fc37e963-8530-3711-d1cf-356bfdff1fe2.png", width=200>|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/a8a383be-f8b1-2eed-8705-2685b0ab5096.png", width=200>|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/c3b6dcd0-b7d3-18e8-c9cb-f605724b6353.png", width=200>|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/d02ee6e4-b22e-8f03-8cbf-a6a5536af82b.png", width=200>|

Colabデモ：[AnimeGAN2Demo](https://colab.research.google.com/drive/1WW7guu-MBJGs7swQBue5Q_tS6rg0e172?usp=sharing)
[<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/c976f319-ac1b-81e8-639a-4c2b2bb059a5.png", width=500>
](https://colab.research.google.com/drive/1WW7guu-MBJGs7swQBue5Q_tS6rg0e172?usp=sharing)
Videoデモ: [huggingface](https://huggingface.co/spaces/nateraw/animegan-v2-for-videos)
![Dec-14-2021 09-40-28.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/4073f8f8-ccfb-863b-b0d3-4458473c00e9.gif)
Pytorchモデル：[bryandlee/animegan2-pytorch](https://github.com/bryandlee/animegan2-pytorch#additional-model-weights)
Tensorflowオリジナルリポジトリ: [TachibanaYoshino/AnimeGANv2](https://github.com/TachibanaYoshino/AnimeGANv2#requirements)
CoreML変換記事：[AnimeGANv2をCore MLに変換してiOSでつかう【変換済みモデルあり】](https://qiita.com/john-rocky/items/e4c757306b4d8f0f2c36)

🐣
****
フリーランスエンジニアです。
お仕事のご相談こちらまで
簡単な開発内容をお書き添えの上、お気軽にご連絡ください。
rockyshikoku@gmail.com

Core MLやARKitを使ったアプリを作っています。
機械学習／AR関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
wxPythonのインストール(M1 Mac book Air)

# M1 MacBookAirでwxPythonがインストールできない。
* まず初めにできていないこと
 * wxPythonがインストール  
 　→tiff.hが見つからない旨のエラーメッセージ(libtifはbrew listで確認済み)

* 環境
 * python3.8.9(仮想環境)
 * pip21.3.1
 * VScodeでターミナル実行(zsh)

# 結論
 * 実行アプリケーションが何で起動しているかの問題だった。
 * VScodeは初期値で「arm64(Appleシリコン)」なのでRosettaに切り替える   
  * RosettaもしくはIntel互換で起動するコマンドは以下  
 ```
arch -x86_64 zsh
```

  * 一応Appleシリコンに切り替え  
```
xarch -arm64 zsh
```

##### まだまだARM64で上手くできるものは少ないようだ…基本Rosetta使うべきか検討
UnityHubに古いUnityをインストールするときに詰まった話

# 前置き
- 仕事の都合で、古いUnityをインストールするときに詰まったことがありました。
- 自分が発生した問題に合わせて解決方法をまとめました。

# 問題1.UnityHubにインストールしたいUnityのVersionが無いとき

- **ダウンロード アーカイブ**をクリックすることで、他のUnityのVersionをインストールことができます。

![Screenshot from 2021-12-14 09-14-25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/763295/2a829c66-1003-f6eb-f3af-437924d4138c.png)

# 問題2.`UnityHub`のボタンを押しても反応がない

- 通常なら、`UnityHub`のボタンを押すことでUnityをインストールすることができます。
- しかし、中にはボタンを押しても反応が無い場合があります。
![Screenshot from 2021-12-14 09-14-59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/763295/e124f59b-91cb-755b-1c05-471794a1ce2f.png)

- その時は、以下の操作を実行することで解決
  - `UnityHub`のボタンを右クリックし「リンクを新しいタブで開く」をクリック
  -  以下の画像のように、リダイレクトリンクをコピーする
  -  `./UnityHub.AppImage リダイレクトリンク`をターミナルで実行することでUnityをインストール
  -  下の画像通りにやると、`./UnityHub.AppImage unityhub://2020.3.24f1/79c78de19888`を実行
![Screenshot from 2021-12-14 09-16-45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/763295/8776b6bf-f510-cdbc-d8f5-b8e9c2bf2e0a.png)


# 問題3.古いUnityをインストールしても途中でエラーが発生する
- 原因は分かりませんが、目的のUnityより古いVersionを削除することで解決しました。



# 参考
- [How do I manually install older versions of unity (2019) for Linux (Arch)](https://stackoverflow.com/questions/59821895/how-do-i-manually-install-older-versions-of-unity-2019-for-linux-arch)
PowerToysでWindows画面のセッションロックを回避する

毎度、ググっても出てこない小ネタを取り扱っております。
本記事は個人的な見解であり、筆者の所属するいかなる団体にも関係ございません。

# 0. はじめに

PowerToysには、Windows画面のセッションロックを回避する機能があります。
セッションロックとは、WindowsPCで操作をしていないアイドル時間が何分か経過するとWindowsの画面をロックして再度ログインしないと操作できないようにする機能です。
セキュリティー対策としては重要な機構だと思いますが、限定された環境であればセッションロックが不要な場合もあります。

# 1. 使い方
## 1-1. PowerToysをインストールする

インストールに関するドキュメントは以下のURLから参照してください。

PowerToys のインストール | Microsoft Docs 
https://docs.microsoft.com/ja-jp/windows/powertoys/install

簡単に言うと以下のGitHubのリリースページから最新のインストーラーをダウンロードして実行するだけです。
https://github.com/microsoft/PowerToys/releases

## 1-2. 設定

インストールが終わったら、設定します。
PowerToysの設定画面を開いて、
- 「Awake」＞「Awakeを有効にする」＞「オン」
- 「モード」＞「無期限に起動したままにする」を選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/75d4e845-8acd-32f5-1e97-68867ccc29f5.png)

# 2. まとめ

PowerToysになぜこの機能が入ったかはよく分かりませんが、アイドル時間で強制的にセッションロックされる必要がない場合もありますので、そういう場合に使って欲しいと言うことなのだろうと思います。
a-blog cmsのフォームでスパム対策をしてみました

## 経緯
お問い合わせフォームから、毎日何十通も「〇〇導入しませんか？」系の営業目的のメールが飛んでくるようになる。
GAの目標設定に影響が出るし、注目しないといけない正規の問い合わせが埋もれやすくなるので、「明らかに営業目的なメールは問い合わせを送信できないようにしてほしい」と依頼がくる

## 対応方法検討
サイトで使用しているa-blog cmsでは、管理画面のフォーム設定で正規表現を使用した入力チェックが使えるので、エラーにしたいワードを正規表現で禁止にすれば良さそう。

## 正規表現での対応
### 指定した単語を含まない
^(?!.*単語A).*$
### 指定した単語のいずれも含まない
`^(?!.*(単語A|単語B|単語C|単語D)).*$`

## 対応検証
ひとまず下記の文言をエラーに設定して試す。
`^(?!.*(のご案内をさせて|サービスのご提案|参加費)).*$`

### 管理画面での設定変更
管理画面の「サイト管理」の「フォーム」から進んで該当フォームの「変更」から設定する。

![クリップボード一時ファイル02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2349581/6d554ed8-2a8c-ddbc-c50b-c33b46d4cbd7.png)


フィールドにtextareaのnameを、オプションに「正規表現マッチ」を、値にエラーにしたい正規表現の値を設定する。
`^(?!.*(のご案内をさせて|サービスのご提案|参加費)).*$`

### つまづき
この段階でフォームを試すと、設定した単語が含まれて無くても改行が含まれるとエラーになってしまう。
正規表現でいろいろ試してみるも、正規表現そのものへの理解が浅いこともあり解決できず・・・・。

### 修正
フォーム送信直前にtextareaからinput hiddenに値をセットし直し、その値で正規表現チェックをかければ改行を考えなくて良くなると考えて検証。

### フォームのコード
```html:
<form action="" method="post" enctype="multipart/form-data" onSubmit="setHiddenText();">
-------(中略)------
  <textarea id="contact_text" name="contact_text">\{contact_text\}</textarea>
  <input type="hidden" name="field[]" value="contact_text">
  <input type="hidden" name="contact_text:v#required">
  <input type="hidden" id="contact_text_hidden" name="contact_text_hidden" value="">
  <input type="hidden" name="field[]" value="contact_text_hidden">
-------(中略)------
</form>
<script>
function setHiddenText() {
  let val = $('#contact_text').val();
  val = val.replace(/\r?\n/g,"");
  $('#contact_text_hidden').val(val);
}
</script>

```
※該当の正規表現チェックの際、エラーメッセージは出さないようにしています。


### 管理画面での設定変更
正規表現チェックのフィールドの値を「contact_text」から「contact_text_hidden」へ変更する。

### 成功！
上のコードと管理画面の設定変更で意図した挙動になる。
(改行OKで指定したワードのいずれかが含まれていたらエラーにする)

単語については管理画面から設定ができるため、エンジニアでなくても追加・削除が可能になっています。

## 備考
もっと簡単にスパム対策する方法あるかもしれないです。
GAS＋LINE NotifyのよるConnpassの新着・更新情報の通知

# はじめに
この記事は2021年Advent Calendar[身の回りの困りごとを楽しく解決！【PR】Works Human Intelligence Advent Calendar 2021](https://qiita.com/advent-calendar/2021/works-hi)の14日目の記事です。

自分はGAS＋LINE Notifyで下記のような通知機能の実装をよくしてます。

 - Googleカレンダーから取得した本日の予定
 - 本日発売のマンガ

本記事では、そのうちの一つである「Connpassの新着・更新情報の通知」をご紹介します。

# 作ったきっかけ
自分が住んでいる福岡はIT大企業だけでなくベンチャー企業も多く、エンジニア同士の横のつながりも非常に深い土地で、コロナ禍になる前は頻繁に勉強会が開催されていました。
単純な自分自身のスキルアップだけでなく、様々なエンジニアの方々との関係性も深めたいと思い、このアプリを作成しました。

現在は、対面での勉強会の開催はまだ難しい状況ですが、オンラインでの勉強会は頻繁に開催されていますので、今でも大活躍出来ていると思っています。

# アプリの説明
## 前提
以降の内容は、下記知識がある人を前提とした説明となっています。

- LINE Notifyの環境構築の知識がある人
- Google Apps Script(GAS)の環境構築の知識がある人

## アプリの概要
1. Connpass公式の[イベントサーチAPI](https://connpass.com/about/api/)を利用し、指定キーワードで検索
2. 本日更新があった記事のみをピックアップ
3. LINE Notifyで通知

## ソースコード
GitHubで公開しています
https://github.com/macochin/searchConnpass

## アプリ環境設定の流れ
1. LINE Notifyのトークンを発行
2. 自身のGAS環境に、上記GitHubのソースコードをコピペ
3. GASの「プロジェクトのプロパティ」にて、LINE Notifyのトークンを **「LINE_NOTIFY_TOKEN」** で設定
   1. なぜか最新エディタではプロパティの設定ができないため、「以前のエディタを使用」をクリックし、一時的に旧エディタに戻して設定する
4. トリガーでGASを起動する時間帯を設定

## 実行結果
こんな感じです
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16977/86552c41-118e-76ec-112a-863da07722c2.png">


# 最後に
Web APIが公開されていれば、GAS＋LINE Notifyパターンは色々使えるものが多いと思います。
特にGoogleドキュメント等のサービスはGASとの連携が容易ですので、他にもいろんな使い道があると思いますので、是非参考にして頂ければ幸いです。
友達とのチーム開発を成功させるためには？〜仲良く学びを深めるために〜

#はじめに
エンジニアになりたての頃や、未経験転職からエンジニアを目指すなどの際に
**友人とチーム開発をしてプロダクトを作ろう**とされる方がいらっしゃると思います。

ちゃんと行うことができればとてもいい経験で、たくさんの学びがあります。

一方で、自分もこれまで友人とのチーム開発を実施し、うまく行ったことやいかなかったことがあるので
その背景を伝え、同じ失敗を繰り返さないように、アドバイスできる記事になればと思います。（__）

## 重要な前置き
※本記事は、比較的実務系経験が浅いかつ、趣味でのチーム開発を想定します。
※これまで一緒にチーム開発をしたメンバーには本当感謝しており、悪く言うつもりは一切ありません。自分の学びとして、こう言うふうにすべきだったと言う反省を記録したいと思い、まとめてあります。

## 失敗の原因と結果、今度どうするか？
<div align="center">
  <img width="300px" src="https://user-images.githubusercontent.com/67455005/146308967-d2a652c0-b4fb-4f26-9bfc-2abd5436f040.png">
</div>

失敗の原因とどうなったか、そしてその対策を端的に示します。

- 最初に目指すものが大きすぎた
初心者が多い中で、フロントエンドやバックエンドチームなどを分けたり、たくさん経験したことのない技術を選定した結果、要件定義だけで終わってしまうなどのことが起こりました。**さっさと手を動かす開発をすべきだった。**

- スケジュールが長すぎた
余裕を持ったスケジュールにしようとするがあまり、予定する期間が長くなってしまい、途中でだれてしまった。**ここまでにリリースをする、間に合わなかったら解散するorバッファを作って絶対にここで終わらせるなどを決めるべきだった。**

- それぞれの意思がバラバラだった
人によって本業に集中したかったり、本気でチーム開発に全力を注ぎたかったり、参加理由はバラバラです。熱量とも言えると思いますが、それがバラバラだったために、途中抜けしてしまうメンバーがいました。（原因は他にもあったかもですが）**最初に、やり切る意思やモチベーション維持の方法を考えるべきだった。**


## やっておいてよかったこと、今後もやる場合はおすすめの方法
<div align="center">
  <img width="300px" src="https://user-images.githubusercontent.com/67455005/146309742-37b65594-9489-49ad-bae2-5f690a66596b.png">
</div>

- 1人ベテランの方や、慣れている方に参加してもらう
その人におんぶに抱っこにならないようにすることは大事ですが、本当に全員が詰まった時に相談できる人を開発メンバーとして入ってもらうと良いと思います。**全員の学びも増えます**し、本当に詰んだ時に救われます。

- ベースは全員が慣れているフレームワークや言語を選定する
何か新しいことをチーム開発をきっかけに学ぶのは良いことですが、全員が知らないものをベースにすると、キャッチアップも必要ですしコードがカオスなことになります。**あまりにも言語特有のエラーにハマってもモチベーションが下がってしまう**ので、ベースは全員が慣れているものにして、ちょっと学びになるものを盛り込む方が良いと思います。

- 開発環境とGitFlowやプルリクなどのテンプレを整備する
OSの違いで最初にストレスを生んでしまうことは避けたいです。（3人Macで1人Windowsで、Windowsの人がエラー多発して寂しい思いをするなど...）**Dockerなどを駆使するのも良いでしょう。また、コードを書く以外の部分に関しても最初に整備をしておき、気持ちの良い開発フローを**作っておくのが大切だと思いました。

- 完成後にどうするか、運用のお金を含めて最初にゴールを決める
完成が一つのゴールですが、やっぱり作ったら運用してみたいと思うのも自然です。誰が運用するのか、お金は誰が支払うのか、万が一大きな問題が起きた時にどう責任を取るのか、そういった開発完了後のことも想定しておいた方が、**後々トラブルがないと思います**。

## まとめ
もし、自分が友人とチーム開発をするとしたら、以上のことに気をつけて行いたいと思います。
友達とのチーム開発は楽しく、学びも多いと思いますが、やっぱり限られた時間を投資してみんなで行うものだと思います。

仲良くトラブルなく開発を進めるためにも、相手のことを思いやると同時に、最初に決めるべきところはがっちり決めるのも大切だと考えています。
AppGoatでメニューが一部表示されない問題はキャッシュクリアで何とかなりました！

これはシーエー・アドバンス Advent Calendar 2021 14日目の記事です。
前回の記事は @syk_nakayama さんの 「[BurpのIntruderを遅延開始する方法](https://qiita.com/syk_nakayama/items/54452afad1194de643dc)」 でした。
明日の記事は @k_bobchin さんです。

完全にタイトルで完結してしまっています。

こんにちは。
シーエー・アドバンス（CAAD）技術統括本部セキュリティチームの @asami-H-Ishi です。
社内（グループ会社含む）サービスの脆弱性診断に関わる業務を行っています。
開発未経験で入社して6年目で、現在は脆弱性診断前の対象調査を担当する「支援チーム」を立ち上げ、診断作業の効率化を図っています。

今回は、セキュリティチーム全体で取り組んでいる毎週の勉強会で先月から触り始めた「AppGoat」について、ちょっぴり困ったことがあったので何をして解決したかをまとめました。
結論はタイトルどおりなのですが、お時間ある方は最後までご覧ください…！

# AppGoatとは
IPAが提供している、脆弱性体験ツールです。
https://www.ipa.go.jp/security/vuln/appgoat/
上記ページで導入方法など説明していますので、関心がおありの方は見てみてください！

# わたしに起こった「困ったこと」
手順通り、他のチームメンバーと同じようにWindowsPCにダウンロード、インストールをしたはずなのに、脆弱性一覧のリンクが一部無効になっていました。
脆弱性一覧は下記のとおりです。

1.	クロスサイト・スクリプティング
2.	SQLインジェクション　
3.	CSRF(クロスサイト・リクエスト・フォージェリ)
4.	ディレクトリ・トラバーサル
5.	OSコマンド・インジェクション
6.	セッション管理の不備
7.	認証制御や認可制御の欠落
8.	HTTPヘッダ・インジェクション
9.	バッファオーバーフロー　
10.	クリックジャッキング　
11.	メールヘッダ・インジェクション　
12.	その他の脆弱性(システム情報漏えい等)

ところが、わたしの手元では、「ディレクトリ・トラバーサル」以外のメニューへのリンクがありませんでした。
隣の席のチームメンバーの手元では、普通に全メニューリンクが効いていて、学習を進められているのに！　ディレクトリ・トラバーサルしかできない！

# 解決方法
AppGoatはインターネットへの接続を切った状態で、ブラウザでローカルに落としたツールを開いて学習します。
ブラウザのキャッシュをクリアしたら、それまで表示されていなかったメニューリンクが全て表示されるようになりました。
タイトル通りです。キャッシュクリアです。
※あっという間に直ってしまい、スクショ撮る暇もなかったのでパッとしなくてすみません。。

# おわりに
その後、特に再現していないので、何が原因だったんだろうな〜とぼんやり考えながら毎週AppGoatで脆弱性の学習(復習）をしています。
また何か不具合が生じたら、ひとまずキャッシュクリアしてみようと思います。

少なくともうちのチームメンバー10人中、この状態に陥ったのはわたし1人だったので、あまりいないかもしれませんが、
同じような状態になって困ってしまった人がいたら、キャッシュクリアしてみてください！

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

それではみなさん健康第一で、よいクリスマス、よい新年をお迎えください！
マンガの台詞をネガポジ判定してみた[Python]

# 概要
- Huggingface Transformersを使って、台詞がポジティブorネガティブの感情分析をしたいと思います。
- Huggingface Transformersとは？
  - 自然言語理解や自然言語生成の最先端の汎用アーキテクチャと何千もの事前学習済みモデルを提供するライブラリです。
  - 他に「テキスト分類」「質疑応答」「要約」などができるようです。

# 今回使う台詞は？
- マンガの台詞は以下の2つのサイトから選んでいます。
   - [漫画の名言をランキングで紹介！王道の台詞からネタ系迷言まで【2021年版】](https://ciatr.jp/topics/317301)
   - [中毒性抜群!! 声に出して読みたくなる『ジョジョの奇妙な冒険』カッコイイ名言・迷言ベストまとめ](https://www.animatetimes.com/news/details.php?id=1625130166)

# コード（GoogleColabで実行）

- Huggingface Transformersのインストール

```python
!pip install transformers
```

- 感情分析を実行

```python
from transformers import pipeline 
from transformers import AutoModelForSequenceClassification 
from transformers import BertJapaneseTokenizer 

# パイプラインの準備
model = AutoModelForSequenceClassification.from_pretrained('daigo/bert-base-japanese-sentiment') 
tokenizer = BertJapaneseTokenizer.from_pretrained('cl-tohoku/bert-base-japanese-whole-word-masking') 
nlp = pipeline("sentiment-analysis", model=model, tokenizer=tokenizer) 

# マンガの台詞
# マンガの台詞
manga_list = ["“海賊王”に！！！おれはなるっ！！！！",
              "あきらめたらそこで試合終了ですよ……？",
              "計画通り",
              "お前はもう 死んでいる",
              "生殺与奪の権を他人に握らせるな！",
              "さすがディオ！ おれたちにできない事を平然とやってのける そこにシビれる！ あこがれるゥ！",
              "我がドイツの医学薬学は世界一ィィィ！",
              "『てめーは、おれを怒らせた』",
              "だが断る",
              "吐き気をもよおす『邪悪』とはッ！ なにも知らぬ無知なる者を利用する事だ……!! 自分の利益だけのために利用する事だ… 父親がなにも知らぬ『娘』を!! てめーだけの都合でッ！ 許さねえッ！ あんたは今 再びッ！ オレの心を『裏切った』ッ！"]

# 感情分析の実行
for manga in manga_list:
    print(nlp(manga))

# 感情分析の実行
for manga in manga_list:
    print(nlp(manga))
```

# 実行結果

- labelはポジティブ・ネガティブ、scoreは0.5~1で評価されるようです。

- 4,9,10の台詞はネガティブと分析されました。
- 予想としては、「生殺与奪の権を他人に握らせるな！」「『てめーは、おれを怒らせた』」はネガティブと判定されそうでしたが、意外にもポジティブと判定されました！

```
[{'label': 'ポジティブ', 'score': 0.9633078575134277}]
[{'label': 'ポジティブ', 'score': 0.8562269806861877}]
[{'label': 'ポジティブ', 'score': 0.9065709710121155}]
[{'label': 'ネガティブ', 'score': 0.9287938475608826}]
[{'label': 'ポジティブ', 'score': 0.6454976797103882}]
[{'label': 'ポジティブ', 'score': 0.6881616711616516}]
[{'label': 'ポジティブ', 'score': 0.9514427185058594}]
[{'label': 'ポジティブ', 'score': 0.9115254282951355}]
[{'label': 'ネガティブ', 'score': 0.7114869952201843}]
[{'label': 'ネガティブ', 'score': 0.5508970022201538}]
```

# 感想
- Huggingface Transformersと使うことで、簡単に日本語による感情分析を試すことができました。


# 参考にしたサイト

- [【Python】日本語による感情分析をTransformersで行う](https://self-development.info/%E3%80%90python%E3%80%91%E6%97%A5%E6%9C%AC%E8%AA%9E%E3%81%AB%E3%82%88%E3%82%8B%E6%84%9F%E6%83%85%E5%88%86%E6%9E%90%E3%82%92transformers%E3%81%A7%E8%A1%8C%E3%81%86/)

- [Huggingface Transformers 入門 (10) - 日本語の感情分析](https://note.com/npaka/n/ne0adde2d7ae8)
Dynamics 365 Finance and Operations ~ パーソナライズ（個人ビュー）・保存されたビュー ~

おはこんばんちは。
Dynamics 365 に限らずなのですが、とりあえず ERP ってイケている UI/UX を見たことがないんですが、私だけでしょうか。
（イケている必要があるのか問題はありますが）

当然セキュリティロールが効いていれば有る程度絞り込まれた機能だけ表示させることができますので、見やすくはなります。
ただ、権限の問題は別途ありますが、モジュール内の Form までいくと、その中で表現されるリストはパーソナライズなどで必要なフィールドを取捨選択しないといけません（フィールドや設定値を変えることができないものもありますが）。

例.PO画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2375815/1d53236b-9705-8496-aa04-c9d03dd73a10.png)

Ctrl + Shift + P でパーソナライズ用のツールバーが出現 （各設定項目は[こちら](https://docs.microsoft.com/ja-jp/dynamics365/fin-ops-core/fin-ops/get-started/personalize-user-experience#personalization-tools)を参照してください）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2375815/a001d197-1460-6550-6817-d9f848a408b3.png)

色々パーソナライズの機能を試してください。ちなみに、Power Apps のアプリもこんな感じで埋め込むこともできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2375815/4e8294dd-b686-0c54-0657-415c5ad8ffc1.png)

好みのパーソナライズ設定が出来たら、以下から保存（デフォルト設定にもできます）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2375815/15e32cc1-ac82-719f-c39a-695275f340ae.png)

このパーソナライズを他のユーザとも共有することができます。（2021年Wave2より法人ごとにビューを設定することができます）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2375815/5771698f-f7ab-a860-741a-8a24580ff3e3.png)

https://docs.microsoft.com/ja-jp/dynamics365-release-plan/2021wave2/finance-operations/finance-operations-crossapp-capabilities/improved-legal-entity-support-saved-views
ハードリンクとかシンボリックリンクってなんぞや(初心者向け)

Linuxを勉強していたら出てきた、「ハードリンク」とか「シンボリックリンク」
初見では意味がわからなかったので、自分なりに解釈してまとめてみます。

## 参考にした書籍
本当にお世話になった導入書です。基礎の基礎を学ばせていただきました。

https://www.amazon.co.jp/1%E9%80%B1%E9%96%93%E3%81%A7LPIC%E3%81%AE%E5%9F%BA%E7%A4%8E%E3%81%8C%E5%AD%A6%E3%81%B9%E3%82%8B%E6%9C%AC-%E7%AC%AC3%E7%89%88-%E5%BE%B9%E5%BA%95%E6%94%BB%E7%95%A5%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-%E4%B8%AD%E5%B3%B6%E8%83%BD%E5%92%8C-ebook/dp/B07TD1TTYJ

## ファイルとiノード
ファイルは、**iノード**(index node)で管理されています。iノードには、ファイルサイズや最終更新日時、アクセス権情報や、ディスク上のどの場所にファイルの内容が書き込まれているか、といった情報が記録されています。

全てのファイルやディレクトリには、それらを管理するiノードが存在します。iノードを見れば、ファイルの属性がわかり、ファイルの内容にアクセスできるというわけです。lsコマンドに**-i**オプションをつけて実行すると、iノード番号を確認できます。

この仕組みを図書館で例えるなら、図書管理カードです。図書管理カードには書名、著者名、ページ数や、その本が図書館のどの棚に保管されているか、といった情報が書き込まれています。

利用者は図書管理カードを見て、目当ての本が図書館にあるのかどうか、またどこの棚に保管されているのかを調べることができるという仕組みと同じです。

## ハードリンクとは
iノード番号とファイル名の対応付けを**リンク**と言います。**ハードリンク**とは、1つのiノードに複数のファイル名をリンクさせることです。ハードリンクを作成するには**ln**コマンドを使います。

### パーティション
1つの物理的なディスクを論理的に複数に分けた領域のことを**パーティション**という。

iノードはパーティションごとに管理されているため、ハードリンクは異なるパーティション間で作成することができません。パーティションが異なると、同じiノード番号であっても、ファイルの実体は別々となります。

## シンボリックリンク
シンボリックリンクはファイルに別名をつける仕組みのことです。言い換えると、ファイルやフォルダに対する注文を代わりに受け付けて本来のファイル中継する役目をしているものです。lnコマンドに**-s**オプションをつけて実行するとシンボリックリンクを作成できます。

## 元のファイルを削除するとどうなるのか
リンクの元となっているファイルを削除するとどうなるのでしょうか。

答えは、ハードリンクの場合だと同じようにアクセスできますが、シンボリックリンクの場合だとアクセスするとエラーになってしまいます。
シンボリックリンクはあくまでファイルへのポインタ(ファイルの参照先)を格納しているに過ぎないので、参照先がなくなってしまうわけですから、「そんなファイルは存在しないよ」と怒られてしまうわけです。
AtCoder001をやった(Java)

AtCoder001をやった。
URL張り付けてて思ったけど、昔ってAtCoderの各問題の末尾は**abcxxx_[数字]**なんですね。。

##[A](https://atcoder.jp/contests/abc001/tasks/abc001_1)
引き算によって積雪を求める問題。
単純に1つ目の入力値から2つ目の入力値をひいてあげればよい

```
import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        // Your code here!
        Scanner scan = new Scanner(System.in);
        ArrayList<String> list = new ArrayList<String>();
        
        while (scan.hasNextLine()) {
            String str = scan.nextLine();
            list.add(str);
        }
        
        System.out.println(Integer.parseInt(list.get(0)) - Integer.parseInt(list.get(1)));
    }
}
```

##[B](https://atcoder.jp/contests/abc001/tasks/abc001_2)
問題文に記載のパターンを条件として書き出して、入力値がどれに該当するかを探せばよい。
問題文中にも記載の通り**5km より大きく 6km 未満**みたいなものは入ってこない。

```
import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        // Your code here!
        Scanner scan = new Scanner(System.in);
        ArrayList<Double> list = new ArrayList<Double>();
        
        list.add(Double.parseDouble(scan.nextLine()) / 1000);
        
        if(list.get(0) < 0.1){
            System.out.println("00");
        } else if(list.get(0) >= 0.1 && list.get(0) <= 5){
            if(list.get(0) * 10 < 10){
                System.out.println("0" + Integer.toString((int) (list.get(0) * 10)));    
            } else {
                System.out.println(Integer.toString((int) (list.get(0) * 10)));    
            }            
        } else if(list.get(0) >= 6 && list.get(0) <= 30){
            System.out.println(Integer.toString((int) (list.get(0) + 50)));
        } else if(list.get(0) >= 35 && list.get(0) <= 70){
            System.out.println(Integer.toString((int) (list.get(0) - 30) / 5 + 80));
        } else {
            System.out.println("89");    
        }
    }
}
```
※本当は変数VVを用意すべきなのかもしれない


C問題いけそうな気がする。
いつかC問題もJavaで解きたいな。
データサイエンティストになって1年 思ったことまとめる

##あいさつ
こんにちは！
データサイエンティストになって1年が経ちました。
実際、経験をしてみて前後で想像と異なることが多々ありました。

今後、このデータサイエンティストというキャリアを目指される方に向けて
ざっくりとですが
実際との差分を埋めるため、この記事を書きたいと思います。


##1年で伸びたと思うスキル
・日本語文章力
・話す、聞き取り力
・Pythonコーティング力
・データ構造把握能力

何をやるにしてもベースの日本語が必要なので必然的に伸びた感じはします　笑

##データサイエンティストこういう人が向いているかも
・発表、話すのが好きな人
・相手の課題を話しながら探り、提案をできる人
・研究を一通りやったことがあり課題解決までのプロセスを理解している人

濃い1年を過ごして
1年で結構変わるのだなと実感をしました。

##未経験からデータサイエンティストになるためのスキル
ちょっと前まで未経験からデータサイエンティストになるには
**SQL**で経験を積むのが最短ルートだと考えていましたが

最近では**Tableau**も引き合いも強かったりするので、
他の人との差別化しやすいのではないかと思います。

Tableauライセンスは学生無料なので一度試していただければと

##自分のこれから

実は一度分析案件をやってみたのですが
正直やっている間はどちらかというと辛いことが多く、楽しむことができませんでした。

データ基盤の構築だったり、運用保守の方が向いているし
楽しいなと思うことが多かったですね

これは実際に案件に携わってみて気づいたことです。
早めに気付けて良かった！

今後のキャリアとして一度方向転換を行い
データ基盤や開発をメインでやっていこうかと思っています。

もちろん最終的には
分析の案件も再チャレンジをしたいですが、一度軸足固めてからかなと考えています！
短いですが今回は以上になります〜
Jリーグの対戦成績をPythonでデータ分析してみた

# 概要
kaggleにあるサッカーJリーグの2017年から2019年シーズンの全対戦成績から、Pythonを用いて、多方面に分析してみます
ソースコードの記載がありますが、初心者向けにコメント多めです

# 前提
1.kaggleのサイトからcsvファイルをダウンロードします
https://www.kaggle.com/yosafatvs/meiji-yasuda-jleague-1-20182019-league-log
※kaggleの会員登録必要です

2.Python3の環境構築
https://qiita.com/search?q=python+%E7%92%B0%E5%A2%83%E6%A7%8B%E7%AF%89

3.サッカー愛があること

# 実装編
最初にダウンロードしてきたcsvファイルを読み込んで、中身を見てみましょう

```python:analysis.py
# -*= encoding: utf-8 -*-
import pandas as pd

# csvファイルのパス(任意)
csv_path = '/Users/app/csv/J. League Data Site.csv'

# csvファイルを読み込む
data = pd.read_csv(csv_path)

# 出力
print(data)
```
ここで、ターミナルで「python3 analysis.py」を実行すると
このような出力がされます
![スクリーンショット 2021-12-13 23.04.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603047/0040fb18-a148-c34d-b4f9-56101e35e082.png)
"Year"の列を見ると2017年から2019年にかけて、全試合の勝敗が入ってそうです

"Year"の列だけで出力してみましょう

```python:analysis.py
# "Year"の列だけ出力
print(data['Year'])
```
![スクリーンショット 2021-12-13 23.13.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603047/3c183804-4bd7-0c19-4efd-783ce83afab6.png)

csvファイルのヘッダーの真ん中の方にある観客数（Att.）も出力できます

```python:analysis.py
print(data['Att.'])
```

次に、ホームチームの1試合当たりの平均得点と
3シーズン分のホームチームの合計得点を計算してみましょう
ヘッダの"Score_Home"項目を設定します

```python:analysis.py
# ホームチームの1試合当たりのゴール数を計算（Score_Homeより）
print(data['Score_Home'].mean())

# ホームチームのゴール数の合計を計算（Score_Homeより）
print(data['Score_Home'].sum())
```

![スクリーンショット 2021-12-13 23.23.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603047/236b1e01-88e6-7151-3a4a-fddd6bfdbece.png)
1試合あたり1.4点くらい入ってますね
3年間のホーム側の合計得点は1271なので、1シーズンで約400点も入っていますね

2022年の王者川崎フロンターレの2017年〜2019年のホームゲームの成績を出力してみましょう
ヘッダの項目が"Home"で、値が"Kawasaki-F"で絞ります。

```python:analysis.py
# 川崎フロンターレがホームの場合
print(data.set_index('Home').loc['Kawasaki-F'])
```

![スクリーンショット 2021-12-14 20.55.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603047/ef58b985-fbfe-5cbb-0d27-262b18fa4781.png)
ほとんど勝っていますね。強いな〜

↓2019年に限ると、あんまり勝っていないですね
![スクリーンショット 2021-12-14 20.56.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603047/e1d361e6-5b85-4fce-9776-81a6d4313c2a.png)

川崎の3シーズンのホームの試合の平均得点、平均失点を見てみましょう

```python:analysis.py
# 川崎フロンターレがホームの試合のスタッツ
print(data.set_index('Home').loc['Kawasaki-F'].mean())
```
![スクリーンショット 2021-12-14 21.00.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603047/b5e4cc67-0273-9984-29fa-082332fe0fda.png)
1試合平均得点は、1.96点、ほぼ2点！
1試合平均失点は、0.94点、1点未満！
多くの試合が2-1で勝っている成績
強さが分かります

そして1試合平均観客数は2万2867人
多いですね！


最新のソースコードはGitHubで公開しています
https://github.com/heihei-wooooo/analysis-j-league


# 備考
有料ですがfootystatsというサイトでJリーグや欧州のプレミアリーグ、ラリーガなどの詳細なデータがあります。
APIが公開されているので、サッカー好きなPythonエンジニアはクリックしてみてください！
https://footystats.org/jp/
ESP32の書き込み

ESP32用に2SC945(私の世代の汎用TR)を使って、書き込み回路をつくてみたのですが、上手く動かず、ずいぶん調べたのですが原因がわからず、仕方なくバラしてボタンにしてみました。

![ESP-BUTTON.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/7f9c8420-f277-57b1-0d40-8f3cd6a6d9e3.png)

![写真（2021-12-14 8.02） #2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/dd481d92-096a-c2a5-fb0c-2f9ae7a3346d.jpeg)

リセット(EN)だけ押すとシリアルに以下のような出力があります。

```
$ sudo cu -l /dev/cu.usbserial-DA00WSMM -s 115200
Connected.
ets Jun  8 2016 00:22:57

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:1044
load:0x40078000,len:8896
load:0x40080400,len:5828
entry 0x400806ac
```

GPIO0を押しながらリセットすると以下のようになります。

```
ets Jun  8 2016 00:22:57

rst:0x1 (POWERON_RESET),boot:0x3 (DOWNLOAD_BOOT(UART0/UART1/SDIO_REI_REO_V2))
waiting for download
```

これでやっと書き込みができるようになりました。

ESP8266でも書き込みに苦労したような記憶があり、どうもESPとは相性悪いです。

M5とか買えばこんなことないのかもしれませんが、貧乏なのでM5とか高価なものは買えません。ガジェットは1K以内が自分の決まりごとになっています。
筋トレは全てを解決する

## おい、プログラムのことを書けと言ったよな？

はい、これはプログラムには直接は関係ないかも知れません。しかし、多くのエンジニアを幸せにするものだと信じています。

## テレワークにより破壊されているもの

テレワークは正義！そう思っていた時期が、僕にもありました……
テレワークを続けると、どんどん鬱になります。正直ヤバかったですね。
筋力がどんどん衰えていって、やる気が失せていって、そのうち「何で生きてるんだろう？」となりました。
そう、テレワークは**人の心を破壊します。**

## 科学に頼ろう

パワハラも受けてないのに鬱になった。なんだこれは。死にたい。いや理由無いのに何で。おかしいだろ。これは病気だ。
で、いろんなお医者さんに行った結果。
「**男性ホルモン**……フリーテストステロン値が11.4ぐらいは最低なければならないのに、**あなたには5.4しかないです**」
病気である、と診断された。
テストステロン。**社会性のホルモン**と言われる。つまり自分が「今の俺の生活に社会性なくなったな」と思ったら、引っ込んでしまうホルモンらしい。テレワーク環境だとこのホルモンが非常に低下する。そしてそのホルモンの数値が低下すると発生するうつ症状がある。
**なので、実はここを読むような多くのギークが必要としている情報なのだ。**

## 科学が出した治療法

###「テストステロン充填法」
不足したなら足せばいい。テストステロンを筋肉注射。保険も効いて格安で定期的にちゅーっと注入する事ができる。
ただ、これは緩和にしかならない。根本の治療とはならない。

## 人類の英知が生み出した治療法

### 「筋トレ」
人の血液内の「フリーテストステロン」は、腿の前側を刺激すると筋肉内で製造される。それは**通常時の100倍**というものすごい強い効き目だ。
すでに「腿の前側を刺激してフリーテストステロンを通常の100倍の状態にして、腕立てをして、筋力がよりつくかどうか」など数々の論文の基本的なエビデンスとして使われている。
そう、とりあえず腿の前側を鍛えればいいというのは**数々の論文により実証済だ**。スポーツジムにはそれっぽい器具がある。でも、そればかりするとすぐ**膝がアウト**になるので膝の裏側もやるか、**素直にバーベルかついでスクワットする**かだ。

## 筋トレをやれば治るのか

自分は２週間で鬱を脱出しました。危なかった。筋トレしたらマジでこの変な鬱な症状から脱出した。多くのエンジニアよ。このテレワーク環境下、**スポーツジムに行くことをおすすめする。**いやマジで。

## 治ってからのエンジニア生活

### 対ストレス耐性が半端なくなった
これはいい所と悪い所がある。とりあえず怒られても平気になったので、今まで上司にパワハラされて鬱だ死のう状態になりそうな場面でも「あーこういうコミュニケーションしか取れないのかこのひと……可愛そうだな」と思えるようになった。その人を刺激せず、かつちゃんと仕事をすすめるにはどうすればいいか、理性的に考える事ができるようになった。選択肢の中に平気で「叱られる」を入れ、実行して、叱られるのを対価に様々な有利な立場を手に入れる。
逆に弱点といえば、危機感が無いので、ありとあらゆるものが隙だらけ。SEとしては致命的な弱点だ。ここはしかし経験でカバーできる。

### 肝臓の値が全部正常値に
これは全然狙ってなかったのだけど、全く食事制限しなかったのにも関わらず肝臓の値が全部Aになった。エンジニア初めてずっとCとかDだったのに。どうやらテストステロンに肝臓を良くする成分があるらしい。マジか。
# 筋トレはいいぞ
結局技術的な事は何一つ語ってなかったが、今のここを読む人に非常におすすめしたいのである。よく判らない原因不明な鬱に悩まされている方への救いの手となる事を希望している。
辞書のキーに変数を使う方法 mshmura


元々の辞書

``` test.py
dic = {"りんご":200,"みかん":200,"なし":100}
```

通常、変数を使用して辞書を作ろうとするとエラーになります...と思ったらエラーになりませんでした。以前はエラーになっていたはずなのに変わったのかな...

```
new_key = "メロン"
dic[new_key] = 700
print(dic)
```
出力結果

```
{'りんご': 200, 'みかん': 200, 'なし': 100, 'メロン': 700}
```

下記コードを使おうと思っていたのですが、不要でしたね。

```
new_key = "メロン"
v = 700
exec('dic["{}"] = {}'.format(new_key, v))
print(dic)
```
Railsエンジニアの比較用Phoenixコマンド集


※この記事は [fukuoka.ex Elixir／Phoenix Advent Calendar 2021](https://qiita.com/advent-calendar/2021/fukuokaex) 14日目の記事です。
 
前日13日は [@the_haigo](https://qiita.com/the_haigo) さんが 12日の
[LiveViewとNxで画像処理](https://qiita.com/the_haigo/items/236e0e3c6cfbbd12799a) に引き続き書いて下さるようです。
LiveViewやNX系の記事は個人的に興味ありありです。

## 目的

個人的に普段Railsを使っていると、なかなかフルスタックのフレームワークを新しく・・という機会もなかなか訪れないもので、せめて序盤のコマンドだけでもすんなりこなしたいという目的で備忘録的に書いております。

## 対象

Railsは大体OKの方。
Elixir興味ありありの方。
Ruby3.0.1 Rails6.1.4

## 環境

MacOS 11.6(BigSur)
Elixir 1.12.2 (compiled with Erlang/OTP 24)
Phoenix v1.6.0
Postgres 14.1

## コマンド表

|  |rails|phoenix|
| ---- | ---- | ---- |
|FWのインストール| gem install rails | mix archive.install hex phx_new |
|アプリの作成<br>(db:pg)| rails new rails_sample -d posgresql| mix phx.new phx_sample |
| プロジェクトに移動 | cd rails_sample | cd phx_sample |
| DBの作成 | rails db:create | mix ecto.create |
| webpackerの設定 | yarn install --check_files | |
| サーバーの起動 | (rails) rails s<br>(webpacker) bin/webpack-dev-server | mix phx.server |
| DBの設定ファイルの場所 | vi config/database.yml | vi config/dev.exs |
| モデルの作成<br>tb:users col:name | rails g model User name:string | mix phx.gen.schema User users name:string |
| モデルの場所 | vi app/models/user.rb | vi lib/phx_sample/user.ex |
| マイグレーションファイル作成<br>tb:users col:name | rails g migration users | mix ecto.gen.migration create_user |
| マイグレーションファイルの場所 | vi db/migrate/xxxxxxxx_create_users.rb | vi priv/repo/migrations/xxxxxxxx_create_user.exs |
| nameカラムを追加 | [![Image from Gyazo](https://i.gyazo.com/eea3f821bd3ccd69416763c9102f40e7.png)](https://gyazo.com/eea3f821bd3ccd69416763c9102f40e7) | [![Image from Gyazo](https://i.gyazo.com/2c1df1086d54cc78445aa6a57dfd2214.png)](https://gyazo.com/2c1df1086d54cc78445aa6a57dfd2214) |
| マイグレーション | rails db:migrate | mix ecto.migrate |
| ロールバック | rails db:rollback | mix ecto.rollback |
| リセット | rails db:migrate:reset | mix ecto.reset |
| ルーティングの確認 | rails routes | mix phx.routes |

## コマンド表

| コンソールコマンド | rails | phoenix |
| ---- | ---- | ---- |
| コンソールの起動 | rails c | iex -S mix |
| 新規作成(blank) | User.new | PhxSample.User.changeset(%PhxSample.User{}, %{}) |
| 新規作成 | User.new(name: "taro") | PhxSample.User.changeset(%PhxSample.User{}, %{"user" => "taro"}) |
(ぼちぼち追加予定)

## 参考資料

https://qiita.com/pojiro/items/1339b85fd4e53f2c9542

https://elixirschool.com/ja/lessons/ecto/changesets



## おわりに

今年もあっという間にアドベントカレンダーの季節がやってきてしまいました。

業務でなかなかもくもく会にも出られず残念な後半戦でしたが、今年はElixirやメタバース関連でトップエンジニアの方々の思想や引き寄せを目の当たりにできるという非常に貴重な1年となりました。
そして、少しずつではありますが、Elixieのメンテナンス性のありがたさがわかってきたような気が。

来年も頑張ろ・・・。

## 次は・・・

15日目[@MzRyuKa](https://qiita.com/MzRyuKa) さんです。
過去にLiveViewの記事やNervesなども扱われているようなので、どんなジャンルのものが来るのか楽しみですね。よろしくお願いいたします。
【AWS】アカウントエイリアスとは？IAMで作成する手順を紹介

こちらでIAMユーザー作成方法も紹介しております。

https://qiita.com/u_skayyyyy/items/395bbe670a33f87c35de


## アカウントエイリアスとは？

AWSのアカウントエイリアスとは、簡単に言うと、AWSのアカウントID（番号12桁）の代わりに使用できる「文字列」です。

AWSでは、ルートユーザーおよびIAMユーザーが一つのAWSアカウントを共有して使用するため、この共有アカウントのことを「AWSアカウント」と呼びます。

ルートユーザーがログインするときは、「Eメール」＋「パスワード」でログインできます。

一方、IAMユーザーがログインする場合は、下の画像の様に、「**アカウントID（番号12桁）**or **アカウントエイリアス**」＋「ユーザー名」＋「パスワード」の3つが必要です。


この番号12桁が覚えにくいので、代わりに「カスタムの文字列」を割り当てます。

これが「**アカウントエイリアス**」です。
![Screen Shot 2021-12-13 at 7.51.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1975528/682dd2af-cbf5-7117-9bb5-83c2e33b48a4.png)


## アカウントエイリアスの作成手順

1. まず、ルートユーザー（またはエイリアス作成権限のあるアカウント）でログインします。
2. IAMのマネジメントコンソールから、左サイドバーの「ダッシュボード」ページに行きます。
3. 画面右側に「AWSアカウント」の情報が載っています。
現状は、エイリアスがIDと同じで、IAMユーザー用のログインURLにはアカウントID（番号12桁）が含まれている状態です。
4. 「アカウントエイリアス」の「作成」ボタンがあるので、クリック。
![Screen Shot 2021-12-08 at 8.51.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1975528/6ef3eaf5-1dd1-3af3-a833-8ccead1bfe92.png)
    
5. ここで、アカウントエイリアスも名付けます。
![Screen Shot 2021-12-08 at 8.52.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1975528/bd2a7c97-b6b1-2950-a5aa-4d13a506a7de.png)
    
6. 「アカウントエイリアス」は「アカウントID」に割り当てられるものなので、ユニークでないと画像のようにエラーがでます。
![Screen Shot 2021-12-08 at 8.56.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1975528/eaf2888e-a5c0-0a30-a5ea-7a04ae41a72d.png)
    
7. 再挑戦。
![Screen Shot 2021-12-08 at 8.57.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1975528/a1e1193c-0ccb-adb2-e02d-0f52b836c26a.png)

1. 無事作成できると、ダッシュボードの画面右側に新しい「アカウントエイリアス」とIAMユーザー用の「ログインURL」が表示されます。
![Screen Shot 2021-12-08 at 8.58.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1975528/4b7bb2e5-b5c8-6dda-4da0-053de6cb2c10.png)

2. 先程のログインURLに行くと自動でアカウントエイリアスが入力されていますが、このURLがなくても「アカウントエイリアス」を覚えていればログインに困ることはありませんね。
![Screen Shot 2021-12-08 at 9.00.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1975528/edebf187-fd76-7625-76d4-ef9651df426a.png)

3. ログインすると画面右上には「ユーザー名＠アカウントエイリアス」が表示される様になりました。（エイリアスを設定していないと12桁のIDになっています。）
![Screen Shot 2021-12-08 at 9.34.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1975528/35959819-0c32-3d06-9d7a-ff21f132aacc.png)
slackのセクションの活用

# 自己紹介

こんにちわ、 [IVRy](https://ivry.jp) で、バックエンドエンジニアをしている島筒です。
といっても私個人としては、フリーランスのエンジニアで、IVRyの開発に関わっております。
IVRy以外にも、懇意にしているクライアンからの受託開発などを行なっています。

# 本題

皆さん、slackを活用していますか？
IT系のエンジニアの方々は、slackを利用していることも多いと思いますが、チャンネルが増えすぎて、あーもう！ってなることありますよねw
そこでセクションが有効活用できます。

# セクションとは

https://slack.com/intl/ja-jp/blog/uncategorized/intl-ja-jp-simpler-more-organized-slack
2020年3月にリリースされた機能で、もうとっくに知ってるよという方もいらっしゃるかもしれませんが、そういう方は読み飛ばしてください。

セクションとは、slackのチャンネルをグルーピングする機能です。
slackのチャンネルは、雑談や連絡から、重要な案件のチャンネルまで、多数のチャンネルがあると思いますが、通知が多くなり、重要な通知を見落としてしまうことがありますが、グルーピングすることで見落としてを減らすことができます。

# 私のグルーピング例

重要なセクションのivryは開きっぱなしにし、残りはクローズしてます。
「チャンネル」も開いてることが多いかな。

* ivryセクション
    * 最重要
* チャンネル
    * よく見る（default）
* times
    * timesチャンネルの説明は、[こちら](https://note.com/ryogaskywalker/n/n6f5532888e82)
* reacji
    * reac字チャンネルの説明は、[こちら](https://slack.com/intl/ja-jp/help/articles/360000482666-Slack-%E7%94%A8%E3%83%AA%E3%82%A2%E3%82%AF%E5%AD%97%E3%83%81%E3%83%A3%E3%83%B3%E3%83%8D%E3%83%A9%E3%83%BC)
* etc
    * 見落としても良いやつ

![スクリーンショット_2021-12-14_6_58_24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115974/3f2880c9-e9ab-c830-1fe1-ff8f542e3180.png)


# TIPS

よく使うショートカットの紹介

1. チャンネル移動： ⌘Command + T（Windows: Ctrl + T）
1. スレッド表示： ⌘Command + Shift + T（Windows: Ctrl + Shift + T）
pgstattupleやpgstatindexに条件句は使えない

>SELECT * FROM pgstatindex('schema.t_hoge_key')

【疑問】
上記のように「common.t_hoge_key」の情報を得る際、「schema.t_hoge_key」のみに限定せず、Where句などによって全件や、特定条件といった範囲データを抽出が可能かどうか。
【結論】
pgstatindex 関数など、pgstattuple モジュールから提供される関数には「対象とする
リレーションの名前（スキーマ修飾可）」もしくは「OID」を指定することがマニュアル
に明記あり。関数の結果内に、カラム名やインデックス名などの情報をもたないので、全件出力やWHERE句による条件指定などはできない。
Keep Calm

## Long, long ago. 

[Issueを立てていただくよろこび - Qiita](https://qiita.com/e99h2121/items/246ec2354809ca0bfa4b)
本来、Issue は機能強化のヒントだと書きました。

[回答とは目線を合わせること - Qiita](https://qiita.com/e99h2121/items/7899b7055ed7c89a0c56)
焦っている問い合わせの回答にはとにかく、目線を合わせて答えようと書きました。


## Keep Calm..

もう一つ、実は最も大事なことがあります。なんでしょう？

**落ち着くことです。**
この週末に一部界隈には大きな話題がありましたが、この最中でもしみじみ、ホントだなあ～と思ったTweetがいくつかあります。

https://twitter.com/bettersafetynet/status/1469470284977745932?s=20

> (DeepL翻訳)
> あなたがこの状況にいる場合、あなたは何をすべきかを示します。
>
> **1. 落ち着いてください。パニックになる必要はありません。**


https://twitter.com/SiliconShecky/status/1469809342635458560?s=20

> (DeepL翻訳)
>
> **休憩、食事、睡眠、そして一般的に自分自身を大切にすることを忘れないでください。そうすることで、より良い結果が得られます（そして、より効果的です）。**


## It's okay to say. 

[AwesomeなSRE読み物集 - SRE Resources「On call」の章を中心に - Qiita](https://qiita.com/e99h2121/items/ae338e099f2ba765aed4)

何が起こっているのか分からなかったり空気がよく分からなかったりする状況はどこにでもあります。そんなとき[イギリスの政府デジタルサービス](https://ja.wikipedia.org/wiki/Gov.uk) では、こんなルールを掲げていると言います。

https://gds.blog.gov.uk/2016/05/25/its-ok-to-say-whats-ok/

> （新人さんへ、）もちろん、給料の支払い方法やプリンターの使い方、ラインマネージャーが誰なのかなど、公式なことはすべて伝えられます。

> しかし、公式ではないことを伝えるのは難しい。知っていて損はないが、誰も教えてくれないような内容です。おそらく最初の数カ月で知ることになるでしょうが、たいていは偶然に知ることになるでしょう。誰かが何気なく口にしたことで、「え、何？となってしまいます。

> （中略）

> そこでふと思ったのですが、このような非公式なことは、初日に前もって説明しておいたほうがいいのではないかと思いました。何がOKなのかを明確にする必要があるのかもしれません。何年もここにいる私たちが当たり前だと思っていることを明確にするために。

> そこで私たちのチームは、**「やってもいいことリスト」** を作成しました。


https://govdesign.tumblr.com/post/144909646023/download-the-poster-its-ok-to

![](https://64.media.tumblr.com/efba61875c6840522631ee28ca25ef56/tumblr_o7qo29WYqN1vqjzzho1_1280.jpg)


## Now. 

ということで、「師走こそもう休みたいし、こういう猫を眺めて過ごしていいのだよ」が、我々の It's okay to say になると良いなと思うというお話でした。これこそ最大のインシデント対応... 第一声はKeep Calmにしたいですね。

[Google Apps Scriptで、Slackに(またはLINE Botにも)ﾈｺﾁｬﾝをpostする - Qiita](https://qiita.com/e99h2121/items/56b9d7a9db88e0b4744a)
[無料で使える (癒やされたいだけの) 公開APIリスト: ねこ、いぬ、キツネ、柴犬、ジブリ - Qiita](https://qiita.com/e99h2121/items/6d5cc72679f43aa37be2)

![](https://cdn2.thecatapi.com/images/ace.gif)

![](https://cdn2.thecatapi.com/images/bd7.gif)

![](https://cdn2.thecatapi.com/images/82r.gif)


以上です～。
音ゲー周回を少しでも楽にしたいのでbot作った(JavaScript編)

#はじめに
私がプレイしているスマホゲームのコミュニティでは、「Discord」というアプリを使っています。すごく簡単に言えば「ゲーム向けLINE」といった感じです。
Discordの一つの特徴として、ボットを導入することが出来るという点があります。有名どころで言えば「Shovel」ですね。(テキストチャンネルに書いた文章を通話内で読み上げてくれるボット)
そこで自分でもボットを作ることが出来ないか？と考え、行動に出ました。

##何を実装したい？
私がプレイしているスマホゲームでは、音楽ゲームでありながらも「周回要素」が存在しています。そしてこの周回を同じコミュニティのプレイヤーの皆さんと行うのですが、この際発生する動作は以下の通りです。

**スマホゲーム**
・ゲーム内でルームを作成する(この際、部屋番号が発行される)
・周回メンバー全員がルームに入ったら、ただひたすら譜面を叩く

**Discord**
・「通話チャット」で部屋番号を伝える
・部屋番号を「部屋番号チャンネル」に記入する
・場合によっては、通話チャンネルの名称も変更する(例:周回【12345】)

これだけ見るとボットなんて使わなくていいレベルの動作にも見えますが、本気で高速周回をする場合は一緒に周回するメンバーが1~2時間おきに変わるため、場合によってはこの動作をその都度やらなければいけません。
またバグでルームが散ってしまうこともあるので、その際もこの動作をしなければいけないわけです。
Discord側は操作時間にして1分もかからない単純作業ですが、もちろん楽に越したことはありません。「ボットを用いてDiscord側の操作を簡略化したい！」という思いのもと、今回のボット開発がスタートするのでした…

##開発環境・言語の選択
作るものがざっくり決まったところで、実装の仕方を調べてみることにしました。しかしこんな動作のボットを作っている方はあまりおらず、参考記事が全く見つからない。どうすれば実装できるかはすべて自分で考えるしかなさそうでした。
とりあえずJavaScriptかPythonで作ろうと考えていました。というのも、ボットの作り方を調べたところ「Discord.js」と「Discord.py」というのが出てきたためです。
今回はとりあえず基礎を作ること大前提に調べ進めました。そんなところ以下の記事を見つけました。

https://note.com/exteoi/n/nf1c37cb26c41

初回なのでこちらを参考にしてボットの基礎を作ろう！ということで決定したので、言語にはJavaScriptを選択しました。(執筆者の方には大変感謝しております

##ソース
さて、前置きが長くなってしまいました。
今回書いたソースコードは以下になります。

```JavaScript:server.js
    if (message.channel.id == "通話チャットのID") {
      let text = message.content;//通話チャットに書かれた文字列を取得
      var roomCheck = text.slice(0, 6);//文字列の前から6文字切り取る 理由は後述
      NumberChange(roomCheck);//全角を半角にする関数を呼び出す

    if (!isNaN(roomNumber) && roomNumber.length == 5) {//数字のみの5文字であれば名前を変更するなどの処理を行う
      client.channels.get("部屋番号チャンネルのID").send(roomNumber);//番号を送信する
      let VoiceCh = "周回【" + roomNumber + "】";
      let RoomCh = "部屋番【" + roomNumber + "】";
      client.channels.get("周回ボイスチャンネルのID").setName(VoiceCh);//周回チャンネルの名称変更
      client.channels.get("部屋番号チャンネルのID").setName(RoomCh);//部屋番チャンネルの名称変更
      return;
    }

function NumberChange(Text) {//全角を半角に変換する処理
  Text = Text.replace(/[０-９]/g, s => {
    return String.fromCharCode(s.charCodeAt(0) - 65248);
  });
  roomNumber = Text;
}
```
※各チャンネルのIDは、詳細設定の「開発者モード」をオンにしてチャンネルを右クリック→IDをコピー で取得できます

![sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2100617/ef6390df-67b6-4d24-3ba5-8d44ba0deb39.png)


###6文字切り取る理由
```JavaScript
   var roomCheck = text.slice(0, 6);
```
今回対象にしているスマホゲームで用いる部屋番は5桁で統一されているので、あえて6文字切り取ります。こうしないと、間違えて「123456」と打った際に前の5文字を切り取る処理になってしまい誤って変更処理が行われてしまうからです。

###全角数字を半角数字にする処理
```JavaScript
  Text = Text.replace(/[０-９]/g, s => {
    return String.fromCharCode(s.charCodeAt(0) - 65248);
  });
```
この処理は無くても大丈夫なのですが、全角と半角のどちらで入力した際も変更後の表示が統一されると見やすいかなと思い導入しました。

##改善案
現行の仕様だと、5桁の数字「のみ」を入力した場合しか変更処理が行われないため、例として「部屋番号12345です！」のように、文字列のどこかに5桁の数字がある場合も変更処理を行ってくれるプログラムにいつか改良出来たらいいなと思っています。(今のところ困った前例はないけど)

##おわりに
今回実装した処理は難しいものではないのですが、どこにも参考記事が無いものを自分で頑張って実装するというのは中々に楽しく、ほんのちょっとしたスキルアップと(遊びとはいえ)実用性のあるボットを作ることが出来て本当に良かったと感じています。

機会があればPython版の記事も上げたいです。

**最後まで読んでくださりありがとうございました！**
GASでSpreadSheetのデータをBigQueryに入れる

# この記事について
[CyberAgent PTA Advent Calendar 2021](https://adventar.org/calendars/6450)
13日目の投稿です。

# やること
GAS(Google Apps Script)からBigQueryのテーブルを作成して、データを挿入する。
[Connected Sheets](https://cloud.google.com/blog/ja/products/g-suite/connected-sheets-is-generally-available)はめちゃ便利だが、有料プランなので今回は使わない。

# BigQueryのテーブルを作成する
## テーブル定義を決める

```javascript
var projectId = 'XXX';
var datasetId = 'XXX';
var tableId = 'XXX';
var table = {
  tableReference: {
    projectId: projectId,
    datasetId: datasetId,
    tableId: tableId
  },
  schema: {
    fields: [
        {name: 'Time', type: 'string'},
        {name: 'Name', type: 'string'},
        {name: 'Email', type: 'string'}
    ]
  },
  timePartitioning: {
    'type': 'DAY',
    'expirationMs': 31557600000 // 1year
  }
};
```
`Time`, `Name`, `Email`のフィールドで、データ追加した日付で[テーブルパーティショニング](https://cloud.google.com/bigquery/docs/partitioned-tables)。1年経ったら消す。

分割テーブルにすることで、データ量が多くなったときに全データをスキャンする必要がなくなるので、コスト削減になる。

## テーブルを作成
```javascript
BigQuery.Tables.insert(table, projectId, datasetId);
```
GASにはBigQueryのライブラリが用意されているので、`Tables.insert`で作成。

# SpreadSheetのデータをBigQueryに入れる
下記のようなデータを想定

| Time | Email | Name |
| --- | --- | --- |
| 2021-10-06T23:57:36+0900 | test@gmail.com | test |

```javascript
function insertToTable() {
  var range = sheet.getDataRange();
  var blob = Utilities.newBlob(convCsv(range)).setContentType('application/octet-stream');
  var job = {
    configuration: {
      load: {
        destinationTable: {
          projectId: projectId,
          datasetId: datasetId,
          tableId: tableId
        },
        skipLeadingRows: 1 // ヘッダ行は無視
      }
    }
  };
  job = BigQuery.Jobs.insert(job, projectId, blob);
}
 
function convCsv(range) {
  try {
    var data = range.getValues();
    var ret = "";
    if (data.length > 1) {
      var csv = "";
      for (var i = 0; i < data.length; i++) {
        for (var j = 0; j < data[i].length; j++) {
          if (data[i][j].toString().indexOf(",") != -1) {
            data[i][j] = "\"" + data[i][j] + "\"";
          }
        }
        if (i < data.length-1) {
          csv += data[i].join(",") + "\r\n";
        } else {
          csv += data[i];
        }
      }
      ret = csv;
    }
    return ret;
  }
  catch(e) {
    Logger.log(e);
  }
}
```
`sheet.getDataRange()`でスプレッドシートのデータを取得。
`Jobs.insert`でデータを追加する。

# BigQueryのテーブルを削除する

```javascript
BigQuery.Tables.remove(projectId, datasetId, tableId);
```
Windowsユーザーのためのhosts書き換えショートカット

DNSやロードバランサー、新しくサーバーの構築をすると私はよくhostsを書き換えて事前接続確認をしたりします。
ローカル環境の構築でもローカルのhostsを書き換えるというのはよくやります。

Windowsの場合hostsファイルはかなり深い場所にあるので、パスをたどるのに苦労する上、セキュリティ的に保護されているファイルなので、簡単には変更できません。

ということで変更のためのショートカットファイルを作成することで対応します。

新規ショートカットの作成で、パスを以下のように指定します。

```
%windir%\system32\notepad.exe "C:\Windows\System32\drivers\etc\hosts"
```

もちろんお気に入りのエディタがあればそれを指定します。
大抵のエディタは引数にファイルをとることができます。
私はVimが好きなので、Vimにしています。

作ったショートカットのプロパティを開き、管理者モードで実行するように設定するだけです。

![qiita_20211214_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131218/71e567d0-64b9-d37d-b062-d55582be6363.png)


あとは利便性を考えて、スタートメニューとかにショートカットを移動させておきましょう。
ユーザーのスタートメニューは以下になります。

```
%appdata%\Microsoft\Windows\Start Menu
```

![qiita_20211214_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131218/cfc21a8b-918c-6039-8fa9-6af36fde4d6b.png)


するとスタートキーを押下後、hostsと入力するだけで、開けるようになります。

私の周りの人は毎回hostsファイルをたどって開いているので、もう少し楽な方法あるのになと思っています。

まぁhostsを書き換える人なんて、DNSの設定確認とか、ロードバランサーの設定確認とか、ローカル環境にバーチャルホストいっぱい立ててる人とか何でしょうが。。。