OmniAICreator/Qiita-1.07M huggingface dataset:
API23未満でTextViewにsetDrawableTintを使う

# はじめに
TextViewにアイコンを入れた際、色を付けるときにdrawableTintを使いたいですが、API23以降なので、minSDKによっては使えません。
その解決法と学びを記します。

# コード

```kotlin:drawableStart/Endを利用している場合
@BindingAdapter("drawableTintCompat")
fun TextView.setDrawableTintCompat(color: Int) {
    compoundDrawablesRelative.forEach {
        it?.setColorFilter(color, PorterDuff.Mode.SRC_IN)
    }
}
```

```kotlin:drawableLeft/Rightを利用している場合
@BindingAdapter("drawableTintCompat")
fun TextView.setDrawableTintCompat(color: Int) {
    compoundDrawables.forEach {
        it?.setColorFilter(color, PorterDuff.Mode.SRC_IN)
    }
}
```

```xml:レイアウト(databindingが必要)
    <TextView
        app:drawableTintCompat="@{@color/hogehoge}"/>
```

# ポイント
sdk21以上であれば、RTLの関係でdrawableStart/Endが推奨されています。
馴染みのある`getCompoundDrawables`はStart/Endで指定していると取得できないことがあるため、`getCompoundDrawablesRelative`を使いましょう。
https://developer.android.com/reference/android/widget/TextView.html#getCompoundDrawablesRelative()
また、Databindingを利用する関係で、ActivityやFragmentで使う際はDatabindingUtilでinflateやbindをしてレイアウトを設定する必要があります。
(xmlを<layout>で囲んだだけではbindされないため、そのままsetContentViewとかをしてもdrawableTintCompatは動きません)

# おまけ
塗る処理で、setColorFilterではなくsetTintを使う場合は注意が必要です。

```kotlin
@BindingAdapter("drawableTintCompat")
fun TextView.setDrawableTintCompat(color: Int) {
    compoundDrawablesRelative.forEach {
        it?.apply {
            setTint(color)
            setTintMode(PorterDuff.Mode.SRC_IN)
        }
    }
}
```
この場合、drawableに対して直接Tintをしているので、他で使っている同じdrawableリソースの色も変わってしまいます。
色が単色の場合・毎回定義している場合は問題ないですが、そうでない場合は`mutate`を呼んで上げる必要があります。

```kotlin
@BindingAdapter("drawableTintCompat")
fun TextView.setDrawableTintCompat(color: Int) {
    compoundDrawablesRelative.forEach {
        it?.mutate()?.apply {
            setTint(color)
            setTintMode(PorterDuff.Mode.SRC_IN)
        }
    }
}
```

mutateについては、以下の記事に詳しく書かれています。
http://y-anz-m.blogspot.com/2010/10/androiddrawable-mutations.html

# 最後に
drawablesがnullになってるのはなんでだろう・・・。
と思っていたらまさか別の取得方法があったとは。
compoundDrawablesRelative、忘れないでしょう。
クリックした場所に要素を移動させる！(timeclock DAY1)


#今回はjavascriptを用いて要素をクリックした場所に移動させる

というのをやっていきます。
*初心者*が自分で考えて作ったものなので多分最適化したら3行ぐらいで終わるかもしれません…**自身がない方**に採用してほしい…( ;´･ω･`)

##クリックした場所移動
```javascript
window.onload = function(){
//まず動かす対象を取得
var ball = document.getElementById("ball"); 
//対象が動くフィールドとなる部分を取得
 var contents = document.getElementById("contents");
  
//フィールドが押されたときにイベント発生
varcontentsaddEventListener("click",function(){
//押された場所を取得
   var x = event.x;
   var y = event.y;　
//押された場所に移動
   ball.style.left = x + "px";
   ball.style.top = y　+ "px";
},false)
```
これだけです！
引っ掛かるところは関数内部かな？

```javascript
var x = event.x;
var y = event.y;　
```
ここの中では**Ｘ軸からの距離、Y軸からの距離**をそれぞれとってきています。
Javascript では座標を指定するときなどは左上に(0,0)があると考えて、

*Ｘ軸が正の方向にいくときに増加して、
Y軸が負の方向にいくときに減少します。*
なんかすごいわかりずらくてこんがらがりますがそんなもんだと覚えましょう…( ;´･ω･`)

そうして上で得られた変数x,yをここで使います。

```javascript 
ball.style.left = x + "px";
ball.style.top = y　+ "px";
```
落ち着いて分けて考えると、
*ball(変数)のstyle(cssの設定)のtop(上からの距離)=変数px*
です！topはabsoluteと設定したときによくみますよね？あれです…
同じようにyもleft(左からの距離)としています。
→変数 + "px"の部分
　ここはjavascriptでstyleの指定をする際に変数(数字)は""をつけて、px(文字)ではつけないという基本的な原則に乗っ取ってます…

##まとめ
今回の処理では
**変数に現在位置代入！からの
　変数で場所指定！**
という単純な動作をしています。
ポチポチ押して動くのも結構楽しいのでやってみては？？？

###次回の時　旅さん
さーて来週(明日ぐらい)の時　旅さんはー？
俺です。
この動きを導入するときに一緒に導入した移動距離と時間を比例関係におく
っというのをここで紹介したいと思います。
そもそも今日紹介しようとしたけど分量が長くなったのでやめました…
また明日も…見てくれよな！

###なに紹介してる？？
紹介しているものとしては*現在作成しているもののなかで実装した機能*たちです。

タイトルの後ろには現在作成しているものの名前とそれが今何日目なのかを表してます…
こんな感じのものつくりたいっていうのと似てたらそれがついてるやつを追ってけば少しずつ完成していくはずです。
それかそこから紹介してそうだなーっていうのを予想して探してみてください(激ムズ)
要望あったり、面白そうなアイデアくれたら作ります。今は経験が必要なので…

以上！
あなたとともに時を越える旅を？
素因数分解、約数列挙

```python

def prime_decomposition(n):
    table = []
    for i in range(2, int(n ** 0.5) + 1):
        while n % i == 0:
            table += [i]
            n //= i
        if n == 1:
            break
    if n != 1:
        table += [n]
　　　# 素数の場合
    return table
```
素因数分解したリストを返すプログラム。


こちらは約数列挙。競プロでは必須である。まず、リストで欲しい場合。

```python

def make_divisors(n):
    divisors = []
    for i in range(1, int(n**0.5) + 1):
        if n % i == 0:
            divisors += [i]
            if i != n // i:
                divisors += [n // i]

    # divisors.sort()
    return divisors
```
setで欲しい場合はこちら。

```python

def make_divisors(n):
    divisors = set()
    for i in range(1, int(n**0.5) + 1):
        if n % i == 0:
            divisors.add(i)
            divisors.add(n // i)
    return divisors # sortしたリストで欲しい時はsorted(divisors)

```
【chrome extension】ダウンロードが"完了したとき"にアクションを行う方法

# この記事は？

`chrome.downloads.onCreated.addListener()`を使うと「ダウンロードシーケンスを開始した時」になってしまいますね。
ダウンロード先を決めるウィンドウが開いている時すでにリスナーは発火しているわけです。
そうではなく「ダウンロードし終わった時」にアクションを起こしたい場合はどうすればいいのかを解説します。

# コード紹介

まずは結論から、ということでコードをそのまま紹介します。

``` JavaScript
let myDownloadItem = undefined

chrome.downloads.onCreated.addListener((downloadItem) => {
  // 後で使用する。必要なければonCreated()の部分は不要
  myDownloadItem = downloadItem
})

chrome.downloads.onChanged.addListener((downloadDelta) => {
  let nowState = downloadDelta.state
  if (nowState && nowState.current == 'complete') {

    // myDownloadItemを使用して必要な処理を行う

    myDownloadItem = undefined // 必要ないかもしれない
  }
});
```

# 解説
onChanged.addListener()でコールバック関数に渡されるのは`DownloadItem`ではなく`DownloadDelta`です。
downloadDeltaとは簡単に言うと「DownloadItemのプロパティの内、適当なものが変化したもの」です。
学校の物理の授業で何らかの値`x`が時間経過などで変化したものを`x'`と書いたのと同じノリです。

原文を載せておきます。
>An object representing the downloads.DownloadItem object that changed, and the status of all the properties that changed in it.
https://developer.mozilla.org/ja/docs/Mozilla/Add-ons/WebExtensions/API/downloads/onChanged#addListener_syntax

さて、DownloadDeltaですが、`console.log()`で確認したところ、以下のような感じでした。

``` JSON
{
  "endTime": {
    "current": "2019-10-26T04:36:57.568Z"
  },
  "id": 82,
  "state": {
    "current": "complete",
    "previous": "in_progress"
  }
}
```

ここで注目するべきは`state`です。
この`state`は[DownloadItemのプロパティのstate](https://developer.mozilla.org/ja/docs/Mozilla/Add-ons/WebExtensions/API/downloads/DownloadItem)です。
その型は[downloads.State](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/downloads/State)となっており、その値は以下の3つです。

- in_progress
- interrupted
- complete

実装者はこれら3つの値を判別しif文でも使用して適切に処理を分けることが可能になるわけですね。

これで解説は以上です。

# 宣伝
今回紹介したテクニックを用いて初めてのChrome extensionを作成しました。
ReDownload: https://chrome.google.com/webstore/detail/redownload/ofjdipkapbcippofdocjaefbgekmkoai?utm_source=chrome-ntp-icon


# 参考資料
stack overflow: [How to make Chrome Downloads API wait until a download has ended?](https://stackoverflow.com/questions/51600832/how-to-make-chrome-downloads-api-wait-until-a-download-has-ended)
ESXi環境memo

https://www.google.com/search?q=ESXi%E7%92%B0%E5%A2%83&ei=ZW_DXf27G62ImAXMja6oDQ&start=10&sa=N&ved=0ahUKEwi9gpfU9dblAhUtBKYKHcyGC9UQ8NMDCKwB&biw=1146&bih=619

https://qiita.com/mins2112miku/items/7f68336e02b73a1c99f6

https://qiita.com/HishiM/items/41794fcba62e3924e5a2

使えるようにメモ失礼します。
今、LISTENなプロセスを調べたい時

# 今、LISTENなプロセスを調べるコマンド

```
$ sudo lsof -i -P | grep "LISTEN"
```



##ポート番号を指定する場合

```
$ lsof -i:8080 -P | grep "LISTEN"
```


参考: [lsofコマンド入門](https://qiita.com/hypermkt/items/905139168b0bc5c28ef2)
AWKスクリプト・インタプリタ

# awk（オーク）コマンドとは
- パターン走査およびパターン処理の言語。
- `awk 'パターン {アクション}' ファイル名`などと指定します。
- 以下、例文をメモ置き。後にも追記予定。


## すべての行の１列目を表示
`awk '{ print $1 }'`


## if文。3列目がid_XXXX:YYYYYなら、表示
```awk '{ if ($3 == "XXXX_id:YYYY" ) print `3列目がid_XXXX:YYYYなら、表示`;}'```

## 参考
[AWK リファレンス](https://shellscript.sunone.me/awk.html)
[【 awk 】コマンド（基本編）――テキストの加工とパターン処理を行う](https://www.atmarkit.co.jp/ait/articles/1706/02/news017.html)
[awkコマンド](http://unix.oskp.net/linux_command/awk.html)
[Awk 基礎文法最速マスター](http://www.ie.u-ryukyu.ac.jp/~e085739/awk.quick.all.html)
[AWK](http://research.kek.jp/people/yashiro/guide/QuickRef/Appli/awk.html)
[AWKのこういう時はどう書く?](https://qiita.com/hirohiro77/items/713d5bcf60fef7e88dfa)
あとこれもメモ: [データファイル処理に便利なUNIXコマンド](https://www.e.ics.nara-wu.ac.jp/~nogu/tips/unix_command.html)
WinAuthを使ってAzure ADのアカウントにMFAを設定する

# はじめに

WinAuthを使ってAzure ADのアカウントにMFAの設定をするとき少し分かりづらかったので、備忘として記事に残しておきます。スクリーンショットは公開できない情報ばかりでぼかしが多く見づらいですがご容赦ください。

# 前提
- WinAuthをインストールして使える状態になっていること ([WinAuth](https://winauth.github.io/winauth/))
- Azure ADにアカウントが存在すること

# 設定手順
## 1. My Appsポータルにアクセスする

MicrosoftのMy Appsポータルからアカウントの設定を開きます。
My AppsポータルにアクセスするとAzure AD認証を求められるのでMFAを設定するテナントのアカウントでサインインします。

**[My Appsポータル]**
https://myapps.microsoft.com/

## 2. [My Appsポータル] My Appsポータルからプロファイルを開く

右上のアバターをクリックして「プロファイル」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171575/c5ba81fc-21ed-ddfd-55bb-1b9c17d66bcf.png)


## 3. [My Appsポータル] プロファイルのアカウント管理から「追加のセキュリティ確認」を開く

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171575/dbd1a841-8944-51cf-1a05-44ec9fad26aa.png)

## 4. [My Appsポータル] 追加のセキュリティ確認で「Authenticatorアプリの設定」を開く

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171575/5c89d6f9-4c34-86e4-9b68-348d6c4d8e97.png)

## 5. [My Appsポータル] 【重要】「通知をオフにしてアプリを構成」をクリックする

**★この手順を忘れるとWinAuthでは設定できないので注意してください。**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171575/53e0bf99-d73d-3d2f-a529-0c1d3b5929ac.png)

## 6. [My Appsポータル] 秘密鍵の値をコピーする

秘密鍵は英数字16桁です。秘密鍵をコピーした後「次へ」をクリックします。
My Appsポータル側は一旦このままにしておき、次はWinAuth側を設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171575/d5d80071-ef88-4d06-d40e-743a53cb001d.png)

## 7. [WinAuth] WinAuthを立ち上げてAuthenticatorの設定を追加する

「Add」→「Authenticator」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171575/f7f70df9-edf6-b4a0-1738-53b7ea6065dc.png)

## 8. [WinAuth] My Appsポータルでコピーした秘密鍵を貼り付けて「Verify Authenticator」をクリックする

Nameには任意の名前を入力します。
1のテキストボックスにMy Appsポータルでコピーした秘密鍵を貼り付けて、「Verify Authenticator」をクリックします。秘密鍵はスペース付きで貼り付けても問題ありません。4に表示された6桁の数字をコピーしてMy Appsポータルに戻ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171575/3404d827-2dbe-a1ca-3212-b49cf74478f9.png)

## 9. [My Appsポータル] 「今すぐ確認」をクリックする

My Appsポータル側で「今すぐ確認」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171575/6ac50caf-6f33-918a-c266-b39d6f03d83c.png)

## 10. [My Appsポータル] 確認コードを入力して「確認」をクリックする

WinAuthでコピーした6桁の数字をテキストボックスに貼り付けて「確認」をクリックします。
以上でAzure AD側の設定は完了です。その後WinAuthに戻り、設定を完了します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171575/47887ca0-7a14-3eb4-eba7-0f9a30349d55.png)

## 11. [WinAuth] 「OK」をクリックして設定を完了
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171575/539ee74e-ad6e-1436-5966-e64cbcea2389.png)

WinAuthにNameで指定した名前でAuthenticatorが登録されていると思います。Azure ADにサインインする際に認証コードを求められた場合は、右の更新ボタンをクリックして表示される6桁のコードを入力してください。

## つぶやき

手順としては一般的なMFAの設定と変わらず簡単なのですが、Azure ADでは手順5の「「通知をオフにしてアプリを構成」をクリックする」がポイントです。必ず忘れないようにしてください。私はしばらく気付かず何度もURLを貼り付けてうまくいかないとハマってました...(\*'ω'\*)
ec-cube4でtailwindcssを導入する

ec-cube4に[tailwindcss](https://tailwindcss.com)を導入する手順

最初にec-cubeで使われているcss・jsは使わないので、package.jsonを削除する。

vueの設定とtypeScriptの設定が混じってるので、ひょっとしたら設定漏れあるかも。

参考元
[How to use TailwindCSS with Symfony's Encore](https://stefanbauer.me/articles/how-to-use-tailwindcss-with-symfonys-encore)
[tailwindcss Installation](https://tailwindcss.com/docs/installation/)

## webpackの導入
symfony4でwebpackを使うにはwebpack-encore-bundleを導入する必要がある。

手順は[公式](https://symfony.com/doc/current/frontend/encore/installation.html)を参考

```
composer require symfony/webpack-encore-bundle
```
インストール後にyarnでpackageをインストール。

```
yarn install
```

完了後にwebpack.config.jsが生成される。
最終的な中身はこうなる。

ec-cubeを使用しているので出力先をhtml/user_data/buildに設定。

```webpack.config.js
const Encore = require('@symfony/webpack-encore')

if (!Encore.isRuntimeEnvironmentConfigured()) {
  Encore.configureRuntimeEnvironment(process.env.NODE_ENV || 'dev')
}

Encore
// コンパイルされたアセットが保存されるディレクトリ
  .setOutputPath('html/user_data/build/')
  // Webサーバーが出力にアクセスするために使用するパブリックパス
  .setPublicPath('/html/user_data/build/').
  setManifestKeyPrefix('/html/user_data/build/').
  addEntry('app', './assets/js/app.ts').
  //.addEntry('page1', './assets/js/page1.js')

  // 有効にすると、Webpackは最適化を強化するためにファイルを小さな断片に「分割」します。
  splitEntryChunks().

  enableSingleRuntimeChunk().
  cleanupOutputBeforeBuild().
  enableBuildNotifications().
  enableSourceMaps(!Encore.isProduction()).
  enableVersioning(Encore.isProduction())

  // enables @babel/preset-env polyfills
  .configureBabel(() => {}, {
    useBuiltIns: 'usage',
    corejs: 3,
  }).
  enableTypeScriptLoader().
  enableSassLoader(function (options) {}, {
    resolveUrlLoader: false,
  }).
  enablePostCssLoader()

  // uncomment to get integrity="..." attributes on your script & link tags
  // requires WebpackEncoreBundle 1.4 or higher
  //.enableIntegrityHashes(Encore.isProduction())

  // uncomment if you're having problems with a jQuery plugin
  .autoProvidejQuery()

// uncomment if you use API Platform Admin (composer req api-admin)
//.enableReactPreset()
//.addEntry('admin', './assets/js/admin.js')

module.exports = Encore.getWebpackConfig()

```

## tailwindcssの導入
```
yarn add --dev @symfony/webpack-encore less-loader less autoprefixer postcss-loader tailwindcss
```

### webpack.config.jsに設定追加
LessLoaderとPostCssLoaderを有効化する。

```webpack.config.js
.enableLessLoader()
.enablePostCssLoader()
```

### postcss.config.jsの作成
PostCssLoaderを使うにあたってconfigファイルを作成
configファイルの任意の場所を指定
今回は./assets/config/tailwind.js


```postcss.config.js
let tailwindcss = require('tailwindcss');

module.exports = {
  plugins: [
    tailwindcss('./assets/config/tailwind.js'),
    require('autoprefixer'),
  ]
}

```

最後にscssにtailwindcssをインポートして終わり。

```app.scss
@import "~tailwindcss/base";
@import "~tailwindcss/components";
@import "~tailwindcss/utilities";
```
Theiaを隠してみた

[せっかく入れたTheia](https://qiita.com/woolk23/items/0ed23957f0b6cdc1321b)ですが、クラウドやVPSにそのままで入れたのではセキュリティ上の問題になります。そこで、Apacheにリバースプロキシを設定して、Apache を経由してアクセスするように配置しました。そのうえで認証やSSLを設定して、セキュリティを確保する狙いです。
Apacheの導入に特別なことはないので、本稿では導入後の設定について記載します。

# 認証設定
まずは認証設定からです。今回はDigest認証にしました。

sites-available/000-default.conf

```apache
<Location "/">
  AuthType Digest
  AuthName "DigestAuth"
  AuthUserFile /etc/apache2/.digestauth
  Require valid-user
</Location>
```

# リバースプロキシ設定
次にリバースプロキシ設定です。
Theiaは`yarn theia start ~/workspace`のように起動させるものとします。そうするとデフォルトのホスト名localhost、ポート3000で起動します。
TheiaへアクセスするURLを`http://example.com/theia/`とします。TheiaはWebSocketを使った通信も行うため、それについての設定も追加します。

mods-available/proxy.conf

```apache
ProxyPass /theia/services/ ws://localhost:3000/services/
ProxyPassReverse /theia/services/ ws://localhost:3000/services/
ProxyPass /theia/ http://localhost:3000/
ProxyPassReverse /theia/ http://localhost:3000/
```
/theia/services/を/theia/よりも前に設定しないと、全部/theia/で設定した方に持っていかれてしまいます。

# SSLの場合
SSLの導入自体はいくつか方法がありますが、今回は[Let's Encrypt](https://letsencrypt.org/ja/)を利用しました。
導入はコマンドで行い、設定ファイルも書き換えてくれます。その結果、以下のようになっていることを確認してください。

## httpでアクセスしたときにhttpsにリダイレクトする。
sites-available/000-default.conf

```apache
RewriteEngine On
RewriteRule ^ https://%{SEVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
```

## SSLの場合の認証設定
sites-available/000-default-le-ssl.conf
自動的に作られている設定ファイル中に、000-default.confと同じ認証設定が記載されているはずです。

```apache
<Location "/">
  AuthType Digest
  AuthName "DigestAuth"
  AuthUserFile /etc/apache2/.digestauth
  Require valid-user
</Location>
```

# しかし、これでは終わらなかった...
これで、httpでアクセスしてもhttpsにリダイレクトされ、ID/PWの入力ダイアログも表示されて「よしよし」:relaxed:と思ったのですが。。。
PCだとその通り動くものの、iPadだとTheiaにアクセスしたあと、スピナーがくるくるするばかりで何も表示されませんでした。
そう、Theia導入のきっかけはiPadでの開発環境構築です！折れ気味の気持ちを抱えつつ、[旅は続く](https://qiita.com/woolk23/items/a403d2619d941f278486)のでした。:confounded:
【作業記録】仮想通貨Botの作成

#仮想通貨売買bot作成までの作業を記録する

##目標
日利2％を安定して稼ぎだすBotの作成を行う

##動作環境
端末     ：iPad Air2（magic keyboard)
エディタ  ：Google collaborate
サーバ    ：cloud9

##基本構成
[文系でもわかる！Bitcoin自動売買トレードの始め方](https://ryota-trade.com/)を基にプログラムを作成していく。


##作業記録
| 作業日 | 作業内容 | 参考資料 | 作業ファイル |
|:-----------:|:------------:|:------------:|:------------:|
| 2019 / 11 / 8 | Qiitaで作業記録の立ち上げ | [Markdown記法　サンプル集](https://qiita.com/tbpgr/items/989c6badefff69377da7) |  |
| 2019 / 11 / 8 | LSTMの実装検討 | [LSTMでFX予測…](http://www.algo-fx-blog.com/lstm-fx-predict/ )| [LSTM_MODEL.ipynb](https://colab.research.google.com/drive/1_UrAceaty0m-QhVY5SAaNC25y57gTEIv?hl=ja) |
| column | column | column | column |

##作業日誌

###20191108
Qiitaに作業記録を作成
今後、作業する際にはここを起点にBot作成していく
Markdown記法は上記を参照する。

[こちら](http://www.algo-fx-blog.com/lstm-fx-predict/)
githubのREADMEに画像を載せる(爆速で)

githubのREADMEに画像を載せたい。

いろんなやり方があると思いますが、githubのissuesから画像のパスを作る方法が結構早いです。
(もう知っている方はすいません...)

「issues」の「New issue」より、新しいissueを作成する画面にいきます。

あとは、画像をスワイプして、待つだけ。
自動的に画像のパスを作ってくれます。
そのパスをコピーしてREADMEに貼り付けるだけです！
もちろん、issueは作る必要ないです。

![image.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270696/1076e238-720b-6014-0a8a-39d3ed912fe8.gif)

以上です！
Mac で Device Monitor を使用するときの注意

ネイティブはもちろん、 Unity で AR の開発とか、実機で確認中にログをモニタリングしたいときに役立つ `Device Monitor` ですが、いざ使うとなると大変だったのでメモ書き

# まずアプリケーションの場所

`/Library/Android/sdk/tools/lib/monitor-x86_64/monitor.app`

深すぎい！

# Java 入れる

8系を入れる。しかも最新だとダメ。動くけどクリックが反応しなかったり。
なので
https://www.oracle.com/technetwork/java/javase/downloads/java-archive-javase8-2177648.html?ssSourceSiteId=otnjp

ここから適当に古いやつを。。。(私は `8u111` での動作を確認しています。)

# まとめ

マイナーバージョンで動かなかった時は自分にアプリケーションを操作する才能がないと勘違いした。
nodeでnpmのバージョンが違うと怒られた

## 現象


npm installしようとしたらこんなエラーが出て怒られた

```
$ npm install
WARNING: You are likely using a version of node-tar or npm that is incompatible with this version of Node.js.
Please use either the version of npm that is bundled with Node.js, or a version of npm (> 5.5.1 or < 5.4.0) or node-tar (> 4.0.1) that is compatible with Node.js 9 and above.
npm[14907]: ../src/node_zlib.cc:551:static void node::(anonymous namespace)::ZlibStream::Init(const FunctionCallbackInfo<v8::Value> &): Assertion `args.Length() == 7 && "init(windowBits, level, memLevel, strategy, writeResult, writeCallback," " dictionary)"' failed.
 1: 0x10003cf99 node::Abort() [/usr/local/bin/node]
 2: 0x10003bfbb node::AddEnvironmentCleanupHook(v8::Isolate*, void (*)(void*), void*) [/usr/local/bin/node]
 3: 0x1000da0e2 node::(anonymous namespace)::ZlibStream::Init(v8::FunctionCallbackInfo<v8::Value> const&) [/usr/local/bin/node]
 4: 0x100242aaf v8::internal::FunctionCallbackArguments::Call(v8::internal::CallHandlerInfo*) [/usr/local/bin/node]
 5: 0x100241ff1 v8::internal::MaybeHandle<v8::internal::Object> v8::internal::(anonymous namespace)::HandleApiCallHelper<false>(v8::internal::Isolate*, v8::internal::Handle<v8::internal::HeapObject>, v8::internal::Handle<v8::internal::HeapObject>, v8::internal::Handle<v8::internal::FunctionTemplateInfo>, v8::internal::Handle<v8::internal::Object>, v8::internal::BuiltinArguments) [/usr/local/bin/node]
 6: 0x100241690 v8::internal::Builtin_Impl_HandleApiCall(v8::internal::BuiltinArguments, v8::internal::Isolate*) [/usr/local/bin/node]
 7: 0x1c96c9adbe3d 
Abort trap: 6

```

でもnpmのバージョンは`> 5.5.1`になってる

```
$ npm -v
6.12.0
```


## 解決法

nodejsをインストールし直した。
バージョン管理ツール"n"を使ってたので、n上で削除→インストールした

```
$ n prune
$ n install lts
```

そうしたら無事にnpm installできた
zshの初期設定方法(初心者向け)

#はじめに
macOS Catalinaからデフォルトシェルがbashからzshに変更され、
設定どうやってやるの?という方も多いと思うので、個人的に便利だと思うzshrcの設定方法を書いておきます。

#環境
mac OS Catalina

##zsh-completionsのインストール
・zshの補完機能を有効化する。(これめっちゃ便利です！)
・以下コマンドを実行し、**zsh-completions**パッケージをインストールする。
 ```brew install zsh-completions```

##~./zshrcを編集
・以下コマンドを実行し、zshrcを編集する。
`vim ~/.zshrc`

```~./zshrc
# zsh-completions(補完機能)の設定
if [ -e /usr/local/share/zsh-completions ]; then
    fpath=(/usr/local/share/zsh-completions $fpath)
fi
autoload -U compinit
compinit -u
```
・以下コマンドを実行し、編集内容を反映させる。
```source ~/.zshrc```

#zshrcまとめ(aliasとかも含めて)
```~/.zshrc
# zsh-completions(補完機能)の設定
if [ -e /usr/local/share/zsh-completions ]; then
    fpath=(/usr/local/share/zsh-completions $fpath)
fi
autoload -U compinit
compinit -u

# prompt
PROMPT='%m@%n %F{1}%~%f$ '

##################################################
### aliases 
# Git系
alias g='git'
alias gs='git status'
alias gb='git branch'
alias gc= 'git clone'
alias gco='git checkout'
alias gct='git commit'
alias gg='git grep'
alias ga='git add'
alias gd='git diff'
alias gl='git log'
alias gcma='git checkout master'
alias gfu='git fetch upstream'
alias gfo='git fetch origin'
alias gmod='git merge origin/develop'
alias gmud='git merge upstream/develop'
alias gmom='git merge origin/master'
alias gcm='git commit -m'
alias gpo='git push origin'
alias gpom='git push origin master'
alias gst='git stash'
alias gsl='git stash list'
alias gsu='git stash -u'
alias gsp='git stash pop'

#vim教
alias v='vim'
alias vi='vim'
#ls系
alias ls='ls -G'
alias la='ls -a'
alias ll='ls -lh'
#処理確認
alias rm='rm -i'
alias mv='mv -i'
alias cp='cp -i'
#よく使うコマンド(ゆくゆくはAtoZまで埋めたい！)
alias c='clear'
alias h='history'
#zsh(zshいじる趣味が無いなら要らない)
alias zsh='vim ~/.zshrc'
alias szsh='source ~/.zshrc'

##################################################
### オプション

# 同時に起動しているzshの間でhistoryを共有する
setopt share_history

# 同じコマンドをhistoryに残さない
setopt hist_ignore_all_dups

# スペースから始まるコマンドをhistoryに残さない
setopt hist_ignore_space

# historyに保存するときに余分なスペースを削除する
setopt hist_reduce_blanks

# 高機能なワイルドカード展開を使用する
setopt extended_glob

# cd無しでもディレクトリ移動
setopt auto_cd

# コマンドのスペルミスを指摘
setopt correct
```
WebViewでカスタムURLを動作させるには

# WebViewでカスタムURLを動作させるには

Xamarin.FormsのWebViewを使ったアプリ内でHTMLを開いた際に、JavaScriptのwindow.openでGoogleMapsアプリが開かなかったので調べてみた。
同じHTMLをSafariで開いた際に、カスタムURLが動作し、GoogleMaps等の別アプリが起動するようになっている前提とする。

## WebViewを継承させたRendererを使う

[参考:Xamarin.Forms(iOS)でjavascriptのwindow.open()を動作させるには(英語)](https://forums.xamarin.com/discussion/157696/xamarin-forms-webview-on-ios-does-not-execute-window-open-function)
以下抜粋。window.open実行時に下記メソッドが呼ばれる。
URLがカスタムURL形式になっていればアプリが起動する。

```c#:MyWebViewRenderer.cs
[Export("webView:createWebViewWithConfiguration:forNavigationAction:windowFeatures:")]
public WKWebView CreateWebView(WKWebView webView,WKWebViewConfiguration configuration,WKNavigationAction action, WKWindowFeatures  features)
{
    if (action.Request.Url != null)
    {
        NSUrl url = action.Request.Url;
        UIApplication.SharedApplication.OpenUrl(url);
    }
    return null;
}
```
Flutter学習用リソースまとめ

#基礎

Flutterを使ったレイアウトの作り方
https://flutter.dev/docs/codelabs/layout-basics

Flutterを使って簡単なアプリを作ろう 
https://codelabs.developers.google.com/codelabs/first-flutter-app-pt1/#0

Flutterを使って簡単なアプリを作ろう パート2
https://codelabs.developers.google.com/codelabs/first-flutter-app-pt2/#0

Flutterを使ったチャットアプリの作成
https://codelabs.developers.google.com/codelabs/flutter/#7

Flutterを使った簡単なアニメーションの実装
https://flutter.dev/docs/codelabs/implicit-animations

【Widget of the Week】
FlutterのWidgetを毎週一個紹介するyoutubeシリーズ
https://www.youtube.com/watch?v=b_sQ9bMltGU&list=PLjxrf2q8roU23XGwz3Km7sQZFTdB996iG

#発展
Blocパターン入門
https://www.youtube.com/watch?v=d_m5csmrf7I

基本的に相当シンプルなアプリでない限りBlocライブラリーを使う
https://bloclibrary.dev/

Blocライブラリーの初歩的な使い方
https://www.youtube.com/watch?v=hTExlt1nJZI

Bloc ライブラリーを使いこなす
https://bloclibrary.dev/#/coreconcepts?id=core-concepts

Blocライブラリーを使ったFlutterプロジェクトのアーキテクチャー
https://bloclibrary.dev/#/architecture

FlutterでのFlavorの実装方法（環境をbuild time で分ける）
https://flutter.dev/docs/deployment/flavors

https://medium.com/@animeshjain/build-flavors-in-flutter-android-and-ios-with-different-firebase-projects-per-flavor-27c5c5dac10b
TerraformとTerraformerをAWSのCent6に入れてみた。

*OSが古くてすいません。*

Terraform初心者です。

Terraformがなんとなくわかったので、terraform importしていたのですが辛すぎたので
インポートツールを入れてみました。

#Terraformのインストール
本家参照で十分です。
https://learn.hashicorp.com/terraform/getting-started/install.html

しいて言えばプロファイルが、OSがCentなので~/.bash_profileです。

設置場所に悩みましたが、

/usr/local/bin/terraform

に設置しました。

#Terraform importに関して
勉強がてらRoute 53のとあるゾーン1つをimportしようとしてみましたが、terraformでは1レコードずつimportしないといけないので
めげてしまいました。

importツールとしてはterraformingとterraformerが有名だそうですが、なんとなくterraformerにしてみました。

#Terraformerのインストール
##前提
Go言語が必要になります。
また、今現在のTerraformerではGo1.13を求められたので注意が必要です。
CentOS6と古いのが原因かと思われますが、Go1.13がリポジトリにはありませんでしたので別途ダウンロードしています。

##Goのインストール
以下参考。 インストールの04まで行えば大丈夫。（CentOS7って書いてあるけど気にしない）
**すでに古いGolangが入っている場合は消しましょう。**
https://linuxize.com/post/how-to-install-go-on-centos-7/#how-to-install-go

[2019/11/10追記]
rpmが転がっている様なので、そちらで入れてからyum管理にするのをオススメします。

##Terraformerのインストール
本家の"Installation"を参考しました。
https://github.com/GoogleCloudPlatform/terraformer#installation

設置場所はなんとなく
```/usr/local/bin/terraformer```
にしました。

パスも通しましょう。

```bash:.bash_profile
...
export PATH="$PATH:/usr/local/go/bin" #Go言語のインストールで設定したパス
export PATH="$PATH:/usr/local/bin/terraformer" #Terraformerの場所を追記
...
```


保存したら忘れずに

```
source ~/.bash_profile
```

また、3番で、

```
cd /path/to/terraformer/directory
go run build/main.go aws
```
とインストールすると、以降**コマンドがterraformerではなくterraformer-awsになります。**
気を付けましょう。
（私はterraformer-awsで使ってます。）


4番は何を言っているのかちょっと悩みましたが、terraform作業ディレクトリ（私は /home/ec2-user/terraform/ とディレクトリを作りました。）
にinit.tfと言うファイル名で、私の場合はawsなので、

```init.tf
provider "aws" {}
```
を作成して、init.tfがある場所で```terraform init```を実行しろということです。

#Terraformerでインポート
Terraform作業ディレクトリ（init.tfがある場所）で

```
terraformer-aws import aws --resources=vpc,subnet,ec2_instance,route53,cloudfront --connect=true --regions=ap-northeast-1
```
などとするとガンガンtfファイルが作成されます。
resources=、regions=の値は適宜変えてください。

すると作業ディレクトリに

...
generated/aws/ec2_instance
generated/aws/route53
generated/aws/cloudfront
...

といったフォルダができるはずです。

#terraform planしてみる
ここでちょっとはまったのが、tfファイルを変更して、いざinit.tfがあるフォルダでterraform planしても
Already up-to-date! と出て何も計画されません。

なんでだろうと思ったのですが、先ほどgeneratedフォルダを見せた通り、サービス毎に
provider.tfというinit.tf的なファイルができていてそちらで```terraform plan```する形になります。

つまりAWSのサービス毎（ec2_instance、route_53とか）のディレクトリに移動してterraformコマンドを
実行する必要があります。

```
$ cd ./generated/aws/ec2_instance
$ terraform init  #これ大事
$ terraform plan
```

最初なんで動かないんだろうと思ったのでメモです。

#終わり
terraformで手動importは辛すぎです。
また、全体的に適当ですいません。
【Oracle Cloud】3.VMインスタンスを作成してみる

# 1.SSHキーペア作成
- 今回はMacでSSHキーペアを作成

[Linuxインスタンスでのキー・ペアの管理](https://docs.oracle.com/cd/E97706_01/Content/Compute/Tasks/managingkeypairs.htm)

```
$ ssh-keygen -t rsa -N "" -b 2048 -C "foals1" -f ~/Downloads/oraclecloud/.ssh
$ ll -a
total 16
drwxr-xr-x   4 kasumi  IRET\Domain Users   128 10 31 17:45 ./
drwx------+ 25 kasumi  IRET\Domain Users   800 10 31 17:34 ../
-rw-------   1 kasumi  IRET\Domain Users  1811 10 31 17:45 .ssh　★秘密鍵
-rw-r--r--   1 kasumi  IRET\Domain Users   388 10 31 17:45 .ssh.pub ★公開鍵
```

# 2.VMインスタンスの作成
- ホーム画面で**VMインスタンスの作成**をクリック
<img width="1672" alt="a1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449014/ab26f4ef-b0c6-e866-49e8-c3bb46047c25.png">

- 作成画面
<img width="1114" alt="a2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449014/a38c819b-1229-fba3-4a1d-798932886326.png">
<img width="1092" alt="a3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449014/0f6bcbf1-75b5-3265-5800-d851abdc2280.png">
<img width="1099" alt="a4.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449014/3ea0fa38-9950-ed12-2bf8-07bbcbd4b96f.png">
- SSHキーペアの公開鍵を貼り付け
<img width="1100" alt="a6.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449014/98edc560-4b7a-899d-d08c-f13c5c0ebe95.png">

- **作成**をおすと**Out of host capacity.**と出た。。。
- こういうことらしいです↓
>これについてOracle公式チャットにて問い合わせたところ、Oracle Cloud側でもう空きがない状態でユーザ側の問題ではないとのことでした。とにかく空きがでるまで待機するしかないようでした。私もアカウントを登録して３日間ぐらいはずっと同じエラーが表示され作成できませんでした。「Always Free」が発表されてユーザが増えてまだリソースの確保が追いついていないのかもしれません。

[Oracle Cloud に登録して仮想マシンを作成するまでの手順](https://www.virment.com/oracle-cloud-always-free-create-vm/)

<img width="1668" alt="a7.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449014/ff8ba489-524f-eaeb-2386-18aafc6e6336.png">

- 数時間〜数日待つと作成できました
<img width="1362" alt="Oracle_Cloud_Infrastructure.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449014/88661239-9dc2-0492-39f9-15e61f7bc425.png">

- 接続確認
    - VMインスタンスのユーザは**opc**

```
$ ssh -i <秘密鍵> opc@<パブリックIOアドレス>
[opc@foals1-bastion ~]$ 
[opc@foals1-bastion ~]$
```

# 補足
## 拡張オプション
## フォルトドメイン
- Oracle Cloudでは以下を利用し冗長構成を組む
    - リージョン
    - 可用性ドメイン（AD、アベイラビリティドメイン）
        - AWSでいうAZ（アベイラビリティゾーン）
        - GCPでいうゾーン
    - フォルトドメイン
        - AD内での区分けみたいなもの

- **東京リージョン**には現在ADが**1つ**しか無い
    - なので、**フォルトドメイン**で冗長化を行う

## ネットワーク
- 内部IPとホスト名を任意で設定可能
スクレイピング防止とその対策

ビッグデータ時代の到来に伴い、データ分析はますます人々に重視されるようになって行きます。ビッグデータには極めて高速に、多くの異なる形式で生成された大量のデータです。膨大なデータ量と複雑なデータ型があり、低値密度、データ処理の適時性などは、従来のデータの特性とは異なります。そして、多量のデータを収集するため、様々な[Webスクレイピングツール](https://jp.scrapestorm.com/)が登場します。
今回は日常のスクレイピング中によくあるブロック手段と対策を紹介します。
##よく見るブロック手段の紹介
**1.キャプチャー**
キャプチャー(Captcha)とは、「completely automated public Turing test to tell computers and humans apart」（コンピュータと人間を区別する完全に自動化された公開チューリングテスト）のバクロニムです。人々は簡単に画像を識別できますが、ロボットにとってそういう簡単ではありません。これはなぜキャプチャーはよくあるブロック手段の一つになるの原因です。だが、技術の発展につれて、ロボットの画像識別能力もどんどん増えていきます。将来、下記のようなキャプチャーが出で来るかもしれません。
![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482909/48cb7890-3de4-ebe2-7388-c90b1daf9ba5.png)
**2.IPのブロック**
ブロック手段と言えば、よく見かけるのはやはりIPのブロックです。では、なぜIPのブロックは最も有効な手段でしょうか？クッキーなどの情報が偽造できますが、http請求に直接偽造できないのはIPだけです。定期的にWebサイトに膨大なリクエストを送信すると、このIPアドレスがWebサイトにロボットに認識されますかもしれません。一旦IPアドレスがロボットに疑われるなら、ブロックされる可能性がかなり高まります。
##ブロッグを回避する方法
キャプチャーとIPのブロックはよくスクレイピングを邪魔して、人々を困らせます。下記には少し[スクレイピング](https://jp.scrapestorm.com/)防止を回避する方法を紹介します。役に立つなら、幸いです。
####1.スピードを落とす
高速でWebサイトから膨大なデータをスクレイピングすると、サーバーの負担が増加します。有名なのは男性が蔵書検索システムに高頻度のリクエストを故意に送りつけたとして偽計業務妨害容疑で逮捕されたlibrahack事件です。できるだけスクレイピングのスピードを控えてください。
####2.ルーターを再起動する
ルーターを再起動するのはルーターの再起動時に送信されるフォームをシミュレートします。新たなダイナミックIPを手に入れと、簡単にWebサイトにブロックされるでしょう。
####3.IPローテーション
IPアドレスがWebサイトに疑われて、接続を拒否しますの場合、他のIPアドレスを切り替え、スクレイピングをし続けるのがよく使えるブロック防止手段です。
下記は[ScrapeStorm](https://jp.scrapestorm.com/)のIPローテーション方法です。
**①時間よりIPアドレスを切り替える**
プロキシを1分ごと、3分ごと、または5分ごとに切り替えるように設定できます。
![alt](https://jp.scrapestorm.com/wp-content/uploads/2019/09/5-9.png)
**②ページにテキストが表示されば、切り替え条件としてテキストを入力できます。**
以下に示すように、切り替え条件を「表示されている画像の文字を以下に入力してください。」に設定すると、対応するテキストがページに表示されるとプロキシが切り替えられます。
詳細にはScrapeStorm公式サイトのチュートリアルをご参照ください。
[IPローテーションを設定する方法](https://jp.scrapestorm.com/tutorial/how-to-use-the-proxy/)
![キャプチャー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482909/d5191b9d-7f86-bee7-af9b-decad6d15906.png)
####4.UA
UA(英: user agent、日: 利用者エージェント）とは、利用者があるプロトコルに基づいてデータを利用する際に用いるソフトウェアまたはハードウェアのことです。
特にHypertext Transfer Protocolを用いてWorld Wide Webにアクセスする、ウェブブラウザなどのソフトウェアです。
下記はよく使えるUAをご参照ください。
**Chrome**
【Windows7】Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1
【Windows10】Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36

**Firefox**
【Windows7】Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0
【Windows10】Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0

**IE9**
【Windows7】Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR

**IE11**
【Windows10】Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; rv:11.0) like Gecko
Azure DevOps Server #2-2 VB6で使用する プロジェクトの追加

**Chapters**

📘 **Chapter #1**
　📗 **Chapter #1-1**　[継続的インテグレーション（CI）構築](https://qiita.com/tfukumori/items/ef8314857ecb545c4b15)
　📗 **Chapter #1-2**　[継続的インテグレーション（CI）手順](https://qiita.com/tfukumori/items/11d24a5eee8d77a17a80)
📘 **Chapter #2**
　📗 **Chapter #2-1**　[VB6で使用する 環境設定](https://qiita.com/tfukumori/items/37f035694751dc098fcd)
　📗 **Chapter #2-2**　[VB6で使用する プロジェクトの追加](https://qiita.com/tfukumori/items/68aca8cdc04fe76d6eee)
📘 **Chapter #A**
　📗 **Chapter #A-1**　[バージョンアップ TFS 2018 Update 1 → Update 3、検索サービスの分割](https://qiita.com/tfukumori/items/778bb2e3d913106beba9)
　📗 **Chapter #A-2**　[バージョンアップ 2019→2019 Update1](https://qiita.com/tfukumori/items/7f149928a6e413afe755)

---

# TL;DR

- [前の記事](https://qiita.com/tfukumori/items/37f035694751dc098fcd)の続き
- Microsoft Visual SourceSafe(以下 VSS)で管理されたプロジェクトを、Azure DevOps Serverに追加する手順となる
- ファイルの共有がなくなったことに対する対策も記載

# 前提

- [前の記事](https://qiita.com/tfukumori/items/37f035694751dc098fcd)で環境構築済み
- 作業フォルダの設定は実施済み
- VSSで管理しているプロジェクトは、作業フォルダ内の適切な場所に配置済み

# 手順

## (1) 不要なファイル削除

### 必須：接続先リポジトリが記載されたファイル

*.scc

### 任意：プロジェクト(*.vbp)に含まれていない一時ファイル等

削除は必須ではないが、確認用の比較に邪魔となるもの

*.log
*.vbw
*.dca
*.bak
*.tmp

## (2) プロジェクトファイル(*.vbp)を開く

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204150/fea23eee-2e71-3a61-7c74-e0da91dcf348.png)

## (3) リポジトリ登録確認メッセージが表示されるので【はい】を選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204150/15ab5bd2-21d2-e75f-c697-5f976ab2755c.png)


## (4) ファイル追加確認のメッセージが表示されるので【OK】を選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204150/c3efaf66-386d-8bea-42a8-e0c40ecebdf0.png)


- このダイアログは、VB6が表示している
- チェックインコメントを指定する。

    `etc:移行ファイル追加`

## (5) ファイル（*.vbp）追加のメッセージが表示されるので【チェックイン】を選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204150/d43a1b88-8ee4-03cc-6745-161a5d95a825.png)


- このダイアログは、TFSクライアントが表示している
- プロジェクト(*.vbp)とそれ以外のファイルは別々で表示される
- チェックインコメントを指定する。

    `etc:移行ファイル追加`

## (6) ファイル（*.vbp以外）追加のメッセージが表示されるので【チェックイン】を選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204150/c66e0be4-d4b0-7f32-990a-13a53f90e7c0.png)

- このダイアログは、TFSクライアントが表示している
- プロジェクト(*.vbp)とそれ以外のファイルは別々で表示される
- チェックインコメントには、(4)で指定したコメントが入力されている

----

### [注釈]共有ファイルについて

- VSSの共有ファイルは、リポジトリの別フォルダにあるが、同じファイルとして扱われる動作となる（シンボリックリンクのようなもの）
- Azure DevOps Serverでのリポジトリシステム（TFVC）には存在しないので、共有用のフォルダを作成して、VB6のプロジェクトから対象のファイルを相対パスで参照することで、同じ目的を実現する

----

## (7) Microsoft Visual SourceSafeを確認し、共有しているファイルを確認する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204150/ff6768cc-f135-08b4-7355-c1f9ef19ace9.png)


- アイコン左下に矢印が付きのファイルが共有ファイル

## (8) エクスプローラで共有用のフォルダを上の階層に作成し（例：`Common`）、該当の共有ファイルをコピーする

## (9) (8)をAzure DevOps ServerにTeam Foundation Server 2010 Explorerから追加する

- チェックインコメントを指定する。

    `etc:ファイル共有`

## (10) VB6 IDEで(7)のファイルをプロジェクトから削除する

## (11) VB6 IDEで(8)のファイルをプロジェクトに追加する
Android10で画像/動画キャプチャアクションの結果をパブリックディレクトリに保存する

私の開発している Android アプリにおいて、 [MediaStore.ACTION_IMAGE_CAPTURE]() や [MediaStore.ACTION_VIDEO_CAPTURE]() アクションを指定したインテントにより画像や動画を撮影し、パブリックなディレクトリに保存しつつアプリの機能で利用するということをやっていました。

しかしながら [Android10のプライバシー保護のための変更](https://developer.android.com/about/versions/10/privacy?hl=JA) により、利用していた API がことごとく Deprecated になってしまいました。この対応をした時のメモを残します。

## Android 9 まで

### 保存先Uriの決定

[Environment.getExternalStoragePublicDirectory](https://developer.android.com/reference/android/os/Environment#getExternalStoragePublicDirectory(java.lang.String)) メソッドを利用して保存先を指定していましたが、このメソッドは Android10 で Deprecated になりました。

```kotlin
// パブリックなピクチャディレクトリを保存先
val picturesDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
val outputFile = File(picturesDirectory, "captured.jpg")
val outputUri = FileProvider.getUriForFile(context, autholity, outputFile)

val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE).apply {
    putExtra(MediaStore.EXTRA_OUTPUT, uri)
}
startActivityForResult(intent, REQUEST_CODE)
```

### メディアスキャナーによるスキャン

キャプチャ後、パブリックなディレクトリに保存されたファイルをギャラリーアプリ等で表示するために [Intent. ACTION_MEDIA_SCANNER_SCAN_FILE](https://developer.android.com/reference/android/content/Intent#ACTION_MEDIA_SCANNER_SCAN_FILE) アクションのインテントによりメディアスキャナーにスキャンさせていましたが、こちらも Android10 で Deprecated になりました。

```kotlin
val scanIntent = Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, outputUri)
context.sendBroadcast(scanIntent)
```

## Android 10

### 保存先Uriの決定

MediaStore に対して次のコードのようにして保存先Uriを確保します。

```kotlin
val values = ContentValues().apply {
    put(MediaStore.Images.Media.DISPLAY_NAME, "captured.jpg")
    put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")
}
val collection = MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
val outputUri = context.contentResolver.insert(collection, values)
```

キャプチャのキャンセルなど、この確保したUriにファイル保存しなかった場合は、下記のコードで削除しておきましょう。

```kotlin
context.contentResolver.delete(outputUri, null, null)
```

### メディアスキャナーによるスキャン

上記のコードで保存先Uriを確保した場合、改めてスキャンしなくてもギャラリーアプリ等で表示されようです。
Python3 csvライブラリで想定通りにパースされない問題(クォーテーション起因)

記念すべき(?)初投稿です。

# 事の起こり
pythonに触れたての初心者なので、ネットの情報を漁りながらcsvライブラリを使い
tsvファイルを取り込む処理を書いていたところ

```python:tsv_reader.py
import csv
import pprint


def loadTsv(filename):
    with open(filename, newline='') as f:
        reader = csv.reader(f, delimiter='\t')
        for row in reader:
            pprint.pprint(row)
```

下記のようなデータに対してパースがうまく行かない現象が発生しました。

```tsv:sample.tsv
0    test    1    hogehoge    a    b    
0    test    1    "fugafuga    a        c    
0    test    1    piyopiyo    a    b    c
```

# 自分の中の理想値と発生した問題

自分の中の理想としては下記を想定していたのですが

```
('0','test','1','hogehoge','a','b','')
('0','test','1','"fugafuga','a','','c')
('0','test','1','hogehoge','a','b','c')
```

実際には

```
('0','test','1','hogehoge','a','b','')
('0','test','1','fugafuga\ta\t\tc\t0\ttest\t1\thogehoge\ta\tb\tc')
```

というように何とも絶望的な形になっていました。。。
delimiterに\tを指定しているのになんでこうなるんだ？？？と混乱しましたが、結論は簡単なことでした。

# 問題の原因
Dialect クラスの書式化パラメータ「Dialect.quoting」にて、「csv.QUOTE_MINIMAL」が設定されているため

>csv.QUOTE_MINIMAL
writer オブジェクトに対し、 delimiter 、 quotechar または lineterminator に含まれる任意の文字のような特別な文字を含むフィールドだけをクオートするように指示します。

参考: [Python公式ドキュメント Dialect.quoting](https://docs.python.org/ja/3/library/csv.html#csv.Dialect.quoting)
参考: [Python公式ドキュメント QUOTE_MINIMAL](https://docs.python.org/ja/3/library/csv.html#csv.QUOTE_MINIMAL)

2行目の中で

```
"fugafuga ...
```

となっている部分のダブルクォーテーションがクォート対象となり、かつその後閉じられることが無かったため
文末までの全ての\tが無視されることで、問題の結果になっていました。


# 解決方法
少し乱暴ですが、自分の場合は特にクォートを気遣う必要が無かったため、csv.QUOTE_NONEに書き換えました。

>csv.QUOTE_NONE
writer オブジェクトに対し、フィールドを決してクオートしないように指示します。現在の delimiter が出力データ中に現れた場合、現在設定されている escapechar 文字が前に付けられます。 escapechar がセットされていない場合、エスケープが必要な文字に遭遇した writer は Error を送出します。
>
>reader に対しては、クオート文字の特別扱いをしないように指示します。

参考: [Python公式ドキュメント QUOTE_NONE](https://docs.python.org/ja/3/library/csv.html#csv.QUOTE_NONE)


```python:tsv_reader.py
import csv
import pprint


def loadTsv(filename):
    with open(filename, newline='') as f:
        reader = csv.reader(f, delimiter='\t', quoting=csv.QUOTE_NONE)
        for row in reader:
            pprint.pprint(row)
```

csvの常識を考えれば分かるものであった気がします、もっと精進せねば……。
VisualStudioCodeのDL～日本語化までの手順【19/11/08】

VisualStudioの導入をしよう！と思い立った記念に、この記事をしたためようと思います。

・VSCordのインストール
・日本語化

を目指していきます。

#VSCodeをDLしよう

[こちらのサイトからDLします。](https://code.visualstudio.com/)

![6.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413468/792a959a-b7c3-9540-690b-7ce1bb05345b.png)


画面中央部or右上部分にある、「Download」という記述のあるボタンからダウンロードできます。
後はDLしたexeファイルをダブルクリックして、VSCordをインストールしていきましょう。
一般的なソフトウェアと同じ感覚でインストールできます。

##VSCodeを日本語化

インストールしましたら、VSCordを立ち上げましょう。
最初に日本語化を行います。

そうすると画面右側に、ブロックを4個積んだようなアイコンがあるので、これをクリックします。

![1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413468/0b2415dd-1ecc-bcce-f437-c63ca3d6e090.png)


次に、画面左上部分に文字の入力ができる部分があるので、そこに「japanese language」と入力します。

![2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413468/f4b8981e-ef95-0dab-465b-b14883855ce5.png)


すると最上部に、「Japanese Language Pack for Visual Studio code」が出て来るかと思いますので、それをインストールします。

※下部画像で言う所の「Uninstall」と書かれた部分が、「Install」になっているかと思いますので、それをクリックします。

![3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413468/13bfd275-b22d-519c-28cb-9ad1c60e6def.png)


次にVSCodeを再起動します。
画面下部に「Restart　Now」と出るかと思いますからここをクリックしてもいいでしょう。

![4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413468/d277a3f7-4bfa-63b8-dfca-686fea3075ce.png)

再起動が完了しますと、無事に日本語化がされるかと思います。
以下は、日本語化後の画面になります。

![5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413468/48f926da-6395-b008-3339-1d71392c5954.png)


これで日本語化は終了です！
githubからreleaseタグ、commitID、branch名の3パターンでcurlする

普通の使い道ならcloneかsubmoduleでやるべきです
ど〜〜〜〜してもcurlでやりたいとき用のまとめ

organizationでprivateなリポジトリでも引っ張れます


# releaseにあるブツをひっぱる
```
curl -OL --user ':{your personal access token}' \
https://github.com/{owner}/{repo name}/archive/{release tag}.tar.gz
```

# masterをひっぱる
```
curl -H "Authorization: token {your personal access token}" \
-L https://api.github.com/repos/{owner}/{repo name}/tarball > master.tar.gz
```


# commitID指定でひっぱる
tarballのうしろに追記するだけ

```
curl -H "Authorization: token {your personal access token}" \
-L https://api.github.com/repos/{owner}/{repo name}/tarball/{commit ID} > branch.tar.gz
```


# branch指定でひっぱる
tarballのうしろに追記するだけ
commitIDと置き換わるかたち

```
curl -H "Authorization: token {your personal access token}" \
-L https://api.github.com/repos/{owner}/{repo name}/tarball/{branch name} > branch.tar.gz
```
Sassについての学習

# Sassとは
SassとはCSSの機能を拡張した言語である。Sassを利用することで、CSSを効率的にかけるようになる。SassはCSSに非常に似ているが異なる言語である。CSSを簡潔にかけるだけではなく、CSSの中で編集を使ったり、計算を行うことができたりする。
# Sassファイル
Sassは通常のCSSファイルには記述することができない。反対にSassファイルにCSSを記述することはできる。Sassを扱うファイルの拡張子は.sassと.scssの2種類がある。どちらもSassのファイルとなるが記法が大きく異なる。
#### .sass拡張子
拡張子は ```.sass```
__SASS記法__を扱うことができる。
SASS記法では波括弧の省略やセミコロンが不要
しかし、CSSの記法との差がありすぎた為かあまり普及しなかった。

```sass:SASS記法
.body p
  color: #333
  font-size: 15px
  font-weight: normal
  strong
    color: red
    font-weight: bold
```
#### .scss拡張子
.sassに後に作られたSassファイルが.scssの拡張子ファイルである。
CSSに非常に似た記法(__SCSS記法__)でSassの機能を使うことができる。今ではこの記法が主流である。
これからの説明はSCSS記法を用いる。

```scss:SCSS記法
.body p {
  color: #333;
  font-size: 15px;
  font-weight: normal;
  strong {
    color: red;
    font-weight: bold;
  }
}
```
#### 記述の簡略化
__● Sassのネスト構造__
__ネスト__させることで、同じ親のセレクタをまとめることができる。
下記の例で見てみる。

```html:sample.html
<div class="block">
  <h1 class="title">Hello world</h1>
  <p class="text">Sass is <span>great!</span>
</div>
```
__CSSのスタイルで記述する場合__

```css:sample.css
.block {
  background-color: #000;
}

.block .title {
  color: #FFF;
  font-size: 70px;
  text-align: center;
}

.block .text {
  font-size: 15px;
  color: #FFF;
}

.block .text span {
  color: red;
  font-size: 20px;
}
```
__Sassでセレクタをネストして記述した場合__

```scss:sample.scss
.block {
  background-color: #000;
  .title {
    color: #FFF;
    font-size: 70px;
    text-align: center;
  }
  .text {
    font-size: 15px;
    color: #FFF;
    span {
      color: red;
      font-size: 20px;
    }
  }
}
```
### プログラムのような処理ができる
Sassでは変数や条件分岐といったプログラムのような処理を記述できる。
__● Sassにおける変数__
変数の定義の仕方
```$変数名: 値;```
よく使うカラーコードや値は変数にすることであとで変更が楽になったり、コードが読みやすくなる。

```scss:Sassにおける変数
$section-color: rgb(30,30,30);
seciton {
  background-color: $section-color;
}
```
#### 複数のCSSファイルを１つにまとめることが可能
Sassでは__パーシャル__という機能を使用して、複数のSassファイルを１つのCSSファイルとしてまとめられる。機能ごとにファイルを分割することができ、CSSを管理しやすくなる。
__● パーシャル__
パーシャルファイルの作成
ファイル名を```_(アンダースコア)```から始める。
パーシャルファイルの読み込み
```@import ファイル名```と記述する。

__(例)__

```scss:sample.scss
@import "reset";  /* _reset.scssを読み込む */
@import "header"; /* _header.scssを読み込む */
```
#### 同じ値を使いまわすことができる
Sassでは__変数__を使うことによって、同じ値を使い回すことができる。
また、__mixin__という機能を使用することで、同じスタイルをまとめることもできる。

__(例)__

```scss:_variable.scss
$mainYellowColor: #FFEC00;  /* #FFEC00という色をmainYellowColorという変数名で定義する */
```
変数を定義してある_variable.scssを読み込むことで、_variable.scssに定義された変数を他のscssファイルで使用可能。

__● mixin__
まとまったスタイルを定義する機能
mixinの定義の仕方
```@mixin mixin名() {}```
```.clearfix```をよく使用することは多いと思うがその場合は、```_clearfix.scss```(ファイル名は自由)ファイルに定義しておく。

__(例)__

```scss:_clearfix.scss
@mixin cleafix() {
  &:after {
    content: '';
    display: block;
    clear: both;
  }
} 
```
・ mixinの呼び出しは```@include```を使用して以下のように書く。

```scss:_sample.scss
.menu {
  @include clearfix();
  ...

  .menu__list {
    float: left;
    ...
  }
}
```
これで以下のようなsample.scssのコードを同じになる。

```scss:_clearfix.scss
.menu {
  &:after {
    content: '';
    display: block;
    clear: both;
  }
  
  .menu__list {
    float: left;
    ...
  }
}
```
何度も同じような記述をしているものがあったら、mixinにまとめることを考えた方が良い。
TOEIC285学生のためのSwift Lv3 【音楽や効果音を好きな回数ほど再生する】

久しぶりの投稿となります。

MVCとかMVVMとかアーキテクチャはあいも変わらず理解には至っていませんが、少しずつ再利用性のあるプログラムが組めるようになれればなぁと日々邁進しております。

今回は、音楽や効果音（mp３ファイル）を好きな回数ほど重複させて再生させる方法について尾行６...備考録がてらまとめます。

以前まで、ViewController.swiftに全ての処理を突っ込む~~ゴミのような~~フラットなコードを書いていましたが、保守性のへったくれもあったもんじゃないので今回は初めて別々のクラスに処理を分けて音楽を再生してみました。

今回、[K N@ninoko1995氏の記事](https://qiita.com/ninoko1995/items/d470d6af625bfcc079ad) を参考にさせていただきました。この場を借りて御礼申し上げます。



```ViewController.swift
import UIKit
import AVFoundation

class ViewController: UIViewController,AVAudioPlayerDelegate{
    // BGMと効果音を判別しやすいようにmusiとsoundで分けています。
    var music1 =  MusicController()
    var sound1 =  MusicController()
    var sound2 =  MusicController()
 
    override func viewDidLoad() {
        super.viewDidLoad()
        /* 音楽を再生したい箇所に下記を読み込ませたら再生されます。 */
     /* music1.musicPlay(mode: 再生回数,fileName: "音楽ファイル名") */
        music1.musicPlay(mode: -1,fileName: "Tutorial")
        sound1.musicPlay(mode: 5,fileName: "button")
        sound2.musicPlay(mode: 15,fileName: "button2")
        /* 音楽を止めたいときは止めたいときに下記を読み込ませたら止まります。
        music1.musicPlay(mode: -1,fileName: "STOP")
        sound1.musicPlay(mode: 5,fileName: "STOP")
        sound2.musicPlay(mode: 15,fileName: "STOP")  
        */
    }
```

```MusicController.swift
import AVFoundation

class MusicController{
    
    var musicPlayer: AVAudioPlayer!
    
    var mode : Int = 0
    var fileName : String = ""
    
    // 指定のMUSICを指定の回数再生させるメソッド //
    func musicPlay(mode: Int,fileName: String){
        if fileName == "STOP"{
            musicPlayer.stop()
            return
        }
        do {
            let filePath = Bundle.main.path(forResource: fileName,ofType: "mp3")
            let musicPath = URL(fileURLWithPath: filePath!)
            musicPlayer = try AVAudioPlayer(contentsOf: musicPath)
        } catch {
            print("error")
        }
        musicPlayer.numberOfLoops = mode
        musicPlayer.play()
    }
}
```

現職のエンジニアの方の大多数が理解しているので余計かもしれませんが、学生や趣味でやってる方向けに。ViewController.swiftの方で再生回数を指定できますが、−１にすることで永久的に再生されます。

お読みいただきましてありがとうございました。
ラズパイ4

#RaspberryPi4のスペック#

Raspberry Pi3 model B+に引き続き、新型のラズパイが発表された。従来品からかなりアップグレードされているにも関わらず価格は据え置きか。


![Raspberr Pi 4](https://docid81hrs3j1.cloudfront.net/imagecontent/image-1561103505463.jpg)




* ARMチップは1.5GHzで4コアを内蔵。
* Ethernetの速度が改善
* USB-TypeC端子を採用し5V3Aの給電に対応。
*USB3.0端子を2つ、
*


#4K出力にも対応#

* VideoCore VI graphicsを搭載
* 4k60Hzの出力に対応している。
* さらに30Hzでのデュアルディスプレイもサポートしている。
*　端子はmicro-HDMI端子に変更

#選べるスペック#

*  RAMが1GB,2GB,4GB,の3種類のラズパイから選ぶことが可能になった。
* それぞれ値段は35ドル,45ドル,55ドルとのこと。

#参考#
日本での販売時期や価格は現在未定である。SWITCH SCIENCE で購入可能だと思われる。
[購入はこちら](
https://www.switch-science.com/catalog/5680/
)
padding（パディング）の書き方-CSS

**paddingの書き方**

指定したい値が方向ごとに異なる場合、個別で指定する方法もありますが、まとめて書くことも可能。
値を4つ、スペース区切りで指定した場合、「上」「右」「下」「左」の順で適用され
値を2つ指定した場合、「上下」「左右」の順に適用されます

```css:sample
.sample1{
  padding:20px 10px 20px 10px;
/*　　上(top)　右(right)　下(bottom)　左(left)　
　　　　　　時計回りに指定　*/
}

.sample2{
  padding:20px 10px;
/*　　    上下　左右　　　*/
}
Sunriseに参加してきました

# Sunriseってなに？
- Voyage Groupさんの大規模サービス構築インターン
- [公式サイト]
(https://voyagegroup.com/internship/sunrise/)

# どんなことやったの？
- 計測用のインスタンスを3日間でどれだけリクエストを捌けるように性能を向上させれるかという内容

# 印象に残ったこと
- 仮説、検証、考察の一連の業務の流れを体験できた
- ビジネスでは教育現場と違って、新しいこと、興味があることよりも、価値を生み出せることを優先した
- VGさんの実際に業務している時の雰囲気みたいなものを感じることができた

# ネタバレ元
- ここに技術的なネタバレ、それ以外のネタバレ両方あるので、注意してください
- [VoyageGroupインターン Sunriseに参加してきました](https://www.slideshare.net/secret/GHN896vPc0gBqp)

# 感想
- 仮説、検証、考察という流れを通してパフォーマンスが改善されていくのをみて、とてもこの進め方は効果があるということを実感した
- インフラに特化したインターンは初めてで、とても楽しく感じたので、自分はインフラ好きなんだなと改めて実感した
- 逆に合わない人には合わないのかなとも感じました
- kakeruくんがうまく動かない時、夜改修している様子が日常の仕事風景そのままに見えた
- その様子を見て、VGさんで仕事したら楽しく働けそうだなと感じました