4 public function __construct($score_id) {
5 $this->score_id = $score_id;
6 $this->dump_lines = NULL;
10 public function get_filename($dir, $ext)
12 $dirname = sprintf("%s/%d", $dir, floor($this->score_id / 1000) * 1000);
13 return sprintf("%s/%d.%s.gz", $dirname, $this->score_id, $ext);
17 public function show($dir, $ext, $content_type)
19 $filename = $this->get_filename($dir, $ext);
21 if (!file_exists($filename)) {
22 http_response_code(404);
26 $contents = file_get_contents($filename);
27 $etag = md5($contents);
29 if ($etag === filter_input(INPUT_SERVER, 'HTTP_IF_NONE_MATCH')) {
30 http_response_code(304);
34 $content_encoding = self::get_content_encoding();
35 header("Etag: ".$etag);
36 header("Content-Type: ".$content_type);
38 if ($content_encoding !== NULL) {
39 header("Content-Encoding: ".$content_encoding);
42 echo gzdecode($contents);
47 public function save($dir, $ext, $contents)
49 if ($contents === FALSE) return;
51 umask(2); // Group書き込み権限許可
53 $filename = $this->get_filename($dir, $ext);
54 $dirname = dirname($filename);
56 if (!file_exists($dirname)) {
57 mkdir($dirname, 02775, TRUE);
60 $zp = gzopen($filename, "w9");
62 foreach ($contents as $line) {
71 public function exists($dir, $ext)
73 $dirname = sprintf("%s/%d", $dir, floor($this->score_id / 1000) * 1000);
74 $filename = sprintf("%s/%d.%s.gz", $dirname, $this->score_id, $ext);
76 return file_exists($filename);
82 * 読み込んだ配列はメンバ変数dump_linesに格納
84 * @return boolean 読み込みに成功した場合TRUE、失敗した場合FALSE
86 public function readlines()
88 if ($this->dump_lines !== NULL) {
92 $lines = gzfile($this->get_filename('dumps', 'txt'));
93 if ($lines !== FALSE) {
94 $this->dump_lines = $lines;
103 * キャラクタダンプの死ぬ直前のメッセージもしくは勝利メッセージを取得する
105 * @return array 死ぬ直前のメッセージもしくは勝利メッセージを1行1要素にした文字列の配列
107 public function get_last_message()
109 if ($this->readlines() === FALSE) {
115 foreach ($this->dump_lines as $line) {
116 if (preg_match('/^\s*\[(.*)\]\s*$/u', $line, $matches)) {
117 if ($matches[1] == '*勝利*メッセージ' ||
118 $matches[1] == '死ぬ直前のメッセージ') {
121 else if ($in_message) {
127 $result[] = rtrim($line, "\n");
138 * @return string 死因の詳細を表す文字列
140 public function get_death_reason_detail()
142 if ($this->readlines() === FALSE) {
146 $death_reason_lines = array_slice($this->dump_lines, 30, 3);
147 $death_reason = implode("", array_map('trim', $death_reason_lines));
149 if (preg_match("/^…あなたは、?(.+)。/u", $death_reason, $matches)) {
156 private static function browser_accept_encodings()
158 $accept_encoding = filter_input(INPUT_SERVER, 'HTTP_ACCEPT_ENCODING');
159 if ($accept_encoding == NULL) return [];
161 return array_map('trim', explode(",", $accept_encoding));
165 private static function get_content_encoding()
167 $supported_gzip_encodings = array_intersect(
168 self::browser_accept_encodings(),
171 return array_shift($supported_gzip_encodings);