Compare commits

..

5 Commits

Author SHA1 Message Date
lol3rrr
065cfbb230 Add some more ideas 2026-03-27 07:57:58 +01:00
lol3rrr
b11b3ee754 Improve some more stuff 2026-03-25 08:07:27 +01:00
lol3rrr
007b9f86fc Add section about how the modelling should work 2026-03-24 01:13:13 +01:00
lol3rrr
18bc5d61d6 Write some more about quickfacts 2026-03-23 19:15:24 +01:00
lol3rrr
fc183f32ee Fix small misrendering 2026-03-20 21:46:41 +01:00
8 changed files with 492 additions and 11 deletions

View File

@@ -116,9 +116,9 @@ that might be running on different hosts.
2. `/sbin/sysctl -w net.ipv6.conf.all.proxy_ndp=1`
5. Configure [Jool](https://www.jool.mx/en/index.html)
1. `/sbin/modprobe jool`
2. `jool instance add "example" --netfilter --pool6 2001:0bc8:1640:6554:0:0:0:0/96`[^nat64_setup]
3. `jool -i "example" pool4 add --udp 51.158.177.228 1-65535`[^pool4_setup]
4. `jool -i "example" pool4 add --tcp 51.158.177.228 1-65535`[^pool4_setup]
2. Setup NAT64 `jool instance add "example" --netfilter --pool6 2001:0bc8:1640:6554:0:0:0:0/96`
3. Setup pool4 for UDP `jool -i "example" pool4 add --udp 51.158.177.228 1-65535`
4. Setup pool4 for TCP `jool -i "example" pool4 add --tcp 51.158.177.228 1-65535`
6. ndppd for neighbor discovery
1. In `/etc/ndppd.conf`
```

View File

@@ -0,0 +1,12 @@
<svg version="1.1"
baseProfile="full"
width="300" height="200"
xmlns="http://www.w3.org/2000/svg">
<rect width="100%" height="100%" fill="red" />
<circle cx="150" cy="100" r="80" fill="green" id="test" onclick="hide()" />
<text x="150" y="125" font-size="60" text-anchor="middle" fill="white">SVG</text>
</svg>

After

Width:  |  Height:  |  Size: 336 B

View File

@@ -1,12 +1,333 @@
+++
title = "Quickfacts - Part 1"
date = 2026-05-01
description = "The first part of a series about my Quickfacts project"
title = "Quickfacts - Part 1: The Mental Model"
date = 2026-04-02
description = "Building a Mental Model"
draft = true
[taxonomies]
categories = ["Programming"]
tags = ["Factorio", "Rust"]
[extra]
toc = true
+++
The first real entry in my series about my quickfacts project.
For a small introduction, see the [intro blogpost](@/quickfacts-intro/index.md)
<!-- more -->
# Idea
- Everything is a graph
- Each Entity is a node in the graph
- What extra information to include
- Each Edge represents that certain items can move from one node to the other
- Specify what items can move over the edge (for example because of filters)
- Outgoing and incoming priority
- Capacity ?
- What extra information to include
# Interactions
The Construction basically comes down to a large table mapping the different interactions between all the types of entities.
## Belts
For the purpose of my analysis, you can split a belt into the two sides, as they act independent of one another.
### Belt-Belt
Direct 1-to-1 connection, is the simplest and most common way two belts are connected.
In this configuration you have 1 belt basically forwarding everything onto another belt, where each side of the source belt feeds into the corresponding side of the target belt.
For example if you have a simple line of belts forming a long line, they are all direct 1-to-1 connected.
Sideloading, is a more special case. This happens when the target belt already has another belt connected and now the new source belt is connected from the side (as the name suggests).
In this configuration both sides of the source belt are going into one side of the target belt.
### Belt-Splitter
The splitter can only accept direct 1-to-1 style connections going into it, from belts or the output of underground belts.
The ouput of a splitter basically acts the same way as a normal belt would.
### Belt-UndergroundBelt
The input side of the underground supports direct 1-to-1 connections, if the other source belt is coming from the same direction (so no turn is being made).
The input can also be sideloaded, however opposed to normal belt sideloading, only the upstream side of the source belt will feed into the target belt and the other side of the source belt will not be connected.
The output again acts like a normal belt.
### Belt-Direct output machines (miner, recycler, etc.)
Sideloading
TODO What to do if at the "head" of a beltline
## Inserter
### Inserter-Belt
TODO
# Modelling
Each node essentially has a set of input and output "slots", which have different priorities.
Each slot can have filters attached, from both the upstream and downstream side.
Filters from the upstream side are mostly dependent on configuration, like filters on splitters.
Filters from the downstream dependent on their slot filters and also their type, like machines will apply filters to their upstream slots that constrain it to items that it needs/can process.
For transport nodes (belts, inserter, etc.) they should forward their downward filters and combine them with their own filters
To collect input items, a node goes through its input slots in decreasing priority and collects everything that fits its own criteria.
To distribute the items, a node goes through its output slots in decreasing priority and puts as many items as possible in that slot.
## Constraints
The idea with constraints is basically to have some logic formula that constraints the items and their rates along an edge.
So for example if an inserter has a filter configured, its constraints will only allow the specific items as configured by the filter.
Another example is an assembly machine, which will impose constraints on anything going into it, to only be the items that it needs for the recipe.
Constraints can then be propogated and combined upstream, so that an inserter going into an assembly machine also only selects the items that can actually go into that machine.
For propogation, the constraints will be combined by either an intersection or a union.
For example an inserter will perform an intersection, because it can only accept things that fit its specific configuration and any downstream configuration.
But a belt will perform a union, because might have constraints coming from inserters taking from them and downstream belts so the items can take either path.
Basically the constraints for every edge will be combined using an intersection with the constraints of the node itself, and then all downstream edge constraints will be combined using a union to form the final upstream constraint.
JOIN Operator: used to combine multiple "or" constraints, for example for combining downstream constraints.
This is done by adding all the limits for items together.
CHAIN Operator: used to combine multiple "and" constraints.
### Representation
A tree with 3 levels, each doing something different
The lowest level, selects by item.
The next level limits the rate per item.
The top level limits the total throughput.
### Examples
{% carousel() %}
{% carousel_item() %}
Before propogation
{% mermaid() %}
---
title: Inserter Feeding into Assembler
---
flowchart BT
subgraph assembler
direction BT
root_1["unlimited"]
1_first_limit["<= 5/s"]
1_first_items["iron"]
1_second_limit["<= 10/s"]
1_second_items["copper wire"]
1_first_limit --> root_1
1_second_limit --> root_1
1_first_items --> 1_first_limit
1_second_items --> 1_second_limit
end
subgraph inserter with iron filter
direction BT
root_2["total <= 20/s"]
2_first_limit["<= 20/s"]
2_first_items["iron"]
2_first_limit --> root_2
2_first_items --> 2_first_limit
end
{% end %}
{% end %}
{% carousel_item() %}
After first propogation step
{% mermaid() %}
---
title: Inserter Feeding into Assembler
---
flowchart BT
subgraph assembler
direction BT
root_1["unlimited"]
1_first_limit["<= 5/s"]
1_first_items["iron"]
1_second_limit["<= 10/s"]
1_second_items["copper wire"]
1_first_limit --> root_1
1_second_limit --> root_1
1_first_items --> 1_first_limit
1_second_items --> 1_second_limit
end
subgraph inserter with iron filter
direction BT
root_2["total <= 20/s"]
2_first_limit["<= 20/s && <= 5/s"]
2_first_items["iron"]
2_second_limit["<= 0/s && <= 10/s"]
2_second_items["copper wire"]
2_first_limit --> root_2
2_second_limit --> root_2
2_first_items --> 2_first_limit
2_second_items --> 2_second_limit
end
{% end %}
{% end %}
{% carousel_item() %}
After second propogation step
{% mermaid() %}
---
title: Inserter Feeding into Assembler
---
flowchart BT
subgraph assembler
direction BT
root_1["unlimited"]
1_first_limit["<= 5/s"]
1_first_items["iron"]
1_second_limit["<= 10/s"]
1_second_items["copper wire"]
1_first_limit --> root_1
1_second_limit --> root_1
1_first_items --> 1_first_limit
1_second_items --> 1_second_limit
end
subgraph inserter with iron filter
direction BT
root_2["total <= 20/s"]
2_first_limit["<= 5/s"]
2_first_items["iron"]
2_second_limit["<= 0/s"]
2_second_items["copper wire"]
2_first_limit --> root_2
2_second_limit --> root_2
2_first_items --> 2_first_limit
2_second_items --> 2_second_limit
end
{% end %}
{% end %}
{% carousel_item() %}
After final propogation step
{% mermaid() %}
---
title: Inserter Feeding into Assembler
---
flowchart BT
subgraph assembler
direction BT
root_1["unlimited"]
1_first_limit["<= 5/s"]
1_first_items["iron"]
1_second_limit["<= 10/s"]
1_second_items["copper wire"]
1_first_limit --> root_1
1_second_limit --> root_1
1_first_items --> 1_first_limit
1_second_items --> 1_second_limit
end
subgraph inserter with iron filter
direction BT
root_2["total <= 20/s"]
2_first_limit["<= 5/s"]
2_first_items["iron"]
2_first_limit --> root_2
2_first_items --> 2_first_limit
end
{% end %}
{% end %}
{% end %}
# Examples
## Belt Line with one slower belt
{% carousel() %}
{% carousel_item() %}
Initial configuration
{% mermaid() %}
flowchart LR
Src
T1
T2
T3
Output
Src -->|x <= 20| T1
T1 -->|x <= 20| T2
T2 -->|x <= 10| T3
T3 -->|x <= 20| Output
{% end %}
{% end %}
{% carousel_item() %}
Raw Constraint Propogation
{% mermaid() %}
flowchart LR
Src
T1
T2
T3
Output
Src -->|x <= 20 && x <= 20 && x <= 10 && x <= 20| T1
T1 -->|x <= 20 && x <= 10 && x <= 20| T2
T2 -->|x <= 10 && x <= 20| T3
T3 -->|x <= 20| Output
{% end %}
{% end %}
{% carousel_item() %}
Simplified Constraint Propogation
{% mermaid() %}
flowchart LR
Src
T1
T2
T3
Output
Src -->|x <= 10| T1
T1 -->|x <= 10| T2
T2 -->|x <= 10| T3
T3 -->|x <= 20| Output
{% end %}
{% end %}
{% end %}
## TMP
{% carousel() %}
{% carousel_item() %}
Initial Configuration
{% mermaid() %}
flowchart TD
Src
T1
Splitter
T2
T3
Output1
Output2
Src --> T1
T1 --> Splitter
Splitter --> T2
Splitter --> T3
T2 --> Output1
T3 --> Output2
{% end %}
{% end %}
{% carousel_item() %}
Raw Propogation
{% end %}
{% end %}
# Conclusion

View File

@@ -1,23 +1,39 @@
+++
title = "Quickfacts - Intro"
date = 2026-05-01
date = 2026-04-01
description = "An introduction to my Quickfacts project"
draft = true
[taxonomies]
categories = ["Programming"]
tags = ["Factorio", "Rust", "Quickfacts"]
[extra]
toc = true
+++
Quickfacts is a long ongoing hobby project of mine, with the aim of being able to analyze most factorio blueprints.
The goal would be to have a website or application, which you can give most blueprints and it then can tell you things about how the blueprint will perform.
A small introduction to my ongoing quickfacts project.
A set of tools/progams to automatically analyze factorio blueprints, basically the LLVM of factorio.
I have to no idea if this will ever work to a good degree or how far I will get, but I want to share this journey and document my ideas and approaches.
## Analysis Goals
<!-- more -->
# Motivation
I love playing factorio and I especially love optimizing my builds and going down the rabbit hole on analyzing blueprints.
However given my interest in analysis of computer programs and formal methods, I thought why not combine them, because if you squint with your eyes these problems look very similar.
At the end of this road, I would love to have a website, where I can paste a blueprint I am interested in, select/configure an analysis and then get the results.
# Analysis Goals
- Determine the output rate given a fixed input rates (and how much of the input is actually being consumed)
- Check how well a belt-balancer works
- Highlight bottlenecks in a setup
## Known Limitations
# Known Limitations
- Any form of circuit networks/logic
- Trains
- Spoilage (for now)
# Approach
I am going to develop a rough mathematical/formal model for factorio and its' semantics.
Then I hope to do something similar to data-flow analysis and essentially express all the logic and analysis as a set of mathematical steps/functions to apply.

View File

@@ -0,0 +1,126 @@
<ul class="carousel_{{ nth }}">
{{ body | safe }}
</ul>
<style>
.carousel_{{ nth }} {
width: 100%;
/* height: 300px; */
padding: 20px;
display: flex;
gap: 4vw;
overflow-x: scroll;
scroll-snap-type: x mandatory;
/* this will hide the scrollbar in mozilla based browsers */
overflow: -moz-scrollbars-none;
scrollbar-width: none;
/* this will hide the scrollbar in internet explorers */
-ms-overflow-style: none;
}
/* this will hide the scrollbar in webkit based browsers - safari, chrome, etc */
.carousel_{{ nth }} ul::-webkit-scrollbar {
width: 0 !important;
display: none;
}
.carousel_{{ nth }}>li {
list-style-type: none;
/* background-color: #eeeeee; */
/* border: 1px solid #dddddd; */
padding: 20px;
flex: 0 0 100%;
scroll-snap-align: center;
}
.carousel_{{ nth }}>li:nth-child(even) {
/* background-color: cyan; */
}
.carousel_{{ nth }}>li::after {
visibility: hidden;
}
.carousel_{{ nth }}::scroll-button(*) {
border: 0;
font-size: 2rem;
background: none;
color: white;
opacity: 0.7;
cursor: pointer;
}
.carousel_{{ nth }}::scroll-button(*):hover,
.carousel_{{ nth }}::scroll-button(*):focus {
opacity: 1;
}
.carousel_{{ nth }}::scroll-button(*):active {
translate: 1px 1px;
}
.carousel_{{ nth }}::scroll-button(*):disabled {
opacity: 0.2;
cursor: unset;
}
.carousel_{{ nth }}::scroll-button(left) {
content: "◄" / "Previous";
}
.carousel_{{ nth }}::scroll-button(right) {
content: "►" / "Next";
}
.carousel_{{ nth }} {
anchor-name: --my-carousel_{{ nth }};
}
.carousel_{{ nth }}::scroll-button(*) {
position: absolute;
position-anchor: --my-carousel_{{ nth }};
}
.carousel_{{ nth }}::scroll-button(left) {
right: calc(anchor(left) - 70px);
bottom: calc(anchor(bottom) + 10px);
}
.carousel_{{ nth }}::scroll-button(right) {
left: calc(anchor(right) - 70px);
bottom: calc(anchor(bottom) + 10px);
}
.carousel_{{ nth }} {
scroll-marker-group: after;
}
.carousel_{{ nth }}::scroll-marker-group {
position: absolute;
position-anchor: --my-carousel_{{ nth }};
bottom: calc(anchor(bottom) + 10px);
justify-self: anchor-center;
display: flex;
justify-content: center;
gap: 20px;
}
.carousel_{{ nth }}>li::scroll-marker {
content: attr(data-accName);
width: 16px;
height: 16px;
background-color: transparent;
border: 2px solid white;
border-radius: 50%;
overflow: hidden;
text-indent: 16px;
}
.carousel_{{ nth }}>li::scroll-marker:target-current {
background-color: white;
}
</style>

View File

@@ -0,0 +1,3 @@
<li>
{{ body | safe }}
</li>

View File

@@ -0,0 +1,2 @@
{% set data = load_data(path=path) -%}
{{ data | safe }}

View File

@@ -23,6 +23,7 @@ index_format = "elasticlunr_json"
[markdown]
external_links_target_blank = true
insert_anchor_links = "left"
[markdown.highlighting]
theme = "catppuccin-mocha"