OmniAICreator/Qiita-1.07M huggingface dataset:
AWS の EC2 上で動作する Moodle の SELinux を有効にする(その2)

今回は、nfs ではなくて、同じサーバに moodledata を置いてみました。
SELinux を有効にして再起動すると、以下のようなよく見るエラーになりました。

Fatal error: $CFG->dataroot is not writable, admin has to fix directory permissions! Exiting. 

前回 [AWS の EC2 上で動作する Moodle の SELinux を有効にする](https://qiita.com/intrajp/items/ad7ed79262d89d23a7bc) でやったことのうち、file context は手動で設定することをまずはやってみる。
semanage コマンドがインストールされていなくても、以下のようにすればOK


ここで、$CFG->dataroot は、/var/www/html/moodledata であるとする。

```
# vim /etc/selinux/targeted/contexts/files/file_contexts.local

/var/www/html/moodle(/.*)?   system_u:object_r:httpd_sys_rw_content_t:s0
/var/www/html/moodledata(/.*)?   system_u:object_r:httpd_sys_rw_content_t:s0

# restorecon -R -v /var/www/html
```
moodle ディレクトリも設定しているのは、プラグインをインストールできなくなるため。

なお、これは、semanage コマンドで以下を実行したのと同じである。semanage がこのファイルに記述するため。なお、semanage が使える状況では、ファイルを直接編集すると、消されてしまうので注意。
要すれば、手動で上記ファイルを編集するのはダメです。
つねに、semanage コマンドを使いましょう。
semanage コマンドのインストール方法とともに、正しいラベルの張り替え方を教えます。

```
# yum -y install policycoreutils-python
# semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/html/moodle(/.*)?"
# semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/html/moodledata(/.*)?
# restorecon -R -v /var/www/html
```

これもやっておく必要がある。

```
# setsebool -P httpd_can_network_connect 1
```

ページが表示された。

もし、sshd のポートを 2222 で運用しているのなら、以下をやる必要がある。

```
#  semanage port -a -t ssh_port_t -p tcp 2222
```
Apache からメールを送らせるのなら、これも必要。

```
# setsebool -P httpd_can_sendmail 1
```

(参考)
https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/6/html/security-enhanced_linux/sect-security-enhanced_linux-selinux_contexts_labeling_files-persistent_changes_semanage_fcontext
メソッドを外で使用したい時


【概要】
----------------------------------------
<b>1.結論</b>

<b>2.メソッドとは何か</b>

<b>3.どのように使用するのか</b>

<b>4.別解</b>



1.結論
----------------------------------------
インスタンス変数とインスタンスメソッドを使う！

<br>
2.メソッドとは何か
----------------------------------------
>”目的を達成するために決められたやり方。方法。方式”

と出てきますが、簡単に言うと変数にくっつけて使えたり（インスタンスメソッド）、方程式のような元々あるメソッド（lengthやeach,times等々）のことを指します！

外で使用する場合には、スコープの概念が出てくるので
下記の記事に少しだけ書いています！

”<a href="https://qiita.com/taka_no_okapi/items/7aec19c5a901aa4ab8e0">変数とインスタンス変数の違い</a>”
<br>
3.どのように使用するのか
----------------------------------------
では実際はどうなるかといいますと下記の通りになります。


```Ruby:インスタンスメソッドとインスタンス変数の関係
class Student

 def initialize(gender, height, personality)
  @gender = gender
  @height = height
  @personality = personality
 end
　
 def gender
  @gender
 end

 def height
  @height
 end

 def personality
  @personality
 end

end

student = Student.new("男", "175cm", "優しい")
puts "性別:#{student.gender} 身長:#{student.height} 性格:#{student.personality}" 
```
こうすることで、変数にメソッドをつけて自由に
"def end"の外（スコープの範囲を超えて）でも使用できます！

<br>
4.別解
----------------------------------------
メソッドの内でも同じことが書けます！

```Ruby:メソッド内で完結
class student

def initialize(gender, height, personality)
  @gender = gender
  @height = height
  @personality = personality
  puts "性別:#{@gender} 身長:#{@height}# 性格:#{@personality}"
end

student = Student.new("男", "175cm", "優しい")

```
このようにしてもメソッド内で使用することができます！

<br>
PHPでパスワード比較に==とか===使っちゃだめって知ってた？

PHPerの皆さん、重要な文字列を入力データと保管情報を比較するときに比較演算子（"=="とか"==="）使ってませんか？
これ実は**使っちゃだめ**なので、気をつけましょう。

## なぜだめなの？

（2020/8/31修正） 関数名をtypoしていたため修正しました。（正）memcmp・（誤）strcmpです。

PHPを含む多くの言語では、文字列を比較する際に内部で `memcmp()` を使います。
通常の（厳密なセキュリティを必要としない）ケースでは、比較演算子を使うことはまったく問題ありません。
パスワードなど絶対に推測されてはいけない文字列を比較する場合、**この関数は脆弱**といえます。
`memcmp()` は内部で1バイトずつ比較検証するため、応答時間をもとに先頭から何文字正解だったか推測できます。
このような攻撃を「タイミング攻撃」といいます。

## どうすればいいの？

PHPでは、ハッシュ値を用いて文字列を比較する `hash_equals()` という関数が用意されています。
関数の説明にもきちんと「Timing attack safe string comparison」と書かれています。

https://www.php.net/manual/en/function.hash-equals.php

## パスワードを扱う際の正しい実装

（2020/8/28追記） @anirfa さんのコメントをもとに追記しました。

ここまでは平文で保管された「重要な文字列」を扱う際の注意点でした。
たとえばパスワードなどの第三者から読み取らせてはいけない情報はそもそも平文で保管せず、ハッシュ化して保管すべきです。
PHPにはパスワード管理のために以下のような関数がありますので、そちらを使ってください。

- [password_hash()](https://www.php.net/manual/ja/function.password-hash.php)：パスワードを安全に保管する
- [password_verify()](https://www.php.net/manual/ja/function.password-verify.php)：保管されたパスワードを検証する

## 実装をのぞいてみた

本当に比較演算子で `strcmp()` が使われてるかPHPソースコードをみてみましょう。

[zend_string.h#L316-L335](https://github.com/php/php-src/blob/a92022f87828f699916df408f3dcfdd3854a7e17/Zend/zend_string.h#L316-L335)

```zend_string.h
#if defined(__GNUC__) && (defined(__i386__) || (defined(__x86_64__) && !defined(__ILP32__)))
BEGIN_EXTERN_C()
ZEND_API zend_bool ZEND_FASTCALL zend_string_equal_val(zend_string *s1, zend_string *s2);
END_EXTERN_C()
#else
static zend_always_inline zend_bool zend_string_equal_val(zend_string *s1, zend_string *s2)
{
	return !memcmp(ZSTR_VAL(s1), ZSTR_VAL(s2), ZSTR_LEN(s1));
}
#endif

static zend_always_inline zend_bool zend_string_equal_content(zend_string *s1, zend_string *s2)
{
	return ZSTR_LEN(s1) == ZSTR_LEN(s2) && zend_string_equal_val(s1, s2);
}

static zend_always_inline zend_bool zend_string_equals(zend_string *s1, zend_string *s2)
{
	return s1 == s2 || zend_string_equal_content(s1, s2);
}
```

zend_string_equals->zend_string_equal_content->zend_string_equal_val->memcmpが呼び出されていますね。
※インラインアセンブラが使える場合の処理（[zend_string.c#L396-431](https://github.com/php/php-src/blob/a92022f87828f699916df408f3dcfdd3854a7e17/Zend/zend_string.c#L396-431)）の説明は割愛します
【Android】カスタムレイアウトにパラメータを付与したい

1.  カスタムレイアウトの編集

    ```kotlin
    class CustomLayout(context: Context, attrs: AttributeSet?) : 
    ConstraintLayout(context, attrs) {
    
        //省略
    
        fun setCustomText(customText: String?) {
            //ここに処理を追加
        }
    }
    
    ```

2. xmlの編集

```xml
        <jp.co.xxx.CustomLayout
            android:id="@+id/hoge"
            app:customText="hoge" />

```
DataBindingも可能。
UnityのAR用パッケージVuforiaのVersion最新版アップデート方法

" 投稿者のUnity Ver → 2019.4.8f1 "

UnityでARを使用しようと思うとAR Foundationが勢力が強くなってきていますが、まだVuforiaの方が色々と揃っていて使い勝手がいい印象です。
とは言え、色々な機能の充実がAR Foundationでも図られており、２、3年するとどうなるかわかりません。
youtube等ではVuforiaのチュートリアルが豊富にあり、AR Foundationはまだまだ参考になるものが数は少ない印象です。

そんなVuforiaを最新のUnityで使用しようと思うとプリセットされているバージョンでは古く、アップデートする必要があります。
その上、Package Managerで出てくるバージョンも最新のものでもないので、自分で最新版を探さないといけません。そのSDKのURLが下記のものになります

https://developer.vuforia.com/downloads/sdk

ちなみに2020年8月26日現在の
Vuforia最新バージョン :9.3

別の機会にこのバージョンでのARの方法を載せようと思います
読みやすいコードを書くために意識すべき基本的ルール

```
前提
プログラミングを始めたて（1~2ヶ月）の自分が学習した内容をまとめています。
実際の現場では通用しないことや間違っていることなどあるかもしれませんが、
お気づきの際はコメントにてご報告いただければ幸いです。
```
プログラミング初学者の私が、

```
読みやすいコードを書く必要性
どのようにすればわかりやすいコードを記述できるのか
```
について学んだことをまとめました。

## なぜ読みやすいコードを書く必要があるのか
読みやすいコードを書く理由には大きく３つあります。
・個人、組織の生産性が上がる
・保守性が上がる
・柔軟な開発体制が構築できる
プログラミングでの開発は基本的には複数人で行うため、自分さえわかればいいというコードの書き方では生産性は頭打ちになり、柔軟な開発体制からは程遠くなってしまいます。

この３つを実現するために**リファクタリング**が行われています。
リファクタリングとは
実装した機能に影響を与えずにソースコードを読みやすい状態に改善することです。
このリファクタリングによって一緒に開発に携わる人が実装されているコードの理解や修正を簡単に行うことができるようになります。

## 実際にコードを書く時に注意すべき点
変数が他者を考慮した命名になっていること（変数と関数の命名）
複雑なロジックがなく、読みやすい（ロジックの単純化）
コメントが記載されていて、全体像を把握しながらコードが読める（正確で端的なコメント）

### 変数と関数の命名
変数や関数を命名する際には、抽象的な名前は避けて、具体的な名前をつけます。
変数名の場合
その変数がどんな役割を持った値かわかるように定義する。
関数名の場合
動詞+名詞の形で何をどうする処理かわかるように定義する。

#### 変数名の例
悪い例

```
const one = 1;
```
良い例

```
const userId = 1;
```
悪い例では変数oneの名前から1という値がどんなものか、どんな役割をもつ値なのかがわかりません。
良い例では変数がuserIdとなっており、1という値がユーザーIDだということがひと目でわかります。

#### 関数名の例
悪い例

```
const add = () => {
処理
};
```
良い例

```
const addTask = () => {
処理
}
```
悪い例では、何かを追加することはわかりますが、何を追加するのかがわかりません。
良い例ではTaskがついているため、Taskを追加する処理だと一目で理解することができます。

### ロジックの単純化
コードが複雑化していく要素として、大きく２つあります。
ネスト中にネストの記述がある場合
条件式が複雑化している場合
#### ネスト中にネストの記述がある場合
ネストとは？
ネストは入れ子構造のことです。
条件式で例えると、ifのなかにif、そのifの中にさらにifといったような記述の時にネストが深いと言ったりします。
入れ子構造が多く含まれているということです。

この例からもわかるように、１つの構造の中に多数の構造が増えれば増えるほどその構造は複雑化していきます。
つまりネスト中にネストの記述はできる限り少なくすることがより見やすいコードになるということです。
具体的な対策方法
・早い段階で戻り値を返し、処理自体を小分けにする。
・論理演算子を用いる。

#### 条件式が複雑化している場合
条件式が長い場合も処理の内容を把握するのに最初から最後まで読まないといけないため、わかりにくいコードとなってしまいます。

条件式の記述が長くなってしまった場合には、条件式を関数化しその記述を呼び出すように書くことで、より簡潔でわかりやすいコードになります。

それでもそもそも記述内容に複数の条件式があって複雑だ。
という場合には複数の条件式を分解し、複数のifに分けることで記述が簡潔になります。

### コメントで正確な情報をうまく伝える
コード中にはコメントアウトでコメントを残すことができます。
このコメントを用いて、記述をより分かりやすく見てもらえるようにできます。
#### コメントを残すべき場面
・複雑なロジックを記述した場合は処理の概要と自分の考えをコメントで残す
・なぜそのような記述をしているか残す
#### コメントを残すべきではない場面
・コメントの補足コメント
・処理が複雑すぎるコードを補う「補助的コメント」
そもそもコメントは注釈的に残しておくものなので、そのコメントをたくさん読むようでは簡潔なコードとは言えません。
それに加えて、処理が複雑すぎて１つのコメントでは補えない場合があります。
これらの場合はコメントに頼るのではなく、複雑なソースコードを修正するという視点が重要です。

以上でプログラミング初学者の私が学んだわかりやすいコードを書く時に意識すべき基本的ルールでした。
追記や訂正等ございましたら、是非コメントにてお願いします。
JavaScriptの関数を使って両替機を作ってみた

```javascript
    
<script>
      //変数を作る
      let select;
      let yenMoney;
      let usaMoney;
      let doru = 106;
      
      //関数式で記載
      const getYenToDoru = (number) => {
        return number / doru;
      }    
      const getDoruToYen = (number) => {
        return number * doru; 
      }
      
      //繰り返し行う。
      while(true){
        select = prompt('両替しますか？(【１】円→ドル 【２】ドル→円)');
        
        if(select === '1'){
          yenMoney = prompt('金額を入力してください');
          console.log(getYenToDoru(yenMoney) + 'ドルになります');
          break;
          
        }else if(select === '2'){
          usaMoney = prompt('金額を入力してください');
          console.log(getDoruToYen(usaMoney) + '円になります。');
        } 
        //数値が入力されていなかったり、キャンセルした場合は終了
        else break;
      }
</script>
```
正規形について

### 正規形とは
ここ最近データベース周りの学習をしており、正規形に関して学んだのでここに備忘録として残しておきたいと思う。正規形とは「データベースで保持するデータの冗長性を排除したもので、一貫性と効率性を保持するためのデータ形式」のこと。
正規形にはレベルが分けられており、レベル１～レベル５までの第１正規形～第５正規形まである。実際の業務で考える場合は第３正規形まで考えることが多い。

### 第１正規形

第１正規形は「一つのセルの中に一つの値しか含まない。」というもの。そのため、仮に一つのセルに二つ以上のデータが入っている場合は、列を増やすなどして一つのセルに一つのデータが入るようにしなければならない。
第１正規形に直す方法としては
1.列を増やす
2.行を増やす
3.複数のテーブルに分割する

### 第2正規形
第2正規形について理解するにはまず部分関数従属と完全関数従属を理解する必要がある。
主キーの一部の列に対して従属する列がある場合、この関係を部分関数従属と呼ぶ。それに対して主キーを構成するすべての列に従属性がある場合を完全関数従属と呼ぶ。第2正規形はテーブル内での部分関数従属を解消することで得ることができる。
簡単に言うと、主キーが決まると他の列の値も決まるように分けるということ、
例えば「教科」「テスト日」「テストの点数」「教科書」といったカラムを持つテーブルがあったとします。今このテーブルの主キーが｛教科、テスト日｝である場合、「テストの点数」は主キーによって決まるものの、「教科書」に関しては主キーの「教科」のみで決まってしまいます。このような部分関数従属がある場合は排除する必要があり、排除したものを第2正規形という。
第2正規形を直す方法
→複数のテーブルに分割する。

### 第3正規形
第2正規形に変換したとしてもまだ、間接的に従属関係があるものがあったりします。そのことを推移的関数従属と呼びます。この推移的関数従属によるデータ登録時の不都合を解消するためにはテーブルを分割する必要がある。
簡単に言うと、主キー以外によってそのほかの列が決まることはないようにした表のこと
第3正規形を直す方法
→複数のテーブルに分割する。

第4、5正規形に関しては必要になってきたらやるぐらいでいいんだと思う
Vuexの作用イメージ

# 前置き
はじめてVue.js、Vuexをさわって、storeのことが分からなかったのですが、少し分かったのでそのメモです。

- Vuex

> Vuex は Vue.js アプリケーションのための 状態管理パターン + ライブラリです。
これは予測可能な方法によってのみ状態の変異を行うというルールを保証し、アプリケーション内の全てのコンポーネントのための集中型のストアとして機能します。
[Vuexとは何か？](https://vuex.vuejs.org/ja/)

- Vue.js

> Vue (発音は / v j u ː / 、 view と同様）はユーザーインターフェイスを構築するためのプログレッシブフレームワークです。
[Vue.jsとは？](https://jp.vuejs.org/v2/guide/index.html)

## Vuex の作用イメージ

![Vuexイメージ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628295/de034c6b-d460-b002-c6ea-22fd61a717ae.png)

- state: 状態を持つ
- getter: stateの値を取得する
- actions: 非同期で処理を行う  
(mutationsや他のactionsを呼ぶ、外部APIの呼び出しもここで)
- mutations: 同期でstateの値を更新する

## コード例

```Home.vue
...
  computed: {
    ...mapGetters('hoge', ['getFuga', 'getPiyo']),
  },
  async created(){
    await this.$store.dispatch('hoge.updateFuga');
    await this.$store.dispatch('hoge.updatePiyo');
  },
  methods: {
    ...mapActions('hoge', ['updateFuga', 'updatePiyo']),
  }
```

```actions.ts
interface HogeActions {
  updateFuga: { value: number };
  updatePiyo: { value: number };
}

export interface HogeActionsMapper {
  'hoge/updateFuga': HogeActions['updateFuga'];
  'hoge/updatePiyo': HogeActions['updatePiyo'];
}

const actions: Actions<HogeState, HogeActions, HogeGetters, HogeMutations> = {
  async updatefuga({ commit }): Promise<voide> {
    await commit('fuga');
  },
  async updatePiyo({ commit }): Promise<voide> {
    await commit('piyo');
  },
};
```

```mutaions.ts
export interface HogeMutations {
  huga(state, value: number): void {
    state.huga = value;
  },
  piyo(state, value: number): void {
    state.piyo = value;
  },
};
```

- 状態を管理するためのものなので、不要なら使わない方がすっきりする  
ページをまたいで状態を保持したい場合に使う
- mapGetters、mapActions 以外に mapMutaions や mapSate もある  
ただ、複数の呼び出し方法があると複雑度が増すので、程度ルール付けしておくとよい
AWS CLIのMFA認証を簡単するシェルスクリプト

# 背景

AWS CLIでもMFAでセキュアに利用したいする場合、取得したトークンをCLIの情報として設定する必要があるが、これを手作業でやるととても大変なので自動的にセットしてくれるシェルスクリプトを作成した。

公式には以下の手順で設定する。
https://aws.amazon.com/jp/premiumsupport/knowledge-center/authenticate-mfa-cli/



# 必要なもの

AWS CLI (https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-chap-install.html)
jq (https://stedolan.github.io/jq/download/)
IAMのクレデンシャル(aws_accesskey_id, aws_secret_access_key)


# 今回の環境

Mac 
AWS CLI （aws-cli/2.0.42 Python/3.7.3 Linux/4.19.76-linuxkit docker/x86_64.amzn.2）
jq (1.6)
使用するIAMユーザは__仮想デバイス__でのMFA設定をしておく (https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_credentials_mfa_enable_virtual.html)

# やること

## 通常使うプロファイルとクレデンシャルを登録しておく

今回は foo というプロファイル名で登録しておくとする。

```~/.aws/config

[profile foo]
output=json
region=ap-northeast-1

```

```~/.aws/credentials

[foo]
aws_access_key_id = XXXXXXXXXXXXXXXXXXXXXXXXx
aws_secret_access_key = zzzzzzzzzzzzzzzzzzzzzzzzzzzzz

```

## MFA認証後に使うプロファイルを登録しておく

今回は foo-mfa というプロファイル名で登録しておくとする。

```~/.aws/config

[profile foo-mfa]
output=json
region=ap-northeast-1

```

## MFAのクレデンシャルを自動セットしてくれるシェルスクリプト

```aws_mfa_login.sh

#!/bin/bash

# MFAクレデンシャル情報取得
SESSION_JSON=$(aws --profile $1 sts get-session-token --serial-number arn:aws:iam::$2:mfa/$3 --token-code $4 --output json)
if [ $? -ne 0 ]; then
    exit 1
fi

# jqで必要な項目を変数にセットする
MFA_ACCESS_KEY=$(echo $SESSION_JSON | jq -r '.Credentials.AccessKeyId')
MFA_SECRET_ACCESS_KEY=$(echo $SESSION_JSON | jq -r '.Credentials.SecretAccessKey')
MFA_SESSION_TOKEN=$(echo $SESSION_JSON | jq -r '.Credentials.SessionToken')
MFA_EXPIRATION=$(echo $SESSION_JSON | jq -r '.Credentials.Expiration')

# MFA用クレデンシャルをセットするプロファイル名
MFA_PROFILE_NAME=$1-mfa

# MFA用プロファイルにクレデンシャルをセット
aws --profile $MFA_PROFILE_NAME configure set aws_access_key_id $MFA_ACCESS_KEY
aws --profile $MFA_PROFILE_NAME configure set aws_secret_access_key $MFA_SECRET_ACCESS_KEY
aws --profile $MFA_PROFILE_NAME configure set aws_session_token $MFA_SESSION_TOKEN

echo "New credentials have been set successfully. (profile: $MFA_PROFILE_NAME, expiration: $MFA_EXPIRATION)"

```

第一引数： プロファイル名(今回はfoo)
第二引数： AWSアカウントID
第三引数： IAMユーザID
第四引数： MFAトークン（MFAアプリなどで発行された6桁の数字)

### 説明

`sts get-session-token` でMFAのクレデンシャル情報をJSONで取得する。
この結果を jq コマンドで必要な項目のみ取得する。
`configure set` で credentialファイルにセットする。

### 実行してみる

AWSアカウントIDが 123456789012、 IAMユーザが myid 、仮装デバイスで発行されたトークンが 123456 の場合

```bash

$ ./aws_mfa_login.sh foo 123456789012 myid 123456
New credentials have been set successfully. (profile: foo-mfa, expiration: 2020-08-02T20:20:52+00:00)

```

この時点で、credentialファイルに以下の行が追加されている。

```~/.aws/credentials

[foo-mfa]
aws_access_key_id = XXXXXXXXXXXXXXXXXXXXXXXXx
aws_secret_access_key = zzzzzzzzzzzzzzzzzzzzzzzzzzzzz
aws_session_token = ssssssssssssssssssssssssssssssssssssssssssssss

```




これ以降のコマンド実行には --profile に foo-mfa を指定する。
s3バケットリストを取得する場合は以下のように実行する。

```bash
$ aws --profile foo-mfa s3 ls

　　:
　　:

```

### 補足

私は同時に複数のAWSアカウントを取り扱うため、プロファイルは環境変数ではなく--profileオプションでコマンドに明示的に指定するようにしています。
Flutter for Web で SVG の viewBox

Android や iOS では問題なかったのですが、Flutter for Web で 上手くSVGが表示できなかったので..

![Screen Shot 2020-08-26 at 18.38.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54192/f6ffba1c-9506-e8ca-c6c8-2627aa7025cb.png)

viewBox tag に対応した SVG を 表示する Widget を作ってみた。
たぶん、今後、既にあるイケてるプラグインが対応するだろうから
今だけ使うよう.. 

```dart
import 'package:flutter/material.dart';
import 'package:svg_path_parser/svg_path_parser.dart';


class TwitterIcon extends StatelessWidget {

  final double w;
  final double h;
  final double viewBoxX;
  final double viewBoxY;
  final double viewBoxW;
  final double viewBoxH;
  double devicePixelRatio = 1.0;

  TwitterIcon(this.w, this.h, this.viewBoxX, this.viewBoxY,this.viewBoxW, this.viewBoxH) :super() {

  }

  final paths = [
    ["M23.643 4.937c-.835.37-1.732.62-2.675.733.962-.576 1.7-1.49 2.048-2.578-.9.534-1.897.922-2.958 1.13-.85-.904-2.06-1.47-3.4-1.47-2.572 0-4.658 2.086-4.658 4.66 0 .364.042.718.12 1.06-3.873-.195-7.304-2.05-9.602-4.868-.4.69-.63 1.49-.63 2.342 0 1.616.823 3.043 2.072 3.878-.764-.025-1.482-.234-2.11-.583v.06c0 2.257 1.605 4.14 3.737 4.568-.392.106-.803.162-1.227.162-.3 0-.593-.028-.877-.082.593 1.85 2.313 3.198 4.352 3.234-1.595 1.25-3.604 1.995-5.786 1.995-.376 0-.747-.022-1.112-.065 2.062 1.323 4.51 2.093 7.14 2.093 8.57 0 13.255-7.098 13.255-13.254 0-.2-.005-.402-.014-.602.91-.658 1.7-1.477 2.323-2.41z", Colors.blue],
  ];

  @override
  Widget build(BuildContext context) {
    this.devicePixelRatio =  MediaQuery.of(context).devicePixelRatio;
    return Container(
        width: w,
        height: h,
        child: CustomPaint(
          painter: TwitterIconPainter(this) ,
        ),
        color: Colors.blueGrey,
    );
  }

}

class TwitterIconPainter extends CustomPainter {
  final bool showPath;
  final TwitterIcon parenrt;
  TwitterIconPainter(this.parenrt,{this.showPath = true});

  @override
  void paint(Canvas canvas, Size size) {
    //print("paint 00 ${paths}");
    // device ratio
    var drm = Matrix4.identity();
    //drm.scale(this.parenrt.devicePixelRatio, this.parenrt.devicePixelRatio);

    var viewboxWH = Matrix4.identity();
    double widthScale = this.parenrt.w/this.parenrt.viewBoxW;
    double heightScale = this.parenrt.h/this.parenrt.viewBoxH;
    drm.scale(widthScale, heightScale);
    
    canvas.transform(drm.multiplied(viewboxWH).storage);

    //
    canvas.clipRect(Rect.fromLTRB(0.0, 0.0, this.parenrt.viewBoxW, this.parenrt.viewBoxH));

    // viewbox x,y
    var viewboxXY = Matrix4.translationValues(-1*this.parenrt.viewBoxX, -1*this.parenrt.viewBoxY, 0.0);
    canvas.transform(viewboxXY.storage);

    for(var e in this.parenrt.paths){
      //print("print ${e}");
      Path path = parseSvgPath(e[0]);
      Color color = e[1];
      var paint = Paint()
        ..color = color
        ..strokeWidth = 4.0;
      canvas.drawPath(path, paint);
      if (showPath) {
        var border = Paint()
          ..color = Colors.black
          ..strokeWidth = 1.0
          ..style = PaintingStyle.stroke;
        canvas.drawPath(path, border);
      }
    }
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) => true;
}
```
if文によってネストが深くならないようにするために

「ネストが深い」というワードを最近知りました。カッコが多くなって見づらくなることをこのように言うらしいです。
if文などを多用するときに、できるだけ工夫はして見やすくしたいものです。
今回のケースは、else以降に特に処理を書かない場合に使えます。

```example.js
var conditions;//条件
//普通にversion
if(conditions){
  //実行したい処理
}else{
}

//改善version
if(!conditions) return;
//実行したい処理
```

こうすることで、not条件のときにだけreturnして実行したい処理を動かせます。
UiPath 【ブラウザ操作】セレクターに変数

最近になって話題のUiPathに触れてみました。今回はそれで躓いたところを自分用に備忘録としてまとめてみました。
もっといい方法があるのかもしれないので、いい方法がありましたら教えてください。

#はじめに
UiPathでのブラウザ操作に関係する以下のことをまとめてます。
1.セレクターに変数を使用して動的に使用
　　ex.データスクレイピングで得た値を使って『クリック』アクティビティー

#セレクターとは
そもそもセレクターとは、、、

>ユーザーインターフェース内の特定のアクションを自動化するには、さまざまなウィンドウやボタン、ドロップダウンリストなどを操作する必要があります。ほとんどの RPA 製品は UI 要素の画面位置を利用してこの操作を行いますが、これは信頼性が低い方法です。

>より確実な操作を行えるように、UiPath Studio ではセレクターと呼ばれるものを使用しています。セレクターには、グラフィカルユーザーインターフェース要素とその親要素の属性が XML フラグメントの形で検出されます。

公式によると上記の説明なんですが、個人的にはボタンやブラウザの文字が画面上のどこに存在するか示す住所のようなものと理解しています。

#セレクターに変数を使って勤怠管理システムを自動入力
#####①データスクレイピングで日付データ取得
下記のような画面（一部を抜粋したものです、、、）の勤務管理システムを自動入力する場合、データスクレイピングで9/1～9/30の日付の情報をデータテーブル ExtractDataTableに入れます。
![gazou.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559191/64f53295-d9d6-94fd-0e1b-38d2103a3ccc.png)
#####②『繰り返し（各行）』でExtractDataTableに対してクリックを繰り返す
各日に対してクリックの処理を行いたい、勤務時間を入力したいとすると下記のように変数'日付'に日付データを代入します
![gazou1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559191/fa201127-c1dc-d89b-b00c-444aa526e383.png)
代入アクティビティーの下にクリックアクティビティーど設置して、セレクターエディターを開きます
![セレクターエディター.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559191/2f5e208c-1bf8-9a1b-1dd3-e2af2ff5051b.png)
上記のaanameのままだと、ExtractDataTableのデータ数の回数だけ9/1をクリックしてしまいます。
そこでエディター上の9/1(火)を右クリックし、『変数を選択』をクリックし、変数'日付'を選択します。
![gasou.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559191/cf5abeea-a74f-e52e-6bd0-776202033bd4.png)
これでOK！9/1～9/30まで順番にクリックしてくれます。
ローディングアニメーションをパパッと実装！

# 【１】 Jsプラグインの『PACE』を利用
『PACE』
https://github.hubspot.com/pace/docs/welcome/

上記URLにアクセスして下にスクロールしていくと、いくつかのローディングアニメーションが確認できます。
まずはここでイメージに近いものを選びましょう。
ちなみにデフォルトの色は水色ですが、変えたい場合は
「CHOOSE A COLOR」
ボタンをクリックすると変更できるので試してみてください。

# 【２】 CDNでhtmlにプラグインのjsを読み込ませる
『cdnjs』
https://cdnjs.com/libraries/pace
上記URLにアクセスすると、『PACE』を使うためのCDNが表示されます。

今回「Version」は特に気にせず最新の1.0.2を選びました。
すると一覧の一番上に「〜/pace.min.js」というタグが背景色付きで表示されていると思うので、
その右にある「</>（Copy Script Tag）」ボタンでコピーして&lt;/body&gt;タグ前に貼り付けます。


```html:sample.html
<script src="https://cdnjs.cloudflare.com/ajax/libs/pace/1.0.2/pace.min.js" integrity="sha512-ePSfiGQMIzYzXVQLqWoVC3yxVEHIM5Y3EGh9jPNxpf+hPuLtzPdxJX+lTC3ziPMlDgc5OsM4JThxGwN2DkWEeA==" crossorigin="anonymous"></script>
```

ちなみに属性にある「integrity」や「crossorigin」はなくても変わらず動きますが、
それぞれ、サードパーティによる改変が行われていないことを証明するものなので
ちょっと長いけどそのままコピペしておきましょう。

# 【３】 CSSをコピペ！
ここまででローディングアニメーションの下準備はできたので、
次は見た目の部分です。

### デフォルトで用意されているカラーで、特にカスタマイズしない場合
下記の色でしたら【２】でコピペしたコードの下にたくさんあった「〜/色/pace-theme-テーマ名.min.css」というコードのどれかを選んで&lt;head&gt;タグの中にコピペするだけでできちゃいます！
数えてみたら10色ありましたね。

-black
-blue
-green
-orange
-pink
-purple
-red
-silver
-white
-yellow

例えば「Barber Shop」というテーマを「black」カラーで使いたい場合は下記のようなコードになります。

```html:sample.html
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/pace/1.0.2/themes/black/pace-theme-barber-shop.min.css" integrity="sha512-ITJRv1dtcxW1daw2DC57YZo3xZjeCj38SQYnVLEiFnO2oL8MxIrGuV9f1xIA+d1awA6WCbuUZsVAh9Faxa7U3Q==" crossorigin="anonymous" />
```

ちょっと見つけづらいと思いますが、テーマ名は小文字かつスペースをハイフンでつないでコードに入っているので、
「Barber Shop」を見つけたい場合はブラウザの文字検索機能で「barber-shop」と検索すればすぐ見つかると思います。
カラー名もテーマ名のすぐ前に入っているので、わかりやすいと思います。

### 上記以外のカラーを使いたい場合
【１】で色を変えてみたと思いますが、
テーマ名の下にあった
「COPY TO CLIPBOARD」
ボタンをクリックすると、そのカラーを使った場合のCSSがコピーできます。
それをCSSシートにコピペしてください。
※&lt;head&gt;タグ内に&lt;style&gt;タグで…と言うと量が多いので外部CSSに書いた方が良いと思います。

### CSSをカスタマイズしたい場合
色だけでなく形を変えたり、自分で用意したgifアニメーション画像を使いたい場合なども
「COPY TO CLIPBOARD」ボタンからCSSをコピペしてからいじるといいと思います。

私の場合は、「◯%」という読み込み度の表示が欲しかったので、
「Big Counter」というテーマを使って、最終的に下図のように仕上げました。
![スクリーンショット 2020-08-26 17.33.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440512/c7101385-fda7-192a-b3a5-ef8d6a12ccee.png)


# ローディングアニメーションが終わったらフワッとページを表示させたい
おそらく簡単に組み込んだだけだと、ローディングアニメーション中も後ろでページが崩れつつ表示されていくさまが丸見えになっているかもしれません。
私がそうでした。
もっときれいに表示させたいですよねー…
ネット検索したらいくつかやり方があったんですが、結局どれもうまくいかなかったので、
CSSのanimationプロパティを使ってふんわり表示を実現させました。

### １.　paceクラスの要素以外opacity: 0;に
&lt;body&gt;タグ内の子要素の先頭に下記コードが入っていると思いますが、
これ以外の子要素をopacity: 0;にして見えなくします。
※paceクラス以外をdivで囲ってしまった方がラクでしょう。

```html:sample.html
<div class="pace  pace-inactive">...</div>
```

ローディングアニメーション表示中と終了後ではクラスが変わります。
#### body
　表示中：「pace-running」
　終了後：「pace-done」
#### paceクラス
　表示中：「pace-active」
　終了後：「pace-inactive」

これを利用してCSSを書いていきます。

```html:sample.css
/*ローディングアニメーション表示中　ー　非表示*/
.pace-running #contents_wrapper {
    opacity: 0;
}
/*ローディングアニメーション表示中　ー　1秒かけてフワッと表示*/
.pace-done contents_wrapper {
    animation-name: show;
    animation-duration: 1s;
    
}
@keyframes show {
    0% {
        opacity: 0;
    }
    100% {
        opacity: 1;
    }
}
```

# おわり
多分これで出来るはず！
…というサイトを参考にしてできないことなんてざらにあるので、
もしできなかったら頑張っていろんなページ参考にして頑張ってください…
ローカルプリンターをbatでインストール自動化を試した(Windows10 64bit 1909)

# 経緯
仕事上、クライアントPCの大規模な入替があり、
プリンターインストールを極力自動化したい。
調べたところ、以下の方の記事が使えそうなので社内で検証したところ
上手く動作した。
メモ代わりに記事として記載することにした。

# 参考にした記事
https://qiita.com/apophise/items/5b68afa427fd8f8231ab#comments

# 環境
Windows10 64bit Professional 1909

# bat内容

```
rem 「Windowsで通常使うプリンターを管理する」をオフにする
reg add "HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows" /v LegacyDefaultPrinterMode /t "REG_DWORD" /d "1" /f

rem 今のディレクトリを取得
set CURRENT_DIR=%~dp0

rem 64bitを判定
if %PROCESSOR_ARCHITECTURE% equ AMD64 (

	cd C:\Windows\System32\Printing_Admin_Scripts\ja-JP

	rem ポート追加
	cscript prnport.vbs -a -r ポート名 -h IPアドレス -o raw -n 9100

	rem infファイル指定
	cscript prndrvr.vbs -a -m "infファイルに記載のプリンター名" -v 3 -i "%CURRENT_DIR%driver\foo.inf"

	rem プリンタ追加
	cscript prnmngr.vbs -a -p "プリンターの表示名" -m "infファイルに記載のプリンター名" -r ポート番号

	rem プリンターのプロパティ内[場所]追記
	cscript prncnfg.vbs -t -p "プリンターの表示名" -l "[場所]に記載したい内容"

rem 32bitを判定
) else if %PROCESSOR_ARCHITECTURE% equ x86 (
	echo 32bitです

) 

echo.
echo *----------------------------*
echo ^|プリンタが追加されました。  ^|
echo ^|何かキーを押すと終了します。^|
echo *----------------------------*

pause > nul
```

今回は64bitのみ必要だったため、32bit向けの処理については割愛した。
PRESTOでテーブル項目名にselectとかfromなどがついてる場合の対処方法


PRESTOでデータ抽出する時に、テーブル項目名がselectとかfromになっている場合の対処方法


## 抽出方法

```sql

SELECT
  "select"  -- ""で囲んであげる
  , "from"  -- ""で囲んであげる
FROM
  TABLE1

```

こんな感じで**「""」で囲めば抽出可能**です。
こうしないと、**mismatched input 'from'**などとエラーが表示されて実行できません。

テーブル項目名にfromとか、本当やめて欲しいのですが、前提として抽出することが意識されてない場合、ややつけられやすい項目名でもある気がします。
【健康管理】首・肩のコリを解消する

夕方にはガチガチになって気分も滅入るので、ヨガでコリを解消する。
最近はYoutubeでいろんな人のレクチャを受けられるので、気に入ったのを備忘メモがてらまとめていく。


## 首コリ解消
[![IMAGE ALT TEXT HERE](http://img.youtube.com/vi/Z2_Q6TsoKBg/0.jpg)](http://www.youtube.com/watch?v=Z2_Q6TsoKBg)

## 肩こり解消
[![IMAGE ALT TEXT HERE](http://img.youtube.com/vi/BEbDvIrvePM/0.jpg)](http://www.youtube.com/watch?v=BEbDvIrvePM)
頭頂部刺激するポーズがあるのだけど、めちゃスッキリする。
Windowsのhostsファイルを一瞬で開く方法

ローカル環境でhostsファイルを書き換えてテストしたいことがあるかと思います。
実際のパスはここ`C:\Windows\System32\drivers\etc\hosts`ですが、
いちいち覚えるのも面倒だし、エディタで開こうとすると権限どうのこうので面倒だと思います。

そんな時、`コマンドプロンプト`か`ファイル名を指定して実行`にこれを打ち込んでください。
管理者権限でメモ帳を立ち上げます。

```
powershell -NoProfile -ExecutionPolicy unrestricted -Command "start notepad C:\Windows\System32\drivers\etc\hosts -verb runas"
```

便利ですね。

`notepad`の部分がメモ帳の起動コマンドとなりますので、VSCodeを立ち上げたいときはここを`code`に変更してください。
また、新しいクロスプラットフォームの`PowerShell Core`を使っていらっしゃる方は、`powershell`の部分を`pwsh`に変えていただければと思います。

便利ですね。
Android Studioのソースコードの置き場はどこかについて

## ● 前置き
この記事ではAndroid Studioのソースコードをどこにおいたらいいのかについて話していきます。

この記事を書いた理由：
あまりAndroid Studioのソースコードの置き場所について解説されているサイトがあまりないように感じたから。

# ■ 本題
Android StudioのソースコードもといProjectファイルの置き場所はこちらです：
`C:\Users\User\AndroidStudioProjects\`

ちなみに「User」というところは自分のユーザー名に変えてください。
そしてファイルのパスを開くのがめんどくさいという方は`WindowsキーとRキー`を同時に押して、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677340/684a56c9-5cf2-0b8a-2b2d-525410bad5d7.png)
こちらの画面を開いてから、先ほど紹介したファイルのパスを入力し`Enter`キーを押してください。
そうするとファイルの置き場所が表示されるはずです。

ちなみにこのフォルダはUserフォルダです。こんな感じの！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677340/78df2b70-2956-8834-acc4-2f16b304b80a.png)


# ◆ 補足
さきほど通常のファイルの置き場所を紹介しましたが、それだけではこの記事の内容が物足りない
ので補足情報として下記にあることを付け足しておきます。読みたい方は読んでください。

ここからは「Userフォルダ内にAndroidStudioProjectsフォルダを作るのは嫌だ！」という方向けに
ドキュメントフォルダ内にAndroidStudioProjectsフォルダを作る方法とProjectをAndroidStudioから
作るときにフォルダのパスを通す方法をご説明していきたいと思います。

<font color="red">ちなみに特にこだわりがない方は**やらないことを推奨いたします。**
フォルダのパスを忘れてまって、無駄に紛らわしいフォルダを作成するはめになるかもしれませんので。</font>

それではご説明していきましょう！ちなみにここからは自己責任でやられてください。
まず最初にAndroidStudioProjectsフォルダを作りたいところにAndroidStudioProjectsという名前の
フォルダを作ってください。(今回でいうとドキュメントフォルダのところに)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677340/d749bd7a-06f1-b4f9-3bf3-910815e7d17a.png)
そうしたらAndroidStudioを開いて、「Start a new Android Studio project」というボタンをクリックして、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677340/07835702-484a-fb1e-9b6c-89998770c7d5.png)
お好みのテンプレートを選択して、Configure Your Projectという画面を表示させます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677340/2175521c-e917-8c76-a295-bb2882fef8de.png)
そうしたら、「Save location」という項目の下にあるフォルダのパスを任意のフォルダのパスに
書き換えてください。
(任意のフォルダのパスとは：今回で言うところのドキュメントフォルダの中に作成した
AndroidStuidoProjectsフォルダのパスのことです。)


そしたらそのパスの後ろにProject名(Name項目にあるやつ)を付け足して、このようなパスにしてください。
``C:\Users\user\Documents\AndroidStudioProjects\MyApplication``

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677340/ba920871-c2d6-a32c-4c4c-3177dc62bb4f.png)
これで、任意のフォルダ内にProjectファイルを作成することができたはずです。
<font color="green">最後までご購読くださりありがとうございます。</font>

## ● 用語の補足
ファイル・・データそのもの(データファイル、プログラムファイル、システムファイルなど)
フォルダ・・ファイルの入れ物

ファイルのパス・・ファイルの住所
PATH・・住所

詳しくはこちらをご覧ください：https://www.pc-master.jp/words/file.html
## ✨ 情報提供者
@morikentigerさん
https://www.pc-master.jp/words/file.html
return文

#return
returnの役割は、関数の呼び出し元に「値＝引数」を返すことです。
普関数の実行結果を呼び出し元に返却するのが「 return文」です。
return文に処理が到達すると、関数の実行が完了して呼び出し元に制御が戻ります。 returnの戻り値にデータを指定すると呼び出し元にデータを返すとことができます。


return と print の違い
コマンドプロンプトなどで使用する場合、return と print のどちらを使用しても結果は同じに見えますが、全くの別物です。
return は、戻り値を他の関数でも使用することができる利点があるので、出力するために使用するのではなく、他の関数で戻り値を使用するケースに活用する

return ：値を返して関数を終了する
 print ：コンソールに出力する



##返り値のないパターン
関数の定義
def hello():
    return

関数の呼び出し
hello()

例
def hello(name):
    print('こんにちは', name)
    return
 //以下は実行されない
  print('こんばんは', name)

hello(‘畑本’)

 
## 返り値のあるパターン
関数の定義
def number():
    return 0

関数の呼び出し
a= number()

def number(a,b):
    return a + b

c = number(1, 2)
print(c)

def add_number(a, b):
    return (a + b, a - b)

d, e = add_number(1, 2)
print(d, e)


break
breakはfor文またはwhile文の繰り返し処理の中でif文とセットで使われることが多くあります。
breakを使用する基本的な記述方法
 
while 条件式:
処理を中断する条件を分岐
    if 条件式:
        break
     while文で実行する繰り返し処理

breakとcontinueの違い
breakとよく比較されることが多いのが、continueです。continueもループ処理の中で使用されますが、breakとの大きな違いはbreakがループ処理のブロックから抜けるのに対して、continueはループ処理から抜け出すのではなく、ループ処理の先頭に戻って処理を継続する機能になります。

2重ループを抜ける記述方法
2重ループなどの多重ループを抜ける場合の基本的な記述方法
for 変数 in range():
    for 変数 in range():
        if 抜け出す為の条件式:
        break
    break

ループでのreturn
returnはた関数から値を返す場合に使用されます。
returnで値を返した後はそれ以降の関数の処理は終了する為、ループ内で使用する場合は関数ごと終了してしまうため、ループ処理が終了になります。
タスク管理、再配置可能プログラムとプログラムの４つの性質

#タスク管理
　コンピュータから見た仕事の単位がタスクという、ジョブステップの実行準備が整うことで
　タスクが生成される
**タスクの状態遷移**
　再生されたタスクには以下の状態がある。
　・実行可能状態(READY)
　　いつでも実行が可能な、CPUの使用権が回ってくるのを待っている状態。
　　生成直後のタスクは、この状態になって、CPUの待ち行列に並んでいる。
　・実行状態(RUN)
　　CPUの使用権が与えられて、実行中の状態
　・待機状態(WAIT)
　　入出力処理が発生したので、その終了を待っている状態。
　上記の状態を図で表すと以下の通りになる。
　　![図75.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686519/c6e7adfe-845f-5589-35e0-101eb4bbd343.png)

#ディスパッチャとタスクスケジューリング
 　実行可能状態で順番待ちしているタスクにCPUの使用権を割り当てることを
　**ディスパッチャ**という。　また、「どのタスクに使用権を割り当てるのか」を決めるためには、
　タスクの実行順序を定める必要がある。これを**タスクスケジューリング**という。
　
**タスクスケジューリングの方式**
　様々な方式があるが、なかでも以下の３つが代表的。
　
　**到着順方式**
　実行可能状態になったタスク順に、CPUの使用権を割り当てる方式。
　タスクに優先度の概念がないので、実行の途中でCPU使用権が奪われることはない。
　
　**優先順(プライオリティ順)方式**
　タスクにそれぞれ優先度を設定し、その優先度が高いものから順に実行していく方式。
　実行中のタスクよりｍじょ優先度の高いものが待ち行列に追加されると、実行の途中でCPU使用権が奪われる。

　**ラウンドロビン方式**
　CPUの使用権を一定時間ごとに切り替える方式
　実行可能状態になった順番でタスクにCPU使用権が与えられるが、
　既定の時間内に処理が終わらなかった場合は次のタスクに使用権が与えられ実行中だったタスクは待ち行列の最後に回される。

**割り込み処理**
　実行中のタスクを中断して、別の処理に切り替え、そちらが終わるとまた元のタスクに復帰するという
　処理のことを**割り込み処理**と呼ぶ
　割り込み処理は実行中のプログラムが原因で生じる内部割込みとプログラム外の要因で生じる外部割込みに分かれる

#再配置可能プログラムとプログラムの４つの性質
　再配置可能プログラムなら、主記憶上のどこに配置しても問題なく実行できる。
**4つのプログラムの性質**
　再配置可能プログラムは以下の4つのプログラムがある
　**再配置可能(リローケータブル)**
  ![図76.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686519/81d56eb8-362d-654b-6aba-5366946c9e0b.png)
　**再使用可能(リユーザブル)**
  ![図77.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686519/dd8fb2b4-dc3c-9982-016e-a767b8ea799a.png)
　**再入可能(リエントラント)**
　![図78.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686519/39d10ec0-6192-c82c-e380-6649df5d1dde.png)
　**再帰的(リカーシブ)**
 ![図79.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686519/e28b14c1-08b7-8627-dd27-a287d8336689.png)





#以上
【Android】定期購入の一時停止、再開がすべてのアプリで有効になるらしい

最近になって、GooglePlayConsoleに以下のような注意文言が出るようになりました。

![一時停止.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106030/ba6fb172-ade7-948e-37c7-d5b6c8952bef.png)

どうやら、現状オフになっている機能である定期購入の一時停止・再登録（再購入）が、2020/11/01からすべてのアプリでONになってしまうとのことです。
それぞれどういったものか、どんな対応が必要になりそうかを簡単にまとめてみます。
半分が自分用のメモなので、読みづらかったらすみません:cold_sweat:

##定期購入を一時停止する
ドキュメントには以下のように書いてあります。

>ユーザーが定期購入を一時停止できるようにすることで、自発的な解約を防ぐことができます。一時停止機能を有効にすると、契約期間の間隔に応じて、ユーザーは 1 週間から 3 か月の間で定期購入を一時停止することを選択できます。一時停止機能を有効にすると、定期購入センターと解約フローの両方に表示されます。1 週間や 3 か月の一時停止制限は、随時変更される可能性があります。また、年次定期購入は一時停止できません。

要は、「解約する前に１個選択肢を増やしたよ」ってことです。
これにより、定期購入を実装しているアプリではステータスを確認する手間が増えることになります。
例を立てて考えてみたいと思います。

>例）2020/09/01にサブスクのプランをアップグレード。2020/09/10に一時停止し、2020/09/20に再開した。

フリープランとプレミアムプランがあったとして、期間で見るとユーザーは以下のようにプランを遷移することとなります。

・2020/09/01～2020/09/10：プレミアムプラン
・2020/09/10～2020/09/19：フリープラン
・2020/09/20～2020/10/10：プレミアムプラン

これを実現するにはアプリを起動したタイミングでその状態を取得する必要があります。
**Google Play Developer API** or **リアルタイム デベロッパー通知（RTDN）**のいずれかの方法で取得できるみたいです。

方法については以下をご確認ください。
[**定期購入を一時停止する**](https://developer.android.com/google/play/billing/billing_subscriptions#pause)

状態を確認し、一時停止となっていた場合はプレミアムプランを使用できないようにする必要があります。
もしプラン変更ではく、定期購入によるポイント付与のような仕組みを導入している場合は、サーバーでポイント付与のチェックを行なっているパターンが多いと思いますので、サーバー側で上記の状態を取得して一時停止になっていたらポイント付与をしないよう調整が必要になるはずです。


##定期購入を再開する
ドキュメントに書いてある文を羅列します。

>注: 再開機能はデフォルトで有効になっており、定期購入を有効にしたすべてのデベロッパーが利用できます。再開機能をテストして、再開を適切に処理できるかどうかを確認しておくことを強くおすすめします。テストを簡単に実施できるよう、すべてのライセンス テスト アカウントの再開機能を有効にしてあります。定期購入のテストの詳細については、定期購入固有の機能をテストするをご覧ください。
この機能は Google Play Console でオプトアウトできます。その場合、[ストアでの表示] > [アプリ内アイテム] > [定期購入の設定] に移動して、[ユーザーが Google Play で定期購入を再開することを許可します] チェックボックスをオフにします。
解約された定期購入は、有効期限まで Play ストア アプリに表示されたままになります。ユーザーは、有効期限が切れる前に解約した定期購入を再開できます。Play ストア アプリ内の [定期購入] で [再開] をクリックします。

要は、「解約されてもしばらくはPlayストアアプリ内に表示して、そこから購入できるようにしといたよ」ってことです。

これによって自アプリを経由せずに購入できるようになってしまうので、購入時にプラン変更などを行なうためにレシートをサーバーに渡し通知していた場合はその処理を通らないことになるので、起動時にチェックし購入されていた場合の処理を追加する必要があります。（※RTDNを使わない場合のみ）

方法については以下をご確認ください。
[**定期購入を再開する**](https://developer.android.com/google/play/billing/billing_subscriptions#restore)


##最後に
2020/11からすべてのアプリでこの設定がONになってしまうため、それまでにテストして必要な実装を行なう必要があります。
テストする場合は、GooglePlayConsoleから一時停止・再開の機能をライセンステスターのみ有効とすることができますので
それで実際に一時停止・再開を試してみてください。

一時停止も再開もPlayストアのWebページかアプリからしかできないので、しばらくの間はユーザーにはあまり触れられることのない仕組みかもしれません。
なので今のうちに仕組みを理解し、対応できるよう頑張りましょう！

【参考リンク】
https://developer.android.com/google/play/billing/billing_subscriptions
AWS EC2 で Code Deployのセットアップ

## 環境
- EC2
- Amazon Linux 2

## ルートユーザーとしてログインする

```bash
sudo su -
```

## shellを作成する

```bash
vi install.sh
```

## 以下のコードを貼り付ける

```bash
#!/bin/bash
sudo yum update
sudo yum install ruby
sudo yum install wget
cd /home/ec2-user
wget https://aws-codedeploy-ap-northeast-1.s3.ap-northeast-1.amazonaws.com/latest/install
chmod +x ./install
./install auto
```

## 実行権限を付与

```bash
chmod +x install.sh
```

## install.shを実行

```bash
./install.sh
```
【oracle】ROWIDは登録順じゃない

# はじめに
こんにちは。
だいぶ前に調べた内容ですが、メモとして残したいと思います。

時々、DBに登録したレコードを登録順に出力してほしいと言われることがあります。
この対応として、`ROWIDでORDER BY`しておきました！という声を耳にしたことがありませんか。
※筆者も駆け出しのとき、間違えていたと記憶しています。
タチが悪いのは、テストしても登録順に並んでいる時もあるんです。。（←言い訳）


結論から言うと、`ROWIDでORDER BY`しても`登録順に取得できない`です。
そもそも登録順に取得したいという要件が、本当に必須かが怪しいのですが、、それは置いておきます。
あえてやるという事であれば、`登録順を保持する列を追加する`必要があります。

`ROWID`がなにかを理解してもらえれば、「`ああ、全然違うねー`」と分かっていただけるかと思います。


# ROWIDってなあに？？
これに尽きるかと思います。
`ROWID`は、どこにレコードの情報があるかという`データの保存場所`の情報を保持しています。
内容は、表領域番号、相対ファイル番号、ブロック番号、スロット番号です。
あの謎の長い文字列は`データの保存場所`を`BASE64に変換した文字列`です。

ここからちょっと小難しいので、`まとめ`までサラッと流してもいいです。

**・BASE64変換**
値をアルファベット(a～z,A～Z)と数字(0～9)、一部の記号(+,/)に置き換える。
バイナリデータを6bitずつ取り出し(足りない分は0を追加)、6ビットとAscii文字の変換表を用いて、4文字ずつにする(4文字に満たない場合は=を追加)。
参考: [wiki Base64](https://ja.wikipedia.org/wiki/Base64)

**・ROWIDの形式：OOOOOOFFFBBBBBBSSS**
　O：表領域番号 (データ長：6)
　F：相対ファイル番号 (データ長：3)
　B：ブロック番号 (データ長：6)
　S：スロット番号 (データ長：3)
ROWIDは、これをBASE64変換して格納しているという事になります。

# おまけ
ROWIDの中身を見てみたいときは、下記で確認できます。

```
//BASE64のエンコード/デコード
declare
     target   varchar2(255);
     encoded  varchar2(255);
     decoded  varchar2(255);
begin
     -- エンコード対象文字列
     target := 'Hello01!';
     dbms_output.put_line('target=' || target);

     -- base64でエンコード
     encoded  := utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(target)));
     dbms_output.put_line('encoded=' || encoded);
     
     -- base64でデコード
     decoded  := utl_raw.cast_to_varchar2(utl_encode.base64_decode(utl_raw.cast_to_raw(encoded)));
     dbms_output.put_line('decoded=' || decoded);
end;
/
```

# まとめ
ROWIDは、データの保存場所の情報です。
登録順でソートするには、登録順を保持する列を追加する必要があります。


以上ですが、ご参考になれば幸いです。
正規表現を使用するバリデーションの実装

#概要
今回は、正規表現を使用したバリデーションの実装方法についてまとめていきます。

最初に、バリデーションと正規表現についてざっくり述べておきます。

##バリデーション
データを保存する際にバリデーションをかけることによって、無効なデータを弾いてくれます。
空のデータを登録できなくしたり、文字列に含まれなきゃいけない文字を指定したり、文字数制限をしたり、、、
様々なバリデーションがあります。

代表的なものとして、nicknameを入力する際に空にならないようにバリデーションをかけてみましょう。

```ruby:models/user.rb
---省略---
validates :nickname, presence: true
---省略---
```

こんな感じでそれぞれの入力項目にバリデーションをかけます。

##正規表現
正規表現とは、記号と文字列を組み合わせた構文のことで、検索対象となる文から指定した文字列パターンを抽出することができます。

よく使うものだと、
\A...文字列の先頭にマッチする
\z...文字列の末尾にマッチする
のような感じで他にもいくつかあります。

検索すればたくさんでてくるので覚える必要はなさそうです。

##正規表現を使用したバリデーション
今回特にまとめておきたいのが、正規表現を使用したバリデーションです。

具体的には、パスワードに入力するデータを半角英数字にするというバリデーションを実装します。

ポイントは、正規表現を変数に代入してあげて、それをバリデーションに組み込んであげるという感じで書いていきます。

```ruby:models/user.rb
  validates :password, presence: true
  validates :password, length: { minimum: 6 }
  VALID_PASSWORD_REGIX = /\A[a-z0-9]+\z/i
  validates :password, format: { with: VALID_PASSWORD_REGIX }
```

上から順に
・パスワードが必須であること
・パスワードが6文字以上であること
・パスワードは半角英数字であること
のバリデーションが組まれています。
【メモ】vCSA6.0構築で詰まったこと

#vCSA6.0を初めて構築したときのメモ。

今までvCSA6.5しか構築した事がなかったので、installerからデプロイできないのも初めて知った。
で、vCSAを構築する手順は以下の通り。
備忘録のために、vCSA構築手順は後ほど異なる記事で書こうと思う。

1. DNSサーバ作成  
　→これはvCSA6.5の時にDNSサーバが必須だったのでこちらも構築（vCSA６.０も必須）。vCSAを作成するESXi上に作成。  
　 そしてESXiのDNS設定を作成したDNSサーバに指定。

2. 作業用端末にクライアント統合プラグインのインストール
　→これが初めて。  
　 vCSA6.0のisoイメージを作業用端末にマウントして、vcsaフォルダ内の「VMware-ClientIntegrationPlugin-6.0.0.exe」を実行すると、二つインストールされる。  
　 一つは「VMware Client Integration Plug-in」。  
　 もう一つは「VMware Plug-in Sesrvice」。  
　 後述するが、この「VMware Plug-in Sesrvice」のインストールで詰まった。

3. isoイメージの中の「vcsa-setup.html」を実行。私はGoogle Chrome使った。  
　そしてウィザードに従ってインストールを進めていく。


##詰まった事
「VMware-ClientIntegrationPlugin-6.0.0.exe」を実行すると、
まずはじめに「VMware Client Integration Plug-in」のインストールが開始される。
こちらは難なく進み、1分程度でインストール完了。

インストール完了後、「VMware Plug-in Sesrvice」のインストールが開始される。
こちらは途中までは難なく進むが、
「このパッケージに問題があります」という旨のエラーが出てインストールされない。

ちなみにパッケージはダウンロードしてきたホヤホヤのもの。
サイズも合っているのになぜ？？？？

*日本語でググっても出ない。。。*

と、日本語縛りでググってしまったのがダメだった。
インストールログを見たりして、小１時間程度苦労することに。

いろいろな言葉を組み合わせてググっている時に、このページにたどり着いた。
https://kb.vmware.com/s/article/59704?lang=ja

今回はvCSA6.0 U3jのインストールだからバージョンも違うしアップデートでもない。
だが、事象は同じ。

このサイト通りにエラー画面でストップし、「%TEMP%」から「vcredist_x86.exe」をダウンロードだとかその辺のフォルダに移動。
なぜ移動するかというと、「vcredist_x86.exe」を実行する時にエラー画面を付けっぱなしだとインストーラーが進まないのと、エラー画面を閉じると「vcredist_x86.exe」が「％TEMP％」から消えてしまうからだ。

移動してからエラー画面を閉じ、「vcredist_x86.exe」を実行。

インストーラーが表示され、無事インストール。
で、ようやくインストール完了！！！

ここに来るまでめちゃくちゃ時間を使ってしまった。（半日くらい・・・）
その後のvCSAインストールは特に問題なく完了。
なので、次構築する時はスイスイ行けるようにメモ。。
シェルとシェルスクリプト

<h2>シェル環境のカスタマイズ</h2>
>環境変数とシェル変数

　ユーザー環境はさまざまな変数（環境変数、シェル変数）によって定義されています.環境変数とは、シェル自身またはそこから起動したすべてのプロセスで有効となる変数のことです.シェル変数とは、そのシェル内でのみ有効となります.シェル変数を***export***コマンドでエクスポートすることで環境変数に変更できます.また、***env***コマンドや***printenv***コマンドで環境変数を、***set***コマンドでシェル変数と環境変数を表示できます.

>シェルのオプション

構文：***set [-o][+o][オプション]***　-o指定でオプション有効化、+oでオプション無効化

>エイリアス

　エイリアス機能（***ailias***コマンド）を使うことでコマンドに別名を付けたり、コマンドとオプションをひとまとまりにして新しいコマンドのように扱うことができるようになります.解除するには、***unalias***コマンドを使います.

　例）alias ls = 'ls -l'
　　　ただし、エイリアス機能を使っていても***\ls***などと入力すればオプションなしで実行できます.

>関数の定義

　***function***コマンドを使うことでbashシェル上で利用できる独自の関数を定義できます.

　構文：***[function] {関数名}() { コマンド }***
　　　　functionは省略可能.{}内には半角スペースが必須.

　定義した関数を表示するには、***declare -f***コマンド、削除するには***unset***コマンドを使います.

>bashの設定ファイル

　シェルの起動と同時に環境変数やエイリアス、関数を自動的に設定するには設定ファイルに記載します.

- [ ]/etc/profile　…ログイン時に実行されます.
- [ ]/etc/bash.bashrc　…bash起動時に実行されます.

<h2>シェルスクリプト</h2>
>シェルスクリプトの基礎

　シェルスクリプトはテキストファイルにコマンドを記述したものです.実行方法は、***bash {スクリプトファイル名}***、***source {スクリプトファイル名}***、「***.***」、「***chmod a+x {スクリプトファイル名}***」とします.

>ファイルのチェック

　構文：test {条件文}
　　　　条件文：真であれば0を返し、偽であれば0以外の値を返します.
　　　　　　　　-f {ファイル}　…ファイルがあれば真
　　　　　　　　-d {ディレクトリ}　…ディレクトリがあれば真
　　　　　　　　数値1 -eq 数値2　…数値1と数値2が等しければ真
　　　　　　　　文字列1 = 文字列2　…文字列1と文字列2が等しければ真

>制御構造

構文1:
　if 条件式
　then
　　　実行文1
　else
　　　実行文2
　fi

構文2:
　case 式 in
　　値1）実行文1;;
　　値1）実行文1;;
　esac

構文3：
　for 変数名 in 変数に代入する値のリスト
　do
　　実行文
　done

　※***seq***コマンドを使って、'seq 10 15'などとすることで10,11,12,13,14,15のリストが生成されます.

構文4:
　while 条件文
　do
　　実行文
　done

>シェルスクリプトの実行環境

　実行するには、スクリプトの先頭で***#!/bin/bash***と記載しておきます.
Watson StudioのGalleryからデータをプロジェクトにロードする

Watson StudioのGalleryはデータセット、Notebook, サンプルデータやサンプルプロジェクトが公開されてるコレクションです。以前はこれをWatson Studioで使う場合は、ここから自分のPCにダウンロードして、 それをWatson Studioのプロジェクトにアップロードするい必要がありましたが(たぶん）、今現在は直接プロジェクトにロードできます。

この記事では、機械学習初心者には欠かせないみんな大好き(?) オープンデータ「Irisデータセット」をWatson StudioのGalleryからプロジェクトにロードする方法を説明します。

「Irisデータセット」はUCI（カリフォルニア大学アーバイン校）が配布している、3種類のあやめ(Iris アイリス)の数値データです。初心者向けの機械学習用のデータとしてよく使われています。

このデータがWatson StudioのGalleryにありますので、これをWatson Studioのプロジェクトにロードみましょう。

#0. 前提はIBM Cloudのアカウント、 Watson Studio サービスとProject作成されていること
##前提1: 有効なIBM Cloudのアカウント
お持ちでないかたは [こちら](https://cloud.ibm.com/registration?cm_mmc=Email_Events-_-Developer_Innovation-_-WW_WW-_-nishito\tokyo\japan&cm_mmca1=000019RS&cm_mmca2=10004805&cm_mmca3=M99938765&cvosrc=email.Events.M99938765&cvo_campaign=000019RS
) から取得お願いします。
取得方法の動画はこちらです: https://youtu.be/Krn1jQ4iy_s

##前提2: Watson Studio サービスとProjectが作成済
Watson Studio サービスとProjectが作成済でない場合は、以下を参照してを参照して、Watson Studio サービスとProjectの作成を行ってください。
[Watson Studio サービスとProjectの作成](https://qiita.com/nishikyon/items/ba698b638300848b746e)

#1. IBM CloudにログインしてWatson Studioのホームページを開く
[こちら](https://qiita.com/nishikyon/items/ba698b638300848b746e#2-watson-studio-%E3%81%AE%E8%B5%B7%E5%8B%95)を参考に、IBM CloudにログインしてWatson Studioのホームページを開いてください。

#2. ナビゲーションメニューから、「Gallery」をクリック
 Watson Studioのギャラリーを開きます。右上の角の4本線、ナビゲーションメニューをクリックし、「Gallery」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/e2841a17-6be5-43ff-1020-0490801fd542.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/dbf619a1-1709-ff7d-5328-c16ce5867f40.png)

#3. 「Gallery」画面が表示されたら、検索フィールドにirisと入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/56e04f68-fbbe-846f-e7c6-a172124f5f68.png)

#4. Irisが含まれるデータが表示されるので、「データ　UCI: Iris」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/3173a901-e349-a335-6ad0-402852ad0e63.png)

#5. 表示されたUCI: Irisの画面の「プロジェクトに追加」ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/2ce1efa9-6bf5-ac36-a942-890f55c36cbc.png)

#6. データをロードしたいプロジェクトを選択して「追加」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/d7e659c7-a5a1-d7a0-2fdd-a1087de3931f.png)

#7. 「プロジェクトの表示」をクリックしてプロジェクトを開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/784dea7e-9e3f-f12c-c1ab-3906d7c93543.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/8b39c8c2-dcaf-0df7-a14c-0e548a20d387.png)

データが指定したプロジェクトにロードされました!

# まとめ
いかかでしたか？　いとも簡単にデータがロードできたと思います。Galleryには他にも使えそうなデータセット、Notebook, サンプルデータやサンプルプロジェクトがありますので、Galleryを開いて検索で探してみてください。
PySimpleGUI

# 参考
[PySimpleGUI](https://pysimplegui.readthedocs.io/en/latest/)

# 0. 仮想環境準備(venv) 
グローバル環境を汚したくなかったので`venv`で仮想環境を作ってそこで作業することにしました。

```bash:仮想環境起動
$ python -m venv myvenv
$ cd myvenv/
$ source bin/activate
(myvenv)$ pip list
pip (7.1.2)
setuptools (18.2)
```

# 1. すぐに始める
## 1-1. PySimpleGUIを`pip`でインストールする

```bash:インストール
(myvenv)$ pip install pysimplegui
(myvenv)$ pip list
Package     Version
----------- -------
pip         20.2.2
PySimpleGUI 4.29.0
setuptools  18.2
```
## 1-2. サンプルコード
[This Code](https://pysimplegui.readthedocs.io/en/latest/#this-code)

```python:sample.py
import PySimpleGUI as sg

sg.theme('DarkAmber')   # テーマカラー
# ウィンドウ内のレイアウト
layout = [  [sg.Text('Some text on Row 1')],
            [sg.Text('Enter something on Row 2'), sg.InputText()],
            [sg.Button('Ok'), sg.Button('Cancel')] ]

# ウィンドウを生成する
window = sg.Window('Window Title', layout)
# "events"を処理するためのイベントループとインプットの"valuesを取得する処理
while True:
    event, values = window.read()
    if event == sg.WIN_CLOSED or event == 'Cancel': # if user closes window or clicks cancel
        break
    print('You entered ', values[0])

window.close()
```
## 1-3. 実行する

```bash:実行
(myvenv)$ python sample.py 
```
### 起動したウィンドウ
![スクリーンショット 2020-08-26 17.08.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197227/5108ec79-42ef-9bf2-b2c5-061599641a38.png)

### 文字入力
"Hello, World!"と入力して「Ok」を押すと…
![スクリーンショット 2020-08-26 17.13.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197227/a129c3f6-1f95-0ebe-ffe8-f9969bd2f388.png)

ターミナルに入力した文字が出力されます。

```bash:ターミナル出力
You entered   Hello, World!
```

# まとめ
ブラウザを使うWebアプリと違って"イベントループ"を意識してコーディングできるので良いなと感じました。
Joblibを使ってみる(1/2)

# Joblibを利用して処理を並列化してみる
Pythonでの[Joblib](https://joblib.readthedocs.io/en/latest/)を利用する事で並列処理が容易に記述できるので、その手順についてのメモ

## Install
`pip`コマンドを利用してインストール

```terminal
> pip install joblib
```

## 並列処理のお試し

まずは、モジュールのインポート
時間計測用に`elapsed_time`も定義しておく

```python3
import time
from joblib import Parallel, delayed


def elapsed_time(func):
    print(f"Function name: {func.__name__}")
    start = time.time()
    result = func()
    print(result)
    elapsed = time.time() - start
    print(f"Elapsed: {elapsed}")
    print('-' * 20)
```

## 時間のかかる適当な処理

時間計測をするために適当な計算を実行する

```python3
def test_func():
    result = 0
    for i in range(10 ** 7):
        result += 1
    return result
```

### そのまま実行

順番に10回実行する場合

```python3
def normal():
    result = 0
    for i in range(10):
        result += test_func()
    return result
```

### 並列に実行

`joblib`で並列化を行う場合、実行する関数を`delayed`でラップしたものをリスト等として準備する必要がある
ここでは、test_func()を10回実行するため、リスト内包表記で10個分の要素を作成

```python3
jobs = [delayed(test_func)() for i in range(10)]
```

`jobs`リストの中身はこんな具合

```pytnon3
print(jobs)
[(<function test_func at 0x7fa94f117700>, (), {}), (<function test_func at 0x7fa94f117700>, (), {}), (<function test_func at 0x7fa94f117700>, (), {}), (<function test_func at 0x7fa94f117700>, (), {}), (<function test_func at 0x7fa94f117700>, (), {}), (<function test_func at 0x7fa94f117700>, (), {}), (<function test_func at 0x7fa94f117700>, (), {}), (<function test_func at 0x7fa94f117700>, (), {}), (<function test_func at 0x7fa94f117700>, (), {}), (<function test_func at 0x7fa94f117700>, (), {})]
```

これを`Parallel`で並列処理

```python3
def parallel():
    jobs = [delayed(test_func)() for i in range(10)]
    result = Parallel(n_jobs=-1)(jobs)
    return result
```

`n_jobs`で並列ジョブの数を指定
`-1`を指定するとシステムに合わせた最大値となる

### オーバヘッドの少ない並列処理

コンテキストマネージャーを利用して実行

```python3
def parallel_reuse():
    result = None
    jobs = [delayed(test_func)() for i in range(10)]
    with Parallel(n_jobs=-1) as p:
        result = p(jobs)
    return result
```

# 並列処理の実行

それぞれの処理を呼び出す部分を追記

```python3
if __name__ == "__main__":
    elapsed_time(normal)
    elapsed_time(parallel)
    elapsed_time(parallel_reuse)
```

実行結果は下記の通り

```terminal
Function name: normal
100000000
Elapsed: 4.5094709396362305
--------------------
Function name: parallel
[10000000, 10000000, 10000000, 10000000, 10000000, 10000000, 10000000, 10000000, 10000000, 10000000]
Elapsed: 1.9986412525177002
--------------------
Function name: parallel_with_reuse
[10000000, 10000000, 10000000, 10000000, 10000000, 10000000, 10000000, 10000000, 10000000, 10000000]
Elapsed: 1.7216787338256836
--------------------
```

> Macbook Air上で実行しているために、負荷がかかるとCPUの温度が上昇し、駆動周波数が低下するので計算速度はおちてしまうが、並列化の効果がちょっと見える

今回はここまで:smile:
pd.DataFrameに関するあれこれ

## はじめに

pandas.DataFrame（pd.DataFrame）に関するメモ．

### DataFrameの初期化

```
# 空のDataFrame
df = pd.DataFrame(columns=[列名のリスト])

# csvファイルから取得
df = pd.read_csv([ファイルのパス])
df = pd.read_csv([ファイルのパス], names=[列名のリスト])  # ヘッダーなしの場合
df = pd.read_csv([ファイルのパス], sep=',')  # 区切り文字を指定する場合
df = pd.read_csv([ファイルのパス], delim_whitespace=True)  # 空白区切りの場合
df = pd.read_csv([ファイルのパス], comment='#')  # コメント文を含む場合
```

参考：[pandasでcsv/tsvファイル読み込み（read_csv, read_table）](https://note.nkmk.me/python-pandas-read-csv-tsv/)

### DataFrameに辞書を追加

```
df = df.append([辞書], ignore_index=True)
```

リストの```append```と違い，```df.append()```だけではDataFrameが更新されないことに注意．

### DataFrameから要素を抽出

```
#     'a' 'b'
# 0 |  1   2
# 1 |  3   4

# 要素を取得
df.loc[0,'a'] # -> 1

# 行を取得
dist(df.loc[0,:]) # -> {'a':1, 'b':2}

# 列を取得
list(df.loc[:,'a']) # -> [1, 3]
```

参考：[pandasで任意の位置の値を取得・変更するat, iat, loc, iloc](https://note.nkmk.me/python-pandas-at-iat-loc-iloc/)

### DataFrameから条件をみたす行を抽出

```
# 単純な条件
df = df[df['num']>0]
df = df[df['str']=='Yes']
df = df[df['str'].isin(['Yes', 'No'])]  # 候補が複数ある場合

# 文字列に関する条件（欠損値NaNを含む場合は'na=False'をオプションに加える）
df = df[df['str'].str.startswith('Y')]  # 先頭の文字列
df = df[df['str'].str.contains('e')]  # 中に含む文字列
df = df[df['str'].str.endswith('s')]  # 末尾の文字列

# 複数の条件
df = df[(df['num']>0) & (df['str']=='Yes')]  # andの代わりに&
df = df[(df['num']>0) | (df['str']=='Yes')]  # orの代わりに|
```

参考：[pandas.DataFrameの行を条件で抽出するquery](https://note.nkmk.me/python-pandas-query/)

### その他

```
# 指定した列に従いソート
df = df.sort_values('a', ascending=True)

# インデックスの振り直し
df = df.reset_index(drop=True)

# DataFrameをcsvファイルに保存
df.to_csv([ファイルのパス], index=False)
```