OmniAICreator/Qiita-1.07M huggingface dataset:
Amazon Linux1で [Skipping bootstrap because certbot-auto is deprecated on this system.]

## certbot-autoは非推奨になりました。

```
$ sudo ./certbot-auto certonly --debug -n -m [MyEmail] --agree-tos --standalone -d [host.mydomain] --keep-until-expiring

Skipping bootstrap because certbot-auto is deprecated on this system.
Your system is not supported by certbot-auto anymore.
Certbot cannot be installed.
Please visit https://certbot.eff.org/ to check for other alternatives.
```

oh...証明書取得できない

[It is only certbot-auto that we deprecated.](https://community.letsencrypt.org/t/certbot-auto-no-longer-works-on-debian-based-systems/139702/6)
理由は、python2の寿命だよ.

## certbotをいれる

[Apache on Other Linux (snapd)](https://certbot.eff.org/lets-encrypt/othersnap-apache)
[Apache on Other Linux (pip)](https://certbot.eff.org/lets-encrypt/otherpip-apache)

AmazonLinux1だとsnapdは、入らないよな
pipにしましょ

外部リポジトリからpython3を探して入れようとしていたが
Amazonのリポジトリにpython36が提供されていることがわかった。

#### ptthon36を入れる
```
$ sudo yum -y install python36 python36-pip augeas-libs
```

#### Apache on Other Linux (pip)に従って
```
$ sudo python3 -m venv /opt/certbot/
$ sudo /opt/certbot/bin/pip install --upgrade pip
$ sudo /opt/certbot/bin/pip install certbot certbot-apache
$ sudo ln -s /opt/certbot/bin/certbot /usr/bin/certbot
```

これでcertbotで証明書取得成功です。

```
$ sudo certbot certonly --debug -n -m [MyEmail] --agree-tos --standalone -d [host.mydomain] --keep-until-expiring
```
VBAでPDF化する方法

VBAを使用すると、一瞬でPDF化することが出来ます。
下記にコードを記載します。

```
Sub PDF化()

Dim fileName As String
Dim name As Variant

name = Left(ActiveWorkbook.name, Len(ActiveWorkbook.name) - 5)

fileName = ThisWorkbook.Path & "\pdf\" & name & ".pdf"

Worksheets("見積書").ExportAsFixedFormat Type:=xlTypePDF, fileName:=fileName

End Sub
```

詳細を説明していきます。

>Dim fileName As String
>Dim name As Variant

まずは、PDFを格納先パスを含むファイル名(fileName)とファイルの名前のみ(name)を格納する変数を作ります。

>name = Left(ActiveWorkbook.name, Len(ActiveWorkbook.name) - 5)

次に、Left関数で先頭から指定した文字数のところまでの文字列を取得します。
第一引数で対象ファイルのファイル名を取得し、第二引数で何文字まで取得するのか指定しています。

>Len(ActiveWorkbook.name) - 5

第二引数の上記で、ファイル名末尾の「.xlsm」を除いています。

>fileName = ThisWorkbook.Path & "\pdf\" & name & ".pdf"

「ThisWorkbook.Path」で、対象のエクセルファイルの格納先パスを取得しています。
「"\pdf\"」でPDFを格納する場所を指定しています。
こちらを変更することで、好きな場所に格納することができます。
&を使い、格納先ファイルパスとファイル名を連結し、最後に.pdfとします。

>Worksheets("見積書").ExportAsFixedFormat Type:=xlTypePDF, fileName:=fileName

PDFで出力するためには、ExportAsFixedFormatメソッドを使用します。
TypeはxlTypePDF、fileNameには、格納パスを含めたfileNameとします。

以上、VBAでPDF化する方法です。
【Azure】Azure Storage の監視について

Azure Storage の監視について、調べたのでメモです。

##監視方法
Azure Storage を監視する方法は、以下の２つです。
・Azure Monitor アクティビティログ
・Azure Storage Analytics のメトリック (クラシック)

クラシックは今後廃止になるようです。
なので、Azure Monitor アクティビティログを利用した監視方法を選択。

https://docs.microsoft.com/ja-jp/azure/virtual-machines/migration-classic-resource-manager-overview

>現在、IaaS VM の約 90% で Azure Resource Manager が使用されています。 2020 年 2 月 28 日の時点で、クラシック VM は非推奨とされており、2023 年 3 月 1 日に完全に廃止されます。 この非推奨の詳細およびそれが与える影響について確認してください。

##Azure Monitor アクティビティログ
■記録できる操作
StorageRead	：オブジェクトに対する読み取り操作。
StorageWrite	：オブジェクトに対する書き込み操作。
StorageDelete	：オブジェクトに対する削除操作。

https://docs.microsoft.com/ja-jp/azure/storage/blobs/monitor-blob-storage?tabs=azure-portal#collection-and-routing

■ログの形式（スキーマ）

https://docs.microsoft.com/ja-jp/azure/storage/blobs/monitor-blob-storage-reference#resource-logs-preview

取得したアクティビティログは、他のストレージアカウントのアーカイブできるため、ライフサイクル機能を利用して任意の期間保管後に削除するなどの処理が可能。

https://docs.microsoft.com/ja-jp/azure/storage/blobs/monitor-blob-storage?tabs=azure-portal#archive-logs-to-a-storage-account

【Azure Storage Analytics のメトリック (クラシック)との違い】
Azure Storage Analytics のメトリック (クラシック)を利用した監視では、ストレージアカウントに　＄Logs　コンテナーが作成され、規定で ＄Logs コンテナーにログが格納される。
そのため、Azure Storage Analytics のメトリック (クラシック)のログは、ライフサイクル機能で任意の期間保管後に削除するなどの処理が行えないが、Azure Monitor アクティビティログは、システムコンテナーに格納されないためライフサイクル機能の対象となる。

https://docs.microsoft.com/ja-jp/azure/storage/blobs/lifecycle-management-overview

>汎用 v2、Premium ブロック BLOB、Blob Storage のアカウントでは、ブロック BLOB と追加 BLOB でライフサイクル管理ポリシーがサポートされています。 ライフサイクル管理は、 $logs コンテナーや $web コンテナーなどのシステム コンテナーには影響を与えません。
pgAdminを使って本番環境DBと同じDBをAWS上に作成

# はじめに

すでに AWS 上で動いている本番環境 DB からデータを引っ張ってきてアプリ上で表示させたい。ただ本番環境を汚してトラブルになるのは怖いので、別で EC2 インスタンスをたててそこに PostgreSQL をインストールし、本番環境 DB のコピーを作成する。

# EC2 インスタンスに PostgreSQL をインストール

EC2 インスタンスの端末で以下コマンドを実行し、PostgreSQL をインストール。

```
$ sudo apt -y update 
$ sudo apt -y install postgresql postgresql-contrib
```

インストールすると、/etc/postgresql/12/main/postgresql.conf が作成されるので、クライアントから接続ができるように listen_addresses （59行目あたり）を以下のように変更する。

```
#listen_addresses = 'localhost' # デフォルトで書かれている設定
listen_addresses = '*'          # 追記した設定
```

上記設定にすることで、どのクライアントからでも接続できるようになる。制限を加えたい場合は、`listen_addresses = '192.168.0.1'` のように IP アドレスを指定する。

設定を適用するために、一度再起動。

```
$ sudo service postgresql restart
```

また PostgreSQL インストール時に作成されるユーザ postgres はパスワードが未設定の状態である。その状態だとアカウントロック状態になっているので、パスワードを設定する。

```
ubuntu:$ sudo -i -u postgres
postgres:$ psql
postgres=# \password
Enter new password:
Enter it agein:
postgres=# \q
```

# DB へ接続

Windows10 の pgAdmin で 接続する。pgAdmin は [PostgreSQL](https://www.postgresql.org/) からファイルをダウンロードしてインストールする。（詳細は割愛）
pgAdmin を開いて Servers 上で右クリック -> [Create] -> [Server] で DB に接続する。[General] タブで __Name：（任意）__、
[Connection] タブで __Host name/address：(Server の IP アドレス、ifconfig にて確認可能)、Password：（上記で設定していたパスワード）__を入力すれば接続できる。

# DB のバックアップを作成

上記で接続した DB にて、バックアップをとりたい DB 上で右クリック -> [Backup...] を選択。Filename に任意の保存先、Format に Tar、Encoding に UTF8 を選択し、Backup をクリック。
![backup.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/769545/2f802a16-9fb4-a390-ce2a-a0e9cdb98fb8.png)

# DB をリストア

リストアしたい DB 上で、右クリック -> [Restore...] を選択。Filename に先ほど保存したバックアップファイルを指定して、Restore をクリック。![restore.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/769545/4b471c0e-9aa4-d9eb-e037-04f40c926a3b.png)
フレームレートが10未満のmp4を作りたいとき

例えばストップモーション風の動画を作りたくて、
フレームレートを5くらいに設定したい場合。

▼ストップモーションをAeで作る時の参考
https://www.youtube.com/watch?v=8DjXxa33WOk
※とても素敵なチュートリアル。解説の音声がとても素敵！

#MediaEncoderでは最低のフレームレートは「10」？
素材自体はできたけど書き出しでつまずいた。
最低の数値が「10」で「5」へ書き出せない…！
![ 2021-03-26 13.56.37.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168611/d6f13f89-97fa-33f9-e9f0-135c84ff8e05.jpeg)

#回り道だけど解決方法
1. Aeにて「mov」形式でレンダリング　※フレームレートは５に設定できる
2. レンダリングした「mov」をMeiaEncoderでレンダリング

やや力技ですが、これでフレームレート5のmp4が手に入った。

もっとスマートな方法があれば情報お待ちしています！
Acronis True Image 2021 をUSBブートした後、フリーズするのを解決

## 現象

* Acronis True Image 2021 を USBブートした後、操作画面で、何を押しても`ビープ音`しかせず、操作不能になった。

## 解決方法

`Alt + F2`キーを押して端末を開き、

```sh
acronis
```

を実行すると操作画面が表示され、問題は解決した。。
【ExcelVBA】簡易アドイン用

ThisWorkbook

```vb
Option Explicit

Private Sub Workbook_BeforeClose(Cancel As Boolean)
    Application.OnKey "^j"
    Application.OnKey "+^j"
    Application.OnKey "+^q"
    Application.OnKey "^q"
End Sub

Private Sub Workbook_Open()
    Application.OnKey "^j", "LastSheetSelect"
    Application.OnKey "+^j", "SelectSheet"
    Application.OnKey "+^q", "SheetVisial"
    Application.OnKey "^q", "FirstSheetSelect"
End Sub

```

Module1

```vb
Option Explicit

Sub FirstSheetSelect()
'Ctrl + q
'開始シートの選択
Dim i As Long
For i = 1 To Sheets.Count
    If Sheets(i).Visible = True Then
        Sheets(i).Select
        Exit For
    End If
Next

End Sub

Sub LastSheetSelect()
'Ctrl  + j
'最終シートの選択
Dim i As Long
For i = Sheets.Count To 1 Step -1
    If Sheets(i).Visible = True Then
        Sheets(i).Select
        Exit For
    End If
Next

End Sub

Sub SelectSheet()
'Ctrl + Shift + J
'シート選択
Dim shName As String
    shName = InputBox("シート名")
On Error Resume Next
Worksheets(shName).Select
On Error GoTo 0

If Err.Number <> 0 Then
    MsgBox "指定のシートはありません"
End If

End Sub


Sub SheetVisible()
'Ctrl + Shift + Q
'全シートを表示する
Dim i As Long
For i = 1 To Sheets.Count
    Sheets(i).Visible = True
Next i

End Sub
```

Module2

```vb
Option Explicit

Function CONCAT(ParamArray par())
  Dim i As Long
  Dim tR As Range
  
  CONCAT = ""
  For i = LBound(par) To UBound(par)
    If TypeName(par(i)) = "Range" Then
      For Each tR In par(i)
        CONCAT = CONCAT & tR.Value2
      Next
    Else
      CONCAT = CONCAT & par(i)
    End If
  Next
End Function

Function TEXTJOIN(Delim, Ignore As Boolean, ParamArray par())
  Dim i As Integer
  Dim tR As Range
   
  TEXTJOIN = ""
  For i = LBound(par) To UBound(par)
    If TypeName(par(i)) = "Range" Then
      For Each tR In par(i)
        If tR.Value <> "" Or Ignore = False Then
          TEXTJOIN = TEXTJOIN & Delim & tR.Value2
        End If
      Next
    Else
      If par(i) <> "" Or Ignore = False Then
        TEXTJOIN = TEXTJOIN & Delim & par(i)
      End If
    End If
  Next
  
  TEXTJOIN = Mid(TEXTJOIN, Len(Delim) + 1)
  
End Function

Function EXACTA(rng1 As Range, rng2 As Range)

If rng1.Value = rng2.Value Then
    EXACTA = 1
Else
    EXACTA = 0
End If

End Function
DataFrameの先頭に行を追加する方法

プログラミング初心者です。
内容に間違いがあるかもしれないのでご注意ください。

---
DataFrameの先頭に行を追加するメソッドは無さそうだったので、
追加したい行のみのDataFrameを作成して`pandas.concat()`メソッドで合成する方法をとってみる。


###### 追加される側のDataFrameの作成

```py
import numpy as np
import pandas as pd

# 3行2列のランダム数値が入った配列から作成
df = pd.DataFrame(np.random.rand(3,2), index=['A', 'B', 'C'], columns=['foo', 'bar'])
#         foo       bar
# A  0.299105  0.841390
# B  0.424596  0.316961
# C  0.055032  0.110246
```
###### 追加したい行をDataFrameとして作成

```py
# 追加される側と同じ列数の1行配列を作成(ここでは1行2列)
a = np.zeros(len(df.columns)).reshape(1,len(df.columns))
# array([[0., 0.]])

# DataFrameに変換する
df_insert = pd.DataFrame(a, index=['X'], columns=df.columns)
#    foo  bar
# X  0.0  0.0
```

###### `pandas.concat()`で合成
```py
pd.concat([df_insert, df]) 
#         foo       bar
# X  0.000000  0.000000
# A  0.299105  0.841390
# B  0.424596  0.316961
# C  0.055032  0.110246
```

---
もっと良い方法がありそうな気もするけれど、ひとまずこれで対応。
頻出トークンの抽出

# Counterクラスを用いた出現数のカウント

頻出のトークンを抽出するために、Counterクラスの勉強をしています。

```python
import collections
import more_itertools

f = open('minpo.txt')
data1 = f.read()
f.close()

# n-gramでのトークン化（前記事で記載）
l =["".join(lst) for lst in  list(more_itertools.windowed(data1, n=6, step=1))]
# [(トークン, 出現数)]の形の、タプルのリストを取得
c = collections.Counter(l)
# タプルの2つ目（tap[1]、出現数）が100以上の1つ目（tap[0]、トークン）をリストにする
[tap[0] for tap in c.items() if tap[1] >= 100]
```

出力結果は以下です。何に使えるかわからない結果になりました。<br/>
個人的な目標は、裁判などで利用できる書面作成支援アプリであり、よくある言い回しに使えるかもしれないなと思っています。

```shell-session
['しなければな',
 'なければなら',
 'ければならな',
 'ればならない',
 'ばならない。',
 'ならない。\n',
 'の規定により',
 'ったときは、',
 'たときは、そ',
 'ときは、その',
 '。\nただし、',
 'については、',
 'は、この限り',
 '、この限りで',
 'この限りでな',
 'の限りでない',
 '限りでない。',
 'りでない。\n',
 'ことができる',
 'とができる。',
 'ができる。\n',
 'することがで',
 'ることができ',
 'の場合におい',
 '場合において',
 '合において、',
 'ことができな',
 'とができない',
 'あるときは、',
 'をすることが',
 'る。\nただし',
 'したときは、',
 'ないときは、',
 '項の規定は、',
 'について準用',
 'ついて準用す',
 'いて準用する',
 'て準用する。',
 '準用する。\n',
 '。\nこの場合',
 '\nこの場合に',
 'この場合にお',
 'ができない。',
 'できない。\n',
 '項の規定によ',
 'の規定による',
 'を請求するこ',
 '請求すること',
 '求することが']
```

# コーパス
[コーパス](https://raw.githubusercontent.com/foj05123425/lawtech/main/%E6%B0%91%E6%B3%95.txt)は、githubに置いていますが、まだまだ整備中です。
【解決】math.floorで15桁以上の数の小数点を切り捨てると何だか変

先日のAtCorderのB問題、正しくコーディングできているはずなのに、何回やっても不正解でした・・・

[B - Round Down](https://atcoder.jp/contests/abc196/tasks/abc196_b)

###問題文
整数または小数 
Xが与えられるので、小数点以下を切り捨てて整数で出力してください。

###制約
0≤X≤10**100
Xは整数、または小数点以下が100桁以下の小数であり、先頭に余計な0は付かない

###回答
```
import math
X = math.floor(float(input()))
print(X)

84939825309432908832902189.9092309409809091329
84939825309432916635287552
.....................^^^^^
```
AC× 7
WA× 9

math.floorで15桁以上の小数点以下を切り捨てると結果がずれてしまいました。

###解説を見てみる

>以下のように処理すればよいです。

* Xを文字列として受け取る
* Xに小数点が入っているならば、小数点の手前までを出力する
* Xに小数点が入っていないならば、
* Xをそのまま出力する

```
x = input()
dot_pos = x.find('.')
if dot_pos != -1 : x = x[:dot_pos]
print(x)

84939825309432908832902189849398253094329088329021898493982530943290883290218984939825309432908832902189.84939825309432901292309277877514273172978081784495635302598639373471485769315252334956113938585682444288
84939825309432908832902189849398253094329088329021898493982530943290883290218984939825309432908832902189
```

なるほど。問題はクリアできました。

なぜmath.floorだとエラーになるのでしょう？

###質問してみました。

[Python 3.x - math.floorで15桁以上の数の小数点を切り捨てると何だか変｜teratail](https://teratail.com/questions/329198?whotofollow=)

> ベストアンサー
>Pythonのfloatは、CPUのサポートする倍精度浮動小数点数ですが、普通は、有効桁数は2進数で53桁、10進換算で約15.9桁（53 × log2 ≒ 53 × 0.3010）です。
>
>つまり、16桁目以降の数字はゴミです。

なるほど。
約15.9桁までしか扱えないので、16桁以降がしっちゃかめっちゃかになるようです。
簡単な Deb パッケージの作成

次のページと同様のことを行いました。
[[メモ] 最小限の手間で、debパッケージ作成 (非推奨)](https://qiita.com/mt08/items/fe0df6faa06a6aab14f9)

ソースコード

```text
$ tree hellodeb_1.0-1_amd64
hellodeb_1.0-1_amd64
├── DEBIAN
│   ├── changelog
│   ├── control
│   ├── copyright
│   └── rules
└── usr
    └── local
        └── bin
            └── hellodeb.sh
```

作成する必要のあるファイルは、control と hellodeb.sh です。
changelog copyright rules は空です。

>```text
$ ls -al hellodeb_1.0-1_amd64/DEBIAN/
合計 12
drwxrwxr-x 2 uchida uchida 4096  3月 26 13:19 .
drwxrwxr-x 4 uchida uchida 4096  3月 26 13:15 ..
-rw-rw-r-- 1 uchida uchida    0  3月 26 13:12 changelog
-rw-rw-r-- 1 uchida uchida   98  3月 26 13:19 control
-rw-rw-r-- 1 uchida uchida    0  3月 26 13:12 copyright
-rw-rw-r-- 1 uchida uchida    0  3月 26 13:12 rules
```

```text:hellodeb_1.0-1_amd64/DEBIAN/control
Package: hellodeb
Version: 1.0.1
Architecture: all
Maintainer: ekzemplaro
Description: Hello Deb!
```

```bash:hellodeb_1.0-1_amd64/usr/local/bin/hellodeb.sh
#! /bin/bash
#
echo 'Hello Everybody!'
echo 'Mar/26/2021'
```

パッケージの作成

```bash
dpkg-deb --build hellodeb_1.0-1_amd64
```

hellodeb_1.0-1_amd64.deb というファイルができます。

パッケージのインストール

```bash
dpkg -i hellodeb_1.0-1_amd64.deb
```

インストールされたプログラムを実行

```bash
/usr/local/bin/hellodeb.sh
```

実行結果

```text
$ /usr/local/bin/hellodeb.sh
Hello Everybody!
Mar/26/2021
```
width=autoと100％の違い

# width=autoと100％の違い

## 結論
paddingが指定されている時の挙動が違う

これが

![def.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495707/7c5b9c60-b859-c31a-0235-e21e396913dd.png)

こうなります

![autoVS100%.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495707/d6b8041b-8529-eef5-3877-812336cad38b.png)

width=100%にするとpadding指定したものがはみ出るので隣の要素に影響を出すことがあります

使い方に気をつけなければ、、、と思いました
Cloud Spanner の覚え書き

#はじめに
機会があり Spanner について調べたので、その覚え書き。

#Spanner とは
端的に Spanner を説明するなら、こんな感じ。

 - 分散データベースである
 - リレーショナルデータベースっぽい
 - ACID準拠のデータベースである
 - おおよそ、SQLデータベースって感じ
 - CAP定義でいうと、CP（CAは、99.999％の可用性を前提）

#既存RDBMS を Spanner へ移行するなら
Spanner 向けにシステム構築しないと扱うのは難しそうな感じ。
→ 既存のRDBMSを、気楽に載せ替えるっていうのは難しそう。

#Spanner のトランザクション管理
Oracle Database でいう SCN は、TrueTime（※複数リージョン間での時刻同期を実現できる）を使っている。
トランザクション動作は、@kumagi さんの [Spanner](https://qiita.com/kumagi/items/7dbb0e2a76484f6c522b) が分かりやすかった。Commit Wait を使ってデータ一貫性を保証している。


#感想
システムを「イチから作れるよ」というなら Spanner も選択肢に入るかな？
ただ現行のDB向けの仕組み（Frameworkとか）を用意しているものは、このあたりから作り直しになるため、やはり「現行(RDBMS)ものから Spanner へ」というのはハードルが高そう。
但し、「コレからシステム作る」、「新しい概念で作ってみたい」ということであれば採用を検討しても良さそう:thumbsup:

とはいえ「分散型DBの良さをあやかったRDB」には聞こえるのでキラキラしそうな Database(※) にみえちゃう:sparkling_heart:
(※)乱暴ですけど、CAP定義でいうなら分散型データベースなのに、全要件(一貫性、可用性、分断耐性)を満たす Database ってこと。

世界中のどこからでもデータを管理できちゃうってことだよなあ。これはキラキラしちゃう:blush: Spanner は、そこを目指すデータベースなのかも知れないなあ:sparkles:
GatsbyJSでgatsby-node.jsにcreatePagesをしたのにcontextの値がpropsされない時にやったこと

お題の通り、contextのプロパティに追加した値（プロパティもろとも）が渡せないことがありました。

## .cacheファイルを削除する
今のところこれが原因としてcontextに値が渡せないことが多かったです。
この一言のためだけに記事をこしらえたので、短すぎる記事になってしまいました。

ですがググっても出てこなかったので一応記事にして誰かの役に立てばと思います。基本的なことですがキャッシュを消すのは忘れがちになってしまいます（忘れていて同じことで２回ハマった）

おそらく毎回develop時にページ生成せずに早く立ち上げできるようにキャッシュにログが残っているんだと思います。

## 再起動する
これも基本の基本ではあるけれど忘れてる人もいるかもしれないので。
.cacheファイルを消したのにcontextで値を渡せない場合はVSCodeを使っているのであればファイルを再起動すると反映されるかもしれません。

短い記事になりましたが他にも詰まったことがこのトピックであれば追記します（もしくは教えてください）
Python基礎まとめ

## Python基礎まとめてみた
よくあるPythonの基礎をまとめました。
下記にソースコード貼っておきますので、
自分の言葉でどういうものか説明できるようにアウトプットしてみてください。(見づらいと思います💦)

もしくはコードをみて何を表現しているのか説明できるようにしてください！！
基礎を抑えたら応用、開発へ進みましょう！！

https://github.com/KozoNomamoto/Python_Learning/blob/main/pl.py.ipynb
Kotlinのタップで画面遷移、長押しでクリップボードにコピー

###タップでブラウザに画面遷移

```kotlin:click
  view.setOnItemClickListener() { parent, view, position, id ->
       var uri = "https://something"
       var intent = Intent(Intent.ACTION_VIEW, Uri.parse(uri))
       startActivity(intent)
       true
  }
```

###長押しでテキストコピー

```kotlin:longClick
   var clipboard: ClipboardManager = applicationContext.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
   view.setOnItemLongClickListener() { parent, view, position, id ->
       var copyText: String = view.getItemAtPosition(position) as String;
       var clipData = ClipData.newPlainText("コピーしたテキスト", copyText)
       clipboard.setPrimaryClip(clipData)
       var toastText = copyText + " " + "コピーしました"
       Toast.makeText(getApplicationContext(), toastText, Toast.LENGTH_SHORT).show();
       true
   }
```
Azure Stack

#背景
- 「OpenShiftはオンプレでもクラウドでも良いけど、EKS, AKS, GKEはどうなの」に応えるべくOutposts, Anthosと調べていた
- Azure Stackはあまり情報がなく大変


#調べたこと
- Azure StackはいまはAzure Stackサービス群になり、Azure Stack Hubが後継（Edge, HCIは別物）
- Azureの一部機能をオンプレで利用できる
  - Security Group
  - Load Balancer
  - Table Storage
  - Blob
- オンプレネットワークとの接続はVPN経由
- Azure StackはAzureのアプライアンスで内部を触ることはできない
  - 内部はMSエンジニアが海外からサポート
  - なにかインストールしたりはできない
- ユーザーが実施するAzure Stackの運用
  - キャパシティ管理
    - 増設は16台まで、それ以上は新しいAzure Stackを買う（別環境）
  - 監視
  - 障害対応
    - ログを送ってMSに依頼する（海外のタイムゾーンで）
  - バックアップ
  - パッチ適用・アップデート

#提供サービス
- Compute
- ストレージ
- ネットワーク
- Key Vault
- App Service
- Azure Functions
- SQL および MySQL データベース
- Event Hubs

#提供サービス（プレビュー）
- IoT Hub
- Kubernetes


#QA

Q. パブリックのAzureポータルから操作する？
A. No. Azure Stack Hub固有のポータル（ユーザー用、管理用）を構築・利用する。

https://docs.microsoft.com/ja-jp/azure-stack/user/azure-stack-use-portal?view=azs-2008




#参考
https://speakerdeck.com/kongou_ae/ganbareazure-stack

https://speakerdeck.com/kongou_ae/nareru-azure-stack-operator

https://speakerdeck.com/kongou_ae/10-things-i-learned-after-installing-azure-stack-hub-1cd823f9-7ce9-44c0-881a-56d49f5772f6

https://speakerdeck.com/kongou_ae/review-of-azure-stack-hub-in-2020
【備忘録】Linuxコマンド


#目的

自分の書いた記事に自身が助けられる事があったので、備忘録としてアウトプットしておく。


#pwd
今いるディレクトリの確認(print working directory)


#cd
ディレクトリを移動するコマンド(change directory)
**cd 移動先ディレクトリ名**



#ls
ディレクトリの中身を確認する。

> -a 隠しファイルも表示する
> -l 詳細な情報も表示する
> —help 使えるオプションを表示してくれる

**ls -la**
隠しファイル等を含めて、詳細な情報を表示する。


#touch
ファイルを作成する。(本来はファイルの更新日時を更新するもの)

**touch ファイル名**
ファイル名が存在しなければ新規作成してくれる。


#mkdir
ディレクトリを作成する。

**mkdir ディレクトリ名**


#cp
コピー(copy)を実施する。

**cp コピー元のファイル名 コピー先のファイル名**


#mv

ファイル名の変更
**mv 変更元のファイル名 変更後のファイル名**

ファイルの移動
**mv 移動するファイル名 移動先のディレクトリ名**


#rm
削除する(remove)。

ファイルを削除する。
**rm 削除したいファイル名**

①ディレクトリを削除する。
**rmdir 削除したいディレクトリ名**
> ただし、削除したいディレクトリ内にファイルが存在する時は実行出来ない。
> 削除対象ディレクトリ内を全て削除しておく必要がある。

②ディレクトリを削除する。
**rm -rf 削除したいディレクトリ名**
ディレクトリ内にファイルがあっても強制的に削除することが出来る。

#入力中のあれこれ

行頭へ移動
**control + a**

行末へ移動
**control + e**

行頭まで削除
**control + u**

行末まで削除
**control + k**

入力中のコマンドをやめたい時
**control + c**

画面全体を一旦クリアしたい時
**clear**
**control + l**


#history
今まで実行したコマンドの履歴を見る。

```terminal:
$ history

  507  ls
  508  pwd
  509  ls
  510  cd Desktop/
  511  ls
  512  ls
  513  ls -a
  514  ls -al
  515  ls -l
  516  ls -a
  517  man ls
  518  echo $PATH
  519  history
```

##履歴の中から実行したい時
**!番号**

```terminal
$!511
```
で実行すると、**ls**が実行される。


#cat

ファイルの内容を表示する。
**cat test.txt**

> -n 行番号も一緒に出力する。

#more

ファイルの内容をページ単位で表示する。
**more test.txt**

> spaceキー、fキーで次のページを表示。
> bキーで前のページを表示。
> qキーで終了。

#less
ファイルの内容をページ単位で表示する。
**less test.txt**

> spaceキー、fキーで次のページを表示。
> bキーで前のページを表示。
> qキーで終了。
> /検索文字列 で検索が可能。nキーで次にヒットした文字列に移動。



#随時更新予定...
自分用メモ: reg-suit + s3 + cloudfront + lambdaの構成ではaclとcustomDomainをちゃんと設定しよう

reg-suit + s3 + cloudfront + lambdaで画像比較の資料全てに認証を必要としたい時のメモ

[ドキュメントに書いてある](https://github.com/reg-viz/reg-suit/blob/master/packages/reg-publish-s3-plugin/README.md#configure)んだけど、reg-publish-s3-pluginのデフォルトだとaclがpublic-readでputしようとする. [ソースコード](https://github.com/reg-viz/reg-suit/blob/cfb155bb75814eea096e52911a48c8cf78257589/packages/reg-publish-s3-plugin/src/s3-publisher-plugin.ts#L88)
この状態でreg-suitを走らせようとすると、ポリシーを先程の構成に最適化したS3だとpublic-readでのputは当たり前なんだけど、拒否される.
この際のaws sdkのエラーメッセージはAccessDeniedになり、設定したregionもnullになる.
このエラーは以下の様に正しくaclとcustomDomainを追加することにより解消される.

```diff_json:regconfig.json
{
  "core": {
    "workingDir": ".reg",
    "actualDir": "__actual_images__",
    "thresholdRate": 0,
    "addIgnore": true,
    "ximgdiff": {
      "invocationType": "client"
    }
  },
  "plugins": {
    "reg-keygen-git-hash-plugin": {
      "expectedType": "base-commit"
    },
    "reg-notify-github-plugin": {
      "prComment": true,
      "prCommentBehavior": "default",
      "clientId": "your_client_id"
    },
    "reg-publish-s3-plugin": {
      "bucketName": "bucket_name",
+     "acl": "private",
+     "customDomain": "your_domain"
    }
  }
}
```
Jekyllでタイムゾーンを設定する話

# Jekyllでタイムゾーンを設定する話

## 目標

JekyllとGitHub Pagesを利用して運営しているサイトのタイムゾーンを日本に設定する

## 問題

朝ブログを投稿しようとしたところ、Pushしても反応がなかった。しかしActivity logを見る限りではちゃんとdeployされてる。

## 原因

Jekyllには未来の日時のページはサイトに反映させないという仕組みがあるため。またデフォルトではその判定をGMTを基準にしているため。つまり日付を1/1日にして 午前8時に投稿したとしても、GMTでは12/31 午後11時なので日付が未来になっているということで反映されない

## 解決策

_config.ymlにタイムゾーンを記載する。

```yml:_config.yml
timezone: Asia/Tokyo
```

## おしまい

おしまいです。
自分用メモ: SQLの勉強 (途中

[SQL99](https://ja.wikipedia.org/wiki/SQL#%E6%A8%99%E6%BA%96SQL%E8%A6%8F%E6%A0%BC)で[OLAP](https://ja.wikipedia.org/wiki/OLAP)が仕様に追加されたらしい

window function(分析関数)はOLAPの考えで実装されたモデルの上で作用するように作られてるのかな？
OLAPからはかなり深いものが見えたので、sqliteのwindow functionの実装を見てみる
偏見だが、sum関数が一番読むの楽そう

[sum関数の定義](https://github.com/sqlite/sqlite/blob/33941691a526dfc19c3f5a4de39864800a3a9cd9/src/func.c#L2200)を見ると、以下の要素からsum関数は作られている事がわかった

* [sumStep](https://github.com/sqlite/sqlite/blob/33941691a526dfc19c3f5a4de39864800a3a9cd9/src/func.c#L1527)
* [sumFinalize](https://github.com/sqlite/sqlite/blob/33941691a526dfc19c3f5a4de39864800a3a9cd9/src/func.c#L1574)
* [sumInverse](https://github.com/sqlite/sqlite/blob/33941691a526dfc19c3f5a4de39864800a3a9cd9/src/func.c#L1549)

これらの関数は、total, avl, count関数でも使われていた
つまり、sqliteのwindow functionはプリミティブな構成要素を定義し、それを用いて構築されているみたい
ちなみにWAGGREGATEマクロは、W + AGGREGATEの略称ぽい (Wはwindowの略

マクロの状態でコードを読むの結構大変なので、続きはプリプロセッサだけを動かしてマクロを展開した状態でsum等の集計関数をどの様な場所で利用しているかのコードを読み進めて、SQLの理解を進めて見ようと思う.
⇒踏み台 on Azure⇒(VPN)⇒リモートホスト on AWSを実現する設定内容

## やりたいこと
Azureにある踏み台サーバとSite-to-Site VPN経由でAWSにあるリモートホストに接続する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481044/59aaa0b1-424c-215a-990f-61de40af4cfa.png)

## 設定内容
### Azure
**VNETピアリング**
Azure VNET"10.30.0.0/16"⇒VNET"10.20.0.0/16"のピアリング設定
赤枠の設定でAzure VNET"10.20.0.0/16"のVirtual Network Gatewayを使用するようにする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481044/b91ba219-7356-338b-057f-8bc3ea8cb7dc.png)
逆方向のAzure VNET"10.30.0.0/16"←VNET"10.20.0.0/16"にも同様に設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481044/d2f35cb0-e621-01bb-20a0-668496da5300.png)

**Virtual Network Gateway**
通常の手順でAWSのVPN Gatewayと接続設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481044/5ca6aab1-fc35-228f-2d09-b55ee1bdbaf7.png)

### AWS
**VPN Gateway**
通常の手順でAzureのVirtual Network Gatewayと接続設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481044/4da1bc17-f0c9-600c-6c6a-9929d60955c0.png)
静的ルートはAzure VNET"10.30.0.0/16"を設定する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481044/d1a940cc-1cfc-43e0-4b25-04109ab5bee3.png)

**ルートテーブル**
リモートホストが属するAWS VPN"10.10.0.0/16"のプライベートサブネットにアタッチされているルートテーブルの設定
送信先をAzure VNET"10.30.0.0/16"とし、ターゲットに上記VPN Gatewayを設定する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481044/2df3338e-fe5d-31e4-14c3-4b58923d59e7.png)

**セキュリティグループ**
リモートホストにアタッチされているセキュリティグループのインバウンドルール設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481044/5a8a7c05-1fee-f86f-71c8-0e914cf63e9d.png)

## 接続確認
```bash:bash_or_powershell
# ローカルクライアントから踏み台に接続してポートフォワード設定
ssh azureuser@<踏み台サーバのパブリックIP> -L 10022:10.10.0.128:22 -N

# ローカルクライアントでもう一つターミナルを開いてリモートホストに接続
ssh ec2-user@localhost -i <リモートホストの秘密鍵のパス> -p 10022
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481044/e37be148-5daf-0dd0-8a1c-eefcd109e07c.png)
Rubyでボーナスドリンク問題のコードを書く

##はじめに
この記事は以下のサイトにあった問題を解いてみたものです。Rubyのアウトプットを目的として作成しました。
[アウトプットのネタに困ったらこれ！？Ruby初心者向けのプログラミング問題を集めてみた（全10問）]
(https://blog.jnito.com/entry/2019/05/03/121235)

##問題

上記記事より引用。
>「ある駄菓子屋で飲み物を買うと、空き瓶3本で新しい飲み物を1本プレゼントしてくれる。最初に100本購入した場合、トータルで何本飲めるか」という小学校3年生の算数の問題をベースにしたプログラミング問題です。
>
| 購入した本数  |   飲める本数       |
|:----------:|:----------------:|
| 0           |         0       |
| 1           |         1       |
| 3           |         4       |
| 11          |        16       |
| 100         |(プログラムで算出する)|

## コード

```ruby
def drink_count(num)
  if num % 2 == 0
  sum = num + (num - 2) / 2
  else num % 2 != 0
  sum = num + (num - 1) / 2
  end
  puts sum
end

drink_count(100)
```

##考え方
小学3年生の算数の問題をベースにしているらしいので、元の数と飲める本数の数の法則を導いて、それをプログラムに落とし込むことにしました。

### 偶数の時
まず、ドリンクが100本ある場合を考えます。そのうち3本を飲むと、3本空き瓶ができるので1本ドリンクが増えます。結果98本になります。
ドリンクが98本ある時、そのうち3本飲むと同様に3本の空き瓶ができるので1本ドリンクが増えます。結果96本になります。
ドリンクが96本ある時、そのうち3本飲むと同様に3本の空き瓶ができるので1本ドリンクが増えます。結果94本になります。
この思考を繰り返すと、ドリンクが2本になるまで、"ドリンクを3本飲んだら飲める本数が1本増える"事象が起こります。この事象で減る本数は2本で、飲める本数は1本増えます。
つまり飲める本数は、残り2本になるまで"元の数から2本減るごとに1本増える"と言うことが言えるかと思います。

ここで、何本飲める本数が増えたかを考えます。元の数から2本に減るまでに、2本減るごとに1本増えているのですから、元の数から2を引いたものを2で割れば何回増えたか求められそうです。

増えた本数　＝　(元の本数 - 2) / 2
　　　　　　＝　(100-2) / 2　＝　49

これを元の本数に足してやれば、合計の飲める本数が求められます。

合計　＝　元の本数　＋　増えた本数
　　　＝　100 + 49　＝　149

偶数の時に関しては、上記の式の元の本数のところにそれぞれの場合の数を当てはめればこれで求められそうです。

### 奇数の時
次に奇数の時について考えました。

仮に99本が元の本数だったとすると、100本の時と同様の考え方で、飲める本数は"元の数から2本減るごとに1本増える"と言うことが言えるかと思います。これは飲める本数が1本になるまで続きます。

ここで、何本飲める本数が増えたかを考えます。元の数から1本に減るまでに、2本減るごとに1本増えているのですから、元の数から1を引いたものを2で割れば何回増えたか求められそうです。

増えた本数　＝　(元の本数 - 1) / 2
　　　　　　＝　(99 - 1) / 2　＝　49

これを元の本数に足してやれば、合計の飲める本数が求められます。

合計　＝　元の本数　＋　増えた本数
　　　＝　99 + 49　＝　148

これらをコードに落とし込みます。

```ruby
def drink_count(num)
  if num % 2 == 0
  sum = num + (num - 2) / 2
  else num % 2 != 0
  sum = num + (num - 1) / 2
  end
  puts sum
end
```
## 感想、まとめ
100本の時と99本の時の増えた本数が同じなので、そこをうまくプログラムで表現できればもっと短いコードになりそうに感じます。
【AWS】受講予定の2021年 AWS Summit Online

自分用メモ

# AWS Summit Online
オンラインでお家にいながら**タダ**でAWSに詳しくなれるイベントが今年も開催されるらしいのでさっそく登録しました。

https://aws.amazon.com/jp/events/summits/online/japan/

AWSのオンラインカンファレンスはいつも平日ですね。


# Topics
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1203022/b28bef4c-d4b0-4543-f7aa-05fc92557f71.png)

AWSの技術者による技術トークは気になりますね。
実際に操作しているところを見るデモも見てみようと思います。

# セッション
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1203022/c4bfb33a-d930-dc81-a959-d2cbcfd07733.png)

事例セッションが面白そう。
何セッションか受けてみるつもりです。


質の高いオンラインカンファレンスが受けられるのはAWSの特徴だと思うので今から楽しみです。
ブラウザに表示させるための処理周辺の知識

#本記事について
プログラミング初心者がブラウザに表示させるための処理に関する知識について学んだので、その備忘録として載せております。

どうかお手柔らかにお願いいたしますm (- -)(_ _)ペコリ


##処理の概要
・サーバーサイドで色々な言語で記述されたとしても、HTML、CSS、JavaScript等となってブラウザに返される。

・最終的にHTML、CSS、JavaScript等の言語へ変換されていなければブラウザはページを描画できない。

→ブラウザで認識できる言語がHTML、CSS、JavaScript、WevAssmby

##高級言語
・機械よりも人間が理解しやすいように設計されたプログラミング言語

・開発者が開発しやすいように設計
→高級言語は便利であるが、これらは動作する機械が認識できるように通常より多く翻訳する必要がある。

##低級言語
・機械が認識しやすい言語

##コンパイル
・翻訳作業（人間の言葉で書いたコードをコンピュータがわかる言葉に翻訳）

・コンパイラというプログラムによりコンパイル（翻訳）は行われる。

##プリコンパイル
・コンパイラが翻訳できない言葉を翻訳できるようにする事前コンパイルのこと。

・メインとなる処理に対して必要な前処理のこと。
→コンパイラにもコンパイルできる範囲があり、事前処理が必要になることもある。

・ブラウザに渡す静的ファイルはプリコンパイルする必要がある。

##アセットパイプライン
・プリコンパイルを行う手法。

・プリコンパイル、連結、圧縮、配置を行う仕組み

・JavaScriptやCSSなど（のアセット呼ばれる静的ファイル）を小さくまとめてくれる機能

・高級言語のプリコンパイルを行う機能も追加できる。

##静的
最初から用意しておいて途中で変わらない。

##動的
最初からあるけど途中で変わったりする。

##モジュール
機能を１つずつわけて他のファイルから読み込めるようにした処理のまとまり

##システムの構成要素、交換可能な構成単位
・プログラミングの１パーツで、これだけでは機能しない。

・部品の意味で用いられるモジュールはそれだけで機能として成立する。

##モジュールバンドラ
・JavaScriptのモジュールの依存関係を考慮しながら管理するツール

・モジュールの依存関係を解決しながら機能を一つにまとめる。

・Node.js環境では機能をモジュールという単位で扱う。

・モジュールパンドラによってJavaScriptのライブラリ機能を複数組み合わせれる。

・JavaScriptは複数の機能をファイルごとに分割すると、１つのファイルへまとめる際に不具合が生じるためモジュール単位で扱う。

・モジュールにより大量の機能を複数のファイルに分けることができ、分けられて機能を１つにまとめても問題なく動作できる。しかし複数に分かれるため依存関係が生じる問題がある。
→依存関係の問題を解決するのがモジュールバンドラ。モジュールをまとめて束ね管理できる。

##webpack
・モジュールバンドラの一つ。JavaScriptを一まとめに管理するためのツール。JavaScriptの依存関係を束ねてくれる。

・webackが実行すること

・JavaScriptのライブラリとJavaScript以外の様々な言語を、変換、圧縮した上で好きな場所に配置できる。

##Webpacker
・webpackをRails仕様にしたもの。専用の設定ファイルやヘルパーメソッドを用意するGem。

・Railsにもwebpackを導入できるが、設定ファイルの記述が難しくなっている。設定を簡略化してくれるのはWebpacker。

##jQuery
JavaScriptでできることを、より簡単な記法で実現できるように設計されているJavaScriptのライブラリ。


以上です
[Linux] 全体のディスク使用量収集コマンド

## はじめに

まず、全体の使用量を知るためには、dfコマンドを覚えなければなりません。 もちろん、システムエンジニアの方はご存知だと思いますが、短くご説明いたします。

df コマンドは、"Disk Free"の略であり、現在使用中のファイルシステムの全体の大きさ、使用可能な大きさ、使用率、マウント情報などを示している。

開発者であれエンジニアであれ、Linuxで作業を行う場合には、File System Fullによるシステム障害を防止するためには、周期的なファイルシステム使用量点検が必要です。

本論に入って全体の使用量を知るためには、ファイルシステム別に分かれた容量を合わせていかなければなりません。

(dfコマンドをそのまま使う場合、ファイルシステム名が長い場合は次の行に移して出力するため、-Pオプションを与える。)
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619610/767e2894-073d-6a09-909a-f9f87606ad6c.png)

## 全容量

### KB単位

``` sh
df -P | grep -v ^Filesystem | awk '{sum += $2} END { print sum " KB" }'
```
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619610/e7de65ed-9ff0-1bf5-b190-da0110ca2825.png)


### GB単位

``` sh
df -P | grep -v ^Filesystem | awk '{sum += $2} END { print sum/1024/1024 " GB" }'
```
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619610/817ccfd5-6b0b-cf44-274e-eb28f7375967.png)


## 使用量

### KB単位

``` sh
df -P | grep -v ^Filesystem | awk '{sum += $3} END { print sum " KB" }'
```
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619610/1161406a-5b14-cd7d-387b-ee988eedcfd3.png)


### GB単位

``` sh
df -P | grep -v ^Filesystem | awk '{sum += $3} END { print sum/1024/1024 " GB" }'
```
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619610/5f59032c-a1f8-9b45-521a-ac378995b6d4.png)


## 残量

### KB単位

``` sh
df -P | grep -v ^Filesystem | awk '{sum += $4} END { print sum " KB" }'
```
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619610/d783c647-58d1-05cd-7b11-542b21108de3.png)


### GB単位

``` sh
df -P | grep -v ^Filesystem | awk '{sum += $4} END { print sum/1024/1024 " GB" }'
```
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619610/76241939-eba9-c8a5-d0d5-b6bbe36d867e.png)
[MySQL] DBクエリー検索結果をCSVファイルですぐに抽出する方法


# はじめに

DBでクエリー検索結果をCSV ファイルとして取得するときには、2つの方法がある。
DBの中からクエリーをすぐに入力して抽出することもでき、コンソールでコマンドとして抽出する方法もある。

DBがあるサーバーと同じサーバーにファイルを抽出しようとする場合、前者と後者の方法をすべて適用可能であるが、DBサーバーを別々に運用している場合は、1の方法は使用できない。 ファイルが接続サーバ側ではなく、DB側サーバに生成されるだろうからである。

単純にバックアップ目的のEXPORTなら、mysqldumpでエクスポートする方が簡単だ。

## DB内からクエリとしてCSVを抽出する方法

``` sh
SELECT col1, col2, col3 FROM MY TABLE
INTO OUTFILE '~/20190101.csv'
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n';
```

## コンソールコマンドでDBからCSVを抽出する方法

``` sh
mysql -u$USER -p$PASSWORD -D$DATABASE -e "select * from mytable" | tr '\t' ',' > '~/20190101.csv'
```
[REST API] REST APIに関する6つの制約条件


# はじめに

RESTとはRepresentational State Transferの略で、この用語はロイフィールディングによって作られました。 RESTというのはWebサービスでよく使われ、Applicationとの間の結合度を下げるように設計するアーキテクチャスタイルです。 結合度を下げてサーバクライアントが別途に構築され、結合されるようにします。

アーキテクチャ的な結合度を下げるためにRESTは上記の6つの制約条件を備えています。 こうした制約条件をきちんと守れば、このシステムはRESTfulなシステムになるのです。

今日は、それぞれについて簡単に説明したいと思います。

## Client-Server

ユーザに提供するinterfaceであるUser Interfaceとデータストレージ、アルゴリズムなど、サーバ内部の作業を分離することで、User Interfaceは様々なプラットフォームでの移植性を向上させることができ、サーバはその構成要素を単純化して拡張性を単純化できます。
クライアントとサーバが互いに依存することなく、別途に進化することができます。 クライアントはサーバのリソースURIを知っていればいいからです。

## Stateless

クライアントからサーバへの各要請には、その要請を理解するために必要なすべての情報が含まれなければなりません。 サーバに保存された環境情報を利用して利得[サーバ内のクライアント情報の維持など]を取ってはいけません。 したがって、セッション情報は全てクライアントが持っていなければなりません。
ログインしたというセッションの維持が必要なら、その情報もクライアントが当該情報を持ってサーバーに伝達しなければならない。 [ex) JWT等を使用]

## Cacheable

要請に対する応答内のデータに該当する要請がキャッシュに可能であるかどうかを明示しなければなりません。 応答をキャッシュできるなら、クライアントから同じ要請が来たときに応答データを再利用できるようにしてください。
cache-controlヘッダーでキャッシュの有無を明示する。

## Uniform Interface

全体的なシステム·アーキテクチャを簡単かつよく把握できるようにするための約束されたInterface、当該規約をRESTをユーザが守ることで、後に使用するクライアントを開発するユーザとサーバーを開発するユーザとの結合度が低くなる可能性がある（Decoupling）。 開発RESTは規約で4つを示します。
identification of resources
manipulation of resources through representations
self-descriptive messages
hypermedia as the engine of application state.

## Layered System

階層化されたシステム·アーキテクチャを使用して各構成間の階層を自由に相互作用できないように制限することで、Interfaceを一元化できます。

## Code on demand (optional)

サーバがネットワークを通じてクライアントに伝達したjavascriptなどのプログラムは、それ自体で実行されなければならない。 このことは、事前実装に必要な機能の数を減らすことでクライアントを単純化します。
この言葉は、普段は静的なデータをxmlまたはjsonに入れてclientに送り、clientがこれを加工します。 ですが、code on demandとは、clientに送るデータをすぐに実行可能なコードを送ってClientで実行することです。
Bootstrap導入の流れ１

Bootstrapは有名なWebフレームワークで、CSSを細かく指定せずにサイトをある程度形にできる。レスポンシブにも対応してくれる便利なツール。Bootstrapを導入するとWebアプリケーションを効率よく開発できる。

①　gem 'webpacker', '~> 4.0'　（※既に記述あり）

②　jQueryとBootstrapを導入
　　% yarn add jquery bootstrap popper.js

③　package.json に
　　"bootstrap": "^4.5.3",
    "jquery": "^3.5.1",
    "popper.js": "^1.16.1",　を記述。

④　config/webpack/environment.js　に
　　const webpack = require('webpack')
  environment.plugins.append(
    'Provide',
    new webpack.ProvidePlugin({
      $: 'jquery',
      jQuery: 'jquery',
      Popper: ['popper.js', 'default']
    })
  )
　　を追加記述。

⑤　app/javascript/stylesheets/application.scss　に
　　
　　@import '~bootstrap/scss/bootstrap';　を記述。

⑥　app/javascript/packs/application.js　に

　　import 'bootstrap';
  　　import '../stylesheets/application';　を一番上に記述。

⑦　app/views/layouts/application.html.erb　に
　　<%= stylesheet_pack_tag 'application', 'data-turbolinks-track': 　　　　　　　　　　'reload' %>　を追加
Djangoでゲームを作る


#背景
学びのためにDjangoでゲームを作ってみることにする。
テトリスなど色々候補はあると思うがスロットゲームにすることにする。
#モヤモヤ
Djangoと言ったってRestもあるし・・・画面も面倒だし・・・
どうしたって業務・即戦力がきになる・・・オシャレなこともしたいし・・・
→　データアクセスがどっちも1つの山なんでデータベースから取ってきて
JSONで投入するという一旦完璧を目指す。
この時に、スクレイピングとかデータ解析などもやってしまう。
#考えないこと
DjangoRest
#ロードマップ　作り物系
・公式やってみる。
・toDoリスト作ってみる
・ゲーム作ってみる
　　　　→　今ここ
・データベースから取ってきて管理画面だけのを作ってみる。
　→JSONでデータ投入
#仕様
・スロットマシン
・初期表示　4　が3枚並んでいる。
・ボタンを押すとランダム検索が起こる。
・スロットの絵柄と得点　例
6　３個揃うと　10000点　
7　３個揃うと　　7000点
5　３個揃うと　300点 
・結果を表示する。
・Python3 Djangoを使用
#やって見て
もちろんやって見てよかったと思う。
やりすぎない感じで練習できたらと思う。
他の人のソースも参考にしたほうがいいと思う。




#ソースコード
```py
from django.http import HttpResponse
from django.shortcuts import render


def index(request):
    return HttpResponse("Hello, world. You're at the polls index.")

def card(request):

    import random
    word = ''
    suits = ['S', 'H', 'D', 'C']
    ranks = range(4, 8)
    deck = [(x, y) for x in ranks for y in suits]
    if request.method == 'GET':
        dictionary = {
            'suit': 'C',
            'rank': '04',
            'suit2': 'D',
            'rank2': '04',
            'suit3': 'C',
            'rank3': '04',
             'word': word
        }

    elif request.method == 'POST':
        random.shuffle(deck)
        card1 = deck.pop()
        card2 = deck.pop()
        card3 = deck.pop()

        if card1[0] == 6 and card2[0] == 6 and card3[0] == 6:
            word = "scoreは10000点です"
        elif card1[0] == 7 and card2[0] == 7 and card3[0] == 7:
            word = "scoreは7000点です"
        elif card1[0] == 5 and card2[0] == 5 and card3[0] == 5:
            word = "scoreは300点です"

        dictionary = {
            'suit' : card1[1],
            'rank' : str(card1[0]).zfill(2),
            'suit2' : card2[1],
            'rank2' : str(card2[0]).zfill(2),
            'suit3': card3[1],
            'rank3': str(card3[0]).zfill(2),
            'word': word,
        }

    return render(request, 'card.html', dictionary)

{% load static %}
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>トランプ</title>
</head>
<body>
    {%static "cards/" as card_path %}
    <img src="{{card_path}}{{ suit }}_{{rank}}.png">
    <img src="{{card_path}}{{ suit2 }}_{{rank2}}.png">
    <img src="{{card_path}}{{ suit3 }}_{{rank3}}.png">
<form action="" method="post">
{% csrf_token %}
    <input type="submit" value="送信">
</form>
{{ word }}
</body>
</html>

```

![スクリーンショット 2021-03-26 16.07.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271383/21f31802-ef68-d3f5-5d94-3fc9651cbbff.png)
Kotlinで◯日前という表記をスマートに実装

#Kotlinで時間差を表示したい
Twitterなどで見る、「◯時間前」とか「◯日前」などの表記を簡単に実装したいと思います。
ちなみにこの方法なら、スマホの言語設定に合わせて勝手にローカライズされ、「◯ days ago」といった表記に変わりますので、配信する地域を気にせず使えます。

```Kotlin
var hoge = DateUtils.getRelativeTimeSpanString(指定時刻のミリ秒, 現在時刻のミリ秒, 0)
```
で◯日前、◯時間前といった表記を取得できます。

##現在時刻のミリ秒を取得
ちなみに現在時刻のミリ秒は下記で取得します。

```Kotlin
val now_milisec = System.currentTimeMillis()
```
Herokuにデプロイしたら500 Server Errorが出た

Herokuでデプロイをしたときにエラーに遭遇したので備忘録のために残します。


## 500ServerError

このエラーの原因は様々あるみたい？で原因究明が難しいという記事が多かったです。
Webサーバー側に何らかの問題が発生しているとのこと。

今回、私が作成しているのがLaravelのアプリケーションなのですが同じようなエラーでアプリ作成直後に500Errorが出ている方のエラーは`.envが存在しないから`というものが多かったのですが、私の場合はデプロイ後のエラーなので違うよなーと思いつつ。

でも原因は同じ.env系では？と思いながらググって探していたらありました。

[LaravelをHerokuにデプロイするまでに最低限やる事。](https://mrkmyki.com/laravel%E3%82%92heroku%E3%81%AB%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4%E3%81%99%E3%82%8B%E3%80%82)

上記の記事では

>Laravelの.env はgit管理外なので、Heroku用の.env.heroku を用意しておき、デプロイの際にHerokuサーバー内で.env.heroku を.env にコピーするようにします

とあり、さらに`composer.json`に追記しないと500エラーが出るよとのことでした。

私は公式の通りにアプリを作成したのですが、元々`.env.example`というファイルが存在していたのでこちらを利用し、composer.jsonに追記しました。


```PHP:composer.json
"scripts": {
        "post-autoload-dump": [
            "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
            "@php artisan package:discover --ansi"
        ],
        "post-root-package-install": [
            "@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
        ],
        "post-create-project-cmd": [
            "@php artisan key:generate --ansi"
        ],

//以下を追加
        "compile": [
            "@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
        ]
    }
```

こちらで解決できました！
ありがとうござます！
なぜReactが好きなのか答えられない人へ

**あるいは、なぜVue.jsが好きなのか答えられない人へ**
**あるいは、なぜAngularが好きなのか答えられない人へ**

そんな初心者の方への記事です。

## Reactが好き

僕はReactが好きでReactを使っています。
でも、Vue.jsが好きでVue.jsを使っている人もいますし、Angularが好きでAngularを使っている人もいます。
下記は僕が「Reactが好きな理由」を聞かれるときに、頭の中で思い浮かべているマトリックスです。

|  | ライブラリ | フレームワーク |
|:---|:---:|:---:|
| HTMLベース | Vue.js | Angular |
| JavaScriptベース | React |  |

僕の「Reactが好きな理由」はJavaScriptベースでUIが記述でき、アプリケーションにおけるライブラリ構成を独自にカスタムしていける点です。

## HTMLベース or JavaScriptベース - UIをどう記述するか？

HTMLベースというと正確ではないため、Templateベースと言いかえたほうが良いかもしれません。
しかし、HTMLベースと言った方が伝わりやすいかなと思いました。

アプリケーションのコードはビルドすることでJavaScriptのバンドルファイルとしてまとめられます。まとめられた後はみんな大して変わりません。
しかし、まとめる前のソースコードをトランスパイラがどのように解釈するのか？という点において、Vue.js/AngularとReactの間に相違点があります。

Vue.js/Angularでは、アプリケーションのUIとなる部分のコード(HTML)をTemplateとして記述し、処理の部分(Script)と分けて記述します。
このTemplate(HTML)と処理(Script)はそれぞれ別世界のものであるため、トランスパイラがUIと処理を紐づけるために仕事をします。

- HTMLの世界では属性の命名で大文字と小文字が区別されないのでケバブケース(hoge-key)をつかう
- JavaScriptの世界では大文字と小文字が区別され、基本的にキャメルケース(hogeKey)をつかう

これをトランスパイラがガッチャンコします。

一方、ReactではUIのコードも処理のコードも同じJavaScriptに記述します。JSXがそれです。
JSX内にかかれたHTML的なコードは、見た目はHTMLのようなものですがJavaScriptなので、宣言した処理とUIが直接紐づきます。

TypeScriptが流行するのと同時にReactのユーザが増えたのは、UIのコードもTypeScriptでカバーできるので、TypeScriptの恩恵を受けやすいというのもあったでしょう。

しかし、Vue.jsやAngularもいいと思います。

個人的な見解ですが、TemplateとScriptに分けて実装する方法は、従来のSSRによるアプリケーションの実装方法とイメージが近いんです。Ruby on Railsに代表されるような。
JavaにおけるJSPにおいてもそうであったと認識しています。僕がやっていたときはXMLベースでしたが、実装におけるパターンは一緒だといってよいのではないでしょうか。(PHPやPerlはあまりやったことがなくて語れません)
なので、従来のSSRにおけるアプリケーション開発をがっつりやってた人とかはVue.jsやAngularの方が何かとやりやすいと思ってるんです。

だから僕は、Reactしか勝たんとは思ってません。
解は人によると思います。

## ライブラリ or フレームワーク - アプリケーションの構成について

React/Vue.jsはUIライブラリです。一方、Angularはフレームワークです。
React/Vue.jsでは、ライブラリ本体がUIを実装するための最低限の内容で構成されています。なので、用途に合わせて姉妹ライブラリもインストールしていく必要があります。
Angularはフレームワークなので、はじめから色々なライブラリがいっぱい入っています。

好みの問題です。
node_modules配下は最小構成にしたい！ミニマリストだ！という人はReact/Vue.jsの方が合うかもしれません。
ライブラリ構成考えるのが手間！入れたらすぐ使いたい！という人はAngularの方が合うかもしれません。

僕はReactばっかり使ってますが、ライブラリのバージョンアップとかするときに対応関係がシビアになってくるのが少し手間だと感じるときもあります。Angularはその点、フレームワークとして吸収してくれるので楽なのかなって思ってたりします。

まあでも使わないモジュールがnode_modules配下にいたら、ちょっと気持ち悪く感じるのかな。コンテナ上でのインストール時間とかちょっと変わってくるのかもしれない。
まあでも、個人の趣味でいいのかもしれません。
僕はぶっちゃけ、この点についてはどっちでもいいかなと思ってます。

ちなみにですが、フレームワーク的ポジションとしてReactにはNext.jsがあり、Vue.jsにはNuxt.jsがあります。
両者ともそれぞれ本家ライブラリと別にAPIがありますので、ある程度のキャッチアップと慣れが必要な世界ではあります。

## まとめ

簡単にまとめると……

**好きな理由として言いやすいパターン**

- JavaScriptベースでUIが書けるからReactが好き
- TypeScriptをより生かせるからReactが好き
- 最小構成で作れるからReactが好き

**好きな理由としてちょっと微妙かもなパターン**

- 宣言的UIだからReactが好き ... Vue.js/Angularも宣言的UI
- 仮想DOMだからReactが好き ... Vue.js/Angularも仮想DOM


## チラ裏

React、Vue.js、Angularのどれがいいのかトークというのを何度も繰り返してきましたが、なんとなくよい気分にはならなかったのかもしれません。

つい３年程前まで僕はReactが一番格好良くて最高なんだ！と思い、他のライブラリはイケてない！と思い込んでました。時には他ライブラリを好んでいる方の前で得意気になったこともあります。この記事はそんな自分への罪滅ぼしでもあります。

すべてのエンジニアが自信をもって好きなものを語り合える、そんな未来に貢献できたらいいなと思って書きました。Thank you !!
JavaScriptでDropbox APIから読み込む



とりあえず動いた喜びとメモ帳書きとして


```html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>Dropbox Test</title>
    <script src="https://unpkg.com/dropbox/dist/Dropbox-sdk.min.js"></script>
</head>
<body>
<h1>DropBox Test</h1>
<script>
    let accessToken = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
    let dbx = new Dropbox.Dropbox({accessToken: accessToken});

    dbx.usersGetCurrentAccount()
        .then(function (response) {
            console.log(JSON.stringify(response, null, 4));
        })
        .catch(function (error) {
            console.error(error);
        });

    let dir_path = "/document"
    dbx.filesListFolder({path: dir_path})
        .then(function (response) {
            console.log(JSON.stringify(response, null, 4));
        })
        .catch(function (error) {
            console.error("error " + error);
        });
</script>
</body>
</html>
```


#参考
知識ゼロだけど、Dropbox APIを使用したい
https://qiita.com/Ella_Engelhardt/items/c33f08b6b427eab8b310
openwrtのSoftEtherVPNClientでguiのリモート管理を許可する方法

openwrtをsshでloginして
vpncmd  localhost  /CLIENT
VPN Client>RemoteEnable
これでおｋです
後はクライアント管理ツールをオプションを付けて実行。最後に/remoteを付ける。
"C:\Program Files\SoftEther VPN Client\vpncmgr_x64.exe" /remote
これでWindows側でかんたんに設定できるかと思います
keycloakのサイジング

2021/09/27:サイジングの基礎値でいいのを見つけたので、それをベースに修正しています。

本記事では、シングルサインオンのサイジング基礎値について記載します。

たとえば、1分間で2千人のユーザがログインする要件があったり、全体で10万人ログイン状態を維持しないといけないとかの場合、どれぐらいのCPUとメモリのリソースが必要かの感覚が掴んで貰えればいいかなと思います。

今回シングルサインオンで使うソフトウェアは、OSSのKeycloakです。
OSSのKeycloakの商用版が、Red Hat Single Sign-On(SSO)になります。
現時点のRed Hat SSOの最新版が7.4で、それに対応するKeycloakは9.0.12です。
今回は、１台構成でやってます。リクエストあれば、設定変えたり、クラスタ構成などでもやってみようかと思います。(ないかな:disappointed_relieved:)

＊:本記事は、あくまで執筆者の見解です。公式な内容ではありません。

## サイジング基礎値の項目
サイジング基礎値の項目は、以下の２つとします。

|項目  |対応するリソース  |補足  |
|---|---|---|
|最大同時実行数 |CPU  |1秒間で最大何人ログインできるか(待ちに入らずに)  |
|最大同時ログイン数  |メモリ  |最大何人ログインしっぱなしできるか  |

今回は、NWの帯域やDB周りなどは、見ませんので。

## 測定環境
課金を気にしながら、AWS上でやりました。
・EC2： r5.xlarge(vCPU:4,メモリ:32G)
・OS:Red Hat Enterprise Linux release 8.3 (Ootpa) 
・keycloakバージョン：9.0.12
・JDK:openjdk 1.8.0
・keycloakの設定:Standaloneでrealmを１個追加
・Javaのヒープサイズ：-Xms20G -Xmx20G

測定したあとに、もう少し安いインスタンスでよかったなと思いました。。

## メモリの測定
計測が面倒くさくなるため、強制FullGCを実行して、Old領域を見ます。
javaヒープの測定は、jstatでやりました。

計測の順番は以下です。
1:ウォームアップ実施(siegeで10000セッションぐらい作る)
2:セッションを全部破棄する
3:強制フルGC x2 (keycloak自体の利用ヒープなどはOld領域に移動)
4:セッションを作りまくる(siege)
5:強制フルGC x2 

・計算式
セッションの総メモリサイズ ≒ 5のOld領域 - 3のOld領域 
1セッションあたりのメモリサイズ = セッションの総メモリサイズ ÷ セッション数

・今回の環境での結果
5のOld領域:91817.5KB - 3のOld領域:71699.6KB ≒ セッションの総メモリサイズ:20117.9KB
セッションの総メモリサイズ:20117.9KB ÷ セッション数:11548  ≒ 1セッションあたりのメモリサイズ:1.74KB

100万セッションでも、1.66GBぐらいですね。
※:上の値をそのまま使うのではなく、1ユーザで複数セッション作る場合もあるので係数かける必要があります。また、New、Old領域なども考慮して、Javaヒープのサイズは決めます。

## CPUの測定
処理待ちが発生しなくて、CPU負荷がそこそこかかる絶妙な多重度で実行します。
CPUの測定は、sarでやりました。

1:ウォームアップ実施(siegeで10000セッションぐらい作る)
2:セッションを全部破棄する(なんとなく)
3:強制フルGC x2 (なんとなく)
4:いい感じの負荷をかける(siege)

・計算式
コア単位の平均CPU利用率(平均) ≒ 測定時の平均CPU利用率(平均) ÷ 搭載コア数
CPU単価 =  コア単位の平均CPU利用率(平均) ÷ 1秒間のログイン処理数(平均)

1秒間のログイン処理数は、siegeのtransactions÷elapsed_timeでOK

・今回の環境での結果
測定時の平均CPU利用率(平均):58.14% ÷ 搭載コア数:4 ≒ コア単位の平均CPU利用率(平均):14.53%
コア単位の平均CPU利用率(平均):14.53% ÷ 1秒間のログイン処理数(平均):24.8  ≒ CPU単価:5.86msec

今回の測定結果であれば、1コアあれば、1000(msec)÷5.86(msec)で、1秒間にログイン処理を約170個さばけます。


## まとめ
今回は、ほぼデフォ構成のstandaloneで内蔵DBで、だいぶ楽して測定してみました。
オフライン系を有効にすると、DB処理が増えたりすると思うので、CPU単価は増えると思いますし(メモリも)、
DBを外にもって行けば、CPU単価は減ると思います。（AWSだったので、RDSでやればよかった..)
ざっくりなところはありますが、規模感を掴むのには、いいかなと思っています。誰かのお役にたてれば幸いです。

ではでは〜
基本情報技術者試験に合格しました

#基本情報に合格しました（合格者一覧で確認）

令和2年度春の試験で合格しました。自分が合格するために考えたことの殴り書き

書いた人のステータス
・運用監視業務1年程度経験
・javaを少し勉強した

##勉強時間のトータル= 40hくらい

2020/8月~9月くらいに25h (ぜんぜん勉強してない)

・キタミ式のやつでざっくり理解
・過去問を解きまくる　　 おすすめ：[過去問道場](https://www.fe-siken.com/fekakomon.php)
・午後問題全然わからん

**コロナで延期！LPIC取ろう。2月の中頃に終わった**
**基本情報まで受けれる！試験開始まで10日くらいしかない。とりあえず受けよう**

##2週間くらいで受かるためにはどうすればいいか

・「基本情報　最短」や「勉強しない」みたいなワードで検索する


[崖っぷちのあなたへ。基本情報技術者試験を一夜漬けで合格した僕がやったこと。](https://b-masaki.me/kihonjoho)


>知識なんて二の次だ！とりあえず試験を突破しなきゃいけない！そんなあなたに向けて書いて行きますね。


##試験に向けて

・上記のブログによると、午前は勉強する、午後はしないという考え方。（詳しくは読んでみてください）

**自分にはちょっと厳しいかもと思ったので、午後は少し勉強しよう**

・午前：過去問をときまくる
・午後：問題文をさっと読んで、解説を読む（文章題の解き方に慣れる）
　　　　午後は文章題。文章の中に答えがあるという気持ちで挑む
Unity 2020.3.0f1 でDOTSをインストールする方法

# あらまし
UnityにDOTSをインストールしてみよう！と思って方法を探す中で、
2019年版の日本記事が出てきたのですが、2020年版(Unity 2020.3.0f1)では、
導入方法が少し違っていたので紹介しておこうと思います。

手順はUniry公式の

https://docs.unity3d.com/Packages/com.unity.entities@0.17/manual/install_setup.html

に記載されています。

# 手順
1. ウィンドウ → パッケージマネージャ を選択
2. ＋を押して、"GIT URLからパッケージを加える"を選択
![a無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/231056/f9de9f9a-efde-ed8f-373f-0e7435e5cb5f.png)
![ww.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/231056/117c25aa-eb45-76ef-a3fc-49d2dce7d4e9.png)


3. 必要なパッケージ名を入力して導入
![2ww.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/231056/4980ae02-41c4-c349-c0ca-ef043edc36f6.png)


- 推奨パッケージはこの３つ
   * com.unity.entities
   * com.unity.rendering.hybrid
   * com.unity.dots.editor

以上で導入が完了します。

また、冒頭で紹介した元ページの方では、
`Packages\manifest.json`を用いてインストールする方法も紹介されているので、
他の方法も検討したい方はチェックしてはいかがかと思います。
桁ごとの数字を取り出すスクリプト

スプライトでこういう感じのカウンターを作って、その内容を変えたいとき用のスクリプトです。
このアルゴリズムはよく忘れるのでホントの意味での忘備録です。

![Counter.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1146955/4ff53dc3-0b82-752c-3004-ecda4a6324f7.png)

一桁表示

```C#:NumOne
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class NumOne : MonoBehaviour
{
    public Sprite[] digit;
    public bool visible
    {
        set
        {
            gameObject.SetActive(value);
        }
        get { return gameObject.activeSelf; }
    }
    [SerializeField]
    private int _num = 0;
    public int num
    {
        set
        {
            _num = Mathf.Clamp(value, 0, 10);
            gameObject.SetActive(true);
            GetComponent<SpriteRenderer>().sprite = digit[_num];
        }
        get { return _num; }
    }
}

```

複数桁表示用

```C#:NumSet
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class NumSet : MonoBehaviour
{
    public NumOne[] Digit;
    public SpriteRenderer[] Comma;

    [SerializeField]
    private int _num = 0;
    public int num
    {
        set
        {
            _num = value;
            if (_num < 0) { _num = 0; }
            string numstr = _num.ToString("D");

            Comma[0].gameObject.SetActive(numstr.Length > 3);
            Comma[1].gameObject.SetActive(numstr.Length > 6);

            for (int i = 0; i < Digit.Length; i++)
            {
                if (numstr.Length > i)
                {
                    Digit[i].visible = true;
                    Digit[i].num = int.Parse(numstr[numstr.Length - i - 1].ToString());
                }
                else
                {
                    Digit[i].visible = false;
                }
                if (numstr.Length > Digit.Length)
                {
                    Digit[i].num = 9;
                }
            }
        }
        get { return _num; }
    }
}

```

文字列に変換して、下位の文字から数字を取り出しています。

![Counter3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1146955/1df14bdb-dc67-447c-30e1-0932308c3e02.png)

私の場合はSpriteでカウンターを表現していますがTextMeshProのSpriteAssetにも応用できます