「アイディア」に関する日記(7)

<前 次>

無題

アンパンマンDBでリンク先をすばやく表示するためにリンク先のデータをキャッシュしておくというアイディアを以前に言っていたのですが、必要ないかもしれません。
もちろん今は普通に表示が遅い状態なので改善が必要なのは確かなのですが、そもそもの問題はリンクの数だけデータベースにアクセスしていたことにあるのです。
つまりキャラが200人いればアクセスは200回、遅くなるのも当然です。
そこで、データベースへのアクセスを減らすためリンク先の取得結果をキャッシュとして保存しておこうと考えたわけです。
しかしそうなるといつキャッシュを保存していつ更新するかが問題となります。
データベースの更新によってリンク先は変わる可能性があるのですから。
なので、リンク先は毎回調べることにするけれど、これをデータベースへの1回のアクセスでまとめて取得すれば体感的にはほとんど時間がかからないのです。
現実的には1回では済まないと思いますが、キャラの多いページではおそらく劇的に高速化可能だと思われます。

無題

アンパンマンDBのリンク先のキャッシュデータを作るということを考えてみました。
もともとアンパンマンDBの一部のページは表示が非常に遅いという問題があります。
原因はキャラクター名などのリンクを作るためにデータベースに対し非常に多くのアクセスを行うためです。
しかし、キャラクター名などに対するリンク先はあまり頻繁に変化することはないわけです。
そのため、リンク先をキャッシュデータとして保存しておけば一つ一つデータベースを参照しなくてもリンク先を知ることができる可能性があります。

隅隠し

時々マウスポインタが暴れて、右上に吹っ飛んでいったりします。
すると、右上には最大化したウィンドウの「閉じる」ボタンがあるわけです。
「上書き保存」ボタンを押そうとした瞬間に飛んでいくとえらい目に遭うわけです。
たいていのソフトは気を利かせて終了確認を出してくれますが、全てのソフトが気を利かせてくれるわけではありません。
なので、予期せぬ終了動作をなるべく防ぎたいわけです。
そのためには、単純には画面端をクリックできなくすればいいわけです。
しかし単にクリックできなくすると今度はクリックで閉じられなくなって不便なわけです。
なので、一度クリックすると一時的にクリック禁止を解除するようにすれば、意識的に閉じる場合にはダブルクリックすればよくなります。
こういう発想のソフトはたぶん探せばあるのでしょうが、作ったほうが早そうです。

無題

ナマライザ、読み込みながらURLデコードというのはしんどいので、とりあえず表示だけURLデコードに対応させてみました。
あと、docomoの検索ワードを拾えるようにしたいので、そちらに対応したら公開しようと思います。
検索ワードについては、いずれ検索ワードの解析方法をユーザー定義できるようにしたいと思っています。

無題

NeoMuplDLL初期化の方針。DirectShowとDirectMusicを使うと仮定して。MCIはまた対応はずすかも。

  1. バックグラウンドでDirectSoundを初期化。これは両方に必要。
  2. DirectShowとDirectMusicのどちらを先に初期化するか決める。デフォルトはDirectShowで、再生キューにDirectMusic使用曲が先に入っていたら順番を入れ替える。
  3. DirectShowを初期化。
  4. DirectMusicを初期化。

…としたいんだけど、メインスレッドと別のスレッドで初期化だけしてもいいのかな。
場合によってはアプリケーション本体用スレッドと再生専用スレッドに完全に分離するかも。

メテオスもどき

そんなわけで、アニメーションやリソース管理システムをいじりました。
これでマップを表示するときにアニメーションをコピーしまくってもメモリエラーを起こさないのです。
マップ表示自体は一から作り直すことになったのですが、流用を考えて中身をチェックしていたおかげで問題点がいち早く見つけられたように思います。
そんなわけで、明日からはマップ表示を一から作り直します。

こっそりメテオスもどきを作ってやろうかと画策中です。
遠からず終わってしまうメテオスオンラインに最後の光を与えることができるか、それともQに喧嘩を売ることになるのか、はたまた燃えカス1個ほども影響がないのか、わかりませんが、何か思い出に作っておきたいんです。

IIB

うむ、とりあえずインデックスカラー・インデックスカラー・ブレンド比率が並ぶデータだから、拡張子はiibにしようと思います。
ヘッダに必要そうな情報は、まず識別情報に、インデックスカラーに使うビット数、ブレンド比率に使うビット数、画像のサイズに、圧縮方式やパレット内の色の表現方法の識別コードも必要かな。
そして拡張ヘッダ。
ヘッダの次に来るのがパレットデータで、生の色の情報。
あとは決められたビット数で、インデックスカラー・インデックスカラー・ブレンド比率を最後まで続けて、必要ならば圧縮も。
うんうん。決まってきた。

ブレンディング

ふにゃさんのとげとげの拡張をするついでに、最後に一つ余ったキャラ枠をどう使うか考えてました。
順当なところで1アップか、あるいは取らなくてもいいけど取ったバナナの数にカウントされるボーナスアイテムか、それとも他のものにするべきか、そして決まったところで、アイテムの外観はどうするか、そのあたりが決まっていないのです。

それはそうと、画像フォーマットを一つ考えてみました。
インデックスカラーの長所で、パレットを差し替えれば画像全体の色が変えられたり、パレット番号何番は服の色、などと色に論理的な意味がつけられたり、そういうところを活かしつつ、なおかつたくさんの色を無理なく表現できてインデックスカラーの苦手そうなアンチエイリアシングもしやすい形式です。
まず、パレットは意味のある必要最低限の色だけを用意しておいて、画像本体には、どの色とどの色をどんな割合で混ぜ合わせるかのデータを入れるのです。
もしかしたら似たようなのが既にあるかもしれないのでまた調べてみます…。

本当の完成

ふにゃさんは今度の更新でかなりたくさんの部分を改良したり追加したりします。
それはもう、なんで今まで1年間以上も未完成を提供していたんだと思わせるほどに…したいのですが。
とりあえず、昨日の続きで、無重力状態での上下左右の接続はさすがにむちゃくちゃすぎるので廃止し、逆に場外負けを上方向にもつけるようにしました。
そして、キャラ絵をあんこ、サングラスをかけたふにゃの2バージョンを作ってオプションで変更できるようにしてみたりもしました。
あと、操作説明のところで、終了できなくなるバグを修正したつもりが、更に別の操作をするともっと悪い状態になってしまうことがわかったので、逆にどんな悪い状態になっても終われるように修正しておきました。
で、サングラスのことなんですが、サングラスをかけさせると黒背景のタイトルではサングラスが見えなくなるんですよね。
そこで、絶対に改悪にならないように、背景を黒以外にする方法を考えていると、デモプレイを背景に流すというのを思いつきました。
なんだか難しそうな気もしますが、しかし何とかできるような気もします。

1171033149.png

マップシステム作り直そうか

Bomber丸World、高さマップ廃止とかで、マップ構造にも変化が現れそうなので、いっそマップシステムをまた1から作り直すとして、やりたいことを考えてみます。

1.複数のマスにまたがるキャラを作れるようにする。
これ、当初主人公たちも2マス×2マスにしていて、つまり半歩ずつ歩けるようにしていたんですね。
ただ、実装の面倒さから再び1マスの大きさに戻したんです。
しかし、このゲームはかなり体格差のある人々が出てくるため、やっぱり主人公基準の1マスじゃ小さすぎるわけです。

2.高速な追跡アルゴリズムを実現する。
現在の次に探索すべき場所をすべて含む矩形内をくまなく調べる追跡アルゴリズムはマップの一辺を1として最悪でO(l3)の処理時間でしたが、次に探索すべき場所を記録しておいて調べるのは実際調べなければならない場所だけというアルゴリズムにすればO(l2)の処理時間に短縮することが可能なはずです。

3.エディタを利用することを前提としたファイル形式にする。
何しろアニメーションにせよキャラクターにせよテキストエディタで書いていること前提であらゆる省略記法を想定し、ファイル形式が複雑になってしまいました。
専用のエディタを作れば、データ量が増えてもあまり手間は増えないので、データ構造の単純化が実現でき、同時に作る人の頭も単純な考えで動かしてかまわなくなるのです。

ウィキウィキウェブ

突然ですが爆ボンバーマンWikiを始めました。
なんというか、メテオスWikiに触発されました。
とりあえずWikiにしときゃあ何かあるだろう的な考えの元、深く考えずに作ってみました。
Bomber丸Worldが完成したら、私の干渉しない、ユーザーの作る攻略ページをWikiで作れたらなぁと思い、その練習もかねて作ってみたわけです。

そんなBomber丸Worldのことですが、エンディング時の強さを保ったまま最初からゲームが始められるシステムというのはどうだろうと考えてみたりしました。
これがあれば裏ボスとかを滅茶苦茶強くしても10周目ぐらいに勝てるようにしておけば問題ないし、1回目は苦戦していたボスを楽勝で倒す快感も味わえるのです。

バリエーションデータの続き

で、バリエーションデータの、どのデータをどのタイミングで読み込むか、というのを考えてました。
Aという基本データと、Aと少し違うBのデータがあったとして、BにはAと同じ内容のデータは記載せずに、Aとの関連と差分のみを記録するという方式でデータを扱うのがバリエーションデータなのですが、記録するほうはそれでいいとして、Bを読み込むときにはどうすればいいのか、という問題があるわけです。
基本となるAを読み込むならただ読み込むだけでいいのですが、Bを読み込むとき、同時にAをも読み込む必要はあるのか、ということです。
同時にAを読み込んで初めから完全なBのデータを用意しておくのはプログラム的にも簡単なのですが、例えばBがAとほとんど違っていた場合や、Aから派生したBから更に派生したCからまた派生した……Zなんてデータが来た場合、Zには最早Aの面影は残っていなくて、YやXまでさかのぼれば充分な場合、そもそもデータを参照する回数が少ない場合など、つまり、さかのぼりがあまり頻繁には起こらない場合などには、いちいち全部用意していると読み込み負荷ばかりが余計にかかる可能性が高いわけです。
もちろん現実的にはさかのぼるのはせいぜい5回程度までのはずなので、そんなに神経質になる必要は無いのでしょうが、auto_resourceとの相性なども考えていきたいのです。
先程とは逆にBを読み込んだときにAを読み込まない方式としては、Bのデータを参照して、該当するデータが無かったときにそのつどAを読み込んで該当するデータを探す方法を考えています。
当然のことながら性質も逆で、さかのぼりが少なければ少ないほど、効率的になります。
とりあえず前者をA方式、後者をB方式と呼ぶことにすると、基本データよりも派生データが圧倒的に多いときのメモリ効率で考えた場合、A方式だと末端に行くにつれてデータが追加されるので、メモリ消費が多くなりがちですが、逆にB方式では本当に最小限のメモリ消費しかないはずです。
とにかく、データの性質によってかなり変わりそうではあります。

バリエーションデータ

Bomber丸Worldの最初に表示される画面、すなわちよく言われるところのタイトル画面について考えてみました。
最初の予定では、2002/10/05(Sat)の日記や、2003/11/19(Wed)の日記で書いていたように、普通にタイトル画像を用意しておいて、それをドカンと出す方式にしようかと思っていたのですが、どうにもこの方式だとまず画像が必要だし、タイトルからゲームに入るところのインターフェイスをどうするかに迷うし、なんとなくだけど「らしくない」気がしたりするので、よくある正攻法のタイトル画面とは違う方式にしてみようと思いました。
そこで考えたのが、ゲーム画面を最初から出しておくという方式。
具体的に言うと、タイトル画面用のマップを用意しておいてそこを自由に動き回れるようにしておいて、マップ内にある特定のオブジェクトを調べることで実際にゲームが開始されるようにします。
もちろんタイトル画面というからにはタイトルも表示しなきゃいけませんが、マップ上にタイトルを表示するのは別に難しくないと思うのでこの方法で検討してみようと思います。

そして、データをXMLとかで管理しようと考えていたのですが、目的から考えるとやっぱりXMLである必要はなさそうに思えてきました。
Bomber丸Worldに必要なデータは、多重に階層化されていて、それぞれの階層にはデータがあって、末端の階層にあるべきデータを参照して該当するデータがその階層に無ければ上位の階層に該当するデータが無いか見に行き、あればそのデータを使うという、すなわち、もっとわかりやすく例で言えば、例えば、「カイモチ民であるふにゃが困った顔をしているとき」の歩くスピードを調べたいとき、「困った顔」というのには困った顔のデータしか無くて、歩くスピードがわからないので「ふにゃ」の歩くスピードを見に行くんだけれどもふにゃの歩くスピードが標準的なカイモチ民と変わらないから特には設定されてなくて、最終的に「カイモチ民」まで見に行って、最終的には「カイモチ民であるふにゃが困った顔をしているとき」の歩くスピードは「カイモチ民」の歩くスピードとして得られるわけです。
これを使えば何がうれしいかというと、ほとんど同じだけど一部が少し違うようなデータを簡単に作れるんです。
オブジェクト指向とかがわかる人ならクラスの継承のようなもの、といえばわかるでしょうか。
詳しい実装方法は後で考えることにします。

IDの数値

TGscriptのIDをどうするか考えていました。
例えばIDをファイル名として記録していた場合、不正利用者がLinuxのコマンドをIDの代わりに送信してきた場合に非常にまずいことになるのです。
ですから通常CGIなどでは外部からの入力をそのままファイル名として開くようなことはしません。
しかし今回はたくさんあるかもしれないIDをファイル名として扱ったほうが非常に都合がいいと思われるのです。
そこで、IDを数字にすることで、コマンド実行をできなくすることにしました。
もちろん数字じゃなくてもコマンド実行をできなくすることは簡単ですが、ID生成のとき乱数をそのまま使えたり、IDに使われる文字の種類が少ないというだけでも充分に意味はあります。
さらに、ID偽装防止のためのキーも用意したりしました。
もっとも、ID偽装防止のキーを使うのはIDを使って悪さができる段階、つまり書き込みのタイミングのみですが。

auto_resource実装案

Bomber丸Worldのリソース管理システム(auto_resource)のメモリ管理を考えていました。
メモリ確保のほうはshared_resourceと同じで全く問題ないのですが、メモリ解放が問題なのです。
メモリ確保をしていくうちにメモリが足りなくなったら最近使われていないものからメモリを解放していくのですが、その実装方法がいくつかあって、どれを選ぶべきかというのが難しかったのです。

考えている方法は三つあって、一つ目はその時点で使われていなければ新しかろうと古かろうと片っ端から全て解放してしまうというものです。
解放の際には全てのリソースが入っているコンテナの中身を全て走査して参照カウントが0のものを全て解放します。
この方法は最も実装が簡単で消費メモリも少なくなりますが、一時的に使わなくなったりソースを後のために取っておくというauto_resourceの考え方に反してついさっきまで使っていてまたすぐ使うかもしれないものまでどんどん解放していってしまいます。
マップ切り替えなどで一度に大量のリソースを読み込んで解放する場面ではすごくまずいことになります。

二つ目の方法は、字面通り最後に使われた時間が一番古いものから順番に解放してゆく方法です。
これを現実的な処理時間で実現しようと思えば、リソース参照用のファイル名-リソースを関連付けたマップのほかに、今まで使った順番に並べられたリストが必要になり、必然的にリソース本体とは別の余計なメモリが必要になります。
更にリソース側にも、解放や順番の並び替えの高速化のためにリストやマップへのイテレータが必要になります。
リストの実装によっては更に難しいコーディングが必要になるかもしれません。
そして当然、使用するたびに使用時刻の更新やリストの並び替えが発生するのでパフォーマンスは低下します。
ファイル読み込みによるパフォーマンス低下を嫌ってauto_resouceを作ろうとしたのに全く逆効果の可能性すらあるのです。
解放の際にはリストの末尾から順番に見て行って規定のメモリ以内に収まるか全て走査し終えるまで参照カウントが0のものを解放していきます。

三つ目の方法は、上記二つの中間を取って、ある時間より古ければ数が多かろうと少なかろうと全部解放してしまうという方法です。
これであれば、一つ目の方法ほど無駄は出ませんし、順番を考える必要が無いので二つ目の方法のようにリストを保持しておく必要がありません。
解放の際には適当にしきい時刻を決め、全てのリソースが入っているコンテナの中身を全て走査して参照カウントが0かつ使用時刻がしきい時刻より古い場合には解放します。
これの問題点は、しきい時刻の決め方やリソースの使用状況によって著しく性能が変化するということです。

それぞれ長所と短所がありますが、まず一つ目の方法は通常時には問題外ですが終了時に全てのリソースを解放する必要があるときには効果を発揮します。
二つ目はリソース自体の消費メモリが大きかったり使用するときの実行時間が長いなど、欠点が問題にならないほどスケールの大きいものであれば相対的に長所のみが残って最善の手段となります。
三つ目は二つの中間的なものなので無難としかいえません。
そんなこんなで、三つとも実装してみる価値はありそうです。

GChatの管理画面の改良を行いました。
まず、辞書画面での検索機能です。
これにより辞書への重複登録ということは少なくなったはずです。
そして、なぜか今までずっと実装していなかった全ログ確認機能。
これでもう直接ログファイルを見る必要はなくなったのです。
そんなこんなでアルニックもレベル29になりました。

XMLパーサ試作型

Bomber丸Worldに使うデータの一般的な書式について考えています。
アニメーション定義ファイルにせよキャラクター定義ファイルにせよ、省略記法により手作業の手間を省くつもりが却って全体の見通しが悪くなって様々な問題を引き起こしてるんですね。
融通の利かない仕様でデータ一つ一つに対して新たなプログラムを作り直す必要があるし、手作業を前提としたファイル構造のためプログラムでの生成が難しくなったりもしました。
そこで、融通が利き、拡張性が高く、なおかつゲーム向き、そういうのがほしくなったわけです。
で、とりあえず一つのアルゴリズムでいろんなデータを読み込めて、わりと自由に要素を作れるXMLというものに着目してみました。
特定用途に使うものであり、なおかつ専用ソフトを使って編集する可能性が高いということで、読み書きに都合の良いように独自のアレンジを加えるというのもありかもしれません。
タグの管理は、同じタグがいくつもあるということもありうるのでmultimapで管理するとよいでしょうか。
もっとも、XMLのような考え方を使うとすると、正確にXMLである必要が無いどころか、実際が全くXMLからかけ離れた内容でも大きな問題はなく、初めから専用エディタでのみ作るという前提にすれば、バイナリ形式で構造的にXMLのような、というのもありかもしれません。

機能停止とファイル解析と確認画面

今日メモちらしが原因不明の動作停止をしました。
元々暴走が怖かったため動いてるか動いてないかわからないぐらいの低速で動かしていたのでずいぶん長いこと気付きませんでした。
とりあえずソフトを再起動したら直ったのですが、止まる条件はプログラムの終了以外になかったはずだったので少し気持ち悪いです。

のんびりナマライザのログ読み込み部分の中枢が出来上がりました。
先月27日に言っていたところのファイル解析です。
まず、速度は多少遅くなるのですが、エラー処理を正しく行い、可読性の高いコードになるように、そしてもちろん正しいデータに対しては最低限正しく動くようにしました。
読み込みの都合や実際に解析するときの必要性などから一部のデータを使わないことにしたり場所を色々移動したりもしました。

掲示板の迷惑書き込み対策、もっと単純でなおかつ当たり前の方法がありました。
投稿内容反映の前に、投稿内容確認画面を入れて1ステップ多くするのです。
これにより一般のお客様には利便性が上がり、迷惑書き込みをする人には面倒になるのです。
一般のお客様から見れば、投稿結果のイメージが投稿前に確認できるし、やろうと思えばその場で修正もできるし、不適切な表現があれば警告が出るし(出せるようにしたい)、チャットのようにガンガン書き込みまくるということもないので便利さだけが大きく上がるのです。
そして迷惑書き込みをする人にとっては、一手間多くかかる(つまり2倍面倒になる)、機械での投稿がしにくくなる、ということで書き込みにくくなるのです。

投稿フォームのこと

掲示板にの一般の利用者に迷惑のかかりにくい迷惑書き込み対策については、一つの案として、レベル別の書き込みフォーム&投稿内容制限の変化を考えています。
まず書き込みフォーム。
元々用途に応じて様々な形態の書き込みフォームを使うことを考えているので、普通の投稿にも様々な投稿フォームがあってもあまり問題にならないのです。
非常に大まかに分けると、簡易コメントフォームと通常書き込みフォーム。
簡易コメントフォームはテキストだけのシンプルな画面構成で誰でも書き込むことができますが、載せられる情報は少なく、ちょっとしたことで投稿内容審査に引っかかり、封印されます。
通常書き込みフォームは、クッキーと画像を使って、利用者別の投稿画面が自動的に割り当てられます。
画像には適切な代替テキストを用意せず、目で見ないと何が書いてあるかわからないようにし、入力フォーム自体の形や配置も毎回変化します。
これでロボットによる書き込みフォームの判別は難しくなります。
しかし、各入力欄のname属性がわかりやすい名前であると意味がないので、一見意味のない文字の羅列をname属性に使い、投稿された時点でCGI側で、じゃなくてPHP側で元の名前に読み替えます。
そして、元の名前と意味不明な名前の対応も、一定時間で変化します。
すると変化する時間をまたいでの投稿がまずいことになりますが、そのあたりの時間差は考慮して、正しい対応を取れるようにします。

属性

メモちらしのページに暴走について記述しましたよ。
ちょっと数値設定に対してデリケートすぎるんですね。
こちらのほうでは時間を掛けてやっと傷跡が戻ったところです。
とにかく極端なパラメータ変化は危ないようなのです。

Bomber丸Worldの属性攻撃について考えてます。
私は敵の属性がわからず力押しで戦ってしまうことがたびたびあり、自分のゲームでも同じようなことがみんなに起こったら嫌だなぁと思うのです。
属性を色分けしてみるとか、いっそのこと誰かが教えてくれるとか、ちゃんと考えてプレイできるような方法を考えているところです。

エラー対応と自動調整について

ナマライザの読み込み処理、これで完成かと思いきや全く正常に動かないプログラムであることが判明!
いえ、まだ実行したわけじゃないですが、簡単なデータを想定してコードを順番にたどっていったら、まだ読み込まれていないデータを処理しようとして、データがないとして、データが丸々残ってるのに次のステップに行って、その次のステップでは次に来るデータが特定の形式であることしか想定していないので、誤った場所のデータでは当然形式が会わなくて、どんどん違うデータを生み出し続ける、ということになってしまっています。
特定のフォーマットのみに対応して高速化を図ろうという考えでしたが、ちょっといくらなんでもデータの狂いに対して弱すぎるようでした。
今の状態だと全く正しく読み込めないばかりか、その正しく読み込めないところを修正したとしても、データそのものに少しエラーがあった場合でも、どんどん誤りを蓄積してそれ以降の全てのデータに悪影響を及ぼすのです。
ログデータは行単位で記録されているので、データの破損があったとしてもそれにより信用できなくなるのは該当する行だけであり、改行コードの一つも出ればそれ以降のデータは正しい可能性が高いのです。
というわけで今後の課題は、データの正しい読み込みと、エラー時の復帰の2つになります。
末端の表示処理はまあ速度さえ気にしなけりゃそれなりに楽にできるでしょう。
データ読み込みのときにも同じことを思っていたような気がしてなりませんが。

メモちらしの改良を考えています。
どうしても粒子の数が増えてくると色々なところで腕が伸びきってしまって扱いにくくなるので、腕が必要以上に伸びないような対策を考えています。
これの根本的な原因は平方根計算をするのを嫌って反発力の算出に距離の二乗に反比例した値ではなく距離に反比例した値を使ってしまったことだったのですが、既にこの仕様で動き出してしまっている以上、この部分は現段階のメモちらしでは変更するわけには行きません。
そこで、対症療法的な考え方ですが、これ以上伸びてもらうと困るという、そういう数値を設定しておいて、腕の長さがその数値を超えている場合は腕の引っ張り強さを上げるのです。
ただ、腕が長すぎる間ひたすら上げっぱなしだと、本当は時間さえかければ規定の長さに戻るのに、その途中であっても規定の長さに達していないというだけで必要以上に腕を引っ張ってしまうので、それが暴走や、縮みすぎという結果を招く可能性が高いです。
それを防ぐには、自動で腕の引っ張り強さを下げることはしないので、とにかく腕の引っ張り強さの上げすぎに注意する必要があります。
腕が長すぎるということは、つまり、腕の引っ張り強さが弱すぎて、反発力に負けているということを意味するので、反発力≧引っ張り力である間だけ引っ張り強さを上げてゆきます。
反発力<引っ張り力となっている間は腕は縮み、腕が縮むと反発力が上がり、引っ張り力は弱まります。
引っ張り強さが足りない場合、腕の長さが規定に達する前に再び反発力≧引っ張り力になるため、改めて引っ張り強さを上げてやります。
これを規定の長さになるまで続けてやれば、おおよそ規定の長さよりも少し短いところで腕は縮み終わるはずです。
縮みすぎたところがあれば、まあ、それを編集するのは長すぎの場合よりは簡単なので、手動で調整してもらいましょう。

<前 次>