roundabout,
created on Monday, 29 April 2024, 11:32:36 (1714390356),
received on Wednesday, 10 July 2024, 16:59:59 (1720630799)
Author identity: vlad <vlad.muntoiu@gmail.com>
a8fd453a859c7a9bfb0e26b9981125340ca5e5f0
.idea/workspace.xml
@@ -4,8 +4,19 @@
<option name="autoReloadType" value="SELECTIVE" /> </component> <component name="ChangeListManager"> <list default="true" id="b2c629ea-d173-4caf-b306-cbeaee617270" name="Changes" comment="Reverse order of articles"><change beforePath="$PROJECT_DIR$/main.py" beforeDir="false" afterPath="$PROJECT_DIR$/main.py" afterDir="false" /><list default="true" id="b2c629ea-d173-4caf-b306-cbeaee617270" name="Changes" comment="Build in another worktree"> <change afterPath="$PROJECT_DIR$/projects/echo.md" afterDir="false" /> <change afterPath="$PROJECT_DIR$/projects/waste.md" afterDir="false" /> <change afterPath="$PROJECT_DIR$/projects/wordle.md" afterDir="false" /> <change afterPath="$PROJECT_DIR$/static/photos/wordle-analyser.png" afterDir="false" /> <change afterPath="$PROJECT_DIR$/static/photos/wordle.png" afterDir="false" /> <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" /> <change beforePath="$PROJECT_DIR$/articles/Markdown testing.md" beforeDir="false" /> <change beforePath="$PROJECT_DIR$/articles/Moved to a roundabout.md" beforeDir="false" afterPath="$PROJECT_DIR$/articles/Moved to a roundabout.md" afterDir="false" /> <change beforePath="$PROJECT_DIR$/projects/ampoule.md" beforeDir="false" afterPath="$PROJECT_DIR$/projects/ampoule.md" afterDir="false" /> <change beforePath="$PROJECT_DIR$/projects/roundabout.md" beforeDir="false" afterPath="$PROJECT_DIR$/projects/roundabout.md" afterDir="false" /> <change beforePath="$PROJECT_DIR$/static/style.css" beforeDir="false" afterPath="$PROJECT_DIR$/static/style.css" afterDir="false" /> <change beforePath="$PROJECT_DIR$/templates/default.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/default.html" afterDir="false" /></list> <option name="SHOW_DIALOG" value="false" /> <option name="HIGHLIGHT_CONFLICTS" value="true" />
@@ -29,11 +40,12 @@
"Python.main.executor": "Run", "RunOnceActivity.ShowReadmeOnStart": "true", "git-widget-placeholder": "master", "last_opened_file_path": "/home/vlad/blog/static/fonts""last_opened_file_path": "/home/vlad/blog/static/photos"} }</component> <component name="RecentsManager"> <key name="CopyFile.RECENT_KEYS"> <recent name="$PROJECT_DIR$/static/photos" /><recent name="$PROJECT_DIR$/static/fonts" /> <recent name="$PROJECT_DIR$" /> </key>
@@ -203,7 +215,15 @@
<option name="project" value="LOCAL" /> <updated>1713812790244</updated> </task> <option name="localTasksCounter" value="16" /><task id="LOCAL-00016" summary="Build in another worktree"> <option name="closed" value="true" /> <created>1714373192680</created> <option name="number" value="00016" /> <option name="presentableId" value="LOCAL-00016" /> <option name="project" value="LOCAL" /> <updated>1714373192680</updated> </task> <option name="localTasksCounter" value="17" /><servers /> </component> <component name="Vcs.Log.Tabs.Properties">
@@ -233,6 +253,7 @@
<MESSAGE value="Article" /> <MESSAGE value="Add dates" /> <MESSAGE value="Reverse order of articles" /> <option name="LAST_COMMIT_MESSAGE" value="Reverse order of articles" /><MESSAGE value="Build in another worktree" /> <option name="LAST_COMMIT_MESSAGE" value="Build in another worktree" /></component> </project>
articles/Markdown testing.md
articles/Moved to a roundabout.md
projects/ampoule.md
@@ -46,6 +46,8 @@ Features
to publish. * If you see fit, it's easy to **convert** to a dynamic site. A **Flask implementation** is planned. * Clear and **magic-free**. You can see exactly what's happening and why. No magic, no configuration files, no hidden behaviour. The code is so short you can read it.Minimal example ---------------
@@ -126,26 +128,47 @@ More information
An ampoule is smaller than a flask. Because it is related to Flask (it uses Jinja2) but is a much smaller static version of it, the name makes sense. ### Why not use Jekyll, Hugo, or Pelican?#### JekyllJekyll is Ruby, and it's very much Ruby, in fact, it's 17,000 lines of Ruby. Configurationis done only in YAML. It's hard to extend, and the plugin and theme systems areoverengineered. It's also limited (no OOP, not even multiple index directories). And for theFlask users like me, it uses a template language that is very similar to Jinja2, but it'snot Jinja2, so templates aren't reusable. I've actually used Jekyll, and it's not nice.#### HugoHugo is actually pretty interesting, but it's not as flexible, because it's not scriptable,and a compiled language is not appropriate for this. Did I mention it also has anoverengineered theme system? And it's even larger, a whooping 133,000 lines of Go!You can never know it all.#### PelicanPelican is opinionated and relies on plugins for everything. It's extremely limited, infact it can only do blogs. It also can't be portable and implemented in Flask.### Why even use a static site generator?You've got two other options. Let's examine them.### What about the other static site generators? There are many static site generators out there, but they all have their own problems. In particular, I haven't seen one that uses code to describe the site, rather than a configuration file. This makes it much more flexible and powerful. Also, Ampoule is familiar to Python programmers, because it's written in Python and uses Jinja2, a templating engine that is also used in Flask. It's even the smallest static site generator: 1. Hugo: written in Go, uses go html/template, and it has 133k lines of Go, not counting comments or blanks. 2. Jekyll: written in Ruby, uses Liquid, and it has 17300 lines of Ruby, not counting comments or blanks. Interestingly, it's got more Markdown than Ruby. 3. Gatsby: they call it a framework, and rightfully so, because it's overkill for actually static (i.e. for publishing content) sites, even though JS people use it for precisely that purpose. It's written in JavaScript, uses React, and it's git 380k lines of JavaScript and TypeScript combined. (For comparison, it's over 1/100 of Linux itself, which is HUGE considering it uses a high-level language and only has to do so much.) 4. Pelican: written in Python, uses Jinja2, and it has 12400 lines of Python, not counting comments or blanks. 5. Docusaurus: written in TypeScript, uses React (of course, because it's made by Facebook), and it has 140k lines of TypeScript and JavaScript combined. 6. VuePress: written in JavaScript, uses Vue, and it has 11k lines of JavaScript, Vue and TypeScript combined. 7. Zola: written in Rust, uses Tera, and it has 17k lines of Rust, not counting comments or blanks. Also, it's designed to be monolithic and not extensible at all. Whereas I have only got 750 lines of Python, not counting comments or blanks. Add the script to generate the site, and it's still under 1000 lines. I don't want to criticise other static site generators, they all do some things well, but they're not what I want. I want a simple, small, flexible and versatile static site generator that is low-maintenance and easy to use. I don't know about you, but maybe you want the same thing. The JS-based ones are particularly unsuitable for most people, because they're slow, bloated, hard to install, and most often actually generate an SPA, which is not what you want for a blog or documentation or web book or anything like that. ### Why generated static sites? If you don't want generated static sites, you've got two other options.#### Dynamic sites * bloated;
@@ -167,7 +190,8 @@ You've got two other options. Let's examine them.
* markup languages must be manually converted; With a *generated* static site, you get the best of both worlds. It's the best publishing platform, because it's just files.platform, because it's just files, but it still provides the convenience of just writing content and having it magically appear on the site and formatted correctly.How to install --------------
@@ -211,9 +235,11 @@ one argument, the value to be filtered, and return the filtered value.
A decorator that registers a test function with the site. The function should take at least one argument, the value to be tested, and return a boolean. #### def `build(self)`#### def `build(self, dont_delete: typing.Optional[list[str]] = None)`Build (save) the site to the build directory it was constructed with. This will create the directory if it does not exist, clear it (but not delete it) and then write all the pages. You can set `dont_delete` to a list of files that should not be deleted when the directory is cleared, for example, the `.git`.#### `context: dict[str, typing.Any]` A dictionary containing names that are available to all pages. It can be overriden by the
projects/echo.md
@@ -0,0 +1,40 @@
--- title: Echo source-url: https://roundabout-host.com/roundabout/itec24-echo --- Echo is a very basic status tracker for web endpoints. I don't recommend you use it. It was made for a programming competition (hackathon) organised by the Automation and Computing faculty of the Politehnica University of Timișoara, in 3 days, alone. I decided to publish it because it might be useful for someone and doesn't hurt me to have it online, and the contest encourages publishing the works. It uses Flask, SQLAlchemy and PostgreSQL. I wanted to use htmx, but I didn't have time to learn it, because one of the contest mentors recommended it to me 2 hours before the end of the contest. Therefore, there is really no JS, it's form-based. The app won the 7th place out of 24 teams. Luckily I did learn about htmx and now I will use it in my other projects. Features -------- * User registration * User login/logout * App and endpoint creation * Endpoint status change * Endpoint status history * Pinging endpoints * Customisable ping interval and stability threshold (since when must all endpoints be OK to consider the app OK) * ... and that's it Licence ------- Copyright 2024. Use of the works is permitted provided that this instrument is retained with the works, so that any entity that uses the works is notified of this instrument. **DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY.**
projects/roundabout.md
@@ -5,7 +5,7 @@ source-url: https://roundabout-host.com/roundabout/roundabout
The roundabout is a **git repository hosting** server software. It is designed to be a complete alternative to GitHub, GitLab, BitBucket, Gogs/Gitea/Forgejo, and other similar services. It is still in development and not yet ready for production use. As of version 0.2.0 developmentis still in development and not yet ready for production use. As of version 0.3.0 developmentstage, it supports: * User registration
@@ -20,36 +20,70 @@ stage, it supports:
* Favourite repositories (subscriptions) * Commit views and diffs * Themeing * Static site hosting * Really basic search * Markdown, but only for files (see below)For now, it doesn't support, but certainly will before the 1.0.0 release:For now, it doesn't support, but certainly **will** before the 1.0.0 release:* Code review features (like comments on commits, for now you'll use the forum), something like Google Docs comments is planned * Static site hosting* CI/CD * Wiki* API * Native clients* Git over SSH or other protocols* Repository metadata* Repository metadata (licence, topics, language, etc.)* Decentralization * Packaging * Code syntax highlighting * Any kind of search* Any kind of statistics * Web-based code editing * Any kind of integration with other services* Users changing passwords * Admin panel * Forum labels * User mentions * Markdown comments (we just need to cache the HTML so it won't be too slow) It won't support: * Wikis (why have another interface just for markdown, when you can use your own repo and publish it as a static site?) * Issues (forum does it already) I'm still not sure about: * Project boards (what about making label grouping instead?) * Advertising (don't worry, instances could disable it, and logged-in users could also disable it for free, and it won't track anyone, no video, animation, sound, popups, overlays, or JS) * Paste service (does it really work well with Git? Couldn't you just use a repo for that?) * Git over SSH or other protocols (do people need it? HTTPS does the same things, and it's easier to set up; doesn't require daemons) * Native clients (Android development is hard, iOS is hostile, and on desktop it's not needed, there are GUI git clients that work with any server, for social features web is fine) * IDE plugins (sounds good, but it's hard work)The roundabout is written in flask, a Python web framework. It uses SQLAlchemy for database management. For light UI interactivity it uses htmx.management. For light UI interactivity it uses htmx and some vanilla JS. It does some GitPython calls for basic operations, but mostly calls git with subprocess. Repositories are non-bare because this allows the server to understand the repository and can lead to some performance gains since querying git is not required. The server is designed to be run on a single machine but decentralisation will be added in the future, but it won't be automatic, you'll have to choose a server to use. roundabout-host.com -------------------The official instance of the roundabout, roundabout-host, is hosted at [roundabout-host.com](https://roundabout-host.com). Anyone can register and create repositories there. However, we ask that you do not rely on it and always keep your repos locally as well. Uptime is not guaranteed, and data loss is possible. The server is not backed up.In the future it may require payment for some features, but **the program it runs will always be free**. Payment will not be required to lift artificial limitations, but to support server-intensive features like CI/CD.server-intensive features like CI/CD. Some free usage for useful projects will always be provided on demand. Additionally, we may have advertising on the site. It will be unobtrusive and not track you. Logged-in users will be able to disable it for free. We will never have video, animation, sound, popups, overlays, or JS ads. Ads will be relevant to the content of the site, but they won't be personalised or use cookies. This just means no car, insurance, supermarket, or other unrelated ads. Most likely we will use EthicalAds, which is itself free software.The roundabout program is licensed under the AGPL licence, version 3.0 or, at your option, any later version.later version. Whatever I decide to do for roundabout-host, I can't pull the rug from under you, you can always run your own instance.
projects/waste.md
@@ -0,0 +1,111 @@
--- title: Waste detection source-url: https://roundabout-host.com/roundabout/waste-detection --- An YOLO model specifically trained to detect waste in images. We collected a custom dataset of waste, classified and annotated it, and trained the model using YOLOv8 on Keras. The model is able to detect the position and class of waste in images. It can separate the following classes of waste: * Plastic * Metal * Paper * Glass * Organic * Wood * Textile * Medical * Electronic * Other There are actually over 90 classes, but they are grouped into these ones because there is only a small amount (in the 1-2 digits) of samples for each class. The model is able to detect multiple classes in the same image, or acknowledge that there is no waste in the image. YOLO is used pretrained on the COCO dataset, and then fine-tuned on our dataset. This is until there are enough samples for each class to train the model from scratch. Contributions are welcome. If you have a dataset of waste, please share it with us. We will annotate it (if it's not already) and train the model on it. You don't need technical knowledge to contribute. If you can take photos with a phone and make a ZIP of them, you can contribute. If you can draw rectangles around objects with the mouse, you can contribute. If you can drop photos into folders corresponding to their class, you can contribute. Of course, if you do have technical knowledge, you can help with the model training, testing, and optimisation. You can also improve the training code and better process the dataset. Licence ------- Unless otherwise stated, the software (source code) in this repository is licenced under the GNU Affero General Public License, with an additional permission in section 7. A copy of the licence is located in the file `LICENCE-GNU-AGPL.md` in this directory. > This program is free software, you can redistribute it and/or modify it under the terms of GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. > > This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of or FITNESS FOR A PARTICULAR PURPOSE. See the General Public License for more details. > > You should have received a copy of the the GNU Affero General Public License, along with this program. If not, see <https://www.gnu.org/licenses/>. > > ##### Additional permission under the GNU Affero GPL version 3 section 7: > If you modify this program, or any covered work, by linking or combining it with other code, such other code is not for that reason alone subject to any of the requirements of the GNU Affero GPL version 3. Unless otherwise stated, the annotations in this repository are dual-licensed under either of these licences: * [Creative Commons Attribution Share-Alike 4.0](https://creativecommons.org/licenses/by-sa/4.0/). To view a copy of this license, read the `LICENCE-CC-BY-SA.md` file, visit http://creativecommons.org/licenses/by-sa/4.0/ or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA. * [Creative Commons Attribution Non-Commercial 4.0](https://creativecommons.org/licenses/by-nc/4.0/). To view a copy of this license, read the `LICENCE-CC-BY-NC.md` file, visit http://creativecommons.org/licenses/by-nc/4.0/ or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA. You do not have to comply with the terms of both licences. Choose one and comply only with it. The images in the repository are licensed depending on their source: * If the file name has the `original` prefix (or no prefix at all), the images are licenced under the same terms as the annotations (see above). * If the file name has the `trash-detection` prefix, it comes from https://universe.roboflow.com/nora-slimani/trash-detection-otdmj and is licensed under [Creative Commons Attribution 4.0](https://creativecommons.org/licenses/by/4.0/). * If the file name has the `ffml` prefix, it comes from https://www.kaggle.com/datasets/cristeaioan/ffml-dataset and is licensed under [Creative Commons Attribution Share-Alike 4.0](https://creativecommons.org/licenses/by-sa/4.0/). * If the file name has the `dwc` prefix, it comes from https://www.kaggle.com/datasets/arkadiyhacks/drinking-waste-classification and is public domain. * If the file name has the `hitl` prefix, it comes from https://www.kaggle.com/datasets/humansintheloop/recycling-dataset and is public domain. I hope I didn't infringe on any licences or miss any sources. If you think there is a problem, please send me an email at <mailto:root@roundabout-host.com> and I'll remove the infringing files. The VIA application shipped in this repository (located at the `/via` path) is licensed under the BSD licence. > Copyright (c) 2016-2021, Abhishek Dutta, Visual Geometry Group, Oxford University and VIA Contributors. > All rights reserved. > Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: > > Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. > > Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. > > THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
projects/wordle.md
@@ -0,0 +1,53 @@
--- title: Teletype Wordle source-url: https://roundabout-host.com/roundabout/tty-wordle --- Just like the original Wordle, you have to guess a 5-letter word in 6 tries and it tells you how many letters are correct and in the right position, how many are correct but in the wrong position, and how many are not in the word at all. The only difference is that this one is played in the terminal. It's a great SSH toy for when you're bored. The game is written in Python and uses the `termcolor` library for coloured output. Since it uses `colorama`, it works on Windows as well as Unix-like systems. ![A game of teletype Wordle](/static/photos/wordle.png) You can also customise the game quite a bit. You can change the number of tries, the list of words to guess from (and length will be inferred from that), and the list of words to randomly choose an answer from. You can also enable the analyser, which shows all the letters that have been found so far. Let's make someone play it with the full dictionary :) There is also a hard mode, where you must use all the letters that have been found in your guesses. ``` usage: tty-wordle [-h] [-a] [-x] [--delay DELAY] [-l WORDS] [-n ANSWERS] [-t GUESSES] A Wordle for your console. options: -h, --help show this help message and exit -a, --analyser add the analyser, a row of all found letters -x, --hard enable hard Wordle: you must use all found letters in your guesses --delay DELAY time to show error messages for, in seconds -l WORDS, --list WORDS file to pull allowed guesses from -n ANSWERS, --answers ANSWERS file to pull a random answer from -t GUESSES, --tries GUESSES number of tries ``` Also, this is how the analyser looks like: ![The analyser in teletype Wordle](/static/photos/wordle-analyser.png) If you press ^C it asks you whether you want to give up or not. If you do, it shows you the answer. If you don't, it continues the game. You can press ^C again to close it and never see the answer. Licence ------- Apache 2.0
static/photos/wordle-analyser.png
static/photos/wordle.png
static/style.css
@@ -81,7 +81,9 @@ nav {
justify-content: space-between; align-items: center; box-sizing: border-box; height: 4rem;min-height: 4rem; padding: 1rem 0; margin: 0 0.5rem;} nav > ul {
@@ -98,6 +100,29 @@ nav > ul {
text-transform: uppercase; } @media (max-width: 576px) { nav > ul { flex-flow: row wrap; justify-content: center; row-gap: 0.5rem; } nav { flex-direction: column; gap: 1rem; } header { position: static; } } @media (max-width: 720px) { nav { flex-direction: column; padding: 0.5rem; gap: 0.5rem; } } nav > ul > li > a { font-weight: normal; text-decoration: none;
@@ -243,6 +268,19 @@ pre {
transition: 400ms; } @media (max-width: 512px) { .project-title { flex-direction: column; align-items: center; } .project-title > a { min-height: 1.5lh; margin: auto; padding: 0 2rem; } } .project-title > a:hover { border-width: 8px; }
@@ -269,4 +307,26 @@ strong, em {
font-feature-settings: "zero" on; font-weight: 625; text-align: center; }} blockquote { font-family: "Source Serif", serif; font-weight: 350; border-top: 0.5px solid #009688; border-bottom: 0.5px solid #009688; padding: 0.5rem 2rem; margin: 0; } blockquote > p:first-child { margin-top: 0; } blockquote > p:last-child { margin-bottom: 0; } img { max-width: 100%; height: auto; }
templates/default.html
@@ -25,7 +25,7 @@
</main> <footer> <p>Page generated on {{ timestamp.strftime("%A, %e %B %Y at %H:%M:%S") }}</p> <p>© Roundabout developer</p><p xmlns:cc="http://creativecommons.org/ns#" >This work is marked with <a href="https://creativecommons.org/publicdomain/zero/1.0/?ref=chooser-v1" target="_blank" rel="license noopener noreferrer" style="display:inline-block;">CC0 1.0 Universal</a> (🄍). No rights reserved.</p></footer> </body> </html>