2013-09-27

Surface 2 の発表から Windows RT の普及を考える

9 月 24 日(米国時間)から Microsoft 直営店の Microsoft Store サンフランシスコ店で Surface Pro 2 および Surface 2 の予約が開始されたということです。Surface Pro 2 は、Surface Pro の後継機で、プロセッサに第4世代 Core シリーズの Core i5-4200U、Surface 2 は Surface RT の後継機で、プロセッサには Tegra 4(1.7GHz、ARM Cortex-A9: 4コア、NVIDIA GPU: 72コア)が採用されています。詳細は関連サイトの記事をご覧になってください。

今回の新モデルの発表で注目したいのが Surface 2 です。搭載されている OS は Windows 8.1 RT、ARM 系プロセッサ対応の Windows です。

Windows NT 4 まで、Intel 系プロセッサの他に Alpha, MIPS そして PowerPC もサポートされていました。2011 年初めに Windows NT 系プラットフォームが ARM 系プロセッサにも対応することが発表され、2012 年 10 月に Windows 8 シリーズ(Windows NT 6 系)のひとつとして ARM 系プロセッサのモバイル端末向けの Windows RT がリリースされました。

今回、ARM 系プロセッサ対応の Windows RT も 8.1 と更新され、新しい端末と共に発売されるということは、たとえ初代の Surface の売上が芳しくなくとも、今後も Intel 系プロセッサと同様に ARM 系プロセッサ対応の Windows が開発され続けることへの期待が持てます。そうであれば、Windows RT がもっと普及して欲しいと応援したくもなってしまいます。

個人的には、Intel 系の CPU が省電力と処理能力の向上に成功することに期待するより、既にモバイル端末分野で普及している ARM 系プロセッサ用に、OS としての Windows がもっと普及する方に期待してしまうのです。

Intel 系プロセッサ (x86) の市場は、追撃する AMD を寄せ付けず Intel の一人勝ちの様相であるのに対して、ARM 系プロセッサの市場では、Qualcomm / Snapdragon, Samsung / Exynos, NVIDIA / Tegra などなど、ARM 社から IP コアのライセンス供与を受けている企業のプロセッサが数多く存在します。プロセッサは PC に使われているだけではなく、自動車や電化製品その他、様々な分野で利用されていることは言うまでもありません。そして ARM チップは世界で最もよく使われている CPU デザインの一つとなっています。すでにスマートフォンなどモバイル端末では広く使われているプロセッサですが、PC では今まで触れることのなかった ARM プロセッサに、PC 的な使い方(プログラミングができる環境)で触れたいという欲求があります。

また、Windows PC が爆発的に普及した結果、ハードウェア仕様の標準化が進められ 注)、アマチュアでも PC パーツからパソコンを組み立てることが簡単にできるようになりました。そして Linux もこの標準化の恩恵を受けて Windows PC への Linux のインストールがずいぶん簡単になったと言えます。Windows RT が普及することでも、似たような「仕様の標準化」が進むことを期待してしまいます。

注)厳密に言えば PC のハードウェア仕様の標準化は DOS/V と呼ばれた IBM PC/AT 互換機対応から始まったと言った方が適切かも知れません。

そういうわけで Linux ユーザでありながら、Windows RT の普及に期待を持ってしまうのですが、考えてみると Android 端末の普及でも同じことが言えそうです。ところが Android は Linux がベースになっているとは言え、最新のソースコードが限定的な Google のパートナー(Tier 1 と呼ばれる限定数社)にしか提供されていない状態で、とてもオープンソースのプロジェクトとは言えないという記事も目にします。Windows はオープンソースのプロジェクトではありませんが、Windows が動作するハードウェアの仕様や Windows 対応 PC と認証するプログラムを積極的に推進しています。

モバイル業界では技術開発競争が激しく、マイクロソフトも Surface という自社開発のハードウェアを投入しないと参入が難しいぐらい追い詰められているのかもしれませんが、そこは世界的な大企業の立場をフルに活かして、Surface をリファレンスモデルとして、サードパーティが参入しやすいように仕様を標準化する方向に互恵関係を築き上げて欲しいものだと願っています。こういうビジネスモデルは世界的な大企業でないと効果的には展開できないと思うからです。

いずれは Surface 2 が日本で発売される日がくるでしょう。初代の Surface RT の発売時は様子見と決め込んでいましたが、そろそろ買い時かもしれません。

関連サイト

  1. Microsoft、Haswell搭載の「Surface Pro 2」とTegra 4搭載の「Surface 2」 ~日本でも近日発表か? - PC Watch
  2. Surface 2/Pro 2の予約販売が米国で開始 ~店頭の展示実機を写真でチェック - PC Watch
  3. 「Surface 2」の第一印象--薄型軽量化した「Tegra 4」搭載の新モデル - CNET Japan
  4. Surface 2のLTEモデルが来年登場か!? 中の人が語る
  5. Windows NT系 - Wikipedia
  6. WindowsがARMをサポートするという話 - ブログ de OS - unakami - builder by ZDNet Japan
  7. ビジネスニュース 企業動向:100億個規模のCPUコア市場、ARMが独占状態 - EE Times Japan
  8. Androidの透明性とGoogle先生とのつきあい方 - Future Insight
  9. Windows ハードウェア - Windows ハードウェア デベロッパー センター
  10. Microsoft forges ahead with ARM tablets | Microsoft - CNET News

2013-09-23

お手軽 Firefox OS Simulator - テトリス

HTML5 の canvas を使ったテトリスを、Firefox OS Simulator 上で動くようにしてみました。下記のサイトの JavaScript を Firefox OS Simulator 上で動くようにテトリスが描画されるサイズを調整してボタンを付加しただけで、まだスコアもレベルもありません。

スコアやレベルを加え、汎用な画面サイズでの使用に耐えられるように改良していこうと考えていますが、とりあえず下記からパッケージ型アプリとしてダウンロードできるようにしました。

実行例を下記に示しました。

スコアもレベルもありませんが、とりあえず遊べます。


JavaScript

下記に編集したところも含めてテトリスの JavaScript の部分 tetris.js を示しました。この JavaScript はライセンスが明記されていないので、扱いをどうするか悩みますが、GitHub にソースが公開されている以上、改変して使用しても大丈夫だろうと判断しました。念のため、下記「補足」に作者に確認を取っています。

スクリプトの末尾にボタンのイベントハンドリング処理を加えました。

/**
 * Canvas Tetris
 * Author: Dusko Jordanovski <jordanovskid@gmail.com>
 **/
var SQ = 20;   // square side in pixels
var HCOUNT = 15;   // horizontal width in squares
var VCOUNT = 20;   // vertical width in squares
var WIDTH = SQ * HCOUNT;
var HEIGHT = SQ * VCOUNT;
var SPEED = 250; // game speed in the loop.
var DROPSPEED = 50;  // game speed when dropping objects.
var ORIGSPEED = 250; // original game speed
var BGCOLOR = '#fff';

var canvas = document.getElementById('game');
canvas.width = WIDTH;
canvas.height = HEIGHT;

var ctx = canvas.getContext('2d');

// Object definitions
// Cube, Left L, Rright L, S shape, Z shape, T shape, Pipe (I)
// '0' is the normal orientation
// '1' is the object rotated 90 degrees clockwise
// '2' is the object rotated 180 degrees clockwise
// '3' is the object rotated 270 degrees clockwise

var objects = [
    {// Cube
        fill: '#8e8',
        0: [[0, 0], [1, 1], [0, 1], [1, 0]], 1: [[0, 0], [1, 1], [0, 1], [1, 0]],
        2: [[0, 0], [1, 1], [0, 1], [1, 0]], 3: [[0, 0], [1, 1], [0, 1], [1, 0]]
    }, {// Normal L
        fill: '#e88',
        0: [[0, 0], [1, 0], [1, 1], [1, 2]], 1: [[0, 1], [1, 1], [2, 1], [2, 0]],
        2: [[0, 0], [0, 1], [0, 2], [1, 2]], 3: [[0, 0], [1, 0], [2, 0], [0, 1]]
    }, {// Reverse L
        fill: '#88e',
        0: [[0, 0], [1, 0], [0, 1], [0, 2]], 1: [[0, 0], [1, 0], [2, 0], [2, 1]],
        2: [[1, 0], [1, 1], [1, 2], [0, 2]], 3: [[0, 0], [0, 1], [1, 1], [2, 1]]
    }, {// S - shaped
        fill: '#ee8',
        0: [[0, 1], [1, 1], [1, 0], [2, 0]], 1: [[0, 0], [0, 1], [1, 1], [1, 2]],
        2: [[0, 1], [1, 1], [1, 0], [2, 0]], 3: [[0, 0], [0, 1], [1, 1], [1, 2]]
    }, {// Z - shaped
        fill: '#8ee',
        0: [[0, 0], [1, 0], [1, 1], [2, 1]], 1: [[1, 0], [1, 1], [0, 1], [0, 2]],
        2: [[0, 0], [1, 0], [1, 1], [2, 1]], 3: [[1, 0], [1, 1], [0, 1], [0, 2]]
    }, {// T - shaped
        fill: '#e8e',
        0: [[0, 0], [1, 0], [2, 0], [1, 1]], 1: [[0, -1], [0, 0], [0, 1], [1, 0]],
        2: [[0, 0], [1, -1], [2, 0], [1, 0]], 3: [[2, -1], [1, 0], [2, 0], [2, 1]]
    }, {// Pipe
        fill: '#888',
        0: [[0, 0], [0, 1], [0, 2], [0, 3]], 1: [[-1, 1], [0, 1], [1, 1], [2, 1]],
        2: [[0, 0], [0, 1], [0, 2], [0, 3]], 3: [[-1, 1], [0, 1], [1, 1], [2, 1]]
    }
];

// current object
var object = null;
// object's orientation
var or = 2;
// last position of the object
var objectPos = [];
// horizontal position (offset) of the object
var hpos = 4;
// vertical position (offset) of the object
var vpos = 0;
// whether this is the first tick of a new object
var newOb = true;
// last tick's time
var t = new Date();
// If true the last object should be glued
var glue = false;
// The Map, Grid, Matrix .. whatever
// Note: The map has 3 types of fields (squares). Empty fields have 
// value 1, fields that are occupied by the current moving object have value 2,
// and fields that are occupied by settled objects have a string value of the
// color in which they should be displayed (object's 'fill' property)
var Map = [];

function resetGame() {
    for (var i = 0; i < HCOUNT; i++) {
        Map[i] = [];
        for (var j = 0; j < VCOUNT; j++)
            Map[i][j] = 1;
    }
    glue = false, newOb = true, vpos = or = 0, hpos = 4;
}
resetGame();

// The main game logic loop
function tick() {
    // Clears the map cells where the object used to be in the previous tick
    var color = 1;
    var removeLines = false;
    if (glue) {
        removeLines = true;
        glue = false;
        newOb = true;
        color = object.fill;
        vpos = 0;
        hpos = 4;
        or = 0;
    }
    for (var i = 0; i < objectPos.length; i++)
        Map[ objectPos[i][0] ][ objectPos[i][1] ] = color;
    objectPos = [];

    removeLines && removeFullLines();

    if (newOb) {
        // next random object to appear
        object = objects[ Math.floor(Math.random() * objects.length) ];
        // compensates the vpos for the object's height
        //vpos -= Math.max( object[or][0][1], object[or][1][1], object[or][2][1], object[or][3][1] ) + 1;
    }

    var x, y, olength = object[or].length;

    // Place the object on the map
    // The object won't be out of horizontal bounds
    for (i = 0; i < olength; i++) {
        x = hpos + object[or][i][0];
        y = vpos + object[or][i][1];

        if (Map[ x ][ y ]) {
            Map[ x ][ y ] = 2;
            objectPos.push([x, y]);
        }
    }

    // Check the time difference from the last tick
    // This dictates the game speed
    var t1 = new Date();
    if (t1 - t > SPEED) {
        // if it's time for a new tick
        var columns = {};
        for (i = 0; i < olength; i++) {
            x = hpos + object[or][i][0];
            y = vpos + object[or][i][1];

            if (y < 0)
                continue;

            !isNaN(columns[x]) || (columns[x] = y);
            columns[x] = Math.max(columns[x], y);
        }

        for (i in columns)
            if (columns[i] === VCOUNT - 1 || Map[i][columns[i] + 1] !== 1) {
                glue = true;
                if (newOb) {
                    alert("Game Over");
                    resetGame();
                }
                SPEED = ORIGSPEED;
                return;
            }

        t = t1;
        vpos += 1;
    }

    newOb = false;
}

// Scans the map for filled lines and removes them.
function removeFullLines() {
    var line, j, i, k;
    for (i = VCOUNT - 1; i > 0; i--) {
        line = true;
        for (j = 0; j < HCOUNT; j++)
            if (typeof Map[j][i] !== 'string')
                line = false;

        if (line) {
            for (k = i; k > 0; k--)
                for (j = 0; j < HCOUNT; j++)
                    Map[j][k] = Map[j][k - 1];
            i++;
        }
    }
}

// Checks if the object can be moved to the side
function canMove(side) {
    var maxFunc = side === 1 ? Math.max : Math.min;
    var rows = {}, x, y;
    for (var i = 0, olength = object[or].length; i < olength; i++) {
        y = vpos + object[or][i][1];
        x = hpos + object[or][i][0] + side; // temporarily move the object sideways
        !isNaN(rows[y]) || (rows[y] = x);  // get the leftmost/rightmost square in each row
        rows[y] = maxFunc(rows[y], x);
    }
    // Check if the leftmost/rightmost square is in an illegal position
    for (i in rows)
        if (rows[i] < 0 || rows[i] > HCOUNT - 1 || Map[ rows[i] ][ i ] !== 1)
            return false;
    return true;
}

// Checks if the element can be rotated.
function canRotate() {
    var newOr = (or + 1) % 4;
    var to = object[ newOr ], x, y;
    for (var i = 0, olength = to.length; i < olength; i++) {
        x = hpos + to[i][0];
        y = vpos + to[i][1];

        // If we want to rotate an object at the edge, try 
        // moving that object to the side to see if it can rotate.
        if (!Map[x]) {
            var mod = x < 0 ? 1 : -1;
            hpos += mod;
            if (canRotate())
                return true;
            else
                hpos -= mod;
        }

        if (!Map[x][y] || typeof Map[x][y] === 'string')
            return false;
    }

    return true;
}

// draws a line from point (fromx, fromy) to point (tox, toy)
function line(fromx, fromy, tox, toy) {
    ctx.beginPath();
    ctx.moveTo(fromx, fromy);
    ctx.lineTo(tox, toy);
    ctx.stroke();
}

// The grid line styles
ctx.strokeStyle = '#999';
ctx.lineWidth = .5;
function drawMap() {
    // clear map and draw grid
    ctx.clearRect(0, 0, WIDTH, HEIGHT);
    var currentSquare, w, h, i;
    // this loop draws the current map state
    for (w = 0; w < HCOUNT; w++) {
        ctx.save();
        ctx.translate(w * SQ, 0); // Move the canvas horizontally
        for (h = 0; h < VCOUNT; h++) {
            currentSquare = Map[w][h];
            ctx.save();
            ctx.translate(0, h * SQ); // Move the canvas vertically
            if (currentSquare === 2) {
                ctx.fillStyle = object.fill;
                ctx.fillRect(0, 0, SQ, SQ);
            }
            else if (typeof currentSquare === 'string') {
                ctx.fillStyle = currentSquare;
                ctx.fillRect(0, 0, SQ, SQ);
            }
            ctx.restore();
        }
        ctx.restore();
    }
    // draws the grid
    for (i = 1; i < WIDTH; i++)
        line(i * SQ, 0, i * SQ, HEIGHT);
    for (i = 1; i < HEIGHT; i++)
        line(0, i * SQ, WIDTH, i * SQ);
}

var running = false, drawLoop, tickLoop;
document.onkeydown = function(e) {
    var key = e.which;

    if (running && key === 65 && canRotate()) { // a - rotate
        or = ++or % 4;

    } else if (key === 40) { // down - drop the object by increasing game speed
        SPEED = DROPSPEED;
    } else if (key === 83) { // s - stop (pause)
        if (running) {
            clearInterval(drawLoop);
            clearInterval(tickLoop);
        } else {
            drawLoop = setInterval(drawMap, 50);
            tickLoop = setInterval(tick, 50);
        }
        running = !running;
    } else if (running && key === 37 && canMove(-1)) { // left - move left
        hpos--;
    } else if (running && key === 39 && canMove(1)) // right - move right
        hpos++;
};

document.onkeyup = function(e) { // cancel drop
    if (e.which === 40)
        SPEED = ORIGSPEED;
};

// event handling for button
// added by Fuhito Suguri, 23-Sep-2013
document.getElementById("move_left").addEventListener('click', function(event) {
    if (running && canMove(-1)) // left - move left
        hpos--;
}, false);
document.getElementById("move_right").addEventListener('click', function(event) {
    if (running && canMove(1)) // right - move right
        hpos++;
}, false);
document.getElementById("move_down").addEventListener('click', function(event) {
    SPEED = DROPSPEED;
}, false);
document.getElementById("rotate").addEventListener('click', function(event) {
    if (running && canRotate()) // a - rotate
        or = ++or % 4;
}, false);
document.getElementById("start").addEventListener('click', function(event) {
    if (running) {
        clearInterval(drawLoop);
        clearInterval(tickLoop);
    } else {
        drawLoop = setInterval(drawMap, 50);
        tickLoop = setInterval(tick, 50);
    }
    running = !running;
}, false);

HTML

メインファイル index.html は画面をタッチして操作出きるようにボタンを加えてあります。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Canvas Tetris</title>
        <link rel="stylesheet" href="css/tetris.css" TYPE="text/css">
    </head>
    <body>
        <!--
                <h1 style='text-align:center; margin-bottom: 5px; font-family:Georgia;'>Canvas Tetris</h1>
                <div style='text-align:center; font-family:Georgia; font-size:12px'>
                    This is a tetris game implemented in HTML5.<br>
                    You'll need a browser that supports the <canvas> element.<br>
                    Left, Right and Down arrows to move, "a" to rotate, "s" to start/pause.<br>
                </div>
                <br>
        -->
        <div style='text-align:center'>
            <canvas id='game' style='border:solid 2px #aaa;'>
                Your browser does not support the <canvas> element.<br>
                Please use a normal browser. Hint: Safari, Chrome, Firefox.
            </canvas>
        </div>
        <div id="ctr">
            <button id="move_left"><img src="img/arrow_left.png" alt="<"></button>
            <button id="move_right"><img src="img/arrow_right.png" alt=">"></button>
            <button id="rotate"><img src="img/arrow_rotate.png" alt="a"></button>
            <button id="move_down"><img src="img/arrow_down.png" alt="_"></button>
        </div>
        <div id="func">
            <button id="start"><img src="img/start.png" alt="s"></button>
        </div>
        <script src="js/tetris.js"></script>
    </body>
</html>

CSS

スタイルシート tetris.css は、現在のところボタンの位置決めだけです。

#ctr {
    position: absolute;  
    bottom: 10px;  
}
#func {
    position: absolute;  
    bottom: 10px; 
    right: 10px;
}

ある程度ゲームらしくなったらホームページに解説付きでまとめる予定です。


補足

念のため、Tetris の作者にメールを出して、プログラムの使用の確認を取りました。本名でやりとりしていますが、Fuhito Suguri に書き換えて紹介していることをご了承下さい。

From - Mon Sep 23 20:33:24 2013
Date: Mon, 23 Sep 2013 20:33:20 +0900
From: Fuhito Suguri <xxxxxx at gmail.com>
To: Dusko Jordanovski <jordanovskid at gmail.com>
Subject: Re: distribution license of your tetris program with JavaScript

Hi Dusko,

Thank you for your prompt and kind response.
I got you. :)

Fuhito

(09/23/2013 08:18 PM), Dusko Jordanovski wrote:
> Hi,
>
> I haven't put a license on the code since I didn't expect that anyone 
> would use it.
> In any case, feel free to do whatever you like with the code - it's 
> fine with me.
> If you need a specific license - let's call it MIT.
>
> Regards,
> Dusko.
>
>
> - D
>
> On Monday, September 23, 2013 at 1:10 PM, Fuhito Suguri wrote:
>
>> Hello Dusko,
>>
>> My name is Fuhito Suguri. I would like to know distribution license
>> of the tetris program you made in the following site:
>>
>> https://github.com/skid/canvas-tetris
>>
>> In fact, I've already introduced the tetris apps running on the Firefox
>> OS as an example based on your tetris program on my blog, where is
>> written in Japanese though:
>> http://bitwalk.blogspot.jp/2013/09/firefox-os-simulator_23.html
>>
>> Please kindly advise me if there are some restrictions to use your
>> program. Thank you very much for your kind attention and best
>> understandings in advance.
>>
>> Best Wishes,
>> Fuhito
>

2013-09-20

お手軽 Firefox OS Simulator - 全言語版シミュレータ

Firefox Simulator の全言語版のシミュレータが非公式に公開されていることを下記の資料(42/87 ページ)で知りました。

全言語版のシミュレータは下記のサイトから入手出来ます。既に公式の Firefox OS Simulator をインストールしている場合は、一旦アンインストールしてから、全言語版をインストールしてください。

早速 Fedora 19 (Linux) 上の Firefox 24.0 にインストールしてみましたので、下記にそのハードコピーを示しました。なお、今回インストールした Firefox OS Simulator のバージョンは下記の通りです。

シミュレータを起動して、言語設定をします。

言語を日本語に設定すると、Firefox OS Simulator の画面は以下の様になります。

この全言語対応のシミュレータは、自動で更新されるアドオンモジュールではありませんのでご注意下さい。

2013-09-14

iPhone 5C予約開始 ドコモ、auは新型iPhoneの料金体系発表(13/09/13)

ドコモの参入で三つ巴の消耗戦に突入。ユーザにとってはありがたいことです。それにしても Apple はおいしい商売をしていますね。

2013-09-08

【備忘録】QR コード

QR コードとは、1994 年にデンソーの開発部門(現在のデンソーウェーブ)が開発したマトリックス型二次元コードです。QR は Quick Response に由来し、当初は自動車部品工場や配送センターなどでの使用を念頭に開発されましたが、現在ではスマートフォンの普及などにより日本に限らず世界的に普及しているようです[QRコード - Wikipedia]。QR コードは日本固有の規格だと思い込んでいましたが、ISO/IEC 18004 という国際規格にもなっています。

QR コードの生成

便利な世の中になったもので、QR コードの生成は、Google Chart API を利用すれば簡単にできます。以下に作成例を示します。

<img src="http://chart.apis.google.com/chart?chs=150x150&cht=qr&chl=http://bitwalk.blogspot.jp/" width="150" height="150" alt="bitWalk's">
bitWalk's

QR コードの読み取り(デコード)

一方、QR コードの読み取りは、Android 用の ZXing が有名です。これは Java のライブラリで、Objective C / C++ にもポートされています。JavaScript へは、LazerSoft が jsqrcode としてポートしています。HTML5 の canvas を使用するようです。また、SourceForge.jp に QRcode decode javascript というプロジェクトもあります。

Firefox OS のシミュレータではカメラを使えないのですが、これらのライブラリを利用してなんらかの評価をしてみたいと考えています。評価用の実機があれば…。

  1. QR コードの概要
  2. Google Chart APIでQRコードを作成する方法 [ホームページ作成] All About
  3. Multi-format 1D/2D barcode image processing library with clients for Android, Java - Google Project Hosting
  4. LazarSoft/jsqrcode
  5. QRcode decode javascript プロジェクト日本語トップページ - SourceForge.JP
  6. Mozilla offers free Firefox smartphones if developers port apps for OS | ITProPortal.com

2013-09-03

マイクロソフトのノキア買収が業界に及ぼす影響--山根康宏の見方 - CNET Japan

Steve Ballmer 氏が一年以内の退任するというニュースの次は Nokia の買収です。このところ Microsoft にまつわるなんともビックリなニュースが続きます。リンクした山根氏の論評にあるように、Microsoft にとって、ソフトからハードまですべて自社で開発できなくては、もはやモバイル市場での競争には勝てないという危機感が、この買収の根底にあるように感じられます。

しかし、出遅れた感のある Microsoft が Apple や Google とモバイル市場で積極的に競合しようとすることは、本当にビジネスとして得策なのでしょうか。たしかにモバイル市場は、PC のそれに比べると大きいでしょうし、PC の市場をも一部飲み込んでいくことでしょう。しかし、ビジネスにおいてモバイル機器が現在の PC に完全に取って代わるわけではありません。ビジネスユースにもっともっと優れた PC 用 OS を開発していくというビジョンでは、もはや会社を成功には導くことはできないのでしょうか。

Microsoft が向かう方向、それはやはり、まず、パーソナルユースに向いている、ということなのかもしれません。いや、モバイル市場を制覇することによって、そのインフラとなるサーバ市場をも獲得しようと目論んでいるような気もします。

Microsoft のビジョンは、Google ほどには明確に判らなかったので、下記にそれらしい YouTube の映像を探してきました。ただ、この Microsoft が描く未来の社会からは、今回の Nokia の買収を予感させるようなものを感じませんでした。