OmniAICreator/Qiita-1.07M huggingface dataset:
【MPAndroidChart】グラフ外の余白を無くす


# 概要
グラフ外の余白を無くす。

|余白あり|余白なし|
| ---- | ---- |
| <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694762/fe6b0f18-2062-3818-f4bf-8f6fc9636069.png" width="300"> | <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694762/2207e04d-e205-c62f-8fa0-f51238f6a963.png" width="300"> |

`setViewPortOffsets(0f, 0f, 0f, 0f)`で余白が無くならないことがあったので、原因と対処法を記述。

# 原因
`setViewPortOffsets`の定義を見ると、別スレッドで`offset`をセットしている。そのため、表示タイミングによっては`offset`の反映がされないことがあった。

```Java
    public void setViewPortOffsets(final float left, final float top,
                                   final float right, final float bottom) {

        mCustomViewPortEnabled = true;
        post(new Runnable() {

            @Override
            public void run() {

                mViewPortHandler.restrainViewPort(left, top, right, bottom);
                prepareOffsetMatrix();
                prepareValuePxMatrix();
            }
        });
    }
```

# 対処法1
`invalidate`の処理を遅らせる。

レイアウト
```activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<com.github.mikephil.charting.charts.BarChart
	xmlns:android="http://schemas.android.com/apk/res/android"
	android:id="@+id/chart"
	android:layout_width="match_parent"
	android:layout_height="match_parent"/>
```

処理
```MainActivity.kt
val value = listOf(
	BarEntry(0f, 2f),
	BarEntry(1f, 3f),
	BarEntry(2f, 9f),
	BarEntry(3f, 7f),
	BarEntry(4f, 5f)
)
binding.chart.data = BarData(BarDataSet(value, ""))

binding.chart.setViewPortOffsets(0f, 0f, 0f, 0f)
Handler(Looper.getMainLooper()).postDelayed({ binding.chart.invalidate() }, 100)
```



# 対処法2
グラフの外側にあるビューを削除し、`minOffset`を0にする。`HorizontalBarChart`の場合、`xAxis.position`に`TOP_INSIDE`か`BOTTOM_INSIDE`を指定しないと余白ができた。
対処法1よりも安全。

レイアウト
```activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<com.github.mikephil.charting.charts.BarChart
	xmlns:android="http://schemas.android.com/apk/res/android"
	android:id="@+id/chart"
	android:layout_width="match_parent"
	android:layout_height="match_parent"/>
```

処理
```MainActivity.kt
val value = listOf(
	BarEntry(0f, 2f),
	BarEntry(1f, 3f),
	BarEntry(2f, 9f),
	BarEntry(3f, 7f),
	BarEntry(4f, 5f)
)
binding.chart.data = BarData(BarDataSet(value, ""))

//凡例の削除
binding.chart.legend.isEnabled = false

//x軸の数値削除
binding.chart.xAxis.setDrawLabels(false)

//HorizontalBarChartのみ必要
binding.chart.xAxis.position = XAxis.XAxisPosition.BOTTOM_INSIDE

//y軸の数値削除
binding.chart.axisLeft.setDrawLabels(false)
binding.chart.axisRight.setDrawLabels(false)

//オフセットを0にする
binding.chart.minOffset = 0f

binding.chart.invalidate()
```
Python3エンジニア認定基礎模試試験2回目　-間違えた問題-

<H1>獲得点数　725/1000点</H1>
<H2>正答率: 72.5 % ( 29問 / 40問 正解 )</H2>

```python
仮想環境を生成、管理するのにつかわれているスクリプトを選択肢の中から選びなさい。

A,pyvenv
```

```python
Pythonの対話型インタプリタの中で存在するものを選択肢の中から選びなさい。

A,IPython
```
```python
以下のプログラムを実行した際の出力結果を選びなさい
x = ["a","b","c","d","e"]
print(x[:-3])
#カンマを意識すると理解できる
A,['a', 'b']
```

```python
以下のプログラムをインタプリタにて実行した際の出力結果を選びなさい。
(1,3,5) < (1,2,3,4)

A,FALSE
```
:::note info
インフォメーション
1ステージの3-5より
1ステージの2-3-4は後であるか？
と読み替えるとわかりやすい。
:::

```python
Pythonの関数について正しいものを選択肢から選びなさい。

A,関数をコールするときは、必ず位置引数が先でキーワード引数を後にしなければならない。

ーーーーーーーーーーーーーーーーーーーーーーーーーー
def 関数名(仮引数1, 仮引数2): #ここの仮引数が位置引数、順番が紐づく
    ....
    return

関数名(実引数1, 実引数2)
ーーーーーーーーーーーーーーーーーーーーーーーーーー
def 関数名(仮引数1, 仮引数2):
    ....
    return

関数名(仮引数1=実引数1, 仮引数2=実引数2) #位置引数に代入するので順番は関係ない
関数名(仮引数2=実引数2, 仮引数1=実引数1) #上の関数と同じ結果になる
```

```python
以下のプログラムを実行した際の出力結果として正しいものを選択しなさい。
dic = [
    ('Noro', 'Nakao', 'Miyaoka'),
    ('Kimura', 'Miyashita', 'Shibata'),
    ('Matsumoto', 'Tanaka', 'Ivan'),
]

print(list(zip(*dic)))

A,[('Noro', 'Kimura', 'Matsumoto'), 
('Nakao', 'Miyashita', 'Tanaka'), 
('Miyaoka', 'Shibata', 'Ivan')]
#インデックスごとのイテラブルに作り直す
```

```python
Pythonインタプリタにて以下のように入力した場合の出力結果として正しいものを選びなさい。
>>> import math
>>> math.sqrt(2)

A,1.414213562

```

```python
Pythonインタプリタにて以下のように入力した場合の出力結果として正しいものを選びなさい。

>>>import random
>>>random.sample(range(1000), 5)


A,[756, 121, 482, 264, 841] 
```
:::note info
ランダムに要素を一つ選択: random.choice()
ランダムに複数の要素を選択（重複なし）: random.sample()
ランダムに複数の要素を選択（重複あり）: random.choices()
:::

```python
例外の処理の説明として誤っているものを選択肢から選びなさい。

A,else節は全てのexcept節より前でなければならない。

for arg in sys.argv[1:]:
    try:
        f = open(arg, 'r')
    except IOError:
        print('cannot open', arg)
    else:
        print(arg, 'has', len(f.readlines()), 'lines')
        f.close
```
:::note info
インフォメーション
1.最初にtry節が実行
2.例外が出なければ、except節はスキップされ、try文の実行が終了
3.try節の実行中に例外が発生すると、try節中の残りはスキップされる。
  発生した例外の型がexceptキーワードの後ろで指定してある例外と一致すれば
  except節が実行され、try文の後のプログラムの実行がそのまま続く。
4.例外の型がexcept説にある名前と一致しない場合、更に外側にあるtry文（あれば）に渡される。見つからない場合は、未処理例外となり、エラーが出る。

try ~ exept 文は、オプションで else節がいれられる。
位置は全てのexcept節より後ろでなければならない。
:::

```python
以下のプログラムを実行した際の出力結果を選びなさい。

a = 2
b = 5

c = 3.0 + b, 5 * a

print(c)

A,(8.0, 10)
```
エンジニア４年目の失敗談

# 経歴について

---

## １社目
新卒として自社開発会社に入社
２年目からなぜか社内インフラの担当となり、半年程で気がつけば社内インフラの管理などまでしていた
そこからは、社内インフラの管理者をしながら新規案件のPMなどを行う。
ここからは、PMとして案件管理などを行う。
※人が少なすぎて業務範囲がおかしくなっている😭

---

## 現在
SESとして派遣先でクラウド環境の構築を行なっている。
自社の関係者の取りまとめとしてスケジュールの管理などを行っている。

---

# 失敗①　人に頼ることの難しさ

仕事をしていく中で自分一人でできることは限られています。
その中で目標を達成するためには協力することが必要です。
ですが、私の場合不安になってしまい人に依頼することができなかった。
そのため、一人抱え込んでしまった。

---

# 失敗② みんなが同じ気持ちで仕事をしているわけではない

仕事というのは相手が求めている結果を提供するだけでなく、
可能な限り求められている結果より良い結果を出すものだと考えている。
当時は誰もがそう考えて仕事をしていると考えていた。
だが、考えが一緒とは限らず求められていることの８〜９割でいいと言われることがあった。

---

# まとめ

大きな失敗ではないですが失敗をしたことで学ぶことができた！
Nuxt.jsでmicroCMSの記事を表示させる

# 目的
ヘッドレスCMSを使って記事を投稿する案件があったので、実際に使ってみました

# 動作環境
- node v16.15.1
- npm v8.11.0
- nuxt.js v2.15.8

# 1.はじめに
nuxt.jsの開発環境とmicroCMSの設定はすでにできていることを想定とします

# 1nuxt.jsでmicroCMSを使えるように設定する
microCMSの記事を表示させるには**axios**を使う方法と**microCMSのモジュール**を使う方法があります。
今回は後者のmicroCMSを使った方法を使います

## 1.1 nuxt.jsにmicroCMSのモジュールをインストールする

npmからモジュールをインストールします

```
$ npm install nuxt-microcms-module
```
## 1.2nuxt.config.jpで設定をする
インストールが終わったら**nuxt.config.jp**にて設定をします

```js:nuxt.config.jp
export default {
  buildModules: ['nuxt-microcms-module'],
  microcms: {
    options: {
      serviceDomain: process.env.SERVICE_DOMAIN,//サービスドメイン
      apiKey: process.env.API_KEY,//APIキー
    },
    mode: process.env.NODE_ENV === 'production' ? 'server' : 'all',
  },
};
```
上記のように設定する
今回は**env**ファイルを使って設定しているので**env**ファイルに情報を記載する
```.env
API_KEY=xxxxxxxxxxxx
SERVICE_DOMAIN=xxxxxxxxxxxxx
```
## 2 microCMSを使って表示させる
上記の設定でmicroCMSが使えるようになったので、実際に使ってみます
## 2.1 記事を表示させる
nuxt.jｓのpage/のなかで作業します
```vue:index.vue
<template>
  <ul>
    <li v-for="content in contents" :key="content.id">
      <nuxt-link :to="`/${content.id}`">
        {{ content.title }}
      </nuxt-link>
    </li>
  </ul>
</template>

<script>
export default {
  async asyncData({ $microcms }) {
    const data = await $microcms.get({
      endpoint: 'your_endpoint',
      queries: { limit: 20, filters: 'createdAt[greater_than]2021' },
    });
    return data;
  }
}
</script>
```
こちらのコードで記事のタイトルを表示させることができたと思います
# 3 まとめ
axiosを使うよりもこちらのほうが簡単ではありますね
現在nuxt.js+microCMS+netlifyを使ったブログサイトを作成中です
アクセス修飾子


## アクセス修飾子とは

プロパティやメソッドに対して、アクセスレベルを設定できる
public/protected/private がある

## クラスを定義

動物のクラスがあり、インスタンス化している

```typescript
class Animal {
  age: number = 10;
  isCry: boolean = false;

  constructor(isCry: boolean) {
    this.isCry = isCry;
  }
  cry(): void {
    if (this.isCry) {
      console.log(`age:${this.age}`);
    }
  }
}

let dog = new Animal(true);
dog.cry();
```

## public

public はどこからでもアクセスできる
デフォルトは public になっている

例

```typescript
class Animal {
  public age: number;
  sex: string;
}

let dog = new Animal();
dog.age = 12;
dog.sex = 'オス';
```

自身のプロパティとして、自動的に取り込むことができる
なので初期化の必要なし

```typescript
class Animal {
  age: number = 10;

  constructor(public isCry: boolean) {}
  cry(): void {
    if (this.isCry) {
      console.log(`age:${this.age}`);
    }
  }
}

let dog = new Animal(true);
dog.cry();
```

## protected

自身とその派生クラスの中でアクセスできる

```typescript
class Animal {
  public age: number;
  sex: string;
  protected sayAge() {
    console.log(`${this.age}才`);
  }
}

let dog = new Animal();
dog.age = 12;
dog.sex = 'オス';
//エラー
dog.sayAge;
```

サブクラスの中なら使える

```typescript
class Animal {
  public age: number;
  sex: string;
  protected sayAge() {
    console.log(`${this.age}才`);
  }
}

let dog = new Animal();
dog.age = 12;
dog.sex = 'オス';

class BigAnimal extends Animal {
  constructor(age: number) {
    super();
    this.age = age;
    this.sayAge();
  }
}

let gorilla = new BigAnimal(20);
```

## private は自身のクラスのみ

```typescript
class Animal {
  public age: number;
  sex: string;
  private sayAge() {
    console.log(`${this.age}才`);
  }
}

let dog = new Animal();
dog.age = 12;
dog.sex = 'オス';

class BigAnimal extends Animal {
  constructor(age: number) {
    super();
    this.age = age;
    //エラー
    this.sayAge();
  }
}

let gorilla = new BigAnimal(20);
```

サブクラスでも使えない

## まとめ

アクセスレベル
<strong>public > protected > private</strong>

public : オール OK
protected : サブクラスまで OK
private : 自身のクラスのみ OK
奇妙なJavaScript

## 概要

奇妙なコードを書けたので紹介します。

```javascript
['constructor']['constructor']['constructor']('return this')()['console']['log']('Hello JavaScript!')
// > Hello JavaScript!
```

`unsafe-eval` がOFF、 `static` でない環境でしか動作しません。

## 説明

```javascript
['constructor']
// Array: ['constructor']
```

要素が `'constructor'` の配列のリテラルです。

```javascript
['constructor']['constructor']
// Array()
```

配列の `constructor` プロパティを参照します。配列オブジェクトのコンストラクタは `Array` オブジェクトです。

```javascript
['constructor']['constructor']['constructor']
// Function()
```

`Array` オブジェクトの `constructor` プロパティを参照します。関数のコンストラクタは `Function` オブジェクトです。

```javascript
['constructor']['constructor']['constructor']('return this')
// function() { return this; }
```

`Function()` の引数に文字列を渡すと、その文字列を実行する関数を生成します (`(code) => eval(code)` のようなものです)。

```javascript
['constructor']['constructor']['constructor']('return this')()
// window
```

非 `static` モードの場合、 `global` コンテキストで `this` はグローバルオブジェクトを指します。ブラウザ環境では `window` です。

```javascript
['constructor']['constructor']['constructor']('return this')()['console']['log']
// window.console.log
```

`window.console.log` を参照します。

```javascript
['constructor']['constructor']['constructor']('return this')()['console']['log']('Hello JavaScript!')
```

`console.log('Hello JavaScript!')` と等価です。
[OCI]PL/SQL SDKを使ってAutonomous Databaseのリフレッシュ可能クローンを定期的にリフレッシュさせてみた

Autonomous Databaseのリフレッシュ可能クローンのリフレッシュを、ソースとなっているAutonomous DatabaseでPL/SQL SDKを用いて自動実行させてみました。

**※こちらはあくまでサンプルのため、クローンの状態の確認やエラーハンドリングは実装しておりません。こちらを参考に本番環境に実装される際は、適宜エラーハンドリング等を追加で実装してください。**

リフレッシュ可能クローンのOCIDとリージョンを指定して、10分前のタイムスタンプを指定して対象となるクローンのリフレッシュを実行するPL/SQLプロシージャ「refresh_clone」を作成します。

ここではクレデンシャルとしてリソース・プリンシパルを使用しています。

```sql:refresh_cloneプロシージャ
CREATE OR REPLACE PROCEDURE refresh_clone
IS
  response_body   dbms_cloud_oci_database_autonomous_database_t;
  response        dbms_cloud_oci_db_database_autonomous_database_manual_refresh_response_t;
  refresh_details dbms_cloud_oci_database_autonomous_database_manual_refresh_details_t;
  
  clone_ocid      VARCHAR2(256);
  region_id       VARCHAR2(20);
  
BEGIN
  -- リフレッシュ可能クローンのOCIDをセット
  clone_ocid := 'ocid1.autonomousdatabase.oc1.iad.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
  --リージョン識別子をセット
  region_id  := 'us-ashburn-1';
  
  -- refresh_detailsの初期化
  refresh_details := dbms_cloud_oci_database_autonomous_database_manual_refresh_details_t();

  -- 10分前のタイムスタンプを取得
  SELECT systimestamp-(1/144) INTO refresh_details.time_refresh_cutoff FROM dual; 

  -- 10分前のタイムスタンプを指定してリフレッシュ可能クローンのリフレッシュを実行
  response := DBMS_CLOUD_OCI_DB_DATABASE.AUTONOMOUS_DATABASE_MANUAL_REFRESH(
                autonomous_database_id => clone_ocid,
                autonomous_database_manual_refresh_details => refresh_details,
				credential_name => 'OCI$RESOURCE_PRINCIPAL',
				region => region_id);

END;
/
```

PL/SQLプロシージャが作成できたので実行してみます。
```sql
EXECUTE refresh_clone;
```

コンソールでリフレッシュ可能クローンの状態を確認してみます。

更新中のステータスに変わりました。
![スクリーンショット 2022-07-07 17.46.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/c8485650-3145-c261-1fb1-17d19b09833b.png)

作業リクエストを確認してみます。
![スクリーンショット 2022-07-07 17.47.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/80fb8d03-1d3b-f282-cabd-d94e14265b0c.png)
リフレッシュが開始されたことが確認できました。

作成したプロシージャREFRESH_CLONEが毎日0時に自動実行されるように、DBMS_SCHEDULERのジョブ"REFRESH_CLONE_JOB"を作成します。

```sql:RERESH_CLONE_JOB
BEGIN
    DBMS_SCHEDULER.CREATE_JOB (
        job_name           =>  'REFRESH_CLONE_JOB',
        job_type           =>  'STORED_PROCEDURE',
        job_action         =>  'ADMIN.REFRESH_CLONE', 
        start_date         =>  TO_TIMESTAMP_TZ('2022-07-8 00:00:00 +9:00','YYYY-MM-DD HH24:MI:SS TZH:TZM'),
        repeat_interval    =>  'FREQ=DAILY;INTERVAL=1',
        auto_drop          =>  FALSE,
        enabled            =>  TRUE
    );
END;
/
```

以上で、Autonomous Databaseが毎日0時に自動的にリフレッシュ可能クローンをリフレッシュするように設定できました。
PhpStormを日本語化する

# 実行環境
- OS：Windows10
- PhpStorm Version：2022.1.3
# 手順
[File]>[Settings]を開く。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1015414/b64f65b9-b63c-4bfd-277b-268e50bc9b8b.png)
[Plugins]をクリックし、「Japanese Language Pack」を検索し、インストールする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1015414/fa811a8a-e442-ce44-18e6-4b6aecfe5610.png)
インストール完了後、Restart IDEをクリックする。
ポップアップのRestartをクリックし、PhpStormを再起動する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1015414/79fe164c-2a09-ccdb-5428-e3a9026f744a.png)
日本語化完了♪
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1015414/325bb3fc-01e7-b400-f3ec-fcaee4b9cf90.png)
AWS Glue・AWS Data Pipelineの用語要点まとめ（自分用メモ

・AWS Glue
フルマネージドのサーバーレスETLサービス。
データソース（S3やDynamoDBなど）からデータを抽出し、変換・統合したデータをターゲットのデータベース（S3やRDSなど）へ格納するといったデータ分析における橋渡しの役割を担います。
ETLとは、データのExtract（抽出）・Transform（変換）・Load（書き出し）を意味する用語で、様々なデータソースを基に、データを統合してデータウェアハウス（DWH）へ格納する一連のプロセスのことをいいます。
データ分析を行う上で「ETL」は重要は要素。

AWSには、代表的なETLツールとして「AWS Glue」「AWS Data Pipeline」がある。

・AWS Glue
クローラーは、データソースからデータを抽出し、データカタログを作成。
データカタログとは、抽出したデータのメタデータ（データの属性情報）が保存されたもの。データそのものではなく、データソースのどのデータをどのような方法で抽出するか などの情報が保存されています。
作成したデータカタログを基に、ETLエンジンがデータソースからデータを抽出し、ターゲットへ書き出す処理を行います。このデータの変換およびターゲットへ書き出す処理を「ジョブ」と呼びます。変換処理は、既存のETLツールであるApache SparkやScalaを用いて自動生成したり、生成されたスクリプトを自分で編集することができます。

なお、Glueで作成したデータカタログは、Amazon EMRやAmazon Athenaなどの分析・クエリ実行サービスなどからも参照でき、Glueのクローラーで抽出したデータに対してAthenaでSQLクエリを実行する、といった利用もできます。


・AWS Data Pipeline
データの移動や変換を自動化するサービス。例えば、Amazon S3からDynamoDBへデータを取り込んだり、RDSからRedshiftへのデータコピーなどを毎週土曜に行う、といった運用ができます。
S3やRDS、Redshiftなど、データの型が異なるストレージまたはデータベースであっても、変換および移行を行います。

・GlueとPipelineの使い分け
Glueはサーバーレスなサービスですが、Data Pipelineは処理の実行時にEC2インスタンスが起動されます。
また、Glueはデータ変換処理のベースにApache SparkやScalaを用いていますから、これらを利用したい場合はGlueを、そうでない場合にはData Pipelineを検討するといった使い分けができます。
【Rails】dotenv-railsの導入

# はじめに
* 学習の覚え書として書いています
* 自己解釈ですので参考程度にご覧ください

# dotenv-rails とは
* 環境変数を管理できるgem
* 環境変数 → **公開したくない情報（値）**
(メールアドレスやパスワードなど)

つまりGitなどにアップする際、公開したくない情報（値）をdotenv-rails(gem)で管理することができます。


# dotenv-rails　使用手順
①dotenv-railsの導入
②環境変数を記述するファイルを作成（.env）
③環境変数の記述
④ソースコード内で環境変数を使用
⑤GitHubの公開設定（.gitignoreに.envを追加）

## ①dotenv-railsの導入
* gemfileに追記（一番下の行に　**gem 'dotenv-rails'**　を追記）
* ターミナルで　**$ bundle install**　を実行

## ②環境変数を記述するファイル **.envファイル**を作成
* ターミナルで　**$ touch .env**　を実行
（.envは既定のファイル名なので誤字が無いように作成）

## ③.envファイルに環境変数の記述
* 書き方
**任意の変数名**=**変数に入れたい値**（公開したくない情報）
* 例
SECRET_KEY=hogehoge
（公に公開したくない情報「hogehoge」を　変数「SECRET_KEY」に代入）

## 　(③の補足 代入できているか確認する方法）
### 　rails c で確認
　①　$　**rails c**　入力　（rails c起動）
　②　2.6.3 :001 >　 **ENV['SECRET_KEY']**　入力　（設定した変数の中身確認）
　　　　　　　↓
　　2.6.3 :001 > ENV['SECRET_KEY']
　　=> **"hogehoge"**（値が表示される）

　※表示が「nil」や「0」の場合、下記の手順を実行してから上記手順を再実行します。
　　①　2.6.3 :002 > **exit**　（rails c　一旦終了）
　　②　$ **spring stop**
 　再びrails cを起動　→　コマンド入力し値が表示されればOK

## ④ソースコード内で環境変数を使用
使用したい箇所で下記の書き方で記述
* 書き方
**"#{ENV['** 任意で設定した変数名 **']}"**　(左右の　" "　も含め、全て記述)

* 例（変数名＝**SECRET_KEY**）
**"#{ENV['** SECRET_KEY **']}"**

※上記をビューで表示させる場合は、Rubyタグ＜％＝　％＞で囲うことで表示されました。
※文字と一緒に使用する場合（文字＝ほげほげ）
　**"ほげほげ #{ENV['** SECRET_KEY **']}"**　で　**ほげほげhogehoge**　と表示されました。

## ⑤GitHubの公開設定（.gitignoreに.envを追加）
Gitにアップしたくないファイルやフォルダは **.gitignoreファイル** に追記し除外する。
* .gitignoreファイル　の一番下の行に　 **/.env** 　を追記
* $ git status でGit管理下から除外されたか確認
→　.envファイルが表示されなければ、Git管理下から除外できているのでGitへpushしても情報が公開されずに済みます。

# まとめ

* 公開したくない情報はdotenv-rails(gem)を利用し、環境変数として管理する
* 環境変数を定義した.envファイルをGitの管理下から除外させる必要がある(.gitignoreへ記述)

※本記事は、学習の覚え書として書いていますので参考程度にご覧ください。
PostgreSQLにおけるレプリケーションはこれだ

# 1. レプリケーションとは
レプリケーションとは、データベースを別のデータベースに複製して同期する、データベース管理ソフトウェア（DBMS）の一機能のことである。
レプリカ（複製品）が語源なのではと予想。

引用：[IT用語辞典バイナリ](https://www.weblio.jp/content/%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E3%83%AC%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3#:~:text=%E3%83%AC%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%A8%E3%81%AF%E3%80%81%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E3%82%92,%E3%81%8C%E3%81%A7%E3%81%8D%E3%82%8B%EF%BC%88%E3%83%9B%E3%83%83%E3%83%88%E3%82%B9%E3%82%BF%E3%83%B3%E3%83%90%E3%82%A4%EF%BC%89%E3%80%82)

# 2. レプリケーションのメリット
## 災害対策
バックアップとなる予備系を遠隔地に設置することで、広域災害時にディザスタリカバリが可能。災害大国の日本において、とても大きなメリットとなる。

## 複数設置可能
レプリケーションは、更新された差異のある点をリアルタイムに上書きを実施する仕組みであるため、短時間で複数にバックアップすることができる。
そのため、大容量でも設置することが可能。

## 負荷分散
マスターデータベースにアクセスが集中した場合に、その負荷をレプリケーションによって分散させることができる。この機能を負荷分散機能という。当然、レプリケーションしているDBが多いほどその能力は高くなる

## 障害対策 :フェイルオーバー
レプリケーションは、複製データを作成するストレージ環境が独立している。そのため、マスターDBのストレージに障害が発生することがあっても、レプリケーション用のストレージが被害を受けることはなく、サービス停止などを回避することが可能。

# 3. レプリケーションのデメリット
## 破損したデータが生じた場合
レプリケーションはマスターDBと同一の環境を複製するものである。そのため、マスターDBでデータが破損するようなことがあれば、その破損したデータも同期されることになる。バックアップとして、用いるものではないことがわかる。
## コストの大きさ
マスターDBと同一の環境を用意しないといけない。加えて前項に記載の通り、バックアップを目的としていないため、バックアップサーバも別途用意する必要があり、その分管理工数、費用も増加する。


# 4. レプリケーションの種類
- ストリーミングレ（物理）プリケーション
データベースクラスタを一括で複製する。
下記で構築手法など詳細に記載
https://qiita.com/Yatsushi009/items/76895f73e133a32ed66e
- ロジカル（論理）レプリケーション　
テーブル単位、データベース単位に複製る

[参考サイト](https://www.fujitsu.com/jp/products/software/resources/feature-stories/postgres/article-index/streaming-replication1/)

# レプリケーションと意味を勘違いしやすい単語
- ミラーリング
- アーカイブ
- バックアップ
AWS CLIを使ってVMWare・Hyper-Vなどの仮想データをAWSのEC2上に移行したい



## 簡易流れ
・移行元の仮想データエクスポート
・AWS S3に仮想データアップロード
・S3からAMIイメージインポート
・AMIからEC2インスタンス起動
・各ネットワークなどの設定をする
・コスト配分タグ追加
・翌日コスト配分タグを有効化

・S3アップロード済ファイル削除
・AMI削除、スナップショット削除

## VMImport参考手順
https://xp-cloud.jp/blog/2019/05/31/5071/


## S3へのアップロードは160GB以上であればAWS CLIでのアップロード作業が必要
https://qiita.com/seyself/items/43426f57c50021ea55f8

※Web画面からのアップロードと同時にCLIのアップロードなどしていたら失敗する事があった、
１つずつの方が安全かと思われる


## マルチパートアップロード時の問題
ファイルのアップロードが中途半端な状態で終了してしまった場合、中途半端なデータが裏側で残り課金され続ける
https://blog.katsubemakito.net/aws/s3-multipartupload

## AMIへの複数仮想データファイルインポート方法
### AWS EC2ユーザーガイド
https://docs.aws.amazon.com/ja_jp/vm-import/latest/userguide/vmimport-image-import.html

### containers.json 単一ディスクと複数ディスクの場合の記載方法
https://dev.classmethod.jp/articles/vm-import-image-import/

### AMIが不要になったら
保存が課金対象なのでAMIとスナップショットを掃除する
https://www.ipentec.com/document/amazon-ec2-delete-ami
IT業界に入って4年目で感じたこと

# まず初めに
私はこの業界が**好きではない**。

それならさっさと転職してしまえばいい。と言われるかもしれないが、特にこんな仕事をしたいというのがない。
また、対して動き出すことをしていないのもあって、この業界にまだいるので悪しからず。

この記事ではペーペーの平社員が企業への愚痴を書いてある記事になる。

※伝えたいことは、最後に記載しているので飛んでください。

# おすすめはあまりできない
ITというワードが世の中に溢れてきて、プログラミング・システムエンジニア等の職業にプログラミングスクールにでも入って就きたい人が増えた。高給で場所に縛られないような職だと想像されているかもしれないが、そんな場所ではない。(※しっかりと稼いでいる方は沢山います)

ちなみに私の就職前の想像の世界は、IT土方でゴリゴリにコーディングして、朝も夜も関係ないほど働きまくる場所だと思っていた。

が、初めて社会人になって入社した会社が、「あなたを入れる案件がありません。」と...

ほう。なので、仕事がないけどお給料が頂けるニート歓喜、世のサラリーマン仰天の状況になってしまった。就職前の想像をしていた私からすると意味がわかなかった。

実際には家でゴロゴロしているだけでお金は貰えないが、出社して勉強して定時にが終わりの生活。
特に会社からはあれしろこれしろと指令はないので、最初の頃は気合が先行していることもあって、JAVAの学習であったり書籍を読みながら色々と学習をしていた。

なので、実際に働いて会社に利益をだすといことはなく、現場という環境がどのような場所かさえ知らないまま2年目が終わった。

2年たった私のスキルは、(書籍読んで写経した言語はC,C++)
・C
・C++
・Java
　・springフレームワーク
・MariaDB
・PostgreSQL
・Apache
・CentOs
etc...

と、そこらへんのテスター現場に入れられた新人と比べると、コードが読めてある程度なら組めるようにはなった。

しかし、実際に現場にでたこともないので、自分自身の立ち位置が全然わからないままであった。

# やっと現場へ
3年目になり、上司のコネクションのおかげで初現場へ！
しかも、新しい技術をどんどん取り入れていこうとしていると！

そんな大当たりの現場だったら2年間我慢した甲斐があった。と思いモチベーションも上がりいざ出陣。

まず手始めに、オペレーションを覚えましょう。・・・？？
あ、被災時対応をするからオペレーションは覚えない
といけなんだね！いいよいいよ！

お次はRPAを使って改修しましょう。？？？？？
なにそれ！聞いたことない！え！！！！エンドユーザーが使うコーディング不要なシステムなんだ！！

おいおい、怪しい匂いしかしないな。
新しい技術ってなんなんだ。ブロックチェーンやAWSめちゃくちゃ使ってまっせ。とかあるんじゃないのか。

でも、初めての現場ってのもあって関係なく頑張った。

しかし、運がいいのか悪いのか、特に忙しい現場ではなくタスクが全然ない。

自己学習を進めるほどITが好きではない。
全然コーディングをしない。知識がスルスルと落ちていく音が聞こえた。

# 伝えたかった事
何を言いたかったていうと。

どの業種・業界も当てはまると思うが、自分の思い通りにはなかなかいかないってこと。

でも、冒頭で書いたこの業界が好きではない。を伝えたい。
会社によって異なるが、私が入った会社はSES形態だったので派遣社員のように他の現場に入り込むという形だった。

しかし、現場に入るためには営業しなければならない。商品は私。
営業の人はあーだこーだ言い、私が現場に入れない理由をダラダラと並べる。お前は何ができるのだと。。

そんな営業にあたってしまっては、意思の疎通ができるわけもなく。将来設計にあった現場を伝える機会すらない。

しかも、現場はガチャをしているようなもので、、、
現場経験がないから希望に合わない現場になったり。明らかにスキルマッチしていない現場であったりと、誰がやる気がでるのかとききたい。

技術者として市場価値を上げるならば、現場に囚われず自己学習を好きでする人は向いているだろう。
リーダ職のように進みたいのであれば、同じ現場で経験を積んでリーダを任せられるタイミングを待たないとこないかもしれない。

結局のところ、レールに乗ってスキルアップはできない。
自分が思い描いているチャンスはなかなか存在しない。
営業が商品(人)を商品(人)と思わない。

沢山ある中の一つの、小さな中小企業に入ってよかったと感じることはなかった。
企業からみたら採算に合わないと思われただろう。知るか馬鹿野郎。

従業員もある程度企業と法律内なら同等に会話しても問題ない。
今思えば明らかにパワハラだった。あーほ、はーげ。

# まとめ

・全然思ったようにいかない
・営業が現場に放り込めばいいとおもっている
・そのせいで、現場とのミスマッチ


私はこの業界が**好きではない**。
全然おすすめもしない。

この人売りと言われる業態が良くないと感じる。
なので、私はこの業界が**好き**になれる日がくることを信じて、今日も頑張ります。
C# List（リスト）のコピー

## 0.0 はじめに
List（リスト）を別のListにコピーしたいとき、＝（イコール）を使って単純にリストを代入すると参照渡しになってしまうので注意が必要です。







## 1.0 参照渡し
参照渡しとは、コピー先でも同じListを参照するように渡すことです。 コピーされたListに変更を加えると元のリストにも変更が反映されます。
シャローコピー（Shallow Copy : 浅いコピー）とも言います。


```C# Test.cs
List<string> listA = new List<string> {"test"};  
  
// listAの要素を変えるとlistBも一緒に変わる  
List<string> listB = listA;   
```





## 2.0 値渡し
上記に対して値のみを渡すのが値渡しです。変更がコピー元に影響しません。
値渡しの方法はいろいろありますが、シンプルなのはListのコンストラクタを使う方法だと思います。
ディープコピー（Deep Copy : 深いコピー）とも言います。







```C# Test.cs
List<string> listA = new List<string> {"test"};  
  
// listAを変えてもlistBは変わらない  
List listB = new List(listA); 
```

## 3.0 まとめ
試してみた。
```C# Test.cs
// Listのコピーのテスト
public class Test : MonoBehaviour
{
    // List作成、List Aには0,1,2を入れている
    List<int> listA = new List<int> {0,1,2};
    List<int> listB = new List<int>();
    List<int> listC = new List<int>();

    private void Start() {
        listB = listA; // 参照渡しでコピー
        listC = new List<int>(listA); // 値渡しでコピー
        // 初期値を表示
        ListCheck(listA, "listA"); // 0,1,2
        ListCheck(listB, "listB"); // 0,1,2
        ListCheck(listC, "listC"); // 0,1,2

        // list Aに99を追加
        listA.Add(99);

        // 現在値を表示
        ListCheck(listA, "listA"); // 0,1,2,99
        ListCheck(listB, "listB"); // 0,1,2,99（99が追加された）
        ListCheck(listC, "listC"); // 0,1,2

        // list Bから１を削除
        listB.Remove(1); 

        // 現在値を表示
        ListCheck(listA, "listA"); // 0,2,99（1が削除された）
        ListCheck(listB, "listB"); // 0,2,99
        ListCheck(listC, "listC"); // 0,1,2
    }

    // コンソール画面に表示するために作ったメソッド
    void ListCheck(List<int> list, string listName) {
        string str = "";
        foreach (var item in list) {
            str += item.ToString() + ", ";
        }
        Debug.Log($"{listName} の中身は {str} です");
    }
}
```

ListAへの変更がListBへ反映されている、ListCには影響なし
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352037/352e5049-8e4c-135d-3b64-19ed1d57dd51.png)








ListBへの変更がListAへ反映されている、ListCには影響なし
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352037/86a4acc6-bf60-1dee-5483-b410b95155e2.png)
HTML

■基本のHTML

<!DOCTYPE html>
DOCTYPE宣言と呼び、HTMLのバージョンを宣言するやつ。

HTMLのテンプレート

```
<!DOCTYPE html>
<html>
　<head>
　　<!--文字コードの指定-->
   <meta charset="utf-8">

   <!--ページタイトルの設定-->
   <title>Title</title>

   <!--CSSの読み込み-->
   <link rel="stylesheet" href="stylesheet.css">

　</head>
　<body>

　</body>
</html>
```

■ファビコン(サイトのアイコン)を表示する
ファビコンに使用するアイコンの画像を「.ico」で保存する。
(「png」や「jpeg」でもいいが、ブラウザによってはうまく表示されないことがある。)



`<a>`タグ
リンク
`<a href="[URL]">`

`<li>`タグ

<li>リスト1</li>
<li>リスト2</li>

`<li>`を`<ul>`要素で囲むとリストの文字列の先頭に黒点がつく。

<ul>
<li>リスト1</li>
<li>リスト2</li>
</ul>

```
<ul>
<li>リスト1</li>
<li>リスト2</li>
</ul>
```


`<li>`を`<ol>`要素で囲むとリストの文字列の先頭に数字が連番でつく。

<ol>
<li>リスト1</li>
<li>リスト2</li>
</ol>

```
<ol>
<li>リスト1</li>
<li>リスト2</li>
</ol>
```
■divについて

divはブロックとして扱われる。
親divと子divを作った時、
子divは親divの範囲内に位置するイメージ。

■文中の一部にCSSを適用させたい時
`<span>`で要素を囲む

```
<h1>
<span>Hello</span> World !
</h1>
```
Accessでフォームに入れた値の件数分だけクエリ出力したい【VBA&SQL】

マニアックですが、Accessにて、フォームに入れた【任意の件数】分だけ、レコード出力したい時にVBAとSQLを組み合わせて、クエリの中身を変更するサンプルです。

補足ですが、Access SQLではLIMITが使えません。
なので、SELECTの後に TOP 50 といった数を入れて、
その分だけ抽出するという書き方になります。

毎回書き換えれば良いのですが、作成者と利用者が分かれているなど、
フォーム側でコントロールしたかったので作成しました。

よろしければご活用ください。

```
Private Sub Sample()

Dim QDF As QueryDef
Dim RecLimit As String
Dim TargetTableName As String
Dim TargetQueryName As String
Dim TargetFormName As String
Dim TargetShapeName As String
Dim SqlString As String

'設定項目
TargetTableName = "T_order_3"
TargetFormName = "フォーム1"
TargetShapeName = "limit_num"
TargetQueryName = "STEP2"

'フォームの値の判定 NULLの場合は1000
If IsNumeric(Forms(TargetFormName).Controls(TargetShapeName).Value) Then
RecLimit = "TOP " & Forms(TargetFormName).Controls(TargetShapeName).Value
Else
RecLimit = "TOP 1000"
End If

'一旦テーブル削除
DoCmd.RunSQL "DELETE * FROM " & TargetTableName

SqlString = "INSERT INTO " & TargetTableName & " SELECT " & RecLimit & " * FROM STEP1;"

'該当のクエリの変更（数）
Set QDF = CurrentDb.QueryDefs(TargetQueryName)
QDF.SQL = SqlString
    
'クエリの実行
DoCmd.OpenQuery TargetQueryName, acViewNormal, acReadOnly

'テーブルを開く
DoCmd.OpenTable TargetTableName, acViewNormal, acEdit

End Sub

```
GCE(Google Compute Engine)でgit clone時に詰まった話

件名の通り。
インスタンスを作ってログインし、sshでgit cloneしようとしたら詰まった。
出たエラーは
```
git@github.com: Permission denied (publickey).
fatal: Could not read from remote repository.
```
原因は最初にパーミッションエラーが出た際、それを回避しようとしてsudoを付けたことだった。
今まで
「sudoをつけてコマンドを叩く = ```root権限で```コマンドを実行」
だと思っていたのだが
実際は
「sudoをつけてコマンドを叩く = ```rootユーザーで```コマンドを実行」
だったらしい。
なので現ユーザー配下に作成した鍵(id_rsa)ではなくrootユーザーの鍵を見に行って失敗していた模様
解決策としては
1. rootユーザーの.ssh配下に鍵を配置する
2. 現ユーザーのユーザーグループcloneしたいディレクトリのパーミッションを変更してsudoなしでコマンドを叩く

2の場合は
```
su - 
sudo usermod -a -G root ユーザー名
cd ..
chmod 775 ディレクトリ名
```
でOK。
1が無難な気がする。
Jetpack Compose  composable の recomposition を AndroidStudio で確認する方法

いつ、どの composable が compose されているか、

アプリのパフォーマンスを向上させるのは必須です。

Layout Inspector から ライブで見ながら recomposition の回数を確認します。

<a href="https://www.youtube.com/watch?v=kWeDHOOmhLU"><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588914/d6de7cca-ad9f-b18b-bac3-538964fc06fe.png" width="480"></a>

```
[Tools]

  ↓

[Layout Inspector]

  ↓

[Component Tree]

  ↓

[View Option]

  ↓

[Show Recomposition counts]
```

利用するにはいくつかの設定条件があります。
[👉 【Jetpack Compose】「Layout Inspector Recomposition counts」で re-compose 回数を確認する](https://android.benigumo.com/20220707/layout-inspector-recomposition-counts/)
ScrapyでImportError: cannot import name 'HTTPClientFactory’が出る

Scrapyをインストールして動かす際に少してこずった部分があったため共有しておきます。

# 環境
dockerコンテナ内で実行。
python-alpineを使用。
Scrapy 14.0

# 問題
実行する際に、以下のようなエラーが出る。
``` 
ImportError: cannot import name 'HTTPClientFactory’
```

くわしく見てみると、Scrapyはtwistedという非同期処理ライブラリを使用しているらしい。
その中のインポートでエラーが発生している。該当箇所のドキュメントを見てみる。

https://readthedocs.org/projects/twisted/

調べてみると、最新バージョンではHTTPCilentFactory クラスは消えていますね。
旧バージョンには存在しているためそちらを使います。

# 解決策

pipで古いバージョンのtwistedを入れる。
自分は16で動きました。
[ROS2] ROS1とROS2を共存させる

ROS1もROS2も使いたい．
そういうときは、以下のコードを.bashrcに書き込んでおけばOK！

# 構成
Ubuntu 20.04
以下のROSディストリビューションがインストールされている
- ros1 noetic
- ros2 foxy

# ROS1、ROS2切り替えコマンド

```sh:.bashrc
# ROS1 環境
function rs1(){
  PYTHONPATH=/opt/ros/noetic/lib/python3/dist-packages
  source /opt/ros/noetic/setup.bash
  source ~/ros1_ws/devel/setup.bash
}

# ROS2 環境
function rs2(){
  export PYTHONPATH=/opt/ros/foxy/lib/python3.8/site-packages
  source /opt/ros/foxy/setup.bash
  source ~/ros2_ws/install/local_setup.bash
}

# 端末起動時のデフォルトのROS環境
rs1 # ROS1
#rs2 # ROS2

```

書き込んだら、`source ~/.bashrc`

ROS1に変更したい場合、
```sh
rs1
```
ROS2に変更したい場合、
```sh
rs2
```

これで、端末ごとにROS環境を変更できる．
Atcorderについて

# Atcorderとは
- 日本最大級のプログラミングコンテスト
- 株式会社Atcorder

Atcorderというと上記の二つを指しますが、一般的にはプログラミングコンテストの方で使われていると思います。
また、Atcorderは日本で一番有名なプログラミングコンテストサイトだと思います。様々なIT企業と連携したコンテストも開催され、成績上位者はそのまま採用に直結するということもあるようです。
# なぜやるのか？
僕がやり始めた理由は、就職に少しでも有利になると考えたからです。Atcorderにはユーザーごとにレートが付きます。レートごとに色が割り振られており、色の上下関係は次の通りです。
黒色（未参加）→灰色→茶色→緑色→水色→青色→黄色→橙色→赤色
また、各色のユーザーの分布は以下のようになっています。
これを見ると赤色の人の凄さがよくわかりますね。
ちなみに現在の私のレートは現在526で色は茶色です。
![分布.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2731695/251131d5-3dc4-7079-a8ca-9ff6ee6a6c0c.png)
緑色になることが目標で現在頑張っています。
# 参加方法
Atcorderのプログラミングコンテストに参加するには
1. [Atcorder](https://atcoder.jp/?lang=ja)でアカウント登録を行う
1. 基本的に土日に開催されるので、そのコンテストに参加登録を行う

一つ目については大丈夫だと思います。
二つ目について、Atcorderには「AtcorderBiginner Contest(ABC)」と「Atcorder Regular Contest(ARC)」の二つがありますが、
（厳密には他にもあります）名前の通り、Biginnerの方が難易度が低いのでこちらから参加してみることをお勧めします。
ABCは100分で8問に取り組みます。配点は次の通りです。
1問目:100, 2問目:200, 3問目:300, 4問目:400, 5,6問目600, 7,8問目:600
Atcorderでは正解した時間が獲得スコアに関係しており、間違えるとペナルティとして時間が加算されるのですが、体感だと二問目まですんなり解ければ茶色まではいけるかなといった感じです。
# 問題の難易度
1問目:標準入力の受け取りが出来、プログラミングが出来れば大丈夫
2問目:1問目よりは難しいが同様
3問目:2問目までとは違い、計算量を考える必要がある
4問目:3問目に加え、二分探索やUnion-findなどのアルゴリズムの知識が必要
5問目以降:すみません未知です。こんなんでも茶色までは来れました。
次の記事以降で、Atcorderでよく使う構文やアルゴリズムのコードを書いていこうと思います。興味を持ってくださった方、これから一緒に頑張りましょう！！
AWS EMRの用語要点まとめ（自分用メモ

・Amazon EMR（旧Amazon Elastic MapReduce）
ビッグデータの処理や分析を行うサービス。ビッグデータを処理する既存のフレームワークであるHadoop（ハドゥープ）やSpark（スパーク）を用いています。
さらに、ビッグデータを分析し経営に役立てることを「BI：Business Intelligence」といい、代表的なBIツールにはMicrosoft ExcelやMicroStrategyなどがあります。Amazon EMRはこれらのツールにも対応しています・

EMRのアーキテクチャ
データを複数のサーバーに配置して並列に処理する「分散処理」により、迅速かつ効率の良い処理を実現しています。

「分散処理」という名の通り、EMRでは3つの役割を持つノード（EC2インスタンス）でクラスターを構成し、処理を分散します。
・マスターノード
　クラスター全体を管理するノード。コアノードおよびタスクノードへ処理を投入したり分散処理の調整を行う。
・コアノード
　演算処理を実行するノード。データを保存するファイルシステムHDFS（Hadoop Distributed File System）を持つ。
・タスクノード（オプション）
　コアノードと同様に演算処理を実行する。ファイルシステムを持たない、演算処理専用のノード。

クラスター内のコアノードまたはタスクノードは、手動、または定めたポリシーなどに従って自動でスケーリングすることができます。

■HDFSとEMRFS（EMR File System）
EMRでは、ファイルシステムとしてHDFSとEMRFSを利用できます。

・HDFS（Hadoop Distributed File System）
分散処理ソフトウェア「Hadoop」のファイルシステムです。EMRではマスターノードとコアノードで利用します。
EMRクラスターが終了すると、HDFS上のデータは失われます。

・EMRFS（EMR File System）
Amazon S3をEMRクラスターからファイルシステムとして利用できるようにした機能です。
データを永続的に保持でき、EMRクラスターが終了してもデータは失われません。また、S3が持つ機能（データの暗号化やデータ読み込み時の強い一貫性のサポートなど）も備わっています。

なお、EMRの旧名称「Elastic MapReduce」の「MapReduce」とは、Googleが開発した、ビッグデータを分散処理するフレームワークのことです。
AWS Kinesisの用語要点まとめ（自分用メモ

・Amazon Kinesis
ストリーミングデータをリアルタイムで収集・処理するサービス。
ストリーミングデータとは継続的に生成されるデータのこと。例えばスマートフォンアプリなどでユーザーが生成するログや、証券取引所の株取引情報、SNSやオンラインゲームのデータなどの継続的に生成されるデータが該当します。Kinesisではこのようなストリーミングデータを収集し、サンプリングや分析などの処理を通して、リアルタイムなトレンド情報をユーザーへフィードバックしたり、企業の経営戦略などに繋げることができます。なお、ストリーミングデータを処理することを「ストリーム処理」といいます。
また、その他のデータ処理方式に「バッチ処理」があります。バッチ処理はまとまったデータに対して一括で処理を行う方式です。バッチ処理は、日次、週次、月次、年次の集計処理のように特定範囲のデータに対して定期的に実行されます。
多くの企業ではストリーム処理とバッチ処理の両方を用いてシステムを構築し、柔軟なデータ解析を行っています。


●Kinesis Data Streams
Kinesis Data Streamsは外部から送信されるストリーミングデータを収集するサービスです。センサーなどが生成したストリーミングデータをKinesis Data Streamsのストリームへ送信し、ストリーム上のデータは分析や機械学習などを行うアプリケーションがリアルタイムに読みだして処理します。なお、収集したデータには保持期間（デフォルトで24時間、最長で1年）があります。

なお、Kinesisではストリーミングデータを生成し送信するデバイスやサービスなどを「プロデューサー」、ストリーミングデータを読みだして処理する側を「コンシューマー」と呼びます。

Kinesis Data Streamsでは、ストリーミングデータを「データレコード」という単位で処理します。データレコードには、データそのものに加えて「パーティションキー」「シーケンス番号」が含まれます。
・パーティションキー ... どのシャード（後述）で処理するかを決めるもの。プロデューサー側で設定する
・シーケンス番号 ... シャードごとに一意の番号。シャード内のデータレコードの順序性が保証される

データレコードは「シャード」に分散され処理されます。シャードは、ストリームで処理できるデータの容量を決めるもので、シャードが多いほど並列処理の数が増えてスループットが上がります。

●Kinesis Data Firehose
Kinesis Data FirehoseはストリーミングデータをAmazon S3（ストレージ）、Amazon Redshift（データベース）、Amazon Elasticsearch Service（データ分析）などのサービスへ配信します。Kinesis Data Firehoseへ送信されたストリーミングデータは事前に設定されたデータ配信先へ配信されます。中継するアプリケーションを独自に実装する必要はありません。


●Kinesis Data Analytics
Kinesis Data Analyticsは、Kinesis上のストリーミングデータを処理し、可視化・分析できるサービスです。処理用のテンプレートが用意されていたり、標準SQLのクエリが発行できたり、JavaやPythonなどのプログラミング言語がサポートされているなど、柔軟に処理を組み込むことができます。データをデータベースへ移行することなく処理することで、リアルタイムに結果を得ることができます。



●Kinesis Video Streams
カメラやビデオなどの動画（ビデオストリーム）を取り込むサービスです。取り込んだ動画データはアプリケーションなどによって解析や加工、再生などを行うことができます。
Shopifyにてセット販売機能を実装する方法

## はじめに
こんにちは。
今回は、Shopifyにてセット販売機能を実装する方法についてご紹介していこうと考えております。
最後まで見ていただけますと幸いです！

## セット販売とは
そもそも、セット販売とは何かというところについてご説明しようと思います。
セット販売とは、ざっくりと説明するとまとめ買いを促す仕組みのことになります。
例えば、「セットで購入すると何割お得」みたいなのもセット販売になります。
まとめて購入することでセット割引を適用させたりして、顧客のお得感を刺激することで商品のまとめ買いを促進します。

最近のECサイトでは、セット販売の機能をよく見ると思います。
このセット販売を導入することにより、注文の単価を向上できる可能性があります。
売り上げに伸び悩んでいたり、余った在庫をどうにかしたいみたいな悩みを抱えているマーチャントの方には「セット販売」の導入をお勧めしたいです。

## 実装方法
それでは、実装方法についてご紹介します。
結論から申しますと、Shopifyアプリを使用することにより、「セット販売」機能を導入できます。
Shopifyアプリとは、Shopifyストアのデフォルトの機能にはない機能をストアに追加してくれる拡張機能のようなものです。
Shopifyアプリは、現在海外性のも含めると7372個ほど存在しています。
セット販売アプリだけでも、かなりの数が存在しているためどのアプリを使用したらいいのか迷う方も少なくありません。

そこで、今回私がセット販売アプリを調査して使いやすいものを厳選いたしました。
参考にしていただけると幸いです。

## おすすめアプリ紹介
### セット売り｜リテリア セット販売
![](https://storage.googleapis.com/zenn-user-upload/e7446457f33a-20220707.png)
​
https://apps.shopify.com/shopify-application-345?locale=ja
​
### アプリの特徴
こちらのアプリは、セット販売アプリの中で唯一日本語に完全対応しています。
英語が苦手な方や、Shopifyストアの操作に不慣れな方でも比較的簡単に操作できると思います。
また、アプリが正常に動作しない場合や何か要望がある場合にはアプリ会社に問い合わせることができますが、問い合わせ自体も日本語で行うことが可能です。
海外性アプリですと、英語でメールのやり取りをすることになり、少々面倒ですがこちらのアプリではその心配がないため安心です。

また、価格につきましても月額$14.99とShopifyアプリ相場では普通くらいの価格となっております。

ストアの管理歴が短いマーチャントの方や英語が苦手なマーチャントの方には、おすすめのアプリです。
導入に困ったら、とりあえず一度インストールしてみてください。

ちなみに、アプリ会社さんが公式の解説記事なども出されているためこちらも参考にしてみると良いでしょう。

https://www.re-terior.com/shopify-apps/reterior-bundle-app/guide
​
### バンドル製品 | アップセル
![](https://storage.googleapis.com/zenn-user-upload/91074d20f477-20220608.png)

こちらのアプリの強みはなんと言っても、価格の安さと機能の多さ、信頼性になります。
まず、価格ですが月額$12.49となります。
先程、ご紹介した「セット売り｜リテリア セット販売」よりも安いですね。

また、機能もたくさんあります。
以下に機能一覧を示します。

- バンドル（セット販売する組み合わせ）作成
- ディスカウントとの連携
- どこにでもセット販売表示ができる（カート・ホームなどなど）
- セット販売の日程予約（作成したセット販売の組み合わせが有効な期間を設定できる）
- 商品単位だけではなく、バリエーション単位で設定が可能
- よく一緒に購入されている商品のレコメンド

上記の機能の中に、実装したい機能があるなら迷わずこちらのアプリを導入しましょう。
ただし、日本語対応はできていないため注意が必要です。
また、機能が多いため、管理画面の操作はかなり複雑です。


### Bundler ‑ Product Bundles
![](https://storage.googleapis.com/zenn-user-upload/85cb894276aa-20220608.png)

こちらのアプリは、コストパフォーマンスがメリットであると言えます。
月額は$6.99と非常に安価な上、セット販売を実装するのに必要な機能は揃っているため、価格を抑えたいというマーチャントの方はこちらのアプリを導入しましょう。
ただし、こちらのアプリも日本語には対応しておりませんので注意してください。
## 終わりに
以上で、セット販売の実装方法の紹介は終わりです。
たくさんアプリがあるので迷ってしまいますが自分に必要な機能を見極めて適切なアプリを導入しましょう。
お疲れ様でした。
Power Query workout - Table.TransformColumnTypes

テーブルに含まれる列のタイプを変更するだけではなく、列に含まれる値に対し対応する変換が行われる。そうしないと値変換時のエラー検出ができないですからね。

https://docs.microsoft.com/en-us/powerquery-m/table-transformcolumntypes

```text
Table.TransformColumnTypes(
    table as table,
    typeTransformations as list,
    optional culture as nullable text
) as table
```

# パラメータ
## culture
https://docs.microsoft.com/en-us/powerquery-m/culture-current

Culture.Current と異なる culture、もしくは、明示的な culture を指定できる。ただし、`culture` パラメータへの引数はひとつだけ。なので、必要に応じて分割。

```text:Power&#x20;Query
let
    Source = Table.FromColumns(
        {
            {"2022年7月7日"},
            {"2022年7月7日 木曜日"},
            {"令和4年7月7日"}
        },
        {"Date1", "Date2", "Date3"}
    ),
    ChangedTypeCurrentCulture = Table.TransformColumnTypes(
        Source,{{"Date1", type date}}
    ),
    ChangedTypeWithLocale = Table.TransformColumnTypes(
        ChangedTypeCurrentCulture,
        {
            {"Date2", type date},
            {"Date3", type date}
        },
        "ja-JP"
    )
in
    ChangedTypeWithLocale
```

## typeTransformations
`typeTransformations` パラメータの引数は *list*。ネストしたリストで複数の列に対する処理を記述できる。
リストアイテムひとつめは列名、ふたつめは列のタイプ

```text:Power&#x20;Query
{
    {"Column1", Int64.Type},
    {"Column2", Date.Type}
}
```
となるとき、Column1 列のタイプは Int64.Type になり、列に含まれる値には Int64.From が適用される。結果、Table.TransfromColumnTypes により 値変換時のエラー検出ができるようになっている。よく観察すれば、この動作は明確にできる。

**Column1 列に含まれる値は、Int64.From で変換されるを確認**
```text
let
    Source = Table.FromColumns(
        {
            {0.4, 0.5, 1.4, 1.5, 2.4, 2.5}
        },
        {"Column1"}
    ),
    AddedColumn2 = Table.AddColumn(
        Source,
        "Column2",
        each Int64.From([Column1]),
        Int64.Type
    ),
    AddedColumn3 = Table.AddColumn(
        AddedColumn2,
        "Column3",
        each Int64.From([Column1], null, RoundingMode.AwayFromZero ),
        Int64.Type
    ),
    ChangedTypeColumn1 = Table.TransformColumnTypes(
        AddedColumn3,
        {{"Column1", Int64.Type}}
    )
in
    ChangedTypeColumn1
```
数値の丸めが異なることがわかる。Int64.From 既定の変換動作になってるよね。
|Column1|Column2|Column3|
|--:|--:|--:|
|0|0|0|
|0|0|1|
|1|1|1|
|2|2|2|
|2|2|2|
|2|2|3|

Currency.Type への変換でも Currency.From 既定の丸め動作になるし、タイムゾーンが関与する列の変換だと環境により異なる変換がされるよね。

```text:Power&#x20;Query
Table.TransformColumnTypes(
    Table.FromValue("2022-07-07T14:53:00Z"),
    {"Value", type datetime}
)
```

# 思ったこと🙄
Table.TransfromColumnTypes で行われる値の変換動作は、
- Culture.Current で確認できるロケール
- 動作環境
- Power Query 既定の動作

なのですよ。値の変換は必要になるまで実施されない。大事なことなのでもう一度、**値の変換は必要になるまで実施されない。**
# その他
https://powerbi.connpass.com/

- [Power BI 勉強会 - connpass](https://powerbi.connpass.com/)
- [Power BI Desktop を使い始めるには](http://qiita.com/PowerBIxyz/items/6c4735cb5b5712e70981)
- [Excel で Power Query を使い始めるには](http://qiita.com/PowerBIxyz/items/52e563037b855a099ca9)
BuildVariantsごとのGitSecretの扱い方

# はじめに
GitでRepositoryの管理をする際にAPIのkeyなどそのままPushしないためにGitSecretを使う方が多いと思うのですが...
https://github.com/awslabs/git-secrets

Android開発でステージングかリリース環境かでKeyが違う...って時に困ったのでメモです。
*多分もっとスマートなやり方があります...ゴリ押し手法です...

# やってみた
まずbuild.gradleで設定したBuildVariantsごとにpropertiesファイルを生成しましょう。
```
staging.properties
production.properties
```
次に各ファイルの中にそれぞれのKey情報を書き込みます。

```properties
API_KEY = "hogehogehogehoge"
SECRET_ID = "fugafugafuga"
```

完成したら今度はbuild.gradleの変更です。
```gradle
 def apiKeyPropertiesFile = rootProject.file("staging.properties")
 def apiKeyProperties = new Properties()
 apiKeyProperties.load(new FileInputStream(apikeyPropertiesFile))

 resValue "string", "API_KEY", apiKeyProperties['API_KEY']
 buildConfigField("String", "SECRET_ID", apiKeyProperties['SECRET_ID'])
```

これをBuildVariantsごとに設定してもらえればコード内で同じ変数名でも各環境で個別のキー情報を使用できます。

最後に作成したpropertiesにgit secretを適用することだけ忘れずに...
gradleでJavaのerrorが文字化けする。

# 環境
OS windows11
Gradle Version  7.4.2
Java Version 18.0.1.1



# 原因
環境変数"JAVA_TOOL_OPTIONS"の文字コードとコマンドプロンプトの文字コードが違う。
```
C:>gradlew.bat -p app run
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=Shift-JIS　← ➊JAVAの文字コードはShift-JISが設定される。

> Task :app:compileJava FAILED
C:\Users\�^�ߗ䂠����\Desktop\cmx-master\app\src\main\java\cmx\examples\App.java:30: �G���[: �s�K���Ȍ^: URI��URL�ɕϊ��ł��܂���:
            uri = (getClass().getResource("/KIRAKIRA.MID")).toURI();
                                                                 ^
C:\Users\�^�ߗ䂠����\Desktop\cmx-master\app\src\main\java\cmx\examples\App.java:37: �G���[: File�ɓK�؂ȃR���X�g���N�^��������܂���(URL)
        path =(new File(uri)).getPath();
               ^
    �R���X�g���N�^ File.File(String)�͎g�p�ł��܂���
      (�����̕s��v: URL��String�ɕϊ��ł��܂���:)
    �R���X�g���N�^ File.File(URI)�͎g�p�ł��܂���
      (�����̕s��v: URL��URI�ɕϊ��ł��܂���:)
�m�[�g:�ꕔ�̃��b�Z�[�W�͊ȗ�������Ă��܂��B-Xdiags:verbose�ōăR���p�C�����Ċ��S�ȏo�͂�擾���Ă�������
�G���[2��
・
・
・
BUILD FAILED in 1s
1 actionable task: 1 executed

C:>chcp 
Active code page: 65001　←➋コマンドプロンプトではUTF-8が設定されている。
```

# 解決
```
C:>set JAVA_TOOL_OPTIONS=-Dfile.encoding=UTF-8　←➊これを実行。

C:>gradlew.bat -p app run
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8

> Task :app:compileJava FAILED
C:\Users\UserName\Desktop\cmx-master\app\src\main\java\cmx\examples\App.java:30: エラー: 不適合な型: URIをURLに変換できません:
            uri = (getClass().getResource("/KIRAKIRA.MID")).toURI();
                                                                 ^
C:\Users\UserName\Desktop\cmx-master\app\src\main\java\cmx\examples\App.java:37: エラー: Fileに適切なコンストラクタが見つかりません(URL)
        path =(new File(uri)).getPath();
               ^
    コンストラクタ File.File(String)は使用できません
      (引数の不一致: URLをStringに変換できません:)
    コンストラクタ File.File(URI)は使用できません
      (引数の不一致: URLをURIに変換できません:)
ノート:一部のメッセージは簡略化されています。-Xdiags:verboseで再コンパイルして完全な出力を取得してください
エラー2個

・
・
・
・

BUILD FAILED in 1s
1 actionable task: 1 executed

C:>chcp 65001 ←➋念の為コマンドプロンプトの文字コードをUTF-8に設定。
Active code page: 65001
```


# 参考
https://stackoverflow.com/questions/9842134/setting-java-opts-globally-on-windows
https://www.javadrive.jp/command/display/index5.html
https://docs.oracle.com/javase/jp/8/docs/technotes/guides/troubleshoot/envvars002.html
AWS Certified Machine Learning - Specialty(MLS-C01) を取得しました

# はじめに
AWS認定コンプリートを目指すべく、MLS-C01を取得しました。

# AWS Certified Machine Learning - Specialty(MLS-C01) とは
[この辺](https://aws.amazon.com/jp/certification/certified-machine-learning-specialty/)を参照ください。

# 教材
機械学習の経験は全く無く、下記を約2週間かけて取り組みました。

1. 書籍：[ディープラーニングG検定(ジェネラリスト)最強の合格テキスト](https://www.amazon.co.jp/gp/product/481561167X/)
    - 最初は書籍無しで取り組むつもりでしたが、下記の問題集を見ても、さっぱり分からないため、購入しました。一般的には[公式テキスト](https://www.amazon.co.jp/%E6%B7%B1%E5%B1%A4%E5%AD%A6%E7%BF%92%E6%95%99%E7%A7%91%E6%9B%B8-%E3%83%87%E3%82%A3%E3%83%BC%E3%83%97%E3%83%A9%E3%83%BC%E3%83%8B%E3%83%B3%E3%82%B0-G%E6%A4%9C%E5%AE%9A-%E3%82%B8%E3%82%A7%E3%83%8D%E3%83%A9%E3%83%AA%E3%82%B9%E3%83%88-%E5%85%AC%E5%BC%8F%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88/dp/4798165948/)を購入するようですが、レビューを見ると低評価が目立ったため、こちらを購入してみました。
    - 分かりやすい内容だったと思います。ただ、全ての内容が盛り込まれている訳では無いため、ネットを駆使する必要があります。
1. Udemy：[AWS Certified Machine Learning Specialty Full Practice Exam](https://www.udemy.com/course/aws-machine-learning-practice-exam/)
    - 英語問題集です。
    - 問題数は少なく65問です。
1. [WEB問題集で学習しよう](https://aws.koiwaclub.com/exam/dbs/)
    - おなじみのやつです。
    - 154問(22セクションx7問)です。
1. [試験問題サンプル](https://d1.awsstatic.com/ja_JP/training-and-certification/docs-ml/AWS-Certified-Machine-Learning-Specialty_Sample-Questions.pdf)
    - 公式の試験問題サンプルです。
1. [Exam Readiness: AWS Certified Machine Learning - Specialty (Japanese)](https://explore.skillbuilder.aws/learn/course/629/play/34871/)
    - 公式の講義+問題集です。
    - 問題集は他よりも多く43問です。
1. [AWS Certified Machine Learning - Specialty Official Practice Question Set (MLS - Japanese)](https://amazonwebservices.benchprep.com/app/aws-certification-official-practice-question-sets-japanese#exams)
    - 公式の模擬試験です。
    - Skill Builderへ移行しているはずですが、そちらでは未だエラーとなり利用できません。。。

# 結果
上記と似たような問題は2割、なんとなく回答できたのは6割、全く分からないため直感で回答したのは2割でした。AWSに関係なく機械学習に関する問い、SageMakerに関する問い、Data Analytics(DAS-C01)よりの問い　と言った内容でした。

# 感想
- 機械学習がゼロベースであったため、専門用語がさっぱり分からず、最初の方は苦労しました。まずは、書籍で用語を理解してから、問題集へ取り組んだ方が良いと思います。
- 機械学習は数学の世界もあり奥が深いですが、試験に臨むだけではあれば、概要が分かっていれば良いと思います（数学の問題はありません。算数は若干あります）。
- これでコンプリートかと思いきや、SAP on AWSが残っていました。。。まずは情報収集から始めたいと思います。
ExperimentalContracts メモ

ある関数の戻り値が true だったら、その引数となった値が non-null として smart cast される例。

```kotlin
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract

fun f(s: String?) {
    if (isValidString(s)) {
        // isValidString(s) implies s is not null.
        val validString: String = s // <- smart casted here!
    }
}

// checks if s starts with "hoge:".
@OptIn(ExperimentalContracts::class)
fun isValidString(s: String?): Boolean {
    contract {
        returns(true) implies (s != null)
    }
    return s?.startsWith("hoge:") == true
}
```
Summary-Level Formula Column 


# 日付の対応

元の質問 : [Compare two date fields](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000HEAnpSAH)


```
IF(Lead.MQL_Date__c < DATEVALUE("2022-07-01") , 
Lead.MQL__c:SUM/28, Lead.MQL__c:SUM/24)
```

上記の数式ですが、このエラーになります。
Incorrect parameter type for operator '<'. Expected Object, received Date

色々フィールドを変えてみると、どうもDATEVALUE("2022-07-01")がObjectでないということみたい。しかしそうしたらLead.MQL_Date__cはオブジェクトかな？

更にHelpをよく探してみると、あああ、日付型には対応してないようですねぇ。

[Get the Most Out of Summary Formulas: Tips, Limits, and Limitations](https://help.salesforce.com/s/articleView?id=sf.reports_csf_tips.htm&type=5)

Functions for use with summary formulas in reports are available under the function category. Select a function, then click Help on this function for information.

Summary level formulas don’t support date or date-time functions or fields.

困ったなぁ。結果が数値のものしか受け付けないような感じです。
となれば、SUMを使って上記のIF文を成立させるしかない

まずは、数式フィールド（数値）を作ります。
これで、条件が一致した時はSUMをしても0なので判断できます。

```
IF(MQL_Date__c < DATEVALUE("2022-07-01") ,0,1)
```

Summary-Level Formula Column には以下を設定します。みごとに思った通りになりました。

```
IF(Lead.isMQL:SUM = 0 , Lead.MQL__c:SUM/28, Lead.MQL__c:SUM/24) 
```
# 数式が使えない

+ [レポートでのCASE関数の利用に関するエラー](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000Mivhx)

CASEは機能しません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/8c976d87-2125-c5e6-8a59-a8a0774f6f8f.png)

IFはエラーにはならないですが、判定に違和感がある
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/5b0f6f11-9b66-52ae-cc29-748651e66ac2.png)
Mecab   -Overview / Code


# MECAB　（形態素解析エンジン）
1. [依存ファイルのダウンロード](#依存ファイルのダウンロード)
1. [辞書のインストール](#辞書のインストール)
1. [実行](#実行)
1. [特定の品詞のみ抽出](#特定の品詞のみ抽出)

<a id="#依存ファイルのダウンロード"></a>
# 依存ファイルのダウンロード
 ```
    sudo apt install mecab
    sudo apt install libmecab-dev libmecab2 swig
    sudo apt install mecab-ipadic mecab-ipadic-utf8
 ```


<a id="#辞書のインストール"></a>
# 辞書のインストール
- mecab-ipadic-NEologd辞書のインストール (頻繁に更新されるのでお勧め)
    ```
    git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git
    /mecab-ipadic-neologd$ sudo ./bin/install-mecab-ipadic-neologd -n
    ```
     - 使用説明：
   ```
           mecab-ipadic-neologd$ echo `mecab-config –dicdir`"/mecab-ipadic-neologd"
  ```

---

- IPA辞書（IPADIC）のインストール　（更新滞っているが、簡単に使用可能）
```
    sudo update-alternatives --config mecab-dictionary
 ```

---
fugashiやmecab-python3は、mecabと一緒に自動でダウンロードされるが、辞書は一緒にダウンロードされない。



<a id="#実行"></a>
# 実行

- the basic way
 ```
    mecab -d /usr/lib/x86_64-linux-gnu/mecab/dic/mecab-ipadic-neologd
 ```

- the simpler way of the above
 ```
    mecab -Osimple -d /usr/lib/x86_64-linux-gnu/mecab/dic/mecab-ipadic-neologd
 ```

- wakati
 ```
    mecab -Owakati -d /usr/lib/x86_64-linux-gnu/mecab/dic/mecab-ipadic-neologd
 ```

- ChaSen
 ```
    mecab -Ochasen -d /usr/lib/x86_64-linux-gnu/mecab/dic/mecab-ipadic-neologd
 ```




<a id="#特定の品詞のみ抽出"></a>
# 特定の品詞のみ抽出

- 辞書: unidic-liteをインストール
 ```
    pip install unidic-lite
 ```


- 抽出する特定の項目e.g. 品詞 の番号を探す(今回は名詞を抽出)
 ```
    less pos-id.def
 ```

- Pythonスクリプト作成
 ```
import MeCab

mecab = Mecab.Tagger('-Osimple -d /use/lib/x86_64-linux-gun/mecab/dic/mecab-ipadic-deologd')

sentence = '夏ってこんなに暑かったっけ'
node = mecab.parseToNode(sentence)

while node:
  if 36 <= node.posid <= 67:
    print (node.surface)
  node = node.next
 ```

 - 実行
 ```
    python3 scriptName.py
 ```
Spekで詰まった際のあれこれ（livedataTest, mockk）

# はじめに
ほぼメモの殴り書きですが結構詰まったので個人用にまとめました。
他にも詰まったら更新していきたい

# liveDataのテストを書きたい
LiveDataをあれこれする際にはメインスレッドで動かす必要があるようですがUnitTest内だとメインスレッドで実行されないのでだめのようです。
普通にUT書く際には以下を記述していましたがSpekで実行する場合は怒られました。
```kotlin
@Rule
@JvmField
var instantTaskExecutorRule = InstantTaskExecutorRule()
```



```kotlin
class TestArchTaskExecutor : TaskExecutor() {
    override fun executeOnDiskIO(runnable: Runnable) {
        runnable.run()
    }

    override fun isMainThread(): Boolean {
        return true
    }

    override fun postToMainThread(runnable: Runnable) {
        runnable.run()
    }
}
```



```kotlin
　　　　　beforeEachTest {
            ArchTaskExecutor.getInstance().setDelegate(TestArchTaskExecutor())
        }

        afterEachTest {
            ArchTaskExecutor.getInstance().setDelegate(null)
        }
```


# 右クリック実行がしたい
＠RunWith(JUnitPlatform::class)を入れていなかった
エラー吐かれたらbuild.gradleを確認しましょう
```gradle
dependencies {
    testImplementation 'org.jetbrains.spek:spek-api:${version}'
    testImplementation 'org.jetbrains.spek:spek-junit-platform-engine:${version}'
    testImplementation 'org.junit.platform:junit-platform-runner:${version}'
    testImplementation "org.jetbrains.kotlin:kotlin-reflect:${version}"
}
```

※Android studioのSpekFrameworkをInstallしても解決しました。

# mockkを入れたら動かない
RunWithでなくSpekFrameworkで動かしていると下記エラーが起きてしまった際に解決した方法
java.lang.NoClassDefFoundError: io/mockk/proxy/MockKAgentFactory

```kotlin
//モックインスタンスの生成
        val mockService : MockService = mockk()
//下記のこっちだと動く
        val mockService = mockk<MockService>()
```
Pythonからのdll読み込みでOSError: [WinError 126]が出た話

# 現象
ThorLab株式会社様が作られたdllライブラリを使って
電動フリップマウントを動かしていた時です．
Python3.10では問題なく動いていたのが，
Python3.6で実行すると`OSError: [WinError 126]`が起きました．

# 解決策
大事なのは`os.chdir()`でした．
dllの入っているディレクトリに移動してから
`cdll.LoadLibrary`で読み込めば問題なく動きました．

# 原因は？
わかる方いらっしゃったらご教示願います。