Planeta Blogów WMI UAM

November 27, 2023

Borkowski Marcin

2023-11-27 Clocking in to parent entries

Like many, many Emacs users these days, I’m a heavy user of Org mode. In fact, both of my blogs are written in Org. And while this very blog usually has fairly short entries, my other blog has much longer posts, divided into subsections. This creates a minor problem for me. I track time I spend on writing, but I don’t want to track time spent on individual sections of a blog post. (The reason is a bit complicated. These sections are often pretty short, and I tend to spend my writing time in chunks of 25 minutes, and I have a Beeminder goal to have at least 10 of such chunks every day, so if possible, I prefer not to divide my work time into too short stretches.)

In other words, even if I am in some lower-level heading, when I clock in, I want Org to clock in in the parent heading. Emacs being Emacs, I figured there must be a way to make that happen automatically.

It seems there are at least two ways of achieving this. One is advising the clock-in function, and the other is using one of the several clock-related hooks. It is known that hooks are the preferable way – the Emacs Lisp reference says,
If it is possible to do the same thing [modify a function’s behavior] via a hook, that is preferable.

M-x apropos-variable RET org.*clock.*hook gives several answers, and the most natural candidate seems to be org-clock-in-prepare-hook. A cursory examination of Org sources suggests that using this hook may solve my issue. So, let’s get to work!

Let’s begin with deciding how to mark headings which should be “skipped” when clocking in. Assume that I have the following file structure

* Main entry
** First subentry
** Second subentry

and clocking in when in First subentry should actually clock in the Main entry. How to tell Org this is what I want? An obvious way is to use some tag on First subentry, but I don’t like this idea. I want the “subentries” to be lightweight and easy to add, and having to remember to tag them goes against this goal. I would very much prefer to be able to mark the Main entry as the one to clock in to whenever the user starts work in any of its subentries.

So, let’s get started. (I have to admit that I needed several failed attempts to get this right.) What we need is a function which does this:

  • if the current entry has the CLOCK_HERE property, stay at it;
  • otherwise, go up one level;
  • rinse and repeat unless we get to the top level, in which case get back to where we started.

Here is my code.

(defun go-up-until-clock-here ()
  "Go up in Org hierarchy until an entry with property CLOCK_HERE.
If no such entry is found, leave the point where it was."
  (let ((dest (point)))
    (while (if (org-entry-get (point) "clock_here")
               (not (setq dest (point)))
             (org-up-heading-safe)))
    (goto-char dest)))

(add-hook 'org-clock-in-prepare-hook #'go-up-until-clock-here)

This code is a great illustration of what you (usually) shouldn’t do. It’s extremely concise, has no comments, and – dare I say – is a bit clever. Here’s how it works.

The body of the while loop is empty, so the loop will just repeatedly run the if form until it evaluates to nil. That can happen in two situations.

One of them is when the entry the point is in has the CLOCK_HERE property (by the way, Org mode heading properties are case insensitive), the dest variable will be set to where we are, the not form will evaluate to nil and the while loop will end. This may happen during the first iteration if we happen to start in a “clock here” entry or later, when we get to one while moving up. In either case, the subsequent (goto-char dest) will do nothing, since dest will coincide with (point) – but it won’t hurt, either.

The other way the loop may end is when there is no parent heading to go and org-up-heading-safe returns nil. This means that we traveled to the top of the hierarchy of headlines without finding one with the CLOCK_HERE property. In that case, dest will be what it was first defined to be, that is, the position of point before our function was called, and (goto-char dest) will return to that place as planned.

Now the only remaining thing is to make sure that every headline which starts a blog post has the CLOCK_HERE property set. My little blog engine has the org-clive-create-page command, but I didn’t want to add code very specific to my usage there. (I suspect I am the only user of Org Clive, but maybe I am not, or I will be not.) Of course, that means that what I want is to add a hook to that command. And that is precisely what I have just pushed to master – the org-clive-after-create-page-hook variable. I added this to my init file:

(defun org-add-clock-here-property ()
  "Add the `CLOCK_HERE' property to the current node."
  (org-set-property "CLOCK_HERE" "t"))

(add-hook 'org-clive-after-create-page-hook #'org-add-clock-here-property)

and now I don’t have to worry about adding the CLOCK_HERE property myself anymore.

As usual, Emacs lets you have it your way.

CategoryEnglish, CategoryBlog, CategoryEmacs, CategoryOrgMode

November 27, 2023 09:00 AM

November 13, 2023

Borkowski Marcin

2023-11-13 Coloring CamelCase

Some time ago one of the members of the Emacs mailing list asked about coloring CamelCase identifiers. His idea is to define two faces and have all “even” words in a camel case indentifier colored with one of them, and the “odd” words colored with the other one. The question suggests using some code from Glasses mode, which is a lesser-known Emacs feature which inserts undescores between words in camel case identifiers (and it does it using overlays, so the underscores are not really part of the buffer, they just look like this). My general rule is to avoid camel case whenever I can, but I sometimes use Glasses mode, especially when I have to deal with jsx files, where camel case is the standard.

It turns out that Glasses mode already has (almost) what is asked for. If you customize glasses-separator to be an empty string and glasses-face to be, for example, 'bold, Glasses mode makes all capital letters starting words in identifiers bold (which already helps a lot).

In order to color every other CamelCase subword with some face, however, one has to write a bit of Elisp. So, I set out to do just that, and started with looking at glasses.el.

One interesting feature of Glasses mode is that it uses overlays, which may seem a slightly controversial choice. Glasses mode is pretty old (it has at least two decades!), and overlays used to have performance issues when there were too many of them in one buffer. Fortunately, their implementation was changed in Emacs 29.1 and we no longer have to worry about that. A significant advantage of overlays in the context of Glasses mode is that they are “separate” from the text in the sense that killing text decorated with overlays and yanking it elsewhere loses them. This means that when you kill some text from a buffer with Glasses mode on and yank it in another buffer where it is off does not make the underscores (or faces for word-starting capitals) visible in the target buffer. Given that, I decided to also use overlays and not features like font-lock-keywords. This means that I can steal some code from glasses.el, too. (I could advise glasses-make-readable instead, but I think it will be more educational if I show how to build a minor mode from scratch. Note: as usual, you may freely use code shown in this blog, but this time it is explicitly covered by GPL3+, since a significant portion is copied from Emacs sources.)

All in all, it turned out that modifying Glasses mode to do what I want turned out to be pretty simple. To be fair, I ditched quite a few corner cases which are taken care for in glasses.el, like strings of continuous capital letters in CamelCase identifiers or digits (like in, say, PrintISO8601Date). I am almost sure that handling them would not be terribly difficult, though – I just treated my code as a proof of concept rather than a complete, production-grade solution.

CategoryEnglish, CategoryBlog, CategoryEmacs

November 13, 2023 07:00 AM

October 30, 2023

Borkowski Marcin

2023-10-30 My plans for 2023 - October update

It’s been another two months since my last update, so here we are again! It’s been a busy two months for me, though some plans still are not brought to the forefront (which is a shame, I know, but I can’t do everything).

Let’s start bluntly. Frankly, I’m tired of telling you all that the time for polishing/expanding the Elisp book “will come”. I decided to (finally) do something about it. As I mentioned last time, I devote more time to writing now, so I figured that my writing schedule slot on Mondays will be devoted to the Elisp book. We’ll see how it goes. (And yes, I started today, devoting some 15 minutes to it. Not much, but it’s a start.)

It’s been almost three months since I started my other blog I keep mentioning. There are 7 articles there now (plus a few pages like About, FAQ etc.), and the average length of an article is about 2300 words (and yes, last time I gave higher numbers, but that was because I counted words in the Org mode source – which, as it turns out, contains lots of things like drawers, properties etc. – instead of the resulting HTML. Sorry for my confusion.) For the record, one post there takes me about 5 hours of work on average, which is more than I expected. It doesn’t mean that I complain – I have a lot of fun writing them – but it is time-consuming.

So, I decided to finally disclose it here, in the hope that some of you might find it interesting. Here is the story. (Beware – “it is a long tail, certainly”, as Alice said to the mouse.)

As a prelude, let me mention that I very rarely watch movies, and I basically never watch tv shows. Some ten years ago (maybe even earlier) I made a conscious decision to avoid these time sinks – I have a lot of interesting and worthwhile things to do, and watching 30-60 minutes of usually second-rate tv every week (or even a few times a week, which is possible nowadays with the streaming services) is not something I want to spend (waste?) time on.

The story proper begins early fall 2020, when I was searching for some nice music on a well-known Internet service whose name rhymes with “Blue Cube”. As is generally known, the secret algorithms of that site have a habit of suggesting videos which might or might not be related to the actual interests of the person browsing it. In my case, I got a two minute clip from a certain tv series. I knew about its existence, of course – you can’t really call yourself a geek if you don’t – but, because of my decision, I never watched any of it. For better or for worse, I clicked on it (partially out of boredom and partially out of curiosity, I suppose, which is frankly a very dangerous mix when you’re browsing the Internet!), and I was instantly hooked…

And so here I am, three years later – a devout Whovian… I decided from the get go that I don’t want to watch Doctor Who alone, so I told my (then 10-years-old and also pretty geeky) daughter about that interesting series I found, and we started watching together. (We still haven’t fully converted my wife, who only watched a few episodes with us, but we’ll get there.) Since my young geek doesn’t speak English very well yet, and the quality of translation of subtitles I was able to find on the Internet is abysmal, I set out to translate subtitles for her. (That of course explains my ongoing interest in Emacs Subed mode, which supports editing srt subtitle files.) For over two years we usually watched one episode per week (which was rather demanding for me in terms of time spent on translation!), starting with Series 5 (as every Whovian is aware, this is a very reasonable decision when you watch Who with a kid). We stopped after about three quarters of Series 7, since the final episode of that series turned out to contain a huge spoiler (ha!) for the legendary two-parter towards the end of Series 4. We moved to Rose (don’t skip Nine, as they say, and they are completely correct!) and proceeded to Series 2. Then I figured that watching School reunion would be much more fun (note: the definition of “fun” for us Whovians apparently includes crying your eyes out) if we first got to know young Sarah Jane – so we made a break and watched The time warrior and Robot (and I will certainly watch more classic Who when the time comes, these two serials were a blast!). After resuming with Series 2 and finishing the Tennant specials we got to Eleven again and are now in Utah. Meanwhile, I am translating (much slower now) Series 8 (I have just started working on Time heist). By the way, I spent almost 400 hours on translating and syncing subtitles since October 2020, and it doesn’t look like I’m close to finishing;-).

Almost from the beginning I noticed that Doctor Who is far from a worthless time-killer – in fact, it touches very serious subjects pretty often, and does it in a rather surprising way. (In fact, it happened that after watching a 45-minute episode I had a serious and valuable 1-hour discussion about life with my youngling!) It is a well-known fact that Russel T. Davies is not exactly a conservative, and I suppose Steven Moffat’s view is not much different. I was therefore pretty astonished to notice that many times the message of Doctor Who is quite aligned with my personal Catholic views. After several such astonishments I started to consider sharing my general fascination with Doctor Who and my findings – some of them are staring you right in the face, but some are not very obvious. A decision to start a separate blog about Doctor Who was developing slowly, and about half a year ago I started acting on it.

As I mentioned in the previous update, I didn’t want to announce a blog with just one or two posts in it. While my regular readers should know well that I am capable of delivering new posts regularly, I wanted to have something to show before making a big announcement. Now that I’ve written seven posts (and the eighth one is under way), I feel much more confident, so here it is.

So, if you are a Doctor Who fan who likes to geek out over various minutiae, like when Rose predicts (not knowing that of course) what she’s going to be doing sixteen episodes later in her first episode, or who was the actor playing the Moxx of Balhoon and how that ties in with one of the main topics of The end of the world, or how Gwyneth plants seeds for the events of Father’s day in a seemingly throwaway comment, or how not one, but three characters in Dalek mirror various qualities of the Doctor’s, or how The long game gives me very strong Biblical vibes – head on to my second weblog, called Crimson Eleven Delight Petrichor. I am publishing a post there every other Saturday until I complete Series 1, and then I will decide what to do next. On the one hand, there are many later episodes I’d love to dive deep into. On the other hand, it takes quite some time, and it may turn out that I’ll have to slow down considerably. You can help me make the right decision by going to the Supporting the author page and following instructions there!

As for technicalities, the CEDP blog is (obviously) powered by Org Clive, and I have to say that it works wonderfully. One of the features I built into it are “publication dates” – every page has one, and when you build the site, you are asked about a date (with the default being today). Then, every post scheduled for later gets skipped. This way I can prepare drafts of future posts and not worry about them accidentally being published too early. I even have an idea to further enhance my workflow. At some point in time, I’m going to set up a minimal Emacs installation and a Git repository with the blog on the machine it’s hosted on, and add a Git hook so that every time I push any change, the new version of the site is generated directly in the public/ directory. Also, I plan to set up a simple cronjob to generate the site every 24 hours. This way I won’t even have to do anything on Saturdays when a new post should be published – it will just happen, assuming the post is written and pushed to the server in advance (so far, I almost always finished these posts at least a few days earlier than they were scheduled, and I hope to keep it that way!). I know of course that large and advanced blog engines like Wordpress have such functionality built in, but I’m glad it’s so easy to replicate in my tiny piece of code.

Speaking of the machine the blog is posted on – it is a very minimalistic VPS, offered by a small company located in southern Poland. If you want to rent a cheap GNU/Linux server in the cloud for some little (and maybe even not so little – they also have beefier machines) side project, check out mikr.us (note: the site is in Polish only). So far I am very satisfied with it, and I don’t expect that to change.

Ok, enough about this project of mine (at least for now). I kept it in secret for quite a while, so please forgive me for spending considerable time to finally reveal it. It definitely falls into “labor of love” category, so I could write on and on. Also, don’t hesitate to comment here or send me an email (there are no comments on CEDP, a seemingly strange choice which is explained in the FAQ page) if you are a fellow Whovian and want to tell me about it (even if that comment would be just “Fantastic”, “Allons-y”, “Geronimo” or a picture of your eyebrows;-)).

For now, my writing time is fully used up – between this blog, my other blog, and another project I’m now doing with an old friend, there is not much time left. In fact, there is no time left. This means, that the web extensions book is now officially postponed indefinitely. (Mind you: that does not mean “canceled”.) If you counted on that book being written soon – I am really sorry. These were plans, not promises, and apparently no plan survives first contact with the enemy. But then again – telling me in an emal that you cant this book earlier may influence my decisions in 2024.

As for the other projects – as said above, I am now working on some math-related stuff with a friend and still devote just a little time to some programming side projects. The rest of the time is taken by personal and family commitments, which seem to need a bit more time from me these days (not that it’s a bad thing!).

And that’s it for today. I’m going to make one last 2023 update in about two months (and make it a summary of the year and maybe some sneak peek into 2024). I still don’t know if I’ll be doing these updates in 2024, too – probably yes, but more rarely (since the frequency of publishing here decreased twofold, I don’t want to “waste” precious “post slots” on them too often). Until then, see you on both my blogs, and have a good rest of the year!

CategoryEnglish, CategoryBlog

October 30, 2023 07:00 PM

October 14, 2023

Borkowski Marcin

2023-10-14 Avoiding repetitions

I write a lot of prose. That does not mean I’m good at it nor very creative – I haven’t written any novels or even short stories. By “prose” I mean writing in a natural language (mostly English nowadays). In fact, most of the writing I’ve done in my life is technical in nature (usually either about technology or about mathematics). And (as you obviously know) I’m also a technology geek and an Emacs user. An immediate thought is: how to make Emacs help me write better?

One of the things you should avoid when writing are repetitions, or rather, inadvertent repetitions. Using some word more than once in close proximity is usually not good style (unless you go for some “special effect”, like making several parallel sentences).

Let’s write a simple function to help detect repetitions. When I’ve written a word I suspect I might use too often, I’d like to know how far from this point the nearest other occurrence of that word is. Also, it would be good to have those occurrences highlighted for a while. (The highlighting can also be done by iedit-mode, but that one is case-sensitive by default, and I don’t want that. Interestingly, you can toggle the case sensitivity of iedit-mode with M-C while it is active – but it seems you have to turn it on every time you start using that mode.)

Well, I say “simple”. In fact, it’s far from that. I mean, it’s not exactly difficult to understand, but – like with many other real-world text-editing tasks – there are a few edge cases one must take care of. What if the point is on the first, or last, or only occurrence of some word in the buffer? Will it work if the point is just before the first character of the word, or just after the last one? I guess it would be possible to refine my code so that it is more elegant (or, frankly, less ugly) and probably faster, but I don’t care that much – it works and is not difficult to analyze.

;; find repetitions    -*- lexical-binding: t; -*-

(require 'thingatpt)
(require 'cl)

(defun calculate-distance-to (to fun pred)
  "Calculate distance from BEG to END in units of FUN.
Assume BEG <= END.  FUN is a function moving forward by one unit
of measurement (e.g., a word or sentence)."
  (when to
    (save-excursion
      (let ((count 0))
        (while (funcall pred (point) to)
          (funcall fun)
          (cl-incf count))
        count))))

(defun find-nearest-word-repetitions ()
  "Find and report the nearest repetitions of word at point."
  (interactive)
  (let* ((word (word-at-point))
         (re (format "\\b%s\\b" (regexp-quote word)))
         (case-fold-search t)
         (prev (save-excursion
                 (beginning-of-thing 'word)
                 (when (re-search-backward re nil t)
                   (point))))
         (prev-overlay (when prev
                         (make-overlay prev
                                       (save-excursion
                                         (goto-char prev)
                                         (forward-word)
                                         (point)))))
         (next (save-excursion
                 (end-of-thing 'word)
                 (when (re-search-forward re nil t)
                   (point))))
         (next-overlay (when next
                         (make-overlay next
                                       (save-excursion
                                         (goto-char next)
                                         (backward-word)
                                         (point)))))
         (prev-words (save-excursion
                       (beginning-of-thing 'word)
                       (calculate-distance-to prev #'backward-word #'>)))
         (next-words (save-excursion
                       (end-of-thing 'word)
                       (calculate-distance-to next #'forward-word #'<)))
         (prev-sentences (save-excursion
                           (beginning-of-thing 'sentence)
                           (calculate-distance-to prev #'backward-sentence #'>)))
         (next-sentences (save-excursion
                           (end-of-thing 'sentence)
                           (calculate-distance-to next #'forward-sentence #'<))))
    (message "%s\n%s\n%s"
             (format "Word on point is `%s'." word)
             (if prev
                 (format "The previous occurrence was %s word(s)/%s sentence(s) ago."
                         prev-words prev-sentences)
               "This is the first occurrence.")
             (if next
                 (format "The next occurrence will be in %s word(s)/%s sentence(s)."
                         next-words next-sentences)
               "This is the last occurrence."))
    (when prev
      (overlay-put prev-overlay 'face 'show-paren-match)
      (run-at-time "4 sec" nil (lambda ()
                                 (delete-overlay prev-overlay))))
    (when next
      (overlay-put next-overlay 'face 'show-paren-match)
      (run-at-time "4 sec" nil (lambda ()
                                 (delete-overlay next-overlay))))))

(global-set-key (kbd "C-c r") #'find-nearest-word-repetitions)

As you can see, there is some, well… repetition in the above code. It would be probably possible to abstract away some of it, but I don’t think it’s worth it. One point worth mentioning is the lexical-binding variable – the code would not work under dynamical scoping, because the lambdas in run-at-time are actually closures – they need access to prev-overlay and next-overlay long after this function returns.

And that’s it for today, save for a reminder. If you want to learn some Elisp to be able to write little (or even a bit larger!) commands like this one to help you with your everyday tasks, there are two sources I always recommend. One is the excellent Introduction to programming in Emacs Lisp by the late Robert J. Chassell’s, and if you want to dive a little bit deeper, you can also check my book about Emacs Lisp.

CategoryEnglish, CategoryBlog, CategoryEmacs

October 14, 2023 06:00 AM

September 30, 2023

Borkowski Marcin

2023-09-30 Confirming potentially dangerous actions

A common situation is when I want to do something on my computer with possibly destructive consequences, like deleting a file, truncating a database table etc. One common approach to making sure this won’t happen accidentally is to require the user to press y or even type yes (this is what Emacs does with its y-or-n-p and yes-or-no-p functions). Some time ago I had a similar need in a shell script. I was afraid, however, that even requiring the user to type yes is not enough – it is easy to condition oneself to type a three-letter word without much thinking, after all.

So, I came up with an idea of telling the user to type a different word every time. More precisely, selecting the word to type at random from some large list, which theoretically may result into the same one twice, but it’s very improbable. (Interestingly, another person had almost the same idea very recently, too.)

And here is the code that accomplishes exactly that. You can put it in the beginning of a script doing some dangerous thing, or wrap it in a Bash function and call it only in the appropriate place, etc.

WORD=$(grep -E '^[a-z]{4,5}$' /usr/share/dict/words | shuf -n1)
read -rp "Type the word '$WORD' if you really want to turn the friction contrafibulator on: " TYPED
if [ "$WORD" != "$TYPED" ]; then
        echo You typed \'"$WORD"\' wrong, aborting.
        exit 1
fi

I decided to only go with 4 or 5 letter words, so that I don’t have to type anything too short nor too long. Of course, this creates a small risk of getting, well, certain 4-letter words, but let’s not overthink that. On my machine, grep -E '^[a-z]{4,5}$' /usr/share/dict/words | wc -l reports well over 7000 results, which is more than enough for my purpose.

I installed this code in one of the scripts I’ve written which must not be run accidentally (but which I need to run from time to time), and so I’ll see how it works – so far, it seems to do its job.

CategoryEnglish, CategoryBlog

September 30, 2023 08:00 PM

September 18, 2023

Borkowski Marcin

2023-09-18 Making Anki flashcards from subtitles

Those of you who follow my blog know that one of my hobbies is translating subtitles. The main reason I do this is to watch stuff with my daughter, who doesn’t yet speak English fluently. Some time ago it dawned on me that I can use my translations twice. Not only can I watch films and tv series with her, but I can use them to help her learn English.

Here is the idea. Since I have both the original English subtitles and my Polish translation – and the srt files contain the timestamps – I could use ffmpeg to cut clips with individual sentences, extract Polish and English versions of the dialog and create Anki flashcards (almost) automatically!

One thing which makes this a bit more difficult than it seems is that not every piece of dialog is suitable for importing into Anki. In many cases the translation is not (and cannot be) very faithful. For example, sometimes one subtitle contains only half (or less) of the sentence, and due to how English and Polish work, the order of these parts is different in both versions. Sometimes parts of dialog must be cut in translation because the characters speak too fast. And sometimes there are English cultural references which do not map to similar concepts in Polish, so I have to change things completely.

I decided that the best approach I can think of is to prepare the flashcards in three stages. The first stage (which is completely automatic) is merging the English source file and the Polish translation. This is done with the subed-anki-combine-subtitle-files command. In this stage, I create one srt file with subtitles in both languages – the Polish ones prepended by Q: and English ones prepended by A:. (For some reason, Emacs Subed mode doesn’t like it when the subtitle text has that form – adding a space after the colon helped.) Coding this was fairly easy, although there’s one catch: when translating, I often tinker with the timestamps. This means that I cannot assume that the timestamps are exactly the same in both files. That is not a big problem, though – my code iterates over all subtitles in the “question” file (the Polish one) and for each of them finds the nearest subtitle in the “answer” file (the English one). (There are a few ways to define the “nearest” subtitle – I provided a function for one of them and stubs for two other ones in case anyone wants a different metric.)

The second stage is manual – it is now that I can go through the merged subtitle file, delete the parts which are not suitable for flashcards, fix any issues with the timestamps etc. This can of course be done in Emacs Subed mode.

The third, final stage is automatic again – the merged and edited subtitle file is converted (using subed-anki-export) to a csv, which can be imported into Anki. Additionally, ffmpeg is called for every question/answer pair and a clip is put into a collection.media subdirectory of the current directory. After importing the csv into Anki and copying the clips to its directory the flashcards are ready for learning!

The code is not very elegant – in part because it is still sort of a proof-of-concept, in part because the whole thing has a distinct DIY feeling (I have to admit that the UX with all these stages is rather poor, but I didn’t have any idea how to do it better, at least not without a lot of work), and in part because it is an inherently complex process. If you want to try doing this yourself, I uploaded the code to Gitlab. I will certainly be preparing lots of flashcards very soon!

CategoryEnglish, CategoryBlog, CategoryEmacs

September 18, 2023 07:00 PM

September 02, 2023

Borkowski Marcin

2023-09-02 Irregular recurring TODOs in Org mode, part I

Warning: this is the first part of a series which is not even finished yet. And even though it’s not the whole story, it is still a long, a bit meandering post, with quite a lot of code.

Some time ago I mentioned a very peculiar type of TODOs I’d like to implement. These are things I’d like to do from time to time, but not necessarily on a regular basis. A canonical example is an inspirational blog post I’d like to reread once in a while. I admit that this idea is inspired by spaced repetition, where things I want to remember are presented to me repeatedly, but with increasing intervals. Here, however, the situation is a bit different. First of all, I don’t really need to remember these things actively – I just want to be reminded of them from time to time in the future. The second difference is that I’m not sure if increasing intervals would be the best choice here. In classical spaced repetition algorithms the intervals grow exponentially, so after, say, 10 repetitions of something remembered well, the intervals can become so long you are basically guaranteed to see that item at most once or twice again in your life. In this case, I still want to read that blog post a few times – maybe once per two/three years even, but not once per a decade or even less often! The third issue is that with classical SR I can have days without any repetitions as well as days with many of them. Here, I’d prefer to be shown the same anount of “recurring TODOs” per day (preferably one, but I assume that if I like the system, I may have more of them).

So, after some consideration, here is the heuristic I came up with. (Spoiler alert: it’s not the one that will get implemented evetually.) First of all, the “items” are going to be Org mode headlines (well, that is pretty obvious;-)) – they may contain links, but they may also be just pieces of text stored on my disk. I’d prefer to be flexible and not require all of them to be stored on the same level of Org hierarchy – for example, I might want a tree structure, with broad categories (like “blog posts”, “quotations” or “ideas for things to do”) as level-one headlines, narrower categories (like blog posts about “faith”, “computing” or “languages”) as level-two headlines etc.

When I’m introducing a new item to my system, it should be set to be shown again after, say, a random number of days between a week and a month (more or less). When I’m shown an item again, I should be able to decide what to do next – either schedule it for later with the interval doubled compared to the previous one, or schedule it for later for the interval shortened to 7-30 days (like in the beginning), or use an interval similar in length to the previous one.

This looks clever, and in fact much more similar to classic SR than I initially expected, but I am a bit worried if it’s sustainable. Let’s do some estimation. Assume that I’m going to add one item every five days to the system. This means that after a year I’ll have about 73 items to review regularly. Assuming the first interval to be about 20 days, the subsequent one roughly 40 days, and all the next ones 80 days, it gives me an average load of one item per day after a year of using the system. Let’s also assume that I’m going to use that system for the next 5 years (which I think is quite conservative – a more generous but still realistic estimate could well be 20 years). This means that I’ll have 5 items to review every day. A bit too much.

A tinkerer in me wants now to devise an extremely complex system where there is a cap for the number of items to be reviewed per day, the latest date (kept separately for every item) when I want it to be reviewed, a way for more important items to shift the review dates of the less important ones to later… This is fun to think about, probably a bit less fun to implement and almost surely not fun at all to use.;-) So, let’s keep things as simple as possible. Here is another idea. (Spoiler alert: it’s also not the final one.) Since I do not want to get 0 items on some days and 8+ items on other days (which can happen with classical SR), I could turn the whole thing on its head and just ask the system for “the most important/urgent thing to review now”. On a busy day, I might do it once; on a less busy one, I could do it 2-3 times. This means that for every item I should store some data like “when it was reviewed for the last time” and “how many times it was reviewed”, and devise some function which would then calculate the “urgency” of that item. (Note: I know about the famous Eisenhower matrix, but in this case, I consider all the items “equally important”, so I can just sort them by urgency and that’s fine.)

Here is one idea that came to my mind. Let’s have an item last reviewed D days ago, and reviewed N times altogether (the act of entering the item into the system is considered the first review, so N>0). The higher D is, and the lower N is, the more urgent the item is. Let’s compute U(N,D) := N²/D (excluding the items reviewed today) and consider the items with lower U be more urgent. The square is there to make items reviewed more times less and less urgent, so that the average intervals between reviews will grow.

This formula implies a few things. First of all, items reviewed fewer times will have a preference over those reviewed many times. As (N+1)²/N² tends to 1 as N→∞, this preference will (in a sense) become less pronounced over time. For example, consider two items, one newly entered (N=1) and one entered and then reviewed once more (N=2). To achieve the same urgency, the interval between the last review and today will have to be four times larger for the latter item. On the other hand, if we have two items, one reviewed four times and one reviewed five times, the ratio of the intervals to have the same urgency will need to be only equal to (5/4)²≈1.6.

The next thing is, the longer time elapsed from the last review, the more “urgent” the item is. This is pretty obvious, though the urgency will increase over time rather slowly. Another formula I considered was U(N,D) := N²/D(1+ε)for ε somewhere between 0.001 and 0.01, where longer intervals “contribute more” to the urgency. The obvious downside of that formula is its complexity, which makes it more difficult to analyze.

Probably the most important thing about my approach is that I’d like to have a guarantee that no item will be postponed indefinitely – in other words, I’d like to be sure that every item will have the lowest urgency of them all after a finite amount of time. Surprisingly, this seems a non-trivial property to prove! The intuition goes like this: every item’s urgency tends towards zero, and every review will make that item’s urgency jump above 1, so if we have some item I with such that n items have urgency lower than I, its urgency will be the lowest one after (n-1) days. This “proof” has one flaw – it silently assumes that the change in urgencies happening over time does not change the order of items. This, however, is simply not true! For example, consider an item A reviewed for the second time 8 days ago and an item B reviewed for the third time 18 days ago. Assuming neither A nor B is reviewed from yesterday to tomorrow, it means that while A was less urgent than B yesterday, and it will be more urgent tomorrow!

Unless there exists some simple trick which escapes me now, I cannot prove that every item will be reviewed after a finite number of days, even with the simplifying assumption that no items are added to the system.

Well. If I can’t prove it, so be it. Let’s don my programmer’s hat and make a simulation. I whipped up some code to simulate doing reviews (a given number of them every day) while introducing a new item with a given probability (so 0.2 would mean one new item every 5 days on average). For reference, here is the code – it is definitely not the most beautiful thing in the world, but it is just a prototype to perform some experiments and then be got rid of.

;; Recurring TODOs - simulation

(require 'cl-lib)

(defvar recurring-todos ()
  "A list of \"TODO items\" as plists -- the properties are :id (an
integer) and :reviews (dates of review, integers, decreasing).")

(defvar recurring-next 0
  "The next value of :id.")

(defvar recurring-date 0
  "The \"date\" (number of days elapsed).")

(defvar recurring-buffer-name "*Recurring TODOs simulation data*"
  "Data about recurring TODOs simulation as csv.  Every row
corresponds to one review (including the first one, i.e.,
addition of the item to the system).")

(get-buffer-create recurring-buffer-name)
(with-current-buffer recurring-buffer-name
  (insert "date,id,review,interval\n"))

(defun recurring-add-review-datapoint (id date review interval)
  "Add a datapoint about a review to buffer `recurring-buffer-name'."
  (with-current-buffer recurring-buffer-name
    (goto-char (point-max))
    (insert (format "%s,%s,%s,%s\n"
                    date id review interval))))

(defun recurring-add-todo ()
  "Add a new recurring todo to `recurring-todos'."
  (let ((new-item (list :id recurring-next
                        :reviews (list recurring-date))))
    (push new-item recurring-todos)
    (recurring-add-review-datapoint recurring-next
                                    recurring-date
                                    1
                                    "")
    (cl-incf recurring-next)))

(defun recurring-next-day ()
  "Increment `recurring-date'."
  (cl-incf recurring-date))

(defun recurring-last-review (todo)
  "The date of the last review of TODO."
  (car (plist-get todo :reviews)))

(defun recurring-number-of-reviews (todo)
  "The number of reviews of TODO so far."
  (length (plist-get todo :reviews)))

(defun recurring-urgency (date todo)
  "Compute the urgency of TODO."
  (let ((n (recurring-number-of-reviews todo))
        (d (- date
              (recurring-last-review todo))))
    (/ (* n n) d 1.0)))

(defun recurring-review (todo)
  "Review TODO.  Destructive."
  (when todo
    (recurring-add-review-datapoint (plist-get todo :id)
                                    recurring-date
                                    (1+ (length (plist-get todo :reviews)))
                                    (- recurring-date (car (plist-get todo :reviews))))
    (push recurring-date (plist-get todo :reviews))))

(defun recurring-find-most-urgent (date todo-list)
  "Return the most urgent todo."
  (let* ((result nil)
         (urgency most-positive-fixnum))
    (mapc (lambda (todo)
            (let ((new-urgency (recurring-urgency date todo)))
              (when (< new-urgency urgency)
                (setq urgency new-urgency
                      result todo))))
          (cl-remove-if (lambda (todo)
                          (= (recurring-last-review todo)
                             date))
                        todo-list))
    result))

(defun recurring-reset ()
  "Reset the recurring reviews simulation."
  (setq recurring-todos ()
        recurring-next 0
        recurring-date 0))

(defun recurring-simulate (iterations new-frequency review-frequency)
  "Simulate ITERATIONS days of reviewing TODOs.
NEW-FREQUENCY is the probability of adding a new TODO every day.
REVIEW-FREQUENCY is the number of reviews done every day.  Do not
reset the variables, so that a simulation can be resumed."
  (dotimes-with-progress-reporter
      (_ iterations)
      "Simulating reviews..."
    (when (< (cl-random 1.0) new-frequency)
      (recurring-add-todo))
    (recurring-review (recurring-find-most-urgent recurring-date recurring-todos))
    (recurring-next-day)))

So, my first experiment was to run one year of simulation, with one review per day and the probability of introducing a new item equal to 0.2. After running my code I imported the resulting CSV to SQLite and ran a few queries to analyze it.

The number of items reached 84. It turned out that 5 items were reviewed 9 times and the average interval between interviews for that 5 items was about 142 days. The maximum interval between reviews turned out to be 262 days. The one item which achieved such a long interval between reviews was reviewed on days 20, 21, 22, 25, 30, 40, 55, 89, and 351.

The next experiment assumed the same probability of adding a new item, but now I ran the simulation for 10 years. Again, the item with the longest interval between reviews had the intervals between them rise (more or less) exponentially. Each of reviews 2-9 happened after less than two weeks after the previous one, and then every interval was at least 10 times longer than the previous one!

So, back to square one. It turns out that my initial approach was pretty elegant mathematically, but practically useless. How surprising.

(to be continued…)

CategoryEnglish, CategoryBlog, CategoryEmacs, CategoryOrgMode

September 02, 2023 12:00 PM

August 21, 2023

Borkowski Marcin

2023-08-21 My plans for 2023 - August update

Since about two months have passed since the last blog post with my 2023 plans update, it’s time for another one. This time it is going to be a bit shorter, since not a lot of stuff has happened (or rather, a lot did, but it was mostly concentrated on one of the projects, which I think is… good?).

  1. Elisp book polishing and expanding – still nothing with this one. It still waits, and the time I get to it is getting really close now. In fact, I increased my daily timeslot for writing, so I expect some progress with the book in the following few weeks.
  2. My semi-secret project I keep mentioning again and again is now rolling quite well. (As you might know from one of the previous posts here, this is the reason this blog gets updates less frequently now.) The blog engine I was writing, called Org Clive, is now ready, although not yet stable (that is, anything could be changed yet). I already use it in production, though, and I’m very happy with it! While the code is not the most beautiful thing I’ve made, using it is a pleasure – I have all my blog entries, HTML templates and text assets like CSS and JS files in a single Org mode file, which is great. Also, it generates a configurable RSS feed and supports using images and other binary assets like fonts.
    If you want to see the new blog, well, I haven’t officially launched it yet. I mean, it is online, it is even already indexed by Kagi, DuckDuckGo and Google, but I thought that announcing a blog which only has one post is a bit unprofessional and potentially disappointing for readers. I decided to wait for three posts to start telling people about it. I can almost make an exception for the readers of this blog, though, since you already know that I should be capable of delivering content regularly. So, a hint: the name of the blog is a certain passcode, consisting of four unrelated words, and rather well-known in certain geek circles. (And no, it is not “correct horse battery staple”!) If you type this passcode into your search engine of preference (originally, the passcode was supposed to be thought, using telepathic technology, not typed, but well, we aren’t there yet;-)), followed by the word “weblog” (I call it “weblog”, not “blog”, to give it some 2000s vibes;-)), you’ll be there.
    Unfortunately, it turned out that writing that new weblog takes me more time than I initially planned – I strive to make the posts short, because there is a lot to say about the topics I cover, but the two posts I have already written have over 3000 words each (which should amount to over 15 minutes of reading time), and each of them took me over 5 hours to research and write. (Fun fact: I am always very hesitant to share data about my writing velocity. The reason is that my impostor syndrome kicks in, and I’m always afraid that people would think that I’m slacking and publishing second-rate material because I spend too little time on writing. While it’s true that I could improve my writing – and in fact, I am working on it – I decided not to care that much anymore about what people would think. Not that it’s easy, but at least I’m trying.)
  3. The book about web extensions is obviously on the back burner now. Sorry if you are one of the few people waiting for it… When the Programmer’s diary turned out to be a flop, I have to admit that I lost motivation a bit; also, I figured that the blog (weblog;-)) might have a higher chance of success and decided to start with it instead. On the other hand, I try not to be motivation-driven (motivation, as a feeling, is very unstable, and counting on it to get things done is risky at best. My usual approach is to employ discipline instead.)
  4. Other projects are also being thought about, but all of them will need to wait a bit until vacation ends and my new routine kicks in. (Quite obviously, vacation time does not help with a regular writing routine – while pleasant, it was definitely a huge distraction from that standpoint!)

So, that’s it for today. I do hope to be able to share much more in October!

CategoryEnglish, CategoryBlog

August 21, 2023 06:00 PM

August 05, 2023

Borkowski Marcin

2023-08-05 Plotting ASCII art charts from Org mode tables

Three weeks ago I wrote about simple ASCII art charts in Emacs. Now I’m going to use Org mode tables as the source of the data for them. Since my use case is plotting my weight against time, this will get a bit more complicated because the values of the independent variable are dates.

Let’s recall that my table looks like this.

#+name: weight-data
| Date+time              | Weight |   MA |
|------------------------+--------+------|
| [2023-04-30 Sun 19:23] |   66.1 |    0 |
| [2023-05-01 Mon 05:13] |   66.2 |    0 |
| [2023-05-04 Thu 04:56] |   66.0 |    0 |
| [2023-05-05 Fri 05:08] |   65.8 |    0 |
| [2023-05-06 Sat 19:23] |   66.0 |    0 |
| [2023-05-07 Sun 05:13] |   65.9 |    0 |
| [2023-05-10 Wed 04:56] |   65.6 | 65.9 |
| [2023-05-12 Fri 05:15] |   65.7 | 65.9 |
| [2023-05-13 Sat 05:07] |   65.8 | 65.8 |
#+TBLFM: $3=vmean(@-6$-1..@0$-1);%.1f::@2$3=0::@3$3=0::@4$3=0::@5$3=0::@6$3=0::@7$3=0

Let’s start with getting the data from a table. I know about two ways of doing this. One is the org-table-get-remote-range function. You give it the name of the table (that’s why I added the first line with the name) and the (absolute) range of cells and get a list of strings containing those cells’ data. It is not extremely convenient for our purpose, though – it returns a flat list even if the range is a rectangle of both width and height greater than one. Still, it is fairly easy to use it to get, say, the first three columns of the last two rows of the table:

(mapcar
 #'substring-no-properties
 (org-table-get-remote-range "weight-data" "@>>$1..@>$3"))

(The substring-no-properties is here so that I can yank this form into M-: and see the actual string contents, without all the distracting information about Org text properties.)

Of course, I need the last sixty rows, and putting sixty > signs there by hand is not the best idea. But I can say

(mapcar
 #'substring-no-properties
 (org-table-get-remote-range
  "weight-data"
  (format "@%s$1..@>$3" (make-string 60 ?>))))

There is, however, another, more Org-ish way to do this. We can use an Elisp source block and feed it the data from a table. For example, pressing C-c C-c on this:

#+name: weight-plot
#+begin_src elisp :var data=weight-data :results code
  (cl-subseq data -2)
#+end_src

will result in this:

(("[2023-05-12 Fri 05:15]" 65.7 65.9)
 ("[2023-05-13 Sat 05:07]" 65.8 65.8))

(The :results code causes Org to show the output in a lispy way instead as an Org table.) In this example, (cl-subseq data -2) returns the subsequence of data from the penultimate element on, that is, two last elements. (Of course, I had to (require 'cl) for this to work.)

Now, let’s map over the, say, last 60 elements, disregard the second element of every one of them (to plot only the moving average), and translate the timestamp to the number of days between today and the day specified in the timestamp.

The trickiest thing here is to do time calculations (that is, compute how many days passed from a date, given as a string in Org mode timestamp format). There are three functions which are of help here: org-timestamp-from-string (which converts a string to an Org timestamp object), org-timestamp-to-time (which converts an Org timestamp object to Emacs time value) and time-to-days (which converts an Emacs time value to the number of days from 0001-01-01). Here is how I used Org source blocks to create a list suitable for my plotting functions:

#+begin_src elisp :var data=weight-data :results code
  (mapcar (lambda (row)
	    (let ((timestamp (car row))
		  (value (caddr row)))
	      (cons (- (time-to-days (org-timestamp-to-time (org-timestamp-from-string timestamp)))
		       (time-to-days (current-time)))
		    value)))
	  (cl-subseq data -2))
#+end_src

Now the only thing remaining is to feed it to scatter-plot.

#+begin_src elisp :var data=weight-data :wrap example
  (scatter-plot
   (mapcar (lambda (row)
	     (let ((timestamp (car row))
		   (value (caddr row)))
	       (cons (- (time-to-days (org-timestamp-to-time (org-timestamp-from-string timestamp)))
			(time-to-days (current-time)))
		     value)))
	   (cl-subseq data -60))
   '(:width 60 :height 24 :labelx-skip 10 :labely-skip 0.5 :char ?#))
#+end_src

Note that I used :wrap example (as suggested by Ihor Radchenko on the mailing list). The :results raw option didn’t work because Org interpreted the | signs as a table and botched the formatting. Also, I needed to change the character used to mark the points on the chart to # since Org prepended a comma to the asterisk to avoid treating that line as a headline.

And now I can see my weight data as a plot directly in Org mode!

CategoryEnglish, CategoryBlog, CategoryEmacs, CategoryOrgMode

August 05, 2023 10:00 AM

July 22, 2023

Borkowski Marcin

2023-07-22 Org Clive - a new Org-mode-based blogging engine

As I mentioned a few weeks ago, I am now working on a new Org-mode based blog engine. I am proud to say that it’s now ready (even though it’s not yet feature complete), and you can use it, too!

If you want to experiment with it, clone the repository at https://gitlab.com/mbork_mbork_pl/org-clive, load the org-clive.el file, open the example-weblog.org file and say M-x org-clive-generate-weblog.

As I said, this is a very simplistic thing (which is precisely what I wanted). You can skim the README in 5-10 minutes, the example blog in another 5-10 minutes, and you can probably study the whole source code in an hour. One of my favorite features (and one of the main reasons I implemented this myself instead of using one of a few existing solutions) is the fact that the whole blog – the content, the HTML templates, CSS, JavaScript – is defined in a single Org mode file. Of course, I made an exception for images and other binary blobs like fonts – technically, you could also have them in the Org file, but I don’t think it is a very practical idea.

So, try out Org Clive, and drop me a line if you use it in production! Of course, bug reports and merge requests are welcome – feature requests less so, since I don’t want to spend too much time on it (apart of implementing a few things like RSS or page modification dates).

Also, expect the next article here in two weeks instead of one – after all, I wrote Org Clive to use it!

CategoryEnglish, CategoryBlog, CategoryEmacs, CategoryOrgMode

July 22, 2023 05:00 AM

January 08, 2015

Hromada Mateusz

Warka 9 – American India Pale Ale

Zasyp:

  • pale ale 4kg
  • pszeniczny 0,8kg
  • carapils 0,5kg

Zacieranie w 18l wody, słód dodany w 55°C:

  • 68°C – 65 minut przerwy (po 30 minutach podgrzanie z 65°C do 68°C)

Po filtracji i wysładzaniu wyszło 21,5 litra brzeczki o BLG 11,1.

Chmielenie:

  • 60 minut – 40g Simcoe
  • 20 minut – 30g Simcoe
  • 5 minut – 30g Simcoe
  • 0 minut – 30g Amarillo
  • dry hopping – 30g Simcoe (6 dni), 30g Simcoe (3 dni)

Po schłodzeniu i filtracji wyszło 19 litrów o BLG 16.

Fermentacja (drożdże US-05):

  • 11 dni burzliwej
  • 23 dni cichej

Do refermentacji użyłem 140g cukru i 735g wody.

ABV: ok. 6.2%

by ruanda at January 08, 2015 09:38 PM

Warka 8 – Cydr

Składniki:

  • sok jabłkowy Riviva 22l

Sok ma BLG 12.

Fermentacja (drożdże US-05):

  • 7 dni burzliwej
  • 38 dni cichej

Do refermentacji użyłem 155g cukru i 1135g wody.

ABV: ok. 6.3%

by ruanda at January 08, 2015 09:34 PM

Warka 7 – American Wheat

Zasyp:

  • pszeniczny 2kg
  • pilzneński 2kg

Zacieranie w 16l wody, słód dodany w 45°C:

  • 45°C – 15 minut przerwy
  • 53°C – 15 minut przerwy
  • 68°C – 75 minut przerwy (po 30 minutach podgrzanie z 64°C do 70°C)

Po filtracji i wysładzaniu wyszło 21 litry brzeczki o BLG 7.

Chmielenie:

  • 60 minut – 10g Chinook
  • 20 minut – 20g Palisade
  • 5 minut – 20g Cascade
  • 0 minut – 20g Amarillo
  • dry hopping – 30g Amarillo, 10g Cascade, 10g Palisade

Po schłodzeniu i filtracji wyszło 18 litrów o BLG 12.

Fermentacja (drożdże US-05):

  • 8 dni burzliwej
  • 35 dni cichej

Do refermentacji użyłem 120g cukru i 880g wody.

ABV: ok. 5.5%

by ruanda at January 08, 2015 09:28 PM

November 11, 2014

Girl, lost in IT

Nowy wpis, nowe miejsce

W poprzednim wpisie uprzedzałam, że muszę wprowadzić duże zmiany. Nie jestem już w stanie pisać każdego tekstu w dwóch językach. Dodatkowo czuję, że zmieniłam się przez ostatnie kilka lat – czuję, że „wyrosłam” trochę z tego bloga. Właśnie napisałam pierwszy tekst w nowym miejscu. Blog nazywa się Na miękko - serdecznie zapraszam.

by ynka at November 11, 2014 09:02 PM

October 13, 2014

Krzysztof Szarzyński

Zawieszenie publikacji

Jeśli dobrze liczę, to od 402 dni nic tu nie napisałem. Ponieważ zazwyczaj nie mam niczego interesującego do powiedzenie/napisania, dlatego przerzuciłem się na inne platformy, które lepiej pasują do “beztekstowej” formuły. Nadal robię zdjęcia – więcej niż kiedyś, ale publikuje je w mniejszych porcjach. Zapraszam na mój profil 500px, gdzie wrzucam rożne zdjęcia z całego […]

by Quati at October 13, 2014 06:41 PM

June 12, 2014

Hromada Mateusz

Warka 6 – Żytni Stout

Zasyp:

  • pale ale 2kg
  • żytni 2kg
  • żytni czekoladowy 0,25kg
  • Carafa typ III special 0,25kg

Zacieranie w 16l wody, słód dodany w 55°C:

  • 55°C – 10 minut przerwy
  • 70°C – 60 minut przerwy (po 60 minutach podgrzanie z 62°C do 68°C)
  • 68°C – dodanie ciemnych słodów, 40 minut przerwy

Po filtracji i wysładzaniu wyszło 20,5 litra brzeczki.

Chmielenie:

  • 60 minut – 10g Tomahawk
  • 15 minut – 30g Tomahawk
  • 5 minut – 30g Tomahawk
  • dry hopping – 30g Tomahawk

Po schłodzeniu i filtracji wyszło 18 litrów o BLG 13.

Fermentacja (drożdże S-04):

  • 22 dni burzliwej

Do refermentacji użyłem 125g cukru i 835g wody.

ABV: ok. 4,4%

by ruanda at June 12, 2014 08:38 PM

April 27, 2014

Girl, lost in IT

W planie zmiany + jak tu trafiłam (w obrazkach)

Kolega wyraził ostatnio zaniepokojenie działaniem swojego czytnika RSS. To przecież niemożliwe, żebym tak długo nie napisała nic na swoim blogu! Niestety, możliwe. Do tego powód jest dość absurdalny: piszę mniej, ponieważ piszę więcej. Naprawdę. Pamiętacie, jak przeżywałam swoje 10000. urodziny? Postanowiłam wtedy na poważnie wziąć się za rzeczy, o których zawsze myślałam, że zrobię je […]

by ynka at April 27, 2014 06:28 AM

March 22, 2014

Hromada Mateusz

Warka 5 – Imperial India Pale Ale

Zasyp:

  • pale ale 5kg
  • wiedeński 1kg
  • carapils 0,5kg
  • pszeniczny 0,2kg

Zacieranie w 21l wody, słód dodany w 55°C:

  • 55°C – 10 minut przerwy
  • 65°C – 90 minut przerwy (po 60 minutach podgrzanie z 61°C do 65°C)

Po filtracji i wysładzaniu wyszło 23 litry brzeczki o BLG 14.

Chmielenie:

  • 60 minut – 40g Chinook
  • 10 minut – 20g Citra, 20g Simcoe
  • 5 minut – 30g Citra, 30g Simcoe
  • 0 minut – 15g Cascade, 15g Palisade
  • dry hopping – 15g Cascade, 15g Palisade

Po schłodzeniu i filtracji wyszło 21 litrów o BLG 17.

Fermentacja (drożdże US-05):

  • 9 dni burzliwej
  • 10 dni cichej

Do refermentacji użyłem 130g cukru i 630g wody.

ABV: ok. 7,6%

by ruanda at March 22, 2014 07:44 PM

March 12, 2014

Hromada Mateusz

Warka 4 – American Wheat

Zasyp:

  • pszeniczny 2kg
  • pilzneński 2kg

Zacieranie w 15l wody, słód dodany w 55°C:

  • 55°C – 10 minut przerwy
  • 68°C – 70 minut przerwy (po 50 minutach podgrzanie z 62°C do 67°C)

Po filtracji i wysładzaniu wyszło 21 litry brzeczki o BLG 9,5.

Chmielenie:

  • 60 minut – 10g Chinook
  • 20 minut – 20g Palisade
  • 5 minut – 20g Cascade
  • 0 minut – 20g Amarillo
  • dry hopping – 30g Amarillo

Po schłodzeniu i filtracji wyszło 18 litrów o BLG 13.

Fermentacja (drożdże US-05):

  • 8 dni burzliwej
  • 11 dni cichej

Do refermentacji użyłem 120g cukru i 800g wody.

ABV: ok. 5.3%

by ruanda at March 12, 2014 06:14 PM

February 23, 2014

Girl, lost in IT

Oddam za darmo!

Raz na jakiś czas znajduję w domu coś, co dawno już przestało mi być potrzebne, ale co mogłoby jeszcze przydać się komuś innemu. Niektóre takie rzeczy wystawiam na Allegro (zwłaszcza, jeśli są warte więcej niż kilkadziesiąt złotych), jednak do Allegro często zniechęca mnie konieczność oszacowania kosztów przesyłki. Jeśli chcę pozbyć się czegoś szybko, tanio i […]

by ynka at February 23, 2014 05:23 PM

February 15, 2014

Hromada Mateusz

Instalacja Raspbian przez debootstrap

IMG_20140214_203617

Wymagania

Potrzebny jest Linux, w miarę świeży debootstrap i qemu-arm-static. Oczywiście potrzebny też jest dostęp do użytkownika root.

Partycjonowanie i formatowanie karty SD

Kartę należy podzielić na dwie partycje. Pierwsza, sformatowana w FAT będzie zamontowana jako /boot. Druga partycja będzie zamontowana jako /, można ją sformatować np. w ext4:

root@lol:/mnt# fdisk /dev/sdh
WARNING: DOS-compatible mode is deprecated. It's strongly recommended to
switch off the mode (command 'c') and change display units to
sectors (command 'u').

Command (m for help): n
Command action
e extended
p primary partition (1-4)
p
Partition number (1-4): 1
First cylinder (1-1021, default 1):
Using default value 1
Last cylinder, +cylinders or +size{K,M,G} (1-1021, default 1021): +64M

Command (m for help): t
Selected partition 1
Hex code (type L to list codes): c
Changed system type of partition 1 to c (W95 FAT32 (LBA))

Command (m for help): n
Command action
e extended
p primary partition (1-4)
p
Partition number (1-4): 2
First cylinder (10-1021, default 10):
Using default value 10
Last cylinder, +cylinders or +size{K,M,G} (10-1021, default 1021):
Using default value 1021

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.

WARNING: If you have created or modified any DOS 6.x
partitions, please see the fdisk manual page for additional
information.
Syncing disks.
root@lol:/mnt# mkfs.vfat /dev/sdh1
[...]
root@lol:/mnt# mkfs.ext4 /dev/sdh2
[...]
root@lol:/mnt# mkdir rpi
root@lol:/mnt# mount /dev/sdh2 rpi/
root@lol:/mnt# mkdir rpi/boot
root@lol:/mnt# mount /dev/sdh1 rpi/boot/

Instalacja i konfiguracja

Debootstrap należy przeprowadzić w dwóch etapach, gdyż binarki przeznaczone są na inną architekturę.

root@lol:/mnt# debootstrap --foreign --arch armhf wheezy rpi/ http://archive.raspbian.org/raspbian
[...]
root@lol:/mnt# cp /usr/bin/qemu-arm-static rpi/usr/bin/
root@lol:/mnt# LANG=C chroot rpi/ /debootstrap/debootstrap --second-stage

Następnie można chrootować się na budowany system:

root@lol:/mnt# LANG=C chroot rpi/ /bin/bash

Potrzebne są repozytoria w sources.list:

deb http://archive.raspbian.org/raspbian wheezy main contrib non-free
deb-src http://archive.raspbian.org/raspbian wheezy main contrib non-free

W pliku /boot/cmdline.txt należy dodać parametry do kernela:

dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait

/etc/fstab:

proc /proc proc defaults 0 0
/dev/mmcblk0p1 /boot vfat defaults 0 0

Różne sieciowe ustawienia są w plikach /etc/hostname, /etc/resolv.conf i /etc/network/interfaces.

W chroocie należy doinstalować paczki git, binutils i ca-certificates.

Potrzebne jest narzędzie rpi-update:

root@lol:/# wget http://goo.gl/1BOfJ -O /usr/bin/rpi-update
root@lol:/# chmod +x /usr/bin/rpi-update
root@lol:/# mkdir /lib/modules
root@lol:/# rpi-update
[...]

Aby dostać się do RPi po restarcie potrzebne jest ssh i hasło na roota:

root@lol:/# passwd
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
root@lol:/# apt-get install ssh
[...]

Po wyjściu z chroota, odmontowaniu obu filesystemów i przełożeniu karty do RPi powinien zabootwać się Raspbian dostępny przez ssh:

root@trololo:~# uname -a
Linux trololo 3.10.30+ #640 PREEMPT Fri Feb 14 19:09:14 GMT 2014 armv6l GNU/Linux

Linki

by ruanda at February 15, 2014 01:20 PM

February 02, 2014

Hromada Mateusz

Warka 3 – American Stout

Zasyp:

  • pilzneński 3kg
  • monachijski 1kg
  • jęczmień palony 0,3kg
  • barwiący 0,2kg

Zacieranie w 15l wody, słód dodany w 55°C:

  • 55°C – 10 minut przerwy
  • 68°C – 70 minut przerwy (po 35 minutach podgrzanie z 64°C do 66°C)
  • 66°C – dodanie ciemnych słodów i 15 minut przerwy

Po filtracji i wysładzaniu wyszło 22 litry brzeczki o BLG 11.

Chmielenie:

  • 60 minut – 15g Centennial
  • 15 minut – 15g Centennial
  • 5 minut – 15g Centennial
  • 0 minut – 25g Centennial
  • dry hopping – 30g Centennial

Po schłodzeniu i filtracji wyszło 19,5 litra o BLG 15. Dodałem 1,5l wody.

Fermentacja (drożdże S-04):

  • 8 dni burzliwej
  • 12 dni cichej

Do refermentacji użyłem 140g cukru i 860g wody.

by ruanda at February 02, 2014 09:54 PM

Girl, lost in IT

10000* lat

Parę (naście) dni temu skończyłam 32 lata. Ta magiczna liczba nie doskwiera mi za bardzo i nie ona jest bezpośrednią przyczyną powstania tego tekstu. Do rozmyślań skłoniły mnie życzenia, które składano mi z tej okazji. Kilkoro (młodszych) znajomych, niezależnie od siebie, obdarowało mnie życzeniami brzmiącymi mniej więcej tak: „Wszystkiego najlepszego. Żebyś miała wspaniały rok. I […]

by ynka at February 02, 2014 06:17 PM

January 27, 2014

Hromada Mateusz

Warka 2 – American Pale Ale

Zasyp:

  • pilzneński 2,5kg
  • monachijski 1,3kg
  • karmelowy jasny 0,2kg

Zacieranie w 12l wody, słód dodany w 55°C:

  • 55°C – 10 minut przerwy
  • 69°C – 60 minut przerwy (z podgrzaniem w 40 minucie)

Po filtracji i wysładzaniu BLG 10.

Chmielenie:

  • 60 minut – 15g Simcoe
  • 15 minut – 15g Simcoe
  • 5 minut – 15g Simcoe
  • 0 minut – 25g Simcoe
  • dry hopping – 30g Simcoe

Po schłodzeniu i filtracji wyszło 16,5 litra o BLG 13.

Fermentacja (drożdże US-05):

  • 8 dni burzliwej
  • 10 dni cichej

Do refermentacji użyłem 110g cukru i 740g wody.

ABV: ok. 5%

by ruanda at January 27, 2014 06:25 PM

January 26, 2014

Hromada Mateusz

Warka 1 – American India Pale Ale

Pierwszą warkę uwarzyłem z przygotowanego zestawu surowców.

Zasyp:

  • pale ale 5,5kg
  • Cara Gold 0,5kg
  • pszeniczny 0,2kg

Zacieranie w 18l wody, słód dodany w 55°C:

  • 55°C – 10 minut
  • 69°C – 60 minut (bez podgrzewania, końcowa 62°C)
  • 76°C – mashout

Po filtracji i wysładzaniu wyszło 23 litry brzeczki o BLG 15.

Chmielenie:

  • 60 minut – 25g Warrior
  • 20 minut – 20g Simcoe
  • 10 minut – 10g Amarillo
  • 5 minut – 10g Amarillo
  • dry hopping – 30g Amarillo

Po schłodzeniu i filtracji wyszło 20,5 litra o BLG 17.

Fermentacja (drożdże US-05):

  • 10 dni burzliwej
  • 11 dni fermentacji cichej

Do refermentacji użyłem 135g cukru i 660g wody.

ABV: ok. 7%.

by ruanda at January 26, 2014 07:03 PM

December 15, 2013

Girl, lost in IT

O zmianie (pracy)

Kilka dni temu kolega z poprzedniej pracy spytał, czy przeniosłam blog w nowe miejsce – nie napisałam prawie nic od czasu, gdy zmieniłam pracę. Babcia przy każdym spotkaniu pyta, czy „korporacja” zdążyła już przeżuć mnie i wypluć. Odpowiem krótko: nie i nie! To prawda, że w ciągu ostatnich kilku miesięcy nie napisałam zbyt wiele. Miało […]

by ynka at December 15, 2013 07:46 PM

September 08, 2013

Krzysztof Szarzyński

Warszawa 2013 – Quati w stolicy.

Zanim zaproszę na ostatnią odsłonę zdjęć z mojego krótkiego pobytu w Warszawie, chwila luźnych wywodów. Nocowałem w hotelu przy placu Konstytucji, który oferował dwa rodzaje pokoi: ciche i z widokiem na miasto. Mi się trafiło oglądanie miasta, ale ponieważ ze mną na szkolenie przyjechało kilka innych osób z Poznania, to zdecydowaliśmy się z Adamem iść […]

by Quati at September 08, 2013 06:19 PM

September 04, 2013

Krzysztof Szarzyński

Warszawa 2013 – część druga

Dziś druga porcja obrazków z Warszawy. Hasłem przewodnim miało być “ludzie w Warszawie”, ale chyba troszkę bardziej pasuje “życie w Warszawie”. Chyba nigdy nie byłem dobry w nadawaniu tytułów i nazw. 🙂 Część trzecia zostanie opatrzona moimi przemyśleniami i komentarzem co do samego miasta. Zdjęcia również będą bardziej dotyczyć tego co widziałem i przeżyłem 🙂

by Quati at September 04, 2013 05:27 PM

September 01, 2013

Krzysztof Szarzyński

Warszawa 2013 – część pierwsza

W tym roku wakacje były podzielone na dwie cześći. Najpierw pojechaliśmy z Olą do Zwierzyńca, gdzie odpoczywaliśmy aktywnie zwiedzając Zamojszczyznę i korzystając z dobrodziejstwa krętych rzek i kajaków turystycznych. Ciągle czekam na chwilę weny żeby wybrać kilka zdjęć i je opublikować 🙂  Drugim etapem moich wakacji było… skończenie życia jako student i rozpoczęcie “dorosłości” w […]

by Quati at September 01, 2013 08:07 PM

Girl, lost in IT

Cicho sza!

Wcale nie zarzuciłam pisania tego bloga. Krótko o tym, co ostatnio dzieje się u mnie: Kupiliśmy dom. Trwa remont. Kompletnie nie doszacowałam nakładów czasowych (o finansowych nie będziemy tu rozmawiać) niezbędnych do realizacji takiego przedsięwzięcia. Tłumaczę książkę o C++ i Qt (Dlaczego? Patrz wyżej). Jest gruba. Zamiast tłumaczyć, spędzam godziny na rozmowach z fachowcami. Pół […]

by ynka at September 01, 2013 07:36 PM

July 13, 2013

Girl, lost in IT

Open’er, czyli wieczne poszukiwania

Heineken Open’er to co roku ta sama historia. Wiele tygodni przed festiwalem niecierpliwie zaczynam śledzić lineup i planować, co będę chciała zobaczyć. Bliżej terminu okazuje się, że z pięciu wymarzonych koncertów dwa odbywają się naraz, a trzy inne jeden po drugim – na scenach oddalonych od siebie o kilometr. Planuję także, z kim pojadę i […]

by ynka at July 13, 2013 08:00 AM

June 26, 2013

Krzysztof Szarzyński

Nowe zabawki i noc kupały

Obiecanki – cacanki. Czyli tradycyjnie, jak Quati mówi, że coś napisze, to znaczy, że mówi. 🙂 Dziś mam kilka zdjęć zrobionych za pomocą nowej zabawki, która oprócz tego, że jest świetnym gadżetem, to spełnia też czasami funkcję obiektywu. Otóż moim nabytkiem jest Sigma 50 mm F1.4 DG EX HSM, czyli typowa portretowa “stałka” z dość jasnym […]

by Quati at June 26, 2013 09:43 PM

May 30, 2013

Girl, lost in IT

Feminiści kontra statystyka

Uczestniczyłam ostatnio w konferencji, w której programie znalazł się panel dyskusyjny poświęcony mniejszościom w środowisku informatyków. Podczas panelu miałam okazję porozmawiać z inspirującymi i pełnymi dobrej woli ludźmi, jednak doszło tam również do pewnego zderzenia opinii, które wspominam do tej pory. Był sobie facet. Doświadczony lider, blogger, walczący o zwiększenie liczby kobiet w IT. Osoba, […]

by ynka at May 30, 2013 04:54 PM

April 20, 2013

Girl, lost in IT

Kup swojemu dziecku sobie robota Lego Mindstorms

Pierwszy raz klocki Lego widziałam, będąc małym dzieckiem, nie pamiętam nawet, czy było to Peweksie, „u prywaciarza”, czy może u kolegi, którego tata był kapitanem na statku handlowym, przez co w ich domu zawsze można było trafić na skarby niedostępne w normalnych sklepach (począwszy od mandarynek). Pamiętam, że zachwyciły mnie czyste kolory, przemyślane projekty oraz możliwości, jakie […]

by ynka at April 20, 2013 04:05 PM

March 16, 2013

Girl, lost in IT

Na słodko-gorzko o skutkach asertywności

Minęło już półtora miesiąca od kiedy zmieniłam pracę. Czas… biegnie szybko. Decyzja ciągle wydaje się dobra. Uczę się bardzo dużo. W trakcie ostatnich tygodni dwa razy odwiedziłam Warszawę, po raz pierwszy spróbowałam koreańskiej kuchni (z wyjątkiem zupy kimchi w Art Sushi, którą polecam, ale tylko ludziom o żołądkach ze stali), a także zapisałam się na […]

by ynka at March 16, 2013 12:37 PM

February 24, 2012

Dopierała Andrzej

2011-05-27 Darmowe fotoradary dla nissan connect

Może kogoś zainteresuje - nie znalazłem nigdzie opisu jak to łatwo zrobić “za friko”.

1. Ściągamy listę fotoradarów z http://ump.waw.pl/ plik z mapą fotoradarów (http://ump.waw.pl/update/Jacek.zip).
2. Rozkompresowujemy go
3. Łączymy to co nas interesuje do jednego pliku csv:

undefine@uml:~/tmp$ cat Kontrole\ Drogowe/*.csv Niebezpieczne\ Miejsca/*.csv Przejazdy\ Kolejowe/*.csv >x.csv
undefine@uml:~/tmp$ 

4. Usuwamy polskie znaczki (zapewne można jakoś przekodować, ale nie chciało mi się metodą prób i błędów szukać kodowania):

iconv -f cp1250 -t ascii//TRANSLIT  < x.csv > jacek.csv

5. Plik jacek.csv umieszczamy w katalogu myPOIs/myPOIWarnings na pendrive
6. Pendrive wkładamy do nissan connect i ładujemy POI użytkownika z menu(Setup → Navigation → Download my POIs)
7. Przestrzegamy ograniczeń ;)

February 24, 2012 08:24 AM

December 23, 2011

Dopierała Andrzej

2011-12-23 Ankieta Polskiego Badania Czytelnictwa: Przyszła do mnie prośba o wypełnienie ankiety. Z Polskiego Badania Czytelnictwa, sp. z o.o. Niby nic dziwnego, ale.. przyszła "smailem". A sama ankieta, po podaniu "pinu" z listu do wypełnienia na stronie http://www.ankieta.pbc.pl/ W zamian za wypełnienie ankiety oferują m.in. kupony sodexo na kwotę 20zł. I w sumie... Podszedłem do tematu trochę z mieszanymi uczuciami. Jak? Skąd? Po co? Z tego co znalazłem dane osobowe otrzymali z bazy PESEL na podstawie Dz.U. 2006 nr 139 poz. 993, 44h ust 2 par 2. List - był zaadresowany do mnie (imię, nazwisko, adres). Natomiast w samej ankiecie na stronie zwrot był przez "Pani". Pomyłka? Koniec końców zmarnowałem kwadrans i wypełniłem. Co prawda niezbyt wartościowo, bo z proponowanych czasopism to tylko sporadycznie Metro przeglądam jak akurat mi w korku wcisną, natomiast Fantastyki w ankiecie nie było, ale - jak to badanie statystyczne, to.. czemu nie.

Przyszła do mnie prośba o wypełnienie ankiety.
Z Polskiego Badania Czytelnictwa, sp. z o.o.

Niby nic dziwnego, ale.. przyszła “smailem”. A sama ankieta, po podaniu “pinu” z listu do wypełnienia na stronie http://www.ankieta.pbc.pl/

W zamian za wypełnienie ankiety oferują m.in. kupony sodexo na kwotę 20zł.

I w sumie… Podszedłem do tematu trochę z mieszanymi uczuciami. Jak? Skąd? Po co? Z tego co znalazłem dane osobowe otrzymali z bazy PESEL na podstawie Dz.U. 2006 nr 139 poz. 993, 44h ust 2 par 2.

List - był zaadresowany do mnie (imię, nazwisko, adres). Natomiast w samej ankiecie na stronie zwrot był przez “Pani”. Pomyłka?

Koniec końców zmarnowałem kwadrans i wypełniłem. Co prawda niezbyt wartościowo, bo z proponowanych czasopism to tylko sporadycznie Metro przeglądam jak akurat mi w korku wcisną, natomiast Fantastyki w ankiecie nie było, ale - jak to badanie statystyczne, to.. czemu nie.

December 23, 2011 09:04 PM

November 07, 2011

Dopierała Andrzej

2011-11-07 brother mfc5490CN: drukarka brother mfc 5490cn pod linuksem i.. ipv6.

Stara drukareczka HP 6540 się popsuła (uchwyt od czarnego tuszu przestał kontaktować), naprawa oczywiście nieopłacalna, a mi by się w domu przydał skaner, wiec… Nabyłem nową drukareczkę. Po przejrzeniu dostępnych opcji wybór padł na Brother MFC 5490CN
I - jak na razie nie mam co narzekać.
Drukowanie spod linuksa - ruszyło praktycznie od razu.
Skanowanie spod linuksa - również. Mimo iż po raz pierwszy w życiu konfigurowałem skaner pod linuksem.

A na dokładkę - drukarka działa również po ipv6…

Local> show ip v6

IPv6 is Enabled
IPv6 Static Address is Enabled
IPv6 Addresses are 2A02:848:A::XXXX:XXXX:XXXX:XXXX/64 (via Router)
                   FE80::XXXX:XXXX:XXXX:XXXX/64 (link-local)

The priority IP version of name resolving is IPv4

Będę musiał chyba firewalla wyklikać dla ipv6 :/

November 07, 2011 10:56 PM

September 09, 2011

Ogrodowczyk Wojciech

Koniec tej zabawy

Jak co bystrzejsi czytelnicy mogli zauważyć, nie pisuję już tu praktycznie nic, a zdjęcia tu umieszczane to jedynie opóźnione „przedruki” względem mojego konta na flickr. Kierując się więc brzytwą Okhama i zwykłym lenistwem...

September 09, 2011 08:12 AM

August 22, 2011

Dopierała Andrzej

2011-08-22 Lekko przerobiony multi router looking glass w php: Skrypt do przedstawiania na routerach.

Już kilka osób się mnie pytało jak zrobiłem http://lg.maverick.com.pl/.

Bazuję na lekko zmodyfikowanej wersji MRLG (Multi Router Looking Glass for PHP). Obecnie jego strona niestety nie działa - i oryginału nie mam do pobrania.

Moją zmodyfikowaną wersję umieściłem na mrlg-20091215.tgz, natomiast plik konfiguracyjny do niej na mrlg-config.php. Na pytania nie odpowiadam, w konfiguracji nie pomagam (bo nie mam czasu) - ale może komuś się przyda :).
Licencja - zgodnie z licencja oryginału - GPL.

Ale jak masz jakieś poprawki - podsyłaj :)

Wiem że brzydko zrobione, ale - było potrzebne na szybko i w parę godzin tylko na tyle mnie było stać.

Jak dodasz w swojej sieci kopię - zgłoś na traceroute.org - widoczność swojego miejsca w sieci się często przydaje :).

August 22, 2011 07:55 PM

August 21, 2011

Ogrodowczyk Wojciech

August 11, 2011

Ogrodowczyk Wojciech

August 05, 2011

Dopierała Andrzej

2011-08-05 Problematyczne ipv6 - dziwny resolver: problem z domenami z dodanym rekordem AAAA.

undefine@uml:~$ host aramin.net
aramin.net has address 42.1.94.0
;; Warning: Message parser reports malformed message packet.
;; connection timed out; no servers could be reached

i tak dla sporej części, o ile nie wszystkich adresów z dualstackiem - taki dziwny feature AP DSL-G604T w hotelu.

Do tej pory myślałem że dodanie rekordu AAAA nic nie psuje, teraz - sam się przekonałem że nie jest tak różowo, jak sie okazało że nie mogę się dostać na strony/serwery z dodanym AAAA. Na szczęście - można skorzystać z własnych albo googlowych dnsów.

Oczywiście prawidłowa odpowiedź to

undefine@uml:~$ host aramin.net
aramin.net has address 195.110.48.48
aramin.net has IPv6 address 2a01:5e00:2:52::30
aramin.net mail is handled by 0 mx.aramin.net.

August 05, 2011 04:55 PM

July 29, 2011

Ogrodowczyk Wojciech

July 27, 2011

Ogrodowczyk Wojciech

July 21, 2011

Ogrodowczyk Wojciech

July 14, 2011

Ogrodowczyk Wojciech

June 26, 2011

Dopierała Andrzej

2011-06-26 IPv6 na stronie: ipv6 na stronie

Co prawda po IPv6 day, ale.. wreszcie dołożyłem AAAA do mojej strony(i stron firmowych). Ciekawe co wybuchnie ;)

June 26, 2011 07:24 PM

June 17, 2011

Ogrodowczyk Wojciech

May 31, 2011

Ogrodowczyk Wojciech

Planet shot

Bcn planet shot

Eksperymentale ujęcie wychodka na szczycie świata, krok po...

May 31, 2011 11:44 AM

May 29, 2011

Ogrodowczyk Wojciech

March 12, 2011

Dopierała Andrzej

2011-03-12 IPv6-garsc-statystyk: kilka słów podsumowania o ruchu ipv6

Kilka statystyk z pewnego routerka. Zbierane ip6tables, w dłuższym okresie czasu. Wykresów nie daję, bo za mała próbka by ładnie wyglądało ;)

Dane z pewnej sieci osiedlowej w Poznaniu. IPv6 udostępnione klientom przez radvd. Głównie klienci “prywatni”.

Wejście:
2% - 6to4
pomijalne - PIX
24% - PLIX
3% - natywne IPv6 od Crowleya
69% - tunel z HE

Wyjście:
51% - 6to4(!)
6% - PIX
36% - PLIX
1% - Crowley
6% - tunel z HE.

Wnioski:
- podobnie jak w przypadku ipv4 duża część ruchu przypada na PLIX
- upload to głównie ruch kierowany do 6to4 - jak sądzę ruch p2p.
- bardzo duży download na tunelu z HE. Co prawda miałem trochę wątpliwości czy należy się w to bawić - to jednak obserwując ruch przy włączonym i przy wyłączonym tunelu widać że opóźnienia przez HE są często niższe. Pozatym - alternatywa to pchanie ruchu przez Crowleya, który.. również sporą część ruchu ma przez HE. HAWE jak na razie ipv6 nie dostarcza.

March 12, 2011 11:49 PM

February 22, 2011

Dopierała Andrzej

2011-02-22 IPv6 a 6to4: ipv6 6to4 sit0 routing ruch siec

Powolutku bawię się w wdrożenie IPv6 u pewnego ISP.

Na peeringach (w PIX i PLIX) ipv6 śmiga “natywnie”. Świata niestety jak na razie nikt nie dostarczył, więc leci tunelem z HE.

Do tego rozgłoszenie prefiksów do kilku testowych sieci - i troszkę ruchu widać.

W którymś momencie zauważyłem, że trochę ruchu leci do 6to4. Postawiłem więc bezpośredniego relaya(opis z http://wiki.debian.org/DebianIPv6) i…

mav-ipv6

Wniosek? Wbrew pozorom bardzo dużo (tak na oko 1/3) ruchu to ruch z relayami 6to4. Stąd zapewnienie dobrej komunikacji z nimi powinno być dosyć istotne przy udostępnianiu ipv6. Do testowego ip z którym obserwowałem ruch po ustawieniu bezpośredniego tunelowania 6to4 na moim routerze opóźnienia spadły z ok 80 do 50ms - a ruch wzrósł o kilkanaście procent.

(na wykresie jest widoczny wyłącznie ruch na tunelach - peeringi/polska leci natywnie, stąd nie mam prostej możliwości wyróżnienia go od ipv4)

February 22, 2011 11:06 PM

February 17, 2011

Dopierała Andrzej

2011-02-17 Rozkład ruchu na łączach: rozkład ruchu plix hawe tp pix

Taka mała ciekawostka.

Jest sobie mały operator. Świadczący głównie usługę dostępu do internetu dla “ludzi”. Pakiety - dosyć duże, po kilka/kilkadziesiąt megabitów, upload ciut mniejszy - po 2-3 megabity.
Ogólnie - zazwyczaj mało kto dociera do limitu w którąkolwiek ze stron.

Do tego jest troszkę hostingu i łącz biznesowych… Ale większośc to klienci indywidualni.

Łącza:
- peering w PIX-ie (http://www.pix.net.pl)
- peering w PLIX-ie (http://www.plix.pl)
- PBT HAWE (http://www.pbthawe.eu)
- Transmisję CDP Global od crowleya (http://www.crowley.pl)

i w którymś momencie na parę chwil pojawiła się testowa transmisja do TPSA - normalnie leci przez HAWE (i dalej styk z crowleyem).

Ruch - puszczony przez bgp prawie “samopas”. Lekkie preferencje by sterować ruchem na łączach zagranicznych (hawe/cdp), gdzieniegdzie unikanie problematycznych ścieżek - ale - można powiedzieć że rozkład jest prawie naturalny.

I teraz - procentowy wykres ruchu:
rozklad-lacz

Interesuje nas głównie download - uploadu jest niewiele - ok połowy downloadu, więc zazwyczaj mieści się w ramach kontraktu.

Co jest ciekawe… ok 30% ruchu zamyka się w plixie. Nawet trochę więcej.

PIX - jest malutki. poniżej 3% ruchu. Gdyby nie skala oraz fakt że jest prawie za darmo - nie było by go sensu trzymać.

HAWE i crowley - utrzymują się mniej więcej na zbliżonym poziomie - przerzucanie to głównie zmiany na ich upstreamach oraz “rzucanie” nimi (prepend przez community) by przerzucić na łącze gdzie dalej od kontraktu.

Przez jakiś czas była testowana tpsa. I tutaj niespodzianka - download był ledwo w okolicach 5% sumarycznego ruchu. Czyli - biorąc pod uwagę cenę - malutko. Z koleji upload to ok 20% ruchu - co w tej sytuacji oznaczało że było to jedyne łącze gdzie upload przekraczał download! I przypominam że to nie hosting, tylko głównie klienci indywidualni. Cóż - P2P rządzi.

February 17, 2011 11:59 AM

January 06, 2011

Dopierała Andrzej

2011-01-06 Konto w aliorbank: zakładanie konta w aliorbanku cz.1

Stwierdziłem że w mojej małej firemce przyda się kolejne konto. Obecne mam w mBanku, bo.. wiadomo - za darmo. No - prawie. 1zł za każdy przelew “na zewnątrz” - to już trochę w miesiącu wychodzi.

A Aliorbank ciągle kusi darmowym kontem, 5-cioma darmowymi przelewami w miesiącu i “premią” 50zł przy stanie konta 9k. Czyli więcej niż na lokacie w mbanku.

Z nowym rokiem - próbuję więc założyć konto.
Pierwsze wrażenia po przebrnięciu przez formularz?

  • Nie pozwala mi na wpisywanie polskich znaczków. Przeglądarka chrome. Po wklejeniu tekstu z polskimi znaczkami - ogonki znikają.
  • Do wybrania klasyfikacja usług… Ja w GUS-ie mam zgłoszoną 6202Z(działalność związana z doradztwem w zakresie informatyki - wg klasyfikacji z 2007 roku). A na stronie pozwalają na wybór pomiędzy.. 6201 a 6203.

Ale przebrnąłem - polskie znaczki jak sądzę poprawią mi w oddziale. O efektach pewnie poinformuję…

January 06, 2011 08:40 PM

October 16, 2010

Nawrot Andrzej

Rozmowy ze specjalistą ds. wdrożeń

Taki kwiatek.
Pytanie dotyczące odpowiedzialności za wykonywanie backupów pewnego systemu i odpowiedź konsultanta.

IT: Kto wykonuje backupy?

Specjalista:Backupy wykonuje MS SQL z automatu codziennie, raz na okres np. miesiąc kwartał baza powinna być nagrywana na trwały nośnik i to w zależności od firmy albo my albo dział IT
Danych nie powinniśmy stracić żadnych tylko w przypadku kataklizmu kiedy to stracimy serwer oraz kopie dyskowe – pozostaną nam tylko kopie na trwałych nośnikach, ale to sytuacje bardzo sporadyczna
Kopie na serwerze służą przede wszystkim do ewentualnych porównań w przypadku uszkodzenia – stąd codzienne kopie .

by jendras (noreply@blogger.com) at October 16, 2010 08:34 PM

June 08, 2010

Nawrot Andrzej

PowerShell via GPO

Aby zmienić ustawienia wykonywania skryptów potrzebujemy tego template'a.

http://www.microsoft.com/downloads/details.aspx?familyid=2917a564-dbbc-4da7-82c8-fe08b3ef4e6d&displaylang=en

by jendras (noreply@blogger.com) at June 08, 2010 08:29 AM

March 04, 2010

Nawrot Andrzej

Limit połączeń RDP

Ku pamięci

query session /server:servername


reset session [ID] /server:servername

by jendras (noreply@blogger.com) at March 04, 2010 02:17 PM

October 28, 2009

Nawrot Andrzej

Rodzinka w komplecie

 

Rodzinka w komplecie, brakuje tylko zniewiescialego SL :)
Posted by Picasa

by jendras (noreply@blogger.com) at October 28, 2009 10:08 PM

October 07, 2009

Najtkowski Marcin Jan

Dua Tonight

W trakcie nieustających muzycznych wojaży trafiłem znów na kawałek, którego słucham po kilkanaście-kilkadziesiąt razy dziennie. Kobiecy wokal – oczywiście, fajny, “chwytliwy” rytm oraz ogólna “sympatyczość” sprawiły, że Tonight zespołu Dua stał się moim numerem jeden ostatniego tygodnia.

<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" height="265" width="320"><param name="allowFullScreen" value="true"/><param name="allowscriptaccess" value="always"/><param name="src" value="http://www.youtube-nocookie.com/v/YIfJvPm9-rg&amp;hl=pl&amp;fs=1&amp;rel=0&amp;color1=0x3a3a3a&amp;color2=0x999999"/><param name="allowfullscreen" value="true"/><embed allowfullscreen="true" allowscriptaccess="always" height="265" src="http://www.youtube-nocookie.com/v/YIfJvPm9-rg&amp;hl=pl&amp;fs=1&amp;rel=0&amp;color1=0x3a3a3a&amp;color2=0x999999" type="application/x-shockwave-flash" width="320"></embed></object>

Utwór można znaleźć na A Lounge Supreme vol. 5.

by naytec at October 07, 2009 11:40 AM