トップ 追記

Days of Speed

過ぎゆく日々を書こう。忘れっぽい未来の自分のために

クリエイティブ・コモンズ・ライセンス Jun NOGATA を著作者とするこの 作品クリエイティブ・コモンズの 表示 - 継承 4.0 国際 ライセンスで提供されています。


2014-10-25 [長年日記]

_ 一挙二本立て

ネタを書いてたけど、眠くて最後まで書ききれてなかったネタを2本公開。

Tags: life

2014-10-24 [長年日記]

_ Apache CordovaでAndroidアプリを作ってみる

Apache Cordovaを使うとHTML/CSS/JavaScriptでできたWebアプリをパッケージにして、モバイルデバイスのアプリにすることができます。

leaflet.jsで地図が出て、GeoJSONのデータ位置にピンを打つことができたので、これをCordovaでアプリにしてみました。

Android開発環境の準備

Apache Cordovaは、Ubuntu TouchやFirfoxOSにも対応しているので、それらでもいいのですが、せっかくなら実機で動かしたいので、ターゲットデバイスをAndroidに設定しました。

ということで、まずはApache Cordovaが利用するAndroid開発環境を整えます。

Android SDK関係のインストールは、Debian Sidではパッケージが揃っているので、それを使っても良かったのですが、Androidの開発自体不慣れなのでAndroid Studioをダウンロードして使いました。

ちなみにEclipseを使わなかったのは、Eclipseがコアを吐きまくって、まともに動かなかったからです。

Android Studioのインストールは、アーカイブをホームディレクトリの適当な場所に展開して、パスを通せばOKです。

 $ tar xvfa android-studio-bundle-135.1339820-linux.tgz

パスの場所は、Android StudioのbinとバンドルされているAndroid SDKのtools、platform-toolsがあるので気をつけて下さい。 そして、LD_LIBRARY_PATHは、Android SDKのqemuがlibOpenglRender.soを見つけられないので、これも一緒に追加しておきます。

 ~/.bashrc抜粋

 # android
 export PATH=$PATH:$HOME/android-studio/sdk/tools:$HOME/android-studio/sdk/platform-tools:$HOME/android-studio/bin
 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/android-studio/sdk/tools/lib

終わったら、Android StudioのアップデートとAndroid SDK Managerで必要なAPIのインストール。そして、Android Virtual Device Managerで検証用の仮想デバイスを作っておきます。 実機で検証してもいいのですが、cordovaのコマンド一発でビルドからエミュレーター上でアプリ起動までできるので、ちょっと確認するときには便利です。

 (Android Studio)                  $ studio.sh
 (Android SDK Manager)             $ android
 (Android Virtual Device Manager)  $ android avd

Apache Cordovaのインストール

Apache Cordovaは、node.jsで動くので、Debianパッケージのnode.jsとnode.jsのパッケージマネージャnpmをインストールします。

 $ sudo apt-get install nodejs nodejs-legacy npm

続いてnpmを使ってcordovaをインストールします。

 $ sudo npm install -g cordova

サンプルアプリをビルドしてみる

この辺からは公式ドキュメントそのままです。テストでサンプルアプリを作成します。

cordova createコマンドで、ひな型をを作ります。

 $ cordova create hello com.example.hello HelloWorld

最初の引数は、ひな型のディレクトリ名です。 2番目はドメイン名を逆から並べた識別子です。逆ドメインの形でない、おかしな識別子にしているとAndroidプラットフォームが追加できずハマるので気をつけて下さい。 3番目はアプリ名です。省略可能でconfig.xmlを編集して後から追加もできますが、最初に適切な名前をつけておいたほうがよいでしょう。

作成できたら、ひな型のディレクトリに下ります。

 $ cd hello

用意されたファイルを見てみます。

 $ ls
 config.xml  hooks/  platforms/  plugins/  www/

config.xmlには、cordova createで設定したアプリの設定が書いてあります。

それでは作成するアプリのプラットフォームを追加します。 追加できるプラットフォームは、cordova platformをなにもつけずに実行すると一覧が表示されます。

 $ cordova platform

 Installed platforms:
 Available platforms: amazon-fireos, android, blackberry10, browser, firefoxos, ubuntu

Androidを追加しました。

 $ cordova platform add android

wwwディレクトリにマスコットキャラクターを表示するだけのHTML/CSS/JavaScriptファイル一式が用意されています。 これらのファイルはブラウザで普通に見ることができるので試しに見てみます。

 $ iceweasel www/index.html

ビルドするとこれと同じものが表示されるはずです。cordova buildコマンドを実行してビルドしてみましょう。

 $ cordova build

しばらく時間がかかりますが、正常に終了すると hello/platforms/android/ant-build/CordovaApp-debug.apk というapkファイルが作成されます。

apkファイルをエミュレータ上で実行するには、cordova emulateを実行します。

 $ cordova emulate android

_ leaflet.jsの地図をAndroidアプリにしてみる

これで一通りの流れがわかったので、leaflet.jsを使った地図をアプリにしてみます。

まずはひな型を作って、プラットフォームを登録する。

 $ cordova create leaflet tv.nofuture.leaflet LeafletTest
 $ cordova platform add android

wwwディレクトリにleaflet.jsとプラグイン、jQuery、bootstrapを置く。 ざっくりコピーしたので無駄なものも多いけど、treeで表示するとこんな感じ。

 ├── css
 │   ├── bootstrap-theme.css
 │   ├── bootstrap-theme.css.map
 │   ├── bootstrap-theme.min.css
 │   ├── bootstrap.css
 │   ├── bootstrap.css.map
 │   ├── bootstrap.min.css
 │   ├── index.css
 │   └── leaflet.css
 ├── data (leaflet.jsに読み込ませたいGeoJSONファイル)
 │   └── map.geojson
 ├── fonts (bootstrapのフォントファイル)
 │   ├── glyphicons-halflings-regular.eot
 │   ├── glyphicons-halflings-regular.svg
 │   ├── glyphicons-halflings-regular.ttf
 │   └── glyphicons-halflings-regular.woff
 ├── img
 │   └── logo.png
 ├── index.html (ここに書く)
 └── js
     ├── bootstrap.js
     ├── bootstrap.min.js
     ├── images
     │   ├── layers-2x.png
     │   ├── layers.png
     │   ├── marker-icon-2x.png
     │   ├── marker-icon.png
     │   └── marker-shadow.png
     ├── index.js
     ├── jquery-2.1.1.min.js
     ├── leaflet-src.js
     ├── leaflet.ajax.js
     ├── leaflet.ajax.min.js
     └── leaflet.js

index.htmlを編集して、leaflet.jsで地図を表示したコードをコピペする。

head要素にscript要素でライブラリを読み込む。

   <script src="js/jquery-2.1.1.min.js"></script>
   <script src="js/bootstrap.min.js"></script>
   <script src="js/leaflet.js"></script>
   <script src="js/leaflet.ajax.js"></script>

続いてライブラリのスタイルシートなど。

   <link rel="stylesheet" type="text/css" href="css/index.css" />
   <link rel="stylesheet" type="text/css" href="css/bootstrap.min.css" />
   <link rel="stylesheet" type="text/css" href="css/bootstrap-theme.min.css" />
   <link rel="stylesheet" type="text/css" href="css/leaflet.css" />
   <style>
       body{
           margin: 0;
           padding: 0;
       }
       div#map{
           width: 100%;
           height: 500px;
       }
   </style>

body要素に移って、内容をごっそり削って地図用のdiv要素とスクリプトを移す。

   <div id="map"></div>

   <script>
       var map = L.map('map').setView([34.839378, 134.694097],15);
       var tileLayer = L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',{
               attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors',
               maxZoom: 19
           });
       tileLayer.addTo(map);

       var marker = L.marker([34.839378, 134.694097],{
           title: 'test',
           draggable: true
       }).addTo(map);

       marker.bindPopup("<b>Hello world!</b><br>I am a popup.");

       $.getJSON("data/map.geojson",function(data){
           L.geoJson(data).addTo(map);
       });

   </script>

この2行は、cordovaのライブラリで必要なので消さないこと。

   <script type="text/javascript" src="cordova.js"></script>
   <script type="text/javascript" src="js/index.js"></script>

コピーし終わったらビルドしてエミュレーターで実行してみる。

 $ cordova build
 $ cordova emulate android

Androidエミュレーターで実行できた

きゃー!動いたー!

apkを実機で実行してみると…。

動いたー!

leaflet.jsで地図アプリを作る野望の大枠が見えたので、これで生きる希望が出た。


cordovaで動かしたindex.html

 <!DOCTYPE html>
 <html>
     <head>
         <meta charset="utf-8" />
         <meta name="format-detection" content="telephone=no" />
         <meta name="msapplication-tap-highlight" content="no" />
         <!-- WARNING: for iOS 7, remove the width=device-width and height=device-height attributes. See https://issues.apache.org/jira/browse/CB-4323 -->
         <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height, target-densitydpi=device-dpi" />
         <script src="js/jquery-2.1.1.min.js"></script>
         <script src="js/bootstrap.min.js"></script>
         <script src="js/leaflet.js"></script>
         <script src="js/leaflet.ajax.js"></script>

         <link rel="stylesheet" type="text/css" href="css/index.css" />
         <link rel="stylesheet" type="text/css" href="css/bootstrap.min.css" />
         <link rel="stylesheet" type="text/css" href="css/bootstrap-theme.min.css" />
         <link rel="stylesheet" type="text/css" href="css/leaflet.css" />
         <style>
             body{
                 margin: 0;
                 padding: 0;
             }
             div#map{
                 width: 100%;
                 height: 500px;
             }
         </style>

         <title>leaflet.js Test</title>
     </head>
     <body>
         <div id="map"></div>

         <script>
             var map = L.map('map').setView([34.839378, 134.694097],15);
             var tileLayer = L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',{
                     attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors',
                     maxZoom: 19
                 });
             tileLayer.addTo(map);

             var marker = L.marker([34.839378, 134.694097],{
                 title: 'test',
                 draggable: true
             }).addTo(map);

             marker.bindPopup("<b>Hello world!</b><br>I am a popup.");

             $.getJSON("data/map.geojson",function(data){
                 L.geoJson(data).addTo(map);
             });

         </script>
         <script type="text/javascript" src="cordova.js"></script>
         <script type="text/javascript" src="js/index.js"></script>
     </body>
 </html>

2014-10-23 [長年日記]

_ 引きこもりバンザイ

いや、家にこもってゴソゴソしてるざんすよ。

Tags: life

_ 総務省にある合同会社設立登記申請書テンプレをLibreOfficeで完コピしてみた

以前にも書いたと思いますが、法務省のページに会社の登記申請に必要な書類のテンプレートが置いてあります。

相変わらずdocファイルの中身はrtfですが、それはさておき、中身を見ると書式の直接指定と文字がベタ打ちのスペースを使ったインデントの嵐で、編集しようとすると体裁がガタガタ崩れるシロモノです。 (おそらく印刷したものに書き込むイメージで作成したのだろうなと想像。)

こういう力技で作ったオフィス文書を、スタイルなどの機能を使い文書を構造化してモダンなオフィス文書に書き直すとどうなるのだろう?と思ったので、LibreOffice Writerの練習がてら作りなおしてみました。

ハイブリッドPDFになっているので、LibreOfficeで読み込むと編集できます。IPAフォントを埋め込んでいるのでファイルサイズは大きくなっていますが、OSを問わず、ほぼ同じ見え方になると思います。

書式はスタイルに移植しましたが、元のレイアウトがスペースの挿入で調整されていることもあり正しい位置がわからないので、おおよその位置をインデントで調整しています。 そして、この文書はいくつかの書類の集合ですが、文書としてはセクションで分けるのがよいような気がしたのでセクションで区切っています。

具体的な違いは、編集記号をオンにしてスタイルとナビゲーターを使ってみると、どう変わったのかわかって面白いかもしれません。 こういうのは自己満足ですが、たまに練習がてら頭の体操として作ってみるのも面白いと思います。

_ 箇条書きの行頭文字が2文字の箇条書きをLibreOfficeではどう表現する?

上の文書を再現しようとした時、「合同会社設立登記申請書」の「商号」「本店」など部分は「1.」と書いてあるので番号付け(リスト)のように見えますが、数字はインクリメントしないので単なる箇条書きです。

最初は「箇条書きの文字を変更すれば楽勝」と思ったけれど箇条書き/番号付けのダイアログを開いて気がついた。

これはどうやって表現したらいいのだろう。

LibreOfficeの箇条書きと番号付きリストの仕様は、こんな風になってます。

  • 箇条書き: 行頭の文字は変えられるが1文字だけ。前後に区切り文字はつけられない。
  • 番号付け: インクリメントできる数字/文字。カッコなどがある場合は前後に区切り文字を設定する。

箇条書きで設定しようとするとピリオドが指定できないし、番号付けだと数字がインクリメントされてしまうし、どうしようかと思ってask.libreoffice.orgで尋ねたところ、こんな答えが帰ってきました。

  1. 画像化した文字を使って箇条書きを書く
  2. 番号付きリストの前後区切り文字だけを使う

どちらも思いつかなったので、なるほど!と思いましたよ。

まあ、バッドノウハウといえばバッドノウハウで、正しくはバグ報告出して仕様を改めてもらうのがスジなのだけど、こういうやり方もあるのかと関心しましたよ。


2014-10-21 [長年日記]

_ なんとか雨が降らなかった

網干の祭りだそうで、スーパーに行ったら祭り体制になってた。

Tags: life

_ leaflet.jsの地図にGeoJSONの情報を表示させるいくつかの方法(解決編)

まだ、leaflet.jsでバタバタしてます。

前回、日記に「leaflet.jsの地図にGeoJSONの情報を表示させる」というエントリを書きました。ですが、ファイルに手を加えて表示させるのは不格好だなと思ってました。 そういうこともあって、GeoJSONそのままの形で読み込む方法を探してバタバタした結果、納得できるようになったのでメモしておきます。

参考

leaflet AJAXプラグインを使って読み込む

悩んだ悩んだ。

最初に試したのがこの方法で、悩んで姫路IT系勉強会でも質問のネタにしたのだけど、何回試してもうまくいかない。

デバッガで見るとファイルを読み込んだところでコケるので、GeoJSONのファイルを作りなおしたりしたけれど結果は変わらず投げようかと思っていたところで、ふと、気がついた。 ローカルのHTMLファイルをブラウザで読み込ませるのではなく、httpを通して読み込ませるとどうなる?

これを参考に、

$ python3 -m http.server 8080

という感じでPython3でWebサーバーを実行してアクセスすると、ちゃんと読み込んで表示する!!!

はあ。疲れた。


ということで、ローカルからではなくWebサーバー越しでアクセスして使う方法。

Leaflet Ajaxプラグインは、CDNで配布していないのでローカルにダウンロードしておきます。

Leaflet.jsを読み込んだ下あたりにLeaflet Ajaxプラグインを読み込むように書いておきます。

<script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
<script src="leaflet.ajax.min.js"></script>

GeoJSON読み込み部分は、サンプルほぼコピペでいけます。

var geojsonLayer = new L.GeoJSON.AJAX("map.geojson");
geojsonLayer.addTo(map);

これで、http越しにアクセスするとGeoJSONの場所にピンが打たれるはずです。

Leaflet Ajaxプラグインの成果

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>leaflet.jsの練習</title>
    <script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
    <script src="leaflet.ajax.min.js"></script>
    <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css">
    <style>
        body{
            margin: 0;
            padding: 0;
        }
        div#map{
            width: 100%;
            height: 500px;
        }
    </style>
</head>

<body>
    <div id="map"></div>
    <script>
        var map = L.map('map').setView([34.839378, 134.694097],15);
        var tileLayer = L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',{
                attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors',
                maxZoom: 19
            });
        tileLayer.addTo(map);

        var marker = L.marker([34.839378, 134.694097],{
            title: 'test',
            draggable: true
        }).addTo(map);

        marker.bindPopup("<b>Hello world!</b><br>I am a popup.");

        var geojsonLayer = new L.GeoJSON.AJAX("map.geojson");
        geojsonLayer.addTo(map);

    </script>
</body>
</html>

jQueryを使って読み込む

姫路IT系勉強会で相談した時、「JSONの読み込みは、jQuery使うと楽」とのワテさんからのアドバイスがあったので、こっちでももがいた結果がこちら。 jQueryを使うと、汎用性とHTMLファイルをブラウザで読み込んでも、ちゃんとGeoJSONが読み込めるところがメリットですね。

まず、jQueryを読み込むように書いておきます。新しいブラウザだけでいいので2.x系使ってます。

<script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>

GeoJSONを読み込んで地図表示は、こんな感じ。

$.getJSON("map.geojson",function(data){
   L.geoJson(data).addTo(map);
});

たったこれだけなんだけど、これも結構時間かかった…。

jQueryを使った成果

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>leaflet.jsの練習</title>
    <script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
    <script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
    <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css">
    <style>
        body{
            margin: 0;
            padding: 0;
        }
        div#map{
            width: 100%;
            height: 500px;
        }
    </style>
</head>

<body>
    <div id="map"></div>
    <script>
        var map = L.map('map').setView([34.839378, 134.694097],15);
        var tileLayer = L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',{
                attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors',
                maxZoom: 19
            });
        tileLayer.addTo(map);

        var marker = L.marker([34.839378, 134.694097],{
            title: 'test',
            draggable: true
        }).addTo(map);

        marker.bindPopup("<b>Hello world!</b><br>I am a popup.");

        $.getJSON("map.geojson",function(data){
            L.geoJson(data).addTo(map);
        });

    </script>
</body>
</html>

2014-10-19 [長年日記]

_ いい天気なのに出られない

出ようと思ったところで仮想マシンのWindows Updateが始まって、出鼻をくじかれたので出る気なくなった。

Tags: life

_ 必要なものは「人と違うオレ(ワタシ)すげー」という中二病的な気持ち

昨日は姫路IT系勉強会がありました。 そこで「Ubuntuをインストールしたけど、そこからどうしたらいい?」という話しが出ました。

今でこそLinuxは便利だから使っているけれど、自分がLinuxを使い始めた時を振り返ると、使い始めた一番の理由は「Windowsと違うから」→「人と違うOS使ってるオレ、カッコイイ!」という部分が一番大きかったような気がします。

Linuxに限らず、新しいことを始めるときの強い動機は、良い意味での勘違いと思い込みだと思いますよ。

Tags: linux think

_ isenkramを使うと必要なファームウェアを自動認識してインストールできるのか

試してみたいけど、そういう環境ないし、自動的にnon-freeのリポジトリを追加してインストールしてくれたら嬉しいのだけど。

Tags: debian

2014-10-16 [長年日記]

_ 大丈夫かな?

2日寝てましたが、そろそろ大丈夫ぽい?

Tags: life

_ Atomのクソ安いマシンがいっぱい出てきたのでDebian入れて遊んでみたい

49ドルのセットトップボックスとか。65ドルのWindowsタブレットとか。

値段は出ていないけど、HDMI端子にぶっ差すスティック型端末とか。

どれもハードウェア構成はBaytrailでほぼ同じだけど、似たようなハードウェアのZOTACのZBox picoを動かした記事によるとUbuntuが使えたそう。

問題としては32bit UEFIが必要でUbuntuだとそこが難しいようだけど、Wheezyだけど32bit UEFI対応インストーラあるしサクッと入れ替えられるのではと予想。 てことで、誰かください。

Tags: gadget pc

_ 書籍「3日でマスター JavaScript」読了/JavaScript挫折組におすすめ

3日でマスター JavaScript
伊藤 静香
ソシム
¥ 1,944

読了。手を動かしながら一日2時間×3日の想定なので、読むだけなら1時間ほどで読めました。ということで感想。

leaflet.jsで作った地図をApache Cordovaでアプリにしたいと思ってJavaScriptを書こう!と決意したわけですが、自分にピッタリくる参考書がなかなかありませんでした。

書店にあるJavaScriptの書籍というのは、だいたい2つのタイプに分かれていて、一つはWebデザイナーなどのノンプログラマーに向けに書いたもの。もう一つはJavaScriptをバリバリ書いているフロントエンドエンジニア向けに書かれたものに分かれてます。

レガシーながらもプログラムを書いたことがある人にとっては、ノンプログラマー向けの説明は退屈で必要ないし、エンジニア向けの内容は、その過程に至るまでの解説が足りない。

ということでモヤモヤしながらも「JavaScriptは、もういいや」となってたのですが、この本は初心者向けの本でありながら、短期間で全体像を把握させる作りのためJavaScriptらしい部分の説明は押さえつつも、外れるところは断りを入れてあえて説明しないという割り切りは読んでいて気持ちが良かったです。

自分みたいに、次に行くために手っ取り早く全体像を知りたい人にはオススメですね。

_ Microsoftマウスのホイールがバカになった

Microsoftの「Comfort Mouse 3000」というマウスを使ってるけど、ホイールがバカになったのかクルクル回しても3回に1回ぐらい空回りするのが気持ち悪い。

このマウスは、以前のマウスが壊れて近所のJoshinで適当に買ったものだけど、当初からマウスボタンが硬すぎて指が痛かったり、使いづらくていい思い出はないけど、これはもう捨てだよな。

マイクロソフトのマウスも、昔のインテリマウスとかは良かったのにな。

Tags: hardware

2014-10-15 [長年日記]

_ 腰をイワしております

台風の日の帰りの電車を待っていました。電車が入ってきたので、教科書とノートPCが入ってそこそこの重さのリュックを背負って立ち上がろうとしたときピキッと走った。

「マズいなぁ」と思ってたら、翌朝、見事に動かなかったのでギックリ腰決定。

肩が痛いとか腰が痛いとか、もうすっかり中年だな。 寒くなって腰が痛む秋にぴったりのKinksのAutumn Almanacでも貼っておこう。

Tags: life

_ Skype Qikのビデオに使われているFletcher C. JohnsonのMessin Up My Mindという曲が良い

Skypeのビデオメッセージサービスが始まったそうだけど、これの紹介ビデオに使われている曲がすごく良い。

調べたら、Fletcher C. JohnsonというバンドのMessin' Up My Mindという曲だそう。 bandcampで曲が聞けて買えるので、ちょっと聞いてみよう。

Tags: music

2001|12|
2002|01|02|03|04|05|06|07|08|09|10|11|12|
2003|01|02|03|04|05|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|06|08|12|
2011|01|02|03|06|07|08|09|10|11|12|
2012|01|02|03|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|12|
2014|02|03|04|05|06|07|08|09|10|