USB3.0 が WiFi 2.4Ghz に干渉しすぎて無駄にケーブルやアダプタが増えて金は減る

MacにUSB3.0ケーブルを差すとはっきりWiFiの接続が切れまくる。

もしや、と思い調べてみると。

USB3.0 機器から発生する高周波ノイズも、2.4Ghz無線LAN機器に大きく干渉し、良くない影響(通信速度の低下や通信断)が発生するようです。

USB3.0機器から発生するノイズは、2.4Ghz無線LANに悪影響を与えるらしい。 - ぼくんちのTV 別館

え、中華なケーブルやアダプタって買ってみて気づくこと多くない?

ネットのレビューやランキングって当てにならなくねえ?...

Apple 公式にも。

USB 3 デバイスがコンピュータに接続されていると、Wi-Fi または Bluetooth デバイスが正常に動作しないことがあります。なぜですか?

一部の USB 3 デバイスは、無線周波数干渉を引き起こすことがあります。これによって、2.4 GHz 帯を使用する Wi-Fi および Bluetooth デバイスとコンピュータとの通信に問題が生じる場合があります。

Mac で USB デバイスを使う - Apple サポート

この、WiFiの周波数の話は以前混線が気になっていたのが、もう4年前とか。

公衆無線LANとかWiFiが途切れる場合「5GHz帯」に切り替えたほうがいいんぢゃね?

今、同じアプリで計測してみると、2.4GHzはあいかわらず混雑で、5.0GHzも混んで来ている模様。

ルータを見てみると、今では旧型となり、2.4Ghz オンリー。

当然、飛んでいるWiFiのSSIDにも -g -gw のみ。


○○-a	IEEE802.11n	5GHz帯	        600Mbps
○○-aw	IEEE802.11a	5GHz帯	        54Mbps
○○-g	IEEE802.11n	2.4GHz帯	600Mbps
○○-gw	IEEE802.11g	2.4GHz帯	54Mbps

無線LANルーターのwifiのID内にある「g」「a」「gw」「aw」の意味 | JoyPlotライフ

買い替えますか、WiFiルータ。

【価格.com】無線LANルーター(Wi-Fiルーター) | 通販・価格比較・製品情報

最近のガジェットて使えるものなのに無駄に購入したりしてません?

もう2000円のルータを買おうと思います。 ← これが原因か! (笑)

👉 「これは分からないわ…」Mac miniで2.4GHz帯のWi-Fiが全く通信できないので調べてみたら1000円くらいで買った中華製のHDDケースに付いてたUSBケーブルが原因だった - Togetter 
👉 公衆無線LANとかWiFiが途切れる場合「5GHz帯」に切り替えたほうがいいんぢゃね? 


E を出力させない Double.toPlainString()

こういうの。助かります。


double d1 = 0.00000000000000000000000000000000000000000123456789012345678901234567890d;
double d2 = 1234567890123456789012345678900000000000000000000000000000000000000000000d;
double d3 = 1234567890.1234567890123456789d;

System.out.println(BigDecimal.valueOf(d1).toPlainString());
// 0.0000000000000000000000000000000000000000012345678901234568
System.out.println(BigDecimal.valueOf(d2).toPlainString());
// 1234567890123456800000000000000000000000000000000000000000000000000000000
System.out.println(BigDecimal.valueOf(d3).toPlainString());
// 1234567890.1234567

Java の double を素直な String にしたい、E 要らない - Qiita

直感的には表示できなく、ネット上を放浪していました。

Kotlin では、Extention Functions に追加しておきますわ。


fun Double.toPlainString(): String
    = BigDecimal.valueOf(this).toPlainString()


val d1 = 0.00000000000000000000000000000000000000000123456789012345678901234567890
val d2 = 1234567890123456789012345678900000000000000000000000000000000000000000000.0
val d3 = 1234567890.1234567890123456789
val d4 = 4.34e-05
val d5 = 5.6e-07

println(d1.toPlainString())
println(d2.toPlainString())
println(d3.toPlainString())
println(d4.toPlainString())
println(d5.toPlainString())


I/System.out: 0.0000000000000000000000000000000000000000012345678901234568
I/System.out: 1234567890123456800000000000000000000000000000000000000000000000000000000
I/System.out: 1234567890.1234567
I/System.out: 0.0000434
I/System.out: 0.00000056

Java Double に toPlainString() がないのは何か理由があるのかも。とは思うが。


【Kotlin】sortedWith + compareBy で並び替え

「C# でこんなの書けるけど Kotlin ではどう書くの?」 という話。


var list = new List<Person>();
list.Add(new Person(25, "Tom"));
list.Add(new Person(25, "Dave"));
list.Add(new Person(20, "Kate"));
list.Add(new Person(20, "Alice"));

// will produce: Alice, Kate, Dave, Tom
var sortedList = list
    .OrderBy(person => person.Age)
    .ThenBy(person => person.Name)
    .ToList();

Javaのコードから考えるとKotlinでももちろんシンプルな記述となります。


val sortedList = list
    .sortedWith(compareBy({ it.age }, { it.name }))


val sortedList = list
    .sortedWith(compareBy(Person::age, Person::name))


list.sortedWith(compareBy<Person> { it.age }.thenBy { it.name }.thenBy { it.address })


list.sortedWith(compareBy({ it.age }, { it.name }, { it.address }))

java - Sort collection by multiple fields in Kotlin - Stack Overflow

大文字小文字を無視する場合。


places
    .sortedWith(
        compareBy(String.CASE_INSENSITIVE_ORDER, { it.name })
     )


places
    .sortedWith(
        compareBy(String.CASE_INSENSITIVE_ORDER) { it.name }
     )


places
    .sortedWith(
        compareBy(String.CASE_INSENSITIVE_ORDER, Place::name)
     )

kotlin - How to sort objects list in case insensitive order? - Stack Overflow

降順昇順の対応やモデルに入れたり。


val sortedList = list
    .sortedWith(compareBy({ it.a }, { it.b }, { it.c }))


list.sortedWith(
    compareBy<Foo> { it.a }
        .thenByDescending { it.b }
        .thenBy { it.c }
)


class Foo(val a: String, val b: Int, val c: Date) : Comparable<Foo> {

  override fun compareTo(other: Foo)
      = compareValuesBy(this, other, { it.a }, { it.b }, { it.c })
}
val sortedList = list.sorted()


class Foo(val a: String, val b: Int, val c: Date) : Comparable<Foo> {

  override fun compareTo(other: Foo) = comparator.compare(this, other)

  companion object {
    val comparator = compareBy(Foo::a, Foo::b, Foo::c)
  }
}
val sortedList = list.sorted()

comparable - How to sort based on/compare multiple values in Kotlin? - Stack Overflow

シンプルで便利になりつつも複数の記述で書くことができてしまう最近の言語のパターン。


【仮想通貨】Cryptowatch Public Market REST API を眺める

キャバ嬢に

「リップル買っちゃった。名前がかわいいし。」

などと言われて即全てを手放しました、おはようございます。

そんな下落が止まらない仮想通貨たち。

仮想通貨全体の上げ下げを把握することができます。

Cryptowatch - live Bitcoin price charts

ここではAPIにてリアルタイムな情報を公開しています。

無料では当然制限はついてきますが。

Public Market REST API - Cryptowatch

いくつか簡単にデータを取得してみましょう。

Prices

Returns the current price for all supported markets. Some values may be out of date by a few seconds.

Example: https://api.cryptowat.ch/markets/prices

価格です。量が多いので日本円絡みのものだけ見てみます。


~ $ curl -s https://api.cryptowat.ch/markets/prices | jq "." | grep jpy
    "bitflyer:btcfxjpy": 990450,
    "bitflyer:btcjpy": 980519,
    "bitflyer:btcjpy-biweekly-futures": 984440,
    "bitflyer:btcjpy-weekly-futures": 984750,
    "bitmex:btcjpy-quarterly-futures": 9342,
    "kraken:btcjpy": 980085,
    "kraken:ethjpy": 102171,
    "kraken:repjpy": 0,
    "kraken:xrpjpy": 0,
    "kraken:zecjpy": 0,
    "quoine:bchjpy": 139770.97,
    "quoine:btcjpy": 1010138.75,
    "quoine:ethjpy": 107000,

いくつかは価格が「0」となっていますが。

JSON形式で、項目としては


"(取引所):(通貨ペア)": 価格円

が取得できるようです。

もうひとつみてみます。

Asset
Returns a single asset. Lists all markets which have this asset as a base or quote.

Example: https://api.cryptowat.ch/assets/btc

こちらでは以下のようなものが取得できます。


~ $ curl -s https://api.cryptowat.ch/assets/jpy | jq '.'
{
  "result": {
    "id": 104,
    "symbol": "jpy",
    "name": "Japanese Yen",
    "fiat": true,
    "markets": {
      "quote": [
        {
          "id": 89,
          "exchange": "kraken",
          "pair": "btcjpy",
          "active": true,
          "route": "https://api.cryptowat.ch/markets/kraken/btcjpy"
        },
        {
          "id": 100,
          "exchange": "kraken",
          "pair": "ethjpy",
          "active": true,
          "route": "https://api.cryptowat.ch/markets/kraken/ethjpy"
        },
        {
          "id": 120,
          "exchange": "kraken",
          "pair": "repjpy",
          "active": true,
          "route": "https://api.cryptowat.ch/markets/kraken/repjpy"
        },
        {
          "id": 126,
          "exchange": "kraken",
          "pair": "zecjpy",
          "active": true,
          "route": "https://api.cryptowat.ch/markets/kraken/zecjpy"
        },
        {
          "id": 140,
          "exchange": "kraken",
          "pair": "xrpjpy",
          "active": true,
          "route": "https://api.cryptowat.ch/markets/kraken/xrpjpy"
        },
        {
          "id": 184,
          "exchange": "quoine",
          "pair": "btcjpy",
          "active": true,
          "route": "https://api.cryptowat.ch/markets/quoine/btcjpy"
        },
        {
          "id": 196,
          "exchange": "quoine",
          "pair": "ethjpy",
          "active": true,
          "route": "https://api.cryptowat.ch/markets/quoine/ethjpy"
        },
        {
          "id": 206,
          "exchange": "quoine",
          "pair": "bchjpy",
          "active": true,
          "route": "https://api.cryptowat.ch/markets/quoine/bchjpy"
        },
        {
          "id": 215,
          "exchange": "bitflyer",
          "pair": "btcjpy",
          "active": true,
          "route": "https://api.cryptowat.ch/markets/bitflyer/btcjpy"
        },
        {
          "id": 217,
          "exchange": "bitflyer",
          "pair": "btcjpy-weekly-futures",
          "active": true,
          "route": "https://api.cryptowat.ch/markets/bitflyer/btcjpy-weekly-futures"
        },
        {
          "id": 218,
          "exchange": "bitflyer",
          "pair": "btcjpy-biweekly-futures",
          "active": true,
          "route": "https://api.cryptowat.ch/markets/bitflyer/btcjpy-biweekly-futures"
        },
        {
          "id": 409,
          "exchange": "bitflyer",
          "pair": "btcfxjpy",
          "active": true,
          "route": "https://api.cryptowat.ch/markets/bitflyer/btcfxjpy"
        },
        {
          "id": 248,
          "exchange": "bitmex",
          "pair": "btcjpy-quarterly-futures",
          "active": true,
          "route": "https://api.cryptowat.ch/markets/bitmex/btcjpy-quarterly-futures"
        },
        {
          "id": 424,
          "exchange": "bitmex",
          "pair": "btcjpy-monthly-futures",
          "active": false,
          "route": "https://api.cryptowat.ch/markets/bitmex/btcjpy-monthly-futures"
        }
      ]
    }
  },
  "allowance": {
    "cost": 162263,
    "remaining": 7999837737
  }
}

これを見ると個別のチャートを参照できるURLは


https://api.cryptowat.ch/markets/(取引所)/(通貨ペア)

であることがわかります。

他にもたくさんのデータが取得できるようです。

さあ、みんなもやってみよう。

 

👉 Kotlin 今どきよくある JSON リクエストからのパース hatena-bookmark


イベントハンドラとラムダ

おさらい


val printHelloWorld = {
   println("Hello, world!")
}

printHelloWorld()
//printHelloWorld.invoke()

これで以下が出力される。

Hello, world!

同様に引数を渡す。


val printGreeting = { word: String, name: String ->
   println("$word, $name")
}

printGreeting("おはよう", "太郎")
printGreeting.invoke("こんにちは", "次郎")

おはよう, 太郎
こんにちは, 次郎

これまでのコールバック

inferface を使ったコールバックは kotlin では以下のように書けます。


interface CallBackListener {
    fun onHoge(foo: String, bar: Int)
}

// caller
var callback: CallBackListener? = null
callback?.onHoge("foo", 100)

// callee
val callback = object : CallBackListener {
    override fun onHoge(foo: String, bar: Int) {
        print("$foo : $bar")
    }
}

これを typealias で。


typealias CallBackListener = (foo: String, bar: Int) -> Unit

// caller
var callback: CallBackListener? = null
callback?.invoke("foo", 100)

// callee
val callback = { foo, bar ->
    print("$foo : $bar")
}

【Kotlin】 TypeAliasで関数リテラルに名前を付ける - Qiita

イベントハンドラ

例えば、RecyclerView でそれぞれのアイテムのViewHolder内のある要素のクリックイベントを拾いたい時、Activity(View)までが遠いですよね。

Activity(View)
↓↑
RecyclerViewAdapter
↓↑
ViewHolder

少しでも、コールバック記述をシンプルにして見通し良くしておきたいものです。

ここで Type Alias を使います。

typealias EventHandler = (T) -> Unit

java - Kotlin: Use a lambda in place of a functional interface? - Stack Overflow

1. ViewHolder にハンドラー記述。クラスの外。

ItemViewHolder:


internal typealias ItemHandler = (Item) -> Unit

それを拡張して、ハンドラークラスを作ります。
invoke を override します。

ShareItemHandler:


internal class ShareItemHandler(
  private val activity: Activity
) : ItemHandler {

  override fun invoke(item: Item) {
    IntentBuilder.from(activity)
        .setType("text/plain")
        .setChooserTitle("Share ${item.name} to ?")
        .setText("${$item.name} ${item.address}")
        .startChooser()
  }
}

ClipboardCopyItemHandler:


internal class ClipboardCopyItemHandler(
  private val context: Context
) : ItemHandler {

  override fun invoke(item: Item) {
    val clipboard = context.systemService<ClipboardManager>()
    clipboard.primaryClip = ClipData.newPlainText(item.name, item.address)
  }
}

2. Activity で そのインスタンスを生成して
RecyclerAdapter経由でViewHolder内にセットしていきます。

以下関係部分のみ抜粋。

MainActivity:


val onCopy = ClipboardCopyItemHandler(this)
val onShare = ShareItemHandler(this)

// ...

val layoutManager = LinearLayoutManager(this)
recyclerView.layoutManager = layoutManager
val adapter = ItemAdapter(layoutInflater, onCopy, onShare)
recyclerView.adapter = adapter

ItemAdapter:


internal class ItemAdapter(
  private val inflater: LayoutInflater,
  private val onCopy: (Item) -> Unit,
  private val onShare: (Item) -> Unit
) : RecyclerView.Adapter<ItemViewHolder>() {

  // ...

  override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {
    val view = inflater.inflate(R.layout.item, parent, false)
      return ItemViewHolder(view, onCopy, onShare)
    }

ItemViewHolder:



internal typealias ItemHandler = (Item) -> Unit // ***

internal class ItemViewHolder(
  private val root: View,
  private val onCopy: ItemHandler
  private val onShare: ItemHandler,
) : ViewHolder(root), OnClickListener, OnMenuItemClickListener {

  // ...  

  override fun onClick(view: View) = when(view.id) {
    R.id.copy -> onCopy(item!!)
    R.id.share -> onShare(item!!)
    else -> throw IllegalArgumentException("Unknown menu item: $menuItem")
  }

なんだか素晴らしいですね。

RecyclerView利用時のテンプレートとして。