2024年12月19日木曜日

庭にレイズドベツドを設置しました

大変でした

組み立てがまず大変
二人いないと無理です

高さ80センチまで土を入れるのも大変
うちは何故か玄関側が低く
庭側が高くなっています

玄関側の高さに合わせて設置し
庭の土を放り込みました

去年はライ麦を蒔きました
土に漉き込むことはせず
刈り取ってから乾燥させ
藁の状態にして
その藁を土の上に敷いています

土壌改良を目指して頑張ってきたつもりですが
土壌改良用の多孔質焼成ガラスなどを使った方が手っ取り早いかもしれません

あと3つくらい
この高さのレイズドベツドを設置しようと思っています





2024年11月5日火曜日

XML 構造のファイルシステムへのシリアライズ化及びFUSEの導入について

またまたChatGPTに聞きながらアイデアをまとめていた。

お題は例の「XMLのファイルシステムへのシリアライズ」及び「FUSEの導入に関する考察」と言ったところだろうか

まず以下の質問を投げた

XMLを以下のようにファイルやフォルダ構造に変換しようと考えた

XML例

<books>
    <author name="太宰治">
太宰の作品
        <book title="人間失格" price="100">
         <book title="走れメロス" price="90">
    </author>
    <author name="尾崎紅葉">
        <book title="金色夜叉" price="200">
    </author>
</books>

これを以下フォルダ構造にする
root/0_books/0_author/inner.txt(content:name=太宰の作品)
root/0_books/0_author/attr.txt(content:name=太宰治)
root/0_books/0_author/0_book/attr.txt(content:title=人間失格<crlf>price=100)
root/0_books/0_author/1_book/attr.txt(content:title=走れメロス<crlf>price=90)
root/0_books/1_author/attr.txt(content:name=尾崎紅葉)
root/0_books/1_author/
0_book/attr.txt(content:title=金色夜叉<crlf>price=200)

これであれば、元のxmlを完全にフォルダ構造から復元できる

その上で、FUSEを使えば上記のファイルやフォルダのattr.txtをファイルやフォルダのプロパティとして扱える上に、同一ファイル名や同一フォルダ名の順序も、プロパティの一部として扱えるようになると考えた

以下ChatGPTの答えとなる

このアイデアはとても理にかなっています。FUSEを使うことで、次のようなことが実現可能になります。

1. 属性情報のプロパティ化: attr.txtの内容をファイルやフォルダのプロパティとして扱うため、FUSE層でファイルやディレクトリのメタデータにこれを反映できます。例えば、ファイル操作時に「プロパティ」としてXMLの属性情報が直接利用者に提供されるように見せることができます。
2. 順序の保持: XMLの構造上、同じタグ名で複数のノードが並んでいる場合、その順序が重要です。これも、ディレクトリ名に一意の番号をつけることで保持され、復元時に元の順序が維持されます。
3. XMLの復元: フォルダ構造に従ってファイルを解析することで、元のXML構造に再構築するのが容易になります。特にinner.txtやattr.txtに保存された内容を解析すれば、元の階層構造やテキスト内容、属性も再現できます。
4. 可視性と柔軟性: 利用者にはファイルシステムとして見えるため、XMLの要素を操作する際に通常のファイルシステム操作と同じ感覚で利用でき、複雑なXMLデータの管理が直感的になります。

実装のポイントとしては、FUSEでopenやreadといった各種操作をカスタマイズし、attr.txtの内容をファイルやフォルダのメタデータに割り当てることが重要です。このようなファイルシステムなら、XMLの複雑な構造もフォルダベースで整理され、柔軟な操作が可能になるでしょう。


つまり大当たりなのではないだろうか?
これはやるしかないなぁ

2024年10月20日日曜日

Nuxt + PrimeVue をお試し中

Windows環境にあれこれ設定するのも嫌・・・

というかそもそもWindowsで開発するのが嫌なので、

うちに常時稼働しているRaspberryPiで開発することにする。

(別にWSLでもいいんだけど)

うちのRaspberryPiにはUbuntuが入っているので、VSCodeからリモートでつないでターミナルを起動


■全部すっ飛ばしてNuxtを使ってみる

まずはnpmを入れる

sudo apt install npm

終わったら次はプロジェクトを作成するので、適当なフォルダをつくる

mkdir nuxt_test

cd nuxt_test

続いて、プロジェクトを作成する

npx nuxi@latest init timer

プロジェクト名はtimerにしてみた

(タイマーを設定して動かすだけのページでも作ろうかと思ってみた)

しばらくするとプロジェクトができるので、ターミナルから起動してみる

npm run dev -- -o

しばらく待つと、http://localhost:3000で起動される

ラズパイのIPじゃなくてlocalhostなんだけど、なぜか動く(なんで?)


nuxtのGetting Startedのページを読み進めると、Nuxtのフォルダ構造が出てきた

pagesフォルダを作るのがいいらしい

timer/pages/index.vueを作る

中身はコレ

<template>
  <h1>Index page</h1>
</template>


つづいて、pagesを使う時にはapp.vueを書き換えるらしい

timer/app.vueはすでに存在しているので、中身を変える

<template>
  <div>
    <!-- Markup shared across all pages, ex: NavBar -->
    <NuxtPage />
  </div>
</template>

NuxtPageはpagesフォルダを使う設定らしい

これによって、pages/index.vueがhtmlとして解釈されて表示されるようになる。

ブラウザでIndex pageと表示されていればオッケー

続いて、今動いているターミナルを一度Ctrl+Cで止め、primeVueを入れる

npm install primevue

npm install --save-dev @primevue/nuxt-module

primeVueのテーマを入れる

npm install @primevue/themes

アイコンも入れとく

npm install primeicons


つづいて、nuxt.config.tsを編集

// https://nuxt.com/docs/api/configuration/nuxt-config
import Aura from '@primevue/themes/aura';
export default defineNuxtConfig({
  compatibilityDate: '2024-04-03',
  devtools: { enabled: true },
  modules: [
    '@primevue/nuxt-module'
  ],
  primevue: {
    options: {
      ripple: true,
      inputVariant: 'filled',
      theme: {
        preset: Aura,
        options: {
          prefix: 'p',
          darkModeSelector: 'system',
          cssLayer: false
        }
      }
    }
  }
})

ついでにpages/index.vueへボタンを追加してみる

<template>
  <h1>Index page</h1>
  <Button label="Check" icon="pi pi-check" />
</template>


ターミナルからnpm run devsして、

こんな感じで表示されればオッケー

ん?なんかCheckボタン形偏ってない?わざと?



まぁ気を取り直して

pages/index.vueを編集

IftaLabelというのを使ってみる

<script lang="ts">
import IftaLabel from 'primevue/iftalabel';
</script>


<template>
  <h1>Index page</h1>
  <Button label="Check" icon="pi pi-check" />
  <IftaLabel>
    <InputText id="username" v-model="value" />
    <label for="username">Username</label>
  </IftaLabel>
</template>


動かしっぱなしでもホットスワップ?
ページが変わってくれるのは便利


にしてもこの緑、気に入らない・・・
なんとかならんのかと説明を読んでいたら、Noirモードの定義をしているところがあった。
テーマのAuraをベースにして、あれこれカスタマイズしてNoirを設定している
nuxt.config.tsに結構書き込むことになるけどこんな感じ

// https://nuxt.com/docs/api/configuration/nuxt-config
import PrimeVue from 'primevue/config';
import { definePreset } from '@primevue/themes';
import Aura from '@primevue/themes/aura';

const Noir = definePreset(Aura, {
  semantic: {
      primary: {
          50: '{zinc.50}',
          100: '{zinc.100}',
          200: '{zinc.200}',
          300: '{zinc.300}',
          400: '{zinc.400}',
          500: '{zinc.500}',
          600: '{zinc.600}',
          700: '{zinc.700}',
          800: '{zinc.800}',
          900: '{zinc.900}',
          950: '{zinc.950}'
      },
      colorScheme: {
          light: {
              primary: {
                  color: '{zinc.950}',
                  inverseColor: '#ffffff',
                  hoverColor: '{zinc.900}',
                  activeColor: '{zinc.800}'
              },
              highlight: {
                  background: '{zinc.950}',
                  focusBackground: '{zinc.700}',
                  color: '#ffffff',
                  focusColor: '#ffffff'
              }
          },
          dark: {
              primary: {
                  color: '{zinc.50}',
                  inverseColor: '{zinc.950}',
                  hoverColor: '{zinc.100}',
                  activeColor: '{zinc.200}'
              },
              highlight: {
                  background: 'rgba(250, 250, 250, .16)',
                  focusBackground: 'rgba(250, 250, 250, .24)',
                  color: 'rgba(255,255,255,.87)',
                  focusColor: 'rgba(255,255,255,.87)'
              }
          }
      }
  }
});

export default defineNuxtConfig({
  compatibilityDate: '2024-04-03',
  devtools: { enabled: true },
  modules: [
    '@primevue/nuxt-module'
  ],
  primevue: {
    autoImport: true,
    options: {
      ripple: true,
      inputVariant: 'filled',
      theme: {
        preset: Noir,
        options: {
          darkModeSelector: false,
        }
      },
    }
  }
})



ついでに、アイコンも試そう

pages/index.vueを以下のように編集
<script setup lang="ts">
import Button from 'primevue/button';
import IftaLabel from 'primevue/iftalabel';
import 'primeicons/primeicons.css'
var value = "aiueo";
</script>


<template>
  <h1>Index page</h1>
  <Button label="Check" icon="pi pi-check" />
  <div class="card flex flex-col items-center gap-4">
    <div class="flex flex-wrap gap-4 justify-center">
      <Button icon="pi pi-home" aria-label="Save" />
      <Button label="Profile" icon="pi pi-user" />
      <Button label="Save" icon="pi pi-check" iconPos="right" />
    </div>
    <div class="flex flex-wrap gap-4 justify-center">
      <Button label="Search" icon="pi pi-search" iconPos="top" />
      <Button label="Update" icon="pi pi-refresh" iconPos="bottom" />
    </div>
  </div>
  <IftaLabel>
    <InputText id="username" v-model="value" />
    <label for="username">Username</label>
  </IftaLabel>
</template>

こんな感じの表示になる
あーそうか、Checkの左にチェックマークがあったから偏ってたのか・・・


アイコンも出たし、ようやくまともになってきた。
わたしがPrimeVueすごいなと思ったのは、カレンダーとか補完テキストボックスとか、
自分で作るのがめちゃくちゃ嫌なパーツがそろっていた点

■ちょっと落ち着いてどうなってるのか考察

そもそもVueとはJavaSctiptのフレームワークで、UIを構築できる。
UIはどうもブラウザUIだけではないらしい。

では、vueのアプリを作ってみる
mkdir ~/vue_test
cd vue_test
npm create vue@latest

途中プロジェクト名を聞かれるので、firstProjと入力しあとはただエンターを押した
cd firstProj

vscodeでfirstProjを開いてみた
ターミナルを開いて
npm install
npm run dev

ターミナルにlocalhost:xxxxと出るので、Ctrl+クリックで開くとページが表示される


次にターミナルからCtrl+cで止め、
npm run build

distフォルダにあれこれファイルが出来上がる
これを適当なWEBサーバにおいてあげればきっと動くのだろう
こうしてみるとNuxtの説明とあまり変わらないのだけど
さきほどの画面を見ると、vite+vue3と書かれている
どうやらviteというのがimport なんたら from なんたらという書き方をしているもので、
viteの作者とvueの作者は同じ人であり、viteはvueのビルドツール?という位置づけらしい
本気でわからなくなってきた

出来上がったものだけで判断すると・・・
nuxtはサーバサイドも開発できるもので、サーバはNitroを使っているという。
根っこはvueで、さらにビルドツールとしてviteがあるって感じなのだろうか
しかし、実際のビルドはnpmでやってるわけで・・・
npmの作者はたしか、npmの爆発問題を何とかするためにGoでdenoを作っていて、
途中からRustに移行してるんじゃなかったか?

コンポーネントベースで開発するというやり方を勉強するには、
まずはvueを勉強した方がよさそうなのだけど、
Nuxtでも結局同じようにコンポーネント単位で機能を実装していくことになるため、
vueのテストはここまでにして、
このままNuxtでコンポーネントの作り方を調査することとする。

■JSONのキーとバリュー再帰的にIftaLabelで表示したい

ではIftaLabelを簡単に表示するコンポーネントを作る
components/dispjs.vueを作成する
中身は
<template>
    <IftaLabel>
        <InputText id={{keyStr}} v-model=valStr readOnly=true />
        <label for={{keyStr}}>{{ keyStr }}</label>
    </IftaLabel>
</template>

<script setup>
const keyStr = defineModel('keyStr')
const valStr = defineModel('valStr')
</script>


続いて、index.vueにJSON入れたりあれこれしてdispjsを呼び出す

<script setup lang="ts">
import Button from 'primevue/button';
import IftaLabel from 'primevue/iftalabel';
import 'primeicons/primeicons.css'
import dispjs from '~/components/dispjs.vue';

const contentJSON = {
  Subject: "件名",
  date: "2024-10-19",
  entry: [
    { resource: { resourceType: "目次" } },
    { resource: { resourceType: "はじめに" }, display: "本書を書くにあたり、多くの方にご助力いただきました事を感謝します。", author: ["Aさん", "Bさん", "Cさん"] },
    { resource: { resourceType: "一章" }, display: "まずは動かしてみましょう。" },
    { resource: { resourceType: "二章" }, display: "つぎは応用してみましょう。" },
    { resource: { resourceType: "あとがき" }, display: "最後までお読みいただきありがとうございます。" },
  ]
}

// function dispRecurse(d: any) {
//   if (typeof d === 'object' && d !== null) {
//     for (const key in d) {
//       if (d.hasOwnProperty(key)) {
//         console.log(`${key}:`)
//         dispRecurse(d[key]);
//       }
//     }
//   } else {
//     console.log(`${d}`)
//   }
// }
// dispRecurse(contentJSON);
</script>


<template>
  <h1>Index page</h1>
  <div v-for="(val, key) in contentJSON">
    <dispjs :keyStr="key" :valStr="val" />
  </div>
</template>

ちょっとJavaScriptでどうなるのか試したコードがあるけどコメントアウトしとく・・・
v-forでやってるんで再帰できてない・・・
画面表示はこんな感じ

entryの中は配列で入っているので、上のソースの再帰処理できちんと出せるんだけど、
これをコンポーネント化する方法がまだよくわかってない。
dispjsはラベルとインプットを一緒くたにしたIftaLabelというものを使って表示している。
この際、引数ですごく悩んだ。
export propsとかinterfaceとかやったけど、InputTextでv-model使っててうまくいかなかった。
そこでコンポーネントでもv-modelで引数を設定してやると、
双方向でバインドできるらしく、
Vue3.4以降はdefineModelを使うと楽よ?という情報は手に入ったのでやってみたらうまくいった。

■まとめ
正直全然わかってない・・・
コンポーネントとの引数のやりとりは、v-modelでひと段落したということになるのだろうか?それともまだまだ変わるのだろうか?

Componentで関数書いて再帰処理とかのやり方もまだわからない。

いや、分かった
しかし、よく考えたらそんなことせずとも
scriptで再帰してデータをフラット化して
DataTableやv-forで表示した方がVueとしては正当なやり方だと考えついた。
ので、再帰はできるけど敢えてやらない

2024年9月30日月曜日

MakoServerを動かしてみた

MakoServerというものがある

Lua ServerPage(LSP)を処理するWEBサーバという位置づけで、LSPという拡張子のファイルをHTMLとして表示してくれる
LSPの中にはLuaScriptを書くことができる
ログインフォームのサンプルを表示してみた

これをIISなどで表示するのであれば、
IISからMakoServerへポートフォワードしてやればよさそう
Luaは型の無いスクリプト言語で最速といわれている

GitのサンプルにはWebSocketなどもあり
コンパイル無し(内部ではやってるようだけど)で動かせるため開発効率も高いはず



2024年9月27日金曜日

HTML+JavaScriptで封筒宛名印刷

封筒の宛名印刷をしようと思いHTML+JavaScriptで作ってみました

サンプルをこちらに置きます

ダウンロードして開くとこのようなページが表示されます



キーボードのnでNext、pでPrevious、rで180度回転します


うちのHP SmartTank 6006では回転印刷ができないので、

rを押してひっくり返った状態で印刷をします

ブラウザからプリントで封筒へ印刷できます


封筒は前面給紙トレイに、封筒の表面を下+封筒の閉じる側を手前に向けてセット

位置がずれる場合は適宜調整をお願いします(HTML内に座標が書いてあります)

データはHTML内にJSONで定義されているので、それを参考に差し替えてください




2024年9月25日水曜日

DBでMAX

 DBでIDなんてものはオートインクリメントにしておけよと思うのだけど

select
    max(id)
from
    TBL_A;


こういうのでIDのMAXを取得してインクリメントしてインサートというパターンがある

ところで、上記SQLには大問題がある

データが入ってない場合、NULLになってしまうのだ

するとMAX取得ができないでエラーとなる

仕方ないのでこうする

select
    COALESCE(MAX(id),-1)
from
    TBL_A;

これだと一件もデータがないときには-1となり、インクリメントして0

そのままインサートしてIDが0のデータが出来上がる

次からはMAXを取得するので0が取得できるため、インクリメントして1

そのままインサートしてIDが1のデータが出来上がる


元からダミーデータが入っているような環境だと気が付かないので要注意だ

ついでに書いておくけど

DBにテーブルを作るとPrimaryKeyが必要になる

これが何のために使われるかというと2点あって

1.重複しないため

2.ソートのため

ここで2はあまり重要ではない

IDでソートするパターンなんてあまりないからだ

なので重複しない目的のためならUDIDのようなものを割り振っても構わないはずだ

しかし、本当にそうか?

実はDBのPrimaryKeyとは、インデックスがあるため、順番を検索してインサートが行われる

すると、UDIDの山を一生懸命探しに行くことになるのでインサートは遅くなる


ちなみに大手のDBでは、インデックスを3つ作成するとインサートが10倍遅くなると言う


わたしはこの点、もはやDBの構造的問題に思えて仕方ない

ここ数年かけてXML DBについて考えてきたが

XML DBであればこういうソートだのインデックスだのいう概念をうまく包括できると考えている(インデックスが自動的に勝手に存在するようになる)

その果てにたどり着いたのはファイルシステムで表現してしまえばいいではないかという結論だった(様々な考察をして利点があると考えた)

しかし、次にファイルシステムでは足りないということにも気が付いた

そこで既存ファイルシステムでは何が嫌なのかという点を列挙してみることにした


1. 同じフォルダに同名のファイルやフォルダが作れない

2.ファイルやフォルダに任意のプロパティを設定できない

3.ファイルやフォルダの順序が明確ではない

4.パスに限界がある


何言ってるかわからないかも知れないが

わたしは非常識な事を言っているのである

逆に言うと常識で考えないでほしい


WindowsでもLinuxでもファイルシステムはかなり昔からあるものを拡張し続けている

しかし、上記4点を改善できれば、XMLのタグやInnerTextなどをそのままファイルシステムで表現できるようになる

もちろん、JSONやYAMLもファイルシステムに置き換えられるだろう


早速ファイルシステムを考え始めた(いまさらか?)

世の中にはFUSEというものがある

これを使うと結構簡単に実現できるかもしれない

あとは設計製造だ

今ここまでたどり着いた

2024年8月25日日曜日

3Dプリンタを園芸へ

 最近3Dプリンタを園芸に使っている

バラ用の鉢はこれに統一することにした


PETGで作れば耐候性も充分だ

サボテンの方は以前投稿した通り

TPUで六角形の小さい鉢を作り沢山植えてある

2024年8月11日日曜日

XML Dataをフォルダやファイルシステムでシリアライズする方法に関して考察

XML Databaseライクなものを作るために、XML構造をフォルダとファイルにシリアライズする方法をずっと模索してきた

大体アイデアが固まったので、ChatGPTに聞いてみた

そしたらPythonコードで確認までしてくれて、おいおいお前まぢかってなった

ただし、わたしは知っている
途中に挿入するコメントの事を考えてない(コメントは無視で保存したいが、、、)

ネームスペースはフォルダにアンダーバーで区切って保存するように考えている

====ChatGPTに聞いた内容

XMLをフォルダやファイル構造にしてシリアライズするアイデアを再考していたが
アトリビユートをファイル名にすると、元のXMLを再現する事ができない(アトリビユートの順番が再現不能)

そこでアトリビュートをAttr.txtにまとめ、タグ内のテキストはinner.txtに保存するように考えた

タグはフォルダにするが、プレフィックスとして番号付けを行う

<books>
    <author name="太宰治">
太宰の作品
        <book title="人間失格" price="100">
         <book title="走れメロス" price="90">
    </author>
    <author name="尾崎紅葉">
        <book title="金色夜叉" price="200">
    </author>
</books>

これを以下フォルダ構造にする
root/0_books/0_author/inner.txt(content:name=太宰の作品)
root/0_books/0_author/attr.txt(content:name=太宰治)
root/0_books/0_author/0_book/attr.txt(content:title=人間失格<crlf>price=100)
root/0_books/0_author/1_book/attr.txt(content:title=走れメロス<crlf>price=90)
root/0_books/1_author/attr.txt(content:name=尾崎紅葉)
root/0_books/1_author/
0_book/attr.txt(content:title=金色夜叉<crlf>price=200)

これであれば、元のxmlを完全にフォルダ構造から復元できる

====ここからChatGPTの答え

このアプローチは、元のXML構造を完全に再現するために非常に有効です。アトリビュートやタグ内のテキストの順序も維持できるため、正確な復元が可能です。また、プレフィックスとして番号を付けることで、同じタグ名を持つ要素の区別も明確になります。

この方法での実装は非常に理にかなっています。次に、具体的にそのフォルダ構造を生成し、XMLをファイルシステムにシリアライズするためのPythonコード例を示します。

### Pythonコード例
```python
import os
import xml.etree.ElementTree as ET

def serialize_element(element, parent_path, prefix):
    # Create directory for the current element with prefix
    dir_name = f"{prefix}_{element.tag}"
    dir_path = os.path.join(parent_path, dir_name)
    if not os.path.exists(dir_path):
        os.makedirs(dir_path)
    
    # Write attributes to attr.txt
    if element.attrib:
        attr_file_path = os.path.join(dir_path, "attr.txt")
        with open(attr_file_path, 'w') as attr_file:
            for key, value in element.attrib.items():
                attr_file.write(f"{key}={value}\n")
    
    # Write inner text to inner.txt if it exists
    if element.text and element.text.strip():
        inner_file_path = os.path.join(dir_path, "inner.txt")
        with open(inner_file_path, 'w') as inner_file:
            inner_file.write(element.text.strip())
    
    # Recursively process child elements with a numerical prefix
    for i, child in enumerate(element):
        serialize_element(child, dir_path, i)

# Load XML
xml_string = """
<books>
    <author name="太宰治">太宰の作品
        <book title="人間失格" price="100"></book>
        <book title="走れメロス" price="90"></book>
    </author>
    <author name="尾崎紅葉">
        <book title="金色夜叉" price="200"></book>
    </author>
</books>
"""
root = ET.fromstring(xml_string)

# Define the base directory where the XML will be serialized
base_dir = 'output_dir'
if not os.path.exists(base_dir):
    os.makedirs(base_dir)

# Start the serialization process
serialize_element(root, base_dir, 0)
```

### フォルダ構造生成結果
上記のPythonコードを実行すると、次のようなフォルダ構造が生成されます:

```
output_dir/
└── 0_books/
    ├── 0_author/
    │   ├── attr.txt (content: name=太宰治)
    │   ├── inner.txt (content: 太宰の作品)
    │   ├── 0_book/
    │   │   └── attr.txt (content: title=人間失格\nprice=100)
    │   └── 1_book/
    │       └── attr.txt (content: title=走れメロス\nprice=90)
    └── 1_author/
        ├── attr.txt (content: name=尾崎紅葉)
        └── 0_book/
            └── attr.txt (content: title=金色夜叉\nprice=200)
```

### この方法の利点
- **順序保持**: XMLの要素やアトリビュートの順序が保持され、正確に再現可能。
- **明確な階層構造**: 番号付きのフォルダ構造によって、同一タグ名の要素も正確に区別できる。
- **シンプルな再構築**: フォルダ構造から元のXMLを再構築するのが容易。

これで、XMLデータを正確にシリアライズおよびデシリアライズできるシステムが実現できます。

2024年8月10日土曜日

散水機付けてみました

散水機付けてみました

自分が外出してたら水あげられないので
今後はどうしても必要になります

弁が四つついてて

NOWボタンで現在時刻を合わせ
ABCDで弁を選びます
選んだらOFF長押しでタイマーOFF
蛇口マークでマニュアルで弁を開きます(その際開いてる時間を指定)
プラスマイナスは時間の調整
OKはカーソルを次に送るボタンです

タイマーは何時に弁を開くか
何分開くか
何時間おきにタイマーを繰り返すか
と言う設定が出来ます

値段は最後の写真にありますが
ホースが足りなくて
Amazon探したら同じ物が同じような値段で合ったので追加購入してます(まだセットアップが残ってます)










2024年7月31日水曜日

構文木

5÷(8−3)×2+1を正しく計算できる?

というやつだ

答えは3なんだけど、
LRで構文木を作ると

まず、Rを探しに行く
右端は+ 1
                    PLUS
                /                \
       5/(8-3)*2           1

続いて、LからまたRを探すと、* 2

                    PLUS
                /                \
            MUL             1
          /          \
5/(8-3)      2
さらにLの5/(8-3)にRを探すと/ (8-3)

                   PLUS
                /               \
            MUL           1
          /           \
       DIV          2
     /       \
   5      8-3

んで、今度はR側にまだ再帰できるところがあるので

                   PLUS
                /               \
            MUL           1
          /           \
       DIV          2
     /       \
   5      MINUS
           /             \
         8              3
これで構文木が完成

そんで、答えを出すには最下層から上に上がっていく
8-3=5なので
                   PLUS
                /               \
            MUL           1
          /           \
       DIV          2
     /       \
   5         5

続いて
 5/5=1なので
                   PLUS
                /               \
            MUL           1
          /           \
        1          2
 
さらに続けて
1*2=2となり
                  PLUS
                /               \
              2                1

最後は
2+1=3
という事で、答えの3が導ける

ここで、数式とプログラミング言語を比べると、C言語なんて関数なので、

例えばif文
if (a==b) {
    proc();
}

          if
       /       \
    ==    proc()
   /      \
a        b

のようになるし、forも代入も似たようなもんで、構文木を作って解釈して行くことになる

このやり方はクヌース大先生が考案したもので、その後多くのアイデアが出てくるのだけど、基本はやはり構文木を作るというやり方になっている

そして、lexやyaccが生まれ、
構文木を自動生成するためにBNF記法が生まれ、C言語などのプログラミング言語が出来た

C++では構文定義をC++の記法で置き換えたboost::spiritsなども生まれ、すぐにこの変態的実装はなくなるかと思ったが、C++17でも残ってる

lexやyaccは
flexやbisonになったが
わたしが最近触っているANTLRは構文定義からGoやSwiftのコードも出力できる

好みの言語で新しい言語を作ることができるようになってきた

2024年7月20日土曜日

XML2Json再考

突然思い出したので
忘れないうちに書いておきます

Xerces Xalan
今はなかなか見かけない
この2つのプロジェクトは
XMLを扱っていた人ならご存知でしょう

実装の中身を見ていませんが
XMLをDOMとして扱っておらず
逐次的に処理をする実装になっていると聞いたことがあります

DOMについて
公式での解説も何だかパッとしないので改めて説明します

DOMと言うのは、XMLのツリー構造を構造体などを利用してメモリやファイルなどに保存しておいて、高速にアクセスすると言う仕組みです

例えばHTMLはブラウザでツリー構造が扱えるようになっていて、そのためにDocument.getElenentByIdのようなアクセスが可能となっています

これに対してDOMでは無いパースとは、XMLを単なるテキストとして扱い
上から順にパースして該当項目を探すので
あまりパフォーマンスは良くありません

このようにXerces Xalanは逐次的にパースするので
XMLを一度DOMとしてメモリやファイルなどに展開する時間はゼロです

巨大なXMLを扱う場合にはそれをDOMとしてメモリやファイルに保存しないため、メモリやファイルの消費を抑えることが出来ると言う利点もあります

なぜ突然この二つを思い出したのかと言うと、、、

わたしが以前Goで作ったXML2Jsonの実装を見ていて
DOMでは無い方が良いかも知れないと思い始めていたからです

当時の実装は逐次的にXMLのパースを行うGoのライブラリを使用して、XMLのTokenを取得しながら自前のDOMを作り、そのDOMからJSONに変換すると言う実装でした

しかもその変換関数は再帰ルーチンとなっていました

どうも無駄だらけに見えてきました

やはり一度作ったプログラムは何度か作り直さないとダメです

わたしは天才ではありません

2024年7月12日金曜日

地熱

G Mm/r^2
このエネルギーは潮の満ち引きなどを引き起こしている
そのエネルギーは地表の水だけでなく
地球中心と月中心間の距離の二乗に反比例し
互いの中心に絶えずエネルギーが発生していると考える
同じ事が地球と太陽でも起こり
金星と太陽でも起こっていると考える

金星の表面には太陽の熱エネルギーと金星の内部に溜まり続ける熱エネルギーによって絶えず嵐が吹き荒れている

太陽の吹き出す熱エネルギーも重力も断然金星の方が強い

2024年7月11日木曜日

ススホコリ





しばらく前に庭に発生したススホコリ

GoによるJSONのパースについて

Go言語には、JSONのパースをする際に構造体が必要になるライブラリしかなかった

社員から、その点について質問があり
構造体のように枠が決まっていないと
セキュリティ上の問題になりやすいと言うことを説明した

パースする相手がXMLでも同じ状況だった

そこでわたしは以前、任意のXMLをパースして、汎用的な構造体を使ったメモリーマップに保存することにした
そして、そのマップからJSONを作り出すこともやった

その構造体メモリーマップにパースする事は、XMLでも出来たので、JSONにも対応可能だ

というか、JSONのが簡単だろう

それで最近の状況はどうなのか調べてみると、メルカリの技術者がJSONのパースについてライブラリを作っていたのを見つけた

gitの中身は見てないが、やり方は同じなんだろうと思ってる

わたしは以前自分が作ったものに少し不満があった

その不満を突き詰めるとXML Databaseになってしまうのもわかった

MongoDBのSQLite版的な位置付けの物で、内部データはXMLと言うものになり、XQueryを処理する形でデータを抜き出すと言う簡易データベースだ

こいつがかなり厄介で
XQueryの実装に難儀している
モチベも続かない

しかし、今回社員からマイクロサービスの用途でJSONのパースの話を聞かされて、以前作った物がそのまま使えそうなことに気がついた

冒頭で書いたJSONのパースについては、JavaScriptでフロントからのリクエストがあった時に、通信内容はJSONにした方がいいと意見した流れだったのだけど、XML HttpRequestならそのまま使える
JSONをパースする部分を作れば、相互変換もできる
さらに、ファイルシリアライズを実装すれば、あとはXQueryの実装にも使えるようになる

頭の中であれこれスッキリ繋がった気持ちになっている

やはり一人で考えているより、人と話している方が捗る

2024年7月9日火曜日

Unityのデータ指向には賛成(と言うかゲームはそういう作りにするべき)

 https://game-ace.com/blog/unity-dots-system/

わたしが作っているゲームエンジンはデータ指向でありオブジェクト指向なのだけど、Unityはオブジェクト指向が嫌いなようだ

両者は対立するものではない

オブジェクトがデータに沿って動けば良いだけの話だ

わたしはGo言語もやっているので、モジュール指向で作ることには抵抗が無いし、オブジェクト指向に凝り固まったJavaは嫌いで仕方ない

Goの作者がC++はなんか違うと思い続けてGoが作られたのも納得している

確かにクソコードの作者はクソなクラスを山のように作り出す

それ、なんのため?

意味わからん

遅いだけじゃん!

ずーーーーっとそう思い続けていた

繰り返しになるがオブジェクト指向がクソになるのはクソコーダーの所為なのだ

クソコーダーはアセンブラからやり直せ!

Windowsのクラスがクソなのは間違いない

あのクソ構造なMSお作法のために何人の有能なプログラマがその道を諦めたことか、、、

わたしは全部見て来たが、見ていない人には何もわからないだろう

こうやって歴史は大きな勢力に上塗りされるのだ

ところで、この紹介ページの図

下手すぎ

なんだこのJobが沢山ありますよ的な図は、、、

わたしがUnityを嫌いなのはC#だからだ

C#はJavaが欲しかったMSが苦し紛れに作った言語で、生まれながらにポリシーが無い

C#はクソ真似言語だ

登場当時、C#はC++--(シープラプラマイナスマイナス)と言われていた

C++からオブジェクト指向以外のものを削除した言語という意味だ


こんな古い話、今では知っている人も居ないだろう


とにかく面白く無い言語で、ゲームに向いているとは思えない


あんなもんやるならSwiftやGoの方が何倍も素晴らしい

2024年7月5日金曜日

Doxygen

今更かよ


Call Caller図も出す設定してるなら
こんな図が出ますよって出した方がよくないか?

あれあると、影響範囲見るの楽だよ?

ゲームエンジンでパーティクルの実装

パーティクルを実装しました

正直目が痛い・・・

でも、まぁ思ったように実装できたと思います

まだ、いまいちなところもあるので改善点を考慮中です




2024年7月4日木曜日

ライ麦

ライ麦

中途半端な実り方をしていた穂からライ麦の種を取り出してみた
これでも結構な量ある
撒いた量よりは確実に多い




2024年7月2日火曜日

庭の手入れ

庭の一角を畑のようにしていたのだけど
管理できない
雨が降った後ぐちゃぐちゃになる

実は最近フェルトの鉢を多用している

この鉢はとても水捌けがよく
保肥力が強い土を用意すればかなり手間を無くせる

そのフェルト鉢の方を見ると
かなり良い土の状態を維持できていて
庭全体これで良いんじゃないのかとさえ思える

雑草も生えないように
防草シートを敷いて
上に砂利でも敷いてしまう方が管理が楽だと考えた

プールシートでも良いかも
フェルト鉢から出ていく水をプールシートに溜め
そこに生物も住まわせて
水の再利用をする

構想はまとまった
あとはやるだけだ


2024年6月29日土曜日

JavaScriptでゲームエンジン作ってみた

ゲームエンジン作ってみた
出てきた芽をつつくと昇天する

プログラムで、芽が突かれたらと言う判定をしていると言うよりは芽が自分が突かれた時の処理として昇天するアニメへ切り替えている
つまり、プログラムが制御すると言うよりは
オブジェクトが自分のシナリオデータに沿って動く
オブジェクト指向であり、データドリブンと言うのはこう言うことだと言う例にもなっている
マウスのクリック効果は録画ソフトがつけているので ゲームエンジンで出してるわけではない (やろうと思えばすぐにできる) まだフレームレートの計算でよくわからないところがあって、 適当に調整してしまったんだけど まぁ動いてるからとりあえずいいか・・・ 計算合わないのがすっごい気持ち悪いんだけど・・・ アニメーションはAsepriteで作った 上に飛ばすときにもう一度クリックすることもできてしまうので、判定処理を抜くルーチンを実装してやらないといけない まぁゲームエンジンは大体できてきた


どうもゲームエンジンというものがどういう物かわからないという声が出てくるので説明しておく 画面に絵を表示するとき 絵は矩形で描画する サイズは32x32,16x16など、都合のいいドット数であることが多い 描画するときにX,Y座標を指定するが、 X,Y位置に左上を合わせて描画するのが左上基点 X,Y位置に画像中心を合わせて表示するのが中央基点 X,Y位置に画像の左右中央下端を合わせて表示するのがベース中央基点 まぁ呼び方なんかどうでもいい ベース中央基点は、対戦格闘などでよく使う方法で、キャラクターの地面の立ち位置を基点にして表示する方法だ この方が画面の左右スクロール時に位置がどこなのか考えやすい だが、中央もよく使う 例えば、マウスクリックしたところから四方八方に光を散らせるパーティクル効果を表現するときは、雪の結晶のような画像をX,Y位置に画像中心を合わせて描画する このように都合に合わせて、どこを基点に表示するのか変わってくる これらをプログラムで一々調整するのではなく、Asepriteなどのアニメーションデータで雪がチラつくようなアニメーションを組み、それを再生させながら四方八方に散らせて、最後はアニメーションの透明度で消えていく という制御を、画像側主体で動かすのがゲームエンジンの基本的な考え方だ つまり、画像が自分で自分の次のフレームの画像を切り替え、自分の位置を切り替える プログラムはその切り替えるアニメーションパターンや、四方八方に飛び散る物理演算を設定するだけで、あとは画像側が勝手に動く わたしが先に示した草を引っこ抜くゲームエンジンの例では 「Mebae」「Idle」「Pickup」のアニメーションパターンをAsepriteで作っている


インターバルで草を生成するルーチンは以下2つの指定をしてスプライトを生み出している 1.MebaeからIdleまで再生し、Idleはループさせるという指定でX、Y位置をランダム生成してスプライトを生成している 2.その際、当たり判定を物理演算の一種として登録している。 マウスクリックに当たっていたら「Pickup」へ切り替え、「Pickup」が終わったらスプライトは自己消滅するように指定している 全体のスプライト数もわかるので、60個までで草を生み出すのを止めている

        function isPickUp(spr) {
            if (spr.isTouched()) {
                // Pickupが終わったら消えるように設定
                spr.setTagNames(["Pickup","DIE"]);
            }
        }

        function getRandomInt(max) {
            return Math.floor(Math.random() * max);
        }

        async function dispatch() {
            // 最大60個にしておく
            if (gPrim.primitives.length <= 60) {
                // 乱数で座標を生成
                var x = 32 + getRandomInt(640 - 64);
                var y = 32 + getRandomInt(480 - 64);
                // ["Mebae", "Idle","REPEAT"]のように指定すると、Mebae、Idleの順に実行した後、Idleをリピートする
                // ["Mebae", "Idle","DIE"]の場合はIdleを実行した後Spriteが消える
                var sp = await Sprite.build("Futaba", jsMebae, ["Mebae", "Idle","REPEAT"], x, y, 1, 0);
                sp.addPhysic(isPickUp);
                gPrim.append(sp);

                console.log("dispatched", x, y)
            }
            nextTime = 3 + getRandomInt(5) * 1000;
            setTimeout(dispatch, nextTime);
        }


さて、ゲームエンジンは画面の表示位置だけを担当するのではない 当たり判定、繰り返し、消滅、親子関係(親に追従するかしないかの指定も可)などのほかに、音声再生なども行う 例えば、何もないスプライトを親にして、その子供としてダンジョンマップを登録する 上下左右の移動で、何もない親スプライトの位置を変えれば子供の位置が全部変わる つまりマップがスクロールする 例えばぷよぷよのぷよが、自分の上下左右に自分と同じぷよがいるかどうかを調べ、自分の体を変形させる(その際、変形用アニメも用意されていればスムーズに変形する) こういった、例えばをプログラムだけでやることの愚かさがわかるだろうか? ゲームエンジンを使えば、スプライトが自分で考えて自分の姿形を変え、消滅したり、新たなスプライトを生む出したりもできる ゲームエンジンのシナリオデータだけで、自分がやられたら、子供をたくさん生み出すような敵も作れる 子供は子供の攻撃パターンで動くこともできる 物理エンジンの一種として登録させることができる ゲームエンジンがあれば、
これらを全部同時に動かすことができる
RPGもシューティングも格闘ゲームもパズルも同じ組方で実装できる
ゲームの仕事が来た時に
その都度似たようなプログラムが組みたいならやればいい
わたしはその機種ごとにゲームエンジンを作ってからゲームを作る

ブラウザでよいのなら、ブラウザに特化したゲームエンジンを作り、
スマホにも対応させればよい
G123など、すでにやっているではないか?
あれを作ればいいだけのことだ

 

2024年6月27日木曜日

Duet Web Controller Camera Setting(Microdia)

3D PrinterにつないでいるRaspberryPiにUSBカメラをつけて

Duet Web Controllerから見れるように設定した

※まず、Duet3 に接続しているRaspberryPiにSSHで接続し

1.mjpg-streamerをインストール

sudo apt update

sudo apt install snapd
sudo snap install mjpg-streamer

2.設定
sudo vi /var/snap/mjpg-streamer/current/config


INPUTOPTS="input_uvc.so -y -r 640x480 -d /dev/video0"
PORT="-p 8080"
DAEMON="true"


3.カメラを接続
snap connect mjpg-streamer:camera

4.mjpg-streamer再起動
sudo snap restart mjpg-streamer

これでブラウザから
http://192.168.XXX.XXX:8080/を開いてページが表示される
Streamのところを見るとカメラの映像が見れるはず

続いて
5.Duet Web Controllerの設定
設定→全般のところのカメラのURLに以下を入れる
http://192.168.XXX.XXX:8080/?action=stream

2024年6月23日日曜日

Easeus やられた・・・

SSDのクローンして書き込んでお引っ越しまでできたのだけど

4kアライメントの調整もやってみたら全部吹っ飛んだ・・・

おいおいおい・・・

2024年6月16日日曜日

詳細設計書きたくないと言う話

https://togetter.com/li/2384729

今いる現場でも、四年目あたりの人が同じようなことを言っていた

そもそも、BD、FD、CD、UT、ITなんて用語を知らなかったようだ

基本情報の説明にもあるのだけどなぁ、、、

基本設計から結合テストまでのウォーターフォールについてのドキュメントをIPAがまとめたのは2007年

当時の元気な大企業がよって集まってまとめたものだった

ところが、大企業は各々の文化があり、うちはこうまとめる、よそは知らんという感じで、中身の粒度やフォーマットなどはまとめられないままだった

この投稿で議論されているように、コードの直しが発生する細かすぎる仕様書はメンテされなくなる

仕様書の書き方もよくわからないまま修正したりすれば、さらに意味不明なドキュメントが出来上がり、コードと乖離してるんだよねと言うよく見る状況になる

Javaな人たちは、詳細なんてものはコードからリバースすればいいじゃ無いかと、DoxygenやGraphvizを使ったり、コードからUMLのクラス図を作り上げるようなツールを使いまくって乗り切ってきた

単なる間に合わせだ

このやり方で果たして品質が上がるのか?
もっともな疑問が湧くだろう

大企業様はウォーターフォールをすれば品質が上がると言う論文を自社の社員に大量に書かせて、あたかもこれが一般的なものであると言う根も葉もない根拠を作り上げた

でも、やはり気づくよね?
無理がありすぎる

そんな折、アジャイルが提唱されたのはほぼ10年前だろうか?

イテレーションを繰り返して少しずつ作って行ったほうが早いし、コーディングも綺麗になると言い始めた

だが、わたしは知っている
ゲーム業界は特に仕様書を重視しない
都度コーディングしてディレクターに見せて、指摘を取り込むことを繰り返しつつ、全体スケジュールもきちんと視野に入れた舵取りが行われていた

つまり、ゲーム業界はスーファミ時代からとっくにアジャイルだった

だが、アジャイルだとしても、やはりコーディングする人の技量に左右されまくり、部分部分で全くレベルが違う事態になる

ゲーム業界ではそれでもリリース日があるので、動けばオッケーなレベルで出荷していた

この点どう考えられているのかと
アジャイルについて書かれた本を読みまくったが、お前らそれで物が作れると思ってんのか!と説教したくなった

わたしはそのやり方で失敗しまくった例をたくさん見ているのだ

そうしたら最近だと、アジャイルとは結局何をやっても良いんですよ、うまくいかなかったら工夫してうまくいくようにさせるんですと言い始めた

わたしがそれを聞いた時の感想

おいおい、それができるまでお前ら何度も失敗することになるが、それ、ハウツー本にならんじゃないか、、、

わたしが品質を上げるために重視しているのは、コーディングのレベルだ

コーディング規約ではない

フレームワークと言うものは
ドメインをきちんと取り決めてあり
どこで何をすれば良いのか分かりやすくなっている

これさえも出来ないエンジニアは多い
フレームワークへの理解が足りないから
せっかく用意されている仕組みを使えないのだ

コーディングする人材が勉強不足過ぎるのだ

コーディングとはある意味すごく単純だ
出来ることは代入、条件判定、ループくらいのものだ

しかしコーディングのお題を与えると、人によってすごく短いコードになったり、膨大なコードになってさっぱり意味がわからなかったりする

イベントドリブン、ドキュメントビューアーキテクチャ、モデルビューコントローラ、オブジェクト指向、DDD、機能指向、アルゴリズムとデータ構造など、、、

今迄数多くの概念が提唱されてきたが
マイクロサービスなんてものを見ると、モジュールベースで、機能指向でより単純化されているし、こんなものをasp.netやSpringで作るとしたらバカくさくてやってられない

わたしが言いたいのは
シンプルに考える事の重要性だ

まず画面をシンプルにする

お客様は画面しか見ない
我々も画面でしか表現できない
まず、業務システムなら機能はそこそこで紙芝居画面を作りそこでオッケーをもらったら作る
作っててダメならまた見せる
これの繰り返しで品質は上がる

次にデータの持ち方をシンプルにする
データベースはそこそこ意味があったが
それでは足りなくなっている

XMLやJSONカラムを使った方がシンプルになる場面が多いのに、旧態依然としたSQLしか知らない輩が偉そうにテーブル定義を作る

もちろんそれで動くものは作れるが
よくインサートされた内容を見てみろ
しっかり階層構造になってるだろ?
ならば何故二次元で考える?

今までやったことがないから?
以前はこれでうまく行ったから?

だからお前らのテーブル定義は
出来上がった瞬間に中古物件になってるんだよ!

階層構造を理解できないと言う事は
勉強不足なのだ

新しいSQLの拡張をもっと勉強するべきだ

最後にフレームワークの使い方
どのフレームワークもMVCだろうが
言語によって実装は結構違う
一通り自分でゼロから作ってみてほしい
自分でCMSやECサイトは作れるか?
対戦格闘ゲームサイトは作れるか?

出来合いのECやCMSを使うか?
AWSが用意してるゲームサイト用の機能を使うだけで満足か?

それで中身がどう動いているのか理解できるのか?

全く勉強不足なのだ

プログラマは以前より多くの知識を要求されるようになった

特にセキュリティに関してはガンガン勉強しなくてはならない

BD、FDでその辺りを書ける人は見たことがないし、今まで通りの仕様書の書き方では、かなり粒度を細かく書かなくてはいけないだろう

さて、このように人が全部やるとしたら勉強不足に起因する課題だらけだけど、最近はcopilot様が現れた

時代としては詳細設計はぶっ飛ばして良い時代になったと思っている

だってダメなところはcopilot様が教えてくれるじゃないか?

最終的にcopilot様がオッケー出せば良いんじゃね?とさえ思い始めている

はよ、自分でコーディングしない時代になってもらいたいものだ

copilot様、あとはよろしく

2024年6月2日日曜日

ライ麦の部分的収穫

ライ麦の穂だけ摘んだ
成長度合いにバラツキがあって
しかもこいつ、まだ青いのに種が根本から落ち始めていた
麦色になるまで待ってたら
おそらく種採れない

このまま乾燥させれば
叩くだけで落ちるはず

庭にはまだ半分以上残っているのだけど
現時点でこのフェルト鉢の半分まで収穫できている
フェルト鉢は直径39cm高さ30cmのいつものやつ
持ち上げるとそこそこ重い
これなら余裕でパン焼けるだろう

ダッシュ村で三瓶 明雄さんが教えていた様に、種の選別をするべきだった

このライ麦は緑肥用の種なのだけど
今見直してみたら本当にいろんな種が混ざってる

選別してやらないと良い種を収穫できないし、収穫時期もバラつくと言うことなのだろう




2024年6月1日土曜日

ライ麦試しに剥いてみた

ライ麦の穂を6本くらい剥いてみた
まだ乾燥しきってないのだけど
穂を逆撫でするように指でモミモミしたら種がポロポロと落ちてきた

左が収穫した種
真ん中は種まきに使った種で表面が赤いのはゴム質の粉がまぶしてあって、鳥に食われない様になってるらしい
右は剥いた後のクズになった穂

撒いた時の種より大きい種が多いが
乾燥したら赤いのと同じくらいの細さになるのだろう

全部収穫すれば
ライ麦パン一つくらいは焼けるだろうか

庭のライ麦はまだ花粉が見えてる穂も混ざっていて
生存戦略的に成長がまばらなのかも知れない


それにしても昔の人は
稲藁使って俵、草鞋、綱、籠など
いろんなものを作っていて
本当にSDGSだったのだなぁと感心する

このクズの方は
もう少し細かく切って
イチゴを植えてあるフェルト鉢の表面に撒いておく
保水効果、乾燥防止になって
その下には粒状の土が出来上がるだろう
虫や微生物の働きでそうなるらしい

ちょっと不思議なのだけど
死にかけてた様に見えたアーモンドの木が
今年は豊作になっている
枝も出てきてすごく元気だ

周りにライ麦を撒いたのがよかったのだろうか?
たいして肥料もやってない

ライ麦の根は土中深くまで届くらしく
その周りに根粒菌が増えたのかも知れない



2024年5月25日土曜日

やってみれば良いだけの話なのだが土の話

軽石は人工的に作られた物があって素材はガラス
売られてる軽石を溶かして固め直せばガラスになる

ハイドロボールは粘土質の土を固めて素焼きにした物で、様々な素材が混ざっている状態で、ガラスも混ざっている

サボテンの土として売られてる目の荒い白い土?もガラス等を発泡焼結させた物

家屋の下に強いてある土は赤土で栄養がほぼない
有機物が混ざっていくと黒くなっていく

ウクライナ辺りの黒土は
本来分解されるべき有機物が残ってフカフカになり
植物の根も張りやすく
菌類も住まうのに良い環境になっている
これは半ハイドロカルチャーと言っても良い状態だ

植物の根は根粒菌などと共生して根を張り巡らせ栄養を吸収出来る

ココまでが導入部で
ココから本筋なのだが、、、

菌類が住うことができる場所と栄養があれば
そこに根を張り植物は育つ

菌類と栄養と水分と温度のバランスが取れれば
土なんてなんでも良い気がしてきた

例えば
ガラスリサイクルした敷石が安く売られている
それにバーミキュライトやピートモスを混ぜれば水分が保ちやすくなる
そこに栄養をぶち込んでやれば樹木でも育てられるのではなかろうか

ベランダが2〜3畳くらいあるのだが
屋根の波板が風でバタついてうるさい
いっそ取り外して隅っこにキウイでも植えてやったらどうかと考えていた

しかしながら、土だと重いし水やりも大変だ
そこでフェルト鉢にガラス敷石とバーミキュライトを混ぜ、フェルト鉢の下に水受けを設けて水を溜め、ソーラー散水機で循環させてやればどうかと考えた

水受けは
ケーキのホールカットのように部品を分けて作れば良い
これは3Dプリンタの出番だ
最近使いはじめているPETGなら
耐候性もあるし積層強度も高いため
水も漏れない
12分割してやれば強度も充分だろう

あとはやってみるだけだ