bootstrap.min.css にはフォントの指定があるため、<head>内で最後に読み込んだりしていると自作cssで指定しているのにフォントが効かなくて2時間ぐらい首をひねることになる。
Webフォントを指定しているcssより先に読み込むと自分が指定したフォントが効くようになる。
超簡単だし当たり前のことだけど無駄な時間を使ってしまった…。読み込む順番には注意しよう。
bootstrap.min.css にはフォントの指定があるため、<head>内で最後に読み込んだりしていると自作cssで指定しているのにフォントが効かなくて2時間ぐらい首をひねることになる。
Webフォントを指定しているcssより先に読み込むと自分が指定したフォントが効くようになる。
超簡単だし当たり前のことだけど無駄な時間を使ってしまった…。読み込む順番には注意しよう。
ROのゲームサーバーの時刻がPCの時刻とずれているので、サーバーの時刻を取得して表示するページを作りました。
PHPでROの公式サーバー(ゲームサーバーではない)にHTTPリクエストを投げてレスポンスヘッダから時刻を取り出して表示しています。
Javascriptじゃないんかい! というツッコミはごもっともです。その理由と経緯は以下になります。
「サーバー 時刻 取得」などで検索すると、どうやらJSのajax通信では返ってきたレスポンスヘッダの中にサーバーが応答した時刻が入っており、それを取得すればOK! ということでした。
なーんだ結構簡単じゃん、jQueryでちょちょいとやればすぐできるなと思っていたのですが…
結果から言いますとJavascriptでは公式サーバーにアクセスすることができませんでした。
これは「同一オリジンポリシー(Same Origin Policy)」のせいでした。
コンテンツがブラウザに来る源泉(origin)に基づいて整理して、外部からの干渉を防ごうとする。
同一生成元ポリシー – Wikipedia
要するに他所様のサーバーにはJSで好き勝手させないよ! ってことですね。
HTTPリクエストを投げようとしてもエラーになってしまうので、どうにかこれを越える必要がありました。
解決方法は2つ。
まず1つ目はサーバー側でレスポンスヘッダにAccess-Control-Allow-Originを含める。
それができるんならこんな事しとらんわい!! 次!
2つ目はajax-cross-originというjQueryプラグインです。
これをjQueryとともに読み込むことでSOPを回避して別サーバーにアクセスできます。ただし返ってくるデータはJSON固定です。これで万事解決かのように見えたのですが…
ウキウキしながらgetAllResponseHeaders()で中身を見てみると空っぽでした。
検索してみたところ、こんなことが書いてありました。
DATE
クロスドメインなAjaxリクエスト時に取得できないレスポンスヘッダーについて | mediba Creator × Engineer Blog
Server
ETag
Connection
Accept-Ranges
Keep-Alive
Content-Length
クロスドメインの場合には、上記ヘッダーを取得できていないことがわかります。
これについては解決方法はないようなので、JSで別サーバーの時刻を取得するのは不可能だとわかりました。
JSがダメならPHPで、と検索していたらfile_get_contentsを使えばHTTPリクエストが投げられるので使いました。
1 2 3 4 5 |
$context = stream_context_create(array( 'http' => array('ignore_errors' => true) )); $response = file_get_contents('https://ragnarokonline.gungho.jp/', false, $context); $servertime = str_replace('Date: ', '', $http_response_header[4]); |
レスポンスヘッダは $http_response_header に配列として格納されるので、[4]でdateの部分を取り出しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
let changeDate = (dateobj) => { document.getElementById('year').textContent = dateobj.getFullYear(); document.getElementById('month').textContent = dateobj.getMonth()+1; document.getElementById('day').textContent = dateobj.getDate(); document.getElementById('hour').textContent = ('0'+dateobj.getHours()).slice(-2); document.getElementById('minute').textContent = ('0'+dateobj.getMinutes()).slice(-2); document.getElementById('second').textContent = ('0'+dateobj.getSeconds()).slice(-2); dateobj.setSeconds(dateobj.getSeconds()+1); } let datedata = "<?php echo $date->format('Y,m,d,H,i,s');?>"; datedata = datedata.split(','); let date = new Date(...datedata); changeDate(date); setInterval("changeDate(date)", 1000); |
取り出した $servertime をJSに渡して、1秒ずつカウントアップする関数 changeDate() を setInterval で1秒毎に実行しています。
ここでハマったポイントが1つ、
setInterval に関数を渡すときは ” ” で囲わなければならない
囲わないと最初の1回だけ実行されて終わりになってしまいます。
setInterval の説明をしているページでもわりと” “なしで書いてあるところがあってハマってしまいました。
というわけで無事完成。やったね。
ゲームサーバーとHTTPサーバーの時刻が一緒である、というか細い前提のもと作りましたがたぶんちょっとは役に立つと思います。
実際自分のPCの時刻と比べると8秒ぐらいズレがでてますからね。
え、お前の時刻がズレてるだけだって? まあそうかも…
さてはあなたwindowsですね?
1 2 3 |
folders: - map: C:\Users\username\Documents\app\homestead\code to: /home/vagrant/code |
のようにmapを絶対パスで書きましょう。
エンチャント逆引きを作ったときにdbを構築したのですが、頻繁にデータを追加しないといけないのが面倒でLOAD DATA INFILEを使おうと思いつきました。
しかしこのスペースを借りているusamimi.infoさんではdb接続を内部からのみ許可しているので、phpからアクセスする他なくスクリプトを書きました。
(もしphpなしでできる方法があったら教えてください)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
$dsn = 'mysql:dbname=database;host=localhost;charset=utf8'; try { $pdo = new PDO($dsn, user, password,[PDO::MYSQL_ATTR_LOCAL_INFILE => true,PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,PDO::ATTR_EMULATE_PREPARES=>false]); foreach ($path as $name => $filepath) { $query = []; $query[] = "LOAD DATA LOCAL INFILE './master/$filepath' INTO TABLE $name FIELDS"; if ($name === 'A') { $query[] = "TERMINATED BY ','"; } else { $query[] = "TERMINATED BY '\t'"; } if ($name === 'B') { $query[] = "ENCLOSED BY '\"'"; } $query[] = "LINES TERMINATED BY '\r\n'"; echo $name." ADDED : ".$pdo->exec(implode(' ',$query))."<br>"; } } catch (PDOException $e) { exit('FAILED'. $e->getMessage()); } |
あらかじめ’name’->’filename’の形の連想配列$pathを宣言してあります。
LOAD DATA LOCAL INFILEを使うときにはPDO::MYSQL_ATTR_LOCAL_INFILE => true
を設定しておかないとLOCALが使えません。
$queryにクエリ文を配列の形で追加していき、最後にimplodeで繋げてexecしています。
最初このやり方を見たときは頭いいなあって思いました(小並感)。
csvによって区切り文字や囲み文字が違うので分岐させているのですが、統一しておけばよかったです。めちゃくちゃ面倒くさい。
最初はmysqlで通るクエリをそのまま$queryに追加していたのですが、
FAILEDSQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘LINES TERMINATED BY ‘ ” at line 1
のようなエラーが発生し続けていました。
エスケープのあたりで引っかかっているのはわかったのですが、ちゃんとエスケープしてるにもかかわらずなぜエラーになるのかさっぱりわかりませんでした。
実はこれまで変数への文字列代入の際にずっとシングルクォーテーションを使っていて、今回も単純にクエリ文をシングルクォーテーションで囲んでやっていました。
実はこれが罠。
PHP 改行、タブ(エスケープシーケンス)の使い方 – Web Development Blog
エスケープシーケンスは、「’」(シングルクォーテーション)で囲まれていても展開されず、そのまま表示されてしまいますので必ず「”」(ダブルクォーテーション)で囲むようにしましょう。
ええそうです。これをすっかり忘れていたアホは私です。
というわけでクエリ文をダブルクォーテーションで囲み、スクリプトは無事動くようになりましたとさ。めでたしめでたし。
追記(2019/01/29)
ローカル環境(MySQL 8.0.13)だとLOAD DATA INFILEで追加できたcsvがサーバー(MySQL 5.5.13)では500 Internal Errorで追加できないことがありました。
ファイルサイズは500kb~700kbなのでサイズ超過というわけではないのですが、BigDumpを使うことで追加することができました。
BigDump: Staggered MySQL Dump Importer
bigdump.phpを開き、
$db_server = ‘サーバーアドレス’;
$db_name = ‘データベース名’;
$db_username = ‘ユーザー名’;
$db_password = ‘パスワード’;
を入力してサーバーへアップロード。
同じディレクトリに追加したいsqlファイルをアップロードしてbigdump.phpにアクセスします。
Start ImportでDBへ追加することができます。
今やっている逆引き検索の作成にあたって、いろいろなページを検索しまくっている(特にQiita)のですが、どこへ行っても「上達するならアウトプットすべき」ということが書いてあります。
確かにアウトプットは重要で、見る•聞くだけだと10回やっても覚えられないことが、人に1回教えるだけで頭に定着しているということはよくあります。友人にホラーおもちゃになんの盾を持っていくのか毎回答えているといつの間にかしっかり覚えていたりします。おそらく『自分で考えて何かをする』ことは脳みそへの経験値がすごく多いのでしょう。人のマネやコピペの経験値が1だとしたらアウトプットは10みたいな。
しかしアウトプットが重要だと頭で理解していても慣れてないとなかなか難しいものです。記事を書いている途中はどうにも頭がしっかり回っていないというか、ぼんやり書いている感じです。書き終えたあと見返すともっといい書き方があったり、本当に書きたいことじゃないことを書いてたり。
文章の書き方は良記事や本を読んで覚えていくしかなさそうです。そして一番大事であろうことは自分が何を言いたいのか、それをどう組み立てて文章にするのかということでしょう。自分のしたいことを組み立てるという点ではものを書くということとプログラミングは似ているように感じます。
アニバーサリーイベントのMD回しもいい加減飽きたのでRO丼を眺めているのですが、ほんとうにいろいろなTootが流れてくるのでこちらの方はなかなか飽きが来ません。
気になったTootからプロフィールへ飛び、そこからたいてい貼ってあるブログを見たりしています。
そこでいつも思うことが、みんなセンスいいなぁってことですね。
キャラクターのコーディネートが上手な人はブログのデザインも上手です。
自分はセンスからっきしなので、キャラクターにはいつも同じ衣装を着せていて、
webページを作るにしても最初に起こしたデザインと出来上がったものがかけ離れていることがよくあります。9割型なんていうか垢抜けないデザインって感じになります。無理にオシャレにしようとしてぐっちゃぐちゃになることもよくあります。
日課マネージャもほんとはもっとCoolになるはずだったんですが… まだまだ勉強不足です。
デザインについての本を何冊か買って読んだはずなんですがどうにも身についてないようで、もう一度読み返す必要がありそう。
ただこちらの勉強の方は仕事ではないので楽しんでやれる分モチベを高く保てています。今の所。
でもできることなら楽して欲しいので誰かセンスください。
ROに関係あるようなないような内容です。(ダジャレではないです)
自分は発売年が2008年のHA06という化石になりつつあるマザボを使っているのですが、vmwareで2PCを試そうとしたときにハマったので少し書いておくことにします。
検索しまくった結果、仮想化機能(というらしい、Intel VT-xとAMD-Vがプロセッサごとの名前になっている)をONにするためにはBIOSからチップセット設定に行き、それらしいところをONにすれば良いとのことでした。
しかしAdvanced Chipset Featuresを見に行くもそれらしき項目はありませんでした。
結局の所、件の項目はPower User Overclock Settingの中にありました。項目名は忘れましたがvirtualizeなんとかと書いてあったような気がします。
ONにすることで無事vmwareが動きました。しかし2PCとして使うには重すぎて露店ぐらいしかできませんでした。もっとPCが高性能であれば使えたかもしれません。自分は露店でしか使わないつもりだったので、それでも満足でした。
\ジャジャーン/
なんと前回から1週間で250M稼ぎ、ついに2個目のアルクイエンが買えました!
そのうちの1/3はアニバで出たジェミニcのおかげだったんですがね… 倉庫の肥やしにしてたんですがいつの間にかすごい値段になってました。ありがたや。
毎日飛行船襲撃、呪いの剣士、ギガミックス、ジターバグや最後の部屋を回したおかげでかなりの早さでお金が貯まりました。ペルロック装備やレク武器の精錬がうまくいったのも大きかったです。とはいえペルロックの方は+6が2個できた程度でしたが。レク武器の方は+8鞭や+7鈍器ができたおかげでだいぶお金になりました。
飛行船襲撃は暴走ペルロックを倒すだけで装備と王家貢献の証が20個も貰える(要ポーの戦闘訓練クエ受諾)ので、資産ゼロの人にも超おすすめの金策ですよね。ただある程度強くないと逆に返り討ちにあったりしますけど…。自分もレベルが低くライオットを持ってない時にはよく死んでました。
さて、これでようやくドカタメカのスタートラインに立てたわけですが、まずは聖地アビス3に行ってみたいと思います。楽しみです!
それにしても目標があるとモチベや効率が上がっていいですね。実生活にも活かしたいところです。
毎日22時頃に溜まり場に集まり、そこからMD巡り(通称MD部)をしているのですが、MD部のバ火力担当の人がメカを解体するというので、よその人に売るぐらいなら俺が買うわいということで倉庫に溜め込んでいた収集品をどっさり花売り娘に押し付け、アルクイエンのネックレスを250Mでまずひとつ譲ってもらいました。
メカを作ったときからほしいほしいと思っていましたが、所持金が100Mを超えることなどめったになかったのでなかなか感慨深いです。日課であるギガミックスはこれまでメモラバ+コア2と城下町の地図のパゥワースイングでギリギリやっていましたが、これでだいぶ時間に余裕ができそうです。ジターバグのペルたちもAxT2確くらいになるかな?
あともうひとつを同じく250Mで買い取る予定なので、このアルクイエンで金策を頑張りたいです。Wになればアビス3にも行けるでしょう、もしかしたら1つでも行けるかもしれないので計算機とにらめっこしたいところです。