OmniAICreator/Qiita-1.07M huggingface dataset:
【Azure】Azure LearnのSQLデータベースを作成するをやってみた

#はじめに
執筆者は元々AWSを勉強していたのだが、諸事情でAzureを勉強する必要が出て来た。Azureに関する記事がAWSより少ないと思うので、Azure Learnでやったことをスクリーンショット共に備忘録として残したい。

#手順
リソースの作成を選択する。
![スクリーンショット 2020-11-22 18.27.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/b1443622-f48b-e393-26c5-aa07e9c34731.png)
SQL Databaseを選択する。
![スクリーンショット 2020-11-22 18.29.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/32ddbdfc-ac58-d4f2-1393-7c398a8a3eb9.png)

データベース名をdb1と入力する。

サーバーは新しいものを作るため新規作成を選択する。右の新しいサーバーのところで以下の内容を入力する。できたらOKを選択する。

|設定  |値  |  
|---|---|
|サーバー  |sqlservernnnn (一意である必要があります)  |
|サーバー管理者のログイン  |sqluser  |
|Password  |Pa$$w0rd1234  |
|場所  |(米国) 米国東部  |　

![スクリーンショット 2020-11-22 17.59.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/93d0b13f-b6ab-6ff8-7efb-4af1cb668181.png)
サーバーが作成できたら、次: ネットワークを選択する。
![スクリーンショット 2020-11-22 18.17.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/421fe14d-ba0c-20f0-bc9e-0bda12cc44c8.png)
接続方法をパブリックエンドポイントにする。
![スクリーンショット 2020-11-22 18.06.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/77e0685f-b03c-4fe0-f1bc-2d8cef9c3461.png)
追加設定を選択し、既存のデータを使用しますをサンプルにする。確認および作成>作成を押下する。
![スクリーンショット 2020-11-22 18.11.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/6e315e4e-47a1-2dd4-4508-4b4eb272c931.png)
すべてのリソースを選択する。
![スクリーンショット 2020-11-22 18.27.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/b1443622-f48b-e393-26c5-aa07e9c34731.png)
データベースが作成されているか確認する。
![スクリーンショット 2020-11-22 18.25.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/26727536-6731-a503-578f-1d1ac9d91b51.png)
db1に移り、下記の先ほど作成した管理者名とパスワードを入力しOKを押下する。

|設定  |値  |  
|---|---|
|サーバー管理者のログイン  |sqluser  |
|Password  |Pa$$w0rd1234  |

そうするとエラーが出るので、サーバーファイアウォール設定に移る。
![スクリーンショット 2020-11-22 20.48.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/a3093bb3-e6c0-8932-279a-79053f4e2403.png)
クライアントIPアドレスの追加を選択する。
![スクリーンショット 2020-11-22 20.49.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/dc2195c9-7402-f30e-c411-a2c01b817e10.png)
自分のIPが開始IPと終了IPに追加されているか確認する。確認されたら保存を選択する。
![スクリーンショット 2020-11-22 20.52.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/8d9c6883-2e65-0111-e781-d73d38663c81.png)
もう一度下記の管理者名とパスワードを入力し、OKを押下する。

|設定  |値  |  
|---|---|
|サーバー管理者のログイン  |sqluser  |
|Password  |Pa$$w0rd1234  |

![スクリーンショット 2020-11-22 18.41.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/2fd13531-58ba-4f66-a70c-80799af79131.png)
エディター ウィンドウに次のクエリを入力し、実行を選択する。

```
SELECT TOP 20 pc.Name as CategoryName, p.name as ProductName
FROM SalesLT.ProductCategory pc
JOIN SalesLT.Product p
ON pc.productcategoryid = p.productcategoryid;
```

![スクリーンショット 2020-11-22 21.00.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/66211226-9523-fcf6-a182-422fb43f5919.png)
クエリが成功していることを確認する。
![スクリーンショット 2020-11-22 21.00.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/db960459-8d44-d486-05be-93dc5ebc3abe.png)
UIPickerViewと辞書型で筋トレの内容をlabelに表示させる

せっかくなのでメモ。Swift5 Xcode12.2
UIPickerViewで部位と種目をそれぞれ選択します。
辞書型を使い、選択した部位によって種目のpickerが変わります。

![スクリーンショット 2020-11-23 11.05.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/750629/611eb9be-89ed-0169-18d6-69e8258203f6.png)


![スクリーンショット 2020-11-23 11.06.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/750629/9d218a9c-257d-616e-dfd5-f6cd48b5f87a.png)

## 辞書の宣言

```
    let menuDataList: [String: [String]] = [
        "脚": ["スクワット","レッグプレス","レッグエクステンション","レッグカール"],
        "背中": ["デッドリフト","ベントオーバーローイング","チンニング","ラットプルダウン"],
        "胸": ["バーベルベンチプレス","ダンベルベンチプレス","インクラインダンベルベンチプレス","ペックフライ"],
        "肩": ["サイドレイズ","フロントレイズ","リアレイズ","ショルダープレス"],
        "三頭": ["ナローベンチプレス","トライセプスエクステンション","ケーブルプレスダウン","ダンベルキックバック"],
        "二頭": ["ダンベルカール","インクラインダンベルカール","プリチャーカール","ハンマーカール"],
        "腹": ["クランチ","インクラインクランチ","レッグレイズ"]
    ]
    var partsDataList: [String] = [
        "脚","背中","胸","肩","三頭","二頭","腹"
    ]
    var selectedParts = ""
```

## 2つのpickerにタグを振り分ける

```
override func viewDidLoad() {
        super.viewDidLoad()
        partsPickerView.delegate = self
        partsPickerView.dataSource = self
        menuPickerView.delegate = self
        menuPickerView.dataSource = self
        partsPickerView.tag = 1
        menuPickerView.tag = 2
        selectedParts = partsDataList[0]
    }
```

## PickerViewの個数を返す

```
    func pickerView(_ pickerView: UIPickerView,
                    numberOfRowsInComponent component: Int) -> Int {
        if pickerView.tag == 1{
            return partsDataList.count
        } else if pickerView.tag == 2{
            //menuDataListのオプショナル型にアンラップされたselectedPartsの要素数が空だったら0を返す
            return menuDataList[selectedParts]?.count ?? 0
        } else {
            return 0
        }
    }
```

## 表示内容

```
    func pickerView(_ picker: UIPickerView,
                    titleForRow row: Int,
                    forComponent component: Int) -> String? {
        if picker.tag == 1 {
            return partsDataList[row]
        } else if picker.tag == 2 {
            //menuDataListのオプショナル型にアンラップされたselectedPartsのrow番目が空だったら空文字列を返す
            return menuDataList[selectedParts]?[row] ?? ""
        } else {
            return ""
        }
    }
```

## UIPickerViewのRowが選択された時の挙動

```
    func pickerView(_ pickerView: UIPickerView,
                    didSelectRow row: Int,
                    inComponent component: Int) {
        if pickerView.tag == 1 {
            partsLabel.text = partsDataList[row]
            selectedParts = partsDataList[row]
            menuPickerView.reloadAllComponents()
        } else if pickerView.tag == 2 {
            //menuDataListのオプショナル型にアンラップされたselectedPartsのrow番目が空だったら空文字列をmenuLabelのtextへ返す
            menuLabel.text = menuDataList[selectedParts]?[row] ?? ""
        } else {
            return
        }
    }
```
Windows Forms で PerMonitorV2 設定して動きを見てみた

## 追記

最初 ListBox での動きが変だったのですが .NET Framework 4.7 系から .NET Framework 4.8 に上げたらなおりました。

## 試したこと

- Windows Forms アプリを新規作成して app.manifest を追加
- supportedOS タグの Windows 10 のコメントアウトを外す

```xml
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
  <application>
    <!-- Windows 10 -->
    <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
    </application>
</compatibility>
```

- App.config で PerMoniterV2 の設定を追加

```xml
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
    </startup>
	<System.Windows.Forms.ApplicationConfigurationSection>
		<add key="DpiAwareness" value="PerMonitorV2" />
	</System.Windows.Forms.ApplicationConfigurationSection>
</configuration>
```

- Form のフォントを Yu Gothic UI, 9pt に変更
- Form の AutoScaleMode を Font から Dpi に変更
- ListBox や DataGridView なんかを置いた画面を適当に作成
- デバッガーにアタッチしない状態で実行して動きを確認

## 結果

### ListBox のある画面

拡大率 100% の画面

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70288/83253fe2-d19a-bc70-69dd-3236fc43a100.png)

150% に持って行った状態

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70288/a5c1b000-b252-635e-9deb-4ca144fd600c.png)


100% に再度移動させた状態

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70288/999adccc-a78d-27a3-8f5d-a2ed7c964408.png)

なんか 100% → 150% → 100% に持っていったら ListBox のフォントが大きくなった…

後述しますが、この変な動きは .NET Framework 4.7.2 で起きていて .NET Framework 4.8 にすると、この変な動きは治っていました。

### DataGridView

100% で表示

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70288/f07a75ce-be2e-16c6-da03-ca7b3892fc77.png)

150% に移動

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70288/80568f09-3da1-3e97-7ee7-2666c3e8d4c5.png)

100% に再度移動

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70288/e75b8541-c3a7-c2c0-c04f-72eac51bef84.png)

DataGridView の中のチェックボックスの大きさがちょっとうまく行ってないなぁ。

## .NET Framework 4.8 だとどうなる？

.NET Framework 4.8 で ListBox と DataGridView を試してみました。結果は…

100%
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70288/187ae823-3a8b-a453-5886-7d24585acacb.png)

150%
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70288/2a57e64c-94b3-736a-d85d-cd75467cac1a.png)

100%
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70288/012e583f-a53b-e98d-e9c9-ec14e897bc2d.png)

ListBox の変な動きはなおってましたが、DataGridView は特に内部のコントロールが大きくなるとかはなかったです。

## まとめというか感想

このうまくいかない部分にきちんと対応しようと思ったらどうするのが正攻法なんだろう？？
今回はとりあえず動きを見てみたので、次やるとしたら対処法の調査かな…

## 参考

- [Windowsフォームでの高DPI(Hi-DPI)対応のコツ](https://qiita.com/mono1729/items/a93505a5cb3fe194b7dc#autoscalemode%E3%83%97%E3%83%AD%E3%83%91%E3%83%86%E3%82%A3%E3%82%92dpi%E3%83%A2%E3%83%BC%E3%83%89%E3%81%AB%E3%81%99%E3%82%8B)
- [High DPI support in Windows Forms](https://docs.microsoft.com/ja-jp/dotnet/desktop/winforms/high-dpi-support-in-windows-forms?view=netframeworkdesktop-4.8)
コマンドラインツールのサンドボックス化

#はじめに
Xcodeで自作したコマンドラインツールをサンドボックス化する方法についてのメモ記事です。
##すること
1. Info.plistファイルを準備してプロジェクトに読み込む（他のプロジェクトで作成されたファイルを読み込んで編集すると楽)。
2. TargetのGeneralタブのIdentityのchoose Info.plist File..で(1)のファイルを選ぶ。
3. CapabilitiesでApp Sandboxを追加。適宜設定を変更。
4. TargetのBuidSettingsのPackagingでCreate Info.plist Section in BinaryをYESに変更。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/595771/9dc07a80-09b7-668e-2538-6d323d01717f.png)

これでビルドする。

##サンドボックスの設定を確認

```
codesign -d --entitlements :- 
/Users/yoho/Library/Developer/Xcode/DerivedData/commandLineToolTest-fiajznkvauagbcaqcvfqjyprqven/Build/Products/Release/commandLineToolTest

実行結果:


Executable=/Users/yoho/Library/Developer/Xcode/DerivedData/commandLineToolTest-fiajznkvauagbcaqcvfqjyprqven/Build/Products/Release/commandLineToolTest
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>com.apple.security.app-sandbox</key>
	<true/>
	<key>com.apple.security.files.user-selected.read-write</key>
	<true/>
	<key>com.apple.security.get-task-allow</key>
	<true/>
</dict>
</plist>

```

##関連するエラー
Info.plist Section in BinaryをYESにしないと、ビルド自体は成功するが、Xcodeで以下のエラーが出てデバッグなどができない。

```
Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
```
この時作成されたバイナリをターミナルで実行すると、

```
Illegal instruction: 4
```
と出力される。


#おわりに
App Storeで色々公開しようと思って準備しているが、Sandbox化で手こずっている。なかなか関連する情報が得られず、記事にしておくことにした。
【JavaScript】前置演算と後置演算の違い

#プログラミング勉強日記
2020年11月23日
前置演算と後置演算の違いについて学習したので、記録します。

#1.前置演算とは？
加算/減算の演算子を変数の前方に配置することです。

加算を`インクリメント`

減算を`デクリメント`

と呼びます。

```script.js
let x = 1;
//前置演算
++ x;//結果：2
```

#2.後置演算とは？
インクリメント/デクリメントの演算子を変数の前方に配置することです。

```script.js
let x = 1;
//後置演算
x ++;//結果：2
```

#3.両者の違いとは

上記のコードでは、特に問題ありません。

ですが、インクリメント/デクリメントの演算子で演算した結果を、他の変数に代入する場合は、注意が必要です。

##① 前置演算で他の変数に代入する場合

```script.js
//前置演算
let x = 1;
let y = ++ x;
console.log(x);//結果：2
console.log(y);//結果：2
```
変数xを加算してから、その結果を変数yに代入しています。

## ② 後置演算で他の変数に代入する場合

```script.js
//後置演算
let x = 1;
let y = x ++;
console.log(x);//結果：2
console.log(y);//結果：1
```
変数xを変数yに代入してから、変数xを加算します。

#参考本
* [改訂新版JavaScript本格入門 ～モダンスタイルによる基礎から現場での応用まで](https://www.amazon.co.jp/%E6%94%B9%E8%A8%82%E6%96%B0%E7%89%88JavaScript%E6%9C%AC%E6%A0%BC%E5%85%A5%E9%96%80-%EF%BD%9E%E3%83%A2%E3%83%80%E3%83%B3%E3%82%B9%E3%82%BF%E3%82%A4%E3%83%AB%E3%81%AB%E3%82%88%E3%82%8B%E5%9F%BA%E7%A4%8E%E3%81%8B%E3%82%89%E7%8F%BE%E5%A0%B4%E3%81%A7%E3%81%AE%E5%BF%9C%E7%94%A8%E3%81%BE%E3%81%A7-%E5%B1%B1%E7%94%B0-%E7%A5%A5%E5%AF%9B-ebook/dp/B01LYO6C1N/ref=sr_1_2?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=2KPINCK085EC0&dchild=1&keywords=javascript&qid=1606097113&sprefix=Java%2Caps%2C284&sr=8-2)
Google Colaboratory上のM5StickV用の学習データを作成するノートブック

Google Colaboratory上のM5StickV用の学習データを作成するノートブックいろいろありますが、
Grad-CAM（ヒートマップ）や学習データの変換ツールが動きませんでした。
原因は
tensorflowのバージョンの問題で、最初に

```
%tensorflow_version 1.x
```

を行えば、動いた。
build.gradle変更後Gradle プロジェクトのリフレッシュが必要だった件

Spring Bootで@Sizeアノテーション(javax.validation)が使用できなかったので。
色々と調べた結果、build.gradleに依存性を注入すれば良いと書いてあり、試したが、インポートができなかった。そこで、プロジェクトを右クリックし、GraldeメニューからGradleプロジェクトのリフレッシュを実行したら@Sizeアノテーションがインポートできました。

参考
https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.3-Release-Notes#validation-starter-no-longer-included-in-web-starters
Web Data ConnectorのデータをTableau Onlineで抽出更新する

##はじめに

相当ニッチだと思うのですが、いつか誰かのためになればと思い書き留めておきます。

Tableauは様々なデータに繋ぐことができますが、Web Data Connectorという仕組みを使えば、ネット上の色んなデータを取得することができます。コミュニティーの有志たちが[無料で作成・公開しているWeb Data Connector](https://tableau.github.io/webdataconnector/community/)を利用することもできますし、使用したいデータを提供しているサービスがAPIを公開していてデータの取得を許可しているのであれば、自分で開発して作ることもできます。

この記事ではWeb Data Connectorの作成方法については触れませんが、以下の公式動画を見るとなんとなくどうやって開発すれば良いかはイメージを持っていただけるはずです。ウェブサイトの開発やPythonなどでプログラムを書いたことがある方でしたら1日でPoCレベルのものは十分作れると思います。

[Your first web data connector: from 0 to }](https://www.youtube.com/watch?v=jtGzBq4hw2s&t=7s)
[Write your first Web Data Connector](https://www.youtube.com/watch?v=aHlbkq_YUag)

このWeb Data Connector、Tableau Desktopで使用するぶんには良いのですが、Tableau Server/Onlineにパブリッシュしてスケジュールを組んで**抽出更新したい**となるとちょっと厄介です。ですが、Tableau Serverの場合はWeb Data Connectorのホストをホワイトリスト登録することで実現できます。詳しくは[こちら](https://help.tableau.com/current/server/ja-jp/datasource_wdc.htm)を読んでみてください。

##前提

公式サイトで名言されてる通り、Web Data Connectorを使用して取得したデータソースをTableau Onlineにパブリッシュして利用することはできても、**基本的には抽出したデータソースを更新することはできません。**([公式ヘルプ: Web データ コネクタ](https://help.tableau.com/current/pro/desktop/ja-jp/examples_web_data_connector.htm)より)

>セキュリティ対策として Tableau Online にパブリッシュすると、Tableau Online は Web データ コネクタが作成した抽出に接続したり、その抽出を更新できません。一部の Web データ コネクターの抽出を更新するために、Tableau Bridge を使用できます。

この制限はTableau OnlineはTableauがホストしているサーバーをサイトという単位で切り分けて提供されているサービスですが、ホワイトリスト登録は現在サーバー単位でしかできないため、サイトを利用するお客様ごとにはホワイトリスト登録ができないからではないかと推測してます。

そこで登場するのが「Tableau Bridge（無料）」です。Tableau BridgeはオンプレミスデータをTableau Onlineからアクセスできるようにするアプリケーションです。これを使えば、

* Web Data ConnectorをホストしているサーバーにTableau Bridgeをインストールできる
* Tableau Bridgeを利用している同じアカウントでデータソースを作成できる

という条件であれば、**Web Data ConnectorのデータをTableau Onlineで抽出更新することが可能**です。

## 設定方法

1. Web Data Connectorを準備する
2. Web Data Connectorのプログラムファイルをウェブサーバーに設定する
3. 同じサーバーにTableau Bridgeをインストールする
4. Tableau DesktopでWeb Data Connectorに接続し、データソースをOnlineにパブリッシュ
5. Tableau Online側でデータソースに抽出更新の設定を行う。


全体的には以下のような構成になります。
![WDCの概要図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/884972/35967ef8-4aeb-85e2-0f02-079b1c3d1929.png)

##注意点

+ Tableau BridgeはWindows OSにしかインストールできないので、サーバーをLinuxで立てている場合にはインストールできない可能性があります。
+ Web Data Connectorが認証情報を求める仕様の場合、[正常に抽出更新できない可能性があります。](https://help.tableau.com/current/online/ja-jp/to_sync_local_data.htm)
+ Tableau Bridgeにログインしているユーザーと、Tableau Onlineでデータソースをパブリッシュしたユーザーは同一である必要があります。そうでない場合、Bridgeを使った抽出更新スケジュールを組む際に、以下赤枠部分が選択できません。
![抽出の更新設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/884972/28023bf7-85cf-adb8-8875-d318f787db09.png)


##おわりに

ニッチなニーズかもしれませんが、Web Data Connectorを開発できる技術力とある程度自由にサーバーを構成できる環境があれば、Tableau OnlineからでもWeb Data Connectorのデータは抽出更新できる、ということが伝われば嬉しいです。

P.S. ちなみに私は検証環境として以下を使用しました。

+ AWS EC2 Windows OSサーバー
+ IISでサーバー内にウェブサーバーを構築しWeb Data Connectorファイルを設定
+ セキュリティグループはインバウンド80,443,3389 アウトバウンドは80,443を設定
Redmine(Docker)環境構築メモ


* ローカル環境に、プロジェクト管理ソフトウェアRedmineをDockerで立ち上げる手順についてまとめる。
  * Redmine用DBにはMySQL5.7を利用する。

## 構築手順

* フォルダ構成

  ```
  redmine/
        ├ data/			#マウント場所
        |    └ db       
        |    └ plugins  
        |    └ themes        
        └ docker-compose.yml  
  ```

**1.`docker-compose.yml`を作成する。**

   ```yml
   version: "3"
   
   services:
     redmine:
       container_name: redmine
       image: redmine
       restart: always
       ports:
         - 8081:3000
       environment:
         REDMINE_DB_MYSQL: redmine-db
         REDMINE_DB_PASSWORD: redminepass
       volumes:
         - ./data/plugins:/usr/src/redmine/plugins
         - ./data/themes:/usr/src/redmine/public/themes
   
     redmine-db:
       image: mysql:5.7
       container_name: redmine-db
       restart: always
       environment:
         MYSQL_ROOT_PASSWORD: redminepass
         MYSQL_DATABASE: redmine
       volumes:
         - ./data/db:/var/lib/mysql
       command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci   
   ```
   ※マウント場所やポートなどは自環境に合わせて適宜設定する。
**2. コンテナを起動する。**
 上記`redmine`フォルダに移動し、以下のdocker-composeコマンドを実行する。
   
   ```shell
   docker-compose up -d
   ```
**3.ブラウザから`http://localhost:8081`にアクセスする。**
   ※以下の画面が表示される。
   ![redmine_top.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586535/4e613cc0-f90f-0522-9118-5d316c13a8c8.png)
**4.初期ユーザー情報(ログインID:admin/パスワード:admin)を入力して、ログインする。※ログイン後、パスワード変更を要求される。**

## 参考情報

* [redmine Docker Official Images](https://hub.docker.com/_/redmine)
* [Redmine を docker-compose で秒殺起動する](https://sig9.hatenablog.com/entry/2019/07/06/000000)
RubyでオプションをJSONファイルとコマンドライン引数の双方から取得する

Rubyでプログラムを作成している際に、プログラムのオプションを以下の2つのソースから取得したい場合があります。

1. JSONファイル
2. コマンドラインオプション

こういう場合に、よく使う実装の方法を共有します。

## 基本的なコンセプト

1. オプションは一つのオブジェクトに集める。  
   例: `class Options`
2. オブジェクト生成時に、JSONファイルからオプションを読み込む。  
   例: `opt = Options.new('some.json')` とするとJSONファイルからオプションを読み込む。
3. オプションにアクセスするときはオブジェクトの accessor を使う。  
   例: `opt.option_1` のような感じでアクセスできる。
4. コマンドライン引数は [OptionParser](https://docs.ruby-lang.org/ja/latest/class/OptionParser.html) を使ってハッシュに保存しする。
5. オプションのオブジェクトは、ハッシュから値を取り込むメソッドを持つ。  
  これによりコマンドライン引数から生成した設定値のハッシュ取り込める。   
  例: `opt.import_hash(options)` のような感じで使える。

## 実装例

https://gist.github.com/aikige/3e393a8b04c24b900f4810c5cc55ffa0

```ruby
#!/usr/bin/env ruby

require "json"

class Options
  # list of supported keys.
  TEMPLATE_SAMPLE = { 'option_1' => 'Bool', 'option_2' => 'String' }

  def initialize(filename = "config.json", template = TEMPLATE_SAMPLE)
    @template = template
    File.exist?(filename) and File.open(filename) do |j|
      import_hash(JSON.load(j))
    end
  end

  def import_hash(hash)
    return unless hash.is_a?(Hash)
    @template.keys.each do |key|
      add_variable(key, hash[key]) if hash.has_key?(key)
    end
  end

  private def add_variable(name, value)
    if (@template[name].downcase == 'bool')
      # 'bool' type needs special handling in ruby.
      raise "value is not bool" if (!!value != value)
    else
      raise "value is not #{@template[name]}" unless (value.is_a?(eval(@template[name])))
    end
    # crate instance variable.
    instance_variable_set("@#{name}", value)
    # add getter method.
    self.class.send(:attr_reader, name) unless respond_to?(name)
  end
end

if $0 == __FILE__
  require 'optparse'

  opt = Options.new('config.json')

  option = {}
  arg = OptionParser.new
  arg.on('-1 OPTION', '--option_1=OPTION', 'Set option 1') { |v| option['option_1'] = v.eql?("true") }
  arg.on('-2 OPTION', '--option_2=OPTION', 'Set option 2') { |v| option['option_2'] = v }
  arg.parse!(ARGV)
  opt.import_hash(option)
  p opt.option_1
  p opt.option_2
end
```

JSONファイルはこんな感じです。

```json
{
        "option_1": true,
        "option_2": "test"
}
```

## 補足

* 定数 `TEMPLATE_SAMPLE` が、オプションのテンプレートになっていて、名前と想定する型の組を定義しています。
* モジュールとして再利用できるようにテンプレートは初期化の引数として指定することもできるようにしてあります。
* Ruby では Bool 型はありませんが、ないと不便なので `Bool` キーワードが型として含まれる場合の処理は個別に書いています。

## おまけ

* [Pythonの場合はこちら](https://qiita.com/aikige/items/92406924ad0165ae89e9)
WindowsとMacのショートカットキー対応表

#執筆の動機
今後、学んだことをQiitaでアウトプットしていきたい。
しかし記事を作成した経験が無く、まずは投稿してみたかった。
そんな中、人生で初めてMacを購入しました。
Ctrlキーが無かったり、入力方式（かな、半角英数）を切り替える方法が分からなかったりと操作感が異なり興奮の連続です。新しいことを学ぶのって楽しいですよね。
Qiita初投稿には良い題材ではないかと考え、私がWindowsでよく使用するショートカットキーをMacではどのように使用するのか調べてまとめることにしました。


#ショートカットキー対応表
|操作|Windows     |Mac        |
|:-----|:----------|:----------|
|テキストをコピー |Ctrl + C      |command + C   |
|コピーしたテキストを貼り付け|Ctrl + V|command + V|
|テキストを切り取り|Ctrl + X|command + X|
|操作を戻す|Ctrl + Z|command + Z|
|操作を戻すを取り消し|Ctrl + Y|command + Shift + Z|
|デスクトップ画面を表示|Windwos + D|fn + F11|
|アクティブウィンドウの切り替え|Alt + tab|command + tab|
|画面をロック|Windows + L|command + control + Q|
|ウィンドウを最大化|Windows + ↑|command + control + F|
|入力方式切り替え|半角/全角|control + スペース|

普段どのようなショートカットキーを使用しているかなかなか思い出せませんね。
記事作成の良い練習になりました。
VSCode のリモート開発機能でX11転送させる (Windows)

# 問題

VSCode のリモート開発機能を使って、Windows クライアントから Ubuntu サーバにリモート接続をして開発をしている (WSL2 ではない)。

Cypressを使いたくなったけど、GUIを開くとこができないため X11転送させて、開発する必要があった。

# 解決方法

Windows 側では X Window サーバーを起動しておく。
以下などをインストール。
https://sourceforge.net/projects/vcxsrv/reviews/

VSCode で SSH のリモート開発時に X11 転送もさせる。
これは、拡張機能で実現できる。
以下をインストールする。
https://marketplace.visualstudio.com/items?itemName=spadin.remote-x11

あとは、普通にGUI のソフトウェアを起動すればよい

# まとめ

Windows & VSCode で SSHリモート開発機能を使っているときに X11 転送したいときは、

- VcXsrv
- Remote X11 (VSCode ext)

を使えばいい
【ゴチバトル】ピタリ賞のメニューを求めようとしたが

# はじめに

ふと思いました。

ゴチバトルって **必ずピタリ賞の可能性があるのだろうか？**
つまりメニュー・金額によっては、どう組み合わせてもピタリ賞にならないこともあるのでは？
（もしゴチバトルが公営ギャンブルなら、その辺を明確にすべきですね？）

ということで、ピタリ賞の解を求めるロジックを考えてみたのですが・・・。

# メニューの全組み合わせを調べればよい？

仮にメニューが３品（Ａ,Ｂ,Ｃ）の場合、

・Ａのみ
・Ｂのみ
・Ｃのみ
・ＡとＢ
・ＡとＣ
・ＢとＣ
・ＡとＢとＣ

これらの合計金額のうち設定金額と等しいものが、求める解です。
どれも等しくなければ「ピタリ賞の可能性なし」といえます。

・・・でも そう単純ではありませんでした。

たまにデザートで、**同じメニューを複数 注文する**場合があります。
このパラメータのせいで、組み合わせ数が膨大になってしまいました。

# 数式にする

設定金額：$S$
メニューn品それぞれの金額：$a_1, a_2 ... a_n$
それぞれの注文数：$x_1, x_2 ... x_n$

このとき以下の式が成り立つ $x_1, x_2 ... x_n$ を求める必要があります。

$S = a_1x_1 + a_2x_2 + ... + a_nx_n$

# すみません、ここまでです。

n = 3（メニュー３品）の場合、

注文数 $x_1 ... x_n$ が~~１以上~~０以上の整数なので、
($x_1,x_2,x_3$) をすべて書き出そうとすると、

(1,0,0)
(0,1,0)
(0,0,1)
(1,1,0)
(1,0,1)
(0,1,1)
(1,1,1)

(2,0,0)
(0,2,0)
(0,0,2)
(2,2,0)
(2,0,2)
(0,2,2)
(2,2,2)

(2,1,0)
(2,0,1)
(2,1,1)
(1,2,0)
(0,2,1)
(1,2,1)
(1,0,2)
(0,1,2)
(1,1,2)
(2,2,1)
(2,1,2)
(1,2,2)

(3,0,0)
(0,3,0)
(0,0,3)
(3,3,0)
(3,0,3)
(0,3,3)
(3,3,3)

(3,1,0)
(3,0,1)
(3,1,1)
(1,3,0)
(0,3,1)
(1,3,1)
(1,0,3)
(0,1,3)
(1,1,3)
(3,3,1)
(3,1,3)
(1,3,3)

(3,2,0)
(3,0,2)
(3,2,2)
(2,3,0)
(0,3,2)
(2,3,2)
(2,0,3)
(0,2,3)
(2,2,3)
(3,3,2)
(3,2,3)
(2,3,3)

(3,2,1)
(3,1,2)
(2,3,1)
(1,3,2)
(2,1,3)
(1,2,3)
：
：

もう無理です :sweat:
３品でこうなのだから、メニューが増えたら お手上げです。

（まあ実際は、同じ肉料理を２皿以上注文することは無いのですが・・・。）

# 編集後記？

ピタリ賞の解を求めるのは、パズルの問題ともいえます。
そして この問題を考えていて、上司とのやり取りを思い出しました。

そのとき私は、（ピタリ賞とは別の）パズル的な問題を抱えていました。
私は難しい旨 上司に伝えると、

「データを抽出するのと、パズルの解を抽出するのと、何が違うの？」
（そんなに難しいの？）

というものでした。どうも上司は、

「データベースの全社員から２０代男性を抽出する」ことと、
「パズルの組み合わせから正解を抽出する」ことは、同じと思っていたようです。

エンジニアの考えを、「非エンジニア」に伝えるのは
なかなか難しいものです。
BlueZのマスター名を変えたい話

# LinuxでBluetoothの名前を変えたい
コロナ禍で初の自作PCを組んだのですが、皆さんはホスト名ってどうしていますか？メーカー製なら決まった名前、Windowsだとデフォルトでランダムな英数字、Fedora、openSUSEだとlocalhostだったり、Ubuntu系はインストール時に自分で決めたりetc..。ラップトップ、デスクトップとLinuxを複数動かして名前が被っても面倒なので変えたい、と思ったら引っかかったのでメモ。

## 今回の環境
- 自作PC
- openSUSE Tumbleweed
- GNOME desktop

## ホスト名と分かれている..らしい
![Screenshot from 2020-11-23 08-19-28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/371568/800ea71b-2cce-fabd-b703-99249c4a7af8.png)

 YaSTツールでホスト名を変えて、ターミナル上で変更を確認したのですがBluetoothの設定画面を覗いても変わっていなかったので、一緒に変えてくれるわけではないようでした。
 そこでhciconfigを開こうとしたら、無くなっていたんですね。

## hcitoolやhciconfigはBlueZに同梱されず
参照：[https://wiki.archlinux.jp/index.php/Bluetooth#.E3.82.A4.E3.83.B3.E3.82.B9.E3.83.88.E3.83.BC.E3.83.AB](https://wiki.archlinux.jp/index.php/Bluetooth#.E3.82.A4.E3.83.B3.E3.82.B9.E3.83.88.E3.83.BC.E3.83.AB)
ラズパイだと使ってた気がしたけど、バージョンが古かったのか..?

## なら代替品は？

非推奨なら入れて使う気にもならないしということでBlueZ自体に変わりがあるだろうと、helpを見ると



        [bluetooth]# help
        Menu main:
        Available commands:
        -------------------
        advertise                                         Advertise Options Submenu
        scan                                              Scan Options Submenu
        gatt                                              Generic Attribute Submenu
        list                                              List available controllers
        show [ctrl]                                       Controller information
        select <ctrl>                                     Select default controller
        devices                                           List available devices
        paired-devices                                    List paired devices
        system-alias <name>                               Set controller alias
        reset-alias                                       Reset controller alias
        power <on/off>                                    Set controller power
        pairable <on/off>                                 Set controller pairable mode
        discoverable <on/off>                             Set controller discoverable mode
        discoverable-timeout [value]                      Set discoverable timeout
        agent <on/off/capability>                         Enable/disable agent with given       capability
        default-agent                                     Set agent as the default one
        advertise <on/off/type>                           Enable/disable advertising with       given type
        set-alias <alias>                                 Set device alias
        (以下省略)

それらしきを発見ということで、さっそく
    
    [bluetooth]# system-alias hogehoge

![Screenshot from 2020-11-23 09-05-52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/371568/dc198ec6-fdb9-fd3b-8218-962af4adb69a.png)
識別名称もちゃんと変わってくれましたね
MetaImageIO ( *.mha, *.mhd ) を tiff stackに変換

# pythonでSimpleITKをつかう

コア部分は下記の通り。
出力にtiffを指定すれば、自動的にスタックファイルになる。

```python
import SimpleITK as sitk

reader = sitk.ImageFileReader()
reader.SetImageIO("MetaImageIO")
reader.SetFileName(inputImageFileName)
image = reader.Execute();

writer = sitk.ImageFileWriter()
writer.SetImageIO("TIFFImageIO")
writer.SetFileName(outputImageFileName)
writer.Execute(image)
```

`SetImageIO`を変えれば、他のファイルの読み書きができる。

ターミナルで使いやすいように、私は下記のようにしている。

```python:mhd2tif
#!/usr/bin/env python3
import os,sys
import SimpleITK as sitk

if len(sys.argv)!=3 :
    print("usage: mhd2tif infile.mhd out.tif")
    exit()

inputImageFileName = sys.argv[1]
outputImageFileName = sys.argv[2]

if os.path.isfile(inputImageFileName)==False :
    print(inputImageFileName + ": not found.")
    exit()

reader = sitk.ImageFileReader()
reader.SetImageIO("MetaImageIO")
reader.SetFileName(inputImageFileName)
image = reader.Execute();

writer = sitk.ImageFileWriter()
writer.SetImageIO("TIFFImageIO")
writer.SetFileName(outputImageFileName)
writer.Execute(image)
```

# 参考
https://simpleitk.readthedocs.io/en/master/IO.html
実務経験で身につけた技術　～HTML・CSS編～

#はじめに
未経験から実務経験２か月ちょっとを経て、1つのサイトを完成させることができたので（もちろん色々な人の手助けあってですが）、今後に生かすインプットと自分の備忘録としてPHP、JavasScript・jQuery、HTML・CSSの３つに分けて記録していきます。
この記事では、**HTML・CSSについて**書いていきます。
なお、身につけた技術は随時、記録・更新していきます。
他の記事については、下記のリンク先からご覧ください。

<details><summary>別の記事のリンク</summary>
<div>
[実務経験で身につけた技術　～PHP編～](https://qiita.com/hx_kei/items/cc31823dfc2425ac0688 "実務経験で身につけた技術　～PHP編～")
[実務経験で身につけた技術　～Javascript・jQuery編～](https://qiita.com/hx_kei/items/ff8ff0e98b2545b5e37e "実務経験で身につけた技術　～Javascript・jQuery編～")
</div>
</details>

#HTML
###checkbox
```
//input checkboxには、display:none
<input type="checkbox" id="check"><label for="check">テスト</label>
```
id = for の内容を同じにするとlabelにcheckbox属性をつけられる。
サーバー処理でcheckboxを使っていてcheckboxの見た目を変えたいときに汎用的に使える。

###javascript:void(0)
```
<a href="javascript:void(0);">
```
内容的には、javascriptだけどaタグ要素をつけたいときに使えるやつ。
でも、カーソルを重ねたとき、リンク先にjavascript:void(0);と見えてしまうので、ユーザービリティ的によろしくない。
現在の推奨は、代わりにbuttonタグにするか、cssに要素を持たせる。

```
<button></button>
<style>
a {
  cursor:pointer;
}
</style>
```

###tabel
```
<table>
<tbody>
<tr>
	<th scope=""></th>
	<td></td>
</tr>
</tbody>
</table>
```
よく使うテーブルタグ。忘れそうなので作成。

#CSS
###優先順位
同じタグの処理が存在した場合のjsの優先順位は、下が優先。
CSSもそうだが、違うのが詳細度の点数によって優先順位が決まるということ。優先順位を上げたいなら詳細にタグを記述すること。
（最終手段として!important)
下記リンクを参照。
[CSSの優先順位を自在に適応させる方法](https://www.aiship.jp/knowhow/archives/30349 "CSSの優先順位を自在に適応させる方法 ")


###background: url
```
.test {
	background: url(../test) 5% 8px no-repeat;
}
```
urlで背景に指定した画像を持たせる。%でpositionの指定。pxで高さの指定。画像は繰り返し表示されるのでno-repeatで一枚に指定。


#最後に
まとめることでなんとなく理解していた箇所をクリアに理解することができました。
まだ全然書ききれていないので、随時更新します。
今後もアウトプットした分だけインプットするよう心掛けていきます。
【Visual Studio Code】開始タグから閉じタグまでを一瞬で選択できるショートカットキー

#VScodeショートカットキー紹介
VScodeで開始タグから閉じタグまでを選択できるショートカットキーの設定方法を紹介します。
マウスをクリックして下にスライドさせながら選択していくのが面倒な方にオススメです！


#挙動動画
![short.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/854121/3164a997-a7e8-9b70-d174-0a4d9d777f7a.gif)



#設定方法

##1.VScode左下の歯車のマークをクリックし、キーボードショートカットを選択
選択していくのが面倒な方は、`『cmd + K』+『cmd + S』`を押すとキーボードショートカットの画面が表示されます。

##2.『 editor.emmet.action.balanceOut 』と検索

##3.任意のショートカットキーを設定する
すでに割り当てられているショートカットキーには設定できないので注意です。
僕の場合、`『shift + cmd + A』`で設定しています。
テキストではわかりにくい場合は、下記の動画をご覧ください。



#動画で補足
![setting.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/854121/2c977e9b-471b-17d6-3089-6f2b1c72a66a.gif)
AtCoder Beginner Contest 184

##[A - Determinant](https://atcoder.jp/contests/abc184/tasks/abc184_a)

```C++:C++
#include<iostream>
#include<vector>
#include<algorithm>
#include<iomanip>
#include<utility>
#include<iomanip>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<cctype>
 
#define rep(i,n) for(int i=0; i<(n); ++i)
#define fixed_setprecision(n) fixed << setprecision((n))
#define pai 3.1415926535897932384
#define NUM_MAX 2e18
#define NUM_MIN -1e9
 
using namespace std;
using ll =long long;
using P = pair<int,int>;
 
int main(int argc, const char * argv[]) {
    int a, b, c, d;
    cin >> a >> b;
    cin >> c >> d;
    cout << a*d - c*b;
    
    return 0;
}
```

##[B - Quizzes](https://atcoder.jp/contests/abc184/tasks/abc184_b)

```C++:C++
#include<iostream>
#include<vector>
#include<algorithm>
#include<iomanip>
#include<utility>
#include<iomanip>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<cctype>
 
#define rep(i,n) for(int i=0; i<(n); ++i)
#define fixed_setprecision(n) fixed << setprecision((n))
#define pai 3.1415926535897932384
#define NUM_MAX 2e18
#define NUM_MIN -1e9
 
using namespace std;
using ll =long long;
using P = pair<int,int>;
 
int main(int argc, const char * argv[]) {
    int N, X;
    cin >> N >> X;
    string s;
    cin >> s;
    
    rep(i, N){
        if(s[i] == 'o') X++;
        else if(s[i] == 'x') if(X>0) X--;
    }
    cout << X << endl;
    
    return 0;
}
```

##[C - Super Ryuma](https://atcoder.jp/contests/abc184/tasks/abc184_c)

```C++:C++
#include<iostream>
#include<vector>
#include<algorithm>
#include<iomanip>
#include<utility>
#include<iomanip>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<cctype>
 
#define rep(i,n) for(int i=0; i<(n); ++i)
#define fixed_setprecision(n) fixed << setprecision((n))
#define pai 3.1415926535897932384
#define NUM_MAX 2e18
#define NUM_MIN -1e9
 
using namespace std;
using ll =long long;
using P = pair<int,int>;
 
 
int main(int argc, const char * argv[]) {
    int r1, c1, r2, c2;
    cin >> r1 >> c1 >> r2 >> c2;
    
    int r = abs(r2 - r1);
    int c = abs(c2 - c1);
    
    int res=0;
    if(r==0&&c==0){
        res=0;
    }else if(r+c<=3 || r==c || r==-c){
        res=1;
    }else if(r+c<=6 || (r+c)%2==0 || abs(r - c) <= 3 ){
        res=2;
    }else{
        res=3;
    }
    cout << res << endl;
    
    return 0;
}
```

440パフォーマンス！
ふぉおおおおおおおおおおお！！
グラデーションをつける最も簡単なメソッド【Swift 5】


こんにちは、@Zhalen です。

名前は「ツァーレン」です。


`UIView`にグラデーションをつける最も簡単なメソッドを作ったのでご紹介します。

#Method
```swift

//Gradation
extension UIView {
    func gradient(top: UIColor, bottom: UIColor) {
        let gradientColors: [CGColor] = [top.cgColor, bottom.cgColor]
        let gradientLayer: CAGradientLayer = CAGradientLayer()
        
        gradientLayer.colors = gradientColors
        gradientLayer.frame = self.bounds
        self.layer.insertSublayer(gradientLayer, at: 0)
    }
}

```


#Usage

余計なことは言いません。このようにお使いください。

```swift

view.gradient(top: .red, bottom: .blue)
```


#それではまた。
U-2Netをつかう。

![u2netqual.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/44a7eb2d-8202-89b5-6ae4-85bdef08b244.png)

画像内の顕著なオブジェクトをセグメントしてくれるモデル。

#手順

#####1、[U2-NetのGitHubリポジトリ](https://github.com/NathanUA/U-2-Net)をクローン

```shell

git clone https://github.com/NathanUA/U-2-Net.git
cd U-2-Net/
```

#####2、事前学習済みモデルを[リポジトリのリンク](https://drive.google.com/file/d/1rbSTGKAE-MTxBYHd-51l2hMOQPT_7EPy/view)からダウンロードし、指定のディレクトリに配置

```shell

mkdir saved_models/u2netp/
```

#####3、とりあえずPythonで試してみる。
リポジトリで配布されているモデルは１７４MBと４MBの２種類あって、軽量の方をつかう場合は、model_nameをu2netpに書き換えます。

あと、PytorchでデフォルトはCudaデバイス（GPU）をつかう設定になっているので、CPUで実行する場合は[torch.deviceを切り替えます](http://arduinopid.web.fc2.com/Q5-37.html)。

```python:u2net_test.py
model_name='u2net'#u2netp
```

```shell
python u2net_test.py
```
４MBのモデルでこの性能。すごい。
![im_21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/e9eefee8-df57-54a1-8cfa-6a39a9947826.png)![im_21 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/0e8eb24c-f64c-ceec-6059-938a7318751c.png)

🐣
****
お仕事のご相談こちらまで
rockyshikoku@gmail.com

Core MLを使ったアプリを作っています。
機械学習関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
[ホームページ](https://sites.google.com/view/mlboydaisuke/%E3%83%9B%E3%83%BC%E3%83%A0)
PytorchモデルをONNX経由でCoreMLモデルに変換する（あえてね）

CoreMLTools4.0からPytorchモデルを直接（Traced_Model経由で）変換できるようになりました。
旧式のONNX経由で変換するやりかたは非推奨になったのだけど、とはいえ「直接変換はできない」かつ「旧式ONNX方式だと変換できた」ケースもあったので、書いておくです🐣

1.PyTorchモデルをONNXにエクスポート


```python

x = torch.randn(1, 3, 224, 224, requires_grad=True).cuda() #ダミーインプット(batch_size,color_channel,width,height) モデルがCuda使ってるなら、.cuda()

torch.onnx.export(torch_model,   # モデル
                  x,   # ダミーインプット
                  "torch_model.onnx",   # 保存パス
                  export_params=True,   # モデルの重みも保存するか
                  # opset_version=10,   # エクスポートするONNXのバージョン
                  # do_constant_folding=True,  # 最適化のために定数畳み込みを実行するかどうか
                  # input_names = ['input'],   # the model's input names
                  # output_names = ['output'], # the model's output names
                  dynamic_axes={'input' : {0 : 'batch_size'},
                                'output' : {0 : 'batch_size'}})
```

2.CoreMLTools ONNX_CoreMLをインストール

```shell

pip install coremltools==3.4
pip install onnx_coreml
```

3.ONNXをCoreMLに変換

```python

from onnx_coreml import convert

mlmodel = convert("torch_model.onnx")
mlmodel.save("torch_model.mlmodel")
```

🐣
****
お仕事のご相談こちらまで
rockyshikoku@gmail.com

Core MLを使ったアプリを作っています。
機械学習関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
[ホームページ](https://sites.google.com/view/mlboydaisuke/%E3%83%9B%E3%83%BC%E3%83%A0)
「Delphiなんかで開発していて恥ずかしくないの？」

エンバカデロ社 URL: [Delphi: 概要 - エンバカデロ・テクノロジーズ](https://www.embarcadero.com/jp/products/delphi)

## この記事は

[Develop fun!を体現する Works Human Intelligence Advent Calendar 2020](https://qiita.com/advent-calendar/2020/whi)
[Develop fun!を体現する Works Human Intelligence #2 Advent Calendar 2020](https://qiita.com/advent-calendar/2020/whi-2)

煽り記事的タイトルですが Works Human Intelligence アドベントカレンダーの投稿練習です。

## プログラミング言語に優劣はあるのか

[Delphiで湯婆婆する](https://qiita.com/e99h2121/items/0aba0ce4b5b4d1c27505) を投稿したらそれなりに面白がってもらえたようなのでDelphi（Object Pascal）というプログラミング言語の良いところを書いてみます。結論を先に書いてしまうと、言語に向き不向きはあっても優劣なんてないわけです。たまに表題のように煽られる弊社ではありますが、それを中の人としてどう向き合うべきなのか、という意味であらためてDelphiについて考えてみました。

### 事実
弊社内ではDelphiとCOBOLをいまでも保守に使っており、今回ここではDelphiについて書きます。
なんで？と言われるとなんででしょう、現在の旗艦プロダクトのVersion Upgradeがあった過去、もう20年近く前なのでしょうか、

- 業務アプリたるもの安定を重視すべき。「枯れた技術」のほうが安定している。

のような理由をもってそうしてきたからとイチ開発としては理解しています。だけでなく、「[今も改良が続くPascal/Delphi言語の栄枯盛衰](https://news.mynavi.jp/article/programinglanguageoftheworld-22/)」のような記事を見ると教育用言語として、「とっつきやすい」という利点があったものと私は感じます。


### 世界にプログラミング言語はいくつあるのか

[250という数が最も説得力がある](https://techracho.bpsinc.jp/oasist/2018_12_24/65739#:~:text=1.%20%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E8%A8%80%E8%AA%9E%E3%81%AE%E6%95%B0,%E3%81%A8%E8%A8%80%E3%82%8F%E3%82%8C%E3%81%A6%E3%81%84%E3%81%BE%E3%81%99%E3%80%82) らしいです。

[Delphiが24周年だそうで](https://kabukawa.hatenablog.jp/entry/2019/02/14/153012#Delphi-is-%E4%BD%95)...2019年に24周年を迎えたそうで。
[TIOBEプログラミング言語ランキング](https://news.mynavi.jp/article/20190910-891939/) では堂々13位だったようです。
往年より[得意の逆ハリ](http://ikadoku.blog76.fc2.com/blog-entry-950.html) をしたくてやっているわけではなくそれなりに根拠があってDelphiを当時選択、使ってきたと思います。

### 向き不向き

プログラミング初学者を「プログラミング楽し～い！」と感じさせるには非常に適した言語だったと思います。

動画：[ボタン置いてHello World1行書いたら動く。](https://www.youtube.com/watch?v=Ob0gHLQM0mU)

[![Delphi参考](http://img.youtube.com/vi/Ob0gHLQM0mU/0.jpg)](http://www.youtube.com/watch?v=Ob0gHLQM0mU)

老年に安心、ホームページビルダー並みなのではないでしょうか。なので[湯婆婆](https://qiita.com/e99h2121/items/0aba0ce4b5b4d1c27505)も平日の朝ちょっと手を動かしたらできました。


### 得意不得意

というだけではそれでお金を頂戴している身としては少し足りません。他に良いところといえば、コンポーネントを拡張して作るのが簡単です。日曜大工的に[窓の杜](https://forest.watch.impress.co.jp/)に公開するようなアプリを作るには便利だったのだと思います。[Github](https://en.wikipedia.org/wiki/GitHub)時代以前の話だとおもいます。

ただ一方、きょうび、ライブラリが多くて、テストも書きやすくてなんぼ。そうです。さすがにJavaができないと始まらない。

## レガシー Delphi は過去の話

ということで見ていただきたい最近の我々のプロダクトは、[さすがにWebアプリケーションになっています。](https://www.works-hi.co.jp/products/hcm/talent-search) 逆を言えばそうでもないとプロダクトとして改善も難しい。基本はJava、JavaScriptができないと開発にならないです。Delphiは保守のちょっとしたときに「ソース引っ張り出すのめんどくせ～」と思いながら、申し訳程度に不具合として直す作業をしています (個人の感想です)。

### 言語としてつぶしがきく、競技人口が多い

選手層が厚い言語のほうが優れたものにたどり着きやすい。選択肢が多い。
業務アプリケーションとして、という主軸は今も昔も変わらないですがその点で弊社も常識的なことを考えていると思います。

Java, JavaScriptほか理由があればお好きな言語でも、弊社も割と常識を受け入れて楽しく開発をしています。弊社の開発が枯れた技術だけを、ましてや「疑いもなく使っている」ということはないので安心していただけたらと思います。いや誰向けのメッセージかわからないが。


## モダン Delphi の現在

会社的にも紆余曲折があって勝手なシンパシーを感じずにはいられませんが、エンバカデロ社になったDelphiは、以下であそべるようです。先に書いた通り休日にたしなむには相変わらず楽しいツールの一つだと思います。

https://www.embarcadero.com/products/delphi/starter/free-download

以上Delphiを振り返ってみました。
JavaScript BigIntで階乗計算

階乗を計算したい、というより、BigIntの使い勝手がどんな感じか知りたかったので…

~~~html:index.html
<!doctype html>
<html type='ja'>
<head>
<meta name='viewport' content='user-scalable=no,width=device-width,initial-scale=1'>
<meta charset='utf-8'>
<title>階乗算出(BigInt使用)</title>
<style>
#factorialNum {
    width: 72px;
}
#factorialResult {
    width: 95vw;
    max-width: 800px;
    height: 200px;
}
div.f {
    border: 1px gray solid;
    padding: 4px;
    margin: 4px;
    display: inline-block;
}
</style>
</head>
<body>
階乗算出(BigInt使用)<br>
<div class='f'>
上限設定<br>
<select id='t'>
<option value='1'>1</option>
<option value='5' selected>5</option>
<option value='10'>10</option>
<option value='20'>20</option>
<option value='30'>30</option>
<option value='60'>60</option>
<option value='120'>120</option>
<option value='180'>180</option>
<option value='300'>300</option>
<option value='600'>600</option>
<option value='3600'>3600</option>
</select>秒
<input type='number' value='5000' id='factorialNum'>!
</div>
<input type='button' value='算出' id='cb'><br>
<textarea readonly id='factorialResult'></textarea>
<script>
'use strict';
document.getElementById('cb').addEventListener('click', function() {
    if(this.disabled) return;
    executeFactorial();
});

let time,
    n,
    start,
    end,
    result,
    i,
    execFlg;

function executeFactorial() {
    time = t.value * 1000;
    n = (isNaN(factorialNum.value) || factorialNum.value < 0) ?
        5000 : Math.floor(factorialNum.value);
    factorialNum.value = n;

    start = Date.now();
    end = start;
    factorialResult.value = '計算中';

    result = BigInt('1');
    i = 0;
    execFlg = true;

    cb.disabled = true;
    setTimeout(calc);
}

function calc() {
    const ct = Date.now();
    while(i < n && Date.now() - ct < 250) {
        result = result * BigInt(++i);
        end = Date.now();
        if(end - start >= time || i === n) {
            execFlg = false;
            break;
        }
    }
    if(i >= n) execFlg = false;
    factorialResult.value = '計算中 : ' + Math.floor((end - start) / 1000) + 'sec. / ' + i + '!';
    if(execFlg) setTimeout(calc);
    else {
        factorialResult.value += "\n計算結果変換中";
        setTimeout(function(){
            const resultStr = String(result);
            factorialResult.value = (end - start) / 1000 + 'sec. / ' + i + "! / (" + resultStr.length + '桁)\n' + resultStr;
            cb.disabled = false;
        });
    }
}

if(window.BigInt === undefined) {
    factorialResult.value = 'BigIntが未サポートです';
    factorialResult.readonly = true;
    t.disabled = true;
    factorialNum.disabled = true;
    cb.disabled = true;
}
</script>
</body>
</html>
~~~

**[設置デモ](https://akebi.jp/temp/factorial/index_bi.html)**
【Python3.8~】配列などを定義と同時に書き換える【tips】

#はじめに

>**～配列の初期化をコンパクトにしたい～**

その願い、実現できます。そう、3.8~ならね。

#どうやるか

```python
(変数名 := 定義)[スライス] = 変更
```
注) スライスしない場合も`[:]`などとつけないとエラーを吐きます。

例えば
>**～対角線上に1~9が並んでる正方行列に、3行おきに1を足した行列を定義したい～**

そんな謎のシチュエーションもこの通り

```python
import numpy as np
(x:=np.diag(range(10)))[::3] += 1
x
```

```:out
array([[ 1,  1,  1,  1,  1,  1,  1,  1,  1,  1],
       [ 0,  1,  0,  0,  0,  0,  0,  0,  0,  0],
       [ 0,  0,  2,  0,  0,  0,  0,  0,  0,  0],
       [ 1,  1,  1,  4,  1,  1,  1,  1,  1,  1],
       [ 0,  0,  0,  0,  4,  0,  0,  0,  0,  0],
       [ 0,  0,  0,  0,  0,  5,  0,  0,  0,  0],
       [ 1,  1,  1,  1,  1,  1,  7,  1,  1,  1],
       [ 0,  0,  0,  0,  0,  0,  0,  7,  0,  0],
       [ 0,  0,  0,  0,  0,  0,  0,  0,  8,  0],
       [ 1,  1,  1,  1,  1,  1,  1,  1,  1, 10]])
```

例えば
>**～対角線上に1~9が並んでる正方行列に、自身の左右を反転させた行列を引きたい～**

そんな場合もこの通り

```python
import numpy as np
(x:=np.diag(range(10)))[:] -= x[:, ::-1]
x
```

```:out
array([[ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
       [ 0,  1,  0,  0,  0,  0,  0,  0, -1,  0],
       [ 0,  0,  2,  0,  0,  0,  0, -2,  0,  0],
       [ 0,  0,  0,  3,  0,  0, -3,  0,  0,  0],
       [ 0,  0,  0,  0,  4, -4,  0,  0,  0,  0],
       [ 0,  0,  0,  0, -5,  5,  0,  0,  0,  0],
       [ 0,  0,  0, -6,  0,  0,  6,  0,  0,  0],
       [ 0,  0, -7,  0,  0,  0,  0,  7,  0,  0],
       [ 0, -8,  0,  0,  0,  0,  0,  0,  8,  0],
       [-9,  0,  0,  0,  0,  0,  0,  0,  0,  9]])
```

#さいごに
何気に便利なセイウチ演算子活用シリーズが増えてゆく...
【VSCode】IntelliSense のサジェストが一つしか表示されない

# TL;DR;

![dLayW.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280975/de17bf8c-cfcd-f0ff-3392-c000e819d4f8.gif)
[Visual Studio Code intellisense showing one suggestion at any time](https://stackoverflow.com/questions/64789393/visual-studio-code-intellisense-showing-one-suggestion-at-any-time) より

# 詳細

IDEの問題でInteliSceneceが効いてくれないことはよくあることです。特に、VSCodeのC#はアップデートでロクに動かなくなることが国交ある印象で、デバッグしてるのかって思うぐらいです。なのでいつものようにバージョンを落としたりIssues漁ったりしていたのですが、同じ症状は見られず…

試しにTSとC++で試してみたところ、同じように1つしか出ない！？ということでエディタ本体側を疑いだして、古い記事も対象にして探し始めました。

結果、表示領域の高さが1Line分になっていたというオチ。
（結構な時間悩んでいたのでGIFみて草枯れました）

# まとめ

**あ ほ く さ**
ローカルの openssl で暗号化したファイルがCIの openssl で復号に失敗したため、CIイメージを使って暗号化して対応した

# 記事の内容

タイトル通り。

CircleCIでプライベートなファイルを暗号化してレポジトリ管理する
https://qiita.com/tomoima525/items/dbeeb6d451304333b17d

上記の記事を参考にしたときに openssl のバージョン違いでつまづいたため、その問題と対応を書きます。
下書きのままかなり置いていたので各バージョンが古いです。

# 各環境の openssl

- CI用dockerイメージ (ruby:2.6.3) に入っていた openssl
  - `OpenSSL 1.1.0j  20 Nov 2018`
- ローカルの openssl
  - `OpenSSL 1.0.2s  28 May 2019`

# 発生した問題

ローカルの openssl を使った暗号化ファイルをコミットして、CircleCI で復号しようとしたら `bad decrypt` となって失敗してしまった。

# 対応

CI用dockerイメージ（ruby:2.6.3）をローカルにプルして立ち上げ、 bash でログインして openssl を使って暗号化した。そのファイルをコミットしたら、CircleCI で無事に復号できた。
PostgreSQL: デリミタをタブにしてインポート・エクスポート

PostgreSQL でデリミタをタブにしてインポート・エクスポートをするコマンド

## エクスポート

```sql
psql -h host_name -U user_name db_name -c "SELECT * FROM table_name WHERE condition;" -AF $'\t' --no-align > file_name.tsv
```

SQLの実行結果に絞ってエクスポートできます。

CSV のようにタブ区切りになりますが、 実際は CSV ではなく SQL の実行結果です。


## インポート

```sql
psql -h host_name -U user_name db_name -c "\copy table_name FROM 'file_name.tsv' DELIMITER E'\t' CSV HEADER"
```

COPY でファイルから読み込むことはスーパーユーザにしかできません。 `\copy` を使います。

HEADER は1行目がヘッダであることを示します。 インポートするときは1行目をヘッダとしてインポートの対象から除きます。
スプレッドシートでUNIX timeを日時に変換する方法

ログとかを適当にスプレッドシートに取り込んだときに、日付が読めなくて困るのでメモ

たとえば `2020/11/23 00:00:00` の場合UNIX timeは
`1606057200` となります。これを人間が読めるようにしたい。



| UNIX time | ＋９（日本時間） | 日付 | 時刻 |
|:-----------|:------------|:------------|:------------|
| 1606057200 | =A2 + 32400 | =(B2 / 86400)+date(1970,1,1) | =TEXT(B2 / 86400,`"hh:mm:ss"`) |
（↑テーブルの中で絵文字をエスケープする方法がわからん :mm:）


計算するとざっくりこんな感じになります。
![スクリーンショット 2020-11-23 3.15.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7132/625bd01b-d0b0-02d9-212c-aae5921a7ea0.png)





## 
本当は分単位で取り出してまとめたかったのだけど、TEXT関数の

`mm - 2 桁の月名、または時刻の分。時刻の時と秒とともにこのコードを指定していない場合は、月名が使用されます。`

という地獄のような仕様・・・
Lambdaで日付を扱うときにはまった話

## タイトルの結論
LambdaのtimezoneはUTC(協定世界時)がデフォルトなので、時間を扱うときに時がずれていました。
なので、timezoneをasia/tokyoにする必要がありました。

## Lambdaでtimezoneをasia/tokyoにする方法
Lambdaの環境変数に、
変数名に `TZ`をセットします。その値に `Asia/Tokyo` を設定します。


Lambdaで環境変数を使う方法は以下のURLを参照ください。
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/configuration-envvars.html
【JavaScript】clientWidthプロパティでは小数値は取得できない

JSで横幅や高さを取得する処理を実装することはよくあると思います。
その際に、よく使われるのは

```
# 横幅取得
element.clientWidth

# 高さ取得
element.clientHeight
```
上記だと思います。
ただし、`clientWidth` や `clientHeight`プロパティは整数値に丸め込まれてしまいます。

僕はこれを知らずに`clientWidth` や `clientHeight`を使ってどはまりました。
横幅や高さを取得した上で計算する際に、小数値が丸め込まれてしまうと計算される値がずれてしまいます。

## 小数値まで含まれた値が欲しい
タイトルにもあるように、getBoundingClientRect()メソッドを使います。

```
# 横幅取得
element.getBoundingClientRect().width

# 高さ取得
element.getBoundingClientRect().height
```

ちなみに、`getBoundingClientRect()`は要素の横幅・高さだけでなく、ビューポートに対する位置も取得できます。

## まとめ
最近は、バックエンドだけでなく、フロントエンドの開発も行うようになりました。
そんなフロントエンド初心者の僕は、基本的に要素の寸法と、そのビューポートに対する位置を取得したいときは、
`getBoundingClientRect()` を使えば良さそうだと思いました。

`clientWidth` や `clientHeight`を使うメリットなどがあれば教えてください。
AtCoder Beginner Contest 124 D - Handstand

## 概要

解説ACした問題の[@hirokihello](https://twitter.com/maxyasuda)の反省log

## 問題

https://atcoder.jp/contests/abc124/tasks/abc124_d

1と0が適当に並ぶ列がある。

K回ひっくり返せるが、K回ひっくり返した後の連続する1の最大部分列の長さを求めよ

## 自分の思考

全然思いつかなかった....

何回かひっくり返す時にどの場所をひっくり返せばいいのかわからなかった。

漠然と、0が一番長いところと考えたが、(左右はどちらも1の列なので確実に大きくなる)、それが既存の1の最大部分列より長くなることを確信して導出できなかった。

## 正解で必要な思考

簡潔に言うと、0と１にまたがる部分でひっくり返すことはないと言うことである。

これがまず前提となる。

まずK=１の時を考える。

その時０の部分列を反転させ、左右の1とくっつけることで最大となることは想像できると思う。

またがって反転させた時、それは最大でも0の最大部分列ぶんの長さで、左右両方にくっつけることはできない。よって0の部分のみを反転させることで左右両方をくっつけることができるようになるので最大になる。

2回できる時も同様である。

1回目でどこかにまたがってしまうと、そこの最大でも0の最大部分列分の長さにしかならない。

例えば

1111000111111
を
1000111111111

としても最大部分列にはならない。この場合右側しかくっつけられていないからである。左右(なければ右端・左はじどちらか)をくっつけられるように0の連続を変更するのがその変更でもっとも最大を作れるのである。

1111000111111
を
1111111111111

にすることで最大を得られた。

一回あたり最大を取るのはこの戦略であり、これをn回繰り返すことで最大が得ることができる。

またn>=２について、他のブログの図などを参照してほしいが、あいだにあるものを一気にその両隣の部分列までやってしまっても結局それを反転させることが必要なので最終的なひっくり返す回数は変わらない。

00110001100


について、2回ひっくり返すことを考える

例えば最初と2番目の0の部分列を最終的に1にすることを考えると


0回目: 00110001100
1回目: 11110001100
2回目: 11111111100

とやることと、


0回目: 00110001100
1回目: 11001111100 (0011000をまとめて反転させた)
2回目: 11111111100

となり、結局それは最終的に反転させたいものの個数分の回数となる。

これの前提となるのは、選び方が0で始まり、0で終わるような部分だからだが、そのように選ぶのが最適なのは上記で述べたとおりである。

## 最終的な解法

上記の前提を元に、どこで最大共通部分列を作れるかをしゃくとり法とかでとけば良い。

上記の考察が頭ではわかってもいまいち納得が行かないのが少し悔しい