アプリ置き場

アプリ置き場

http://www.moreread.net/

リタイアシミュレータ

逃げ切り計算機を使わせていただいて妄想が捗っていたのですが、細かい設定がしたかったり、グラフで見たかったり、結果を保存したかったり、等々があったのでシミュレータを作りました。
早期リタイア、アーリーリタイア、セミリタイアのための資産運用シミュレーションです。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 

BitMex 価格の取得

ccxtでBitMexのfetch_tickerが403になる。
下記で価格はとれた。
サーバーが直るのか、APIが禁止でccxtが更新されるのかわからんけど、暫定でとりあえずbotの動作再開。
import urllib
 
data = json.loads(ret.decode("utf8"))
 
return data["result"]["price"]

Amazon Echo スキル開発

審査かなりきびしい。何度めだかわからない申請してようやく通った。
とりあえず習作として「目隠し○×ゲーム」というのを作ってみました。
 
下記のサイトに紹介が。
//動画があったので再生したらうちのAlexaが反応するっていう。。ピザ注文テロとか発生しそう。
 
数字で座標を指定して○×を配置するルールなのだけど、申請のリジェクト理由の一つに、ユーザーは「真ん中」とかいうから!ちゃんと対応して!みたいなのがあって、細かいなぁと思った。まだ登録されてるアプリが少ないけど、審査厳しくて弾かれまくってるんじゃなかろうか。
 
あとDQX用にやいばくだきタイマ―つくったら商標ブランドがうんたらでダメっていわれた。無念。

echo dot 例外処理は?

ようやくとどいたー。結構いい精度で聞き取ってくれる。


そして、チュートリアルに言われるがまま、ぽちぽちクリックしてたらスキルつくれた。
 
無言だったときとか、聞き取れなかった場合などの処理がよくわからなかったが、UnhandledやSessionEndedRequestで拾えるらしい。ちなみにaskは8秒経過で次のメッセージ、さらに8秒経過でセッションが切れてSessionEndedRequestだそうな。
 
var handlers = {
    'LaunchRequest': function () {
        this.emit(':ask', text, text2);
    },
  ~~略~~
    Unhandled: function() {
        this.emit(':ask', ”ぱーどぅん?”, "わっと?");
    },
    SessionEndedRequest: function() {}
};

MaDotPaint V1.0.4

勢いでレイヤー機能も追加したった。

レイヤー構造っても透過画像重ねるだけなんでどうってことないのだけど、ファイルの保存で困った。レイヤーを扱うための一般的な画像形式ってないのだろうか?案外汎用的なフォーマットが見つからない。謎。
よくわかんないから、PNGに連番の名前つけてZIPで固めて保存した。独自の拡張子つけて。もう少し丁寧にやるならレイヤー名やらパレットとの紐付とか管理情報ファイルは別に入れたほうが良いきがするけど、とりあえずこれで足りてるかなー。
 
 

PixelFormat.Format8bppIndexedとGIFアニメ出力

これだとキャッチ―さが足りないのではないか。

 
せっかくペイントソフトも作った(http://www.moreread.net/)のでキャッチ―なドット絵を描きたい。描いてみよう。16x16サイズてきついな……。

描いたところでアニメーションさせてみたくなる。ということで簡易アニメーションビューワも作った。左上からZ字で指定の大きさでスキャンしてくだけのものだけど。

さらについでに画像の分割保存機能もつけた。よし、ついでにアニメーションGIFにしてまえ。DOBONさんのところにアニメーションGIFを吐き出すコードがあった。
 

!?
Bitmapクラス(32bpp)をそのままGIF指定で保存すると、デフォルトのパレットで誤差拡散されて無残な結果になってしまった。
どうも先に8bppIndexedカラー化しておかねばならないようだ。
ググっても見つからなかったのでとりあえずてきとうに書いた。
public static Bitmap GetIndexedBitmap(Bitmap orgBmp)
{
    if (orgBmp == null) return null;
 
    //処理時間計測
    Stopwatch sw = new Stopwatch();
    sw.Start();
 
    //元画像(32bpp)をバッファに読み出す
    BitmapData orgData = orgBmp.LockBits(new Rectangle(0, 0, orgBmp.Width, orgBmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
    byte orgBuf = new byte[orgBmp.Width * orgBmp.Height * 4];
    Marshal.Copy(orgData.Scan0, orgBuf, 0, orgBuf.Length);
    orgBmp.UnlockBits(orgData);
 
    //出力先画像(8bppIndexed)の生成とバッファの取出し
    Bitmap indexedBmp = new Bitmap(orgBmp.Width, orgBmp.Height, PixelFormat.Format8bppIndexed);
    ColorPalette palette = indexedBmp.Palette;
    int boundaryWidth = ((indexedBmp.Width + 3) / 4) * 4;// 4Byte境界込みの幅
    BitmapData indexedData = indexedBmp.LockBits(new Rectangle(0, 0, indexedBmp.Width, indexedBmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
    byte indexedBuf = new byte[boundaryWidth * indexedBmp.Height];
    Marshal.Copy(indexedData.Scan0, indexedBuf, 0, indexedBuf.Length);
 
    //元画像から色を抽出しつつパレットと画像の生成
    Dictionary<Color, int> dicPalette = new Dictionary<Color, int>();
    int count = 1;
    palette.Entries[0] = Color.FromArgb(1, 0, 0); //index 0 は透明色とする
    for (int i = 0; i < indexedBmp.Height; i++)
    {
        for (int j = 0; j < indexedBmp.Width; j++)
        {
            int pos_org = (i * indexedBmp.Width + j) * 4;
            int pos_indexed = i * boundaryWidth + j;
            Color c = Color.FromArgb(BitConverter.ToInt32(orgBuf, pos_org));
            if (c.A < 255)
            {
                indexedBuf[pos_indexed] = 0;
                continue;
            }
            if (!dicPalette.ContainsKey(c))
            {
                dicPalette.Add(c, count);
                palette.Entries[count] = c;
                count++;
                if (count > 255) count = 255;// 256色以上は非対応
            }
            int index = dicPalette[c];
            indexedBuf[pos_indexed] = (byte)index;
        }
    }
 
    //出力先画像(8bppIndexed)の後処理
    indexedBmp.Palette = palette;
    Marshal.Copy(indexedBuf, 0, indexedData.Scan0, indexedBuf.Length);
    indexedBmp.UnlockBits(indexedData);
 
    //計測結果出力
    sw.Stop();
    Console.WriteLine("[GetIndexedBitmap] time = " + sw.ElapsedMilliseconds + "ms");
 
    return indexedBmp;
}
 
ちなみにこちらを参考にしつつ透過情報を埋め込むにあたって、面倒なのでパレット0を透過色固定にしてある。
 
とりあえず上記のコードを通してから、DOBONさんところのGIFアニメを吐き出すコードを通したら、元のパレットを維持したままGIFアニメを出力できた。
 

Meltdown、Spectre、そしてJavaScript

CPUのOut Of Orderやら投機実行における脆弱性というところの仕組み(キャッシュに展開される)はなんとなくわかったのだけど、それはどうやって読み出すのだろう?JavaScriptからも可能ってのはどういうことなんだろう?
CPUのキャッシュに放り込むための投機実行のコードをJSで書けるのはわかるんだけども、

CPUキャッシュから情報を抜き出すための、FLUSH+RELOADなる方法が使われているようだ。サイドチャネルアタック(いろんな手段で観察して情報を推測したりする攻撃)らしいが。
読み取れないはずの領域のデータを添え字にしてメモリアクセスすると、
そこがキャッシュされるため、アクセス時間を正確にはかれば、データ内容が復元できる…?
 
JavaScript does not provide access to the rdtscp in-
struction, and Chrome intentionally degrades the accu-
racy of its high-resolution timer to dissuade timing at-
tacks using performance.now()[1].
However, the Web Workers feature of HTML5 makes it simple to cre-
ate a separate thread that repeatedly decrements a value
in a shared memory location [18, 32]. This approach
yielded a high-resolution timer that provided sufficient resolution
 
Javascriptからはperformance.now()といった高精度タイマーや、Workerを使うと再現でけると。
 
Jann Horn of Google Project Zero Security reported that speculative execution performed by modern CPUs could leak information through a timing side-channel attack. Microsoft Vulnerability Research extended this attack to browser JavaScript engines and demonstrated that code on a malicious web page could read data from other web sites (violating the same-origin policy) or private data from the browser itself.
Since this new class of attacks involves measuring precise time intervals, as a partial, short-term, mitigation we are disabling or reducing the precision of several time sources in Firefox. The precision of performance.now() has been reduced from 5μs to 20μs, and the SharedArrayBuffer feature has been disabled because it can be used to construct a high-resolution timer.
Mozillaはタイマーの制度を下げたのか。
SharedArrayBufferというのはWorker間でメモリを共有する仕組みで、高精度タイマーを作れちゃうのでこれをOffる対応も入ってると。