OmniAICreator/Qiita-1.07M huggingface dataset:
WSL2とdocker のインストールに挑戦

先日、wsl2のインストールを断念したけど、今(2020年9月12日)はできる様になっていたのでそのメモです

## 結論

気がつけば、version 1903でも、WSL2がサポートされるようになっていて、'Virtual Machine Platform'を有効にして、WSLのデフォルトのバージョンを2にすれば良かった。

参考
https://docs.microsoft.com/en-us/windows/wsl/install-win10#update-to-wsl-2

### 1. Virtual Machine Platform を有効にする(管理者権限で起動)

```PowerShell
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42407/20dd25a3-d208-bceb-acbb-3ae6ad813091.png)

### 2. WSL2 をデフォルトバージョンにする

```PowerShell
wsl --set-default-version 2
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42407/e877a81c-c5c0-deb2-2e69-340a150f6c4d.png)

### 3. バージョン 1903から1909にアップデートする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42407/51a7c959-f9a9-a93b-1bf3-5035546ebd54.png)

Win+R → コマンド winver で以下が表示されます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42407/3ba6a044-c3b9-2699-2206-38f493851ea6.png)

### 4. Ubuntu ディストリビューションをwsl2に設定する

既に wsl でubuntuとか実行している様であれば、そのバージョンをwsl2にする必要があります
以下をpowershell上で実行しました


```powershell
wsl --set-version Ubuntu 2
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42407/3b08c312-060f-e6bf-afd8-d30b36e69f3d.png)

コマンド wsl -l -v でバージョンを確認します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42407/75fea2a7-f04b-ba6e-cb8e-df7d02e6edd8.png)


### 4. そして、dockerを入れる

https://docs.docker.jp/docker-for-windows/wsl.html

#### WSL 2 Linux カーネルの更新

1. こちらをダウンロード：https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi
2. インストーラーを実行
3. なんかカワイイのがはじまりました！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42407/d87776a2-ccfd-694b-73ee-fe9cd3a63cc3.png)

4. docker descktopの2.3.0.2 以上のダウンローが必要と言うことで、バージョンを改めて確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42407/0d1e1a0a-579b-3b1c-c33f-d42a97d3bd60.png)

でも、WSL2の設定はインストール時に決まっていたためか変更出来なかったので、ここはdocker desktopを入れ直すことにしました。。

アンインストールして再インストールしただけだと、hyper-v版が上がってしまったので。。

どうやら、windows 10 version 2004が必要っぽいので、こちらからセットアップ
https://www.microsoft.com/ja-jp/software-download/windows10
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42407/7aaa4b7b-e9dc-f796-3a81-124967f80104.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42407/73697ace-4cc0-c701-a7ed-ae9290fe4054.png)

version 2004にしたら、wsl2が使えるものがインストールできる様になりました。
アンインストールする必要なかったかも。。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42407/69bb9ad0-50a4-dcd8-a0a9-ee0a021674c2.png)
CGRectをすっきり記述できるExtension

##とても便利

Swift 5.2.4
Xcode 11.6

```swift:Extension.swift

import UIKit

extension UIView {
    public var width : CGFloat {
        return self.frame.size.width
    }
    
    public var height : CGFloat {
        return self.frame.size.height
    }
    
    public var top : CGFloat {
        return self.frame.origin.y
    }
    
    public var bottom : CGFloat {
        return self.frame.size.height + self.frame.origin.y
    }
    
    public var left : CGFloat {
        return self.frame.origin.x
    }
    
    public var right : CGFloat {
        return self.frame.size.width + self.frame.origin.x
    }
}

```

これだと

 view.frame.size.width　→　view.widthになり

例えばview1の右となりに別のパーツを配置したいときのCGRectのxは

view1.right

view1の下のCGRectのyが欲しいときは

view1.bottom

でいけちゃう。

##参考

[Youtube](https://www.youtube.com/watch?v=g7ipElQVpgU)
Mavericks用、iterm2 (3.0.15)の初期化

### 動作環境

MacOS10.9
iterm2 Build 3.0.15

### 過去に行ったこと

一ヶ月程前、homebrew削除してiterm2が起動しなかった。zsh起動エラー（確かdylibエラーだった）。
zshはhomebrewで一度もインストールしていない。全てソースビルドしている。
zsh起動エラー発生時もzshをソースインストールし解決した。
iterm(zsh)が立ち上がらなくなった時の対処法 - Qiita
https://qiita.com/_am_/items/0ac68d4cbd2081ba4220

この時にzsh起動エラーダイアログを出ない設定にしてしまった。

### 今回、行ったこと

iterm2 の初期化をした。
理由はカラースキームを消したい。それとzsh起動エラーダイアログが出て欲しい為。

iTerm2 の Color scheme インポートしたプリセットを一括削除する - Qiita
https://qiita.com/hatta/items/ee836e9fb5948fb04c42

上記のとおり実行したが、どこかのディレクトリから.plistか復活されて元に戻ってしまう。

iTerm2 を初期化する方法 - Qiita
https://qiita.com/kentarosasaki/items/acf5bc53d559fcd892b5

~/Library/Preferences/
以下で
defaults delete com.googlecode.iterm2
として初期化出来た。

$ ls -ln com.googlecode.iterm2.plist
-rw-------  1 xxx  xx    12K  9 12 13:16 com.googlecode.iterm2.plist
12k

end
SQLで特定の条件を満たすレコードを1件でも持つグループのレコードをすべて抽出する

# はじめに
[こちらの記事](https://qiita.com/takahasinaoki/items/01fe792c9e83bb15c7c5)で紹介した、テーブルの抽出条件に、分析関数（ウインドウ関数）を使用する方法の応用になります。

分析関数はDBMSによっては使えない場合があるのでご注意ください。
こちらの記事は、
MySQL 8.0.20 にて動作を確認しています。

# 汎用的なひな型
特定の条件を満たすレコードを1件でも持つグループのレコードをすべて抽出するSQLのひな型

```SQL
SELECT *
  FROM 
    (SELECT *
          , MAX(CASE WHEN [条件] THEN 1 END)
              OVER (PARTITION BY [グループ化項目]) AS 抽出対象
       FROM 成績テーブル
    ) AS Z
 WHERE 抽出対象 = 1
```
SELECT * の部分は便宜必要なカラムに変更して実行してください

**条件**
[条件]のところに抽出したい条件を記述

**グループ化項目**
[グループ化項目]のところにグループ化したいカラムを記述（複数カラムの指定可）


# 例題
成績テーブルのうち、0点または100点を1科目でも取った生徒のすべての教科の点数を一覧で取得する

**成績テーブル**

| 氏名 | 教科 | 点数 |
| ---- | ---- | ---- |
| 佐藤 | 国語 | 0    |
| 佐藤 | 数学 | 31   |
| 佐藤 | 英語 | 19   |
| 鈴木 | 国語 | 59   |
| 鈴木 | 数学 | 38   |
| 鈴木 | 英語 | 25   |
| 高橋 | 国語 | 92   |
| 高橋 | 数学 | 100  |
| 高橋 | 英語 | 39   |
| 田中 | 国語 | 40   |
| 田中 | 数学 | 52   |
| 田中 | 英語 | 30   |


**抽出結果**
佐藤さんと高橋さんのデータをすべて抽出する

| 氏名 | 教科 | 点数 |
| ---- | ---- | ---- |
| 佐藤 | 国語 | 0    |
| 佐藤 | 数学 | 31   |
| 佐藤 | 英語 | 19   |
| 高橋 | 国語 | 92   |
| 高橋 | 数学 | 100  |
| 高橋 | 英語 | 39   |


## テストデータ作成
```SQL
CREATE TABLE 成績テーブル(氏名 VARCHAR(10), 教科 VARCHAR(2), 点数 INT);  
INSERT INTO 成績テーブル VALUES('佐藤', '国語', 0);
INSERT INTO 成績テーブル VALUES('佐藤', '数学', 31);
INSERT INTO 成績テーブル VALUES('佐藤', '英語', 19);
INSERT INTO 成績テーブル VALUES('鈴木', '国語', 59);
INSERT INTO 成績テーブル VALUES('鈴木', '数学', 38);
INSERT INTO 成績テーブル VALUES('鈴木', '英語', 25);
INSERT INTO 成績テーブル VALUES('高橋', '国語', 92);
INSERT INTO 成績テーブル VALUES('高橋', '数学', 100);
INSERT INTO 成績テーブル VALUES('高橋', '英語', 39);
INSERT INTO 成績テーブル VALUES('田中', '国語', 40);
INSERT INTO 成績テーブル VALUES('田中', '数学', 52);
INSERT INTO 成績テーブル VALUES('田中', '英語', 30);
```


## 対象データの抽出

```SQL
SELECT 氏名, 教科, 点数
  FROM 
    (SELECT *
          , MAX(CASE WHEN 点数=0 OR 点数=100 THEN 1 END)
              OVER (PARTITION BY 氏名) AS 抽出対象
       FROM 成績テーブル
    ) AS Z
 WHERE 抽出対象 = 1
```

**サブクエリ部分の実行結果**

| 氏名 | 教科 | 点数 | 抽出対象 |
| ---- | ---- | ---- | -------- |
| 佐藤 | 国語 | 0    | 1        |
| 佐藤 | 数学 | 31   | 1        |
| 佐藤 | 英語 | 19   | 1        |
| 田中 | 国語 | 40   | « NULL » |
| 田中 | 数学 | 52   | « NULL » |
| 田中 | 英語 | 30   | « NULL » |
| 鈴木 | 国語 | 59   | « NULL » |
| 鈴木 | 数学 | 38   | « NULL » |
| 鈴木 | 英語 | 25   | « NULL » |
| 高橋 | 国語 | 92   | 1        |
| 高橋 | 数学 | 100  | 1        |
| 高橋 | 英語 | 39   | 1        |

**全体の実行結果**

| 氏名 | 教科 | 点数 |
| ---- | ---- | ---- |
| 佐藤 | 国語 | 0    |
| 佐藤 | 数学 | 31   |
| 佐藤 | 英語 | 19   |
| 高橋 | 国語 | 92   |
| 高橋 | 数学 | 100  |
| 高橋 | 英語 | 39   |

## こちらでお試しできます
https://paiza.io/projects/oywmScLN8srvMFsPn3SQEg
[django] modelのmodifiedが更新される場合と更新されない場合について

# はじめに
modelのmodifiedが更新される場合と更新されない場合があるって知ってました？
自分は知りませんでした
ということで調べました

# modifiedが更新される場合

```python
user = User.objects.get(pk=1)
user.name = 'hoge'
user.save()
```

まあ、よくあるやつです

# modifiedが更新されない場合

```python
User.objects.filter(prefecture_id=1).update(prefecture_name='北海道')
```

`update`メソッドを使うと更新されません！

### modifiedが更新するには

```python
User.objects.filter(prefecture_id=1).update(prefecture_name='北海道', modified=datetime.datetime.now())
```

このように明示的に指定する必要があります


```python
users = []
for user in User.objects.filter(prefecture_id=1):
    user.prefecture_name ='北海道'
    user.modified = datetime.datetime.now()
    users.append(user)
User.objects.bulk_update(users, fields=['prefecture_name', 'modified'])
```

bulk_updateも同様に更新されないので、明示的に指定する必要があります
間違えて違うブランチで作業を始めてしまったときの対処法【Git】

# 1. 状況
例えば新しい機能を実装しようとコードを書いていて、
`「ん..？これってmasterブランチじゃね..？！」`と気づいたとき。

そしてまだcommitはしてないけど、既に結構ファイルをいじってしまっている。。

..そんな状況における対処法をさくっと解説します。

結論として、全然大丈夫です！
(実際に自分がmasterで作業していて焦ったので、情報共有します..)

# 2. やること
簡単に流れを説明すると、
　①今の作業ブランチを確認する
　②変更してしまった作業分を退避させる
　③本来作業したかったブランチにその変更を反映させる
です。

# 3. 実際にやってみる
## ①今の作業ブランチを確認
`$git branch`で今の作業ブランチを確認します。

```
$git branch
  feature/#7_add_modal_for_posting
  feature/#9_add_user_name_to_posts
* master
```
今回の例の場合は、本当は`feature/#9..`というブランチで作業したかったのに、masterで作業している状態になっています。(やば..)

## ②変更してしまった作業分を退避させる
まずはmasterブランチなどで書き始めてしまったコードを退避させましょう。
イメージ的には仮置き場に移動させる、といった感じです。
これには`$git stash`というコマンドを使います。

```
$git stash
Saved working directory and index state WIP on master: ○○
```
これで間違えて書き始めてしまったmasterブランチでの作業を退避することができました。

念のため`$git status`で状態を確認してみましょう。

```
$git status
On branch master
Your branch is up to date with 'origin/master'.
nothing to commit, working tree clean
```
masterブランチが綺麗な状態になっていることが確認できます。
ちなみに`stash`は「隠して蓄える」という意味です。

## ③本来作業したかったブランチに変更を反映させる
stashで退避させたら、`$git checkout ブランチ名`で本来作業したかったブランチに切り替えます。

```
$git checkout feature/#9_add_user_name_to_posts
```
<br>
そして先ほどstashに退避させた変更分を、切り替えたブランチに反映させます。

```
$git stash apply
```
<br>
これで作業は完了です。
あとは続きからのコードを気持ちよく書いていけばOKです！
<br>
## ④おまけ
`$git stash list`で現在のstashの状態を確認できます。

```
$git stash list
stash@{0}: WIP on master: ○○
stash@{1}: WIP on master: ××
stash@{2}: WIP on master: △△
```

このように複数のstashがあり、特定のstashをブランチに反映させたい場合は、

```
$git stash apply stash@{1}
```
のようにstashを指定してapplyすればOKです。
逆に先程のようにオプションに何も指定しなければ、最後に退避させたstashがブランチに反映されます。

その他、Gitで困ったことがあったらこちらの記事が非常に参考になります。
<a href="https://qiita.com/shimotaroo/items/b73d896ace10894fd290" alt="Gitでやりたいこと、ここで見つかる">「Gitでやりたいこと、ここで見つかる」</a>
LGTM1000超えの神バイブル。
Gitで困ったことはだいたいこれで解決します。

今回のgit stashの他にも便利なことはたくさんあるので、少しずつ覚えていきたいですね。
MindでFizzBuzz

## まえがき

およそ四半世紀ぶりに書く[Mind](https://www.scripts-lab.co.jp/mind/whatsmind.html)。手始めに定番の[FizzBuzz](https://ja.wikipedia.org/wiki/Fizz_Buzz)でも。

## ソース

```console:FizzBuzz.src
メインとは
　　余り３は　変数
　　余り５は　変数

　　100を　回数指定して
　　　　回数を　３で　割った余りを　余り３に　入れる
　　　　回数を　５で　割った余りを　余り５に　入れる

　　　　もし 余り３が　０に　等しい　かつ　余り５が　０に　等しい　ならば
　　　　　　「Fizz Buzz」を　表示する
　　　　さもなければ
　　　　　　もし　余り３が　０に　等しい　ならば
　　　　　　　　「Fizz」を　表示する
　　　　　　さもなければ
　　　　　　　　もし　余り５が　０に　等しい　ならば
　　　　　　　　　　「Buzz」を　表示する
　　　　　　　　さもなければ
　　　　　　　　　　回数を　数値表示する
　　　　　　　　つぎに
　　　　　　つぎに
　　　　つぎに

　　　　「, 」を　表示する
　　繰り返す。
```

特に何も工夫とかありませんがMindってelseif無かったんや・・・に気付くまで[^1]時間かかった上に短いコードで書くのは放棄してます。

当時はWTERMでマクロ巡回してMindで作ったログカッター通して[Vz](https://ja.wikipedia.org/wiki/VZ_Editor)でゆっくり見る/レス書くなんてやってましたが、今現在Mindは何に使えるかなと思案にふける今日この頃。

[^1]: 思い出すまで
Flutter styleの'title'はdeprecatedになり'headline6'になった模様。

#ある日、titleがdeprecatedになっていた。。
Flutterのstyleで使う`title`が~~`title`~~になっていました。。

![スクリーンショット 2020-09-08 21.54.41.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/4518b63d-b1c0-c3dd-c99f-dd0a481546c4.jpeg)


```dart
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    initializeDateFormatting('ja');
    return MaterialApp(
      title: 'Persona Expenses',
      theme: ThemeData(
          primarySwatch: Colors.red,
          accentColor: Colors.amber,
          fontFamily: 'Quicksand',
          textTheme: ThemeData.light().textTheme.copyWith(
              title: TextStyle(
                  fontFamily: 'OpenSans',
                  fontSize: 18,
                  fontWeight: FontWeight.bold)),
      home: MyHomePage(),
    );
  }
}
```

#`headline6`を使いましょう
![スクリーンショット 2020-09-08 21.55.30.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/068ac101-c611-515c-ba72-dc69e17b9452.jpeg)

```dart
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    initializeDateFormatting('ja');
    return MaterialApp(
      title: 'Persona Expenses',
      theme: ThemeData(
          primarySwatch: Colors.red,
          accentColor: Colors.amber,
          fontFamily: 'Quicksand',
          textTheme: ThemeData.light().textTheme.copyWith(
             // 変更！
              headline6: TextStyle(
                  fontFamily: 'OpenSans',
                  fontSize: 18,
                  fontWeight: FontWeight.bold)),
      home: MyHomePage(),
    );
  }
}
```




#参考

https://stackoverflow.com/questions/61312511/themedata-deprecated-title-argument
【Sapper】マークダウンBlogテンプレートを使ってNetlifyデプロイ

>*動作環境*

```
% node -v
v12.18.3
% npm -v
6.14.6
```
* GitHubアカウント　*[github.com](https://github.com/github)*
* Netlifyアカウント *[netlify.com](https://www.netlify.com/)*

## 1.テンプレート
GitHubで見つけた*『sapper-blog-template』*を使用させてもらいました。
>[DEMO](https://sapper-blog-template.netlify.app/) | [GitHub](https://github.com/Charca/sapper-blog-template)

![sapperqiita00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692347/3662f0dc-a3f0-531a-5e8c-0ef274ace023.png)

ヘッダーのメニューからHome、About、Blogに遷移、Blog記事はマークダウンで作成する比較的シンプルなマークダウンブログのサイトです。Gatsbyと比べてSapper(svelte.js)は100%理解していなくても直感的にカスタムできる印象です。



## 2.GetStart
README通りターミナルでコマンドを実行。

```
npx degit Charca/sapper-blog-template my-blog
cd my-blog
npm install # or yarn!
npm run dev
```

もしくはUse this templateからリポジトリを作ってcloneする。
![sapperqiita01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692347/9960fc91-332d-8287-7a28-7b06961aaa53.jpeg)
clone出来たらREADMEと同じく、

```
npm i
npm run dev
```
これで<localhost:3000>で確認出来ます。

## 3.Netlify設定
基本的なNetlifyの使い方は割愛しますが、
毎回*『Deploy settings』*の設定がわからなくなるのでメモ。

Build settingとPublish directoryの項目を入力。
✳︎　```__sapper__/export```("sapper"前後それぞれアンダーバーを2つ）
![sapperqiita02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692347/ac83142b-5213-01ab-a052-3676867dea2c.jpeg)

## 4.LightHouseで確認
![sapperqiita03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692347/63c1821d-8750-2576-eb12-2288c067fe6f.png)

>[今回作ったDemoサイト](https://hashclip.dev/)
[DRF]PrimaryKeyRelatedFieldを高速化するスニペット

# はじめに
シリアライザで`PrimaryKeyRelatedField`を`many=True`にすると、pkの配列をリクエストパラメータで渡せますが、pkが大量にあるとめちゃくちゃ遅くなります
そのため原因の調査と高速化方法を考えました

# 原因

結論これです

```python:ManyRelatedField.py
def to_internal_value(self, data):
    if isinstance(data, str) or not hasattr(data, '__iter__'):
        self.fail('not_a_list', input_type=type(data).__name__)
    if not self.allow_empty and len(data) == 0:
        self.fail('empty')

    return [
        self.child_relation.to_internal_value(item)
        for item in data
    ]
```

配列分`self.child_relation.to_internal_value(item)`が呼ばれてるため（`to_internal_value`の中でpkをgetしている）遅くなっていました

# 高速化するスニペット

```python
from rest_framework import serializers
from rest_framework.relations import MANY_RELATION_KWARGS, ManyRelatedField


class PrimaryKeyRelatedFieldEx(serializers.PrimaryKeyRelatedField):
    def __init__(self, **kwargs):
        self.queryset_response = kwargs.pop('queryset_response', False)
        super().__init__(**kwargs)

    class _ManyRelatedFieldEx(ManyRelatedField):
        def to_internal_value(self, data):
            if isinstance(data, str) or not hasattr(data, '__iter__'):
                self.fail('not_a_list', input_type=type(data).__name__)
            if not self.allow_empty and len(data) == 0:
                self.fail('empty')
            return self.child_relation.to_internal_value(data)

    @classmethod
    def many_init(cls, *args, **kwargs):
        list_kwargs = {'child_relation': cls(*args, **kwargs)}
        for key in kwargs:
            if key in MANY_RELATION_KWARGS:
                list_kwargs[key] = kwargs[key]
        return cls._ManyRelatedFieldEx(**list_kwargs)

    def to_internal_value(self, data):
        if isinstance(data, list):
            if self.pk_field is not None:
                data = self.pk_field.to_internal_value(data)
            results = self.get_queryset().filter(pk__in=data)
            # 全てのデータがあるかチェックする
            pk_list = results.values_list('pk', flat=True)
            pk_list = [str(n) for n in pk_list]
            data_list = [str(n) for n in data]
            diff = list(set(data_list) - set(list(pk_list)))
            if len(diff) > 0:
                pk_value = ', '.join(map(str, diff))
                self.fail('does_not_exist', pk_value=pk_value)
            if self.queryset_response:
                return results
            else:
                return list(results)
        else:
            return super().to_internal_value(data)
```

### 解説
* 一つずつgetしていたのをfilterのinで取得するように変更
* 存在しないpkが含まれていた場合のエラーメッセージは一つしか表示されなかったのを、カンマ区切りで全て表示するように変更
* `queryset_response`のパラメータを追加しています。`queryset_response=True`にするとレスポンスがquerysetになります（今まではquerysetの配列。個人的にはquerysetになってた方が使いやすいんじゃないかなと思う）
超絶簡単手作りSwiftチェックボックスの作り方

# チェックボックスを作る

現在業務で会社のAndroidアプリをiOSのアプリに作り替えることをしています。色々やり方はあるかと思いますが、下準備なしで、Swiftのデフォルトの機能だけでチェックボックス的なやつを超絶簡単に作ったのでご紹介します。

![スクリーンショット 2020-09-12 11.48.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586072/513ca137-4469-2d42-1a3f-3d7272ae1c2b.png)

Swift 5.2.4
Xcode 11.6

## 使うのはこれだけ
・Booleanをいれる変数
・UIButton
・SF Symbolsから"checkmark"くん

### まずは変数を宣言します

```swift:ViewController.swift
private var isChecked = false
```
デフォルトではチェックされてない状態なのでfalseを代入。

### 次にUIButton

先ほどの変数の下に以下を記述。

```swift:ViewController.swift
    private let checkBox: UIButton = {
        let button = UIButton(frame: CGRect(x: 0,
                                            y: 0,
                                            width: 50,
                                            height: 50))
        button.layer.borderWidth = 2
        button.layer.borderColor = UIColor.gray.cgColor
        return button
    }() //縦横50、灰色の太さ2の枠があるボタン
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(checkBox)
        //ボタンをviewに追加
    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        checkBox.center = view.center
        //ボタンの中心をviewの中心に合わせる
    }

```

### ボタンを押すたびにcheckedの値を変える

ということで以下をreturn buttonの上あたりに追記

```swift:ViewController.swift
button.addTarget(self,
                 action: #selector(didTapCheckBox),
                 for: .touchUpInside)
```
そしてviewDidLayoutSubviewsの下あたりにこれを追記

```swift:ViewController.swift
@objc private func didTapCheckBox(){
     print("tap")
}
```
これで灰色の四角をタップするたびにdidTapRadioButton関数の中身が実行されるようになります。

### 何をどうしたいのか

・ボタンをタップするたびに変数checkedの値をtrueだったらfalse, falseだったらtrueに変えたい
・trueの状態であれば四角にチェックマークが欲しい、falseだったら空っぽにしたい

これらをすっきり記述できるのがSwitch文です！それでは以下をdidTapRadioButton関数の中に記述します。

```swift:ViewController.swift
checkBox.setImage(isChecked ? UIImage(systemName: "checkmark") : nil, for: .normal)
checked.toggle()
```
これで完成！全体像。

```swift:ViewController.swift
import UIKit

final class ViewController: UIViewController {
    private var isChecked = false
    
    private let checkBox: UIButton = {
        let button = UIButton(frame: CGRect(x: 0,
                                            y: 0,
                                            width: 50,
                                            height: 50))
        button.layer.borderWidth = 2
        button.layer.borderColor = UIColor.gray.cgColor
        button.addTarget(self, action: #selector(didTapRadioButton), for: .touchUpInside)
        return button
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(checkBox)
    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        checkBox.center = view.center
    }
    
    @objc private func didTapCheckBox() {
       radioButton.setImage(isChecked ? UIImage(systemName: "checkmark") : nil, for: .normal)
       isChecked.toggle()
    }
}
```


## さいごに
他にも背景色を変えたりアニメーションで遅延を起こしたりして色々アレンジできるので、もしよかったら試してみてください😄
コンピュータ概論-その１　基数変換編

<dl>
  <dt>コンピュータ概論-その１　基数変換編</dt>
　<dt>はじめに</dt>
この記事は、これからコンピュータ概論について勉強しようかと考えられている方向けに作成しました。
</dl>

<strong>基数て何ぞや？</strong>
数値を表現する際に、各けたの重み付けの基礎として用いる数を「基数」と呼びます。
なんて本とかに書いてありますが、要は桁が上がる数のことですね。
人が使う基数は数字が10で桁が上がるので、10進数と呼んでいます。

※n進数とは、予め定められたn種類の記号を使って数を表す方法です。

<strong>n進数について</strong>
n進数を表にしてみると以下のようになります。（赤字：桁上がりが起きている数字）
![n新数.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682891/e9fbb8bd-3e69-2a87-4e5d-759f377735b9.png)
普段10進数を使っている我々にとって○○進数なんて使い辛いからコンピュータも10進数を使えばいいじゃない・・・

<strong>コンピュータって何で2進数でデータを扱うの？</strong>

コンピュータは「自動計算機」です。
10進数を使うとかけ算（九九）だけでも100種類のパターンを覚えなくてはならず、計算が複雑になり、自動計算させるためのプログラムが複雑になります。
2進数だと、かけ算で4種類のパターンを覚えておけば良くて、ハードウエアも「0と1」を「ON/OFF」で表すことができるため2進数を使います。

[豆知識]
世界初のコンピュータ「ENIAC」は10進数を採用したことにより、真空管を18,000本も使いました。
後に2進数を採用した「EDSAC」は真空管が3,000本で済んだそうです。

<strong>２進数で書くのが面倒くさい</strong>
2進数の表記って、1と0が大量に並んで見づらいですよね。
以下の表を見ると2進数の表記は凄いことになってます・・・
![n進数2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682891/99a6a606-e790-83e1-8898-3f0b1607600c.png)
<strong>何とスッキリ16進数</strong>
2進数を4桁毎に区切ってみると・・・
16進数で簡単に読み取れますね！
2進数を16進数に変換する→これが<strong>基数変換</strong>です。
![n進数3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682891/ecdb3f0c-e44d-0a2e-7888-3a3ea30fee74.png)
<strong>他の進数はどうすれば良いの？パート１</strong>
区切る桁を変えると簡単にできるものは・・・
![n進数4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682891/ed1cccd3-979a-679d-bfb0-f1cf3d8b1e2a.png)
[豆知識]
数値の表現方法はいろいろありますが、103102(4) 、 2322(8)の表記が一般的です。
良く使われる2進数は10b　など末尾に“ｂ”を16進数は0xFFなど“０ｘ”を10進数には何も付けないのが一般的です。

注）上記32進数の16I（いちろくあい）は0,1,2,…ABCDEFGHI と記号で表した時のI = 18(10)です。

<strong>他の進数はどうすれば良いの？パート２</strong>
区切る桁で表現できないものは（できるものも含めて）・・・
10進数に変換して基数で割っていけばOK！

例）1,234を13進数で表現する
![n進数5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682891/670e8c92-be35-4b8f-b1ed-0f814ee64282.png)
商が無くなったら、下から余りを並べて<strong>73C(13)</strong>

<strong>○○進数を10進数にするには？</strong>
先ほどの割った商と余りで10進数からn進数に変換できたけど、n進数から10進数にするには・・・
さっき割ったんだから、掛ければOK
![n進数6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682891/6e946a53-c037-256b-14cf-32fccb9a1a5d.png)
７×１６９＋３×１３＋１２＝１，２３４

<strong>これで基数変換はマスターできたことになります。</strong>（多分）
Sublime Text + Emmet2で動かない？

#Emmet2に自動アップグレードされた方向けの対処法

##方法1　古いバージョンに戻す
https://github.com/emmetio/sublime-text-plugin/issues/82

##方法2　頑張って自身で適応する

issueに投稿する人たちは
まずいいものにしようとしてくれていることに感謝して、
その後質問しているのが
なかなか自分ではできないことだったので見習いつつ、
英語が読めない私のような方に少しでもemmet2に適応のヒントになればです。

###CTRL + Eで変換できない
Preferences -> Package Settings -> Emmet -> Key Bindings

```
[
	{
		"keys": ["ctrl+e"],
		"command": "emmet_expand_abbreviation"
	},
]
```

左のdefaultにてコメントアウトされているものから他の機能も使えたりします。

例えば　数字上でコントロールキー＋↑矢印キーをおすと数字が＋1される

```
[
	{
		"keys": ["ctrl+up"],
		"command": "emmet_increment_number",
		"args": { "delta": 1 }
	},
]
```

__以前に01にすると02になったのが今は1となって0がなくなってしまいます。__

###スニペット

Preferences -> Package Settings -> Emmet -> Settings

先に問題から

####variablesがmarkup及びhtmlしか機能しない

```
{
  "config":{
    "markup":{
      "variables":{
        "lang": "ja",
      },
    }
  }
}
```

cssで読み込まなくなりました。

####phpをマークアップでだしたい
ブラケットでくくるといいそうです。

```
{
  "config":{
    "markup":{
      "snippets":{
        "php" : "{<?php ${0} ?>}" ,
      }
    },
  }
}
```
ちなにみカーソルは\${0}でしか機能せず以前のように|や${cursor｝はエラーになるようでした。


####キーに使えないものができた

以前

```
{
  "config":{
    "stylesheet":{
      "snippets":{
        "mtc-" : "margin-top : calc( ${0}px - px );" ,
      }
    },
  }
}
```

とするとmargin-top : calc( px - px );と変換されたのですが、エラーぽいです。

おそらくキーに"__-__"とか入っていると駄目なのかなと思います。

しかたなく。。

```
{
  "config":{
    "stylesheet":{
      "snippets":{
        "mtc" : "margin-top : calc( ${0}px - px );" ,
      }
    },
  }
}
```

としてもエラー
次はvalue値に特殊文字(この場合：)があると駄目みたいで、、無理やり、、

```
{
  "config":{
    "stylesheet":{
      "snippets":{
        "mtc" : "margin-top ${value::} calc( ${0}px - px );",
      }
    },
  }
}
```

こうしてみたらうまくいきました。（キーには無理でしたが）

 
まだまだ以前と挙動が違うものが多々あるかもしれませんが、
これを期にスニペットを見直す機会になればとおもいます。

見てくれてありがとうございました。
MaxでMIDI鍵を離した時の信号（ノートオフ信号）をカット

#前の記事
[MaxでMIDIキーボードを使ってドレミファ](https://qiita.com/waokitsune/items/bcac5e247350877192b8)

#バージョン
Version 8.1.5（9359645）（64-bit windows）

#ノートオフ信号とは何ぞや
MIDI鍵からは鍵盤を **押した時** と **離した時** の2回信号が来る！
鍵盤から指を離した時にMIDI鍵から届くのがノートオフ信号。

**いつ鍵盤が解放されたのか** の情報が無いと音の長さを表現できないからね。
ノートオフが無ければ「ジャーーーーーーーーン♪」なのか「ジャンッ♪」なのかどっちやねん！って話になっちゃう。

#ノートオフが邪魔！って時もある
こいつは前回作ったやつ。MIDI鍵を弾いてみるとあることに気がつく…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/5eea4c3d-46b7-bd30-b701-05ca30888025.png)
**音がまた鳴っちゃう時がある！**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/3f35a574-4580-85fc-38e8-de189da1610f.png)
面白い音だからこれはこれでありだけど…。

#ノートオフ信号をカットするstripnote
**stripnote** っていうノートオフ信号をカットするオブジェクトを追加！
stripnoteには **Velocity≒鍵盤を押した強さ** が必要、ということで第2引数でVelocityの信号を受け取っています(❁´ω`❁)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/72af4ab0-9258-ad21-db3e-52fc10741b7b.png)

#次の記事
[Maxでエンベロープを使ってポーーをポーンやホワーァンに](https://qiita.com/waokitsune/items/a148c65fee51e5171dc4)
BigQueryでテーブルの差分を確認する

BigQueryで２つのテーブルのカラム差分を確認するやり方についてです。

下記のように２つのテーブルがあったときに、

####テーブルA

| id | name | price |
|:-----------|------------:|:------------:|
| 001       | Orange        | 300         |
| 002     | Apple      | 150       |
| 003       | Banana        | 200         |
| 004       | Grape        | 350         |

####テーブルB

| id | name | price |
|:-----------|------------:|:------------:|
| 001       | Orange        | 300         |
| 002     | Apple      | 200       |
| 003       | Lemon        | 300         |

下記のSQLでカラム突合を行い差分を抽出します。

```sql:テーブルAとテーブルBのカラム突合
( --Aには有り、Bには無いレコード抽出
    SELECT 'A-B' AS kind, * FROM A
    EXCEPT DISTINCT
    SELECT 'A-B' AS kind, * FROM B
)
UNION ALL
( --Bには有り、Aには無いレコード抽出
    SELECT 'B-A' AS kind, * FROM B
    EXCEPT DISTINCT
    SELECT 'B-A' AS kind, * FROM A
)
ORDER BY 2, 3, 4, 1
```
####カラム突合結果

| kind | id | name | price |
|:-----------|------------:|:------------:|:------------:|
| A-B | 002       | Apple        | 150         |
| B-A | 002   | Apple      | 200       |
| A-B | 003       | Banana        | 200         |
| A-B | 004       | Grape        | 350         |
| B-A | 004   | Lemon      | 300       |
Ruby nは2の何乗かしたものか知りたい？（2のべき乗判定）

# そもそもべき乗とは
簡潔に言うとnって2をなんじょうかした数字なの？
どうなの？教えて〜〜
ってこと
いや本当に適当すぎて怒られそう
詳しくはこちら。

https://atarimae.biz/archives/20521

# 判定式はこちら

```Ruby:bekijyo.rb
if (n&(n-1)) == 0 then
    puts "2のべき乗"
else
    puts "2のべき乗でない"
end
```

# 投稿の経緯

そもそも「べき乗」を知らなかったからすごい遠回りした。
無駄にややこしい計算式くんだけど、途中から
「これ一発で解決する判定式あるだろ」
ってなってもうそっからはぐぐり祭り。

と言うわけで、言葉を知らないとぐぐりづらい内容なので、
たどり着けるかどうかになっちゃうけど、誰かのお役に立てれば。

以上。
あざした。
Vim: NERDTree plugin

 ```vim:.vimrc
"dein.vim設定 -> プラグイン追加
+ call dein#add('preservim/nerdtree')
"nerdtreeのキーバインド
+ nnoremap <silent><C-e> :NERDTreeToggle<CR>
"隠しファイルの表示
+ let NERDTreeShowHidden=1
```

```vim:基本的な使い方
 "上のキーバインドが前提です。
 "ツリー表示 -> ツリー隠す(トグル)
c-w
 "ツリーと編集画面の移動
c-w w

ツリーのファイル上で -> o(enter) -> ファイルオープン
"-> 新しいタブは開かない -> 編集中ならスプリット表示される

ツリーのファイル上で -> t -> 新しいタブでファイルオープン
```

詳細な使い方はこちら！
[vim-plugin NERDTree で開発効率をアップする！](https://qiita.com/zwirky/items/0209579a635b4f9c95ee)

LGTMお願いします！
モチベーションが上がります！
PythonでDICOM画像を扱う

#きっかけ
[Kaggleコンペ](https://www.kaggle.com/c/osic-pulmonary-fibrosis-progression)で胸部のCTスキャン画像、DICOM画像が出てきてどのように扱えばいいか分からなかったから。

#何ができるようになるか
・DICOM画像とは何か
・DICOM画像の表示、データの扱い方

#DICOM画像とは何か？
>DICOM（ダイコム）とは、CTやMRI、CRなどで撮影した医用画像のフォーマットと、それらを扱う医用画像機器間の通信プロトコルを定義した標準規格である。
[wiki](https://ja.wikipedia.org/wiki/DICOM#:~:text=DICOM%EF%BC%88%E3%83%80%E3%82%A4%E3%82%B3%E3%83%A0%EF%BC%89%E3%81%A8%E3%81%AF%E3%80%81,Medicine%E3%81%AE%E7%95%A5%E3%81%A7%E3%81%82%E3%82%8B)

#使用例
インストール

```console
%pip install pydicom
```

datasetにはメタデータが入っている

```python
import pydicom
import matplotlib.pyplot as plt
from pydicom.data import get_testdata_files

filename = get_testdata_files('CT_small.dcm')[0]
dataset = pydicom.dcmread(filename)
print(dataset)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/3d737ecd-2b02-02d8-b55d-88068f35c98d.png)

値の表示はキー名(.Rows)や番号（0x0010,0x0010）で表示,アクセスできる。

```python
dataset[0x0010, 0x0010]
dataset.Rows
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/fd299460-2c13-c4d4-3df8-94b4b128bf94.png)

画像の表示まで

```python
pat_name = dataset.PatientName
display_name = pat_name.family_name + ", " + pat_name.given_name

print("Patient's name...:", display_name)
print("Patient id.......:", dataset.PatientID)
print("Modality.........:", dataset.Modality)
print("Study Date.......:", dataset.StudyDate)
print(dataset[0x0018, 0x0050])

if 'PixelData' in dataset:
    rows = int(dataset.Rows)
    cols = int(dataset.Columns)
    print("Image size.......: {rows:d} x {cols:d}, {size:d} bytes".format(
        rows=rows, cols=cols, size=len(dataset.PixelData)))
    if 'PixelSpacing' in dataset:
        print("Pixel spacing....:", dataset.PixelSpacing)

# use .get() if not sure the item exists, and want a default value if missing
print("Slice location...:", dataset.get('SliceLocation', "(missing)"))


# plot the image using matplotlib
plt.imshow(dataset.pixel_array, cmap=plt.cm.bone)
plt.show()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/a26c8cd1-c6aa-45f6-5bb0-6abf516eacac.png)


#参考
[pydicom](https://pydicom.github.io/pydicom/stable/auto_examples/input_output/plot_read_dicom.html)
XserverでNetCommons3の登録フォームからメールが送られてこない

XserverにNetCommmons3をインストールして登録フォームを設置したんですが、メールが送られてこなくて「おや？」って一瞬思ったんでメモがてら残しておきます。

# XserverのCLI はPHP5.4

ここが一番の原因。登録フォームからのメール送信は最終的にcakeコマンドを実行するようになっているので、cakeコマンドがPHP5.4で実行されると、メール送信に失敗します。（2020/09/12現在のNetCommons3はPHP7.0以上が必要なので）

# cakeコマンド編集

Xserverの /usr/bin/php はPHP5.4ですが、ちゃんとPHP7系もインストールされてるので、そちらを使うようにcakeコマンドを書き換えちゃいます。

app/Console/cake:40行目あたり

```
exec php -q "$CONSOLE"/cake.php -working "$APP" "$@"
```

↑を↓にかきかえます

```
exec /usr/bin/php7.4 -q "$CONSOLE"/cake.php -working "$APP" "$@"
```

これでcakeコマンドがphp7.4で実行されるようになるので登録フォームからメールが送られるようになります。
Androidエミュレータが起動しない場合の解決法メモ

# どんな内容か？
Xamarinを利用していて、Androidの最近のVersionでテストする必要がありました。デバイスマネージャで新しいデバイスを追加したのですが、起動できずに困った話です。一応の解決方法が分かったのでメモしておくことにしました。同じ悩みを抱えた方の助けとなれば幸いです。全ての起動できない現象に一致する訳ではありません。

# 環境
OS:Windows10
開発環境：Visual Studio 2019 Community Version 16.7.3

# 現象
デバイスマネージャで、Andoird9.0（API28）のOSまでは起動するのですが、それ以上のAndroid10.0(API29)やAndroid11.0(API30)が起動できません。詳しく書くと、エミュレータのスマホ枠は表示されるのですが、１秒くらいですぐに消えてダウンしてしまう状況です。
<img width="640" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143415/64160881-a338-b50e-eb3d-c03cce836842.png">

# 試行錯誤の様子
※結論だけ知りたい方は飛ばしてください
設定（プロパティ）で音声を無効化したり、GPSを無効化したり、全部のプロパティをOFFにしてもダメ。
メモリを増やしたりいろいろ行っても全く効果ありませんでした。効果なし！
<img width="640" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143415/a1333749-e2de-86c3-0262-f87a06faba4d.png">

困ったときはログを確認・・・
したいのですが、Androidデバイスマネージャーから直接起動するとログがどこに出ているのかよくわかりません。
そこで、Android デバイスマネージャーから直接ではなくて、Xamarin（Visual Studio）側からエミュレータをキックしてもらうと少しログが見えました。（既に解決しているので、キャプチャーはないのですが・・・）

```c#
emulator: ERROR: VkCommonOperations.cpp:525: Failed to create Vulkan instance.
```
```c#
VCPU shutdown request
VCPU shutdown request
VCPU shutdown request
//（繰り返し）
```
エラーのキーワードとなりそうなのは上記のメッセージでした。
キーワードから、少しググって、こちらの[stack overflow](https://stackoverflow.com/questions/39865230/android-virtual-device-on-windows-10-endless-vcpu-shutdown-request-doesnt)の記事にぶつかりました。

HAXM（Hardware Accelerated eXecution Manager）にたどり着きます。
自分の記憶では、自らインストールした記憶はありませんが昔のことなので分かりません。

HAXMの最新版を適用することで解決しました。
HAXMのインストール時に、ポップアップのメッセージで、「既にインストールされている6.0.2から7.6.1に上げて良いか？」と問合せがあったので、そこそこ古かったようです。

# 解決策
[HAXM](https://github.com/intel/haxm)の最新のリリースをインストールし解決しました。
<img width="640" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143415/6e4b41f7-eb78-b965-3ac9-a8f22225ab2a.png">
私の場合は、7.6.1を適用して解決しました。

ということで、エミュレータで起動しないOSがある場合は、HAXMの最新版を適用すると幸せになれるかもしれないということで。
現場からは以上です。
avdmanagerを実行し「Exception in thread "main" java.lang.NoClassDefFoundError」が発生した場合の対処法

FlutterでAndroidの開発環境を構築する際、**`avdmanager`**をcliから実行すると下記のようなエラーが発生した際の備忘録です。

```shell
$ ~/Library/Android/sdk/tools/bin/avdmanager list
Exception in thread "main" java.lang.NoClassDefFoundError: javax/xml/bind/annotation/XmlSchema
        at com.android.repository.api.SchemaModule$SchemaModuleVersion.<init>(SchemaModule.java:156)
        at com.android.repository.api.SchemaModule.<init>(SchemaModule.java:75)
        at com.android.sdklib.repository.AndroidSdkHandler.<clinit>(AndroidSdkHandler.java:81)
        at com.android.sdklib.tool.AvdManagerCli.run(AvdManagerCli.java:213)
        at com.android.sdklib.tool.AvdManagerCli.main(AvdManagerCli.java:200)
Caused by: java.lang.ClassNotFoundException: javax.xml.bind.annotation.XmlSchema
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:602)
        at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
        ... 5 more
```

使用するJavaのバージョンを<font color="red">Android Studioに同梱されているJavaに変更する</font>ことで解決しました。

```shell
# パスを通す
$ echo 'export JAVA_HOME="/Applications/Android Studio.app/Contents/jre/jdk/Contents/Home"' >> ~/.zprofile 
$ source ~/.zprofile

# 確認
$ ~/Library/Android/sdk/tools/bin/avdmanager list
Available Android Virtual Devices:
Parsing ~
　:
　:
```

Android Studioに同梱されているJAVAのパスは、アプリを立ち上げ**`cmd + ;` → 「JDK location」**から確認が可能です。
【Android】XMLに1行追加でImageButtonにエフェクトを付加する

ImageButtonにおいて`android:background="@null"`としてしまうと，タップ時のエフェクトが表示れません。
「imagebutton エフェクト」で検索すると割と手間がかかる方法がヒットするのですが，
別にエフェクトのデザインに拘らない場合，レイアウトファイルに1行追加するだけで簡単にimagebuttonにエフェクトを追加することができます。
ImageButtonの養素に以下を追加するだけです

```xml
android:background="?android:attr/selectableItemBackgroundBorderless"
```
もし，背景を既に設定して変えたくない場合，foregroundも指定できます。


以下，サンプルです

```xml
<ImageButton
    android:id="@+id/menuSetting"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:background="?android:attr/selectableItemBackgroundBorderless"
    android:src="@drawable/ic_baseline_settings_24"/>
```

![ImageButtonEffect.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260207/aef0cc64-beb2-6529-1af0-cf6fb505969a.gif)
【JavaScript】超基礎的なメソッドの紹介　その２

JavaScriptで行うDOM(Document Object Model、要はHTML等のマークアップ言語にアクセス・編集しやすい標準的に仕組み)の操作において、基礎的なメソッドを学んだため、備忘として記します。
前回は、「１ HTML要素の取得」、「２　テキストデータの取得」を紹介しましたが、その続きです。

３　セレクタ式による要素の取得とgetメソッドとの比較
　（１）セレクタ式による要素の取得

```js
<ul id="listsSports">
  <li class="list">サッカー</li>
  <li class="list">野球</li>
  <li class="favorite">テニス</li>
</ul>
<ul id="listsDrinks">
  <li class="favorite">ビール</li>
  <li class="favorite">ワイン</li>
  <li class="list">焼酎</li>
</ul>
<script>
  const lists = document.querySelectorAll(`.list`); //class属性がlistに該当する要素すべて取得し、定数listsに代入。
  console.log(lists); //「サッカー」、「野球」、「焼酎」の要素をコンソールに出力。 
  const list = document.querySelector(`.list`); //class属性がlistに該当する要素のうち、最初に該当したもののみを取得し、定数listに代入。
  console.log(list); //「サッカー」の要素をコンソールに主力。 
</script>
```
　（２）getメソッドとの比較
　　　　例えば、上記リストのうち以下の要素のみを取得したいとする。

```js
  <li class="favorite">ビール</li>
  <li class="favorite">ワイン</li>
```
　　　　この場合、getメソッド（getElementByIdとgetElementsByClassName)だと一度定数にいれたものを再度取得する必要が出てくる。

```js
<script>
  const lists = document.getElementById(`listsDrinks`);//まず、id属性がlistsDrinksの要素をすべて取得。
  const favoriteDrinks = lists.getElementsByClassName(`favorite`); //そこからclass属性がfavoriteの要素を取得。
  for ( let i = 0; i < favorite.Drinks.length; i++) {
  console.log(favoriteDrinks[i]); //繰り返し文による出力。
}
</script>
```
　　　　一方で、セレクタ式（queryメソッド）だと、要素の取得に関して１行で記述を済ませられる。

```js
<script>
  const favoriteDrinks = document.querySelectorAll(`#listsDrinks .favorite`);
  for ( let i = 0; i < favorite.Drinks.length; i++) {
  console.log(favoriteDrinks[i]);
}
</script>
```
　　　　定義する変数や定数の数が増えるほど、getメソッドは記述が多くなる。
　　　　比べて、セレクタ式（queryメソッド）は複数の条件を１つにまとめられる点で優れている。

　　　　ただし、処理速度の点でいえばgetメソッドはqueryメソッドよりも速いため、コード記述のボリュームや煩雑さに合わせて使い分けが必要。

今回は以上です。
Ubuntu: Vimの最新バージョンインストール


```vim:add-apt-repositoryのインストール
$ sudo apt-get install software-properties-common
$ sudo apt-get update
```

```vim:リポジトリからインストール
"リポジトリの追加
$ sudo add-apt-repository ppa:jonathonf/vim
$ sudo apt update
"インストール
$ sudo apt install vim
"バージョン確認
$ vim --version
```

プラグイン管理のdein.vimもインストールしておきましょう！
https://github.com/Shougo/dein.vim

LGTMお願いします！
モチベーションがあがります！
SSID(Service Set Identifier)

応用情報技術者平成29年秋期 午前31

無線LANで用いられるSSIDの説明として，適切なものはどれか。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/c5e5048a-b585-fb1a-4ba4-bf48b4e3ed62.png)


１、SSID(Service Set Identifier)は、無線LANの規格であるIEEE802.11系において「混信」を避けるためにアクセスポイントと端末に設定されるネットワーク識別子です。

・SSIDには最長で32文字の任意の英数字を設定できます。
・通信を行う端末とスイッチがコードで接続されている有線LANと異なり、
・無線LAN環境では1つの端末が複数のアクセスポイントと通信できてしまう「混信状態」が発生し得ます。
・これを回避するため、無線LANではアクセスポイントと端末にそれぞれSSIDを設定し、SSIDが一致する機器同士しか通信ができないようにアクセス制御を行っています。

・同一のネットワークで複数のアクセスポイントを設置する場合を考慮してネットワーク識別名に拡張したものをESSID（Extended SSID：拡張SSID）という。現在ではESSIDの意味でSSIDという語を使う場合が多い。

２、BSSID(Basic Service Set Identifier)の説明
48ビットのネットワーク識別子であり，アクセスポイントのMACアドレスと一致する。

・MACアドレスの正体は48のビット列，つまり0と1が48個並んだ数字列である。48ビットを8ビット（オクテットと呼ぶ）ごとにハイフンやコロンで区切り，16進数に変換して表記する。

・オクテット（英: octet、8組の意味）は、コンピュータの、特に通信関係の分野などで、厳密には8ビット以外を指すこともある「バイト」の代わりに、必ず8ビットのことを指すものとして使われている語である。

参照：
https://www.ap-siken.com/kakomon/29_aki/q31.html

正体は48ビットの数字列，最初のビットで運命が分かれる
https://xtech.nikkei.com/it/article/COLUMN/20070829/280708/

SSID  【 Service Set Identifier 】 
http://e-words.jp/w/SSID.html#:~:text=SSID%E3%81%A8%E3%81%AF%E3%80%81%E7%84%A1%E7%B7%9ALAN,SSID%EF%BC%9A%E6%8B%A1%E5%BC%B5SSID%EF%BC%89%E3%81%A8%E3%81%84%E3%81%86%E3%80%82
セッションを用いたセキュリティ攻撃(セッションID、クッキー)

```
前提
プログラミング初学者(2~3ヶ月)が学んだ内容をまとめています。
実際の現場では通用しないことや間違った内容が含まれている可能性があります。
間違っている部分や浅い部分については追記、ご指摘いただけると幸いです。
```
セッションを用いたセキュリティ攻撃について学んだ内容をまとめました。
#セッションを狙った攻撃と対策
##セッションとは？
セッションとは、データを一時的に保存しておく仕組みのことです。
この一時保存される保存先はクッキーと呼ばれます。
youtubeやtwitterに同じ端末からアクセスすると自分のアカウントでログインされた状態になっていますよね。
あれはセッションという仕組みでログイン情報がクッキーに一時的に保存されているため、毎回ログインをしなくてもログイン状態になっているということです。
このログイン情報などが一時的に保存されているクッキーを狙った攻撃をセッションハイジャックといいます。
##セッションハイジャック
XSSなどを用いて、正規利用者ではないものが正規利用者のセッションを取得する攻撃方法です。

XSSはwebアプリやwebページを開いたらスクリプトが発動し、個人情報が攻撃者へ送信されるといったものです。
以前まとめた記事が以下です。
https://qiita.com/Nako4/items/845da2ed4872524c2a15

クッキーにはセッションIDという識別番号を用いて保存します。
このセッションIDを盗み出されることで、セッションハイジャックが成立します。
**セッションID**
通信中の正規利用者へ付与される固有の識別情報のこと
##攻撃されると危険な理由
危険性については、なんとなく察することができると思います。
セッションを悪意ある攻撃者に取得されるとログイン情報が第三者の手に渡ってしまい、正規利用者のできることが全てできる状態になってしまうということです。
例えば、配送先の住所や購入情報（クレカ番号）を登録している場合
・正規利用者の個人情報を見ることができる
・勝手に物品購入をする
・送金ができる
・メールアドレスを使ってなりすましメールを送る
このように正規利用者への被害はとても大きくなります。

##セッションを用いた攻撃方法
具体的にセッションへの攻撃方法は３つあります。
・セッションIDの推測
・セッションIDの盗み出し
・セッションIDの強制
### セッションIDの推測
Webアプリケーションに用いられるセッションIDの生成規則に問題があると、第三者にセッションIDが予測されやすくなります。
問題があるセッションID
・ユーザーIDやメールアドレス
・リモートIPアドレス
・日時
セッションIDの推測は外部から参照可能な値を用いて行われる手法です。
**対策**
独自でセッションID生成は行わない。
推測可能なセッションIDを生成しないために、独自での生成機構は作らず、フレームワークなどのWebアプリケーション開発ツールを利用することが安全とされています。
セッション管理機能に脆弱性が発見された場合、すばやく指摘・改善されることが期待できるためです。
Ruby on Railsもこのアプリケーション開発ツールの１つです。
### セッションIDの盗み出し
JavaScriptでは、

```javascript
<script>document.cookie</script>
```
というスクリプトで
クッキーの情報が表示できます。
このスクリプトへ細工をして、攻撃側のサーバに正規利用者のクッキーの情報を送付するようにすると、セッションハイジャックが成立します。
インターネット環境のセキュリティ対策が不十分であると、正規利用者とサーバーの通信の際に、故意または偶然にセッションIDが第三者へ受信されることがあります。

**対策**
・XSSを防ぐ
・安全なインターネット環境を用いる。
インターネット環境の安全性向上のためには、インターネット上の通信を暗号化する仕組みを使います。
この暗号化の仕組をSSLといいます。

**SSL(Secure Sockets Layer)**
SSLはインターネット上の通信を暗号化してくれる技術です。
暗号化して通信を行うことで、第三者からの情報の盗聴や改ざんを防ぐことができます。
このSSLを使うことで、クッキーのような常用な情報をやりとりする際に安全性を保つことができます。
SSL化されたURLはhttps://から始まるwebページのことです。
### セッションIDの強制
セッションを攻撃者が顔分から強制的に固定化する方法です。
具体的な手順は
①攻撃者が正規の利用者としてセッションID（abc)を取得
②正規利用者に対して、①で取得したセッションIDを強制
③正規利用者は標的アプリケーションにログイン
④攻撃者は正規利用者に強制したセッションID（abc）を使って標的アプリケーションにアクセスする

セッションとは利用者の状態を保持するために使われていました。
正規利用者は攻撃者が強制したセッションでログインなどの認証が完了した状態が一時保存されています。
つまりこのセッションを用いて攻撃者もログイン済みのページにアクセスすることができてしまいます。
**対策**
ログイン後にセッションIDを変更する
セッションIDを固定化する方法は多種多様であるため、固定化されないように常に変更し続けることが重要です。
例えば、ログインした直後にセッションIDを変更するとしておくことで、セッションを強制されていても、ログイン後に更新されるため、攻撃者が強制したセッションを用いてWebアプリケーションを利用することはできません。
Ruby on RailsのGemの１つであるdeviseはこの仕組を採用しています。

##まとめ
セッションとはログイン情報を一時保存できる仕組みでクッキーという場所に保管されている。
セッションを用いたセキュリティ攻撃には推測、盗み出し、強制の３つがある。
推測：独自の生成規則を作らず、既存のフレームワークを使うことでセッションIDを推測されにくくなる。
盗み出し：基本的なXSSの対策を行う。
強制：セッションIDをログイン後に変更することでセッションIDの固定化を防ぐ。
LaravelでVue.JSを使ってみる①

#環境構築
プロジェクト内でnpm installで利用可能（ver 5.6以降？デフォルトでpackage.jsonに設定してある）
※レンタルサーバーの場合はnode.js入れる必要がある。

```
$ npm install
```

#実装してみる
とりあえず、welcome.blade.phpに設定してみます。

```resources/views/welcome.blade.php

<html lang="{{ app()->getLocale() }}">
    <head>
      ～
     <meta name="csrf-token" content="{{ csrf_token() }}">
　　　<link href="{{ asset('css/app.css') }}" rel="stylesheet">
     ～
　　</head>
　　<body>
     ～
      <div id="app">
         <example-component></example-component>
      </div>
     ～
     <script src="{{ asset('js/app.js') }}" defer></script>
   </body>
</html>
```

##①head内でcsrfトークンの設定、cssのリンク

```
<meta name="csrf-token" content="{{ csrf_token() }}">
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
```

##②body内でコンポーネントの設定
vueのコードはresources/assets/js/app.jsに書いてあります。example-componentはデフォルトで設定してあるコンポーネント

```
　　　<div id="app">
         <example-component></example-component>
      </div>
```

##③body閉じタグ直前でjsファイルへのリンク

```
<script src="{{ asset('js/app.js') }}" defer></script>
```

#動かしてみる

コンパイルしてページを開くと表示されているはずです。

```
$ npm run dev
```

npm run dev … minifyされない
npm run prod … minifyされる
npm run watch …　対象ファイルを監視して変更があれば自動でコンパイルしてくれる
データマイニング(Data Mining)

応用情報技術者平成29年秋期 午前30

データマイニングの説明として，適切なものはどれか。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/9fafeeca-feff-7e8b-f189-7248bd01269b.png)

１、データマイニング(Data Mining)は、
データウェアハウスに蓄積されている大量の生データから、統計学的手法、数学的手法を用いて今まで知られていなかったデータの規則や因果関係を見つけ出す手法です。


２、データウェアハウスの説明
基幹業務のデータベースとは別に作成され，更新処理をしない集計データの分析を主目的とする。


３、データマートの説明　Data　Mart
個人別データ，部門別データ，サマリデータなど，分析の目的別に切り出され，カスタマイズされたデータを分析する。

データマート (Data Mart) は、データウェアハウスの中から特定の目的に合わせた部分を取り出したもの。 通常は利用部門が利用目的に合ったデータのみを所持するものである。

※「マート」(mart)は「小売店」

＜＜データマートとデータウェアハウスの比較＞＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/886023d1-b813-d6a3-5712-49fa5aa7e68a.png)

・データマートはデータウェアハウスの一部を指していることがわかりますね。

＜＜データレイクとデータウェアハウスの比較＞＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/b0b5b0e6-e76e-229f-d694-bcd53f244269.png)

つまり、
・データレイクはとりあえず情報をたくさん集め、そこから分析結果を得るという「帰納的」アプローチです。
・データウェアハウスは、先に分析理論が確立されており、そのためにデータを集めるという「演繹的」アプローチとなります




４、OLAP(Online Analytical Processing)の説明
スライシング，ダイシング，ドリルダウンなどのインタラクティブな操作によって多次元分析を行い，意思決定を支援する。

・ネットワークを仮想化、分割する技術 「ネットワークスライシング」とは、ネットワークを仮想的にスライス、つまり分割する技術のことです。ここはスライシングとは、多分分割のことでしょう。
・ダイシング（英語: dicing または die cutting）とは、半導体のウェハー上に形成された集積回路などを、ダイシングソーでウェハーを切削して切り出し、チップ化する工程である。
・ドリルダウンとは、データの集計レベルを１つずつ掘り下げて集計項目をさらに詳細にする操作のこと。
・「インタラクティブ」の意味は相互に作用するさまのこと。



参照：

データマートとは？ データウェアハウスとの比較から話題のデータレイクも含めて解説！
https://data.wingarc.com/what-is-data-mart-12075


https://www.ap-siken.com/kakomon/29_aki/q30.html
Vue.jsの特徴

#プログラミング勉強日記
2020年9月12日
JSには色々なフレームワークがあって、開発の用途によって使用するフレームワークが違うと思うので、まとめてみようと思う。[Reactについて](https://qiita.com/mzmz__02/items/18f04f8e4ec84f1cc1af)と[Angularについて](https://qiita.com/mzmz__02/items/929beb891c194c9d0f43)まとめたので、今回はVue.jsについてまとめる。

#Vue.jsとは
　Vue.jsは、UIを構築するためのJavaScriptのフレームワーク。Vue.jsでコードを書くときは、無駄な長い記述を少なくできる。Vue.js独自の規格やルールも少ないので、他のフレームワークよりも自分の好きな方法でアプリ開発を行うこともできる。

#特徴

##コンポーネント指向である
　ReactとAngularと同様で、Vue.jsもコンポーネント指向である。コンポーネント指向は、ソフトウェアを機能ごとに部品(コンポーネント)として分割して、必要に応じて組み合わせて使う考えのことである。
　機能を小さい部品にして持たせているので、状態の管理もしやすくて再利用も容易にできる。再利用性が高くなり、デザインと技術の共同作業を簡単にすることができ、開発スピードの向上ができる。

##学習コストが低い
　様々なフレームワークがあり、開発現場ごとに新しい技術を取得しないといけないことも珍しくないが、その中でもVue.jsは学習コストが低く、初心者や経験者問わずすぐに開発することができるという特徴がある。Vue.jsがシンプルであり、非常に人気が高いので日本語での技術ブログや記事が充実している。

##ディレクティブ
　Vue.jsはDirectiveというView要素に付加できる独自要素がある。ディレクティブを使用することで、[DOM](https://qiita.com/mzmz__02/items/dc94883c145d143e4fad)を簡単に操作することができ、HTML要素の表示・非表示を柔軟に変化でき、開発スピードを速められる。

##双方向データバインディング
　Vue.jsもデータバインドに特化したフレームワークである。
　アプリでユーザ画面(View)で操作した内容をデータ(Model)の反映、データ(Model)の内容が変わったときに画面(View)に反映する必要がある。なので、Viewを操作するときはModelに反映するために、画面からHTMLの要素を取得して要素をデータとして処理、処理したデータを画面に反映するプログラムを書く必要がある。

##クラスを利用可能
　JSでは使えなかったクラスを利用することができる。Vue.jsでは連想配列の形でクラスを作成して、様々なデータの入れ物として活用することができる。

##TypeScriptも利用可能
　Vue CLIにはJestやMochaを使って簡単に単体テストを行うためのプラグインオプションがある。公式のVue Tesyユーティリティもあり、作成したアプリの動作を検証することができる。

##URLのルーティングができない
　ルーティングとは同じページ上で疑似的なページ遷移すること。
　Vue.jsではURLのルーティングを単体で行うことができる。ルーティングを必要とする場合には管理が複雑になることがあり、単一のページ以外が表示されない扱いになり、アクセス解析やSEO上の不都合が生じることがある。

##古いブラウザには非対応
　Vue.jsを利用して作ったサイトは古いブラウザでは見ることができない。


#参考文献
[【Vue.js入門】特徴や他のフレームワークとの比較などを紹介！
](https://udemy.benesse.co.jp/development/web/vue-js.html)
[Vue.jsとは？特徴とできることを具体例を交えて紹介
](https://engineers-hack.com/about-vuejs/)
AWSクラウドプラクティショナーに合格したのでやって良かったこと&本番トラブルを振り返ってみる

先日オンライン自宅受験でAWSクラウドプラクティショナーに合格しました。直前1週間はかなり焦って無我夢中で対策していたので、一旦落ち着いて振り返ってみたいと思います。
だらだらと書いていますが、受験を考えている方のご参考になれば幸いです。
ちなみに結果は895/1000で、合格ラインの700点と比べると比較的余裕がありました。

<h2>経歴</h2>
<ul><li>AWSはEC2やVPC、S3などほんの少しだけ触っていました。業務での利用はなし。
<li>基本情報技術者（FE）だけ取得済み
<li>仕事の一環でクラウド全般やAWSの基礎講座を何回か受けていました。</ul>

<h2>勉強時間</h2>
30~40時間程度。試験のために本腰を入れたのは約1週間前からで、おそらく20時間くらい。
試験関係なく、AWSの勉強自体を始めていたのは2か月前くらいだったと思います。

<h2>やったこと（◎必須、〇やってよかった、△プラスアルファ）</h2>
◎  公式の試験ガイドを確認する<br>
◎  公式のサンプル問題（10問）<br>
◎  各サービスの紹介ページをみて概要を確認する<br>
◎  模擬試験（有料）を解く<br>
〇 公式トレーニング動画を見る（「AWS Cloud Practitioner Essentials(2nd edition)」）<br>
〇 料金系のサービスなどは実際のコンソールを確認<br>
〇 Udemy講座「この問題だけで合格可能！クラウドプラクティショナー模擬問題7回分」の最後を除いた6回分。分からなかった問題の解説はスクショして、空き時間に確認してました。まさに詰め込み。<br>
△ Udemy講座「これだけでOK!AWSソリューションアーキテクト-アソシエイト突破講座」のEC2やS3、DBなど、ハンズオン以外。（購入はセール期間中に！）<br>
△ Black Beltでサービスの概要と仕様を確認する<br><br>

ちなみにこの試験のための書籍は購入せず、主に公式サイトや動画サービスを利用していました。

<h2>やってよかったこと、感想</h2>
<ul><li>テスト範囲とその配点比重の確認はやはり重要だと思いました。これはサンプル問題10問と公式の試験ガイドで把握できます。プラス2000円で模擬問題も解けば、難易度と本番の試験形式もある程度把握できるかと思います。サンプル問題より本番試験の方が難しく感じたので、注意が必要です。
<li>ちなみに本番1週間前に解いたこの模擬問題が想像以上に難しく感じ、実際テクノロジーや料金の範囲の正答率がかなり低かったので結構焦りました。そこからSAA向けの講座を聞いたり、black beltをざっと確認したりしていましたが、技術面に関してはそこまでの詳細は聞かれなかったと思います。
<li>Udemyの模擬問題も、本番試験と比べると比較的難しめに作られている気がしました。確実に合格したい方はきちんと取り組むと良いかもしれませんが、この結果を真に受ける必要はあまりない気がします（半分くらいしか取れませんでした）。
<li>ただし公式のトレーニング動画よりは試験の方がより広く深く聞かれた体感があります。
</ul>

<h2>重要視されていると感じたこと</h2>
<ul>
<li>基本的なサービスの概要や使い方：EC2,NW(VPC,Route53,CloudFrontなど),ストレージ(S3,EBS,EFS,Snowballなど),DB(RDS,Aurora,Dynamoなど)
<li>責任共有モデル：AWSとカスタマーの責任範囲の分担。数題出題されました。
<li>コスト計算系サービス：Cost Explorer, AWS Budgets, TCOなど。
<li>管理系サービス：Config, CloudTrail, TrustedAdviser, Systems Managerなど。
<li>クラウドを使うメリット：スケーラビリティや柔軟性など。実際の問題は国語力で解けるかもしれません。 
<li>その他サービス：分析系（Redshift,Kinesis）、コンテナ系（ECS,EKS）など以外と幅広く見かけた気がしました。</ul>

<h2>当日おきたこと</h2>
オンラインで受験中、試験の様子がPCのカメラで常に撮影されてチェックされます。
事前のシステムテストは問題なく通りましたが、途中そのビデオの送信が途切れてしまったみたいで、試験官とチャットやコールで何回かやりとりすることに（ちなみに訛りのある英語でやや聞き取りづらめ）。
wi-fiに特に問題はなさそうで、また代わりのネット接続法はないことを伝えると、いったん試験を中断しPCの再起動を要求されました（ちなみに何回かこのやりとりをしました。再起動中は試験官と電話で会話をしたり、しなかったり）。・・お気づきかもしれませんが、監視がない状態なので、この間しようと思えば離席したりネットに繋いだりできてしまいます（もちろんしませんでしたが！！）。
最終的にはビデオが繋がり無事に試験を終えられましたが、今のオンライン受験の体制の限界を垣間見た気がします。

個人の主観が多分に入っていますので、他の方のご意見も参考にされますとより試験のイメージが深まるかと思います。
【Java】　特定の数値を除いた乱数を取得する方法

## 9/13 更新
以前書いたコードを改善しました。改善点としては
- ListではなくSetを使用し、リトライ回数を減らしたこと
- 除外したい数値をString型ではなくInterger型にしたこと

```java:main.java
import java.util.Random;
import java.util.HashSet;

public class Main {
 
    public static void main(String[] args) {
        Random rand = new Random();
        int i;
        // 除外したい数値を格納する
        Set exSet = new HashSet();
        exList.add(2);
	    exList.add(5);
	    exList.add(8);
		
		do {
			i = Interger.valueOf(rand.nextInt(10)+1);　// 1~10までの乱数を生成し文字列に変換
		} while (exSet.contains(i)); //除外リストのいずれかの数値と一致なら繰り返す
		System.out.println(i);
    }
}
```




こちらが改善前のコード




```Java:main.java
import java.util.ArrayList;
import java.util.Random;

public class Main {
 
    public static void main(String[] args) {
        Random rand = new Random();
        String i;
        // 除外したい数値を格納する
        List<String> exList = new ArrayList<String>();
        exList.add("2");
		exList.add("5");
		exList.add("8");
		
		do {
			i = String.valueOf(rand.nextInt(10)+1);　// 1~10までの乱数を生成し文字列に変換
		} while (exList.contains(i)); //除外リストのいずれかの数値と一致なら繰り返す
		System.out.println(i);
    }
}
```

海外でのQAサイトで見つけた特定の数値を除いた乱数を除外する方法も見つけたが
参考までに載せておきます。


```java
public int getRandomWithExclusion(Random rnd, int start, int end, int... exclude) {
    int random = start + rnd.nextInt(end - start + 1 - exclude.length);
    for (int ex : exclude) {
        if (random < ex) {
            break;
        }
        random++;
    }
    return random;
}
```

```java:main.java
int[] ex = { 2, 5, 6 };
val = getRandomWithExclusion(rnd, 1, 10, ex)
//　5,6,7の乱数を発生させた場合、７の値を取得するため、7のみ発生頻度が高くなってしまう
```