Photo by Pixabay on Pexels.com

FastApiのコードをgitで管理するように.あとはテストサーバーのymal

2025.07.31

Logging

おはようございます.FastApiのコードをgitで管理するように.あとは自分のテスト環境用のymalもgithub上に置いておこうと思っています.

というのも、そろそろパソコンを買い替えようかなと思っています.もしかしたらウィンドウズ系からサヨナラするかもですが、Apple系は高いからなぁ置き換えるならまずメインのデスクトップから置き換えていかないとどうしようもない.

逆に言えばメインをウィンドウズを使用している間はアップル系には置き換えが難しいということです.今の仕事はWebシステム系なので、どちらかと言えばウィンドウズよりMacが適していると考える人が多いと思う.自分も買い替えたい気持ちがあるのだけども、自作PCの良いところはメンテナンスが自分で出来るところにある.

こういう事はアップル製品には難しい、精々メモリ交換やSSD交換ぐらいのものしか出来ないのが現状かな、なので徐々にアプリやセキュリティ更新に引っかかり新しい製品を購入しないと難しくなる事が多いのだが、自作PC場合は部品交換すると何とかなる事が多い.

そういう事もあって未だにボロパソコンを使用しているだけど、いろいろとガタがでてきているので部品交換するよりもう取っ替えた方が良い感じになりつつある.

そういう訳でウィンドウズかアップル製品にするかを凄く悩んでいます.皆さんならどうしますか?

因みに来年には恐らく買い替えないとどうしようもない感じになりそうです.ギリまで使い倒すとは思うものの…

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

アップル, あと, アプリ, ウィンドウズ, ガタ, キリ, コード, こと, サヨナラ, システム, しょう, セキュリティ, そう, デスク, テスト, ところ, どちら, ドップ, パソコン, ボロパソコン, メイン, メモリ, メンテナンス, もの, よう, 交換, 仕事, 使用, 場合, 感じ, 明日, 更新, 来年, 気持ち, 現状, 環境, 皆さん, 管理, 自作, 自分, 製品, 購入, 部品,

Camera+ recipe? ? scene: Cloudy ? crop: Golden ? effect: Redscale (77%) ? border: Round White

馬鹿なことをしてしまった、たまにやらかします.そして凹む.

2025.07.27

Logging

おはようございます.自分が運用しているサイトで馬鹿なことをしてしまった、たまにやらかします.そして凹むです.今回やらかしたのは身内は自分が運用しているサイトの広告を表示させないようにするというコードを改修している時にエラーが出て5分ぐらい機能が使えなくなったというやらかし.

原因はイズセットの使い方がお馬鹿さんなコードの書き方をしていたのにも関わらず、その矛盾に気が付かずオロオロしてしまったということ.めちゃ焦ります、サイトの訪問者が少なければ焦らせないですけど、まぁある程度、アクセスがあるサイトなので止まってしまうと焦ります.

そういう時に我に返ることが簡単に出来れば良いのだけども自分の場合はパニクると中々冷静に対応できない所がある.

因みにどんなミスコードかと言えば下記のようなコードになります.イズセットが偽の時に次の判断処理に行くのでエラーになるという事です.本当にやらかしですw

皆さんもこんな凡ミスをしないようにリリースする前にはローカル環境でチェックとユニットテストをお忘れなくーーー!

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

ーーー, アクセス, イズセット, エラー, コード, こと, サイト, サン, たま, チェック, テスト, パニク, ミス, ユニット, よう, リリース, ローカル, 下記, 今回, 使い方, 冷静, 処理, 判断, 原因, 場合, 対応, 広告, 改修, 明日, 書き方, 機能, 環境, 皆さん, 矛盾, 簡単, 自分, 表示, 訪問, 身内, 運用, 馬鹿,

駆け出しエンジニアとつながりたい的なコードを書いてみた.ごっさんです.

2025.07.21

Logging

おはようございます.下記のコードを知っておくと便利ですよ、フレームワークとかなら使わないかもしれないけども素(えいてぃぶコード)のPHP言語で書くと便利ですね.この頃、素のPHP言語で書くことが無くなりつつあります.仕事ではフレームワークやフロントエンドでもライブラリを使用してコードを書くことが多いですね.たまにバニラJSで書くこともありますが.

<?php
$foo = [
	'name' => '山田 太郎',
	'age' => 25,
	'tel' => '09012341234'
	];
var_dump($foo);
var_dump(array_keys($foo));
var_dump(array_values($foo));

駆け出しエンジニアがもういないよなぁ…コードの土台はAIによって書くことが多くなりプロジェクトの改修時に古のコードを見るようになるだろうなぁ.たまに見かける痛いコードを昔は書いていたなぁと思いつつ、今でも痛いコードを書いていると思った方が良いなって.数ヶ月前に書いたコードが痛いコードに見えるので…まだまだ成長過程かなって思っています.

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

```, イブ, エンジニア, エンド, ヶ月, コード, こと, たま, バニラ, フレーム, プロジェクト, フロント, よう, ライブラリ, ワーク, 下記, 仕事, 使用, 便利, 土台, 太郎, 山田, 成長, 改修, 明日, 言語, 過程, 駆け出し,

ワードプレスのテーブルwp_postsデータを取ってきてLaravelで表示.

2025.07.15

Logging

おはようございます.ワードプレスのテーブル(wp_posts)データを取ってきて別サイト(Laravel)にて表示してます.別サイトには広告が付かない感じです.因みにデータは自サイトのブログデータを使用していますが随時去年あたりのデータから取得するようにSQLに記述しています.

尚、どうやって取得しているかをお話するとSQLのコネクション変更する設定をコンフィグフォルダのデータベースファイルに記述してモデルにもその事を明記しています.

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;


class Blog extends Model
{
    protected $connection = 'second_db';
    protected $table = 'wp_posts';
}

そしてそれらを呼び出しているだけです、とても簡単なコードで動いています.そんな感じなのでブレイドのコードをシェアします、流石にコントローラーは見せられないけどYoutubeのリンクやXのリンクは出力する前に置き換えていることをヒントとしてお伝えしときますね.

<!doctype html>
<html lang="ja" class="transition-colors duration-300">

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
    <meta name="robots" content="noindex,nofollow" />
    <title>blog - [taoka toshiaki]</title>
    <link rel="icon" href="https://taoka-toshiaki.com/images/g4DV7mRe_400x400.jpg?t=1752317617"
        sizes="16x16 24x24 32x32 48x48 64x64">
    <!-- Prism CSS -->
    <link id="prism-theme" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1/themes/prism.css" />
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1/plugins/line-numbers/prism-line-numbers.css" />
    <link href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/toolbar/prism-toolbar.min.css"
        rel="stylesheet" />
    <style>
        body {
            background-color: #f9fafb;
            color: #1f2937;
            transition: background-color 0.3s, color 0.3s;
            word-wrap: break-word;
            overflow-wrap: break-word;
        }

        .dark body {
            background-color: #242425;
            color: #f9fafb;
        }

        article {
            background-color: #fff;
            transition: background-color 0.3s;
            word-wrap: break-word;
            overflow-wrap: break-word;
        }

        .dark article {
            background-color: #3d3d47;
        }

        time {
            color: #6b7280;
        }

        .dark time {
            color: #9ca3af;
        }

        .prose {
            color: inherit;
            word-wrap: break-word;
            overflow-wrap: break-word;
        }

        pre[class*="language-"] {
            overflow-x: auto;
            padding: 1em;
            border-radius: 0.5rem;
        }

        code[class*="language-"] {
            white-space: pre;
        }

        a,
        a:hover {
            border-bottom: solid 2px #fbf81c;
        }
    </style>
    @include('header_script')
</head>

<body class="transition-colors duration-300">

    <div class="max-w-3xl mx-auto p-6">
        <h1 class="text-2xl font-bold mb-6"><a href="/" class="text-current">🏠️Top Page</a></h1>
        <p class="mb-3 font-bold"><a href="/blog">🖊️</a>おもしろき こともなき世をおもしろく 住みなすものは 心なりけり.</p>
        @if (request()->input('page') == 108)
            <a href="/blog" class="text-[54px]">📖</a>
            <h1 class="text-2xl font-bold text-[108px] mb-6">108🧘️</h1>
        @endif

        <button id="darkModeToggle"
            class="mb-6 px-4 py-2 bg-gray-200 dark:bg-gray-700 text-gray-800 dark:text-gray-200 rounded">
            ダークモード切り替え
        </button>

        <div class="space-y-10">
            @foreach ($items as $item)
                <article class="shadow-md rounded-lg p-6 transition-colors duration-300">
                    <h2 class="text-xl font-semibold mb-2 break-words">⏩️{{ $item->post_title }}</h2>
                    <time class="text-sm block mb-4">{{ $item->post_date }}</time>
                    <div class="prose prose-sm max-w-none break-words">
                        {!! $item->post_content !!}
                    </div>
                </article>
            @endforeach
        </div>

        <div class="mt-10">
            {{ $items->links() }}
        </div>
    </div>
    <!-- トップに戻るボタン -->
    <button id="scrollTopBtn"
        class="fixed bottom-6 right-6 hidden bg-gray-600 text-white px-4 py-2 rounded-full shadow-lg hover:bg-gray-700 transition-opacity">
        ▲ 上へ戻る
    </button>
    <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
    <script src="https://cdn.jsdelivr.net/clipboard.js/1.5.13/clipboard.min.js"></script>
    <!-- Prism.jsのコアファイル -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-core.min.js"></script>
    <!-- Prism.jsのオートローダ -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/autoloader/prism-autoloader.min.js"></script>
    <!-- Toolbarプラグインのスクリプト -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/toolbar/prism-toolbar.min.js"></script>
    <!-- その他のプラグインのスクリプト -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/highlight-keywords/prism-highlight-keywords.min.js"></script>

    <script>
        const toggleBtn = document.getElementById('darkModeToggle');
        const prismTheme = document.getElementById('prism-theme');
        const darkThemeHref = 'https://cdn.jsdelivr.net/npm/prismjs@1/themes/prism-tomorrow.css';
        const lightThemeHref = 'https://cdn.jsdelivr.net/npm/prismjs@1/themes/prism.css';

        if (localStorage.getItem('darkMode') === 'true') {
            document.documentElement.classList.add('dark');
            prismTheme.href = darkThemeHref;
        }

        toggleBtn.addEventListener('click', () => {
            const isDark = document.documentElement.classList.toggle('dark');
            prismTheme.href = isDark ? darkThemeHref : lightThemeHref;
            localStorage.setItem('darkMode', isDark);
        });

        document.addEventListener("DOMContentLoaded", () => {
            document.querySelectorAll('pre[class*="lang-"]').forEach(pre => {
                const match = pre.className.match(/lang-(\w+)/);
                if (match) {
                    const lang = match[1];
                    pre.className = `language-${lang} line-numbers`;
                    const code = pre.querySelector('code');
                    if (code) code.className = `language-${lang}`;
                }
            });
            // トップへ戻るボタンの処理
            const scrollTopBtn = document.getElementById("scrollTopBtn");
            window.addEventListener("scroll", () => {
                scrollTopBtn.classList.toggle("hidden", window.scrollY < 200);
            });

            scrollTopBtn.addEventListener("click", () => {
                window.scrollTo({
                    top: 0,
                    behavior: "smooth"
                });
            });
        });

        //全選択ボタンを作成&クラス名付与
        Prism.plugins.toolbar.registerButton('select-code', function(env) {
            var newButton = document.createElement('button');
            newButton.className = 'code-select-btn';
            newButton.innerHTML = 'コードを選択';

            newButton.addEventListener('click', function() {
                if (document.body.createTextRange) { // ms
                    var range = document.body.createTextRange();
                    range.moveToElementText(env.element);
                    range.select();
                } else if (window.getSelection) { // moz, opera, webkit
                    var selection = window.getSelection();
                    var range = document.createRange();
                    range.selectNodeContents(env.element);
                    selection.removeAllRanges();
                    selection.addRange(range);
                }
            });
            return newButton;
        });

        //使用言語表示ボタンを作成&クラス名付与
        Prism.plugins.toolbar.registerButton('show-lang-btn', function(env) {
            var newButton2 = document.createElement('button');
            newButton2.className = 'show-lang-btn';
            newButton2.innerHTML = env.language;
            return newButton2;
        });

        $(function() {
            //各ボタン要素の親要素にクラス名付与
            $('.toolbar-item .code-select-btn').parents('.toolbar-item').addClass('code-select');
        });
    </script>

</body>

</html>

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

```, ;;⏩, あたり, いん, オート, お伝え, お話, クラス, コード, コア, こと, コネクション, コントローラー, コンフィグフォルダ, サイト, シェア, スクリプト, その他, それら, ダーク, データ, データベース, テーブル, ドップ, ヒント, ファイル, フラグ, ブレイド, プレス, ブログデータ, ボタン, モード, モデル, もの, よう, リンク, ローダ, ワード, 付与, 作成, 使用, 処理, 出力, 切り替え, 去年, 取得, 変更, 広告, 感じ, 明日, 明記, 流石, 簡単, 表示, 要素, 言語, 記述, 設定, 選択, 随時,

チャットワークのAPIを使ってみました.プロンプトでほぼ書いています.

2025.07.13

Logging

おはようございます.チャットワークのAPIを使ってみました.プロンプトでほぼ書いたコードになります、チャットGPTの無料版にリファレンスのURLリンクとPHPのクラス化、リターンに$thisで返却出来る所は$thisを使用してスマートにコードを書いてと指示を出しました.

出来上がったコードが下記になります.ソースコードは自分の方でモンキーテスト的に動かしてみましたが、ちゃんと動作するようです.

<?php
class ChatworkClient
{
    private string $apiToken;
    private string $baseUrl = 'https://api.chatwork.com/v2';
    private int $retryCount = 3;
    private int $retryDelay = 1000000; // microseconds

    public function __construct(string $apiToken)
    {
        $this->apiToken = $apiToken;
    }

    public function setRetry(int $count, int $delayMicroseconds): self
    {
        $this->retryCount = $count;
        $this->retryDelay = $delayMicroseconds;
        return $this;
    }

    private function request(string $method, string $path, array $params = []): array
    {
        $attempts = 0;

        while ($attempts < $this->retryCount) {
            $attempts++;

            $ch = curl_init();
            $url = $this->baseUrl . $path;

            if ($method === 'GET' && $params) {
                $url .= '?' . http_build_query($params);
            }

            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

            $headers = ['X-ChatWorkToken: ' . $this->apiToken];

            if (in_array($method, ['POST', 'PUT', 'DELETE'])) {
                curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
                curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params));
                $headers[] = 'Content-Type: application/x-www-form-urlencoded';
            }

            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

            $body = curl_exec($ch);
            $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            $error = curl_error($ch);
            curl_close($ch);

            if ($error) {
                if ($attempts < $this->retryCount) {
                    usleep($this->retryDelay);
                    continue;
                }
                throw new RuntimeException("cURL error after {$attempts} attempts: {$error}");
            }

            if ($status >= 200 && $status < 300) {
                return [
                    'status' => $status,
                    'body' => $body ? json_decode($body, true) : null,
                ];
            }

            if ($attempts < $this->retryCount && $status >= 500) {
                usleep($this->retryDelay);
                continue;
            }

            return [
                'status' => $status,
                'body' => $body ? json_decode($body, true) : null,
            ];
        }

        throw new RuntimeException("Request failed after {$this->retryCount} attempts");
    }

    public function setToken(string $token): self
    {
        $this->apiToken = $token;
        return $this;
    }

    public function me(): array
    {
        return $this->request('GET', '/me');
    }
    public function getMyStatus(): array
    {
        return $this->request('GET', '/my/status');
    }
    public function getMyTasks(array $filters = []): array
    {
        return $this->request('GET', '/my/tasks', $filters);
    }
    public function getContacts(): array
    {
        return $this->request('GET', '/contacts');
    }
    public function getRooms(): array
    {
        return $this->request('GET', '/rooms');
    }
    public function createRoom(array $params): array
    {
        return $this->request('POST', '/rooms', $params);
    }
    public function getRoom(int $roomId): array
    {
        return $this->request('GET', "/rooms/{$roomId}");
    }
    public function updateRoom(int $roomId, array $params): array
    {
        return $this->request('PUT', "/rooms/{$roomId}", $params);
    }
    public function deleteRoom(int $roomId, string $action = 'leave'): array
    {
        return $this->request('DELETE', "/rooms/{$roomId}", ['action_type' => $action]);
    }

    public function getMembers(int $roomId): array
    {
        return $this->request('GET', "/rooms/{$roomId}/members");
    }
    public function updateMembers(int $roomId, array $params): array
    {
        return $this->request('PUT', "/rooms/{$roomId}/members", $params);
    }

    public function getMessages(int $roomId, bool $force = false): array
    {
        return $this->request('GET', "/rooms/{$roomId}/messages", ['force' => $force ? 1 : 0]);
    }

    public function postMessage(int $roomId, string $body, bool $selfUnread = false): self
    {
        $this->request('POST', "/rooms/{$roomId}/messages", ['body' => $body, 'self_unread' => $selfUnread ? 1 : 0]);
        return $this;
    }

    public function markRead(int $roomId): self
    {
        $this->request('PUT', "/rooms/{$roomId}/messages/read");
        return $this;
    }

    public function markUnread(int $roomId): self
    {
        $this->request('PUT', "/rooms/{$roomId}/messages/unread");
        return $this;
    }

    public function getMessage(int $roomId, int $messageId): array
    {
        return $this->request('GET', "/rooms/{$roomId}/messages/{$messageId}");
    }

    public function getRoomTasks(int $roomId, array $filters = []): array
    {
        return $this->request('GET', "/rooms/{$roomId}/tasks", $filters);
    }

    public function createTask(int $roomId, array $params): array
    {
        return $this->request('POST', "/rooms/{$roomId}/tasks", $params);
    }

    public function uploadFile(int $roomId, string $filePath, string $message = ''): array
    {
        if (!file_exists($filePath)) {
            throw new InvalidArgumentException("File not found: {$filePath}");
        }

        $ch = curl_init();
        $url = $this->baseUrl . "/rooms/{$roomId}/files";
        $cfile = curl_file_create($filePath);

        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, ['X-ChatWorkToken: ' . $this->apiToken]);
        curl_setopt($ch, CURLOPT_POSTFIELDS, ['file' => $cfile, 'message' => $message]);

        $body = curl_exec($ch);
        $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);

        if (curl_errno($ch)) {
            throw new RuntimeException(curl_error($ch));
        }

        curl_close($ch);
        return ['status' => $status, 'body' => json_decode($body, true)];
    }
}

人が今回のコードを書いた場合、早い人でも10分ぐらいはコードを書かないといけないと思います、どんなに早くてもそれぐらいの時間は必要だと思いますが、生成AIはこれを数十秒で書ける訳ですから、確実に時間短縮になります.

なので人工知能が使える現場は間違いなく最初のコード出力は人工知能に任せた方が良いです.特に新規案件の土台は生成AIに任せると開発コストは削減出来ます.

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

```, クラス, コード, コスト, これ, スマート, ソース, それ, チャット, テスト, プロンプト, モンキー, よう, リターン, リファレンス, リンク, ワーク, 下記, 人工, 今回, 使用, 出力, 削減, 動作, 土台, 場合, 必要, 指示, 新規, 明日, 時間, 最初, 案件, 無料, 現場, 生成, 知能, 短縮, 確実, 自分, 返却, 開発, 間違い,

FF11オンラインを一時停止しました、やっぱ続かない

2025.07.06

Logging

おはようございます.FF11オンラインを一時停止しました、やっぱ続かないなぁー.ソロでレベルアップが大変なのともう一つは時間が勿体ないと感じるので、どうもゲームのソロは続かない感があります.そもそもRPG系に費やす普通の人のプレイ時間よりもかなり少ないのです.

因みにFF16もFF7リバースもまだ攻略していません、まだまだ時間がかかりそうです.そもそも月に一回ゲームをプレイしたら良い方で休日にゲームに費やす時間よりもボーっとしてたり、コードを買いたり映画観たりしている方が多いです.

あと本を読んだりしていることの方が多くてゲームに時間を避けないのが現状かな?

ゲームをしてなにか得ることもあるのだけども、まぁあんまり無いかな.これがオンラインゲームで仲間がいれば違う可能性がありますが、どちらと言えば仲間の輪に入るタイプではなく、一人の方が楽だなって感じるタイプです.

人生のなかで仕事が無くなればどれぐらい時間が余るのだろうかと思った時、自分の場合、あんま余暇に時間を割いている時間はあんまない気がしています、例えばブログを書いたり創作したりと何かしら手を動かすしたりして何か活動していると思います.

因みに今の学生さんが大人になる頃には仕事は肉体労働しかないじゃないかなって思うぐらい人工知能のIQは上がっています.多分、20年後には仕事の量はいまの半分ぐらいまで少なくなっている可能性があります.昔、学校崩壊というものがありましたが、これからは仕事崩壊という事が中小企業や零細企業から起こる気がしています.

学校崩壊というのは今もあるか分からないけど、教師の話を聞かずに生徒が好き勝手行動するようになることです、それを防ぐ為に今では教員二名体制になっているようです、その大人版が会社でも起こるような気がしています.会社の場合はクビにすれば済むことですけど下手すると倒産するケースも出てきそうです.

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

あと, あんま, いま, オンライン, クビ, ケース, ゲーム, コード, こと, これ, サン, そう, そもそも, それ, ソロ, タイプ, どちら, どれ, なか, なに, プレイ, ブログ, ぼー, もの, よう, リバース, レベルアップ, 一つ, 一時, 下手, 中小, 人工, 人生, 仕事, 仲間, 企業, 休日, 会社, 体制, 余暇, 倒産, 停止, 創作, 労働, 勝手, 半分, 可能, 場合, 大人, 大変, 好き, 学校, 学生, 崩壊, 攻略, 教員, 教師, 明日, 映画, 時間, 普通, 活動, 現状, 生徒, 知能, 肉体, 自分, 行動, 零細,

AIで今後どうなるだろうな.自然言語処理で指示出し出来てきた今日.

2025.07.01

Logging

おはようございます.何だか梅雨明けした休日にGeminiCliでコードを生成しています.仕事ではまだ自分はChatに分からない事を質問するぐらいの事しかしていないのだけども絶対にCliなどで作業すると時間短縮になるのは間違いです(仕事でも導入しているのですが自分は使用していない).

休日に作業するときはコパイロットとGeminiを使用して開発しているのです、どちらも無料版なのだけど自分は無料板で事足りています.

因みにコパイロットとGemini、どちらが優秀かという問いに関しては今のところコパイロットの方が優秀なソースコードを書いてくれるというイメージが強いです.有料版ではカーソルやデビィンなどが優秀らしいけども余裕資金があんま無いので試していない.

お金に余裕があればいろいろと試したいことはあります.例えばグラボ(グラフィックボード)を取り替えて機械学習の学習をローカルで試してみたいなどがあります.

この頃思うのだけど、何かとこの業界は移り変わりが激しいのと新しい技術を学ぶときにたまに技術投資が必要になります.昔はオープンソース的な感じだったけどこのIT業界ビックテックはお金を取り出して来ています.

その中でMETA社?だけがオープンソースでいろいろと提供してくれていてとても有り難いです.それでもやっぱそれを動かす端末の推奨環境という物があるので古いPCだと動かなかったりします.

今後、Llm(大規模言語モデル)は容量が小さくなっていくということとローカル端末で動かすのが当たり前になる時代が来るそうです.

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

あんま, イメージ, オープン, お金, カーソル, グラフィック, グラボ, コード, こと, コパイロット, ソース, そう, それ, たま, デビィン, とき, ところ, どちら, ビックテック, ボード, みたい, モデル, ローカル, 今後, 仕事, 休日, 余裕, 作業, 使用, 優秀, 問い, 学習, 容量, 導入, 当たり前, 必要, 感じ, 技術, 投資, 推奨, 提供, 明け, 明日, 時代, 時間, 有料, 梅雨, 業界, 機械, 無料, 環境, 生成, 短縮, 移り変わり, 端末, 絶対, 自分, 規模, 言語, 資金, 質問, 開発, 間違い,

GeminiCliを使ってみました、まぁまぁ使えるかもしれない.

2025.06.30

Logging

おはようございます.GeminiCliを使ってみました、まぁまぁ使えるかもしれないというのが第一印象です、ただデザイン修正には使えそうにない.デザインを提示すればその通りになおしてくれると思うのだけどテキストだけの指示ではなかなか難しいと感じました.

ディレクトリ配下にあるソースコードを読ます場合は下記のようなプロンプトを一度打つとスムーズに機能追加してくれるので良いですよ.

コードベースを把握して

最初にこの言葉をGeminiに投げることでどんな機能のプログラムコードなのか把握します.これがないと駄目な訳でもないだけどもスムーズに指示出しが出来ます.

特定のコードに対して修正やらを書けたい場合は@(アットマーク)を入力するとソースコードの候補が表示されるので選択をしてプロンプトを指示を出すと良いです.

あとGeminiCliを終了する場合は下記のコマンドを打てば終了します.

/exit

!を入力しls -aなどと入力するとMacの場合は階層のファイル一覧が表示されます的なことも出来ます.

ともあれ、ジェミナイ(ジェミニ)は無料で使用できるトークンも他よりも比較的に多いので自分としてはかなり嬉しいです、休日の個人開発はこれで何とか頑張っていけそうです.

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

あっとまーく, あと, コード, こと, コマンド, これ, ジェミナイ, ジェミニ, スムーズ, ソース, そう, ディレクトリ, テキスト, デザイン, トーク, ファイル, プログラム, プロンプト, ベース, よう, 一覧, 下記, 休日, 使用, 修正, 個人, 候補, 入力, 出し, 印象, 場合, 把握, 指示, 提示, 明日, 最初, 機能, 比較, 無料, 特定, 終了, 自分, 表示, 言葉, 追加, 通り, 選択, 配下, 開発, 階層, 駄目,

金高堂の決済方法(支払い方法)がHPに記載されていないので困って調べました.

2025.06.24

Logging

おはようございます.よく行く本屋さんに金高堂の山田店や朝倉店などがあるのだけども金高堂店のHPがシンプル過ぎてちょっと困っています.お店の地図や電話番号があるのは有り難いのだけども.決済方法が記載されていないのは、ちょっと困っています.

ニコニコ現金でお支払いが多いかとは思うものの、コロナ以降、高知県でも電子マネーなどで決済する方が増えてきている気がしています.

そんな中で一度、Xで決済方法を聞いた事があります、それ以降に決済方法が増えていたら申し訳ないけども金高堂へ行く皆さんが恐らく知りたい情報の上位にある決済方法は何があるかを記載します.

金高堂本店はQRコード決済は、J-coin Pay、電子マネーはiD、QUICPay、Edyです、他の店舗もこちらは共通で使用可能かと思います.当然、現金決済はどの店舗でも出来ます.QRコード決済方法は良くわからない.図書カードやクオカードは使用できます👍️.

調べていくと金高堂工科大学店はちょっと違うのか、こちらが最新の情報で各店舗、共通の話なのか微妙ですが情報を記載します.

ともあれ、金高堂さんがHPを更新して頂いて決済方法も記載していただければ有り難いなと思いました.それほど難しい話ではない気がしますが・・・.自分としての追加要望はpaypay決済を追加して頂きたいです、何せ日本国内でシェア率No1ですからね.お店側からすると決済手数料が気になるところなのかもですが・・・.

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

カード, クオカード, コード, こちら, コロナ, サン, シェア, シンプル, それ, ところ, マネー, 上位, 以降, 使用, 共通, 可能, 図書, 国内, 地図, 大学, 山田, 工科, 店舗, 微妙, 情報, 手数料, 支払い, 方法, 日本, 明日, 更新, 最新, 朝倉, 本屋, 本店, 決済, 現金, 申し訳, 番号, 皆さん, 自分, 要望, 記載, 追加, 金高, 電子, 電話, 高知,

Photo by Victor Dunn on Pexels.com

AIで記事を学習して新たな記事を生み出すにはお金が必要だと思っていたがそうでも.

2025.06.22

Logging

おはようございます.AIで記事を学習して新たな記事を生み出すにはお金が必要だと思っていたがそうでもなくローカルPCでそこら辺に落ちているLlamaモデルを持ってきてチューニングすれば何とかなるじゃねぇという思いに至った.

実はあなたの手元にあるPCと、そこら中に「落ちている」オープンソースのAIモデル、特にLlama 3があれば、十分記事が生成できるんです。


ローカルAI記事生成は、もはや夢物語じゃない

「AIで記事生成」と聞くと、SFのような世界や、大企業だけが使える特権のように感じるかもしれません。しかし、今は違います。オープンソースの強力な言語モデル、特にMetaが公開したLlama 3の登場は、この常識を大きく覆しました。

Llama 3は、その性能の高さにもかかわらず、誰でも無料で利用できるという点が最大の魅力です。さらに、80億パラメータの8Bモデルであれば、最新のゲーミングPCとまではいかなくとも、ある程度の性能を持つPCであれば十分に動作します。これにより、高額なクラウドサービスを利用せずとも、自分のPCでAI記事生成の環境を構築することが現実的になりました。


なぜLlama 3があなたのPCと相性抜群なのか?

Llama 3がローカルPCでの記事生成に適している理由はいくつかあります。

  • 完全無料のオープンソース: 利用に費用がかからないため、予算を気にせずAIを試したり、本格的に導入したりできます。
  • 選べるモデルサイズ: Llama 3には様々なサイズのモデルがあり、PCのスペックに合わせて選べます。特に8Bモデルは、個人利用に最適なバランスを持っています。
  • 活発な開発者コミュニティ: 世界中の開発者がLlama 3を使った新しいツールや効率的なチューニング方法を日々共有しています。困ったときには助けを借りられる心強い味方です。
  • 「量子化」でさらに軽量に: モデルのサイズを大幅に小さくする「量子化」という技術を使えば、より少ないメモリでLlama 3を動かせるようになります。これにより、より多くのPCで利用の道が開けます。

あなたのPCを「記事生成マシン」に変える秘訣

もちろん、いきなりプロのライター並みの記事をAIに書かせるのは難しいかもしれません。しかし、ちょっとした工夫で「何とかなる」レベルの記事生成は十分に可能です。

  1. 少量のデータでファインチューニング: 大量の記事データは不要です。あなたが書きたい記事のテーマやスタイルに合った、質の良い記事を数十〜数百程度集めてLlama 3を学習(ファインチューニング)させれば、その分野に特化した記事生成能力が格段に向上します。
  2. プロンプト(指示文)の工夫: AIへの「指示の出し方」は非常に重要です。具体的で明確なプロンプトを与えることで、チューニングが完璧でなくても、驚くほど質の高い記事が生成できます。これはまるで、優秀なアシスタントに的確な指示を出すようなものです。
  3. 効率的な学習方法の活用: 「LoRA(Low-Rank Adaptation)」のような効率的なファインチューニング手法を使えば、少ないGPUメモリでも短時間でモデルを特定のタスクに最適化できます。

あなたの創造性が、今、AIで加速する

かつては一部の専門家や企業にしか手の届かなかったAIによる記事生成が、今やあなたのPCで実現できる時代になりました。これはまさにAI技術の「民主化」です。

とまぁそういう訳なので何とかしてみますが、ファインチューニングにどれぐらい時間がかかるのかが未知数だったりする.

ファインチューニングPythonコード

以下のPythonコードは、Llama 3モデルをロードし、提供されたテキスト記事でファインチューニング(LoRA使用)を実行し、結果を保存します。 上記の入力値は、このコードに自動的に反映されます。 このコードをPythonファイル(例: `finetune_llama.py`)として保存し、実行してください。

import os
import torch
from datasets import load_dataset
from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig, TrainingArguments, Trainer
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training, TaskType

# GPUの利用可能性を確認
print("GPUが利用可能か確認中...")
if not torch.cuda.is_available():
    print("GPUが見つかりません。Fine-tuningにはGPUが強く推奨されます。")
    # GPUがない場合は、ここでスクリプトを終了するか、CPUモードで続行するか選択できます。
    # exit("GPUがないため終了します。")
else:
    print(f"GPUが利用可能です: {torch.cuda.get_device_name(0)}")

# --- 1. モデルとトークナイザーのロード ---
# Llama 3モデルのパスを指定します。Hugging Faceのモデル名(例: "meta-llama/Llama-3-8B")
# またはローカルにダウンロードしたモデルのパスを指定してください。
MODEL_NAME = "meta-llama/Llama-3-8B" # ユーザーが入力したパスがここに挿入されます

print(f"モデルとトークナイザーをロード中: {MODEL_NAME}")

# 4bit量子化設定 (GPUメモリの節約に役立ちます)
# bnb_4bit_compute_dtypeは、Ampere以降のNVIDIA GPUに推奨されるbfloat16を使用しています。
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_use_double_quant=True,
    bnb_4bit_quant_type="nf4", # NF4 (NormalFloat4) 量子化タイプ
    bnb_4bit_compute_dtype=torch.bfloat16 
)

# トークナイザーをロード
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, trust_remote_code=True)
# Llama 3はデフォルトでbos_tokenを付与しないことがあるため、明示的に追加。
# また、padding_side='right'はLlamaモデルに推奨される設定です。
tokenizer.pad_token = tokenizer.eos_token
tokenizer.padding_side = "right"

# モデルをロードし、量子化設定を適用し、自動的にGPUにマッピングします。
model = AutoModelForCausalLM.from_pretrained(
    MODEL_NAME,
    quantization_config=bnb_config,
    device_map="auto", # 利用可能なデバイス(GPU)に自動的にモデルを分散
    trust_remote_code=True # リモートコードの実行を許可
)
print("モデルロード完了。")

# k-bit学習用にモデルを準備 (PEFTライブラリのため)
# gradient_checkpointingを有効にすることで、メモリ使用量をさらに削減できます。
model.gradient_checkpointing_enable()
model = prepare_model_for_kbit_training(model)
print("k-bit学習用にモデルを準備しました。")

# --- 2. データセットの準備 ---
# あなたのテキスト記事ファイルが格納されているディレクトリを指定します。
# 例: 'your_article_data/' の中に 'article1.txt', 'article2.txt', ... と置かれている場合
DATA_DIR = "./your_article_data/" # ユーザーが入力したパスがここに挿入されます

print(f"データセットをロード中: {DATA_DIR}")

# 'text'形式でデータセットをロードします。指定されたディレクトリ内のすべての.txtファイルを読み込みます。
# 各ファイルが1つのエントリとして扱われます。
try:
    dataset = load_dataset('text', data_files={'train': os.path.join(DATA_DIR, '*.txt')})
    print(f"データセットのサンプル数: {len(dataset['train'])}")
except Exception as e:
    print(f"データセットのロード中にエラーが発生しました。ディレクトリとファイル形式を確認してください: {e}")
    exit("データセットロード失敗。")

# データセットをトークン化する関数
# 長い記事をモデルの最大入力長に分割します。
def tokenize_function(examples):
    # Llama 3の最大入力長は通常8192ですが、お使いのGPUのVRAMに合わせて調整してください。
    # ここでは一般的な値として2048を設定しています。
    max_length = 2048 
    # truncate=Trueで最大長を超えるテキストを切り捨てます。
    return tokenizer(examples["text"], truncation=True, max_length=max_length)

# データセットをトークン化します。
# num_procはCPUコア数に応じて並列処理を行い、処理を高速化します。
tokenized_dataset = dataset.map(
    tokenize_function,
    batched=True,
    num_proc=os.cpu_count(),
    remove_columns=["text"] # 元のテキスト列は学習に不要になるため削除します。
)
print("データセットのトークン化が完了しました。")

# --- 3. PEFT (LoRA) の設定 ---
# LoRA (Low-Rank Adaptation) は、元のモデルの重みをフリーズし、
# 小さなアダプター層を追加して学習させることで、効率的にファインチューニングを行います。
# これにより、GPUメモリの使用量を抑えつつ、高い性能を実現できます。
lora_config = LoraConfig(
    r=16, # LoRAのランク。値を大きくすると表現力が増すが、メモリ消費も増える。
    lora_alpha=32, # LoRAのスケーリング係数。rの2倍程度が推奨されることが多いです。
    target_modules=["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"], # LoRAを適用する層。Llamaモデルで一般的な層。
    bias="none", # バイアスを学習しない設定。
    lora_dropout=0.05, # ドロップアウト率。過学習を防ぐために設定します。
    task_type=TaskType.CAUSAL_LM, # タスクタイプを因果言語モデルに設定。
)

# モデルにLoRAアダプターを追加します。
model = get_peft_model(model, lora_config)
print("モデルにLoRAアダプターを適用しました。")
model.print_trainable_parameters() # 学習可能なパラメータ数を確認します。

# --- 4. 学習の実行 ---
# 学習済みモデルを保存するディレクトリ
OUTPUT_DIR = "./llama3_finetuned_model/" # ユーザーが入力したパスがここに挿入されます

# 学習の設定
training_args = TrainingArguments(
    output_dir=OUTPUT_DIR,
    num_train_epochs=3, # エポック数。データセットのサイズと希望する精度に応じて調整してください。
    per_device_train_batch_size=1, # GPUあたりのバッチサイズ。VRAMが少ない場合は1に設定。
    gradient_accumulation_steps=4, # 勾配を蓄積するステップ数。実質的なバッチサイズは per_device_train_batch_size * gradient_accumulation_steps になります。
    optim="paged_adamw_8bit", # 8bit AdamWオプティマイザを使用し、メモリ効率を向上させます。
    save_steps=500, # 500ステップごとにモデルを保存します。
    logging_steps=100, # 100ステップごとにログを出力します。
    learning_rate=2e-4, # 学習率。
    fp16=True, # 混合精度学習を有効化 (GPUが対応している場合)。VRAM削減と高速化に寄与します。
    max_steps=-1, # num_train_epochsに基づいて学習します。
    group_by_length=True, # 同じ長さのシーケンスをグループ化し、パディングを削減します。
    lr_scheduler_type="cosine", # 学習率スケジューラーのタイプ。
    warmup_ratio=0.03, # ウォームアップ比率。
    report_to="none", # レポート先を指定しない (wandbなどを使用しない場合)。
)

# トレーナーの初期化
# data_collatorは、モデルの入力形式に合わせてデータを整形します。
trainer = Trainer(
    model=model,
    train_dataset=tokenized_dataset["train"],
    args=training_args,
    data_collator=lambda data: {
        'input_ids': torch.stack([f['input_ids'] for f in data]),
        'attention_mask': torch.stack([f['attention_mask'] for f in data]),
        'labels': torch.stack([f['input_ids'] for f in data]), # 因果言語モデルでは、入力自体がラベルとなります。
    },
)

# 学習の開始
print("Fine-tuningを開始します...")
trainer.train()
print("Fine-tuningが完了しました。")

# --- 5. 学習済みモデルの保存 ---
# LoRAアダプターのみを保存します。これにより、ファイルサイズが小さく、効率的に管理できます。
trainer.save_model(OUTPUT_DIR)
print(f"学習済みLoRAアダプターが '{OUTPUT_DIR}' に保存されました。")

# 保存したアダプターを使って推論を行う方法の例 (コメントアウトされています):
# このコードは、ファインチューニング後にモデルをロードして推論を行うための参考例です。
# from peft import PeftModel
#
# # 元のモデルをロード (学習時と同じ量子化設定を使用します)
# base_model = AutoModelForCausalLM.from_pretrained(
#     MODEL_NAME,
#     quantization_config=bnb_config,
#     device_map="auto",
#     trust_remote_code=True
# )
#
# # 保存したLoRAアダプターを元のモデルに結合します。
# peft_model = PeftModel.from_pretrained(base_model, OUTPUT_DIR)
#
# # 推論モードに設定します。
# peft_model.eval()
#
# # テキスト生成の例
# prompt = "ローカルPCでのLlama 3ファインチューニングの利点とは"
# inputs = tokenizer(prompt, return_tensors="pt").to("cuda") # 入力をGPUに移動
#
# with torch.no_grad(): # 勾配計算を無効化し、メモリ使用量を削減
#     outputs = peft_model.generate(
#         **inputs,
#         max_new_tokens=200, # 生成する新しいトークンの最大数
#         do_sample=True, # サンプリングによる生成を有効化
#         top_p=0.9, # Nucleusサンプリングの閾値
#         temperature=0.7, # 生成の多様性を制御する温度
#         eos_token_id=tokenizer.eos_token_id # 終了トークンID
#     )
# print("\n--- 生成されたテキスト ---")
# print(tokenizer.decode(outputs[0], skip_special_tokens=True))

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

```, ;;), )。, アウト, アシスタント, アダプター, あたり, アップ, あなた, いくつ, ウォーム, エポック, エラー, エントリ, オープン, オプティマイザ, お金, クラウドサービス, グループ, クン, ゲーミング, コード, コア, ここ, こと, コミュニティ, コメント, これ, サイズ, サンプリング, サンプル, シーケンス, スクリプト, スケーリング, スケジューラー, スタイル, ステップ, スペック, すべて, ソース, そこら, タイプ, ダウンロード, タスク, ため, チューニング, ツール, データ, データセット, テーマ, ディレクトリ, テキスト, デバイス, デフォルト, トー, トークナイザー, とき, どれ, トレーナー, ドロップ, バイアス, パス, バッチ, パディング, パラメータ, バランス, ファイル, ファイルサイズ, ファインチューニング, ファインチューニングコード, フリーズ, プロ, プロンプト, マシン, マッピング, メモリ, モード, モデル, もの, ユーザー, よう, ライター, ライブラリ, ラベル, ランク, リモート, レベル, レポート, ローカル, ロード, ログ, 一般, 一部, 上記, 不要, 世界, 世界中, 並み, 並列, 予算, 付与, 以下, 以降, 企業, 使い, 使用, 係数, 保存, 個人, 優秀, 入力, 公開, 共有, 具体, 処理, 出力, 分割, 分散, 分野, 初期, 利点, 利用, 制御, 削減, 削除, 創造, 加速, 助け, 効率, 動作, 勾配, 十分, 参考, 反映, 可能, 向上, 味方, 因果, 場合, 多様, 夢物語, 大幅, 大量, 失敗, 学習, 完了, 完全, 完璧, 実現, 実行, 実質, 寄与, 対応, 専門, 導入, 少量, 工夫, 希望, 常識, 強力, 形式, 必要, 思い, 性能, 手元, 手法, 技術, 抜群, 指定, 指示, 挿入, 推奨, 推論, 提供, 整形, 新た, 方法, 日々, 明日, 明確, 明示, 時代, 時間, 最大, 最新, 最適, 有効, 未知数, 本格, 格段, 格納, 構築, 様々, 比率, 民主, 活用, 活発, 消費, 混合, 済み, 温度, 準備, 無効, 無料, 特定, 特権, 現実, 理由, 環境, 生成, 発生, 登場, 的確, 相性, 短時間, 確認, 秘訣, 移動, 程度, 管理, 節約, 精度, 終了, 結合, 結果, 続行, 能力, 自体, 自分, 自動的, 蓄積, 表現, 言語, 計算, 記事, 設定, 許可, 調整, 費用, 軽量, 追加, 通常, 適用, 選択, 重み, 重要, 量子, 開始, 開発, 関数, 閾値, 非常, 高速, 高額, 魅力,

x.gdのURL短縮機能を利用するためのコードを作りましたので、お裾分け.

2025.06.08

Logging

おはようございます.x.gdのURL短縮機能を利用するためのコードを作りましたので、お裾分けです、コードは下記になります.ドキュメントをぱぱっと見て作った感じなので不具合などが潜んでいるかもしれないけど恐らく大丈夫そうという事で木曜日の早朝にXでコードをシェアした形になります.

なお、x.gdからAPIの発行を行う作業をお忘れなく(こちらからAPIを発行).

因みに自分はt2t.jpというドメインを私有していて、こちらで自分専用の短縮URLを発行出来るようにしています.この頃は自分が作った短縮URLをあまり使ってないので、こちらをサービス化しようかな等と考えていたりします.

因みにどうするかは未定ですけどね.もしみんなが使用出来るようにしたら、このサイトでも告知します.

<?php
require 'config.php';

class ShortUrl
{

    public $apiKey = null;
    public $endPoint = 'https://xgd.io/V1/shorten?';

    public function __construct($api_key = null)
    {
        $this->apiKey = $api_key;
        return $this;
    }

    public function getShortUrl($url = null, $shortid = null, $analytics = true, $filterbots = false)
    {
        if (empty($this->apiKey)) {
            return json_encode(['status' => 0, 'message' => 'api-keyがありません']);
        }
        if (empty($url)) {
            return json_encode(['status' => 0, 'message' => 'URLがありません']);
        }

        if (isset($url) && !preg_match('/^http[s]?:\/\/(www\.)?/', $url)) {
            return json_encode(['status' => 0, 'message' => 'URLが無効です']);
        }

        if (isset($shortid) && !preg_match('/^([0-9a-zA-Z_]{6,15})$/', $shortid)) {
            return json_encode(['status' => 0, 'message' => '短縮コードが無効です']);
        }

        if (!is_bool($analytics)) {
            $analytics = true;
        }

        if (!is_bool($filterbots)) {
            $filterbots = false;
        }

        $parameter = [
            'key' => $this->apiKey,
            'url' => $url,
            'shortid' => $shortid,
            'analytics' => $analytics ? 'true' : 'false',
            'filterbots' => $filterbots ? 'true' : 'false'
        ];

        $response = @file_get_contents($this->endPoint . http_build_query($parameter));
        return $response;
    }
}

if($argv[1]){
    $url = $argv[1];
    $shortid = isset($argv[2]) ? $argv[2] : null;
    $analytics = isset($argv[3]) && $argv[3] === 'true' ? true : false;
    $filterbots = isset($argv[4]) && $argv[4] === 'true' ? true : false;   
    echo (new ShortUrl(APIKEY))->getShortUrl($url, $shortid, $analytics, $filterbots);
}

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

```, お裾分け, コード, こちら, サービス, サイト, シェア, そう, ため, ドキュメント, ドメイン, みんな, よう, 下記, 不具合, 作業, 使用, 利用, 告知, 大丈夫, 専用, 感じ, 早朝, 明日, 木曜日, 未定, 機能, 無効, 発行, 短縮, 私有, 自分,

Devin(でびん)とかいう生成AIが凄いらしいのは知っていたけど知らんけど

2025.06.06

Logging

おはようございます.Devin(でびん)とかいう生成AIが凄いらしいのは知っていたけどついに自分が勤めている会社でもDevinを導入したみたいです.ひとつのリポジトリはDevinさんがほぼコードを書いていて何だか悲しい気持ちになりました?.

逆に言えばこういうDevinみたいな高性能な生成AIを使えば自分一人でも高機能なwebサービスが出来るだなって言う思いがあります、でも高機能なサービスが作れたとしてもそれを営業するノウハウ等がないので自分には結局意味がないのではないかと思います.

Devinさんに負けない高度なコードを書いても生産性では確実に劣っている気がします、ものの数秒で数千行のコードを書くことは人は出来そうにないので、正直なところDevinの性能が上がったら本当に必要なエンジニアは少なくなるでしょうね.

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

エンジニア, コード, サービス, すひとつ, ところ, ノウハウ, びん, リポジトリ, 会社, 性能, 悲しい気持ち, 意味, 数千行, 数秒, , 生成, 生産性, 自分, 自分一人, 高性能,

Photo by Adil on Pexels.com

AIでレコメンド記事が表示させるロジックを作りました.#機械学習って

2025.06.04

Logging

おはようございます.AIでレコメンド記事が表示させるロジックを作りました、前からそのような事を考えていたのですが、あまり機械学習のことを分かっていなかったのですが、以前、地域の商品券で「実務で役立つPython機械学習入門」を購入していたのを先日の休みにパラパラと捲っていたら、これだったらなんか出来そうだなって思いたち.

昨日の休みに生成AIともに作りました.生成AIが出力したコードに対して再度指示を出したり自分で直したりして上手く処理される形に落ち着きました.

Pythonコードは昨日の記事がある程度役に立つと思います、あのコードを元にブラッシュアップ(改善)した形になります.

自分で機械学習のことに手を出すことになるとは思っていなかったけど、これからはPythonの事もたまに試していこうと思います.

因みに過去記事を参照してもらったら分かるかもですが何度か機械学習にトライして挫折した経緯がありますが、今回は生成AIという物があるので生成AIよって噛み砕いた言葉とコードで何とか自分でも初級か中級ぐらいのことは出来そうな気もします.

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

コード, ブラッシュアップ, レコメンド記事, ロジック, 中級, 休み, 何度か機械学習, , 再度指示, 初級, 実務, , 改善, 機械学習, 機械学習入門, 生成, 生成とも, 程度役, 経緯, 言葉,

AIレコメンド機能を乗せれるかもしれない.VPSだから微妙 #TFIDFベクトライザ

2025.06.03

Logging

おはようございます.AIレコメンド機能を乗せれるかもしれないけど無理かもしれないということで、まだ試してはいないのだけど機械学習で学習済みのモデルをVPSに乗せ動かすことが出来れば、AIレコメンド機能が出来そうです.

いまある記事のデータのタグ付け部分をTF-IDFベクトライザの学習させれば案外簡単に学習させることが出来そうなので生成AIにコードを書いてもらいました.

尚、この方法はECサイトの商品のレコメンド機能にも同じような感じでデータを与えるとレコメンドしてくれたりします.

最後にPythonコードを貼っときます.VPSサーバで再学習できれば良いだけども難しいかもしれない、、、.

import pickle
import os

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
import pandas as pd

# モデル保存ファイル名
MODEL_PATH = "tfidf_vectorizer.pkl"  # TfidfVectorizer
DATA_PATH = "article_tags.pkl"       # 記事IDとタグ

# 類似度モデル構築(再学習対応)
def build_similarity_model(article_tags_input, save_model=True, retrain=False):
    # 再学習時は既存データを読み込んで結合する
    if retrain and os.path.exists(DATA_PATH):
        with open(DATA_PATH, "rb") as f:
            existing_data = pickle.load(f)
        existing_data.update(article_tags_input)  # 新しいデータを追加
        article_tags_input = existing_data

    article_ids = list(article_tags_input.keys())
    processed_corpus = [" ".join(tags) for tags in article_tags_input.values()]

    # 再学習またはモデル未保存時に新たにモデルを学習・保存
    if retrain or not os.path.exists(MODEL_PATH):
        vectorizer = TfidfVectorizer()
        tfidf_matrix = vectorizer.fit_transform(processed_corpus)

        if save_model:
            with open(MODEL_PATH, "wb") as f:
                pickle.dump(vectorizer, f)  # ← ここでモデルを保存
            with open(DATA_PATH, "wb") as f:
                pickle.dump(article_tags_input, f)  # ← ここで元データを保存

    else:
        # 保存済みモデルを使って変換する
        with open(MODEL_PATH, "rb") as f:
            vectorizer = pickle.load(f)
        tfidf_matrix = vectorizer.transform(processed_corpus)

    cosine_sim_matrix = cosine_similarity(tfidf_matrix)
    cosine_sim_df = pd.DataFrame(cosine_sim_matrix, index=article_ids, columns=article_ids)

    return cosine_sim_df, article_ids

# 類似記事を取得する関数
def get_recommendations(article_title, similarity_matrix, articles_map, top_n=3):
    if article_title not in articles_map:
        print(f"エラー: 記事 '{article_title}' が見つかりません。")
        return []

    sim_scores = list(enumerate(similarity_matrix[article_title]))
    sim_scores = sorted(sim_scores, key=lambda x: x[1], reverse=True)

    recommended_articles = []
    for i, score in sim_scores:
        if articles_map[i] != article_title and len(recommended_articles) < top_n:
            recommended_articles.append((articles_map[i], score))
        if len(recommended_articles) >= top_n:
            break

    return recommended_articles

# 入力記事データ ( 例 )
article_tags_input = {
    "記事1": ["Python", "機械学習", "データサイエンス"],
    "記事2": ["Python", "Web開発", "Django"],
    "記事3": ["機械学習", "自然言語処理"],
    "記事4": ["データサイエンス", "統計学"],
    "記事5": ["Python", "データサイエンス", "可視化"]
}

# 類似度モデル構築 + モデル保存 ( 初回学習 )
cosine_sim_df, article_ids = build_similarity_model(article_tags_input)

# 使用例
target_article = "記事1"
recommendations = get_recommendations(target_article, cosine_sim_df, article_ids, top_n=2)
print(f"\n「{target_article}」へのおすすめ記事 ( 上位2件 ):")
for article, score in recommendations:
    print(f"- {article} (類似度: {score:.4f})")

# 新しい記事を追加して再学習
new_article_id = "記事6"
new_article_tags = ["Python", "統計学"]
article_tags_input = {new_article_id: new_article_tags}

# 再構築+再学習
cosine_sim_df, article_ids = build_similarity_model(article_tags_input, retrain=True)
target_article = new_article_id
recommendations = get_recommendations(target_article, cosine_sim_df, article_ids, top_n=2)
print(f"\n「{target_article}」へのおすすめ記事 ( 上位2件 ):")
for article, score in recommendations:
    print(f"- {article} (類似度: {score:.4f})")

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

エラー, コード, サーバ, タグ, データサイエンス, ベクトライザ, レコメンド機能, 上位件, 初回学習, 学習, 学習済み, 既存データ, 最後, 機械学習, 統計学, 自然言語処理, 良いだけ, 関数, 類似度, 類似度モデル構築,

デジタルアドレスAPIのコードを書いてみました.書いたのは

2025.05.30

Logging

おはようございます.デジタルアドレスAPIのコードを書いてみました.書いたのは生成AIだけど一度で上手く正しいコードが生成出来たわけではなくて二、三回の指示出しを行って下記のコードが生成されました.

デジタルアドレスのAPIを使用するには企業もしくは個人事業者で屋号を登録されている方でないとAPIのアカウント登録は今のところ出来ないので、自分はリファレンスと生成AIが出力したコードを見て恐らく正しく処理されるだろうと思ったのでgist.githubに公開しました.

尚、引数にIPアドレスを渡さないといけない所があるけれど、これはサーバーのIPアドレスになります.


<?php

class JapanPostAPIClient
{
    private string $clientId;
    private string $secretKey;
    private string $clientIp;
    private ?string $accessToken = null;
    private ?array $lastResponse = null;

    public function __construct(string $clientId, string $secretKey, string $clientIp)
    {
        $this->clientId = $clientId;
        $this->secretKey = $secretKey;
        $this->clientIp = $clientIp;
    }

    public function authenticate(): self
    {
        $url = 'https://api.da.pf.japanpost.jp/api/v1/j/token';
        $data = json_encode([
            'grant_type' => 'client_credentials',
            'client_id' => $this->clientId,
            'secret_key' => $this->secretKey
        ]);

        $headers = [
            "Content-Type: application/json",
            "x-forwarded-for: {$this->clientIp}"
        ];

        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

        $response = curl_exec($ch);
        $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        if ($httpcode !== 200) {
            throw new Exception("Token request failed with status {$httpcode}: {$response}");
        }

        $responseData = json_decode($response, true);
        $this->accessToken = $responseData['token'] ?? null;
        $this->lastResponse = $responseData;

        return $this;
    }

    public function searchCode(string $searchCode, array $params = []): self
    {
        if (!$this->accessToken) {
            throw new Exception("Access token is not set. Please call authenticate() first.");
        }

        $defaultParams = [
            'page' => 1,
            'limit' => 10,
            'choikitype' => 1,
            'searchtype' => 1
        ];

        $queryParams = http_build_query(array_merge($defaultParams, $params));
        $url = "https://api.da.pf.japanpost.jp/api/v1/searchcode/{$searchCode}?{$queryParams}";

        $headers = [
            "Authorization: Bearer {$this->accessToken}",
            "Accept: application/json"
        ];

        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        if ($httpCode !== 200) {
            throw new Exception("Search request failed with status {$httpCode}: {$response}");
        }

        $this->lastResponse = json_decode($response, true);
        return $this;
    }

    public function getJson(): string
    {
        return json_encode($this->lastResponse, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
    }

    public function getArray(): ?array
    {
        return $this->lastResponse;
    }
}

// 使い方の例:
// $client = new JapanPostAPIClient('YOUR_CLIENT_ID', 'YOUR_SECRET_KEY', 'IPアドレス.xxx.xxx.xxx');
// echo $client->authenticate()->searchCode('1000001')->getJson();

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

```, アカウント登録, アドレス, コード, サーバー, デジタルアドレス, リファレンス, 下記, 企業, 使い方, , 個人事業者, 屋号, 引数, , 指示出し, 正しいコード, 生成, 自分,

いにしえのサイトの変数の命名を直しました.大部分を生成AIに直してもらった.

2025.05.29

Logging

おはようございます.いにしえのサイトの変数の命名を直しました.大部分を生成AIに直してもらいましたがまだ残ってはいます.因みにいにしえのサイトというのは、このサイトのことを指しています.

生成AIに「変数と関数の命名を直して」と頼むとプログラミングのコードはそのままで変数の命名や関数の命名を直してくれます.

その方法でいにしえのサイトのコードを書き換えて「駆け出し感」は少し消えている感じがします.

命名もそうですがプログラミングには命名規則という物があります.自分はそんな事を知らずにコードを書いてきたのですが、いまやっと命名規則などをちゃんとした職場にいます.

なのですが、今までのなんか癖が抜けきれていない部分があり、ちゃんとしたコードを昔から書いていたらという後悔があります.

最後に命名規則というのは何なのかという人のために命名規則をわかりやすく書いているQiitaの記事を載せておきます.

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

いにしえ, コード, プログラミング, 命名, 命名規則, 変数, 大部分, 少し, 後悔, 方法, , 最後, , 生成, , 職場, 自分, 部分, 関数, 駆け出し感,

トランプ大統領の2025年からの任期をカウントするJSコードです.

2025.05.24

Logging

おはようございます.トランプ大統領の2025年からの任期をカウントするコードです.まだまだトランプ政権は始まったばかりなんですが、もう自分としてはあんま嬉しい気持ちはしていません.いま儲かっているのはデイトレードを行っている人達かも知れないです.

// トランプ大統領の2025年からの任期をカウント
const termStart = new Date('2025-01-20');
const termEnd = new Date('2029-01-20');
const today = new Date();

const totalTermDays = Math.floor((termEnd - termStart) / (1000 * 60 * 60 * 24));

if (today < termStart) {
  console.log('任期はまだ始まっていません。');
} else if (today > termEnd) {
  const servedDays = totalTermDays;
  console.log('任期は終了しています。');
  console.log(`トランプ大統領は ${servedDays} 日間、在任しました。`);
} else {
  const servedDays = Math.floor((today - termStart) / (1000 * 60 * 60 * 24));
  const remainingDays = Math.floor((termEnd - today) / (1000 * 60 * 60 * 24));
  console.log(`任期中です。(${today.toISOString().split('T')[0]} 現在)`);
  console.log(`在任日数: ${servedDays} 日`);
  console.log(`残り日数: ${remainingDays} 日`);
  console.log(`任期全体の日数: ${totalTermDays} 日`);
}

秒でウクライナとロシアの戦争を止めると言っていたのに、泥沼化しています.トランプさんになってからアメリカは前より酷くなったのではとか思っていますが、アメリカ国民は満足しているのでしょうか🤔.

知らないけれど、結構たいへんそうな気がしています.

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

```, アメリカ, アメリカ国民, あんま嬉しい気持ち, ウクライナ, カウント, コード, ディトレード, トランプ大統領, トランプ政権, ロシア, 任期, 任期中, 任期全体, 在任日数, 戦争, 日数, , 泥沼化, ,

見るだけでわかる!! 英語ピクト図鑑ってのを購入してみて

2025.05.23

Logging

おはようございます.見るだけでわかる!! 英語ピクト図鑑ってのを購入してみて思ったことを書いていきます.まず、図解は分かりやすいのですが自動詞や前置詞、他動詞とかいう用語が出てきてそこが知らないというか、もう全忘れしている自分にとっては難解でした.

難解でしたが生成AIが解説してくれたので何とかなりそうで、今回はなんか今までよりは続きそうな予感がします.

因みに英語が全く分からないわけでもないのだけど何となく理解できるけど、日本語にちゃんとした和訳が出来ないレベルなんですね、何を言わんとするかは分かるので頭の中で分かると言えば良いのかな.

そんな理由でちゃんとした訳が出来ないや基礎が全く出来ていないまま、生きてきたので結構コードを書くのが大変です.今でもどう書けばよいのやらと不安だらけ…そう言っても命名はしないといけないので命名しているけども自信がないですよね.

この頃は生成AIだよりになっている部分もあり前よりは命名が良くなってきている気がしています.

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

コード, 予感, 他動詞, 命名, 和訳, 図解, 基礎, 日本語, , 理由, 生成, 用語, 置詞, 自信, 自動詞, 英語, 英語ピクト図鑑, , 部分, ,

推し記事をXに頻度にポストする「ぷらぐいん」を作りました.

2025.05.20

Logging

おはようございます.昨日から自分の推し記事をXに頻度にポストする「ぷらぐいん」を作りました.コードは使い回し的な要素が多いのですが、上手く動いていたりしてアクセス数も普段より微量に多かったりして作ったのは良かったと思っています.

この頃、生成AIがコードを書いてくれるので、以前よりも早くコードが書けている気がしています.そのままでは使用できない時もあるけれど、良い感じです.ただ、無料枠のGeminiはテストコードやGitHubのgithub Actionなんかを作るのが難しい.

ここらへんは無料枠なので仕方がないかなって思っています.

生成AIが進化していくと人はいらない、ただAIの苦手な部分もあってUIやUXはどうも苦手な部分みたいですね.でもこれも時間の問題なのかも知れないなって思います、何故かというと人の意図を汲み取るのは今からいろいろな人が生成AIを使用する中でデータが蓄積されそれを元に改善されていくと思うので.

そのうち、生成AIとエンジニアの二人三脚でアプリやWEBサービス、ソフトウェアを個人が作り出す時代になるでしょうけど、アプリの飽和が起こりそうな気もしています.

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

アプリ, うち, エンジニア, コード, ここらへん, ソフトウェア, データ, テストコード, プラグイン, 二人三脚, , 微量, 意図, 推し記事, 普段, 無料枠, 生成, 要素, 頻度, 飽和,

配列で返して変数で受け取る事を分割代入というであってる.

2025.05.16

Logging

おはようございます.配列で返して変数で受け取る事を分割代入という…どんなコードか具体的に書いたのが下記です.

<?php

function getArray(): array {
  return [10, 20];
}

[$x, $y] = getArray();

echo "x: " . $x . "\n";
echo "y: " . $y . "\n";

// 要素数が合わない場合
function getMoreArray(): array {
  return [100, 200, 300];
}

[$p, $q] = getMoreArray(); // $q には 200 が代入され、300 は無視される
echo "p: " . $p . "\n";
echo "q: " . $q . "\n";

[$m, , $n] = getMoreArray(); // カンマで要素をスキップ
echo "m: " . $m . "\n";
echo "n: " . $n . "\n";

// 連想配列のようなキー指定も可能 (PHP 7.1以降)
function getAssocArray(): array {
  return ['name' => '太郎', 'age' => 30];
}

['name' => $userName, 'age' => $userAge] = getAssocArray();

echo "名前: " . $userName . "\n";
echo "年齢: " . $userAge . "\n";

?>

最初、凄くこれに違和感を覚えたのを覚えています.理由はカッコカッコで括ってあるから、なんだか配列を連想するのですよね.とても便利ですけどね、因みにPHP言語でも比較的に新しいバージョンだったら使用できます.

尚、PHPバージョン7.1以下だった場合はlistを使用すると同じようなことになります.

<?php

function getArray(): array {
  return [10, 20];
}

list($x, $y) = getArray();

echo "x: " . $x . "\n";
echo "y: " . $y . "\n";

// 要素数が合わない場合
function getMoreArray(): array {
  return [100, 200, 300];
}

list($p, $q) = getMoreArray(); // $q には 200 が代入され、300 は無視される
echo "p: " . $p . "\n";
echo "q: " . $q . "\n";

list($m, , $n) = getMoreArray(); // カンマで要素をスキップ
echo "m: " . $m . "\n";
echo "n: " . $n . "\n";

?>

それにしても分割代入って呼び名、直ぐに忘れそう・・・.

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

```, $代, カッコカッコ, カンマ, キー指定, コード, スキップ, バージョン以下, 分割代, 分割代入, 呼び名, 変数, 太郎, 新しいバージョン, 最初, 要素, 言語, 連想配列, 違和感, 配列,

Photo by Amy Chandra on Pexels.com

tMDbのAPIを使用して今まで観た映画をリスト化してみましたよ.

2025.04.27

Logging

おはようございます.tMDbのAPIを使用して今まで観た映画をリスト化してみましたよ.sqliteの構造は下記になります.idはbigintと記載していますが、AUTO_INCREMENTの間違いです🐼.

Xにも呟きましたがAPIを使用して何かするのはこの頃飽きてきて触らなかったのですが、たまには触れてみようとコードを書いているうちに簡単に作れるようになってしまって少々物足りなさを感じています.

次回はAPIを使う側ではなくて作る側になろうと思っています.GW期間になると思いますが600円のレンタルサーバーのフリードメインを使ってツマラナイAPIみたいな失笑系を作ってみます.

なお、ソースコードの解説がなくてすみません、このソースコードを生成AIに投げてどのような処理か説明して言えば恐らく正解を教えてくれます.

明日へ続く

#真相をお話します.
少年と犬
Flow
curl -sS https://getcomposer.org/installer | php
composer require guzzlehttp/guzzle
composer require illuminate/database
<?php
require_once 'config.php';
require_once 'vendor/autoload.php';
use Illuminate\Database\Capsule\Manager as Capsule;
use Illuminate\Database\Capsule\Manager as DB;

class MovieList
{
    public $result = '';
    public $imgBasicUrl = 'https://image.tmdb.org/t/p/w500';
    public $filePath = FILEPATH_DIR_;
    public function __construct($filePath='')
    {
        $filePath = $filePath?$filePath:$this->filePath;
        if (!file_exists($filePath.'/movie-list.db')) {
            exit;
        }        
        $capsule = new Capsule();

        $capsule->addConnection([
            'driver'   => 'sqlite',
            'database' => $filePath.'/movie-list.db',
            'prefix'   => '',
        ]);

        $capsule->setAsGlobal();
        $capsule->bootEloquent();
    }

    public function getMovieList(string $q): void
    {
        $client = new \GuzzleHttp\Client();

        $response = $client->request('GET', 'https://api.themoviedb.org/3/search/multi?query=' . $q . '&include_adult=false&language=ja-JP&page=1', [
            'headers' => [
                'Authorization' => 'Bearer ' . API_KEY,
                'accept' => 'application/json',
            ],
        ]);
        $this->result = $response->getBody();
    }

    public function getResult(): void
    {
        $data = DB::table('list')->get();
        $lists = [];
        foreach ($data as $key => $value) {
           $result = unserialize($value->value);
            if(isset($result?->media_type) && $result->media_type == 'movie'){
                $lists[] = [
                    'id'=>$data[$key]->id,
                    'title'=>$result->title,
                    'img'=>$this->imgBasicUrl . $result->poster_path,
                ];
            }
        }
        print json_encode($lists);
    }

    public function saveCsvlist(): void
    {
        $fileData = explode("\n",file_get_contents('movie-list.csv'));
        $fileData = array_reverse($fileData);
        foreach($fileData as $line)
        {
            foreach(explode(',',$line) as $data){
                $q = urlencode($data);
                $movieList = new MovieList();
                $movieList->getMovieList($q);
                foreach((json_decode($movieList->result))?->results as $result){
                    DB::table('list')->insert([
                        'value' => serialize($result)
                    ]);
                }
            }
        }        
    }

    public function delete($id): void
    {
        
        DB::table('list')->where('id', '=', $id)->delete();
        print json_encode(['res'=>'true']);
    }

}
//(new MovieList())->saveCsvlist();
if($_SERVER['REQUEST_METHOD'] == 'POST')
{
    if(!isset($_POST['id'])){
        (new MovieList())->getResult();
    }else{
        //(new MovieList())->delete($_POST['id']);
    }   
}

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

```, コード, ソースコード, ツマラナイ, フリードメイン, レンタルサーバー, , , 処理, 失笑系, 少年, 構造, 次回, 正解, , 生成, 真相,

404画像をそのまま残しておくとSEOに影響があるのでどうするか?#php

2025.04.23

Logging

おはようございます.404画像をそのまま残しておくとSEOに影響があるのでどうするか?php の場合、下記のコードで404ページに飛んでいるかどうかの確認は出来る.でも毎回、確認しているとページを表示している時に遅延が発生してとても良い処理とは言えないなのでDBに画像あるなしが確認できるテーブルを作ります.

<?php
class HttpCodeChecker
{

    public function getHttpStatusCode(string $url): int|false
    {
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_NOBODY, true);
        curl_exec($ch);

        if (curl_errno($ch)) {
            curl_close($ch);
            return false; // エラーがあった場合
        }

        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        return $httpCode;
    }
}

画像のステータス確認できるコードで定期的にページをクロールしてステータスをテーブルに保存(更新)することにより404画像によってSEOに影響を与えない作りになります.

他にも方法はあるけど、レンタルサーバーではこの方法がベストプラクティスな解なのかもしれない.クロールするのが出来ない場合は一度、画像URLをJsonデータで出力してフロントエンド側で画像有無を判断し存在するものだけを表示するという案もあるのだけども、今のSEO的にはあまりオススメはしない.

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

```, エラー, コード, ステータス, データ, テーブル, フロントエンド側, ベストプラクティス, レンタルサーバー, 下記, 保存, 影響, 方法, , 毎回, 画像, 画像有無, 確認, 良い処理, 遅延,

Camera+ recipe? ? scene: Cloudy ? crop: Golden ? effect: Redscale (77%) ? border: Round White

Reactでパスワード生成にバグがあって数値、記号が確実に入らなかったので.

2025.04.22

Logging

おはようございます.Reactでパスワード生成にバグがあって数値、記号が確実に入らなかったのでその修正を先日行いました.そういやそうだなってソースコードを見返して思った次第です…

修正したコードはこちらになります.その話とは別にVScodeにもAI補助が付いてから自分も生成AIと言う物を個人開発するときに使用するようになっただけど…

import RingLoader from "react-spinners/RingLoader";
import { useState } from "react";
import "./App.css";

function PasswordTmp() {
  const [passwordLength, setPasswordLength] = useState(8);
  const [password, setPassword] = useState("");
  const [includeSymbols, setIncludeSymbols] = useState(false);
  const [includeNumbers, setIncludeNumbers] = useState(false);

  function makePassword(passwordLength, includeSymbols, includeNumbers) {
    const lowercase = "abcdefghijklmnopqrstuvwxyz";
    const uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    const numbers = "0123456789";
    const symbols = "!@#$%^&*()_+[]{}|;:,.<>?";
    let characters = lowercase + uppercase; // 文字のセットを初期化
    if (includeNumbers) {
      characters += numbers; // 数字を追加
    }
    if (includeSymbols) {
      characters += symbols; // 記号を追加
    }
    let result = remakePassword(characters,includeNumbers,includeSymbols);
    setPassword(result);
  }

  function remakePassword(characters,includeNumbers,includeSymbols){
    let passwords = "";
    let NumbersChecking = true;
    let SymbolsChecking = true;
    for (let i = 0; i < passwordLength; i++) {
      const randomIndex = Math.floor(Math.random() * characters.length);
      passwords += characters[randomIndex]; // ランダムな文字を選択
    }
    if (includeNumbers) {
      NumbersChecking = passwords.match(/[0-9]/g) ? true : false;
    }
    if (includeSymbols) {
      SymbolsChecking = passwords.match(/[\!@#\$%\^&\*\(\)_\+\[\]\{\}\|;:\,\.<>\?]/g) ? true :false;
    }
    return NumbersChecking && SymbolsChecking?passwords:remakePassword(characters,includeNumbers,includeSymbols);
  }


  return (
    <>
      <div>
        <h1>パスワード生成</h1>
        <p>
          <input
            type="number"
            value={passwordLength}
            placeholder="パスワードの長さ"
            max={99}
            min={3}
            onChange={(e) => setPasswordLength(e.target.value)}
          />
        </p>
        <p>
          <input id={'Symbols'}
            type="checkbox"
            value={1}
            checked={includeSymbols}
            onChange={(e) => setIncludeSymbols(e.target.checked)}
          />
          <label for={'Symbols'}>記号を含める</label>
        </p>
        <p>
          <input id={'Numbers'}
            type="checkbox"
            value={1}
            checked={includeNumbers}
            onChange={(e) => setIncludeNumbers(e.target.checked)}
          />
          <label for={'Numbers'}>数字を含める</label>
        </p>
        <button
          className="btn"
          onClick={() =>
            makePassword(passwordLength, includeSymbols, includeNumbers)
          }
        >
          パスワードを生成
        </button>
        <button
          className="btn"
          onClick={() => navigator.clipboard.writeText(password)}
        >
          パスワードをコピー
        </button>
        <p>生成されたパスワード: {password}</p>
        <p>パスワードの長さ: {passwordLength}</p>
        <p>記号を含める: {includeSymbols ? "はい" : "いいえ"}</p>
        <p>数字を含める: {includeNumbers ? "はい" : "いいえ"}</p>
      </div>
    </>
  );
}

export default PasswordTmp;

この頃、補完機能がとても「うざったく」思う時と「ありがとう」と思うときが存在していてなんとも言えない.特にウザって思うときは自分が望んでいないコードが出てきた時は正直困る.コードを直打ちしないといけないので今までの補完機能がやはり良いなと思います.

自分としては生成AIの補完機能をOFFに出来る機能がほしいところ、それがあればとてもコードを書くのは快適ですねー.あるのかなぁー🤔調べてみます.

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

コード, コピー, セット, ソースコード, バグ, パスワード, パスワード生成, ほしいところ, ランダム, 修正, 初期化, 数値, 数字, 文字, 次第, 生成, 補助, 補完機能, 記号, 選択,

Photo by Adam Fejes on Pexels.com

動画を見て時代だなって思った瞬間.自分、時代って言葉を使いすぎw.

2025.04.19

Logging

おはようございます.以前、少し書いたのですが教育の場ではデジタル機器を使用してきていますよね.もうこんな田舎でもノートパソコンやタブレットを小学校から使用しています.そんな子供達が大人になったとき、社会はどう変わるのだろうかとこの頃おもうことがあります.

あと20年後といえば自分は仕事を退職して年金暮らしているような年代になるのかと思うですが、その想像が全くというほど想像できない.20年になるまえに恐らく南海トラフ巨大地震も起きていて大きく日本も変わった社会になっているのではないだろうかと思っています.

多分だけど自分はあと20年後も働いているような気がします.その頃にはプログラマーという職ではなくAIの書いたコードを手直しする職として働いている可能性が高いですね.

10年後は何となく今の延長線上にある気がするのだけど、20年後は今の延長線上では予測できない社会になっていそうです.

100年時代と言われている今日(こんにち)ですが、自分たちが老人と言われる時代は老化を止められる時代にもなってくるのだというのが自分の見解です.もしかするとブレイクスルーが起こり老化を止めるどころか、細胞を若返ることが出来るかも知れない.

そういう時代を目にすることが出来ると思うとワクワクしかないですね.

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

コード, タブレット, デジタル機器, ノートパソコン, ブレイクスルー, プログラマー, まえ, 南海トラフ巨大地震, 小学校, 年代, 年金, 延長線上, 想像, 教育, 田舎, 細胞, 老人, 老化, , 見解,

一人でスーパーマリオワールドを3D化したツワモノ現る.超再現度高いですね.

2025.03.23

Logging

おはようございます.一人でスーパーマリオワールドを3D化したツワモノ(Bobby Ivar)現る.これを見たときニヤけてしまったぐらい、素人目でもこれ一人で作るの凄すぎだよと.

あの懐かしいスーパーマリオワールドの2Dをここまで忠実に3Dに落とし込むことが出来る人はいない.熱烈なファンっていうのは本当に凄いですね.熱量がないとここまで打ち込めないと思います.

このスーパーマリオワールドを作った人(Bobby Ivar)を任天堂さんがどうするか、自分だったら彼の作ったコードを引き継いで開発します.これぐらい忠実に3D再現しているわけだからこれを駄目だと切り捨てるのは、勿体ないなって思います.

尚、2Dから3Dにするために開発ツールを自作したりモンスターのAI(アルゴリズム)も新たに構築したそうです.そしてドットテクスチャも自らポチポチと制作したそうです.

マリオファンから称賛の嵐だとか.

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

アルゴリズム, コード, スーパーマリオワールド, ツワモノ, ドットテクスチャ, ニヤけ, ファン, マリオファン, モンスター, 一人, 任天堂さん, , , 懐かしいスーパーマリオワールド, 熱量, 称賛, 素人目, 自らポチポチ, 自分, 開発ツール,