index.php

https://個人の見解.jp

GitLab REST API で MR を作成直後に merge しようとするとエラーが返却される

前提

Pipeline 実行状態や Approval 状態、権限とか該当プロジェクトにおいて merge できる条件をクリアしているのに以下のいずれかのエラーが発生する

  • 422 Unprocessable Entity (Branch cannot be merged)
  • 405 Method Not Allowed (405 Method Not Allowed)

原因

MR 作成直後は GitLab の内部処理が完了していない場合がある(らしい)

結論

Create MR のレスポンスもしくは、Get single MR のレスポンスに含まれる detailed_merge_statusmergeable になるまでリトライする1

コード

最小限のコードなのでエラーハンドリングなどは別途行う必要があります。

<?php

try {
    // MRの作成
    $createMergeRequest = (new \GuzzleHttp\Client())
        ->post("{$_ENV['GITLAB_API_BASE_URL']}projects/{$_ENV['GITLAB_PROJECT_ID']}/merge_requests", [
            'headers' => [
                'PRIVATE-TOKEN' => $_ENV['GITLAB_BOT_TOKEN'],
                'Content-Type' => 'application/x-www-form-urlencoded'
            ],
            'form_params' => [
                'source_branch' => 'branch name',
                'target_branch' => 'main', // 任意のmerge先
                'title' => 'MRのタイトル',
                // MR作成時に行うその他任意のパラメータ定義
            ]
        ]);
    $content = json_decode($createMergeRequest->getBody()->getContents());

    // マージチェック通過後にマージする
    if (mergeable($content->iid)) {
        (new \GuzzleHttp\Client())
            ->put("{$_ENV['GITLAB_API_BASE_URL']}projects/{$_ENV['GITLAB_PROJECT_ID']}/merge_requests/{$content->iid}/merge", [
                'headers' => [
                    'PRIVATE-TOKEN' => $_ENV['GITLAB_BOT_TOKEN'],
                    'Content-Type' => 'application/x-www-form-urlencoded',
                ],
                'form_params' => [
                    'should_remove_source_branch' => true,
                    // mergeの際に行う任意のパラメータ
                ],
            ]);
    }
} catch (\Throwable $th) {
    echo "エラー: {$th->getMessage()}";
}

/**
 * detailed_merge_status が mergeable になるまでリトライする
 *
 * @param int $iid
 * @return bool
 */
function mergeable(int $iid): bool
{
    $start = time();
    $maxWaitTime = 30;
    while (time() - $start < $maxWaitTime) {
        $getMergeRequest = (new \GuzzleHttp\Client())
            ->get("{$_ENV['GITLAB_API_BASE_URL']}projects/{$_ENV['GITLAB_PROJECT_ID']}/merge_requests/{$iid}", [
                'headers' => [
                    'PRIVATE-TOKEN' => $_ENV['GITLAB_BOT_TOKEN'],
                    'Content-Type' => 'application/json',
                ],
            ]);

        $content = json_decode($getMergeRequest->getBody()->getContents());
        if ($content->detailed_merge_status === 'mergeable') {
            echo "mergeable になりました。\n";
            return true;
        }
        // 次のリクエストまで3秒待機
        echo "current status -> {$content->detailed_merge_status}\n";
        sleep(3);
    }

    throw new RuntimeException('タイムアウト');
}

最後に

お前... まさか feature ブランチでの作業直後にセルフマージしようとしてないよな?

参考

docs.gitlab.com


  1. GitLab の Version が 15.6 未満の場合は merge_statuscan_be_merged になるまで

【PHP】外部サイトで使用されている画像を一括でダウンロードする

はじめに

外部サイトで使用されてる画像を一括でダウンロードしたいときってあるよね?(ない)

どうせ使い捨てだしブラウザの Console で JS で書くのが一番楽だな〜と思ってたけど HAR file viewer 使ったり、ブラウザのダウンロード上限が 10 件だったりとか考えると結局 PHP でいいや、になった

対象外の画像

hover 状態など、特定の状況にならないと読み込まれない画像

方法

  1. Chrome DevTools で Network タブを表示する
  2. 画面を reload する
  3. Filter で Img のみを適用する
  4. .har ファイルをダウンロードする

github.com での Network タブ

<?php

// .har ファイルのパス
$har = '/path/to/example.har'

$extFromMimeType = function ($mimeType) {
    return match ($mimeType) {
        'image/jpeg' => 'jpg',
        'image/png' => 'png',
        'image/gif' => 'gif',
    };
};

$src = json_decode(file_get_contents($har), true);

foreach ($src['log']['entries'] as $entry) {
    $url = $entry['request']['url'];
    $img = file_get_contents($url);
    $info = pathinfo($url);
    $ext = $info['extension'] ?? null;
    // クエリパラメータの除去
    if (!is_null($ext)) {
        $ext = explode('?', $ext)[0];
    }
    // ファイル情報に拡張子がない場合は header から取得する
    if (is_null($ext)) {
        $headers = get_headers($url, 1);
        $ext = $extFromMimeType($headers['Content-Type']);
    }
    $fileName = "{$info['filename']}.{$ext}";
    file_put_contents("./path/to/downloads/{$fileName}", $img);
}

最後に

外部サイトの画像を全部ローカルに保存したいときなんかねーーーーーーーーーーーーーーーーーーーーよ!!!!!!!!!!!!

GitLab CI に tbls で作った ER 図を push してもらう

やりたいこと / この記事に書いてあること

  1. 人間がマイグレーションファイルを変更して Git に push(省略)
  2. GitLab CI が migration を実施して DB を更新(省略)
  3. GitLab CI が 最新のテーブル構成を元に tbls で ER 図を作成(書いてある)
  4. GitLab CI が 作業ブランチに push(書いてある)

やること

1. アクセストークンの作成

  • GitLab の Access tokens 画面でトークンを発行する
    • Role は Developer 以上
    • Scope は write_repository のみでいけるはず(多分)(覚えてない)

Access tokens 画面での登録

2. 変数定義

  • 作成したらコピったトークンを CI/CD Variables に登録
    • VisibilityMasked にする
    • 作業ブランチで使用したいため Protect variable のチェックを外す
  • 他にも使いたい変数があれば定義しておく

CI/CD Variables 画面での登録

CI_JOB_TOKEN くん、push 権限与えられてなくて草

3. tbls.yml を定義

接続情報を外部から取れるようにしておく

# tbls.yml

dsn: mariadb://${TBLS_DB_USER}:${TBLS_DB_PASSWORD}@${TBLS_DB_HOST}:3306/example

4. .gitlab-ci.yml を定義

# .gitlab-ci.yml

stages:
  - generate_er

generate_er_job:
  stage: generate_er
  script:
    - git config user.email "bot@example.com"
    - git config user.name "[bot] er diagram generator"
    - git clone https://oauth2:${CI_JOB_TOKEN}@gitlab.example.com/${CI_PROJECT_PATH}.git repo && cd repo
    - git checkout ${CI_COMMIT_BRANCH}

    # ER 図の出力とか
    - TBLS_DB_USER="${DB_USERNAME}" TBLS_DB_PASSWORD=${DB_PASSWORD} TBLS_DB_HOST="${DB_HOST}" tbls doc --rm-dist
    - rm ./path/to/dbdoc/* && mv ./dbdoc/* ./path/to/dbdoc/

    # 作業ブランチに push
    - git add ./path/to/dbdoc/*
    - git commit -m "[🤖bot] Auto-generated ER diagram from ${CI_COMMIT_BRANCH}"
    - git push origin ${CI_COMMIT_BRANCH}
  rules:
    - if: '$CI_PIPELINE_SOURCE == "push"'
      changes:
        - path/to/migrations/* # 変更を検知したいディレクトリ

CI_PROJECT_PATH, CI_COMMIT_BRANCH は定義済み変数

「こいつ…動くぞ!」になったら成功✌️✌️✌️

最後に

このままだとテーブル構成に変更がない場合(コメントの修正とか)にも commit しちゃうから ER 図の差分がないときには実行しないようにしたほうが実用的かも

関連記事

iliiliiiliili.hatenablog.jp

参考

gitlab-docs.creationline.com

gitlab-docs.creationline.com

docs.gitlab.co.jp

tbls on docker-compose でER図を作ってみた

tbls って何?

データベースのドキュメンテーションに使える go lang 製の OSS
既存の db schema から ER 図を出力したいときとかに便利。
ぎゃう「てか設計段階でER図がないことがおかしくね?」

github.com

初期設定

環境

docker-compose.yml

今回は services.db の内容からドキュメンテーションするため docker-compose.yml に定義

version: "3"

services:
  db:
    image: mariadb:10.5.22
    ports:
      - "3306:3306"
    volumes:
      - ./docker/mysql/init:/docker-entrypoint-initdb.d # 初期データのマウント
    container_name: example-db
    hostname: example-db
  tbls:
    image: ghcr.io/k1low/tbls
    volumes:
      - ./tbls.yml:/tbls.yml
    depends_on:
      - db
    container_name: example-tbls
    hostname: example-tbls

tbls.yml

services.tbls.volumes に定義している場所に tbls.yml (or .tbls.yml) を配置

# {dbツール名}://{ユーザー名}:{パスワード}@{ホスト名}:{ポート番号}/{データベース名} で設定する
dsn: mariadb://username:password@db:3306/example

出力

コンテナ起動

$ docker-compose up -d

ファイル出力

$ docker-compose run tbls doc --rm-dist

--rm-dist を指定することで既存の出力ファイルをすべて削除してから、再度出力してくれる

初期設定であれば dbdocs/* に出力される

全体

Viewpoints単位


次はこれをベースに Liam ERD でER図作るぞ!!!!(←本当にやりたかったこと)

参考

github.com qiita.com

CodeIgniter4 のクエリビルダでサブクエリを作る

<?php

namespace App\Models;

use CodeIgniter\Model;

class Table1 extends Model
{
    protected $table = 'table1';

    public function getExample()
    {
        $subQuery = $this->db->table('table2')
            ->select('table2.column')
            ->where('column', 1)
            ->getCompiledSelect();

        $this->db->table($this->table)
            ->join("{$subQuery} as table2", 'table1.column = table2.column', 'left', false)
            ->get()->getResult();
    }
}

getCompiledSelect()BaseBuilder に生えてるから $this->db->table() しないといけないっぽい。1
CodeIgniter4 では fromSubquery()selectSubquery() が追加されたみたいだけど JOIN で使いたいときは CodeIgniter3 と同じように組み立てないといけないみたい。
joinSubquery() 的なものも欲しいっす…


  • この記事では $ php spark make:model をしたときに作成される Model ファイル内で実装しています。
  • join() の第三引数で escape を無効にしています。外部からの値を許容する場合は十分に注意してください。

iliiliiiliili.hatenablog.jp


  1. 検証してない+記述量が増えるだけだけど $this->db->newQuery()->from('table') でも BaseBuilder を返却してるからいけると思う。多分。

ぴよログにつけた搾乳量の総量を算出する

やりたいこと

自分の体内から出ていった母乳の総量を知りたい

やったこと

1. ぴよログでデータの出力

メニュー > 記録の出力 > データのエクスポート にて新生児〜離乳食開始するまでの5ヶ月間のデータを出力する。

1ヶ月単位での出力だから最大5ファイルの出力が必要。
(期間で抽出できるようにしてほしい…)

2. 総量を算出する

↓のようなフォーマットのファイルをPHPで処理する

<?php

$files = glob('/path/to/files/*');
$sum = 0;
// 搾乳の行から値をキャプチャ
$pattern = "/[0-9]{2}\:[0-9]{2}[\ ]{3}搾乳\s([0-9]{1,})ml/";

foreach($files as $file) {
    $content = file_get_contents($file);
    preg_match_all($pattern, $content, $match);
    // 合計を追加していく
    $sum += array_sum($match[1]);
}

// 合計
echo "合計: ".$sum." ml\n";
// 1/21 ~ 6/10=141日間の平均量(入院期間はぴよログにつけてないので含まれない)
echo "一日平均: ".($sum / 141) ." ml\n";
// 2Lペットボトルに換算
echo "2Lペットボトル: ".($sum / 2000) . " 本分\n";

算出してて思ったけど 搾乳量 > 搾母乳量なのが悲しいね(´・ω・`)

結果

最後に

2Lペットボトル42本分も出してるのに未だに体重が戻らないの産後バグすぎて鬱(他責)

【GAS】フォルダを再帰的に見て24H以内に更新されたファイルがあればSlackに通知を送る【Googleドライブ】

きっかけ

サイレント修正が憎い

やりたいこと

folder1 > folder1-1 > folder1-1-1 ...のようにフォルダが存在する限り各階層のファイルを探索したい

.
├── folder1
│   ├── folder1-1
│   └── folder1-2
│       └── folder-1-2-1
├── folder2
│   └── folder2-1
└── folder3

コード

1. フォルダーを再帰的に探索して24H以内に更新されたファイル情報を返却する

function recursiveUpdatedFolder(folderId, values = []) {
  const tmp = values;
  const folder = DriveApp.getFolderById(folderId);
  // フォルダー内のファイルを取得
  const files = folder.getFiles();

  while (files.hasNext()) {
    const file = files.next();
    // ファイルの最終更新日時
    const dt = new Date(file.getLastUpdated());
    const diff = new Date() - dt;
    // 最終更新日が24H以内のフォルダをチェックする
    if ((diff / 1000 / 60 / 60) <= 24) {
      // Slack の通知で使いたい情報
      tmp.push({
        name: file.getName(),
        url: file.getUrl(),
        lastUpdated: dt,
        updatedAt: `${dt.getFullYear()}/${dt.getMonth() + 1}/${dt.getDate()} ${dt.getHours()}:${dt.getMinutes()}`,
        created: file.getDateCreated(),
        folder: folder.getName(),
      });
    }
  }

  const folders = folder.getFolders();
  // フォルダーがあれば再帰処理
  while (folders.hasNext()) {
    const next = folders.next();
    recursiveUpdatedFolder(next.getId(), tmp);
  }

  return tmp;
}

2. 更新情報をSlackに送る

// Slack の attachments 用にフォーマット
const title = "24H以内に以下のファイルに更新がありました。";
const color = "#33cccc"; // 任意のカラーコード
const fields = [];
files.forEach((file) => {
  fields.push({
    value: `<${file.url}|${file.name}(更新日時: ${file.updatedAt})>`,
    short: false,
  });
});
const messages = [{ title: title, fields: fields, color: color }];

const SLACK_TOKEN = "xoxb-xxxxx"; // Slack Bot のトークン
const CHANNEL = "#channel"; // チャンネル名
// Slack 通知を送る
UrlFetchApp.fetch("https://api.slack.com/api/chat.postMessage", {
  method: "post",
  payload: {
    token: SLACK_TOKEN,
    channel: CHANNEL,
    icon_emoji: ":emoji:", // Slack Bot に表示したいアイコン
    username: "username", // Slack Bot に表示したい名前
    attachments: JSON.stringify(messages),
  },
});

iliiliiiliili.hatenablog.jp

↓こんな感じでSlackに通知が表示されればOK

コード全文


株式会社エイルシステムでは Web エンジニア・モバイルアプリエンジニアを募集しています。
実務経験がなくても OK です。ご興味のある方は弊社 HP よりご連絡ください。

2024年に読んだおすすめ漫画10選

今週のお題「読んでよかった・書いてよかった2024」

  • 「2024年に出版された漫画」ではなく、「2024年に自分が読んだ漫画」を挙げています。
  • 一部ネタバレを含みます。
  • 順番は思いついた順であって順位ではないです。

おすすめ漫画10選

1. 黄泉のツガイ荒川弘

山奥の小さな村で暮らす少年のユルは、野鳥を狩り、大自然の中で静かに暮らしていた。しかしユルの双子の妹のアサは、何故か村の奥にある牢の中で「おつとめ」を果たしているという。それはまるで幽閉されているかのように…。 穏やかな村に浮かぶ不自然な謎、この村に隠された秘密とは一体…!?

ガンガンONLINEより引用

連載当初に存在は知りつつも、なんとなく積読してた漫画なんだけど今考えるとマジで時間がもったいなさすぎる。積読しておく意味がわからない。

初っ端から伏線盛り込みで何度も読み返してまうし、読み返すのが楽しい。
The 少年漫画なんだけど設定が本当に細かくてちゃんとしてる。
読み手が設定忘れててもキャラたちがちゃんと細かい設定通りに動いてるのが改めてすごいなって思う(当たり前なんだけど)

あと、いろんなツガイのキャラデザを見て荒川先生って本当に絵がうまいんだなって思った(何様?)
個人的に一番好きなツガイは愛と誠です。

同じように気になるけど読んでなかったり、なんとなく積読してる人は本当にその時間がもったいないから早く読んでほしい。
みんなの人生の中でこの漫画を読んでない時間をできるだけ短くしてほしい。(?)

www.ganganonline.com


2. このクラスにギャルはいない(時田時雨)

優等生の七瀬さん。ギャルに憧れ大胆なイメチェンをし、ドキドキの高校デビューを果たすことに。しかし進学校のためギャルがおらず、ヤンキーの間宮くんと一緒に2人で浮いてしまい…!?「赤面しないで関目さん」の時田時雨が贈る、すれ違いコメディ!

少年ジャンプ+より引用

読み切りのときに好きだった漫画の連載(古参アピ)

主要キャラはもちろんなんだけどモブまで全員もれなくいい子たちすぎる。
登場人物のデフォルメされた大根足もかわいすぎる。

廃れたメンタルに沁みて泣ける。浄化される。
いつか早乙女先生回も待ってます。

shonenjumpplus.com


3. サチ録~サチの黙示録~(茶んた)

悪魔と天使がある人間を審査し、その結果で人類の命運を決める「人間神判」。対象に選ばれたのは、稀代のクソガキ小学生・上野サチ(6歳)だった…!人類の未来をかけた、悪魔と天使と人間のヘンテコ共同生活が今始まる!

少年ジャンプ+より引用

これも廃れたメンタルに沁みる。
何でもない平和な日常回が一番泣けるんだけどこれなんて現象?

もしアニメ化したらプール回で頭身バグってる作画崩壊待ってます。

あと作者のホームページが可愛いから見てください。
ドメイン名も意味わかんなくて好き。加点+1000

chanta-in-inari.com

shonenjumpplus.com


4. ねずみの初恋(大瀬戸陸)

ヤクザに殺し屋として育てられ、人の愛を知らずに育った少女、ねずみ。何も知らない普通の青年、碧(あお)。二人は恋に落ち、共に暮らし始めるが、魔の手はすぐそこまで迫っていた‥‥。あまりに残酷で、あまりに切ない、初恋の物語。

コミックDAYSより引用

2024年ハピエン切望ランキングぶっちぎりで1位の漫画。
(けど、ハピエン切望してはいるんだけど、それと同時に救いのない絶望展開を待ってる自分もいる…)

ねずみちゃんはもちろんだけど、水鳥ちゃんも本当に幸せになってほしい……

comic-days.com


5. だくてん(大瀬戸陸)

『ねずみの初恋』の大瀬戸陸、16歳の初期衝動。

コミックDAYSより引用

ねずみちゃんも水鳥ちゃんも幸せになれないっぽい。

comic-days.com


6. 阿武ノーマル(原作: 川上大和 / 作画: タイジュン)

阿武英子、29歳。独身、彼氏なし。ものごとの価値基準は「普通」か否か。「普通」に固執するあまり、彼女を取り巻く人間関係が綻び始める。「普通」とは何か、「異常」とは何か、人の倫理を問う戦慄&衝撃の新感覚サイコ・サスペンス、開幕!!

マガポケより引用

そうはならんやろって展開連発でおもしろすぎる。
このマンガのヒロイン?河原さんに決まってんだろ!!

pocket.shonenmagazine.com


7. 写らナイんです(コノシマルカ)

見えてはいけないものを引き寄せてしまう、超霊媒体質の“黒桐まこと”。オカルト部に情熱を捧げる“橘みちる”と出会い、彼の人生が動き出すーーー新感覚のオカルト青春劇、開幕!!

サンデーうぇぶりより引用

恋愛関係未満の男女がわちゃわちゃしてる漫画、大好物です。
単行本派だからまだ2巻分までしか読めてないけど、これからたくさん個性的なキャラが増えてくのが楽しみ
橘さん vs 呪術廻戦の受肉してない状態の宿儺で戦ったらどっちが勝つんだろう

www.sunday-webry.com


8. マイホームヒーロー(原作: 山川直輝 / 作画: 朝基まさし)

頼れる妻と、ちょっと反抗期気味だけど可愛い大学生の娘。鳥栖哲雄の人生はそれなりに幸せだった。娘の顔に殴打の傷を見つけるまでは。「100万の命の上に俺は立っている」の山川直輝、「サイコメトラー」「でぶせん」の朝基まさしの異色コンビが描く、罪と罰、愛と戦いの物語、開幕!

ヤンマガWebより引用

ラストどう転んでも悲しいのはわかってるから最終巻が中々読めなかった。
連載中に自分が親になったのもあり、色んな目線から終始楽しめました。
欲を言えば最終話の明は人間が出来すぎてると思うから、もう少し深堀りしてほしかったな〜とか思ったり…

yanmaga.jp


9. 保健の授業聞いてなかった奴(小野寺こころ)

『スクールバック』の小野寺こころが描く衝撃作!! 高校1年生の夏、人生で初めて告白されたはるか。いじめから助けてくれたこともあり、そのまま流れで付き合うことになり…。

コミックDAYSより引用

あの、あの、えーっと……。ぼく同作者の だんしゃり とか スクールバック みたいなのが読めると思ってついてきただけなんですけど…
ここまで刺さる漫画だと思ってなかったんですけど…

comic-days.com


10. ひとりでしにたいカレー沢薫 / ドネリー美咲)

いわゆるひとつのバリバリのキャリアウーマンで、優雅な独身生活、余裕の老後を謳歌していたかに見えた伯母がまさかの孤独死。黒いシミのような状態で発見された。その死にざまに衝撃を受けた山口鳴海(35歳・学芸員・独身)の人生は婚活から一転終活へ。死ぬのは怖い。だけど人は必ず死ぬ。ならば誰より堂々と、私は一人で死んでやる。一人でよりよく死ぬためには、よりよく生きるしかない。愛と死をひたむきに見つめるフォービューティフルヒューマンライフストーリーの決定版誕生!

コミックDAYSより引用

ハートフル猫マンガ

comic-days.com

おまけ

すみにごり(たかたけし)

実家には怪物が暮らしていた。兄貴という名の──

29歳、夏。会社から長めの休みをもらった僕は、久しぶりに実家に帰省した。住んでいたのは父母、そして35歳、無業無言の兄だった。この家族は怪物なのか?それとも家族とは怪物なのか?新ホームドラマ、襲来。

ビッコミより引用

最新刊もめちゃくちゃ面白かったから今年もランクインさせてくれ。

去年のブログでお兄ちゃんが一番まともかも、みたいなこと言ってゴメン。
やっぱりお前が一番クレイジーや。
フミヤしか勝たん。

bigcomics.jp


関連記事

iliiliiiliili.hatenablog.jp


input type="range"でつまみのない丸っこいスライダーを作る

作りたいもの

つまみを非表示もどきにして丸っこくしたい

動作確認環境

コード

まずは HTML と CSS でできるところまで作るゾ1

<input type="range" value="0" min="0" step="1" max="5" />
input[type="range"] {
  -webkit-appearance: none; /* デフォルトのCSSをリセット */
  --range-height: 20px;
  --range-width: 250px;
  width: var(--range-width);
  height: var(--range-height);
  border-radius: 10px;
  background-color: skyblue;
  cursor: pointer; /* つまんでる感を出す(←?) */
  /* つまみのCSS */
  &::-webkit-slider-thumb {
    -webkit-appearance: none; /* デフォルトのCSSをリセット */
    width: 0; /* つまみを非表示に見せるため0にする */
    height: 0; /* つまみを非表示に見せるため0にする */
    border: calc(var(--range-height) / 2) solid blue; /* range の半分の高さで先っちょの丸みを作る */
    border-radius: 50%;
  }
  &:focus {
    outline: none;
  }
}

デフォルトの CSS をリセットしたら、つまみの前後で色の変化がなくなるの悲しみ。

ということで JS でつまみの前後の色を変える。

(() => {
  const input = document.querySelector('input[type="range"]');
  const min = input.min;
  const max = input.max;
  const width = parseInt(window.getComputedStyle(input).width);

  setRangeStyle(input, min, max, width);
  input.addEventListener("input", () => {
    setRangeStyle(input, min, max, width);
  });
})();
function setRangeStyle(input, min, max, width) {
  const border = (width / max) * input.value;
  // グラデの変化を急にしてつまみの前後を再現する
  input.style.background = `linear-gradient(90deg, blue ${border}px, skyblue ${border}px)`;
}

やったねたえちゃん!完成だよ!

⊂ 二二二( ^ ω ^)二二 ⊃ ブーン

(^ ω ^) おっ?

(´・ω・`)・・・?

Σ(゜ □ ゜;)ナンテコッタイ!!!

適当な div を作って step の箇所を確認してみる2

ズレてやがる・・・

多分、開始と終了で border radius の起点が変わるから、中間点で調整されていってズレてくっぽい(伝われ)

ズレないようにつまみの位置を調整してみる

input[type="range"] {
  -webkit-appearance: none;
  --range-height: 20px;
  --range-width: 250px;
  width: var(--range-width);
  height: var(--range-height);
  --slider-thumb-right: var(--range-width); /* 追加。初期値をrangeでみたときに0始まりになるようにする */
  border-radius: 10px;
  background-color: skyblue;
  cursor: pointer;
  position: relative; /* 追加 */
  &::-webkit-slider-thumb {
    position: absolute; /* 追加 */
    top: 0; /* 追加 */
    right: var(--slider-thumb-right); /* 追加 */
    -webkit-appearance: none;
    width: 0;
    height: 0;
    border: calc(var(--range-height) / 2) solid blue;
    border-radius: 50%;
  }
  &:focus {
    outline: none;
  }
}
(() => {
  const input = document.querySelector('input[type="range"]');
  const min = input.min;
  const max = input.max;
  const style = window.getComputedStyle(input);
  const width = parseInt(style.width);
  const height = parseInt(style.height);

  setRangeStyle(input, min, max, width, height);
  input.addEventListener("input", () => {
    setRangeStyle(input, min, max, width, height);
  });
})();

function setRangeStyle(input, min, max, width, height) {
  const border = (width / max) * input.value;
  // グラデの変化を急にしてつまみの前後を再現する
  input.style.background = `linear-gradient(90deg, blue ${border}px, skyblue ${border}px)`;
  let right = height / 2;
  if (input.value === min) {
    right = height; // つまみの起点 = rangeの最小値と同じ
  } else if (input.value === max) {
    right = 0; // つまみの終点 = rangeの最大値と同じ
  }
  input.style.setProperty(
    "--slider-thumb-right",
    `calc(${(width / max) * (max - input.value)}px - ${right}px)`
  );
}

✌✌✌

CodePen

See the Pen input range by m1y474 (@m1y474) on CodePen.

最後に

このブログ書いてるときに、JS使わずにワイがやりたいことやってる人見つけて鬱\(^o^)/

See the Pen Input Range with Gradient colors (CSS) by Victoria Azola Silva (@VickyAzola) on CodePen.

追記

でも↑これだとグラデの割合が絶対的にしか指定できないっぽい!ワイの作ったやつなら相対的にできるゾ!メンタル保てる!!

See the Pen input range gradient by m1y474 (@m1y474) on CodePen.

参考

zenn.dev


  1. WebKit 系のプロパティ使ってるから Safari でも動くと思うけど動作確認はしてないから注意してくれよな!Firefox はもちろん確認してないゾ!
  2. もしかしたら range の中に区切り線の入れられるのかもしれないけどやり方がわからなかった。

ワイ「3.8 - 3」 JS「0.7999999999999998」 ワイ「?!?!?!!」

勘のいいワイ「0.8(10) -> 0.11001100…(2)」

知ったかワイ「なるほど!完全に理解した!!」

Google「っ https://ja.wikipedia.org/wiki/IEEE_754

ワイ「・・・・・うんち!」

まとめ

ワイ「(3.8 - 3).toFixed(1)

JS「0.8

♡♡♡ 𝑯𝒂𝒑𝒑𝒚 𝒆𝒏𝒅 ♡♡♡

参考

ja.wikipedia.org

developer.mozilla.org

HTMLとCSSのみでカルーセルを作る

はじめに

n番煎じ感が否めない記事だけど、scroll-snap-type とかいう知らないプロパティくんがシゴデキっぽくて、わざわざ激重パッケージ用意する必要ないじゃんと思ったのでまとめておく

コード

<div class="container">
  <div class="items">
    <div class="item">item 1</div>
    <div class="item">item 2</div>
    <div class="item">item 3</div>
  </div>
</div>
:root {
  --width: 300px;
}
/* カルーセルのcontainerの領域を指定 */
.container {
  width: var(--width);
  height: var(--width);
}
.items {
  /* スクロールを停止するとスナップポイントにスクロールする */
  scroll-snap-type: x mandatory;
  display: flex;
  overflow: scroll;
  /* スクロールバーを非表示にする */
  &::-webkit-scrollbar {
    display: none;
  }
}
.item {
  /* スナップ位置 */
  scroll-snap-align: start;
  /* スナップ位置を通過しない。一旦ストップする */
  scroll-snap-stop: always;
  flex: 0 0 100%;
  width: var(--width);
  height: var(--width);
  /* 以降装飾に関するスタイル */
  font-weight: bold;
  font-size: 30px;
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
}
.item:nth-child(1) {
  background-color: red;
}
.item:nth-child(2) {
  background-color: green;
}
.item:nth-child(3) {
  background-color: blue;
}

ページネーションもつけたい

ページネーションは JS ないと無理っぽい

<div class="container">
  <div class="items">
    <div class="item">item 1</div>
    <div class="item">item 2</div>
    <div class="item">item 3</div>
  </div>
  <!-- ページネーションとなるボタンの設置 -->
  <nav>
    <button type="button"></button>
    <button type="button"></button>
    <button type="button"></button>
  </nav>
</div>
.items {
  scroll-snap-type: x mandatory;
  display: flex;
  overflow: scroll;
  /* ナビゲーションをクリックしたときに smooth scroll させるために追加 */
  scroll-behavior: smooth;
  &::-webkit-scrollbar {
    display: none;
  }
}
/* ページネーションボタンの装飾 */
button {
  width: 15px;
  height: 15px;
  background-color: grey;
  border: none;
  border-radius: 50%;
  cursor: pointer;
}
const buttons = document.querySelectorAll("button");
const items = document.querySelector(".items");

buttons.forEach((button, index) => {
  // 先頭要素をアクティブとする
  if (index === 0) {
    button.style.backgroundColor = "black";
  }
  // ボタンをクリックしたときに同じ順のアイテムのボタンの色を変更する
  button.addEventListener("click", () => {
    [...buttons].findIndex((tmp) => {
      if (tmp === button) {
        tmp.style.backgroundColor = "black";
        return;
      }
      tmp.style.backgroundColor = "grey";

      // スクロール位置を変更
      items.scrollLeft = width * index;
    });
  });
});

const width = parseInt(
  window.getComputedStyle(document.querySelector(".item")).width
);
// スクロール終了時に該当アイテムのボタンの色を変更する
items.addEventListener("scrollend", (elm) => {
  const scroll = elm.target.scrollLeft;
  const num = scroll / width;
  buttons.forEach((button, index) => {
    button.style.backgroundColor = "grey";
    if (num === index) {
      button.style.backgroundColor = "black";
    }
  });
});

アクティブ状態のプロパティが多い場合は classList を操作したほうが楽かも

CodePen

See the Pen Untitled by m1y474 (@m1y474) on CodePen.

最後に

scroll-snap-type にずっと proximity を指定してて、スナップ部分で止まるのは無理なんだと諦めて JS で実装した俺の無駄な努力を供養させてくれ

// スクロール終了時、起点で止まっていない場合に表示領域が多い方にスクロールさせる
document.querySelector(".items").addEventListener("scrollend", (elm) => {
  const width = parseInt(window.getComputedStyle(document.querySelector(".item")).width);
  const max = document.querySelectorAll(selector).length;
  const scroll = elm.target.scrollLeft;
  for (let index = 0; index < max; index++) {
    const point = index * width;
    if (scroll > point && scroll < point + width) {
      const half = point + (width / 2);
      if (scroll < half) {
        elm.target.scrollLeft = point;
        return;
      }
      elm.target.scrollLeft = point + width;
    }
  }
});

株式会社エイルシステムでは Web エンジニア・モバイルアプリエンジニアを募集しています。
実務経験がなくても OK です。ご興味のある方は弊社 HP よりご連絡ください。


【CSS】線形・放射・扇形・反復グラデーションまとめ

線形グラデーション

1
2
3
4
5
6
7
8
9
10


.linear-1 {
  /* orangeからblueにグラデする。orange 0%, blur 100% と同じ挙動 */
  background: linear-gradient(orange, blue);
}
.linear-2 {
  /* 左から右にグラデする。to right = 90deg or 0.25turn と同じ挙動 */
  background: linear-gradient(to right, orange, blue);
}
.linear-3 {
  /* 45度回転した状態でグラデする。45deg = to right top or 0.125turn と同じ挙動 */
  background: linear-gradient(45deg, orange, blue);
}
.linear-4 {
  /* グラデ軸の開始点を10%, 終了点を50%にする。 */
  background: linear-gradient(orange 10%, blue 50%);
}
.linear-5 {
  /* 複数グラデ&各色の開始を指定 */
  background: linear-gradient(orange 10%, blue 50%, deeppink 100%);
}
.linear-6 {
  /* グラデ軸の開始と終了点が同じのため変化が急になる。指定数値が昇順じゃない場合も開始>終了となるので変化が急になる */
  background: linear-gradient(orange 30%, blue 30%);
}
.linear-7 {
  /* 変化の中心点を30%にする */
  background: linear-gradient(orange 0%, 30%, blue 100%);
}
.linear-8 {
  /* 左下に向かって複数グラデ */
  background: linear-gradient(to bottom right, orange 0% 20%, blue 20% 40%, deeppink 40% 60%, lime 60% 80%, yellow 80% 100%);
}
.linear-9 {
  /* 複数レイヤー(?)でのグラデ。透過箇所がない場合は最初に指定した色が表示される */
  background: linear-gradient(orange, transparent, transparent),
              linear-gradient(transparent, blue, transparent),
              linear-gradient(transparent, transparent, deeppink);
}
.linear-10 {
  /* 背景画像に対してのグラデ */
  background: linear-gradient(transparent, orange), url("https://i.imgur.com/djkvTYX.png") center no-repeat;
  background-size: contain;
}

放射グラデーション

1
2
3
4
5
6
7
8
9
10
11
12
13


.radial-1 {
  /* デフォルトはellipse(楕円) */
  background: radial-gradient(deeppink, lime);
}
.radial-2 {
  /* 正円 */
  background: radial-gradient(circle, deeppink, lime);
}
.radial-3 {
  /* 左始点で正円のグラデ */
  background: radial-gradient(circle at left, deeppink, lime);
}
.radial-4 {
  /* 末端がボックスの中心から一番近い辺に隣接するように描画される */
  background: radial-gradient(circle closest-side, deeppink, lime);
}
.radial-5 {
  /* 末端がボックスの中心から一番遠い辺に隣接するように描画される */
  background: radial-gradient(circle farthest-side, deeppink, lime);
}
.radial-6 {
  /* 末端がボックスの近い頂点(角)に隣接するように描画される */
  background: radial-gradient(circle closest-corner at 20px, deeppink, lime);
}
.radial-7 {
  /* 初期値。末端がボックスの中心から最も遠い頂点(角)に接する */
  background: radial-gradient(circle farthest-corner at 20px, deeppink, lime);
}
.radial-8 {
  /* 正円の大きさを指定 */
  background: radial-gradient(circle 50px, deeppink, lime);
}
.radial-9 {
  /* 楕円の大きさを指定 */
  background: radial-gradient(ellipse 10px 50px, deeppink, lime);
}
.radial-10 {
  /* 複数グラデ */
  background: radial-gradient(ellipse, deeppink, lime, yellow, darkviolet);
}
.radial-11 {
  /* グラデ変化なし正円 */
  background: radial-gradient(circle, deeppink 0% 10%, lime 10% 20%, yellow 20% 30%, darkviolet 30% 40%, transparent 40%);
}
.radial-12 {
  /* xy軸20px起点の正円グラデ */
  background: radial-gradient(circle at 20px 20px, deeppink, lime);
}
.radial-13 {
  /* 複数レイヤーのグラデ */
  background: radial-gradient(circle at 0px 0px, deeppink 40%, transparent 0%),
              radial-gradient(circle at 100px 200px, lime 40%, transparent 0%);
  background-color: white;
}

扇形グラデーション

1
2
3
4
5


.conic-1 {
  /* yellowからdarkvioletに変化する扇型のグラデ */
  background: conic-gradient(yellow, darkviolet);
}
.conic-2 {
  /* x, y軸の指定 */
  background: conic-gradient(at 0% 40%, yellow, darkviolet);
}
.conic-3 {
  /* 複数グラデ */
  background: conic-gradient(yellow, darkviolet, orange, blue);
}
.conic-4 {
  /* 起点・終点を指定した複数グラデ */
  background: conic-gradient(yellow 0% 20%, darkviolet 20% 40%, orange 40% 60%, blue 60% 80%, deeppink 80% 100%);
}
.conic-5 {
  /* 90度回転を起点としたグラデ*/
  background: conic-gradient(from 90deg, yellow, darkviolet);
}

反復グラデーション

1
2
3
4
5
6
7
8


.repeating-1 {
  /* 4分割のグラデ */
  background: repeating-linear-gradient(crimson, deepskyblue 25%);
}
.repeating-2 {
  /* 90回転して変化が急なグラデ */
  background: repeating-linear-gradient(90deg, crimson 0% 10%, deepskyblue 10% 20%);
}
.repeating-3 {
  /* 複数レイヤー */
  background: repeating-linear-gradient(crimson 0% 10%, transparent 10% 20%),
              repeating-linear-gradient(90deg, deepskyblue 0% 10%, transparent 10% 20%);
}
.repeating-4 {
  /* 開始・終了が同じ色で終わる */
  background: repeating-linear-gradient(crimson 0% 5%, transparent 5% 20%, crimson 20% 25%),
              repeating-linear-gradient(90deg, deepskyblue 0% 5%, transparent 5% 20%, deepskyblue 20% 25%);
}
.repeating-5 {
  /* 4に続くグラデ */
  background: repeating-linear-gradient(crimson 0% 5%, transparent 5% 20%, crimson 20% 25%),
              repeating-linear-gradient(90deg, deepskyblue 0% 5%, transparent 5% 20%, deepskyblue 20% 25%);
}
.repeating-6 {
  /* 放射グラデ */
  background: repeating-radial-gradient(crimson 0% 10%, deepskyblue 10% 20%);
}
.repeating-7 {
  /* アニメーション付き放射グラデ */
  background: repeating-radial-gradient(deepskyblue 0% 10%, crimson 10% 20%);
  animation: 0.3s linear 0s infinite normal moving;
}
@keyframes moving {
  from {
    background: repeating-radial-gradient(crimson 0% 10%, deepskyblue 10% 20%);
  }
  to {
    background: repeating-radial-gradient(deepskyblue 0% 10%, crimson 10% 20%);
  }
}
.repeating-8 {
  /* 扇形グラデの反復 */
  background: repeating-conic-gradient(deepskyblue 0deg 20deg, crimson 20deg 40deg);
}

CodePen

線形グラデーション

See the Pen Untitled by m1y474 (@m1y474) on CodePen.

放射グラデーション

See the Pen radial-gradient by m1y474 (@m1y474) on CodePen.

扇形グラデーション

See the Pen conic-gradient by m1y474 (@m1y474) on CodePen.

反復グラデーション

See the Pen repeating-gradient by m1y474 (@m1y474) on CodePen.

感想

スプラ4は赤×水色の配色が来ると思います!(適当)

参考

developer.mozilla.org

developer.mozilla.org

developer.mozilla.org

developer.mozilla.org

developer.mozilla.org

developer.mozilla.org

developer.mozilla.org

ics.media


株式会社エイルシステムではWebエンジニア・モバイルアプリエンジニアを募集しています。
実務経験がなくてもOKです。ご興味のある方は弊社HPよりご連絡ください。

【Googleドライブ】ファイルの最終更新者を取得する【GAS】

前提

Google Workspace のアカウントで検証・実装しています。
API によっては個人アカウントと挙動が異なる可能性があります。多分。

やりたいこと

Google ドライブに保存しているファイルの最終更新を取得したい。

ググった感じ、古い情報しかなかったり最終更新日時しか取得できなかったりで自分の環境で動かなかった。
インターネッツによると、Drive.Files.get()lastModifyingUserNameが取得できるらしいんだけど、ワイがアクセスしたときのレスポンスがこれ↓だったからググってコピペでイッセンマンにはなれませんでした。

{ "name": "XXXXX", "mimeType": "XXXXX", "kind": "XXXXX", "id": "XXXXX" }

ドキュメントに記載されてるリソースと違いすぎて笑えてきまちゅわ〜(泣)
(多分Google Workspaceのアカウントだったりファイルの共有設定とかの環境のせいもあると思うけど、単純にワイのドキュメントに対する読解力がないだけ)

やったこと

ということでできないもんは仕方ない!別の方法でやっていこう!

GAS の設定周り

1. 必要なサービスを追加する

以下の使用するAPIをサイドバーのサービスから追加する。

  • Drive
  • DriveActivity
  • People

サイドバー->サービス->+ボタンのサービスを追加をクリックすると以下のようなモーダルが出てくるので該当 API を選んで追加する。

People APIを追加する場合

IDはプロジェクト内の他の定義と重複していなければこのままでOK

2. appsscript.jsonoauthScopes を定義する

プロジェクトの設定->全般設定にある「appsscript.json」マニフェスト ファイルをエディタで表示するにチェックを入れる。

サイドバーのエディタにappsscript.jsonが出てくるからoauthScopesを定義して、以下の権限を記述する。1

"oauthScopes": [
  "https://www.googleapis.com/auth/userinfo.profile",
  "https://www.googleapis.com/auth/contacts.readonly",
  "https://www.googleapis.com/auth/drive.readonly",
  "https://www.googleapis.com/auth/drive",
  "https://www.googleapis.com/auth/drive.activity",
  "https://www.googleapis.com/auth/drive.activity.readonly"
],

GAS が用意してる API は基本的に設定しなくても使えるはずなんだけど、People API の以下の 2 つだけは明示しないと呼び出せないみたいだった。

  • https://www.googleapis.com/auth/userinfo.profile
  • https://www.googleapis.com/auth/contacts.readonly

と同時に、oauthScopesを定義すると設定しなくても使えるはずの他のサービス(Drive, DriveActivity…etc)の権限が死ぬみたいで、最終的に使うサービスのスコープはすべてoauthScopesに記述しないと動かなかった。(だったら最初から全部明示的に記述しないと動かないようにしとけ!!!)

このへんは実行したときに必要なスコープをログに出してくれるから指定値がわからなくなることはないと思う。Google ちゃん優しいね。

3. コード.gs の実装

3-1. ファイル情報を取得する
const activities = DriveActivity.Activity.query({
  itemName: "items/XXXXXXX", // items/ファイルID の形式でファイルを指定
  pageSize: 1,
}).activities;

再現性取れてないけど、たまにactivitiesが空で返却されることがあるけどなんでだ?ファイルが存在する以上は履歴が空になることはなくない??

3-2. ファイル情報から最終更新ユーザーの識別子を取得する
const personName = activities?.[0]?.actors?.[0]?.user?.knownUser?.personName;
3-3. 識別子からユーザー情報を取得する
const lastModifyUser = People.People.get(personName, { personFields: "names" })
  ?.names?.[0]?.displayName;

うん、済まないがoptional chaining アレルギーの人は帰ってくれないか(´・ω・`)2

コード全体(一例)

フォルダ内のファイル数が多い場合とか再帰的にアクセスしてく場合は、多分レートリミットにすぐ引っかかるから API にアクセスする直前に 1,2 秒の sleep 入れたほうがいいと思う。(10行目)

組織外のユーザーの情報も取得したい場合は多分 GAS 以外の設定もいるっぽい。多分。知らんけど。

4. GAS に対して権限を許可する

実行したらGASへのアクセス権限を聞かれるから許可してあげて完了。

トラブルシューティング

Exception: Specified permissions are not sufficient to perform the action. Required permissions: (https://www.googleapis.com/….)と表示される

appsscript.jsonに必要なスコープが記述されていない可能性があります。
記載されている URL をoauthScopesに設定してあげましょう。

Quota exceeded for quota metric 'Critical read requests (xxxxx)' and limit 'Critical read requests (xxxxx) per minute per user' of service 'xxxxx.googleapis.com' for consumer と表示される

短時間に複数のファイルにアクセスし続けている場合、API のレートリミットに引っかかっている可能性があります。
上限を引き上げる申請をするか、API へのアクセスの直前で 1,2 秒のスリープを入れてあげましょう。

最後に

いろんな条件が重なって lastModifyingUserName で最終更新者が取得できてないだけだと思ってるんだけど、本当にここまでしないと取れないんか…?
ファイルが持ってる公開情報だからもっと簡単に取得できても良さそうなんだけど…
誰かもっと簡単に取得できる方法知ってる人がいたら教えてくだちい。

参考

rikoubou.hatenablog.com developers.google.com developers.google.com developers.google.com


株式会社エイルシステムではWebエンジニア・モバイルアプリエンジニアを募集しています。
実務経験がなくてもOKです。ご興味のある方は弊社HPよりご連絡ください。


  1. ちなみにoauthScopeshttps://www.googleapis.com/auth/drive.metadata.readonly, https://www.googleapis.com/auth/drive.appdata とかを追加してもlastModifyingUserNameは取得できなかった。
  2. キメラ文章になっちまった

育休中に基本情報技術者試験を受験した話

※ 本記事は2024年9月時点での情報です。

1. 基本情報技術者試験って何?

IPAがやってる国家資格の1つ。
令和2年度以降、CBT方式で受験できる。

科目A 科目B
試験時間 90分 100分
出題形式 四肢択一式 多肢選択式
合格基準 600点以上 / 1000点 600点以上 / 1000点

www.ipa.go.jp


2. なんで今更?

  • 育休中で割と時間があって暇だった
  • 未経験でIT業界に入り、自分にはITに関する基礎知識がないと常々コンプレックスに思っていたから
  • 運転免許以外の何かしらの国家資格が欲しかった
  • 転職を考えていて採用において有利になると思った(※後述あり

3. 勉強方法

3-1. 科目A

3-1-1. 過去問道場

みなさんご存知、過去問道場を以下の手順で2周した。

  1. 過去問道場に掲載されている過去問を全年分1周
    (→自分は基礎知識をつけることも目的だったから全年分を1周したけど、シラバス外もやることになるので基本情報の受験対策としては全年分をやる必要はない)
  2. 過去問道場の [試験回を指定して出題] 機能で、過去10年分の問題のうち、間違えた or 理解が浅い問題を中心に2周目

www.fe-siken.com

3-1-2. YouTube

育児でどうしても手が空かないときには以下の動画を流してた。(けど正直、自分は動画学習には向いていないみたいで、あまり身につかなかった。)


www.youtube.com

3-1-3. Newmonic(暗記アプリ)

主にストラテジ系の頭字語の暗記が苦手で Newmonic っていうスマホアプリを使ってスキマ時間で覚えた。
単語をPCから編集できて、CSVインポートもできるから自分には使いやすかった。

play.google.com

Newmonic

Newmonic

  • baton Inc.
  • 教育
  • 無料
apps.apple.com

3-2. 科目B

3-2-1. 過去問道場

過去問道場にも掲載されている、IPAが出しているサンプル問題を2,3周した。

3-2-2. 参考書

アルゴリズム×擬似言語 トレーニングブック を3周くらいした。
ただ、サンプル問題もそうなんだけど1周目で解けた時点で解き方&解答を覚えてしまうので2周目以降はあまり意味なかったなと思う。
参考書自体はページ数が多くない割にオリジナル問題が多いからおすすめ。

3-2-3. その他

IPAが出しているサンプル問題以外の問題を解きたかったから、YouTubeでオリジナル問題を出している動画を探したり、過去問道場の掲示板やLINEのオプチャで他の人がヘルプを出してる問題を解いてた。1

3-3. セキュリティ対策

IPAが出してる 情報セキュリティ白書 とか 情報セキュリティ10大脅威 を漁った。(多分、試験対策にはサンプル問題と科目Aをやるだけでだけで充分だと思う。)

www.ipa.go.jp

www.ipa.go.jp


4. 試験当日

4-1. 受験1回目

「1回目」という見出しがあるということは…?
そうだね!不合格でした(^_-)-☆

科目A 815点 / 科目B 550点

受験3日前くらいに科目Bのサンプル問題を解いて「この感じなら余裕じゃん!!コード読むだけとかwww経験者ナメんなし!wwwwwww」とか思って受けたら、本番で全然時間足りなくて草でした。

なるべく参考書を買わずに合格することを目標としてたけど、翌日速攻買いに行ったよね。

4-2. 受験2回目

リテイクポリシーの関係2で1ヶ月後に再受験して合格できた。

科目A 745点 / 科目B 725点
合格ではあるけど勉強した割に点数低くね〜〜???
科目Aに関しては1回目より点数下がってんの何でだよ


5. 反省点

5-1. 電子版の参考書を購入した

本番と近い感じでPC見ながら問題を解きたいと思って、電子版を購入したけど、使い捨てみたいなもんだし後々のことを考えて紙にすればよかったと後悔。

5-2. テストセンターはすぐ確保できると思ってた

「CBTって毎日開催してるからすぐ予約取れるっしょw」って思ってて、いざ予約取ろうとしたら近所のテストセンターが悉く1ヶ月先まで埋まっててワロタ\(^o^)/
地域差あると思うけど、予約の変更は(3日前までなら)何回でもできるからとりあえず早めに予約すべきだと思う。

5-3. 勉強から資格取得までの時間をかけすぎた

予約がすぐに取れなかったのもあるけどもう少し短期間で取得したかった。
育児の合間とはいえ、5ヶ月も使ったのは掛かりすぎだと思う。

子どもが4ヶ月くらいのときに勉強し始めたけど、月齢が進むにつれて寝返りしたり、つかまり立ちしたりで益々目を離せなくなるから勉強時間を確保するのが難しくなってた。もう少し早く取りかかればよかった。(というか時間がフルに使える産前休暇のうちに始めるべきだった。3

5-4. 科目Bの時間管理が雑魚すぎた

1回目の受験時では、出題されたコード全文を把握しようとしてたから回答時間が圧倒的に足りなかった。

2回目はコードすべてを把握せずに、問題文と選択肢から予想して回答した。
体感「落ちててもおかしくないな〜」って感じだったから合格できたのは運もあったと思う。


6. よかったこと

  • シラバスが変わる前に滑り込みで合格できた4
  • 受験料が2回まで会社負担で受けられるので自己負担がなかった(2回目で受かってよかった…)

7. 基本情報は採用において有利なのか

受験した理由 に「採用において有利になると思った」って書いたけど、実際に勉強してみて基本情報を持ってるくらいでは有利にはならないなと思った。特に、経験者が持っていても別にプラス要素ではないと思う。(自分は採用担当でもなければ面接官をやったこともないので、マジでガチのめちゃくちゃ超超超個人的感覚による感想です。)

IT業界に身をおいていて、受けるかどうか迷ってる方は基本情報は飛ばして、応用技術者試験を受けるだけでいいと思う。

ただ、今まで曖昧だった分野の基礎知識はついたし、応用技術者試験にも活かせるから自分的には受けてよかった!

8. 最後に

次は応用技術者試験とデータベーススペシャリストを取得したいけど、保育園も始まってフルタイムで復帰したらオデはいつ勉強したらいいんだ???


  1. 参加したのが夏休みだったからかわからないけど、オプチャの民度は終わってた☆(オプチャ自体そんなもん?)
  2. 前回の受験日の翌日から30日以内は再受験できない。
  3. スプラやってたら気付いたら産休終わってた。
  4. 2024年10月の試験からシラバスが変更になった。

🤰妊娠・出産レポ👶

※ 出血、嘔吐、💩の話が出ます ※

妊娠期🤰

つらかったこと

6月〜8月あたまくらいまでつわりがあって、これがとにかく辛かった。

  • 世の中のありとあらゆる酸っぱいものと糖なし炭酸を欲しては嘔吐
  • 「これはつわり酷くても食べられる!」を数日ごとに繰り返しては嘔吐
  • 歯磨きするときに嘔吐
  • 浴室に入るたびに浴室のニオイで嘔吐

現代医学で未だにつわりの原因が解明されてないとか意味がわからないもぅマヂ無理
あとは食事制限で約10ヶ月の間、生ものとかカフェインが摂取できないのも結構ツラかった;

反省点

タクチケを余らせた

市から妊婦用のタクチケがもらえるんだけど、もったいないオバケが発動して数千円分余らせた。通院時にもっと贅沢して使えばよかった。

妊娠線ができた

保湿できればいいと思ってニベアとかヴァセリン使ってたら、普通にガッツリ妊娠線できた。専用のクリーム買えばよかった。

母子手帳ケースをケチった

無料でもらえる応募者全員プレゼント的なものを使ってたけど、使い勝手が悪くて中期頃にちゃんとしたやつを買った。通院時はもちろん出産後も使うものだからマジで最初からちゃんとしたものを買ったほうがいい。

出産👶

時系列

2024/01/05(火) - 38w1d

検診日に予告なしで内診ぐりぐりとやらをやられる。
あるとは聞いてたけど予告なしでやられるとは思わなかった。もちろん痛すぎて汗だく。(当たり前だけど出産はこれより痛いと聞いてビビり散らかす)
子宮口は指一本分空いてたらしいけど出産はまだ先らしい。

その日の夜中に腹痛があるも陣痛は来ず。

2024/01/10(水) - 39w0d

この日も夜中に腹痛あり。(前駆陣痛ってやつ?)
一日一回以上は💩出る快便マンだけどこの日は便秘でなんとなく覚悟するも当てが外れる。

2024/01/11(木) - 39w1d

💩快便&下痢💩

2024/01/12(金) - 39w2d

検診にて子宮口2センチとのこと。
内診後に微量の出血があったけど、その後は出なかった。
これがおしるしってやつ?!って思ったけど粘液栓も出てないし違った。

2024/01/13(土) - 39w3d

記憶がない。

2024/01/14(日) - 39w4d

06:30頃

下痢のときみたいな腹痛のあと、10分間隔で陣痛あり。
粘液栓っぽいのが出る(多分これがおしるしだった)
病院に電話するも7~5分間隔になったらまた電話してと言われたから朝ご飯食べてゆっくり過ごす。

09:00頃

7分間隔になったから病院に電話するも、痛みがまだ我慢できるレベルなことを伝えたら5分間隔になったら連絡してと言われる。(もちろん破水したり、胎動が少なくなった場合も)

スプラフェス参加するも途中で陣痛が酷くなってきたから、ホラガイ消化とフェスTクリーニングして断念。(2023年の卵巣腫瘍の手術のときも病院でスプラフェスしてたの思い出す)

ゴカム実写化のCM見てて、玉木宏の鶴見中尉めっちゃ合ってるね〜とか話してたんだけど、今日出産するだろうからふと01/14生まれの有名人調べたら玉木宏が出てきて「ワイの勘すげ〜!!」ってなる。(何が?)

14:00頃

2回目の粘液栓出る。

17:00頃

陣痛が限界になってきたから病院に電話したら所見によっては自宅に帰されるかもだけど来院してもいいとのこと。
「体力つけるために夜ご飯しっかり食べてから来てね〜」と言われたのでガストで定食を頼むも食後に吐き気MAXでトイレ直行。
間に合わなくて食べたものを全部トイレの壁にマーライオンする。
掃除するも陣痛が限界だったから中断して定員さんに平謝りx100

18:00頃

病院に着いてNSTとやらをやったけど見る余裕なし。(本来は次の検診でやる予定だった)
陣痛を和らげる呼吸法を教えてもらうも、息を吐くたびにマーライオン

初産婦なこともあり、まだ出てこないだろうとのことで帰宅を勧められる。
一旦帰るのを決意して会計を済ますも、会計してる間に5分未満間隔になってきたから入院をお願いする。

22:00頃

トイレ行ったら股から大量出血してて、子宮口が全開だったみたいでそのまま分娩台へ。
出産直前の記憶があんまないけど「💩する感じでいきんで」と言われて3、4回全力でいきんだら出てきたっぽい。
出てくる瞬間を見てないし、出した感もなかったけど助産師さんが取り出したのを見て、ほんとに中に人が入ってたんだ〜って思った記憶だけある。
カンガルーケアしながら母乳もあげたけど初産婦なこともあり、あんまり出ず。(ちな出産までに名前を決めきれなくてずっと「赤ちゃん」って呼んでたw)

18:00頃に帰そうとしたのは、初産婦だったから陣痛が長丁場になると踏んでたからみたいだけど結果帰らなくて良かったらしい。

陣痛のたびに何でワイは無痛分娩にしんかったんや…って思ってたけど、経験したことでこの世のあらゆるコンテンツの出産の例えが理解しやすくなるから結果オーライ✌️
「鼻からスイカ」が一番よく使われる表現だと思うけど、個人的にはピンと来なかった…
何で鼻からなのかがわからんし、スイカも大袈裟すぎる。でっかい💩出すって感じ。

会陰切開

会陰切開後の縫合と縫合跡が痛かった。(分娩中に会陰切開されたけど、切られたときはそれどころじゃなくて痛みを感じなかった。)
特に縫合跡がずっと痛くて、ドーナツ椅子も円座クッションも役に立たなかった。
というか初産婦で会陰切開しなかった人、前世でめちゃくちゃ徳積んできたとしか思えない。

入院生活

夜勤

前半はとにかく休みたいから預けまくって、後半で夜勤マスターした。

導尿されまくった

便通は問題なかったけど、とにかくおしっこが出なかった。
尿意はあるのに出ない、出たとしてもちょろちょろ&残尿感MAXって感じで毎回導尿してもらってた;;(後日明細見たら16回も導尿されてた☆)
総合病院での分娩だったからそのまま泌尿器科で診察もしてもらって、なんとか退院前日(出産後6日目)には改善して自己導尿は回避した。総合病院万歳🙌
自己導尿は回避したからちょっと違うけど導尿の流れはほぼ↓この方の漫画と同じだった。

niwatorisanno.blog.jp

最後に

出産から9ヶ月くらい経つけど、20kg近く増えた体重はいつ戻るんだ???まだ産後だよね??????