OmniAICreator/Qiita-1.07M huggingface dataset:
GoogleAppsScriptを使ってGoogleCalendarの予定をLINEに通知する

#はじめに
日頃からGoogleCalendarを使っていて, 毎朝当日の予定をLINEに通知してくれたら便利だと思い, 色々調べてみました. 
そこで見つけたのが, **GoogleAppsScript**です. 
GoogleAppsScriptはgoogleが提供しているサービスなので, 他のgoogleのサービスとの相性抜群ということで今回は使用していきます. 

#LINENotify
まずはLINEへ通知するために, LINENotifyのアクセストークンを取得しましょう. 
方法は以下を参照してください. 
[pythonでLINENotify使ってみる](https://qiita.com/pontyo4/items/10aa0ba0a17aee19e88e)

#GoogleAppsScript
GoogleドライブからGoogleAppsScriptへアクセスしてください. 
<img width="672" alt="スクリーンショット_2019-06-26_22_00_43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319132/aab705ad-2089-90c9-5ba8-de8275c5222d.png">

すると, エディタが開かれるので以下のコードを貼り付けてください. 
このときコード内に取得したアクセストークンを入れましょう. 

```JavaScript
var lineToken = "ここにアクセストークン";
 
function main() {
  var calendars = CalendarApp.getAllCalendars();
  var text = Utilities.formatDate(new Date(), 'JST', 'yyyy/MM/dd') + "\n";
 
  for(i in calendars) {
    var calendar = calendars[i];
    var events = calendar.getEventsForDay(new Date());
 
    if( events.length > 0 ) {
      text += "◆ " + calendar.getName() + "\n";
    }
 
    for(j in events) {
      var event = events[j];
      var title = event.getTitle();
      var start = toTime(event.getStartTime());
      var end = toTime(event.getEndTime());
      text += start + ' - ' + end + " " + title + '\n';
    }
 
    if( events.length > 0 ) {
      text += "\n";
    }
  }
 
  sendToLine(text);
}
 
function sendToLine(text){
  var token = lineToken;
  var options =
   {
     "method"  : "post",
     "payload" : "message=" + text,
     "headers" : {"Authorization" : "Bearer "+ token}
 
   };
   UrlFetchApp.fetch("https://notify-api.line.me/api/notify", options);
}
 
function toTime(str){
  return Utilities.formatDate(str, 'JST', 'HH:mm');
}
```

メニューバーの「実行」からmain関数を実行すると, LINEへ通知されます. 
<img width="1083" alt="スクリーンショット_2019-06-26_22_07_03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319132/8505915b-b81e-3046-0ecf-253de1b7e68f.png">


定期的に実行するためには, メニューバーの下の時計マークから設定しましょう. 
<img width="400" alt="スクリーンショット_2019-06-26_22_09_38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319132/54a4de73-7133-9b6c-3de7-97f81e0c5b28.png">
「トリガーを追加」から細かい設定をすれば, あとは勝手に実行してくれます. 
<img width="861" alt="スクリーンショット_2019-06-26_22_11_32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319132/8a35e574-cd76-57be-caba-d6bdbc594325.png">

うまくいけば, こんな感じで通知してくれます. 
便利ですね. 
<img width="289" alt="スクリーンショット 2019-06-26 22.14.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319132/91348f59-5f8f-8ed8-86ca-8e7957956632.png">
2019/06/26 UNIX 系のコマンドやvimtutorを使うための準備

##1. SlideShareの使い方

[SlideShareの解説](https://ferret-plus.com/8483)

[それでもSlideShareを使うべき理由](https://tekunabe.hatenablog.jp/entry/2018/08/05/slideshare)

##2. E37: No write since last change (add ! to override)

- viでテキストを編集して終了しようと「:wq」キーを入力したらタイトル通りのメッセージが表示されて困った


[参考にさせていただいた記事](https://docs.oracle.com/cd/E19683-01/816-3946/editorvi-9/index.html)

```terminal
#ファイルを変更していない場合のviの終了のコマンド
:q   

#ただしファイルを変更していた場合、メッセージが表示されて実行できない
No write since last change (:quit! overrides)

#なので変更内容を破棄して終了するなら
:q!

#Returnキーを押す
```
##3. ファイルを探す

[参考にしたサイト](https://tech.nikkeibp.co.jp/it/article/COLUMN/20060228/231052/)

```terminal
$ find / -name ファイル名-file
```

##4. VirtualBox VMから抜け出せない

1. commandキーを押す
2. 1本指でタッチしてカーソルを動かす

##5. rootユーザーにログインしないで管理者権限を行使したい

[スーパーユーザーについて](https://qiita.com/shinpeinkt/items/74f1a4607293349ce731)

## 6. vimtutorを使いたい

[vimをインストールするときに参考にした記事](https://qiita.com/yukichii/items/03498038c3a691aea03c)

[ソースビルドでのインストールで参考にした記事](https://note.mokeco.in/67/)

[rootユーザーから一般ユーザーへの切り替えで参考にした記事](https://webkaru.net/linux/su-command/)

[-bash-4.2$について](https://cha-shu00.hatenablog.com/entry/2017/05/24/212016)

[vimtutorの日本語版を使いたい時には参考にした記事](https://vim-jp.org/vimdoc-ja/usr_01.html)

##その他の参考にしたサイト
[ソートとは](https://wa3.i-3-i.info/word14885.html)

[grep系のコマンド](https://qiita.com/kenju/items/a73a3610011391eee252)

[尊師スタイル](https://qiita.com/midorinokimi/items/8da9f234e96f1fa0f9e0)
簡単なCI環境を立ててみよう

# このページについて
個人用CI環境を構築した際に調べた事やった事を書き溜めておく


|構成要素|サービス|
|:--|:--|
|サーバ|[KAGOYA CLOUD メモリ2GB 2コア](https://www.kagoya.jp/cloud/vps/price/#vps_header)|
|開発環境|eclipse 4.11.0|
|ソース管理|Github|
|ミドルウェア管理|Docker|
|CIツール|Jenkins|
|単体テスト|Spock|

# eclipseとGithubの連携

 * [Eclipse 上から新規プロジェクトを Github に Push する方法](https://qiita.com/cotrpepe/items/7cafaacb538425a78f1f)

# LinuxサーバへDockerをインストール

[Docker入門（第一回）～Dockerとは何か、何が良いのか～](https://knowledge.sakura.ad.jp/13265/)
[CI環境構築手順(Jenkins + SonarQube + Nexus)](https://qiita.com/ogu1101/items/a04e77f0fca03fec8197)

>$ yum install -y yum-utils device-mapper-persistent-data lvm2
>$ yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
>$ yum makecache fast
>$ yum install docker-ce
>$ systemctl start docker
>$ systemctl enable docker

# Jenkinsのインストール

 * [Jenkinsをdocker上に構築](https://qiita.com/legitwhiz/items/e6ac1f5a94f09ff2bb1d)

> docker run -p 8080:8080 -p 50000:50000 jenkins/jenkins:lts

# OpenJDK,Gradleの追加

 * [JenkinsでOpenJDKを自動インストール](https://qiita.com/boushi-bird@github/items/49627b6a355ea2dfa57a)

※上記設定後、Jenkinsを再起動する

# GithubとJenkinsを連携

 * [GitHubとJenkinsのWebhook連携](https://qiita.com/tz2i5i_ebinuma/items/528ea5163bb2df379852)

# 改行コードがCRLFになっていてJenkins on KAGOYA(Linux)で実行エラーが発生した

Gitにはcore.autocrlf、core.safecrlfという改行設定があり、inputにすることで解消。

 * [Git の改行コードでハマった話](https://obel.hatenablog.jp/entry/20170828/1503910703)
 * [コミット、チェックアウト時に改行コードを自動変換する](https://maku77.github.io/git/settings/autocrlf.html)

# 以下、Spockについて

## とりあえずこれ見ておけ的な資料
 * [JavaのテストGroovyでいいのではないかという話](https://www.slideshare.net/disc99_/javagroovy-65909637)

## JUnitと比較したSpockの可読性メリット
 * [JavaのユニットテストにSpockを適用する](https://qiita.com/euno7/items/1e834d3d58da3e659f92)

## アノテーションチートシート
 * [Spockノウハウの簡単なまとめ](https://qiita.com/it__ssei/items/16f7ffd640dac221d9f9)

## 実行サンプル
 * [Groovy, Spockを使ってJavaのテストを作成する](http://hkou.hatenablog.com/entry/2018/04/15/111242)
 * [Spring boot 1.4 testing with Spock](https://qiita.com/AHA_oretama/items/55bbde42cfa4bdbf50a0)
 * [Spring Boot + SpockでRestControllerのテストをサクッと書く](https://qiita.com/NagaokaKenichi/items/7236a68e0cdb77a97479)

## Groovyチュートリアル
 * [Apache Groovy チュートリアル](https://koji-k.github.io/groovy-tutorial/index.html#)

## SpringBoot RestAPIに適用する
 * [APIのテストを書くならspock + RESTClientが便利かも(Groovy)](https://qiita.com/kimromi/items/2368d6f004666e87b313)
 * [GroovyでJSONを簡単に処理する](https://qiita.com/ligun/items/b27fe1d1e742b9d90914)
 * [Grabアノテーションが効かない場合](https://stackoverflow.com/questions/18173908/error-compiling-a-groovy-project-using-grab-annotation)

## ところで、単体テストは何処を目指せばよいのだろう
 * [テストカバレッジ100%を追求しても品質は高くならない理由と推奨されるカバレッジの目標値について](https://qiita.com/bremen/items/d02eb38e790b93f44728)
Visual Studio 64bit 版で、ファイルまたはアセンブリ、またはその依存関係の1つが読み込めませんでした





# 参考

[Visual Studio で 64ビット版のASP.NET を実行すると「ファイルまたはアセンブリ、またはその依存関係の1つが読み込めませんでした。間違ったフォーマットのプログラムを読み込もうとしました。」エラーが発生する (Visual Studioの使い方 Tips)](https://www.ipentec.com/document/visual-studio-2015-asp-net-runtime-error-in-64bit)
[Python] 多次元リストを複数キーでソートする

例えば、次のような２次元リストがあるとします。

```python
data = [['きゅうり',1,4],['いちご',2,6],['にんじん',2,1],['とうふ',1,0]]
```

上記のリストを下記のように、２次元目の第２引数と第３引数の要素を桁のようにみなして昇順にソートする方法を説明します。
2番目の要素で昇順にして、そのまま3番目の要素で昇順にするわけです。

```python
data = [['とうふ',1,0],['きゅうり',1,4],['にんじん',2,1],['いちご',2,6]]
```

#多次元リストを複数キーでソートする
今回、多次元リストのソートには、関数sorted()とlambda式というものを使います。

```python
data = [['きゅうり',1,4],['いちご',2,6],['にんじん',2,1],['とうふ',1,0]]
#昇順でソートする
sorted_data = sorted(data, key=lambda x:(x[1], x[2]))
print(sorted_data) #data = [['とうふ',1,0],['きゅうり',1,4],['にんじん',2,1],['いちご',2,6]]
```

昇順にソートできました！！

#おまけ
####降順にソートしたい場合

```python
data = [['きゅうり',1,4],['いちご',2,6],['にんじん',2,1],['とうふ',1,0]]
#降順でソートする
sorted_data = sorted(data, key=lambda x:(x[1], x[2]), reverse=True)
print(sorted_data) #data = [['とうふ',1,0],['きゅうり',1,4],['にんじん',2,1],['いちご',2,6]]
```

関数sorted()の第３引数にreverse=Trueを追加するだけです。

####itemgetterを使う場合

```python
from operator import itemgetter

data = [['きゅうり',1,4],['いちご',2,6],['にんじん',2,1],['とうふ',1,0]]
#昇順でソートする
sorted_data = sorted(data, key=itemgetter(1, 2))
print(sorted_data) #data = [['とうふ',1,0],['きゅうり',1,4],['にんじん',2,1],['いちご',2,6]]
```

コードがスッキリしますね！
Amazon ECS の「タスクのスケジューリング」利用時の注意点

## 概要

* [Amazon ECS タスクのスケジューリング](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/userguide/scheduling_tasks.html)は、CloudWatch イベント機能を使っているので、CloudWatch イベント利用時の注意点を考慮する必要がある。

## cron式はUTC
参照：[タスクのスケジューリング (cron)](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/userguide/scheduled_tasks.html)

* 例えば、cron式で cron(0 10 * * ? *) と設定した場合、毎日 10:00 (UTC) に実行する。
* 日本時間で毎日 10:00 に実行させるには、cron式で cron(0 1 * * ? *) と設定する（JST=UTC+9）。


## スケジュールされた期間に対して同じルールを複数回トリガーする可能性がある
参照：[1 つのイベントに応じてルールが複数回トリガーされました](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/events/CWE_Troubleshooting.html?fbclid=IwAR2rYOjBfgh0N6n_zt_7mnyjdWt5gqj7Ez2xSkEABV23vRdNAAcUYWAI4Ug#RuleTriggeredMoreThanOnce)

* タスクの起動タイプ(ECS/Fargate)によらず、上記挙動が発生する可能性がある。これは、CloudWatch Events の仕様なので、どうしようもない（実際にAWSサポートに確認済）。
* この挙動が発生した場合、複数回トリガーがするということは、複数回タスクが実行されコンテナが作られるということ。
なので、タスク内の処理は重複実行に対応した形で実装しておく必要がある。
【自分用メモ】Pythonでの正規表現

#正規表現とは
　文字列を1つのパターン化した文字列で表現する表記法のこと。
　正規表現を使用して、文字列をパターン化した文字列に置き換えることで、文字列の検索や置換えを行うことができる。

#例題

```py
import re

source = "Hatsune Miku"

result = re.match("Hatsu", source)
if result:
    print(result.group())    
#matchはオブジェクトを返す。
#オブジェクトから、マッチした部分を取り出す(str)には
#.group()関数を使う
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374781/8b3bb901-e4ff-8785-775f-50ba004c71d4.png)

ここでは、"Hatsu"がパターン、"Hatsune Miku"がソース文字列で、match()は、ソースの先頭がパターンになっているかどうかをチェックする。

パターンとソースを比較する方法はmatchだけではない。他にも次のようなメソッドを使える。

・search()は、最初のマッチを返す。（ある場合）
・findall()は、重なり合わないすべてのマッチのリストを返す。（ある場合）
・split()は、パターンにマッチしたところでソースを分割し、部分文字列のリストを返す。
・sub()は、置換文字列引数をとり、ソースのうち、パターンにマッチするすべての部分を置換文字列に置き換える。


#人名からMiss.を抽出してみた

```py
source = "Graham, Miss. Margaret Edith"

title_search = re.search(' ([A-Za-z]+)\.', source)
#' ([A-Za-z]+)\.'は、英文字（[A-Za-z]）1文字以上でかつ .が語尾につくものを表す。

if title_search:
    print(title_search.group()) 
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374781/c0af4d84-4c91-ed08-0100-d659c919d92c.png)



【参考・引用】
・[入門 Python 3(Bill Lubanovic (著), 斎藤 康毅  (監修), 長尾 高弘  (翻訳))](https://www.amazon.co.jp/%E5%85%A5%E9%96%80-Python-3-Bill-Lubanovic/dp/4873117380)
・https://techacademy.jp/magazine/15635
・https://qiita.com/wanwanland/items/ce272419dde2f95cdabc
・https://qiita.com/sea_ship/items/7c8811b5cf37d700adc4
Ruby メモ①オブジェクト〜変数


###◆オブジェクト
　ひとことでいうと、何らかの「モノ」。
　rubyで扱える全てのデータは「オブジェクト」と呼ばれる。
　文字列オブジェクト、数値オブジェクト……
###◆メソッド
　ひとことでいうと、何らかの「命令」。

```ruby:ruby.rb
 puts "こんにちは"

 # こんにちは と出力
```
　例えば、これは文字列オブジェクトに、**「ターミナル上に出力せよ」**と命じている。

###◆返り値
　オブジェクトやメソッドが処理されたあとの最終的な値。
　例えば、数字を計算した場合…

```ruby:ruby.rb
 12 + 5
 # ==>17
```
 この場合であれば、返り値は**「17」**となる。

```ruby:ruby.rb
 puts "こんにちは"
 # こんにちは と出力
 # ==> nil
```
　この場合であれば、出力される「こんにちは」ではなく「**nil**」が返り値となる。
　なぜ「nil」なのかは分からない。
　（nil : 存在しない　という意味）
###◆変数
　ひとことでいうと、モノを入れておく「箱」。
　この「箱（変数）」に「モノ（オブジェクト）」を入れることで、「モノ（オブジェクト）」自体が扱いやすくなる。
　例えば、変数に文字列オブジェクトを入れてみる。

```ruby:ruby.rb
 name = "田中幸子"
 # 代入する。
```
　変数にオブジェクトを入れることを「代入する」という。
　変数に文字列オブジェクトを入れるときは「**=**」を使う。
　一見、「nameと田中幸子は等しい（同じ）」という意味に見えてしまうが、「nameという箱の中に"田中幸子"という文字列オブジェクトを入れていますよ」という意味である。
　
　変数の中に入っている文字列オブジェクトを出力させたいときは、
　**puts + 変数**
　を使う。　

```ruby:ruby.rb
 puts name
 puts name
 puts name

 ==> 田中幸子
     田中幸子
　　　田中幸子
```
　このようにすることで、**puts "田中幸子"** と何度も打たなくても、田中幸子をたくさん出現させることができる。

　ちなみに、変数の中身は何度も変更可能。
　プログラミングは上から下に向かって読まれるため、変更したい変数よりも下に変更後のコードを書くことで、変数の中身を変更することができる。

```ruby:ruby.rb
 # 変数に「田中幸子」を代入する
 name = "田中幸子"
 puts name # 「田中幸子」が出力される
 
　# 変数に「山田太郎」を再代入する。
 name = "山田太郎" 
 puts name # 「山田太郎」が出力される
```
Javaにメモリを意識した実装は必要か？

## はじめに
メモリに対する考えを相談したので学んだことの備忘録。
用語については自分が分かっている部分はそのまま書いている。
逆に使い方が間違っているようであればご指摘いただきたい（そして教えてほしい）。

## メモリ使用の意識

### クラスロードについて
main実行時（かその前main関数を持っているクラスがjvmに解釈されたとき）に、
関連するクラスを芋づる式にメモリ上にロードする。

### （疑問）クラスロードとかインスタンス生成とか…そこまで意識しなくてよい？
（捉え方によっては叩かれそうだが）**そこまで**意識しなくてよい。
なぜならばJavaという言語は実装者が（そこまで）メモリ管理を意識しなくてよい言語だから。
この辺りはwikipediaに書いてある。
[Java#ガベージコレクション - Wikipedia](https://ja.wikipedia.org/wiki/Java#%E3%82%AC%E3%83%99%E3%83%BC%E3%82%B8%E3%82%B3%E3%83%AC%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3)

メモリ管理を意識するのであればJVMの実装の話になってしまう。
（完全に管理したいのならそもそもCとかC++などを使うべき？）

### 末端のプログラマでもメモリを意識した方がいい点

##### staticフィールド（static変数）は必要以上に使わない。

staticフィールドの右辺は意識した方がよい。
staticフィールドはクラスロードの際に作成される。
右辺（初期化）に重い処理を入れてしまうとメモリの圧迫の原因になる。
インスタンス変数やstaticイニシャライザ、イニシャライザも同様に気を付けなければいけない。

##### インスタンス生成（new）はコストがかかることを意識する。

インスタンス生成はヒープを確保して、オブジェクトを生成する行為。
（インスタンス変数、インスタンスメソッド、イニシャライザの実行）
当たり前だが生成の度にコストがかかる。

##### （書き直し検討中）~~staticメソッドでいいものはstaticメソッドにする~~

副作用がないものは生成コストがかからないstaticがの方が良い。
ここで言う副作用とはインスタンスの状態に依存しないで作成できるかどうか。
いわゆるUtilクラスは積極的に使ってよいということが理解できた。
（mainメソッド実行時にクラスロードされているので生成コストがいらない）

※例：以下のような処理はインスタンスを生成するメリットがないのでstaticにする。

```java
public static int plus(int a, int b){
    retrun a + b;
}
```

##### immutableを意識する

immutable論争があるという話。
>immutableとは・・・
>immutable(イミュータブル:不変)とmutable(ミュータブル:変更可能)なオブジェクトのこと。

Javaで代表的なのは`String`、`LocalDateTime`など。
これについて肯定派と否定派が日夜熱い議論を交わしているらしい。

**肯定派：**
値の更新がされないことを保つことでプログラムが安全になる。
また新規にインスタンスを作成するとしても元のインスタンスは不要になるはずなので適宜コピーGCで解放されるであろうということ。

**否定派：**
インスタンスの無駄な生成コスト。
（書き直し検討中）~~メモリリークの危険。~~

開発者としては、Stringのように同じ値は同じ参照先を見るように実装できたら気持ちいいだろうが、そこまでロジックに落とすと大変なのでimmutableを意識するようにしていれば良いと思う。

### 今後、どう実装していけばよいか
そこまで深く考えなくても今まで通りメモリリークしないように実装すればよい。
例だと以下のようなことか。

- GCで拾ってもらえるように変数のスコープを意識する。
- 使わなくなった参照が残らないようにする。（あくまで実装上で）
- （不必要に）static変数を使わない

基本的にはJavaを使っている以上、メモリ管理はJavaに任せる。


### （おまけ）GCについて

コピーGCとフルGCがある。
GCログを出せる。（vmオプション）

##### さらに余談
開発しているシステムのGCログを見せてもらった。
ログでは、起動開始時に何回かfullGCが発生していた。
（昔は実行時にメモリ指定していたようだが何らかの理由により今はやめたらしい。テスト環境だったからかもしれない。）
使う最低ラインが分かっているのであればvmオプションの`-Xms`を指定してfullGCが起きないようにすればよいと思った。

GCについてはまた勉強したいと思う。

## おわりに
2週間くらい悩んでいたが自分の中でJavaのメモリについてはいったん収束した。
ネットの情報を探したり、色々な人に聞いたのだが自分の中でピンと来なかったので納得できるまでに時間がかかってしまった。
忙しい中、丁寧に解説してくれた現場のリーダーに大きく感謝。

## 記事リンク
@j5c8k6m8 さんがこの記事を読んでポエムを書いてくださったのでリンクを貼らせていただきました。
[Qiita - メモリを意識したプログラミング(実装)は必要か](https://qiita.com/j5c8k6m8/items/60c357f1876e46b4c6d4#_reference-056ae72ba97995e4fc8f)
読ませていただきましたが勉強になりました。

## 参考
[Qiita - OutOfMemoryError の調べ方](https://qiita.com/opengl-8080/items/64152ee9965441f7667b)
ドメインの死活監視 〜死活判定編〜

## 前置き

ドメインを立ててその上でサービスを運用する。
そこには複数のサードパーティーのサービスや、負荷分散対応を挟んだりする。

時々予期しない事態（サードパーティーの不具合、負荷分散側の機能アップデート、自分たちのポカとか）で、
知らぬ間に一部のページだけが機能しなくなっていた・・・なんてことがあります。

こうしたケースって、サーバ全体の異常ではないこともあって、
運用側での検知が遅れがちになりやすい気がします。どうしたものかなと。

だから、手間なく準備できる死活監視の仕組みを設けてみようかなと考えてみました。


## 何を使って監視をするか

curlはどうでしょうか。

http://curl.haxx.se/

誰でも手軽に対象との通信状態を検証できる便利なコマンド。
これで通信状態をチェックして、バッチ処理にまで落とし込んでみると良さそうです。


## 何をもって「死」「活」と判断するか

コンテンツの中身まで監視するとやることが非常に多くなるので、
シンプルに「リクエストに対するHTTPステータス」で判断するのがよろしいかと。

ざっくり判断であれば、以下のようになると思います。

|ステータス|概要|死活判断|
|:--|:--|:--:|
| 2xx系 | リクエストは通った。 | 活 |
| 3xx系 | リクエストは通り、別ページ等への遷移が発生した。 | 死 or 活 |
| 4xx系 | リクエストした先は存在しないページだった。 | 死 or 活 |
| 5xx系 | リクエストをサーバが処理できなかった。 | 死 |

2xx系は「活」。

3xx系も基本は意図した設計を行ってのリダイレクトなので、基本は「活」です。
ただ、こちらの想定と異なるリダイレクトがあったりすると、そこは「死」と見るべきです。

4xx系は見る場所によりますね。
存在しないコンテンツのリクエストでの4xxなら「活」だと思いますが、
あるはずのコンテンツのリクエストが4xxなら、それは「死」ですよね。

5xx系になると理由はどうあれ、それは「死」ですよね。

こんな具合に、HTTPステータスを見るだけでも、
ざっくりとした死活監視ならまぁ問題は無いかなと考えました。


## curl でHTTPステータスだけを取得しよう

普通にcurlを叩いてみます。

````
curl https://www.google.co.jp
<!doctype html><html itemscope="" …略
````

コンテンツをまるっととってくる。情報量が多すぎます。
欲しいのは、HTTPステータスだけですのでオプション指定で情報を削っていきます。

まず、ファイル出力時の進捗状況はいらない。→ -s
続いて、SSL接続での証明書エラーはスキップしたい。→ -k
あと、レスポンスボディもいらない。→ -o /dev/null
だけど、ステータスコードだけは取得したい。→ -w '%{http_code}\n'

````
curl -sk https://www.google.co.jp -o /dev/null -w '%{http_code}\n'
200
````

これで、HTTPステータスだけ取得できました。


## curlをシェルスクリプトに組み込む

死活監視の対象にしたいURLは、テキストでダダ書きにしておきます。
⇨ url.txt

````
https://google.co.jp
https://www.google.co.jp
https://www.google.co.jp/aaa
````

上記テキストはシェルスクリプトの同一なりに置いて、
以下のシェルスクリプトを準備しました。
⇨ domain.sh

````
while read url
do
    status=$(curl -sk "${url}" -o /dev/null -w '%{http_code}\n')
    printf "URL:%s / STATUS:%s\n" $url $status

    if [ ${status:0:1} = 2 ] ; then
        echo "OK"
    elif [ ${status:0:1} = 3 ]; then
        echo "OK"
    elif [ ${status:0:1} = 4 ]; then
        echo "WARNING"
    elif [ ${status:0:1} = 5 ]; then
        echo "ALERT"
    fi
done < ./url.txt
````

URLの一覧ファイルを読み込んで、curlで回していきます。
一旦、2xx はOK、3xx も（思うところはあるが今は）OK、4xx はWARNING、5xx はALERTとしています。
実行結果は以下となりました。

````
URL:https://google.co.jp / STATUS:301
OK
URL:https://www.google.co.jp / STATUS:200
OK
URL:https://www.google.co.jp/aaa / STATUS:404
WARNING
````

↑ひとまず期待動作だと思います。

この結果を「判定結果を誰かに伝える処理」まで準備できれば、
ドメインの死活監視として、最低限は機能してくれそうです。

あと、3xx系、4xx系は見るURL次第では「死」にも「活」にもなりますから、
そこは考慮できる実装に見直したいです。例外処理ももう少し足していかないと・・・。

やるべきことはまだまだありそうです。続きはまた次回。
（コードが全て仕上がったらgithubとかにでも載せていこうと思います）
LaravelでAmazon SQSのFIFOキューを使う方法

# はじめに
Amazon SQSには、標準キューとFIFOキューがあります。
Laravelに予め用意されているSQSの接続設定（標準キュー用）を使ってFIFOキューにメッセージを送ると、

`Error executing "SendMessage" on "https://sqs.ap-northeast-1.amazonaws.com/XXXXXXXXXXXX/hoge.fifo"`
`The request must contain the parameter MessageGroupId.`

となってしまうため、ちょっとした実装で回避します。

# 前提条件
- Laravel 5.8.24で動作確認しました。
- aws/aws-sdk-phpがインストール済であるものとします。
- Amazon SQSの設定については割愛します。

# 実装
１．既存のSqsQueueを拡張し、FIFOキューにメッセージを送るサービスを作成します。

```php:app/Services/SqsFifoQueue.php
namespace App\Services;

class SqsFifoQueue extends \Illuminate\Queue\SqsQueue
{
    public function pushRaw($payload, $queue = null, $options = [])
    {
        $response = $this->sqs->sendMessage([
            'QueueUrl' => $this->getQueue($queue),
            'MessageBody' => $payload,
            'MessageGroupId' => uniqid(),
            'MessageDeduplicationId' => uniqid(),
        ]);
        return $response->get('MessageId');
    }
}
```

２．既存のSqsConnectorを拡張し、FIFOキューに接続するサービスを作成します。

```php:app/Services/SqsFifoConnector.php
namespace App\Services;

use Aws\Sqs\SqsClient;
use Illuminate\Support\Arr;

class SqsFifoConnector extends \Illuminate\Queue\Connectors\SqsConnector
{
    public function connect($config)
    {
        $config = $this->getDefaultConfiguration($config);
        if ($config['key'] && $config['secret']) {
            $config['credentials'] = Arr::only($config, ['key', 'secret']);
        }
        return new SqsFifoQueue(new SqsClient($config), $config['prefix'] . '/' . $config['queue']);
    }
}
```

３．FIFOキュー接続用のサービスプロバイダを作成します。

```php:app/Providers/SqsFifoServiceProvider.php
namespace App\Providers;

use App\Services\SqsFifoConnector;

class SqsFifoServiceProvider extends \Illuminate\Support\ServiceProvider
{
    public function register()
    {
        $this->app->afterResolving('queue', function ($manager) {
            $manager->addConnector('sqsfifo', function () {
                return new SqsFifoConnector;
            });
        });
    }
}
```

４．作成したサービスプロバイダを登録します。

```php:config/app.php
return [
    // ...
    'providers' => [
        // ...
        App\Providers\SqsFifoServiceProvider::class,
    ],
];
```

５．FIFOキュー用の接続設定を追加します。

```php:config/queue.php
return [
    // ...
    'connections' => [
        // ...
        'sqsfifo' => [
            'driver' => 'sqsfifo',
            'key' => env('AWS_ACCESS_KEY_ID'),
            'secret' => env('AWS_SECRET_ACCESS_KEY'),
            'prefix' => env('SQS_PREFIX'),
            'queue' => env('SQS_QUEUE_FIFO'),
            'region' => env('AWS_DEFAULT_REGION'),
        ],
    ],
];
```

６．環境変数の設定例です。（東京リージョンに「hoge.fifo」というFIFOキューを作成した場合）

```text:.env
// ...
SQS_PREFIX=https://sqs.ap-northeast-1.amazonaws.com/XXXXXXXXXXXX
SQS_QUEUE_FIFO=hoge.fifo
```

７．最後に、使用例です。

```php
HogeJob::dispatch()->onConnection('sqsfifo');
```
---
FIFOキューを既定の接続として使う方法や、接続するFIFOキューを指定する方法は、他の接続の場合と同様です。
コンフリクトが解消できない！Resolve conflictsが押せない！！

# はじめに
共同開発を始めてコンフリクトに悩まされていたので
その中でもコンフリクトが解消できないパターンのコンフリクトに4回くらい遭遇し
なんどもメンバーの助けを借りてしまったので
いい加減覚えろ自分！！！
ということでqiita書きをします。
作業環境：visual studio code
　　　　：github Desktop

今回書くことは
![conflict.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346005/b2357c08-4a8c-298d-f38d-8d98edc8ba0a.png)

こちらです。

# コンフリクト解消ボタンが押せない問題
コンフリクト解消したいのに解消できないのを解消します。


## ローカルでコンフリクトを起こす
リモートデスクトップでコンフリクトは起こっていますが
ローカルではなぜか認識されていないので

masterに移動して
ローカルのmasterを最新の状態にします。

```
$ git pull origin master
```
では次にブランチを作業中のブランチにします。

```
$ git checkout 作業ブランチ
```
ローカルmasterにマージする

```
git merge master
```
するとvisual studio codeでコンフリクト起きてる箇所には丁寧に表記が変わっているので
あとは愚直に修正しています。

ローカル環境で該当箇所のエラーなどがないことを確認後
リモートブランチへPUSH!

以上です。
個人的なメモとして記録しておきます。

最後まで読んでいただきありがとうございました。
プリミティブ型と参照型の違い

メモ

# プリミティブ型（基本データ型）と参照型  
Javaの型は大きく分けて2種類あります。**プリミティブ型**と**参照型**です。
それぞれについてまとめてみました。

## プリミティブ型とは
以下の8つがプリミティブ型です。


|型   | 分類   | bit数  |  
|-----|-------|--------|
| boolean | 真偽値　| 1 |
| byte | 整数 |8|
|short | 整数 | 16 |
| char | 文字 | 16 |
| int | 整数 | 32 |
| float | 小数 | 32 | 
| long | 整数 | 64 |
| double | 小数 | 64|

プリミティブ型の変数宣言時は、宣言と同時に変数に値を格納できます。  
以下の変数aには、そのまま1という値が格納されます。
  
```Java
int a = 1;
```

## 参照型とは
参照型は、上の8つ以外の型です。
例えば、Stringや配列などが参照型です。

```Java
Hoge hoge = new Hoge();
String str = "fuga";
```

参照型では変数に値はそのまま格納されず、値が格納されたメモリの場所を格納します。

# 再代入で見る基本型と参照型の違い

基本型と参照型では再代入での挙動で違いが出ます。

以下のサンプルコードは基本型の再代入しているコードです。こちらは直感的に分かると思います。

```Java:kihon.java
int a = 1;
int b = a; // bにはaの値：1が格納される
a = 2;

Systemout.println(a); // 2 が出力される
Systemout.println(b); // 1 が出力される

```

一方、参照型では以下のようになります。
基本型と同じような考え方では、b[0]は1を出力しそうな感じです。
ですが、参照型では変数に格納されるのはデータが格納されたメモリの場所だけです。

配列a宣言時、aには`{1, 2, 3}`という配列の情報が格納されたメモリの場所情報が格納されます。
配列b宣言時、bにもaのもつ`{1, 2, 3}`という配列のあるメモリ上の場所を格納します。  
  
このとき、aもbも同じメモリの場所情報が入った変数となっています。

`a[0] = 0;`では、aに格納されたメモリの場所にある配列`{1, 2, 3}`の0番目の値を0に置き換えます。これでメモリ上に格納された配列は`{0, 2, 3}`となりました。

よって、bに格納されたメモリ上の場所から配列の0番目を見てみても、出力される値は0となります。

```Java:sansyo.java
int[] a = {1, 2, 3};
int[] b = a;
a[0] = 0;

Systemout.println(a[0]); // 0 が出力される
Systemout.println(b[0]); // 0 が出力される
```
自分用メモ：PC版Chrome上でのjQuery.animate scrollTop 謎の挙動

```javascript
$("html,body").animate(
    {scrollTop: $(this).offset().top
})
```

こんな感じでクリックしたコントロール位置にあわせてjQueryのアニメーションでスクロールさせると、他の要素を消したり追加したりした際に勝手にスクロール位置があらぬ位置に戻ってしまう。

どうやらChromeでしか起こらないので、ブラウザのスクロール位置の記憶が邪魔しているっぽい。

予め、処理前に現在のスクロール位置を記憶してから、処理が終わったときにsetTimeout()を使って元のスクロール位置に戻すようにすると強引に解決させることができる。

```javascript
let scrollY = $(window).scrollTop()

//～～～～～～～～～～
//処理
//～～～～～～～～～～

//ブラウザのスクロール位置記憶バグを無視
setTimeout(function(){$("html,body").scrollTop(scrollY)},0)
```
python3 multiprocessingライブラリによる子プロセス処理内でも、pdbでデバッグする方法

#問題
python3ではmultiprocessingライブラリを使うと、例えば次のように簡単に並列処理が実現できます。

```python:test.py
from multiprocessing import Pool

def f(x):
    return x*x

if __name__ == '__main__':
    p = Pool(5) #数字分プロセス数を確保
    print(p.map(f, [1, 2, 3, 4, 5])) #並列処理したい関数とその引数を指定
```

実行すると、次のように並列処理された結果が出力されます。

```shell
$ python3 test.py 
[1, 4, 9, 16, 25]
```

この並列処理対象のメソッドをpdbでデバッグしたい時、あると思います。
その際にpdbを使おうと思うと、次のように書いてしまうと思います。

```python:test_ng_pdb.py
from multiprocessing import Pool
import pdb #追加

def f(x):
    pdb.set_trace() #追加
    return x*x

if __name__ == '__main__':
    p = Pool(5) #数字分プロセス数を確保
    print(p.map(f, [1, 2, 3, 4, 5]))
```

しかし、次のように実行してもエラーが出てしまい、pdbによるデバッグができません。

```shell
$ python3 test_ng_pdb.py
(略)
The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "test_ng_pdb.py", line 10, in <module>
    print(p.map(f, [1, 2, 3, 4, 5]))
  File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/multiprocessing/pool.py", line 268, in map
    return self._map_async(func, iterable, mapstar, chunksize).get()
  File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/multiprocessing/pool.py", line 657, in get
    raise self._value
bdb.BdbQuit
```
先ほどの追加部分を書かずに次のように実行したとしても、同様の問題でpdbが使えません。

```shell
$ python3 -m pdb test.py
```

前置きが長くなりましたが、この問題を解決してpdbでデバッグしたい、という内容になります。

#解決方法
[stack overflowのこの記事](https://stackoverflow.com/questions/4716533/how-to-attach-debugger-to-a-python-subproccess)記載の回答を試したら上手くできました、というただの検証の記事です。。

次のように、forkした子プロセス用pdbクラスを別途定義して使います。追加でsysをインポートする必要がありますが、標準ライブラリのみで済むのがとても良いなと思っています。

```Python:test_pdb_rev.py
from multiprocessing import Pool
import sys
import pdb

#下記のclassを追記
class ForkedPdb(pdb.Pdb):
    """A Pdb subclass that may be used
    from a forked multiprocessing child
    """
    def interaction(self, *args, **kwargs):
        _stdin = sys.stdin
        try:
            sys.stdin = open('/dev/stdin')
            pdb.Pdb.interaction(self, *args, **kwargs)
        finally:
            sys.stdin = _stdin

def f(x):
    ForkedPdb().set_trace() #書き換え
    return x*x

if __name__ == '__main__':
    p = Pool(5) #数字分プロセス数を確保
    print(p.map(f, [1, 2, 3, 4, 5]))
```

このような感じで、pdbでデバッグできます。

```shell     
$ python3 test_pdb_rev.py 
> /Users/purplejp/Documents/python/test_pdb_rev.py(20)f()
-> return x*x
(Pdb) > /Users/purplejp/Documents/python/test_pdb_rev.py(20)f()
-> return x*x
> /Users/purplejp/Documents/python/test_pdb_rev.py(20)f()
-> return x*x
(Pdb) (Pdb) > /Users/purplejp/Documents/python/test_pdb_rev.py(20)f()
-> return x*x
(Pdb) > /Users/purplejp/Documents/python/test_pdb_rev.py(20)f()
-> return x*x
(Pdb) x
1
```

普通にnを押して進むと、別のプロセスの変数も確認することもできました。
ということで、問題なくpdbを子プロセス上でも使うことができました。

#検証環境
python 3.7.3

#参考文献
[Python公式ドキュメント「multiprocessing --- プロセスベースの並列処理」](https://docs.python.org/ja/3/library/multiprocessing.html)
[Stack Overflow「How to attach debugger to a python subproccess?」
](https://stackoverflow.com/questions/4716533/how-to-attach-debugger-to-a-python-subproccess)
GAS で共有カレンダーを作る

Google Calendar でチームの共有カレンダーを作っているんですが、一括で入れたいと思うとなかなか面倒なんですよね。 GAS で作ろうとして権限まわりが少し難しかったのでメモです。

## 全体

```js
Date.prototype.addMinutes = function(m) {
   return new Date(this.getTime() + (m * 60 * 1000));
};

/**
 * @param {string} name
 * @return {Calendar} カレンダー
 */
function findOrCreateCalendar(name) {
  var calendar = CalendarApp.getCalendarsByName(name);
  if (calendar.length > 0) {
    return calendar[0];
  }
  return CalendarApp.createCalendar(name);
}

function addUsers(calendarId, emails) {
  emails.forEach(function(email) {
    Calendar.Acl.insert({
      "role": "owner",
      "scope": {
        "type": "user",
        "value": email,
      },
    }, calendarId);
  });
}

function newJSTDate(date, time) {
  return new Date(date + "T" + time + ":00+09:00");
}

function main() {
  const calendar = findOrCreateCalendar("カレンダーの名前");
  calendar.setSelected(true);

  Calendar.Acl.insert({
    "role": "reader",
    "scope": {
      "type": "domain",
      "value": "GSuite のドメイン",
    }
  }, calendar.getId());
  addUsers(calendar.getId(), [
    // 作成者はすでに入っている
    "招待する人のメールアドレス１",
    "招待する人のメールアドレス２",
  ]);

  // 以下は例
  // これぐらい単純だったら CSV をインポートする方が楽かも

  var startAt = newJSTDate("2019-06-24", "13:30");
  calendar.createEvent("タイトル１", startAt, startAt.addMinutes(90));
  startAt = newJSTDate("2019-06-24", "15:15");
  calendar.createEvent("タイトル２", startAt, startAt.addMinutes(90));
  startAt = newJSTDate("2019-06-24", "17:00");
  calendar.createEvent("タイトル３", startAt, startAt.addMinutes(90));
}
```

リソースは Calendar API だけ付与しています。メニューの「リソース」→「Google の拡張サービス」から追加しましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15627/e96a9b2c-4a20-e584-c72b-63863e40e3c2.png)

## ポイント

### ドキュメント

* [Calendar Service](https://developers.google.com/apps-script/reference/calendar/)
* [API Reference](https://developers.google.com/calendar/v3/reference/)

### getCalendarsByName

[CalendarApp.getCalendarsByName](https://developers.google.com/apps-script/reference/calendar/calendar-app#getCalendarsByName(String))

名前では一意にならないので注意。 `array` が返ってきます。

### Calendar.Acl

`Calendar.Acl` のドキュメントは App Script には無いので [API Reference](https://developers.google.com/calendar/v3/reference/acl?hl=ja) の方を見てください。

自分は作成時点で含まれていて変更できません。上記の `addUsers` に含めるとエラーになります。

GSuite のドメインで絞りたい場合は `domain` を利用します。メールアドレスのドメイン部分を `value` に指定してください。

### Date

startAt や endAt に利用する Date は JavaScript と同様です。 [MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Date) を参照すると良いです。

### createEvent

何度も実行できるように冪等にして宣言的に書きたかったんですがあきらめました。タイトルで一意なら簡単なんですが。 [Properties](https://developers.google.com/apps-script/reference/properties/) で ID を覚えたりするとできそうです。
【IBM Cloudメモ】既存ユーザーにすべての管理権限を付与する

# はじめに
表記の手順の問い合わせがあったのでメモを兼ねてアップしておきます。

# ダッシュボード表示
[ダッシュボード](https://cloud.ibm.com/)の画面を表示させます。

![スクリーンショット 2019-06-18 20.42.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206130/c314a26b-fe1a-e7ec-d95e-d6a807e456e3.png)

メニューから「管理」「アクセス(IAM)」を選択します。

# ユーザー管理機能の選択
下の画面で「ユーザー」をクリックします。

![スクリーンショット 2019-06-26 20.19.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206130/517ef144-f70f-e6de-aa9c-c34ac1fa533c.png)

# 対象ユーザーの選択
下のようなユーザーの一覧が表示されるので、権限をつけたい対象ユーザーのリンクをクリックします。

![スクリーンショット 2019-06-26 20.21.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206130/48f6047d-3fe4-1764-f402-3bbbf924f0e3.png)

# アクセスポリシーの設定
最初にアクセスポリシーの設定を行います。下の画面で「**アクセスポリシー**」タブを選択し、続いて「**アクセス権限の割り当て**」ボタンをクリックします。

![スクリーンショット 2019-06-26 20.25.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206130/11e1065d-bec9-754e-b885-b89df0611622.png)

下の画面で「**リソースへのアクセス権限の割り当て**」をクリックします。

![スクリーンショット 2019-06-26 20.28.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206130/130e650e-314a-233e-01db-d7c0373566b9.png)

次の画面で**サービス**のドロップダウンから「**すべてのIDおよびアクセス対応サービス**」を選択します。
**地域**はデフォルトの「**すべての地域**」のままにします。
その下の2箇所の**管理者**の欄にチェックをつけて、最後に画面右下の**割り当て**ボタンをクリックします。

![スクリーンショット 2019-06-26 20.31.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206130/08ea7bbf-1d0d-79f1-d52a-085b5296ccf4.png)

# クラシック・インフラストラクチャーの設定
次にクラシック・インフラストラクチャーの設定をするため、**クラシック・インフラストラクチャー**タブを選択します。
画面右上の**許可セット**として**スーパーユーザー**を選択して、**設定**ボタンをクリックします。

![スクリーンショット 2019-06-26 20.36.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206130/780ffc48-dd57-3270-cc33-d1900ab29822.png)

# Cloud Foundryアクセス権限の設定
最後にCloud Foundryアクセス権限の設定を行うため**Cloud Foundryアクセス権限の設定**タブを選択し、**組織の割り当て**ボタンをクリックします。

![スクリーンショット 2019-06-26 20.41.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206130/8ac80788-5bd3-3966-3199-6003b21c55ce.png)

以下の項目を順に設定します。

**組織**: 設定対象の組織を選択します。

**組織の役割**: **管理者**を選択します。

**地域**: **すべての現行地域**を選択します。

**スペース**: **すべての現行スペース**を選択します。

**スペースの役割**: **管理者**を選択します。
更にその下の「**スペースの役割の追加**」のリンクをクリックします。

![スクリーンショット 2019-06-26 20.45.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206130/a5442a78-bd6f-0248-a691-5ccf3cb3fa76.png)

下の画面のように入力欄が一つ増えるので、今度は**開発者**を選択し、最後に画面右下の「**割り当て**」ボタンをクリックします。

![スクリーンショット 2019-06-26 20.45.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206130/fb74c2e7-b2b8-9c08-0ea2-618f66be61cf.png)

お疲れ様でした。これで、既存の特定ユーザーに対してすべての管理権限を付与することができたはずです。
【Swift】iPadデバイスでActionSheetを利用する

# はじめに
今回Swiftでアクションシートを使ったアプリを作ったのですが、iPadでビルドするとクラッシュしてしまう問題が発生したので解決方法を書いておきます。


# エラーの内容
```ViewController.swift
 @IBAction func pushButton () {
        let alert = UIAlertController(title: "お腹すいた？", message: nil, preferredStyle: .actionSheet)
        let yesAction = UIAlertAction(title: "うん", style: .default, handler: nil)
        let aLittleBitAcion = UIAlertAction(title: "ちょっと", style: .default, handler: nil)
        let noAction = UIAlertAction(title: "全然", style: .default, handler: nil)
        
        alert.addAction(yesAction)
        alert.addAction(aLittleBitAcion)
        alert.addAction(noAction)
        
        self.present(alert, animated: true, completion: nil)
```

ボタンを押したときにアラートが表示されるサンプルを作成しました。このときiOSデバイスでビルドしてもクラッシュしませんがiPadでビルドすると`hread 1: signal SIGABRT`と怒られ、デバッグエリアを見てみると`reason: 'Your application has presented a UIAlertController ~~~`となってます。

# 解決策
`alert`プロパティに`popoverPresentationController?.sourceView = self.view`
と指定してあげるとクラッシュしませんでした。

```ViewCntroller.swift
 @IBAction func pushButton () {
        let alert = UIAlertController(title: "お腹すいた？", message: nil, preferredStyle: .actionSheet)
        let yesAction = UIAlertAction(title: "うん", style: .default, handler: nil)
        let aLittleBitAcion = UIAlertAction(title: "ちょっと", style: .default, handler: nil)
        let noAction = UIAlertAction(title: "全然", style: .default, handler: nil)
        
        alert.addAction(yesAction)
        alert.addAction(aLittleBitAcion)
        alert.addAction(noAction)
        
        //ここにぶちこむ
        alert.popoverPresentationController?.sourceView = self.view
        
        self.present(alert, animated: true, completion: nil)
```

# 終わりに
今回[こちら](http://re-engines.com/2017/11/01/swiftipadのactionsheet表示でクラッシュする問題/)の記事を参照させていただきました。
アラートのポップアップを下に指定したい場合は上記リンクをご参照下さい。
AWS CodeBuildを使ってRuby lambda functionにデプロイする

方法論的なものが少なかったので。
Rubyだけでなく、他の言語でも応用が効くはず。
CodePipelineと組み合わせると強力。

## TLDR

```yml:buildspec.yml
# 抜粋
phases:
  install:
    runtime-versions:
      ruby: 2.6
    commands:
      - rbenv install 2.5.5 && rbenv global 2.5.5
      # bundler install --path vendor/bundle等
post_build:
    commands:
      - zip data.zip *.rb -r vendor && aws lambda update-function-code --function-name 'FUNCTION_NAME' --zip-file 'fileb://data.zip'
```

## 解説

`bundle install` した状態のファイル群をまとめてlambdaに投げたい。

### Rubyバージョンの乖離

2019/06/26現在、lambdaのRubyは通常2.5しか選択できない。
CodeBuildはRuby2.6しか選択できない。
`bundle install --path vendor/bundle` したときに困ってしまう。
CodeBuildのログを見る感じrbenvが入っているので使いたいRubyバージョン入れてしまおうというアプローチ。

### lambdaへの反映

`aws`コマンドが使えるので使う。zipを作って普通にアップロード。**CodeBuildの権限ロールにlambdaのアクセス権限つけるのを忘れずに。**(AWSLambdaFullAccessをつければ動くことは確認)

### 別のアプローチ

カスタムコンテナ使えば解決ではあるが・・・。

## 補足

実際の `buildspec.yml` のコマンド欄には `hoge.sh` みたいにシェルスクリプトを指定したほうが見通しや管理が楽。
zipするところは必要なファイル群を入れておくこと。
Scrapboxの画面をstrongの記法で拡大する

相変わらずScrapboxのカスタマイズをやっていますが、デフォルトだと画像の張り込みが小さいので以下のようなUsercss(Usercssの使いかたについてはググってください)を使うことで、* をつかった strong の記法でサイズが変えられるようになりました。

```style.css
.level-1 img.image { width: 50%; max-height: none !important; }
.level-2 img.image { width: 60%; max-height: none !important; }
.level-3 img.image { width: 70%; max-height: none !important; }
.level-4 img.image { width: 80%; max-height: none !important; }
.level-5 img.image { width: 90%; max-height: none !important; }
.level-6 img.image { width: 100%; max-height: none !important; }
```

実際のsettingsは以下あたりを確認してください。
https://scrapbox.io/memoranda/settings

ほんと人類全員がScrapboxを使ったらいい、と思うくらいに使いやすくて快適です。JSで拡張したり砂場としても楽しんでいますし、Scrapboxのお陰で人生変りました(笑・主に時間の使える量が)。
Pythonの お勉強 8日目

### 機械学習の２日目
RaspberryPiにライブラリのインストールを行います。
参考書：RaspberyPiではじめる機械学習、金丸隆志（kindle版）
私のRasberyPiは参考書にあるRasberyPiと壁紙が違っていたり
Browserの名前も違っていましたが、とにかくscikit-learnの
インストールをを実行する-->正常にインストールされません。

`sudo apt-get updata`
`sudo apt-get install python-sklearn`


RaspberryPiにはいろいろ機種があり私のものはOSも古いもので
した。余っていた３２GBのSDカードに新しいOSを入れて差し替える
と　scikit-learnはインストールされました。

この続きは、勉強（いい素材の仕入れ方、自分流の調理方法）して　
RaspberryPi4をGet出来てから書いていきます。
スプレッドシートでウェブページの簡易リダイレクトテストツールを作った

# なんで作った？

URLたくさんポチポチするの嫌だったから・・・。
ちゃんとリダイレクト先が合っているかも確かめたかった。

# 実行結果

![スクリーンショット 2019-06-26 20.31.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120339/2dfa33c1-5c3d-2425-672e-0e7fc0e3a543.png)

# 実装

google apps scriptで作っています。
spread sheetからスクリプトエディタ開いてもらって下記をコピペしてください。
redirectTestを実行してもらえれば実行結果のように3列に対して処理が走る仕組みです。

URL列は、調べたいURLをhttpから始めてもらっても、省略した形でも大丈夫です。
status code列は、200なら緑、他は赤に塗られます。
redirect to列は、HTTPレスポンス部分にリダイレクト先が明記されている場合に、リダイレクト先URLを記載します。

いじるのはURL列にURLを羅列するだけ。
gasの処理時間制限の6分があるので、対象URLが多い場合は小分けにするなどしてみてください。


```js
function redirectTest() {
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = spreadsheet.getSheetByName('redirect test');
  var range = sheet.getDataRange();
  var values = range.getValues();
  
  var options = {
    'followRedirects' : false
  };
  
  var url, code, location, response;
  for (var i = 1; i < values.length; i++) {
    url = values[i][0];
    code = '';
    location = '';

    response = UrlFetchApp.fetch(url, options);    
    code = response.getResponseCode();
    location = response.getAllHeaders().Location;

    paintForStatusCode(range, i + 1, code);
    setLocation(range, i + 1, location);
  }
}

function paintForStatusCode(range, i, code) {
  var cell = range.getCell(i, 2);
  cell.setValue(code);
  if(code == 200) {
    cell.setBackground('#00FF00');
  } else {
    cell.setBackground('#FF0000');
  }
}

function setLocation(range, i, location) {
  var cell = range.getCell(i, 3);
  if(location != undefined) {
    cell.setValue(location);
  } 
}
```
Windows sub-systems for LinuxをGUI環境として使えるようにしてみた

# はじめに
所属している研究室でネットワークシミュレータns-3を使用することになりました。
ns3を使用する上でネックなのが、Linux環境が推奨とされていました。
Linux環境で動くns-3をなんとかWindowsで動かせないか調べた際、WSL(Windows sub-system for Linux)をGUI環境にできる方法を見つけたので、その方法を書きたいと思います。

# 使用環境
- Windows 10

# 前提
WSLの有効化はすでに様々な記事が出ているので、ここでは割愛します。

# WSLのGUI環境の構築手順
## 1. VcXsrvを入れる
sourceforgeから入手し、インストールします。
https://sourceforge.net/projects/vcxsrv/

## 2.　xfceをUbuntuに入れる
    sudo apt-get update
    sudo apt-get upgrade
    sudo apt-get install xfce4-terminal
    sudo apt-get install xfce4

## 3. Ubuntuの環境設定をする
`sudo nano ~/.bashrc`で.bashrcを開き、

    export DISPLAY=:0.0
    export LIBG_ALWAYS_INDIRECT=1
を.bashrcに書き込み、Ubuntuを再起動するか、`source .bashrc`をする．
## 4. Xlaunchを起動する
VcXsrvをインストールしたら、xlaunchと書かれたアプリを起動する。
'One large window'または'One window without titlebar'のどちらかを選択する。
Display numberは0に設定する。
後は'次に'を押し続けて起動する。

## 5. xfceを起動する
WSLに戻り、`startxfce4`でxlaunchの黒い画面にGUI環境が現れる。  
これで、Linux環境をWindowsホストで作成できました。

# ns3のインストール
GUI環境できたので、ns3をインストールする。インストールの仕方は公式ドキュメントにあるので割愛。

# 参考資料
[WSLでwindows上にLinuxのGUI環境を作る[メモ]](https://qiita.com/MERIK/items/ef4ecf7a51f89c403e94)
[Installation - Nsnam - ns-3](https://www.nsnam.org/wiki/Installation)
Raspberry Pi2で指定ESSIDのSignal levelを取得するプログラムを作成してみた

#1. はじめに
研究で、受信信号強度を取得するプログラムを作る必要があったため、取得プログラムを作成しました。色々方法はあるだろけど、今回はiwlistコマンドで指定のESSIDを探し、そのSignal levelを取得するプログラムを作りました。

#2. 使用機器・環境
Raspberry Pi 2 model B+
OS : Raspbian
Wifi usbアンテナ : I-O Data製WN-G300UA
開発言語 : Python3.5.3

#3. コード
```Python
import sys
import subprocess

def PrintSignalLevel():
    essid = '検索したいESSID名'
    cmd = 'sudo iwlist NIC名 scan | grep -e ESSID -e Signal'
    process = (subprocess.Popen(cmd,stdout=subprocess.PIPE,shell=True).communicate()[0]).decode('utf-8')
    iwlist = process.split('\n')
    for idx,line in enumerate(iwlist):
      if essid in line:
        print(line)
        sigline_idx = idx+1
        sigline = iwlist[sigline_idx]
        print(sigline)
        tmp = sigline.rfind('=')
        tmp1 = signline.rfind('/')
        rssi_per = sigline[tmp+1:tmp1]
        rssi_dBm = (0.6*int(rssi_per))-95
        print('RSSI[%] = {rssi_per} -> RSSI_dBm} = {rssi_dbm}'.format(rssi_per=rssi_per,rssi_dBm))
        break

if __name__ == "__main__":
    PrintSignalLevel()
```

#4. まとめ
今回使用した無線LANドライバーがAtheros社製であったため、パーセンテージとして表示されているのをdBm変換して最後表示しています。例外処理してないけど、基本的な処理は作れたので、今後そこらへんは追加する予定です。

#5. 参考資料
[Converting Signal Strength Percentage to dBm Values](http://madwifi-project.org/attachment/wiki/UserDocs/RSSI/Converting_Signal_Strength.pdf?format=raw)
[小ネタ]前回のgit commitコメントを再利用するシェルスクリプト

コンソール上でgit commitするときに、前回のコメントを基に書き換えてコミットしたいときがちょくちょくあります。コメント中のキーワードをまた使うときや、amendで書き直したりするときとか…
git logでもちろん確認できますが、いちいち確認するのも面倒。

そんな面倒を解決するシェルスクリプトを作ってみました。

# スクリプト

わずか2行。

```shell
COM=$(git log -n 1 --pretty=format:"%s")
echo -n "git commit -m '$COM'" | pbcopy
```

# 解説

git logで前回のコメントを取得して、git commitコマンドに仕立てて、クリップボードに格納する、という流れです。

## 1行目

```[変数]=$(コマンド)``` は、変数にコマンドの実行結果を確認する処理です。git logにオプション指定していますが、```-n [個数]``` は何個コミットを取得するか、```--pretty=format:"%s"``` は、コミットのコメントのみ出力する書き方です。

つまり、**最新1回分のコミットのコメントのみ出力**というコマンドの結果を、COMという変数に取り込むという処理になります。

## 2行目

echoで実行した結果を、pbcopyでクリップボードに格納しています。
echoのオプション```-n``` は、echoの出力結果の末尾で改行しないという指定。これを忘れるとペーストしたときに一気に実行までされてしまうので書き換えができなくなってしまいます。
pbcopyはmacOSのコマンドで、渡された出力をクリップボードに格納する機能になります。便利。

# おわりに

いまさっき作ったばかりでまだ使ってないので、便利かどうかは…？投稿の中身がほとんどコマンドのオプション説明なのはご愛嬌。
はじめてのプロコンメモ(その5)

# はじめに
[AtCoder に登録したら次にやること ～ これだけ解けば十分闘える！過去問精選 10 問 ～](https://qiita.com/drken/items/fd4e5e3630d0f5859067)の類題もやっています
第 5 問(200 点)問題を解いています。

## [B - Some Sums](https://atcoder.jp/contests/abc083/tasks/abc083_b)

## 問題文

```
1以上 N以下の整数のうち、10進法での各桁の和が A以上 B以下であるものの総和を求めてください。
```

## 標準入力例

```
20 2 5
```

### 考えた解答
これは自力で解けなかったので解答をみてPythonに書き直した
躓いたところ
- `n = round(n/10)`割り算の丸め込みができてなくて最後の条件に合わなかった
下記で書いてもテストが通らなかった

```Python
N, A, B = map(int, input().split())

def find_sum_of_digits(n):
  sum = 0
  while n >0:
    sum = sum + n%10
    n = round(n/10)
  return sum

total = 0
for number in range(1,N+1):
  all_sum = find_sum_of_digits(number)
  if A <= all_sum and all_sum <= B:
    total = total + number

print(total)  
```

### 解答改善策

これを見てむしろ文字列にして桁を数えれば良いのではと思いたち改善したら通った
https://note.nkmk.me/python-digit-int-float/

```Python
N, A, B = map(int, input().split())

def find_sum_of_digits(n):
  s = str(n)
  sum = 0
  #Stringに変換桁数を数える

  for i in range(0,len(str(n))):
    sum = sum + int(s[i])
  return sum

total = 0
for number in range(1,N+1):
  all_sum = find_sum_of_digits(number)
  if A <= all_sum and all_sum <= B:
    total = total + number

print(total)
```

# [ABC 080 B - Harshad Number](https://atcoder.jp/contests/abc080/tasks/abc080_b)

## 問題

```
整数 Xを十進法で表したときの各桁の数字の和を f(X)としたとき、Xが f(X)で割り切れる場合、Xはハーシャッド数です。整数 N が与えられるので、ハーシャッド数かどうか判定してください
```

## 解答

これも配列にとりあえず入れて、数を数えて解決してしまった

```Python
X = int(input())

char_list = list(str(X))
data2 = map(lambda x: int(x), char_list)
data3 = list(data2)
if X % sum(data3) == 0:
    print("Yes")
else:
    print("No")
```
AppStoreConnectにアップロードしたのにビルドから消えた時の対応

Xcodeでアプリをアップロードし「Upload Successful」と表示され
AppStoreConnect側でも処理中なのを確認したのに少し時間が経ったら消えていました。

↓これが消えていた
<img width="692" alt="スクリーンショット 2019-06-26 17.48.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218/4aede1ee-9c10-5424-45f7-b0689106de19.png">


# 解決法

契約が更新されていて同意が必要でした。

[https://appstoreconnect.apple.com/agreements/](https://appstoreconnect.apple.com/agreements/#/)
から利用規約に同意。

![270f2bf6ca3e7147bba9affa8000d7c8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218/9ac2b793-9306-6fe8-a2cd-527027e7e0b0.png)


アップロードするときにそういうエラーを出してほしい…


※自ブログからの転載です
http://akinov.hatenablog.com/entry/2019/06/26/195732
僕が "Jetbrains" のIDEを使う理由(適宜更新)

# 話のテーマ
僕は現在、Web系スタートアップ企業で フロントエンド・バックエンド・インフラ を担当しています
開発環境は React/Django/GCP/AWS です

IDE は Webstorm と Pycharm を使用しているんですけど
がっつり使っていく上で、「あ、これ便利」
と感じる機能が結構あったので、それを共有していこうかなと思います

ちなみに
【追加インストール無しでデフォルトで搭載されている機能】
のみの説明です！

僕嫌いなんです、ゴチャゴチャ色々入れるの・・・
アホだから何入れたかすぐ忘れるんですよね

「そんなんもう知ってる」っていう方は、優しく見守って下さい

# Pycharm
###アイコン
IDEなら当たり前だろ！と思われるかもしれませんが、オーバーライドや継承のアイコンが付いているのが地味に便利です。
もちろんクリックによって、オーバーライド元のコードへジャンプできます。
Pythonは「多重継承」を行うことができる言語なので、この機能が無いと生産性がゴリゴリ落ちます。僕には辛いです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445967/b0e21570-7d80-bbfb-b374-d8e087184008.png)

### 自動整形
option + command + L によって、自動的に各種コーディング規約に基づいた自動整形ができます。
ちょ便利です。

### 簡単に pip install 
入ってると思い込んだまま、import しようとしたら入ってなかった！！
そんな時には option + enter で、インストールできますぜ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445967/8e7cfd22-957f-b827-96b7-cb042ed6c746.png)

### この行編集したのは誰だ！
アノテート機能でサクッと確認！！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445967/86d76528-5c88-1860-bbf8-cb29d97a79b3.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445967/0a15b751-9930-8c8e-2d91-05c3f9ab91ee.png)

### もちろんローカルヒストリー
定期的にバックアップを取ってくれてるから
ちょっと前のやつ復元させたいなぁ！
って時も、サクッと確認可能！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445967/2e2b3be7-5962-3443-73e3-c66a2d55bb95.png)

### ツリーからライブラリを辿れる
以前はVSCを使っていた時、ジャンプはできたけどツリーを追って行くことができなくて不便だったんですよね・・・
pip で入れたやつとかここからサクッとみたいじゃ無いですか？？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445967/a31439e7-9f39-6c4e-5a28-ac48bcc2f9c5.png)

# WebStorm
ほとんど Pycharm と被るので、独自のやつだけ・・・

### Typescript 実装箇所へのジャンプ（d.ts へのジャンプではなく）
「command + クリック」で d.ts ファイルへジャンプできるけど
「command + option + クリック」 で実装箇所へジャンプできる

VSCodeには無い機能なので嬉しい
（2021/10月現在）

### カラーパレット
これはマジで便利。
皆、「このサイトのこの部分の色が知りたいよ！！」って時どうしてます？？
webサイト使う？
ネイティブアプリ使う？
イラレ？？
いやいや・・・・そんなめんどくさいこと要らないです
そう・・・webstorm ならね

![名称未設定 8.MOV.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445967/954ab54a-d5fb-7f53-abbe-81c7316c71b3.gif)

# 終わりに
皆さんもオススメの機能あったら教えてくれると助かります
Node.jsでGoogle Driveの指定フォルダからファイル一覧を取得メモ (Google Drive API v3)


フォルダーIDを指定しての実行がなかなか見つからなかったのでメモです。

## 環境

* Node.js v12.2.0
* Google Drive API v3 (過去の調べるとv2も出てくるので念のため)

## 基本

公式のNode.jsチュートリアルをやります。

> https://developers.google.com/drive/api/v3/quickstart/nodejs

## フォルダIDを指定して取得

ブラウザで開いた時のURLのこの部分です。

> ![スクリーンショット 2019-06-26 19.45.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/b075d159-efb2-d5db-4ba0-09cf9d71da79.png "スクリーンショット 2019-06-26 19.45.46.png")


チュートリアルの`function listFiles`の箇所を書き換えます。

```app.js

async function listFiles(auth) {
  const drive = google.drive({version: 'v3', auth});
  const FOLDER_ID = `xxxxxxxxxxxxxxxxxxxxxxxxxxxxx`; //ここにフォルダIDを指定
  const params = {
    q: `'${FOLDER_ID}' in parents and trashed = false`,
  }

  try {
    const res = await drive.files.list(params);
    const files = res.data.files;
    if (files.length) {
      console.log('Files:');
      files.map((file) => {
        console.log(`${file.name} (${file.id})`);
      });
    } else {
      console.log('No files found.');
    }    
  } catch (err) {
    console.log('The API returned an error: ' + err);
  }
}
```

## 所感

`q`に`'${FOLDER_ID}' in parents and trashed = false`なんて指定の仕方をするんですね.....

一応[中のこの辺](https://github.com/googleapis/google-api-nodejs-client/blob/master/src/apis/drive/v3.ts#L3316-L3336)をみるとパラメータで何があるか分かりますが、公式の[list.js](https://github.com/googleapis/google-api-nodejs-client/blob/master/samples/drive/list.js)ってサンプルもparamsの書き方が書いてなくて見つけるのがしんどかった苦笑

driveIdとかteamDriveIdとか色々あるけど別物らしい（調べきれてない）

## 参考

* https://github.com/googleapis/google-api-nodejs-client/blob/master/samples/drive/list.js
* https://github.com/googleapis/google-api-nodejs-client/issues/1011
cyberduck で S3 のバケットを管理する

## Cyberduck のダウンロード&インストール
以下からお使いの OS の Cyberduck をインストールしてください
https://duck.sh/

## S3 の アクセスキーとシークレットキーを用意する
S3 の IAM からアクセスキーとシークレットキーを準備します。
<img width="426" alt="スクリーンショット 2019-06-26 19.31.21.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278797/001f8bbd-6240-6b25-e596-e43c19bc20a6.jpeg">
IAM の左タブのユーザーを開きます。
<img width="262" alt="スクリーンショット 2019-06-26 19.31.53.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278797/c999b19c-3c97-1a36-fe99-6d026b16ddfb.jpeg">
次に認証情報を開き
<img width="526" alt="スクリーンショット 2019-06-26 19.31.59.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278797/a238fb5a-4842-9eb2-cb3e-61f529b5a261.jpeg">
アクセスキーの生成を行い, アクセスキーとシークレットキーをコピーしてください。
<img width="868" alt="スクリーンショット 2019-06-26 19.32.06.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278797/7cb6298e-0313-8283-7966-74832671b95b.jpeg">

## Cyberduck から S3 に接続する
Cyberduck の新規接続から, Amazon S3 を選択します。
<img width="523" alt="スクリーンショット 2019-06-26 19.36.27.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278797/efc9aa8c-e974-0a8a-3490-ed92b434bcc9.jpeg">
そしたら, アクセスキーとシークレットキーを求められるので入力します。
<img width="490" alt="スクリーンショット 2019-06-26 19.36.46.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278797/a6ddff21-df5a-c78f-2471-c60d29956783.jpeg">

その後, 無事接続が完了しましたらバケットが表示されると思います。もしうまく繋がらない方は, IAM からお使いのアカウントが S3 のアクセス許可が出てるかなど確認してみてください。
Cyberduck を使うことで, AWS マネージメントコンソールを使用するより簡単にサーバーにデータを送受信することができるようになりました。cyberduck 便利ですね！
Android Flavor wrapper object

When using multiple flavors in a single Android project, a wrapper such as below is a useful utility when checking the current flavor (e.g. when assigning different features to different flavor). 

It is not recommended to check the BuildConfig.Flavor string manually outside of this wrapper, due to potential errors in the string equality. Instead, we only need to ensure the "Name" enum in this wrapper is correct, to ensure correctness throughout the project. 

The example here assumes two flavors in the build.gradle: "euro" and "japan"

```kotlin
object Flavor {

    // NOTE: must match flavor/dimension names given in build.gradle
    enum class Name {
        euro,
        asia
    }

    val current: Name 
    get() {
        Name.values().firstOrNull { it.name.equals(BuildConfig.FLAVOR) }?.let{ name->
            return name
        } ?: run {
            throw Exception("Unknown flavor: " + BuildConfig.FLAVOR)
        }
    }

    val isEuro: Boolean = current.equals(Name.euro)
    val isAsia: Boolean = current.equals(Name.asia)
}
```