OmniAICreator/Qiita-1.07M huggingface dataset:
素の OpenJDK 8 だと maven のリポジトリからダウンロードに失敗するので対処した件

:sweat_smile: 今更、OpenJDK 8 ですかというツッコミはなしで…

Oracle JDK から OpenJDK に切り替えてから、maven のセントラルリポジトリから、以下のような警告が出てダウンロードができなくなりました。

---

[WARNING] Failed to retrieve plugin descriptor for org.apache.maven.plugins:maven-clean-plugin:2.5: Plugin org.apache.maven.plugins:maven-clean-plugin:2.5 or one of its dependencies could not be resolved: Failed to read artifact descriptor for org.apache.maven.plugins:maven-clean-plugin:jar:2.5
Downloading from central: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-install-plugin/2.4/maven-install-plugin-2.4.pom

---

で、SSL の問題かと思い、

[maven - MavenにSSLエラーを無視するように指示する方法(およびすべての証明書を信頼する方法) - ITツールウェブ](https://cloud6.net/so/maven/39411)

というページを見つけ、以下のオプションを追加したら、ダウンロードできることは確認できました。

```
-Dmaven.wagon.http.ssl.insecure=true -Dmaven.wagon.http.ssl.allowall=true -Dmaven.wagon.http.ssl.ignore.validity.dates=true
```

ですが、セキュリティを無視するわけですから、気持ちよくありません。

おそらく https://repo.maven.apache.org/ の証明書を発行している認証局のルート証明書(DigiCert Global Root CA)が OpenJDK のキーストアに入ってないのだろうということで

[Java環境に手動でグローバルサインのルート証明書をインストールする方法 | サポート・お申し込みガイド | GMOグローバルサイン【公式】](https://jp.globalsign.com/support/faq/331.html)

を参考に keytool を実行したのですが、キーストアの初期パスワードが分からないという罠に。

[java - OpenJDK keytool password - Stack Overflow](https://stackoverflow.com/questions/56847306/openjdk-keytool-password)

を見つけ、`changeit` であることが分かりました。

```
keytool -import -alias DigiCertGlobalRootCA -keystore Path\to\java-se-8u41-ri\jre\lib\security\cacerts -file filename.pem
```

無事にキーストアに追加でき、特にオプションを指定しなくても Maven セントラルリポジトリから、ダウンロードできるようになりました。
`preinstall: typesync`がgit clone直後にエラーになるのを防ぐ

# はじめに

npm scriptsに[preinstall](https://docs.npmjs.com/cli/v7/using-npm/scripts#life-cycle-operation-order)を書いておくと、`npm install`とか`yarn add`の前に自動でスクリプトを実行してくれます。

TypeScriptで開発する場合、[typesync](https://github.com/jeffijoe/typesync)をpreinstall内で流すと、インストール時に`@types/`のパッケージがあれば自動インストールしてくれて便利です。

```json
{
  "scripts": {
    "preinstall": "typesync"
  }
}
```

# 問題点

`preinstall`が走る時点でtypesyncがインストールされていないと、スクリプトの実行がエラーになり、続くインストールが止まってしまいます。
そのため、typesyncがdevDependenciesに含まれてるプロジェクトをgit cloneしてきた場合、clone直後の`npm install`は失敗しちゃうんですね。

単独でtypesyncだけ先に入れるとか、そもそもグローバルインストールしておけば解決しますが、ローカルインストールでも`git clone && npm install`が普通に成功する方法があります。

# 解決策

```json
{
  "scripts": {
    "preinstall": "typesync || true"
  }
}
```

または

```json
{
  "scripts": {
    "preinstall": "typesync || :"
  }
}
```


https://linuxjm.osdn.jp/html/GNU_sh-utils/man1/true.1.html

>  true は何もせず、終了ステータスとして'成功'を意味する 0 を返す。 本コマンドはシェルスクリプト中で正常終了するコマンドが必要な場合に 使われる。なお，シェルのビルトインコマンド ':' （コロン）は 同じ動作をより速く実行する。

スクリプト全体の終了ステータスが0であればインストールが実行されるので、シェル芸で`command || true`すれば`command`が失敗してもインストールは続くわけです。`try-catch`でエラーを握りつぶす感覚に近いですね。

typesyncに関しては、clone直後のインストールであれば、その時点で`@types/`が新規追加されることはなくて、package.json内の全パッケージが入ればOKですからね。

もちろん、typesync以外ではちゃんと異常終了を検知すべき場合も多いので、やみくもにエラーを握りつぶさないようには気をつけましょう。

では今日はこのへんで！
NSExpressionで加算を行う

CoreData周りの技術を使っていると、たまに`NSExpression`が利用できると便利そうなケースがありますが、これまでなるべく避けておりました。今回、やっと使い方を調べてテストをパスしたので、似たようなニッチなところで困っている人のために記事を残しておきます。

# 利用可能なオペレーター
[expressionForFunction:arguments:](https://developer.apple.com/documentation/foundation/nsexpression/1413747-expressionforfunction?language=objc)のDiscussionで利用可能なオペレーターが列挙されています。

# 使い方
`FUNCTION`などで包まず、`add:to:(param1, param2)`という形式で指定します。

```swift
func testAddingTwoNumbersWithExpression() throws {
    let exp = NSExpression(format: "add:to:(1, 2)")
    let intValue = try XCTUnwrap(exp.expressionValue(with: nil, context: nil) as? Int)
    XCTAssertEqual(3, intValue)
}
```

# 他のオペレーションの使い方
引数を2つ取るものは同様に`xxx:yy:(param1, param2)`の記法で、
引数を1つしか取らないものは`xxx:(param1)`の記法で実装します。

## 引数が1つの場合のサンプル

```swift
func testAbs() throws {
    let exp = NSExpression(format: "abs:(-3)")
    let intValue = try XCTUnwrap(exp.expressionValue(with: nil, context: nil) as? Int)
    XCTAssertEqual(3, intValue)
}
```

# 注意点
パラメーターは必ず丸括弧の中に記載してください。そうでないとパースに失敗してエラーを投げます。

# どこで使うか
`NSBatchUpdateRequest`の[propertiesToUpdate](https://developer.apple.com/documentation/coredata/nsbatchupdaterequest/1506582-propertiestoupdate)や`xcmappingmodel`でのmigration時に簡単な処理の実行させるのに使うと便利です。

# おまけ: カスタム処理を利用する

カスタム処理は`FUNCTION`を利用することで利用可能です。

```swift
@objc public extension NSNumber {

    func threeTimes() -> NSNumber {
        return NSNumber(value: self.intValue * 3)
    }

}

// テストターゲット内
func testThreeTimes() throws {
    let exp = NSExpression(format: "FUNCTION(1, 'threeTimes')")
    let result = try XCTUnwrap(exp.expressionValue(with: nil, context: nil) as? NSNumber)
    XCTAssertEqual(result, 3)
}
```

# 参考
[How to use modulus operator with NSExpression?](https://stackoverflow.com/questions/29061407/how-to-use-modulus-operator-with-nsexpression)
Ubuntuでupdateすると毎回Warningが出る

# 起こったこと

いつものように apt updateなどしていると、以下の表示が毎回現れるようになりました。

```
update-initramfs: Generating /boot/initrd.img-5.4.0-71-generic
W: Possible missing firmware /lib/firmware/rtl_nic/rtl8125a-3.fw for module r8169
W: Possible missing firmware /lib/firmware/rtl_nic/rtl8168fp-3.fw for module r8169
I: The initramfs will attempt to resume from /dev/sdb3
I: (UUID=*****(怖いので伏せ字))
I: Set the RESUME variable to override this.
```
initramfsのアップデートが毎回うまく行っていない？
でもapt update周りはできてるぽくて、上記Warningがでても"Already up to date"とか言われます。
とはいえなんだか気持ち悪いので解決しようと思い、ネットでぼちぼち調べました。

# 実行環境

```
$ cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04.5 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.5 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic
```

# 解決方法
問題としては "missing firmware" 部分にあったっぽくて、とりあえず解決しました。
まず、無いものは以下から取ってくる。
普通にブラウザからダウンロードしましたが、wgetでも良い。それだと次の手順が飛ばせるため。
https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/tree/rtl_nic
私の場合はrtl8125a-3.fwとrtl8168fp-3.fwの２つ。

つぎに、メッセージに書かれている場所にコピー(移動でもいいと思う)。wgetで既に落とし込んでる場合はこれは飛ばす。

```
$ sudo cp rtl8168fp-3.fw /lib/firmware/rtl_nic/rtl8168fp-3.fw
$ sudo cp rtl8168fp-3.fw /lib/firmware/rtl_nic/rtl8168fp-3.fw
```

最後に、以下コマンドを実行して何もWarningが出なければ成功！

```
$ sudo update-initramfs -u
```

ずっとIssueの方で調べてたのですが、結果が出なかったのでWarningの方で調べ直しました、すぐ解決した...

# 参考にしたサイト
https://silverymemo.wordpress.com/2020/08/06/linux-mint%E3%81%A7possible-missing-firmware%E3%81%A8%E8%AD%A6%E5%91%8A%E3%81%8C%E5%87%BA%E3%82%8B%E5%95%8F%E9%A1%8C/

https://itectec.com/ubuntu/ubuntu-possible-missing-frmware-lib-firmware-i915/
JavaScriptのHoistingについてメモ

## この記事について
Hoistingができるタイプの変数とできないタイプの変数があるので整理する。
■Hoistingとは
宣言をする前でもその変数を使えることができる仕組み

## 変数のタイプ
① 関数宣言(Function Declaration) （関数に名前があるタイプ）
例）```function calc(a, b) {return a + b }```
② varでの変数宣言
③ const や letでの変数宣言
④ 無名関数(Function expression or arrow function)　（関数に名前がないタイプ）
例）```const calc = function(a, b) { return a + b }```

## Hoistingができるのは...

### ① 関数宣言
関数宣言の書き方では、宣言する前に関数を呼んでいるのに、ちゃんと戻り値5で返ってくるんです。（Hoistingが機能する）

```javascript:example1
console.log(calc(2, 3));

function calc(a, b) {
  return a + b;
}
```
コンソール上でのログ↓
![スクリーンショット 2021-04-15 13.23.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/291576/c34bc23b-a262-5c01-f27d-9e31d390635c.png)
Hostingによって宣言前でもエラーにならず動くのですね。

### ② varで宣言した変数
変数を定義する前にcalc変数を使ってみます。

```javascript:example2
console.log(calc);
var calc = 2 + 3;
```
コンソール上の結果はこちら
![スクリーンショット 2021-04-15 13.33.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/291576/3c523b38-b689-b022-95b8-151ebd5daba9.png)
エラーにはならないものの、undefinedで結果が表示されます。

### ③letやconstで宣言した変数
②と同じコードをletで書くと

```javascript:example3
console.log(calc);
let calc = 2 + 3;
```
コンソール上の結果はこちら
![スクリーンショット 2021-04-15 13.35.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/291576/1dea778e-1e5b-95af-8fe2-d333a01ec5a8.png)
エラーになりますね。
これはletやconstには、Temporal Dead Zone（TDZ）が適用されるから。
TDZは、そのスコープ内で、使いたい変数が定義される(この場合```let calc = 2+3```）以前に書かれたコードに対してはその変数は使えないよという意味。
なので上記の例では、「initializationの前には'calc'は使えません」ってエラーが出ています。

### ④無名関数
①と同じコードを無名関数で書くと

```javascript:example４
console.log(calc(2, 3));

let calc = function (a, b) {
  return a + b;
}
```
console.logで結果を確認すると、エラーになっています。
![スクリーンショット 2021-04-15 13.23.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/291576/4ff100a8-0fce-a4e1-72b8-ed2babb5676e.png)
③で見たエラーと同じですね。letで書いているのでTDZが適用されています。


ちなみに、無名関数をvarで書くとこのようなエラーになります。
![スクリーンショット 2021-04-15 13.30.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/291576/42fc6258-3c76-2bf6-61e8-f7115eccacf8.png)
②で見た例では、var宣言したものはエラーにならずundefinedと表示されました。
これは、varで定義するとundefinedとなりますが、undefinedという名前の関数のようになってしまい、「calc is not a function」とエラーが出てしまっています。

## Hoistingが適用されるとこんなことにも...

```javascript:example5
if(!num) delete();

var num = 10;

function delete() {
  console.log(`deleted!`);
}
```
↑はvarの定義をif文より上に書けば問題ないのですが、もし間違えて下に書いてしまった時の例です。

if文で0の初期値はfalseなのを利用して「!でfalse->trueにして0だったらdelete()を実行、0以外の数字だとfalseになりdelete()は実行しない」という意図で上記コードを書いたとします。
「numは10が入るのでdelete関数は動かない」なんて思ってしまったらバグになってしまいます。varで定義されているためHoistingが適用されて最初のif文でのnumはundefinedが入るんです。
undefinedの初期値はfalseなので、!で反転してtrueになり、delete関数が動きコンソール上に「deleted!」と表示されてしまいます。
一方constやletで書いていたとするとTDZが適用されてエラーになってくれます。

## 感想
letやconstを使っているならエラーが出るので大丈夫ですが、varを使用して意図せずHoistingが適用されりすると見つかりにくいバグができたりするのかなーと思いました。
Hoistingの仕組みを知っているとバグ調査の時も、「varで書かれてるからもしやHoistingが適用されているのかな？」と疑ってみることもできるので、大事な知識だと感じました。
STM32G031とMCP3425でなんちゃってluxを液晶表示(MCP3425A0T-E/CH 16bitADC)(明るさ)


X計算間違えで約2Vで約400luxにならないといけないがたんに電圧の100倍になっている、修正予定　2倍すればよい。修正済2021/4/18

構成
STM32G031J6M6
MCP3425A0T-E/CH
NJL7502L
AQM0802A


1.SCLとSDAを接続、プルアップも忘れずに
2.電源の接続
3.下記のソースコードを書き込む
4.コンパイル実行で表示されたら終了
5.おわり

参考

https://blog.goo.ne.jp/sircs-gid/e/1fb2f6e382a19a9d342561206c4bfeb4


```c++

#include <Wire.h> //I2C library

//STM32G031J6M6
#define sdaPin PA12    // ArduinoA4
#define sclPin PA11    // ArduinoA5

#define ADDR    0x68  // 2進数 1101000
#define I2Cadr  0x3e  // 固定

int     ii;           //ループカウンター

//初期レジスター
char INIT_com[]={0x0,0x38,
0x0,0x39,
0x0,0x4,
0x0,0x14,
0x0,0x70,
0x0,0x56,
0x0,0x6C,
0x0,0x38,
0x0,0xC,
0x0,0x1,
0x40,0x41};

//画面クリアレジスター
char INIT_cls[]={0x0,0x1};

//明るさをLCD表示形式に変換
char ch_hex_a_b[5];
char *ch_hex_a(int l_num)
{
    int a,b,c;
  
//  if( l_num >= 200 ) {
//    a=2;b=0;c=0;
//  } else if( l_num >= 100) {
//    a=1;b=(l_num-100) / 10;c=l_num % 10;
//  } else {
//    a=0;b= l_num / 10;c=l_num % 10;  
//  }

    // 2021/4/18 0から999まで10進数変換
    // 123の時
    // 123/10=12
    // 123-(12*10)=3
    // 12/10=1
    // 12-(1*10)=2
    
    b=l_num/10;
    c=l_num-(b*10);
    l_num=b;
    a=l_num/10;
    b=l_num-(a*10);
    //a=l_num/10;
    
    ch_hex_a_b[0] = '@';
    ch_hex_a_b[1] = '0' + a;
    ch_hex_a_b[2] = '0' + b;
    ch_hex_a_b[3] = '0' + c;
    ch_hex_a_b[4] = 0;
    return(ch_hex_a_b);
}

//i2c書き込みルーチン 2と4のみ
void i2c_led_w(char *buff1,int n){
  Wire.beginTransmission(I2Cadr);
  Wire.write(buff1[0]); //rs 0がレジスター rs 1がデータ
  Wire.write(buff1[1]); //値1
  if( n == 4 ) {
    Wire.write(buff1[2]); //値2
    Wire.write(buff1[3]); //値3
  }
  Wire.endTransmission();
  delay(2);
}//i2c_led_w

void setup()
{
  Wire.begin(sdaPin,sclPin); //STM32G031J6M6
  //Wire.begin(); //UNO
  //Serial.begin(9600); //UNO

  //液晶の初期化
  for(ii=0;ii<11;ii++){
    i2c_led_w(&INIT_com[ii*2],2);
  } //for

  //16ビットadcの初期値の書き込み
  Wire.beginTransmission(ADDR);
    Wire.write(0b10011000); //16bit 15sps PGA x1
  Wire.endTransmission();
  
} //end setup

int read_data() {

    //2文字の読み込み
    Wire.requestFrom(ADDR, 2);

    //戻し
    return ( (Wire.read() << 8 ) + Wire.read() );
}

void loop()
{
  int p,s; //明るさの一時変数
  
  //液晶のクリア
  i2c_led_w(INIT_cls,2);

  //明るさの読み込み
  s=read_data();
  //Serial.println(s); //uno

//  // 32768/163.84=200 luxに変換
//  p=( ((s>>5)*6)  + (s>>7)  ) >> 5;
//  //Serial.println(p); //uno

  // 32768/(163.84/2)=400 luxに変換
  p=( ((s>>5)*6)  + (s>>7)  ) >> 4;
  //Serial.println(p); //uno


  //画面に表示 0から200まで
  i2c_led_w(ch_hex_a( p ) ,4);

  delay(1000);  //1秒待つ

}//loop


```

![mcp3425_031_lux_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/a3e17c77-5f56-2482-7d65-aadab3386bdd.jpeg)
VBAの基本操作（セル）

VBAの初心者向けに基本操作方法（セル）を紹介していきたいと思います。

```:セルに文字列の表示
Cells(1, 1) = "こんにちは"
Range("A1") = "こんにちは"
```
Cells( )とRange( )はセルを指定します。

```:セル範囲を指定して文字列の表示
Range("A1", "A2") = "こんにちは"
Range(Cells(1, 1), Cells(1, 2)) = "こんにちは"
```
上記の様にRange( )とSells( )を組み合わせて使用することも出来ます。


```:セルの色変更
Cells(1, 1).Interior.Color = RGB(250, 0, 0)
```
RGBとは、色の表現法の一種で、赤 (Red)(●)、緑 (Green)(●)、青 (Blue)(●) の三つの原色を混ぜて幅広い色を再現する加法混合の一種です。表現方法については下記のサイトを参照すると良いです。
https://www.scollabo.com/banban/lectur/websafe.html


```:数列の表示形式
Cells(1, 1).NumberFormatLocal = "yyyy-mm-dd"  '20210416 ▶︎ 2021-04-16
Cells(1, 1).NumberFormatLocal = "#,###.##"    '12345678 ▶︎ 12,345,678.00
```


```:セルの削除
Cells(1, 1).Delete xlShiftToLeft   '削除して左へシフト
Cells(1, 1).Delete xlShiftToUp     '削除して上へシフト
Cells(1, 1).EntireRow.Delete       '行の削除
Cells(1, 1).EntireColumn.Delete    '#列の削除
``` 


```:セル内の文字列の削除
Cells(1, 1).ClearContents
```


```:行の挿入
Rows(1).Insert
```


```:コピーと貼り付け
Cells(1, 1).Copy            'コピーする
Cells(1, 2).PasteSpecial    '貼り付ける
```


```:切り取りと貼り付け
Cells(1, 1).Cut Destination:=Cells(1, 2)
```

```:枠線の操作
'上に枠線をつける
Range("B2").Borders(xlEdgeTop).LineStyle = xlContinuous
'範囲内の水平方向に線をつける
Range("B2", "D6").Borders(xlInsideHorizontal).LineStyle = xlContinuous
'範囲内の縦方向に線をつける
Range("B2", "D6").Borders(xlInsideVertical).LineStyle = xlContinuous

'枠線の上だけ削除
Range("B2").Borders(xlEdgeTop).LineStyle = xlLineStyleNone
'枠線を全て削除
Range("B2").Borders.LineStyle = xlLineStyleNone
```

　今回紹介した内容は普段からExcellを使用している方なら頻繁に利用する機能だと思います。これだけだとわざわざマクロを組む必要性はないと思いますが、いろいろな関数と組み合わせることでデータを集めたり拡散できたりといろいろなことができるようになります。

#蛇足
###ユーザーの操作無効化
Enabled関数とLocked関数を使用するとユーザー操作をできなくすることができます。

```:書き方
txtID.Enabled = False 'ロックしない場合はTrue
txtID.Locked = True   'ロックしない場合はFalse
```
PyInstallerで作ったファイルをTaskSchedulerで起動するとエラーになる

手動だと起動できるのに、タスクスケジューラ経由だとできない問題。
`Failed to execute script`というメッセージは表示される。


## 解決法
開始 (オプション)を指定してあげる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447423/f4d40e67-c02c-8892-ce2a-1249b6b0aac3.png)

## 参考にしたページ
ここのコメントにリンクがあって、
https://github.com/pyinstaller/pyinstaller/issues/4568

ここに解決法がありました。
https://stackoverflow.com/questions/51948219/pyinstaller-generated-exe-doesnt-run-with-windows-task-scheduler
leaflet で coast line の表示

# はじめに
R の leaflet でカラーマップなどを表示した際に、陸地と海の境界線が非常に見難くなった。そこで「海岸線(coast line)」のみを表示しカラーマップと一緒にプロットしようと考えた。その方法についていろいろと調べたので備忘録として記事に残しておく。

# GeoJSON データの入手
leaflet の中に海岸線のみを表示するような機能を見つけられなかった。一方で、GeoJSON形式で海岸線データを配布してくれているところ([https://github.com/nvkelso/natural-earth-vector](https://github.com/nvkelso/natural-earth-vector))があったので、それを使用することとする。

ここでは、1:10m, 1:50m, 1:110m の分解能でデータが提供されている。github 上で、geojson フォルダ内の、ne_10m_coastline.geojson, ne_50m_coastline.geojson, ne_110m_coastline.geojson のいずれかをダウンロードして使用する。

# GeoJSONデータを leaflet 上に表示
geojson を読み込み、スタイル（線の色、塗りつぶしの有無など）を変更し、`addGeoJSON`でleaflet 上に表示する。以下が、そのコードである。

```R:
#必要なパッケージの読み込み
library(dplyr)
library(leaflet)
library(jsonlite)
library(mapview)

#GeoJSONファイルの読み込み
#geojson <- read_json("./natural-earth-vector/geojson/ne_10m_coastline.geojson")
#geojson <- read_json("./natural-earth-vector/geojson/ne_50m_coastline.geojson")
geojson <- read_json("./natural-earth-vector/geojson/ne_110m_coastline.geojson")

#スタイルの変更
geojson$style = list(
  color = "#000", #線の色
　weight = 1, #線の太さ
  fill = FALSE #塗りつぶしの有無
)

#leaflet で表示
map <- leaflet() %>% addTiles() %>% addGeoJSON(geojson)
print(map)

#png に保存
mapview::mapshot(map, file = "./coast_line.png")
```
![coast_line.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1077734/f351d01d-d1a4-1c5f-6ff3-f55b75bd6c56.png)

海岸線が表示されているのが分かる。


# 分解能の違い（10m, 50m, 110m）
地図を拡大してみると、細かい部分の違いが見えてくる。分かりやすさのため線を太くし、石川県周辺(`setView(lng = 136.4, lat = 36.3, zoom = 8)`を追加)で見てみると、

110m：能登半島が直線で表されていて、形は全く分からない。
![coast_line_110m.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1077734/f73f79a9-9084-0ebe-7f6e-1a0d52b47d77.png)

50m：能登半島の概形が分かる程度
![coast_line_50m.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1077734/b49444f7-039e-baa8-0848-5ea93f04f712.png)

10m：細かい湾港まで形が分かる
![coast_line_10m.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1077734/7fe8496a-e072-d27a-c82a-5d2ff14becf5.png)

となる。もちろん細かい方がデータも重いので表示にかなり時間がかかる（自身のノートPCで10mの表示に数分かかった）ので、用途に応じて選択することが必要となる。

# おわりに
GeoJSON 形式のファイルなら同様の方法で leaflet に重ねていくことができると思われるので、他の GeoJSON データでもいろいろと試してみたい。また、今回はオープンソースになっている GeoJSON データを用いて、cosat line の表示を行ったが、もし leaflet のパッケージで簡単に行える方法をご存じの方がいれば是非コメント下さい！
Pタグとwidthの相性の悪さの落とし穴にハマったので報告します

Pタグの横幅設定に```width```すれば余裕で横幅調整できると思っていたら落とし穴にハマったので
ご報告します。


↓普通のPタグで日本語文字と意図しない文字、そして数字を囲ってみました。

```HTML
<p>おはようございます。こんにちは。こんばんは。おはようございます。こんにちは。こんばんは。おはようございます。こんにちは。こんばんは。おはようございます。こんにちは。こんばんは。</p>

  <p>hogohogohogohogohogohogohogohogohogohogohogohogohogohogohogohogohogohogohogohogohogohogohogohogohogohogohogohogo</p>

  <p>1234567891012345678910123456789101234567891012345678910123456789101234567891012345678910</p>
```
```CSS
p {
  width: 200px;
  border: 1px solid black;
}
```
結果↓
![first2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1311071/a2dc6f00-d2ce-5a64-0881-56db722b2294.png)


日本語文字は、```width```にきっちり納まってくれてます。
意図しない文字と数字は```width```の横幅からはみ出てしまいました

次に、```height```を設定したらどうなるか？検証してみます

```css
p {
  width: 200px;
  height: 250px; ※
  border: 1px solid black;
}
```

![second2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1311071/9f8997fb-0dc1-efd4-555f-c9b8f9c2a3ba.png)

きちんと縦幅、横幅は設定されています
検証ツールで確認しても同じです。

はみ出さない様に設定してあげるには

```css
p {
  width: 200px;
  height: 250px;
  border: 1px solid black;
  word-wrap: break-word; ※
}
```

![finish2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1311071/7e1d4bf9-2d70-64f7-4ae3-2ed63a8a502d.png)

```word-wrap: break-word; ```を設定したら無事『枠』に納まりました。

では、何故『意図しない文字と、数字』は```widhth```設定の枠からはみ出てしまうのか。
色々調べてみたら、問題解決に参考になった記事がありましたのでリンクします。

## 文字がはみ出してしまう

参考: [css – ブロックレベルから文字がはみ出してしまう](http://memorandum-plus.com/2018/04/03/css-%E3%83%96%E3%83%AD%E3%83%83%E3%82%AF%E3%83%AC%E3%83%99%E3%83%AB%E3%81%8B%E3%82%89%E6%96%87%E5%AD%97%E3%81%8C%E3%81%AF%E3%81%BF%E5%87%BA%E3%81%97%E3%81%A6%E3%81%97%E3%81%BE%E3%81%86/)



>>半角などの隙間がない英字（英単語の形ではないもの）だと、どこで折り返していいか分からず、そのまま伸びちゃってる現象です。



##　まとめ
半角で隙間のない英数字は、折り返し地点が不明になるので落とし穴にハマってしまう現象に陥ってしまう。
```word-wrap: break-word; ```　を設定してあげるか、隙間のある英数字とするか。
これで一応問題は解決しました。
```p```タグの文章がまだ決まっていない際「なんでも文章にしとおけば良い」とは限らずで
意外な部分に```p```タグと```width```の相性の悪さがありました。
ただ、問題は解決したので一安心


引き続き、codeを書き沢山エラーを出して解決力を向上させていきます。

今回は以上です
ありがとうございます！
LaravelからVueにデータ渡す

ネット上の情報を収集してから、実装した上での心得を整理してみました。

## 背景
Bladeファイルでは、Laravel Controllerからのデータを受け取って使うことが可能ですが、Vue.jsファイルの中に同じことができるかどうかを知りたくて、調査してみました。

調査した結果だと現時点では同じことができなさそうですが、代案がありまして、これを実装すればControllerからViewに渡すデータをVue側で取れます。

### jsの処理をBladeファイル内に実装すれば良いではないか？
そういうのも考えましたが、これも代案の一つ選択肢だと思います。
けど、やはりjs処理をBladeファイルに書きたくないので、別の案をしました。

## 対応方法
簡単な方法ですので、先に内容を書いておきます。
Bladeファイル内Controllerから渡してきたデータを受け取って、jsのGlobal変数に保存するとVue側で利用することが可能になります。

これからは対応の詳細を書きます。
1. 全体の構成
2. 本題に入る

## 全体の構成
### Controllers
app/Controllers/xxxController.php
表示したいViewと渡したいデータを設定します。

```xxxController.php
...略

public function index() {
    ...略
    return view('/yyy')->with('data', $data);
}
```

### Views
1. resources/views/yyy.blade.php
Viewの構成を管理します。
また、laravel-mixを使ってVue関連処理のjsファイルをrequireしますので、Vue関連処理のjsファイル（`resources/js/zzz.js`）が必要となります。また、`resources/js/zzz.js`には`resources/bootstrap.js`をrequireしています。

```yyy.blade.php
...略
<script src="{{ mix('js/zzz.js') }}"></script>

```

```zzz.js
require('../bootstrap');
...略

```

laravel-mixを使うため、webpack.mix.jsも編集します。

```webpack.mix.js
mix
.js('resources/js/zzz.js', 'public/js')
.vue();
```

### Routes
ルートを設定するため、`routes/web.php`を編集します。

```web.php
...略
Route::get('/xxx_index', [xxxController::class, 'index'])->name('xxx.index');

```

### ここまでのまとめ
一つの画面を作成するには、追加＆修正が必要なファイルは下記となります。
- xxxController.php
- yyy.blade.php
- zzz.js
- webpack.min.js
- web.php


## 本題に入る

### Vue側でControllerのデータを使う
対応方法にも書きましたが、まずはBladeファイル側でControllerのデータを受け取る。受け取ったデータをwindow.LaravelというGlobal変数に保存します。

同じ処理を各Bladeファイルに実装するのではなく、共通化できるようにしたいため、親Bladeファイル(`base.blade.php`)を作成し、その中に処理を実装し、各Bladeファイルがこの親Bladeファイルに継承するようにしました。
下記のように、`<script>`内にjsの処理を実装しました。

```base.blade.php
...略
<script>
    window.Laravel = {!! json_encode(['data' => $data ?? null]) !!};
</script>

```

### Vue側で利用する


```
let data = window.Laravel.data;
```

これでVue側で利用することができました！
エラーに遭遇(warning: parser/current is loading parser/ruby27, which recognizes warning: 2.7.3-compliant syntax, but you are running 2.7.2. warning: please see https://github.com/whitequark/parser#compatibility-with-ruby-mri.)

Rails+Docker+VSCodeという環境でVSCodeから表示された警告がみたことがなかったのでメモ。

### TL;DR
- Rubyのバージョンアップは大事(特にパッチレベル)
- Rubyのバージョンのパッチバージョンが上がったらバージョンアップするべし
- Dockerの場合は端末側のRubyのバージョン指定も変更するべし

### 動作環境
21/04時点での動作環境です。

|||
|:----:|:----:|
|MacOS|Catalina(10.15.7)|
|VSCode|1.55.0|
|Ruby|2.7.3|
|Rails|6.0.3.6|


### 内容
VSCodeに突然下記のような警告が表示されるようになりました。
`warning: parser/current is loading parser/ruby27, which recognizes warning: 2.7.3-compliant syntax, but you are running 2.7.2. warning: please see https://github.com/whitequark/parser#compatibility-with-ruby-mri. cannot load such file -- rubocop-rspec`

特にRailsやDockerの設定を変えた覚えはなかったのでとても焦りました。

### 原因
`parser`というgemが原因でした。
上記のコメントの中に[githubへのリンク](https://github.com/whitequark/parser#compatibility-with-ruby-mri)があったのでその内容をgoogle先生で直訳すると
`パーサーはセマンティックバージョニングを使用しません。パーサーのバージョンは次のように構成されますx.y.z.t。ここで、x.y.zはサポートされている最新のRubyリリースを示し（時系列的に早いすべてのRubyリリースのサポートを意味します）、t単調に増加する数です。`

という内容が書かれていました。

「じゃあいいじゃん、問題ないじゃん」

という話になるのですが、その下に
`Unfortunately, Ruby MRI often changes syntax in patchlevel versions. This has happened, at least, for every release since 1.`
と書かれています。
直訳すると、
`残念ながら、RubyMRIはパッチレベルバージョンで構文を変更することがよくあります。これは、少なくとも1.9以降のすべてのリリースで発生しています。`

どうやらRubyMRIでパッチレベルバージョンでの構文の変更が今回の警告に影響したようです。
> [Backwards compatibility
](https://github.com/whitequark/parser#backwards-compatibility)
> [whitequark/parser: A Ruby parser.](https://github.com/whitequark/parser#compatibility-with-ruby-mri)

### 解決法
Rubyのバージョンを上げて、それに伴う変更を行いましょう。
それで解決する(はず)です。
今回の内容はDocker環境・非Docker環境でも流れは一緒(のはず)です。


例えば今回の内容であれば(`2.7.2`から`2.7.3`へバージョンアップ)、

- 使用しているプロジェクトのルートディレクトリで`.ruby-version`の数値を変更する(`2.7.2`->`2.7.3`)
- ローカルでrbenvを使用しているなら
    - ruby-buildのアップグレード(brewのアップデートも必要)
    - rbenvで新しいバージョンのrubyをインストール
    - 使用しているプロジェクトに新しいバージョンを適用する

といった感じです。

これを手順化すると下記になります(<strong>rubyのバージョンはご自身の状況に合わせてください</strong>)。
手順1と手順4はそれなりに時間がかかります。

1.terminalで下記を実行してruby-buildのアップグレード、Rubyをインストール

```bash:terminal
brew update && brew upgrade ruby-build && rbenv install 2.7.3 && rbenv local 2.7.3 && rbenv rehash
```

2.`.ruby-version`の数値を変更

```diff:.ruby-version
+ 2.7.3
- 2.7.2
```

3.`Gemfile`にrubyのバージョンを明記していれば数値を変更

```diff_ruby:Gemfile
+ ruby '2.7.3'
- ruby '2.7.2'
```

4.Dockerfileを修正後`docker-compose build --no-cache`でコンテナを再構築(Docker環境のみ対象)

```dockerfile:Dockerfile
+ FROM ruby:2.7.3
- FROM ruby:2.7.2
```

上記を実行して特にエラーが発生していなければVSCodeで適当なrubyファイルを開いて保存してみてください。
上記の警告は表示されなくなっていると思います。

以上です。
ありがとうございました。
Azure Data Factory （Azure Syanpse Analytics pipeline）のコピーアクティビティにてAvro形式の日付型等（論理型）に関する注意事項

## 概要
Azure Data Factory （Azure Syanpse Analytics pipeline）のコピーアクティビティにて、Avroファイルの日付型を含む論理型（Logical Types）が利用ができないそうです。データフローでは利用できるそうなので、コピーアクティビティ以外の代替案の検討が必要です。


## Avroの日付型
Avroのドキュメントを参照すると、日付型はプリミティブ（基本データ）型には含まれておらず、論理型に分類されている旨が記載されております。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/3b5c9694-3aa6-3cd0-492a-6b504934fcee.png)
引用元：[Apache Avro™ 1.10.2 Specification](https://avro.apache.org/docs/current/spec.html#schema_primitive)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/67e168f2-bc28-115c-1548-a383033efc4b.png)
引用元：[Apache Avro™ 1.10.2 Specification](https://avro.apache.org/docs/current/spec.html#Logical+Types)



## Azure Data Factory （Azure Syanpse Analytics pipeline）のドキュメント
ドキュメントにて、下記のように複合データ型がサポートされていないとの記載があり、論理型に関する記載はないのですが同様にサポートされていないようです。

> Avro の複合データ型はサポートされていません

引用元：[Azure Data Factory での Avro 形式 - Azure Data Factory | Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/data-factory/format-avro#data-type-support)


同じドキュメントにて、データフローであれば複合データ型がサポートされているとの記載があり、論理型に関する記載はないのですが同様にサポートされているようです。

> データ フローで Avro ファイルを使用する場合は、複合データ型の読み取りと書き込みを行うことができますが

引用元：[Azure Data Factory での Avro 形式 - Azure Data Factory | Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/data-factory/format-avro#data-type-support)
VS Codeの置換について（Mac版）

VS codeで置換をしたい。

①command+[F]

![20210416-130955.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/960935/e6378231-69ef-d00a-2377-cd399b377423.png)
が右上にあらわれます。

②検索窓「end」左横の「>」をクリック
![20210416-131031.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/960935/2a425301-6547-ef33-8137-caa574439697.png)


③上の検索窓には置き換えるべきワード。下の検索窓には置き換えたいワードを入力

![20210416-131628.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/960935/8a9dfa14-2b91-6c14-0908-9c462a509e48.png)


④一括で置き換えと１語づつ確認しながら置き換えはそれぞれは右下のアイコン

一括置き換え
![20210416-131825.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/960935/f1b02b81-4e91-61da-e0d9-d50c779b4a99.png)
をクリック

１語づつ
![20210416-131815.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/960935/70177cbe-9e2b-8b5f-18bb-948939787694.png)
をクリック
strptime()の引数に空文字を指定した場合の戻り値が異なる

諸事情でPHP5.6.40で`strptime()`を使った際に沼ったので備忘録として。

- 開発環境では問題なかった。
    - 本番環境（開発環境とは別サーバ）で発生した。
    - 共にPHPは5.6.40
- ライブラリの問題？
    - 参考
        - https://mikeda.hatenablog.com/entry/20090112/1231739798


```php
var_dump( strptime('') ); // 想定される戻り値は false
```

でも実際に返ってきた値は以下。
パースしちゃってるので`empty()`などで事前チェックしましょうねってことで。

```
array(9) {
  ["tm_sec"]=>
  int(0)
  ["tm_min"]=>
  int(0)
  ["tm_hour"]=>
  int(0)
  ["tm_mday"]=>
  int(0)
  ["tm_mon"]=>
  int(0)
  ["tm_year"]=>
  int(0)
  ["tm_wday"]=>
  int(0)
  ["tm_yday"]=>
  int(0)
  ["unparsed"]=>
  string(0) ""
}
```
【SwiftUI】最低限のコードでカメラのプレビューを表示する

SwiftUI上で必要最低限のコードでカメラのプレビューを表示します。

- フロントカメラのみ
- デバイスの向きはポートレートのみ
- カメラのアクセス許可のチェックなし

# 環境

- Swift: 5.3.2
- Xcode: 12.4 (12D4e)
- macOS: Big Sur 11.1 (20C69)

# コード

```swift:ContentView.swift
import SwiftUI
import AVFoundation

struct ContentView: View {
    var body: some View {
		CameraView()
			.edgesIgnoringSafeArea(.all)
    }
}

struct CameraView: UIViewRepresentable {
	func makeUIView(context: Context) -> UIView { BaseCameraView() }
	func updateUIView(_ uiView: UIViewType, context: Context) {}
}

class BaseCameraView: UIView {
	override func layoutSubviews() {
		super.layoutSubviews()
		_ = initCaptureSession
		(layer.sublayers?.first as? AVCaptureVideoPreviewLayer)?.frame = frame
	}

	lazy var initCaptureSession: Void = {
		guard let device = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera],
															mediaType: .video,
															position: .unspecified)
				.devices.first(where: { $0.position == .front }),
			  let input = try? AVCaptureDeviceInput(device: device) else { return }

		let session = AVCaptureSession()
		session.addInput(input)
		session.startRunning()

		layer.insertSublayer(AVCaptureVideoPreviewLayer(session: session), at: 0)
	}()
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
```

```xml:Info.plist
	<key>NSCameraUsageDescription</key>
	<string>This app uses the camera</string>
```

# リポジトリ

https://github.com/sugiharam2-samples/SwiftUICamera01
M1搭載のMacbookでAmong Usをプレイする方法

## 細かい諸々は省略
表題の通りです。

- SteamでAmong Usをダウンロードしたらwindowsでしか起動できなかった
- M1でBootcamp使ってwindows入れようとしたらまだ対応していなかった
- スマホだとAutoMuteUsBotが使えない

これらの課題を解決するために、windowsPCを買おうとしましたがなんとかなったので共有です。

## 結論
お急ぎの方が多いと思うので、細かい説明を省いてどうやればできるかだけ書きます。

**①Bootcampの代わりにParallelsをインストールする（14日間は無料）**
[M1に昨日正式に対応したらしい。](https://www.parallels.com/news/press-releases/show/2021-pd16-5-m1chip/)

[ここ](https://www.parallels.com/jp/)からインストール

**②Windowsのイメージを入れる**
ちょっと手こずりました。ARMに対応しているものを入れなければならなかったです。
[ここ](https://www.microsoft.com/en-us/software-download/windowsinsiderpreviewARM64)からゲット

Microsoftアカウントを持っていない人は作成し、insiderプログラムに参加する必要があります。
自分の場合ぽちぽちクリックして行ったらできました。

ダウンロードは30分くらいかかりました。重めです。

**③Parallelsを起動して②のイメージを選択して実行する。**
起動すると、どのイメージで実行するか聞かれるので、②でダウンロードした
「Windows10_InsiderPreview_Client_ARM64_en-us_21354.VHDX」を選択します。

**④windowsが起動するので、steamをインストールして、その後amongusをインストールする**
プレイを押すと起動できます。最大化を勝手にするので、気をつけてください。
option + return を押せば回避できます。steamの設定からwindowで開くこともできます。
ただ、サイズは変えられなさそうでした。

![スクリーンショット 2021-04-16 10.08.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/557847/19fa1d05-e66c-1998-441f-97fb5d3dbe3b.png)

やったぜ！
Google Sitesに設定したHTMLをMarkdown化するために特定タグ内のみ置換や削除 した

Google Sitesに登録されているドキュメントを、どうにかMarkdownに変換できないかと思ったのですが、
でも、WYSIWYGエディタで生成されたHTMLは結構怪しい構造になっており、
ツールによる変換を行うことができず、色々と加工する必要がありました。
その加工のうちの一つについて説明します。

正規表現で抜き出した部分のみを対象として、さらに正規表現で置換をかけた方法です。
言葉で説明するのが下手くそなので、見ていただいたほうが意味がわかるかもしれないです。

まずはこいつを見てほしい。

```html
<div>
  hoge<br>
  fuga
  <p>
    piyo<br>
    piyo
  </p>
  <p>
    foo<br>
    <br>
    bar
  </p>
</div>
```

すごく適当です。

今回説明するのは、上記のHTMLから、pタグの中のbrタグだけを削除する方法です。
（divタグ直下のbrは残す）

つまり、以下の結果を期待する、と。

```html
<div>
  hoge<br>
  fuga
  <p>
    piyo
    piyo
  </p>
  <p>
    foo
    
    bar
  </p>
</div>
```


で、行った処理がこちら

```javascript
const str = "<div>\n  hoge<br>\n  fuga\n  <p>\n    piyo<br>\n    piyo\n  </p>\n  <p>\n    foo<br>\n    <br>\n    bar\n  </p>\n</div>"
const replaced = str.replace(/<p>(.*)<\/p>/sg, function(match){ return match.replace(/<br>/g, '') })
console.log(replaced);
```

まあ、String.prototype.replace()を当然利用するわけなんですが

[String.prototype.replace](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/replace)

replaceの第２引数には、関数を指定可能であると。
で、正規表現にグローバルフラグ `/正規表現/g <- コレ ` を付けていると、マッチした回数だけ、無名関数の第一引数 `match` にマッチした部分文字列が入った状態で実行されるわけです。
示した例だと、pタグが2つあるので、２回実行されます。

```javascript
var str2 = "<div>\n  hoge<br>\n  fuga\n  <p>\n    piyo<br>\n    piyo\n  </p>\n  <p>\n    foo<br>\n    <br>\n    bar\n  </p>\n</div>"
var replaced2 = str.replace(/<p>(.*)<\/p>/sg, function(match){ console.log(match) })

//// １回目の無名関数実行の第一引数matchのvalue
//  <p>
//    piyo<br>
//    piyo
//  </p>
//// 2回目の無名関数実行の第一引数matchのvalue
//  <p>
//    foo<br>
//    <br>
//    bar
//  </p>

```

HTMLの場合なんかだと、タグ間の改行も考慮が必要なので、 sフラグ `/正規表現/s <- これ` も付けます。

```
/<p>(.*)<\/p>/sg　// <- つまり、sフラグとgフラグをつけてこうなる

```



この無名関数内で、returnした値が、matchした箇所と置換されることになります。
なので、matchに対して、再びプロトタイプのreplace関数を実行したものを returnすると

```javascript
match.replace(/<br>/g, '') // brタグを削除する置換

```


意外と情報がなかったので備忘録として。
情報がなかったのは、正規表現を利用しないもっと良いやり方があるのかもしれない。。。
【TypeScript】インターフェイスの一部のキーからなるユニオン型を作る

```ts
interface Alarm {
  Sun: number;
  Mon: number;
  Tue: number;
  Wed: number;
  Thu: number;
  Fri: number;
  Sat: number;
}
```

からTue以外のキーからなるユニオン型`"Sun" | "Mon" | "Wed" | "Thu" | "Fri" | "Sat"`を作る。


```ts
type Syukkinbi = keyof Omit<Alarm, 'Tue'>;
// type syukkinbi = "Sun" | "Mon" | "Wed" | "Thu" | "Fri" | "Sat"
```

SunとSatを除く場合

```ts
type Heijitsu = keyof Omit<Alarm, 'Sun' | 'Sat'>;
// type Heijitsu = "Mon" | "Tue" | "Wed" | "Thu" | "Fri"

```

#### コメントありがとうございます。

@sugoroku_y さんから教えて頂きました。

`Exclude`をつかって書くこともできる。

```ts
type Syukkinbi = Exclude<keyof Alarm, 'Tue'>;
// type Syukkinbi = "Sun" | "Mon" | "Wed" | "Thu" | "Fri" | "Sat"

type Heijitsu = Exclude<keyof Alarm, 'Sun' | 'Sat'>;
// type Heijitsu = "Mon" | "Tue" | "Wed" | "Thu" | "Fri"
```
【就活用】SESの求人募集していない企業を探す便利な方法

#はじめに
SESとして働くことは、企業に常駐し技術提供を行うことです。
その企業のプロジェクトに参加し、その企業の問題・課題等を解決する素晴らしいお仕事です。

素晴らしいお仕事であると知っていながらも、エンジニアリングを仕事とする上で、SES以外の受託開発、自社開発で働きたいという方向けの記事です。

求人情報からSES募集でないことを確認できる方法を共有します。

#本記事では何が得られるか
本記事では、求人サイト（Wantedly）において
企業の求人内容でSESを募集していることを、一瞬で見極める方法を紹介します。

転職活動では時間に余裕はなく、自分が働きたくない業種の選考には進みたくないと思います。

転職者がSES以外のエンジニアを希望しているにも関わらず、
面接中に、「実はSESでの募集でした」と言われてしまったら、転職者と企業にミスマッチが起こってしまいます。

以下の方法を使えば、予め転職者が効率的に、SESの案件以外の自社開発、受託開発の求人をサイト内で探しやすくなります。

もちろん、以下の方法を使って、さらに求人内容をよく見たとしても、面接の中で実はSESの募集であることや、いざ入社してから実はSESとして勤務するということはあるかと思います。

本記事ではあくまでも考察手段としてご参考ください。

#メソッド、それは検索
①Wantedlyの求人情報の閲覧画面にいきます。

②Macであればキーボードで"command + F"を押す

③検索欄に「ses」と入力しEnterを押し、検索をかける

④③で表示されなかったら検索欄に「常駐」と入力し検索をかける

※時々「ses案件ではありません」等の逆接的表現をしている求人もあるので、検索がヒットしても目視で確認してください。

#最後に
検索機能を使い、SES案件を即座に見極めることができるので、それ以外の求人応募を効率的に探し出すことができます。

いずれにせよ募集内容がどんなものかを最終確認する必要があるので、確認作業はミスマッチを防ぐためにも重要になります。

以上です。
TypeScriptでaxiosのmockテストを実行するための3つのポイント

## 概要

TypeScript で axios の mock が正常に動かない問題の解決策の1つを共有します。
axios の mock を単純に書いても正常に機能しません。

コードの完全なサンプルは次の repository に置いてあります。
https://github.com/algas/axios-mock-example

## TypeScript で axios mock テストを動かす3つのポイント

1) client コードで axios adapter に HTTP を設定する  

```.ts
const httpAdapter = require('axios/lib/adapters/http');
axios.defaults.adapter = httpAdapter;
```

2) client コードから axios を export する  

```ts
import axios from 'axios';
export { axios as axiosModule };
```

3) client から import した axios module を `axios-mock-adapter` で呼び出す  
Jest を使ったテストの例

```ts
import { getUser, axiosModule } from 'axios-client-example';
import MockAdapter from 'axios-mock-adapter';

test('mock test getUser', async () => {
  const mock = new MockAdapter(axiosModule);
  const resData = { /* foo: bar */ }; // mock response data
  mock.onGet('/path/to/client').reply(200, resData);
  // write code to test your client
  mock.reset();
});
```

もし client と test を同じパッケージ内で使う場合には axios の import, export は不要です。

## まとめ

axios adapter に HTTP を設定して `axios-mock-adapter` を使うことで TypeScript で axios mock のテストが実施できます。
もっといい方法を知ってる場合にはぜひコメントをいただけるとうれしいです。
【Flutter】Textを簡単にグラデーションさせる

#パッケージのインストール
gradient_textを導入すれば簡単にテキストのグラデーションを実装できます。

```yml:pubsub.yml
gradient_text: ^1.0.2
```

#インポート
```dart
import 'package:gradient_text/gradient_text.dart';
```

#グラデーション可能なテキストウィジェットを作成
テキストウィジェットを下記のGradientTextに置き換えるだけです。

```dart
GradientText("テキスト",
  gradient: LinearGradient(
      //ここでグラデーションの色を複数設定できる
      colors: [Colors.deepPurple, Colors.deepOrange, Colors.pink]
  ),
  style: TextStyle(fontSize: 30), //スタイルも設定可能
  textAlign: TextAlign.center); //テキストの配置
```
StoryboardとXibと繋げる方法

Xibを作成

Viewも一緒に作成してください。

![スクリーンショット 2021-04-16 12.10.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494487/61eab066-bbb4-c8d5-4a49-0638b9a13f43.png)

Class名を統一させてください。

![スクリーンショット 2021-04-16 12.11.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494487/c6574a72-8c36-88de-6112-70da9e1038da.png)

VeiwController側でxibを呼び出します。
そしてViewControllerでxibを追加します


        let view: UIView = UINib(nibName: "buttonView", bundle: nil).instantiate(withOwner: self, options: nil).first as! UIView
                self.view1.addSubview(view)
Swiftでのクラス

#WHY
最近日常で実際に使ってみたいアプリを思いつき、それを実現させるため、Swiftを勉強し始めました。今後はswiftについてのアウトプットが増えていくと思います、今回は基本のSwiftでのクラスについてアウトプットしていきます、

## クラスとは
クラスとは簡単にいうと設計図です、その設計図を元にインスタンス、つまり「もの」を作ることができます。
考え事態はRubyなどと同じです。

## クラスの継承
Swiftで重要になってくるのがこのクラスの継承、、
継承は以下のように書きます、

```swift
//「A」というクラスがあった場合
class A{

}

//「B」クラスに「A」クラスを継承させる
class B:A{

}
```

そして今回私が勘違いしていたことなのですが

```swift
//パターン１
@IBOutlet weak var imageView: UIImageView!

//パターン２
var timer = Timer()
```

<b>これらはクラスの継承ではありません!!</b>
パターン１はimageViewを<b>UIImageView型で宣言した</b>ということです。
コロンより右の「UIImageView」はクラスではなく、「型」であるということです。

「UIImageView」以外にも「UILabel」（テキストの要素）、「UIButton」(ボタンの要素)などの<b>クラスがあらかじめ用意</b>されています。
それらを使うことでそれぞれの型のプロパティを宣言することができます。

パターン２では<b>変数「timer」は「Timer型」</b>だよ、と宣言している文です。

そしてそれらのクラスは「UIKit」というものの中に入っています。

## import
viewcontrollerファイルをみてみるとはじめに

```swift
import UIKit
```
という記述があります。
これは<b>あらかじめSwiftが用意されているクラスや機能、そして「型」を全てこのファイルで使えるようにする</b>という宣言のようなものです。
ほかにもpodというライブラリなどを導入することでこのimportは追加記述することができます、
つまりこの<b>importを増やす</b>ことで、<b>使えるクラスやメソッドや機能が増えてい</b>くということです、

-----------
今回ご指摘をいただき、記事を一度修正させてもらいました。型という概念をイメージしながら今後も学習進めていこうと思います！！
統計検定2級:合格レポート

2021年3月に[統計検定2級(CBT方式)](https://www.toukei-kentei.jp/cbt/)を受けてきました。
本記事はその議事録です。これから受験する方の参考になれば良いと思っています。

##目次
1：CBTを受験した感想
2：使用テキスト
3：勉強時間・勉強方法
4：CBTのコツ

##1：CBTを受験した感想
まず、私の結果ですが70点(60点以上で合格)で合格しました。![スクリーンショット 2021-04-16 8.47.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/861630/84d68d23-f887-5d52-79fc-154bc6438720.png)

受験する前にCBT方式に関するネット記事やtwitterで統計検定2級と検索していると「CBTは時間が足りない」「一問一答」「検定の問題がたくさん出題される」「計算問題がたくさん出題される」と言う方が多かったです。
実際に、私が受験した感覚だと「時間は余る」「一問一答」「検定はペーパーテストと同じくらい」「計算問題は多い」という感想です。ネットの方々は計算問題が多いから時間が足りないということだと思うのですが、確かに計算問題が多いですが消去法で回答できる問題も多く、計算する必要がない問題も多かったです。また、検定の問題に関してはペーパーテストと同じくらいの量でした。
CBT方式は、問題がランダムに出題されているので、今回私が受験した内容だと上記のような感じでした。

##2：使用テキスト
受験するにあたり、勉強に使用したテキストを紹介します。
①[統計検定2級公式問題集2017-2019](https://www.amazon.co.jp/%E6%97%A5%E6%9C%AC%E7%B5%B1%E8%A8%88%E5%AD%A6%E4%BC%9A%E5%85%AC%E5%BC%8F%E8%AA%8D%E5%AE%9A-%E7%B5%B1%E8%A8%88%E6%A4%9C%E5%AE%9A-2%E7%B4%9A-%E5%85%AC%E5%BC%8F%E5%95%8F%E9%A1%8C%E9%9B%86-2017%E3%80%9C2019%E5%B9%B4/dp/4788925524)
②[kindle unlimited統計検定2級模擬問題集1-3](https://www.amazon.co.jp/%E7%B5%B1%E8%A8%88%E6%A4%9C%E5%AE%9A2%E7%B4%9A-%E6%A8%A1%E6%93%AC%E5%95%8F%E9%A1%8C%E9%9B%862-BellCurve-ebook/dp/B07G6XFMFR)
③[統計web](https://bellcurve.jp/statistics/)
の3つです。

①は定番の公式問題集です。これは間違いなく必須でしょう。
②はkindleで読むことができる模擬問題集です。統計webを運営している会社が出版しており、基礎を抑えるのに役立ちます。
③は統計webと言うサイトです。統計検定を受験する方はみなさんこのサイトを活用しています。
私はこの3つを用意すれば十分だと感じました。費用も3000円以内で済むと思います。

##3：勉強時間・勉強方法
まず、勉強時間ですが合計で20時間いかないくらいです。
内訳は、公式問題集12時間、模擬問題集3時間、統計web3時間くらいです。
続いて、勉強方法です。あくまで個人的な方法なので、この方法を試せば合格を補償できると言うわけではありません。
①過去問3年分を一周する(一周目の出来は30~50%)。
②過去問でわからなかった問題を統計webの解説で調べる(過去問の解説がわかりにくい)。
③過去問3年分の二周目をやる(二周目の出来は70~90%)。
④模擬問題集を一周解く。
このような流れで行っていました。これで、本番70点でした。

##4：CBTのコツ
CBTはペーパーテストの問題と全く違います。なので、CBT用の対策が必要だと終わってから感じました。
コツ1：感想のところで少し述べたように、一問一答なので、とにかく文章を読むスピード・計算スピードが求められます。そこで、過去問を30分~60分で解けるようになるとCBTでも時間余るレベルになると思います。
コツ2：一問一答になったからなのか、ペーパーよりも問題が基礎的な内容になったように感じました。なので、用語や公式など基礎を抑える必要があります。模擬問題集がこれらの対策にはピッタリです。

##最後に
統計学はこれからの時代の教養科目になると思うので、ぜひ勉強してみてください。
Xibのサイズ変更

![スクリーンショット 2021-04-16 12.07.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494487/bda69794-dfa1-2f38-f6c3-cf5142850c17.png)

SizeをFreeformにします。
![スクリーンショット 2021-04-16 12.08.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494487/be70de27-2c74-1dd9-7eff-851fe4edc792.png)

すると上記の画面でもXib上でも変更できるようになります。
Amazon CloudFrontについてメモ

## はじめに

[AWS サービス別資料](https://aws.amazon.com/jp/aws-jp-introduction/aws-jp-webinar-service-cut/) にある [Amazon CloudFrontの概要](https://d1.awsstatic.com/webinars/jp/pdf/services/20190730_AWS-BlackBelt_Amazon_CloudFront.pdf) の資料をもとに社内で勉強会を実施しましたので、そのメモを共有します。

## Amazon CloudFrontについて

### 概要

* AWSが提供するCDN（Content Delivery Network）サービス
* 世界中のエッジにオリジンのキャッシュが展開する
* リージョンによらず世界中のアクセスからのレスポンスを改善し、オリジンの負荷を削減

### 構成要素
* オリジン
  * キャッシュ元のWebサイト・サービス

* エッジロケーション
 * 「エッジ」はIoTでも使われるエッジコンピューティングのエッジと同じで、利用者の近くでコンピュータ資源を使うことを指す
 * エッジロケーションは世界に約200拠点ある。リージョン、AZの中または近くにある（はず）
 * グローバルサービス（Route53とか）も AWS エッジロケーションでホストされている
 * ユーザに近い拠点で配信することになり、レイテンシ（通信遅延）が減少し、ユーザ体験を高めることにつながる

* リージョナルエッジキャッシュ
 * 最近はエッジロケーションとオリジンの間にリージョナルエッジキャッシュという大容量キャッシュ層が挟まれていて、スペック向上している
 * https://dev.classmethod.jp/articles/cloudfront-regional-edge-cache/ が参考になる

* 「ユーザの近く」はどうやってわかる？
 * 謎テクノロジー
 * 資料p.15の図によると、CloudFront専用のDNS（機械学習込み）で99.8%の精度で位置および国情報がわかるらしい

### 機能

* 以下のHTTP/HTTPSメソッドに対応
 *  GET, HEAD, OPTION(選択可能) (Cacheモード)
 * PUT, POST, DELETE, OPTION, PATCH (Proxyモード)
　→ キャッシュはされず、 オリジンにフォワードする

* キャッシュ時間
 *  デフォルトは24時間
 * キャッシュコントロールヘッダー（デフォルトTTL、最小TTL 、 最大TTL） の 3 つの値でコントロール可能
 * 最小TTL = 0秒 の場合とそれ以外の場合でCache-Control no-cacheの挙動が違うため注意

* キャッシュの無効化
 * コンテンツごとまたはワイルドカード指定可能。（ただし料金はかかる）

* ヘッダーをオリジンへ転送
 * 任意のヘッダーを付与することが可能
 * CroudFront独自ヘッダーとして、接続プロトコル、デバイス判定、地域・国判定した結果をオリジンに送ることが可能

* Cookie をオリジンへ転送
 * Cookieもキャッシュする
 * セッション情報などキャッシュできないものに絞ってホワイトリストに追加してフォワードする

* クエリパラメータ値をオリジンへ転送
 * クエリパラメータと値もキャッシュする
 * languageなどキャッシュできないものに絞ってホワイトリストに追加してフォワードする

* カスタムエラーページの生成
 * オリジンで5xxエラー発生時にS3のカスタムエラー静的HTMLを表示する
 * エラーキャッシュ期間はデフォルト5分

* タイムアウト
 * オリジンの読み取りタイムアウト（デフォルト30秒、4秒〜60秒まで指定可能）
 * キープアライブタイムアウト（デフォルト5秒、1秒〜60秒まで指定可能）

* オリジンフェイルオーバー
 * プライマリオリジン、セカンダリオリジンを指定可能
 * オリジンシールド（オリジンへの到達の前に必ず通過する配信拠点）を設定可能

* セキュリティ
 * 地域・国制限 - クライアントの地域情報を元にアクセス制御できる（ブラックリストまたはホワイトリスト）
 * 署名付きURL/Cookie - セキュリティ要件が厳しいデバイス -  オリジン間で使える？
 * AWS WAF、AWS Shield - オプションでCloudFrontの前段に設置できる

* レポート・統計
 * CloudWatch連携あり
 * Google Analytics的に分析用途にも使える？
 * アクセスログの詳細解析用としてAmazon Athena、QuickSightに流す用途もあり


### 性能

* 他CDNよりもトラフィック減少
 * p.20の図は悪いグラフ図（赤線が同じ位置にない）

### 料金体系

* AWS EC2やS3のオリジンからCloudFrontのエッジへの通信量は無料（逆はかかる）
* データ転送アウト（GBあたり）とリクエスト（10000件あたり）とオリジンへのデータ転送アウト（GBあたり）でそれぞれ料金発生
* キャッシュの無効化リクエスト（最初の1000ファイル/月は無料、それ以降はかかる）

## Lambda@Edgeについて

### 概要
* CloudFrontのエッジで展開（ディストリビューション）されて動作するAWS Lambda（Node.js、Python）
* 4つのCloudFront周辺のイベントでLambdaをトリガーできる[^1]
[^1]: https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/lambda-cloudfront-trigger-events.html
* CloudWatchのメトリクスもある

##  まとめ

* CloudFront は世界中のエッジにオリジンのキャッシュが展開されることでユーザーへのレスポンスを改善し、オリジンの負荷を削減
* CloudFront は AWS WAF との組み合わせや、組み込みの DDoS 対策により、高いセキュリティを実現
*  ログ & レポート機能でアクセス傾向分析も可能
* 大容量の画像・動画配信や大量アクセスがあるサイトでの活用が有用
* 小規模でも WAF/DDoS 等のセキュリティ対策が必要なサイトで有用
メールがブラックリストで弾かれた際の調査と対応

##１．はじめに
運営しているサイトからのメールが届かないという事象の調査と対応を記載する。
###環境構成(AWS)

* Route53(DNSサーバー)
* CloudFront→ELB→EC2(メールサーバー兼WEBサーバー)

##２．どう調査したか
###①ログの調査
まずメールの送信ログを調査。ブラックリストで弾かれているという内容が記載されていた。
###②ブラックリストの確認
以下のブラックリストを確認すると、SPAMHAUSのブラックリストにメールサーバーのIPが載っていた。
・[SPAMHAUS](https://www.spamhaus.org/lookup/)
![spamhaus.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1286237/d9f698bc-f852-79ba-47ca-34118a377fb3.png)
・[proofpoint](https://ipcheck.proofpoint.com/)
![proofpoint.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1286237/4866977d-cc31-e5ef-becd-d180777736a5.png)
###③解除申請
一時的な対応としてSPAMHAUSにブラックリスト解除申請を出し、数分後解除されたことを確認。
###④原因調査
ブラックリストに載った原因を調査開始したが、SPFレコードとPostfixの設定に問題はなさそうだった。
　**・Route53のSPFレコード：以下で設定されていたため、問題なし**
`v=spf1  +ip4:XXX.XXX.XXX.XXX/32 +ip4:YYY.YYY.YYY.YYY/32 +ip4:ZZZ.ZZZ.ZZZ.ZZZ/32  ~all`
　**・メールサーバのPostfix設定(/etc/postfix/main.cf)：\$myhostnameと\$mydomainが一致しているため問題なし**
###⑤追加調査
さらに調査を進めると、以下の3つで整合性がとれていないとブラックリストに載る可能性がある模様。
　**１．メールサーバーのIPから検索したドメイン(nslookup の逆引き)**
　**２．↑でヒットしたドメインから検索したメールサーバーのIP(nslookup の正引き)**
　**３．メールの送信元アドレスに設定されているドメイン**
　　　※1のドメインは、3のドメインもしくはサブドメインである必要がある
###⑥IPでドメインを検索(逆引き)
メールサーバーのIPでドメインを検索(逆引き)すると、EC2自体のデフォルトドメインが返ってきた。
###⑦ドメインでIPを検索(正引き)
上述した⑥のドメインでIPを検索(正引き)すると、メールサーバーのIPが返ってきた。
###⑧メールの送信元アドレスを確認
メールの送信元アドレスに設定されているドメインと逆引きの結果が異なっており、不整合が発生していた。
##３．どう対応したか
送信元メールアドレスのドメインはサイトのドメインとなっており、正引きの結果はCloudFrontのIPが返ってくる。そのため新しくサブドメインを作りメールサーバーのIPを割り当てて、逆引きでこのサブドメインを返す。
これにより、正引き/逆引きで送信元メールアドレスのドメインのサブドメインに解決されるようになり、上述した⑤の条件を満たすようにする。
正引きはRoute53のみで対応できるが、逆引きはAWSに申請する必要がある。

###①正引きを設定
正引きをRoute53で設定。
###②逆引きの申請
逆引きのためAWSに[メール制限解除申請フォーム](https://console.aws.amazon.com/support/contacts?#/rdns-limits)から申請。
![メール制限解除.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1286237/a21b3e4d-ca06-4bcc-e6a2-b0c28c9d6e98.png)
###③設定完了
翌日AWSが設定完了のメールが来たため、nslookupで正引きと逆引きを確認。
![nslookup.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1286237/70c3f6e2-9517-b224-20b3-60a3db197c43.png)
数日経過観察したが、再度SPAMHAUSに乗ることはなかった。
##４．まとめ
・ブラックリストに載る理由は、Postfixの設定やTXTレコードだけではない。
・メールドメインの正引き/逆引きを設定しないといけない。
・メールサーバーを追加/入替するときには、上記の事を忘れてはいけない。
UXデザインの実践: Yelpのテストとリデザイン

[(原文) UX Design in Action: Testing & Redesigning Yelp (free e-book)](https://www.uxpin.com/studio/blog/ux-design-action-redesigning-yelp-upcoming-free-e-book/?utm_source=Blog&utm_medium=Qiita&utm_campaign=Japan&utm_content=UX%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%81%AE%E5%AE%9F%E8%B7%B5%3A%20Yelp%E3%81%AE%E3%83%86%E3%82%B9%E3%83%88%E3%81%A8%E3%83%AA%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3)

UXデザインのプロセスについては、理論と実践が全く異なるものであることは誰もが知っています。そこで私たちは、[UserTesting社](https://www.usertesting.com/)と[Optimal Workshop社](http://www.optimalworkshop.com/)の協力を得て、デザインプロセスを実際に体験してもらうことにしました。彼らがオリジナルのユーザーリサーチを終えた後、私たちはYelpのリデザインを担当しました。私たちの目的は、ユーザーリサーチがより良いデザイン決定につながることを示すことです。

全体のプロセスと新しいYelpサイトのスクリーンショットは、[無料電子書籍](https://www.uxpin.com/studio/ebooks/ux-design-in-action-yelp-website/?utm_source=Blog&utm_medium=Qiita&utm_campaign=Japan&utm_content=UX%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%81%AE%E5%AE%9F%E8%B7%B5%3A%20Yelp%E3%81%AE%E3%83%86%E3%82%B9%E3%83%88%E3%81%A8%E3%83%AA%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3)にすべて収録されますが、以下に全体のプロセスを垣間見ることができます。


### 1. Yelpの定義
最初のステップは、Yelpのビジネスモデルを分析することでした。どのような人たちが利用しているのか？どのように成功しているのか？どこを改善すればいいのか？私たちのデザインは、ビジネスのインサイトに基づいていることを確認する必要がありました。

### 2. ユーザーテストの実施
全体的な目的を把握した上で、ユーザーグループに適したテスト方法を決定しました。ユーザーテストとオプティマムワークショップは、ユーザーテスト、ツリーテスト、カードソート、クリックテストなどの一次調査を行い、ユーザーが現在のWebサイトをどのように利用し、どのように情報を分類しているかを把握しました。これらのテスト方法によって、どの機能が重要で、どの機能が無視され、どの機能が実際に人々を混乱させているかがわかるのです。

### 3. データの分析
4つのテスト方法のデータを統合し、サイトの変更点を決定しました。Yelpが基本的にビジネス検索エンジンであることを考慮し、私たちの目標は、ユーザーのインサイトを、より関連性の高いコンテンツを提供するためのデザイン変更に結びつけることでした。

### 4. Yelpのデザイン変更
何を変えるべきかがわかったところで、私たちのアイデアをスクリーンに映し出すことにしました。スケッチ、ワイヤーフレーム、そして最終的にはプロトタイプを作成しました。

### 5. 絶え間ないイテレーション
私たちはデザインスプリントという手法を用いて、完璧さよりも改善を目指しました。イテレーションは、UXデザインプロセスのすべてのステップをつなぐのに役立ちました。チームメンバー全員がUXPinを使用して、コメント、コラボレーション、質問を行いました。

これはほんの一例に過ぎません。新しいYelpをいち早くご覧になりたい方は、[こちらから](https://studio.uxpincdn.com/studio/wp-content/uploads/2014/10/blog-600x275.png.webp)ご登録ください。

**本記事は2014/10/10投稿、2020/4/22更新を翻訳したものです。**
M1 Macでpythonのバージョンの設定について

#はじめに
この記事では、M1のMacでpythonのデフォルトバージョンの設定について解説します。
brewからpyenvをインストールし、pyenvでpythonのバージョンを切り替えという方法をよく見ますが、僕の場合pyenvをインストールするときにエラーが発生したので、より簡単な方法でやっていきます。

##pythonバージョン、path確認
まず、もともとMacにインストールされているpythonを確認

```
$ python -V
```

デフォルトではpython 2.7.~ になると思います。

それから自分でインストールしたpython3系を確認

```
$ python3 -V
```
出力に自分がインストールしたpythonのバージョンが出てくると思います。

次に、python3系のpathを出力させ、後ほどそれを使います。

```
$ which python3
```
僕の場合は/usr/bin/python3になってます。

次は自分のTerminalはbashかzshかを確認してください。
確認方法としてはTerminalのウインドの上部で、自分のユーザ名の後にあります。
Big Surではほぼzshになってると思いますが、両方やります。
###bashの場合
Terminalがbashの場合は、

```
$ open ~/.bash_profile
```
と上記のファイルを開きます。

```
# Setting PATH for Python 3.7
# The original version is saved in .bash_profile.pysave
PATH="/Library/Frameworks/Python.framework/Versions/3.7/bin:${PATH}"
export PATH
```
中身は大体上記のようになってます。そして最後の行(下の空白のところ)に

```
$ alias python="先ほど確認した自分のpythonのpath"
```
と書き加えます。僕の場合は

```
$ alias python="/usr/bin/python3"
```
を入力しました。
それから、ファイルを保存し、Terminalで

```
$ source ~/.bash_profile
```
と打ちます。これは先の変更を有効化する意味です。
1回Terminalを開き直して、python -Vで確認してみてください！
###zshの場合
zshの場合ほとんどだと思います。先ほどを大体同じやり方で、

```
$ open ~/.zshrc
```
と入力します。ファイルを開いたら

```
$ alias python="自分のpython3のpath"
```
と下に追加します。

もしかしてopenのところでファイルが存在しないというエラーが吐くかもしれないので、その場合は、

```
$ echo 'alias python="自分のpython3のpath"' >> ~/.zshrc
```
と入力し、またopenで.zshrcファイルを開いて、alias python="自分のpython3のpath"というコードは入っているかを確認してください。

最後terminalを再起動し、python -V でバージョンがpython3の方になっているかを確認してください！

今回は以上です。
sketchupでruby その3

# 概要

sketchupでrubyやってみた。
sin波やってみた。
add_line使ってみた。

# サンプルコード

```
def sin_ha
   model = Sketchup.active_model
   entities = model.active_entities
   px = -30
   py = 0
   -30.step(30, 0.01){ |i|
      x = i
      y = Math::sin(i) * 20
      line1 = entities.add_line [px, 0, py], [x, 0, y]
      px = x
      py = y
   }
end

```

# 実行結果

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/359bcd3d-7be1-dac3-77ec-8616ffd0367a.png)


以上。
sketchupでruby その2

# 概要

sketchupでrubyやってみた。
zundokoやってみた。

# サンプルコード

```
def zundoko
   words = []
   def zd
      word = (rand(2) == 0) ? "zun" : "doko"
      puts word
      return word
   end
   while true
      words.push zd
      ans = words[-5, 5]
      if ans == ["zun", "zun", "zun", "zun", "doko"]
         puts "kiyosi！"
         break
      end
   end
end

```

# 実行結果

```
zundoko
zun
doko
doko
doko
doko
doko
zun
zun
zun
doko
zun
doko
doko
doko
doko
doko
doko
doko
doko
zun
zun
doko
zun
doko
zun
zun
doko
zun
doko
zun
zun
zun
doko
zun
zun
zun
zun
zun
doko
kiyosi！
nil

```

以上。
sketchupでruby

# 概要

sketchupでrubyやってみた。
fizzbuzzやってみた。

# 環境

windows vista 32bit
sketchup 8.0

# rubyのバージョン確認

```
print RUBY_VERSION                                                                                                                  
1.8.6
```

# サンプルコード

```

def fizzbuzz
   for i in 1..99
      if i % 15 == 0
         puts "FizzBuzz"
      elsif i % 3 == 0
         puts "Fizz"
      elsif i % 5 == 0 
         puts "Buzz"
      else
         puts i
      end
   end
end



```

# 実行結果


```
fizzbuzz
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
16
17
Fizz
19
Buzz
Fizz
22
23
Fizz
Buzz
26
Fizz
28
29
FizzBuzz
31
32
Fizz
34
Buzz
Fizz
37
38
Fizz
Buzz
41
Fizz
43
44
FizzBuzz
46
47
Fizz
49
Buzz
Fizz
52
53
Fizz
Buzz
56
Fizz
58
59
FizzBuzz
61
62
Fizz
64
Buzz
Fizz
67
68
Fizz
Buzz
71
Fizz
73
74
FizzBuzz
76
77
Fizz
79
Buzz
Fizz
82
83
Fizz
Buzz
86
Fizz
88
89
FizzBuzz
91
92
Fizz
94
Buzz
Fizz
97
98
Fizz
1..99
```

以上。