Moving all of the website into the public repo. This is a mess

launchpad/website
Katharina Fey 7 years ago
parent b004cfd65b
commit 964d22f599
  1. 124
      Makefile
  2. 117
      README.md
  3. 11
      blog_update.sh
  4. 14
      content/blog/00_introduction.md
  5. 57
      content/blog/hardware/001-omnitool-introduction.md
  6. 33
      content/blog/hardware/002-christmas-bauble.md
  7. 38
      content/blog/hardware/003-christmas-bauble-update.md
  8. 21
      content/blog/hardware/004-ws2812b-breakouts.md
  9. 51
      content/blog/hardware/005-open-plantb0t.md
  10. 89
      content/blog/miscellanious/000-newdawn.md
  11. 45
      content/blog/miscellanious/001-lonelyrobot.md
  12. 53
      content/blog/miscellanious/002-reedb-c-port.md
  13. 59
      content/blog/miscellanious/003-recovering-a-luks-container.md
  14. 91
      content/blog/miscellanious/004-getting-started-with-xmmpp.md
  15. 127
      content/blog/miscellanious/005-getting-started-with-reedb.md
  16. 27
      content/blog/miscellanious/006-another-blog-update.md
  17. 67
      content/blog/miscellanious/007-post-congress-2017.md
  18. 116
      content/blog/miscellanious/008-libgdx-super-ui.md
  19. 60
      content/blog/miscellanious/009-moonscript-adventures.md
  20. 25
      content/blog/summerofcode/gsoc-000-i-got-accepted.md
  21. 37
      content/blog/summerofcode/gsoc-001-prepping-the-patient.md
  22. 69
      content/blog/summerofcode/gsoc-002-final-evaluation.md
  23. BIN
      content/downloads/cuckoo_hashing.pdf
  24. BIN
      content/downloads/gameofcodes/artpack1.zip
  25. BIN
      content/images/banner_bg2x.png
  26. BIN
      content/images/banners/plantb0t_revA.png
  27. BIN
      content/images/cf_disk.png
  28. BIN
      content/images/cf_disk1.png
  29. BIN
      content/images/christmas_bauble_pcb.jpg
  30. BIN
      content/images/christmas_bauble_pcb.png
  31. BIN
      content/images/christmas_bauble_render.png
  32. BIN
      content/images/example.png
  33. BIN
      content/images/favicon.ico
  34. BIN
      content/images/flora_pinout.png
  35. BIN
      content/images/flora_withleds.jpg
  36. BIN
      content/images/front_matrix_background.png
  37. BIN
      content/images/gameofcodes/series01/01_setup_ui.png
  38. BIN
      content/images/gameofcodes/series01/02_setup_ui.png
  39. BIN
      content/images/gameofcodes/series01/04_eclipse.png
  40. BIN
      content/images/gameofcodes/series01/05_eclipse.png
  41. BIN
      content/images/gameofcodes/series01/06_eclipse.png
  42. BIN
      content/images/gameofcodes/series01/07_gamechange.png
  43. BIN
      content/images/gameofcodes/series02/01_framelife.png
  44. BIN
      content/images/gameofcodes/series02/02_createclass.png
  45. BIN
      content/images/gameofcodes/series03/01_badrotation.gif
  46. BIN
      content/images/gameofcodes/series03/02_rotating.gif
  47. BIN
      content/images/gameofcodes/series04/01_800x600.png
  48. BIN
      content/images/gameofcodes/series04/02_720p.png
  49. BIN
      content/images/gameofcodes/series04/03_1080p.png
  50. BIN
      content/images/gameofcodes/series04/04_1440p.png
  51. BIN
      content/images/gsoc/00_acceptance.png
  52. BIN
      content/images/gsoc/01_debugger.png
  53. BIN
      content/images/gsoc/02_cryptoui.png
  54. BIN
      content/images/jabber/pidgin1.png
  55. BIN
      content/images/jabber/pidgin2.png
  56. BIN
      content/images/jabber/pidgin3.png
  57. BIN
      content/images/jabber/pidgin4.png
  58. BIN
      content/images/jabber/pidgin5.png
  59. BIN
      content/images/jabber/pidgin6.png
  60. BIN
      content/images/libgdx_ui/01_base_problem.png
  61. BIN
      content/images/libgdx_ui/02_ui_structure.png
  62. BIN
      content/images/logo3.png
  63. BIN
      content/images/lua_moon_banner.jpg
  64. BIN
      content/images/lua_moon_banner.png
  65. BIN
      content/images/omnitool_background.jpg
  66. BIN
      content/images/omnitool_background2.jpg
  67. BIN
      content/images/plantb0t_RevA_front.png
  68. BIN
      content/images/plantb0t_RevA_naked.png
  69. BIN
      content/images/rad1o_badge.png
  70. BIN
      content/images/rdb_article_banner.png
  71. BIN
      content/images/reedb_banner.png
  72. 0
      content/images/silly_no_visitors_blog.png
  73. BIN
      content/images/ws_2812b_single.png
  74. 112
      content/kookie.txt
  75. 21
      content/pages/aboutme.md
  76. 9
      content/pages/home.md
  77. 6
      content/pages/showcase.md
  78. 6
      content/pages/teaching.md
  79. 114
      content/pgp/kookie.txt
  80. 16
      content/pgp/msg
  81. 296
      content/teaching/gameofcodes/01-goc-setup-basics.md
  82. 270
      content/teaching/gameofcodes/02-goc-input-movement.md
  83. 159
      content/teaching/gameofcodes/03-goc-input-rotation.md
  84. 110
      content/teaching/jni/01-jni-intro.md
  85. 103
      develop_server.sh
  86. 94
      fabfile.py
  87. 85
      pelicanconf.py
  88. 53
      plugins/summary/Readme.rst
  89. 1
      plugins/summary/__init__.py
  90. BIN
      plugins/summary/__pycache__/__init__.cpython-36.pyc
  91. BIN
      plugins/summary/__pycache__/summary.cpython-36.pyc
  92. 90
      plugins/summary/summary.py
  93. 75
      plugins/summary/test_summary.py
  94. 24
      publishconf.py
  95. BIN
      static/fonts/opensans-02a7f5c491cda3d79832291d9f0903a1086ad308.woff2
  96. BIN
      static/fonts/opensans-0780068aad6429b678dbfc89a831016b16efa340.woff2
  97. BIN
      static/fonts/opensans-082d935809ff8624c407f5ebfa9f707031f6871d.woff2
  98. BIN
      static/fonts/opensans-0843ae9e7843eae6a72c5b8f28d4dd6e5106f516.woff2
  99. BIN
      static/fonts/opensans-101147f1175d6b5ffc2f79f8a3f64a0d7f94e418.woff2
  100. BIN
      static/fonts/opensans-14a380d9ddfdee7aecf38c241c450bfe813d94e5.woff2
  101. Some files were not shown because too many files have changed in this diff Show More

@ -0,0 +1,124 @@
PY?=python3
PELICAN?=pelican
PELICANOPTS=
BASEDIR=$(CURDIR)
INPUTDIR=$(BASEDIR)/content
OUTPUTDIR=$(BASEDIR)/output
CONFFILE=$(BASEDIR)/pelicanconf.py
PUBLISHCONF=$(BASEDIR)/publishconf.py
FTP_HOST=localhost
FTP_USER=anonymous
FTP_TARGET_DIR=/
SSH_HOST=localhost
SSH_PORT=22
SSH_USER=root
SSH_TARGET_DIR=/var/www
S3_BUCKET=my_s3_bucket
CLOUDFILES_USERNAME=my_rackspace_username
CLOUDFILES_API_KEY=my_rackspace_api_key
CLOUDFILES_CONTAINER=my_cloudfiles_container
DROPBOX_DIR=~/Dropbox/Public/
GITHUB_PAGES_BRANCH=gh-pages
DEBUG ?= 0
ifeq ($(DEBUG), 1)
PELICANOPTS += -D
endif
RELATIVE ?= 0
ifeq ($(RELATIVE), 1)
PELICANOPTS += --relative-urls
endif
help:
@echo 'Makefile for a pelican Web site '
@echo ' '
@echo 'Usage: '
@echo ' make html (re)generate the web site '
@echo ' make clean remove the generated files '
@echo ' make regenerate regenerate files upon modification '
@echo ' make publish generate using production settings '
@echo ' make serve [PORT=8000] serve site at http://localhost:8000'
@echo ' make serve-global [SERVER=0.0.0.0] serve (as root) to $(SERVER):80 '
@echo ' make devserver [PORT=8000] start/restart develop_server.sh '
@echo ' make stopserver stop local server '
@echo ' make ssh_upload upload the web site via SSH '
@echo ' make rsync_upload upload the web site via rsync+ssh '
@echo ' make dropbox_upload upload the web site via Dropbox '
@echo ' make ftp_upload upload the web site via FTP '
@echo ' make s3_upload upload the web site via S3 '
@echo ' make cf_upload upload the web site via Cloud Files'
@echo ' make github upload the web site via gh-pages '
@echo ' '
@echo 'Set the DEBUG variable to 1 to enable debugging, e.g. make DEBUG=1 html '
@echo 'Set the RELATIVE variable to 1 to enable relative urls '
@echo ' '
html:
$(PELICAN) $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS)
clean:
[ ! -d $(OUTPUTDIR) ] || rm -rf $(OUTPUTDIR)
regenerate:
$(PELICAN) -r $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS)
serve:
ifdef PORT
cd $(OUTPUTDIR) && $(PY) -m pelican.server $(PORT)
else
cd $(OUTPUTDIR) && $(PY) -m pelican.server
endif
serve-global:
ifdef SERVER
cd $(OUTPUTDIR) && $(PY) -m pelican.server 80 $(SERVER)
else
cd $(OUTPUTDIR) && $(PY) -m pelican.server 80 0.0.0.0
endif
devserver:
ifdef PORT
$(BASEDIR)/develop_server.sh restart $(PORT)
else
$(BASEDIR)/develop_server.sh restart
endif
stopserver:
$(BASEDIR)/develop_server.sh stop
@echo 'Stopped Pelican and SimpleHTTPServer processes running in background.'
publish:
$(PELICAN) $(INPUTDIR) -o $(OUTPUTDIR) -s $(PUBLISHCONF) $(PELICANOPTS)
ssh_upload: publish
scp -P $(SSH_PORT) -r $(OUTPUTDIR)/* $(SSH_USER)@$(SSH_HOST):$(SSH_TARGET_DIR)
rsync_upload: publish
rsync -e "ssh -p $(SSH_PORT)" -P -rvzc --delete $(OUTPUTDIR)/ $(SSH_USER)@$(SSH_HOST):$(SSH_TARGET_DIR) --cvs-exclude
dropbox_upload: publish
cp -r $(OUTPUTDIR)/* $(DROPBOX_DIR)
ftp_upload: publish
lftp ftp://$(FTP_USER)@$(FTP_HOST) -e "mirror -R $(OUTPUTDIR) $(FTP_TARGET_DIR) ; quit"
s3_upload: publish
s3cmd sync $(OUTPUTDIR)/ s3://$(S3_BUCKET) --acl-public --delete-removed --guess-mime-type
cf_upload: publish
cd $(OUTPUTDIR) && swift -v -A https://auth.api.rackspacecloud.com/v1.0 -U $(CLOUDFILES_USERNAME) -K $(CLOUDFILES_API_KEY) upload -c $(CLOUDFILES_CONTAINER) .
github: publish
ghp-import -m "Generate Pelican site" -b $(GITHUB_PAGES_BRANCH) $(OUTPUTDIR)
git push origin $(GITHUB_PAGES_BRANCH)
.PHONY: html help clean regenerate serve serve-global devserver publish ssh_upload rsync_upload dropbox_upload ftp_upload s3_upload cf_upload github

@ -1,114 +1,9 @@
# Nest
www.spacekookie.de
===
This is my very heavily customised website theme for [spacekookie.de](https://spacekookie.de). Not sure why I keep this public as it will probably never be any good for anyone. But oh well ¯\\\_(ツ)_/¯
Dependencies are `pelican markdown webassets`
This is a fork that I created as it's own repository. The original is from [https://github.com/molivier/nest](https://github.com/molivier/nest)
The pelican build.
## Features
* Featured site header image
* Featured article header image
* **Pygments** syntax highlighting
* **Disqus** support for comments
* **Google Analytics** support
* RSS and Atom feeds
## Settings
Nest template can be customized by adding parameters to your `pelicanconf.py` file. Template specifics parameters are prefixed with template name.
### Pelican.conf example
```python
# NEST Template
THEME = 'nest'
SITESUBTITLE = u'My Awesome Blog'
# Minified CSS
NEST_CSS_MINIFY = True
# Add items to top menu before pages
MENUITEMS = [('Homepage', '/'),('Categories','/categories.html')]
# Add header background image from content/images : 'background.jpg'
NEST_HEADER_IMAGES = ''
NEST_HEADER_LOGO = '/image/logo.png'
# Footer
NEST_SITEMAP_COLUMN_TITLE = u'Sitemap'
NEST_SITEMAP_MENU = [('Archives', '/archives.html'),('Tags','/tags.html'), ('Authors','/authors.html')]
NEST_SITEMAP_ATOM_LINK = u'Atom Feed'
NEST_SITEMAP_RSS_LINK = u'RSS Feed'
NEST_SOCIAL_COLUMN_TITLE = u'Social'
NEST_LINKS_COLUMN_TITLE = u'Links'
NEST_COPYRIGHT = u'© blogname 2015'
# Footer optional
NEST_FOOTER_HTML = ''
# index.html
NEST_INDEX_HEAD_TITLE = u'Homepage'
NEST_INDEX_HEADER_TITLE = u'My Awesome Blog'
NEST_INDEX_HEADER_SUBTITLE = u'Smashing The Stack For Fun And Profit'
NEST_INDEX_CONTENT_TITLE = u'Last Posts'
# archives.html
NEST_ARCHIVES_HEAD_TITLE = u'Archives'
NEST_ARCHIVES_HEAD_DESCRIPTION = u'Posts Archives'
NEST_ARCHIVES_HEADER_TITLE = u'Archives'
NEST_ARCHIVES_HEADER_SUBTITLE = u'Archives for all posts'
NEST_ARCHIVES_CONTENT_TITLE = u'Archives'
# article.html
NEST_ARTICLE_HEADER_BY = u'By'
NEST_ARTICLE_HEADER_MODIFIED = u'modified'
NEST_ARTICLE_HEADER_IN = u'in category'
# author.html
NEST_AUTHOR_HEAD_TITLE = u'Posts by'
NEST_AUTHOR_HEAD_DESCRIPTION = u'Posts by'
NEST_AUTHOR_HEADER_SUBTITLE = u'Posts archives'
NEST_AUTHOR_CONTENT_TITLE = u'Posts'
# authors.html
NEST_AUTHORS_HEAD_TITLE = u'Author list'
NEST_AUTHORS_HEAD_DESCRIPTION = u'Author list'
NEST_AUTHORS_HEADER_TITLE = u'Author list'
NEST_AUTHORS_HEADER_SUBTITLE = u'Archives listed by author'
# categories.html
NEST_CATEGORIES_HEAD_TITLE = u'Categories'
NEST_CATEGORIES_HEAD_DESCRIPTION = u'Archives listed by category'
NEST_CATEGORIES_HEADER_TITLE = u'Categories'
NEST_CATEGORIES_HEADER_SUBTITLE = u'Archives listed by category'
# category.html
NEST_CATEGORY_HEAD_TITLE = u'Category Archive'
NEST_CATEGORY_HEAD_DESCRIPTION = u'Category Archive'
NEST_CATEGORY_HEADER_TITLE = u'Category'
NEST_CATEGORY_HEADER_SUBTITLE = u'Category Archive'
# pagination.html
NEST_PAGINATION_PREVIOUS = u'Previous'
NEST_PAGINATION_NEXT = u'Next'
# period_archives.html
NEST_PERIOD_ARCHIVES_HEAD_TITLE = u'Archives for'
NEST_PERIOD_ARCHIVES_HEAD_DESCRIPTION = u'Archives for'
NEST_PERIOD_ARCHIVES_HEADER_TITLE = u'Archives'
NEST_PERIOD_ARCHIVES_HEADER_SUBTITLE = u'Archives for'
NEST_PERIOD_ARCHIVES_CONTENT_TITLE = u'Archives for'
# tag.html
NEST_TAG_HEAD_TITLE = u'Tag archives'
NEST_TAG_HEAD_DESCRIPTION = u'Tag archives'
NEST_TAG_HEADER_TITLE = u'Tag'
NEST_TAG_HEADER_SUBTITLE = u'Tag archives'
# tags.html
NEST_TAGS_HEAD_TITLE = u'Tags'
NEST_TAGS_HEAD_DESCRIPTION = u'Tags List'
NEST_TAGS_HEADER_TITLE = u'Tags'
NEST_TAGS_HEADER_SUBTITLE = u'Tags List'
NEST_TAGS_CONTENT_TITLE = u'Tags List'
NEST_TAGS_CONTENT_LIST = u'tagged'
# Static files
STATIC_PATHS = ['images', 'extra/robots.txt', 'extra/favicon.ico', 'extra/logo.svg']
EXTRA_PATH_METADATA = {
'extra/robots.txt': {'path': 'robots.txt'},
'extra/favicon.ico': {'path': 'favicon.ico'},
'extra/logo.svg': {'path': 'logo.svg'}
}
```
## Third-party assets
The theme uses external softwares, scripts, libraries and artworks:
* [Bootstrap](http://getbootstrap.com/) 3.x.x
* [Open Sans Font](http://www.google.com/fonts/specimen/Open+Sans)
Host with `pelican content` and `make devserver`
Default port is 8000.

@ -0,0 +1,11 @@
# Get to the right location
sudo lxc-attach -n spacekookie
cd /var/www/website
# Update the data
git pull
# Re-generate
rm -rf output/
. env/bin/activate
pelican content/

@ -0,0 +1,14 @@
Title: An open source GPU
Category: Blog
Tags: OpenMPU, matrices, opengl, hardware
For as long as I can remember I've wanted to build my own computer. Sorta from scratch.
And there is something I want to do even more: build a GPU. Something that can process vectors and matrecies in an efficient manner, build a graphics rendering pipeline in hardware. Sorta from scratch.
And that's what this project is about. OpenMCU stands for "Open Matrix Computation Unit" and will be a part of the OpenGPU (working title).
## The basic architecture
`<insert picture>`

@ -0,0 +1,57 @@
Title: 01. Omnitool - Introduction
Slug: 01-omnitool-introduction
Category: Blog
Tags: Dev Diary, Hardware
Date: 17-09-2015 15:45
Status: published
Illustration: omnitool_background2.jpg
Any good fan of the game, book, comic, stuff series will now jump up and down in excitement. The omnitool is a constant companion, helper and friend for Commander Shepard and a life saver in several situations. Whether it be hacking doors, turning into a plasma blade and cutting peoples faces open or just plain transferring a bribe credit to the slimy Vorcha in front of you.
But please, settle down, I haven't invented holographic technology. Nor have I invented plasma tubings or even solved the financial crisis by coming up with a perfect currency (of couse generically called 'credits') that everybody wants to use.
### Then why waste your time
That's a good question :) I would hope that this series doesn't turn into a waste of time for anyone. Because...well, while I haven't done any of those things. I am planning on building an omnitool. Just a bit more low-tech.
I was actually inspired by something on Adafruit, called the Flora. It's a round gimmick with a ring of RGB LED's, GPS (I think) and an arduino to program it.
![Adafruit Flora](/images/flora_pinout.png "Adafruit Flora")
I was only really inspired to do this project when a friend of mine showed off his Flora on the CCCamp2015.
He did some minor modifications to it, including a wristband (IDE cable) and a battery on the underside and programmed a few modes for displaying time (as an analogue clock) and a flashlight by just dialing the LED's up to full power.
![Adafruit Flora 2](/images/flora_withleds.jpg "Adafruit Flora2")
And that's kinda what gave me the idea for an omnitool. The idea of circular rings of LED's as display elements are pretty cool.
### Basic concept
So the basic conceptis a simple. Create a wrist accessory with one or two LED rings (using shift register RGP LED's to display patterns, colours and different brightness settings), include a generic SOC to program, probably something single core ARM. Give it a bunch of RAM to run applications and a embedded systems linux.
Include GPS, blutooth, a sensor package such as temperature, preasure, accelerometer, etc.
Include extention slots where, with a simple click, the tool can be expanded to include speakers, a microphone, a bigger screen, a bigger battery, etc.
And all this in the form factor of the so beloved omnitool from Mass Effect.
I know this is a bit of a crazy project. And it will take months, if not years to complete.
Because this is the thing: I want to do it all as custom cut PCB and maybe some custom cut plastic for casings.
I've been getting into KiCad recently, with my first project the Christmas Bauble ([Click here for details](/dev-diary/jolly-christmas-decoration/)) and have fallen in love with the tool – Don't worry Ashley, not *that* much :)
But it is pretty awesome and I urge everybody who wants to get into that sort of electronics stuff to checkout it out! [KiCad](http://www.kicad-pcb.com)
### What to expect
So what will this series be? (Hopefully) regular status reports about what I've been doing, writing about my experimences with the project, letting you guys know what I'm learning and generally just let people follow the project.
All stuff about the project will be in a Github repo. From the KiCad files to the C firmware I'll have to write. Everything you would potentially need to make your own, study it and learn from it is in there.
**[Omnitool Repository](https://github.com/spacekookie/omnitool)**
I hope that you follow along. And I'm looking forwards to comments from all of you. Have a lovely day and read you soon.
~Kate

@ -0,0 +1,33 @@
Title: Jolly Christmas Decoration
Category: Blog
Date: 2015-09-17 15:30
Tags: Dev Diary, Hardware
Christmas is getting closer (not really but let's just roll with it) and I wanted to learn [KiCad](www.kicad-pcb.com) a software that let's you create circuits and design PCB for manufacture.
I found a tutorial series online by a guy named [Ashley Mills](https://www.youtube.com/channel/UCaBNA-lmg35Wfx2eh2oDkWg) (with quite a legendary beard) who showed off a simple circuit using a 555-timer, a shift register and an XOR gate made from NPN transistors and resistors to display and repeat a pattern on several LED's.
The series focused on getting to know KiCad and all it's features. And while I did that in the first revision of my board, I've diverged from it since. I can however recommend his videos on KiCad to anyone who wants to dive into PCB design, has no clue about the software and could use a little chuckle while also learning some really awesome software (youtube channel link above).
### My Christmas Bauble
So this is what I've got.
![Kookies Christmas Bauble](/images/christmas_bauble_pcb.png "Kookies Christmas Bauble")
As you can see it's a round PCB with simple 5mm LED's around the edges. It no longer uses NPN transistors but rather a single SMD XOR gate. Much easier to wire up, cheaper and less prone to errors as well.
In general I've switched the entire design over to primarily use SMD components as they're smaller and more elegant. And it theoretically allowed me to get the footprint of the board down to something that isn't too excruciatingly expensive to produce.
It took me two more revisions to get the board to a state where it's not too complex and actually fit on a single layer (!) with no vias except for the holes for the LED's obviously.
It uses a round cell battery on the back of the board to hide it away and has a hole at the top to actually hang off a christmas tree. Theoretically the battery should lasta few days, so maybe have a few spare ones around in the christmas season.
### What now?
I haven't manufactured this yet. I am still thinking about refining the design slightly. I have the **entire** back to work with and add things. I was thinking about adding a simple bluetooth chip so that patterns could be pushed to the device via an android app. But that's the future. For now it should actually be functional and maybe I'll order some `Revision 3` boards just to see that everything worked.
Here is a dynamic render from KiCad as well.
![Kookies Christmas Bauble Rendered](/images/christmas_bauble_render.png "Kookies Christmas Bauble Rendered")
And be sure to checkout my Github repo for the project if you want the KiCad files. Either to play around with them or to manufacture some baubles yourself. If you do, I'd be interested in pictures of the decorations on your christmas trees so I can add them to this article as a slideshow :)

@ -0,0 +1,38 @@
Title: [Update] Jolly Christmas Decoration
Category: Blog
Date: 2015-11-27 15:30
Tags: Dev Diary, Hardware
You might remember I played around with Kicad a few months ago and made this [tacky little thing](/hardware/jolly-christmas-decoration/). Just about 2 1/2 weeks ago I went onto [DirtyPCB](http://dirtypcbs.com/) to get them actually made. I wanted to have gone through the production process and get something built before I started doing more complicated projects.
Unfortunately I discovered a little mistake with the design in the layout that ended up at the manufacturer (Rev 3.1). I tried to fix them but Rev 3.2 didn't make it in time, which means my boards will be a bit more complicated to power. However not too complicated as the power-in are just throughholes so I can actually strap anything behind it to power it.
But without further a due, here is the result from DirtyPCB (which I am actually quite impressed with).
![PCB with Banana for Scale](/images/christmas_bauble_pcb.jpg)
Now, I'm new to all of this so I started doing beep-tests on the pads to make sure things were properly connected and all the boards passed them. The production quality is pretty good. Unfortunately I can't start assembling them yet just because none of the parts I ordered for them have arrived yet. The manufacture and shipping of the boards actually beat the shipping of off-the-shelf parts!
Anyways, I'm kinda excited. First time making an electronics project. I might post another update on when the parts arive and post a few gifs of the finished products. If I don't I'll probably tweet about it though.
Now, I have another smaller electronics project in the making where I am, again, waiting for parts to arrive to do some testing. And already designing a modular PCB board. (Limited a bit with the 10x10cm limitations on DirtyPCB I need to design my project in a way that I can take a bunch of smaller panels and stick them together into a large one, which would take hundreds of dollars to make elsewhere).
[But realistically for the production quality I saw with these, I'd be happy to give them my money again for future projects. Especially at that price, just unbeatable.](https://www.youtube.com/watch?v=d36wUmJGzvA)
:)
Anyways, enough ramblings. Read you later.
### Update...update
Right...so after tinkering with the bauble a bit I found out a few things. The most important one being that I made some mistakes. Some big ones :)
- Pin 9 of the shift register was connected to both input A and input B of the XOR gate. Which meant that both inputs were always the same...which also meant that the output was always 0.
- The 555-timer clock ran at several hundred kilohertz. I had to change the capacitor down to ~12µF and the resistors to ~4.7 ohms.
- The coin-cell battery didn't have enough juice to run it. Two had to be put in parallel. Even then, two batteries would not be able to run for very long.
To make the bauble work I bridget the xor gate completely, so just feeding back the shift register end to the beginning.
In addition to those things some of the LED's sometimes didn't work. I'm not sure if that is due to broken shift registers, traces or LEDs. All in all I do consider it to have tought me quite a lot about electronics, going through the process of producing a PCB and debugging electronics once it arrived and inevidably goes wrong :)
I am currently in the process of redesigning the entire circuite from scratch. And making it easier to solder. I want to make it into a beginner soldering kit that people can both learn how to solder with and also have something to hang off their christmas tree in the jolly season.

@ -0,0 +1,21 @@
Title: WS2812b LED breakouts
Category: Blog
Date: 2016-03-16 12:08
Tags: Dev Diary, Hardware
You all know I have a fetish for [ws2812b RGB-LEDs](http://rgb-123.com/wp-content/uploads/2013/08/PinLayout.jpg). I admit that. They're just awesome. And recently I've found myself wanting to do some projects with them (*cough* programmable alarm clock *cough*). But I dislike the strips, although they're pretty cheap they are usually just very messy and horrible. And making a PCB for every project can be weird. Especially if gigantic PCBs would be required.
So I designed this little doodad.
![ws2812b Single Mount](/images/ws_2812b_single.png ws2812b Single Mount)
The idea is the following: Sometimes you just need a few ws2812b (I'm saying that word too often in this post) somewhere. But you don't want to lay a strip. Or make a big PCB for it.
So here is an alternative. Easily make ~800 of these for 25$, screw them to a surface, connect **PRETTY** wires between them, such as [Ribbon cables](http://cdn.usdigital.com/assets/images/galleries/ca-c10-f-c10_0.jpg) and boom. You're done.
### One to rule many
Now...I mentioned that programmable alarm clock earlier. And while I'm not quite done designing what will go into it all, I do know that I want to have a ~ 21x9 Pixel display, each individually addressable. And instead of building a way too big PCB that will be insanely expensive to manufacture...why not split them up? Then I have these "tiles" of LEDs that I screw to a backplate, wire everything together and from the outside you can't tell the difference.
With 21:9 (Aspect ratio and pixels) in mind, this is my prototype:
<TO BE CONTINUED>

@ -0,0 +1,51 @@
Title: Open Plantb0t - Rev A
Category: Blog
Date: 2016-03-16 12:08
Tags: Dev Diary, Hardware
Illustration: banners/plantb0t_revA.png
Howdy everybody,
Spring is coming in Berlin and thus my thoughts - as every year - are with plants. And growing shit. I live in an appartment with a tiny tiny balcony so I don't have much space but that has never stopped me from wanting to cram as many plants into the space as possible to the point of starting nuclear fusion.
In addition to that I have a few house-plants and very water-sensitive trees in my appartment. My current approach is to go around with a jug of water every couple of days and water them individually - making sure the soil has a certain moisture and doesn't exceed a certain limit - but I've always had the dream of being able to automate away as much as possible. That's where the idea of `Plantb0t` started. And I want to tell you a little bit about it.
The basic idea is to have a little controller in each plant-pot that measure the moisture of the soil and reports that back to me via an ESP-12 SOM (System on a Module). The ESP has WiFi capabilities and would log to an MQTT server on my home media server. This way (when I'm at home - none of that IoT shit) I can see how my plans are doing.
### Current state
So that's what Revision A of Plantb0t is. I also added a second sensor slot which is meant to be populated by a temperature sensor but could theoretically house a second moisture sensor. In the end the probes are only sticks in the ground that have a resistance between them.
Here is a dynamic render of the board (that went into prototype production on the 29th of march, 2016).
![Plantb0t Rev A](/images/plantb0t_RevA_front.png Plantb0t Revision A)
As you can see it's powered by an ESP-12 and comes with it's own programmer (The lovely CP2102) and micro-USB header. The USB-Port is currently the only way to power the board.
In the future it is planned to bypass the USB power and only use it for the programmer and otherwise drive everything off an externla powerboard which provides 3.3V for the Plantb0t.
In the bottom you see two constant current sources that can power two analogue sensors that get multiplexed into the ADC of the ESP-12.
GPIO pin headers are included for external gismoz such as a pump to act on the moisture data as well as screwholes to mount the whole thing in a 3D printed case.
In total the board is only 5x5cm big!
### Future plans
A few things I want to realise with this project in the next coming weeks:
- Primarily the Rev A board needs to be tested to make sure that the programmer works
- Figure out a good way to calibrate the sensors. Maybe drive a button via GPIO?
- Design a power board that generates 3.3V for the board (but not the programmer!) from a solar panel and a battery to decouple the entire sensor-board from all power-sockets.
For the next revision of the board (Rev B) I want to include more sensor slots. Maybe work on the part spacing a bit and increase footprint sizes. It should be easier to solder and someof the parts are ridiculously small. I mean...I have the whole back to work with?
I also have some crazy ideas for a "Plantb0t+" Version with even MOAR SENSORS (Including a pH-value sensor!). But that's all faaaaar in the future.
Either way...I'm excited for my boards to get here (hopefully in the next 7-8 days) as well as all the parts I need for the prototypes.
I leave you with a screenshot from KiCad where you get to see under the hood of the board. Cheers o/
![Plantb0t Rev A](/images/plantb0t_RevA_naked.png Plantb0t)
(The project has a [Github](https://github.com/spacekookie/open_plantb0t) repo where I will try to populate the wiki with as much info as possible)

@ -0,0 +1,89 @@
Title: Static sites vs Wordpress
Category: Blog
Date: 2015-08-14 20:59
Tags: Dev Diary, Meta
Regular readers will notice slight differences in my blog from the last time they were here. A lot has changed in the last two years since I started this website. Back then I decided to use Wordpress to host the stuff I wanted to write about because it offered lots of plugins and an easy to use CMS + editor to write articles. But over time I noticed that wordpress, while nice, can be more trouble than it's worth.
So for the last couple of months I've had a look at different web frameworks. Django, Ruby on Rails and some static site generators like Nikola and now Pelican. The last one is now powering this website.
The advantages of a static site generator is significantly less server load, simpler design and less overhead with updates and security issues. With no database to hold any kind of data and only static `html` documents being generated at "compile time" and dealt via a very simple html server using exploits or manipulating the website to gain access to my server is almost impossible.
So...while you can read a lot about why static site generators are cool and what their limitations are, I wanted to use this article to write a little bit about the challenges that I had to deal with porting my old website to a new framework. Because I didn't want to start from scratch. I wanted to keep all my stuff.
### Creating basic site layout.
Most of my website are blog posts of different categories and streams. For example, I had one page that displayed all blog posts while I then had other pages that displayed only certain categories. Most static site generators don't really support that. On Pelican I am now using one category for Blogs (Blog) and then have other categories displayed on pages that I statically link in my config:
```python
MENUITEMS = (
('Home', '/'),
('About Me', '/about-me/'),
('Blog', '/blog/'),
('Projects', '/projects/'),
('LibGDX', '/libgdx-game-of-codes/'),
('Linux', '/linux/'),
('Teaching', '/teaching/')
)
```
So essentially the menu items link to the category pages that then display articles. By default these pages only displayed a list of posts so I had to modify the category template in my theme. But more about that later.
Right now I still don't have a work-around for having different categories on the "Blog" page. But my current idea is to not link to a category page but rather a "tag" page. Then give every article that should show up on that page the "blog" tag (or use some voodoo setting that automatically adds tags to articles).
To get pretty links you can set some options to save pages and posts under different URLs in the config:
```pytho
nARTICLE_URL = '{category}/{slug}'
ARTICLE_SAVE_AS = '{category}/{slug}/index.html'
PAGE_URL = '{slug}'
PAGE_SAVE_AS = '{slug}/index.html'
CATEGORY_URL = '{slug}'
CATEGORY_SAVE_AS = '{slug}/index.html'
```
### Theming with [Pelican Themes](http://www.pelicanthemes.com)
Obviously a website should be something personal. And on my old wordpress site I spent several weeks tweaking the Wordpress Theme to my liking. Static site generators like Nikola or Pelican do offer theming where people much better at writing CSS and html put together something nice. I would recommend cloning a template that you want to use (most of them are on Github) and then modifying it however you like. For example, my template and the modifications I'm making on it can be found here: [github.com/spacekookie/nest](https://github.com/SpaceKookie/nest).
The first thing I did was tweak the dynamic content filling a bit. I mentioned earlier that I had to modify some stuff to make sure that I didn't just get a list of entries in my blog page but rather either the content or a summary of the page. With a little plugin called "summary" that becomes even nicer but I'm getting ahead of myself.
```html
{% for article in articles %}
<dt>{{ article.locale_date}}</dt>
<dd>
<a href="{{ SITEURL }}/{{ article.url }}"><h2>{{ article.title }}</h2></a>
<p>{{ article.summary }}</p>
</dd>
{% endfor %}
```
As you can see you can embed data from your pelican site into HTML via curly braces, aka Jinja. So the above snippet is obviously a loop that takes an article from articles (which is provided by Pelican in my case) and then renders a "h2" link to the article with the title (`article.title`) and then adds the `article.summary`.
If you wanted to display the entire content of the post it's as trivial as changing the summary to article.content. That's the beauty of Jinja: it's ridiculously easy :)
### Next up
Another thing you might wanna have a look at is the static/css folder of your theme. In the one I use there is a `nest.css` file that contains a lot of modifications to the underlying bootstrap theme. Including changing paddings, colours as well as overriding headers to not have these weird dashes (that look pretty cool for some parts. But not so cool for others).
But that's all details then. Other things you might want to consider if you move your Wordpress blog to a static site generator is that Wordpress sets up a lot of metadata that then ends up in your Markdown files (if you choose Markdown). Which means that you might want to go through all your articles cleaning out unwanted metadata that might just screw things up.
I'm using Sublime Text for the multi-cursor/ multi-file edits and regex searching which made editing my article metadata less of a pain in the bum.
As for this site: I still have a lot of things to work out. For example I still don't have a projects page. Markdown is nice for writing articles but I'm thinking about adding Restructured Text (`.rst`) files for static pages. It's a lot more powerful but also more annoying to write.
**-EDIT-**
A quick insertion a few weeks after having created but not yet published this site.
Alternatively, something I've now started using for my front page is a dedicated template for certain pages. You can set a template via `Template: <template_name>` into a files metadata. Then create a corresponsing `<template_name>.html` in your themes template folder.
That way I can have special settings for certain pages without having to work with embedded if statements in a sinle html template.
**-EDIT-**
But for today that shall be it. I hope you like my new website. Enjoy the new comment system as well (which I just moved to Disqus because that's pretty cool). Until another day.
~ Kate

@ -0,0 +1,45 @@
Title: Lonely Robot and the future
Category: Blog
Date: 2015-08-25 15:30
Tags: Dev Diary, Lonely Robot
Hey everybody, long time no read.
As I returned from vacation on the Chaos Communication Camp 2015 (Not sure if I'll post more about that) and probably starting a new job next week (*pssst* not sure if I should talk about it ;) ) the rest of my summer is still ahead of me and I'm booming with ideas and inspiration to do stuff.
I've started more intensively coding on the `newdawn` branch of Reedb, the C port of the database and planning some features for the old codebase via the `backports` branch. Because the new codebase will use a different crypto backend (from OpenSSL to gnu_crypt) a migration agent will be neccesary to migrate between 0.11.x to 0.12+ vaults. But as very few people currently use Reedb and most setups are for testing purposes only that isn't a very big priority right now. Depends on how the current version of reedb develops :)
But that's talk for another day. What else has been going on? After the Chaos Communication Camp 2015 I've been playing around a bit with my rad1o badge.
![Rad1o Badge](/images/rad1o_badge.png "Rad1o Badge")
But not much has resulted from that yet. The distribution I'm using (Fedora 22) at this time unfortunately has a broken arm-gcc package which means that a linker for embedded systems isn't working properly. So hacking on that will have to wait a little bit. But I will very likely post more stuff about that in the future.
Now, what was this post supposed to be about? Not Reedb. Or my new job. Or the Rad1o Badge or even the cccamp. It's supposed to be about a new software studio I created.
### Lonely Robot
So far we have a website at [lonelyrobot.io](https://www.lonelyrobot.io), an issue tracker at [bugs.lonelyrobot.io](https://bugs.lonelyrobot.io) and are expanding our web prescence but mostly working on projects.
Two things that we currently have going on are an Android game called **Graviton** (which started out as a tech demo that got out of hand) and, more exciting, LRGE, the `Lonely Robot Game Engine`.
The whole thing got started between my boyfriend and me who wanted to make video games together. And after a few months of day-dreaming, talking about ideas late at night and bitching about the current state of the gaming industry. But only after a few months of talking we actually started doing something.
Over the last couple of months we've been working with the LibGDX framework, making some minior and other major modifications to it and writing the specification for an engine.
We decided to use C++ for it and build it on top of SDL (the Simple DirectMedia Layer) with a very modular design which will allow for modules to be swapped in and out.
While we are still early in the planning phase of the engine it is what we want to focus our efforts on for the next couple of months, possibly the next year.
While we do make (free) software most of our ideas are for games. Our vision is that with this game engine we will be in a position where we can create them.
We decided to go for a self-written engine over something like Unreal or Unity because of a multitude of reasons. One of which is that neither of us are very great at blackbox development (that is the development of systems with another system that the developer doesn't fully understand). It is a problem I've always had with game modding but have also run into when playing around with the Unreal Development Kit.
Even with LibGDX I've always wanted to understand the inner workings of the framework which in the end lead me to modifying large chunks of it.
So that's that. I wanted to write about it here but will probably move other thoughts about the studio to my Lonely Robot dev blog on [lonelyrobot.io](https://www.lonelyrobot.io/blog).
That'll be it for now. I have an idea for a different project brewing in my head but I don't want to talk about it for now. All you should know now is: `hardware` :D
Until another day,
Kate

@ -0,0 +1,53 @@
Title: All aboard, it's a C port
Category: Blog
Date: 2015-10-21 18:02
Tags: Dev Diary, Reedb
It's been a long time coming. This blog post, not what I am writing about. Though...what I am writing about has also been a long time coming. So in a way, yes, I guess I was right.
### Anyways.
Over a year ago I switched to Linux. I was a Mac fangirl before. I loved the ecosystem, the OS, loved the convenience and the idea of having a system that just *worked* and the power of a root terminal.
But something changed. The garden of bliss grew smaller and smaller and as I realised that I didn't own or understand my computer, that Apple was in charge of what icons I used on my Desktop, I was drawn towards Linux.
I had used the OS on servers before and even my gaming computer ran Ubuntu to play the 64bit variant of *Kerbal Space Program*. But that last step...that took a bit longer.
One of the issues I was faced with was compatibility of software. And while most of the things I used (Eclipse, Sublime Text, Spotify, etc.) were also available on Linux, one thing wasn't: my password manager.
I shall not name it by name because I don't want to advertise a product I no longer want to use. But my password manager was a problem.
So just over a year ago I set out to write my own password manager. > How hard could it be < I remember myself saying. Oh could I have been more wrong? Probably. But it wasn't easy.
### The Origin
Back in the day (and I know it's silly because it's only been a year. But still - a lot of things have changed since then) I knew Java, some Python and wanted to learn Ruby. My brother told me about a mobile framework with which I could easily make a mobile version of the password manager and I was convinced:
I wanted to write it in Ruby.
7 months of development, feedback, discussions in a variety of hackerspaces with an even larger variety of people later - Reedb 0.10, the first usable version of what was once a password manager and had migrated into something bigger, something much cooler than I ever thought it would be: a database.
And as I added more and more features and this database became more and more intelligent I suffered from the limits of Ruby. Speed was terrible, packaging was practically impossible and it became obvious to me that Ruby was a language for the web (not because of the language. But rather because of the people that used it. The rails hipsters and web devs).
After mucking around with it for at least a month, trying several build systems and desperately trying to get this application to work I had enough. I wanted to port it.
Only around 3000 lines of code it wouldn't be too difficult to port Reedb into a different langauge. After all, most of the work had gone into the design process, not the actual coding. And while I wrestled with myself and tried a variety of languages, in the end I settled for C.
With it came a wave of problems. Conventient datastructures that just existed in Ruby such as the Hash (`{}`) or dynamic types made it easy to prototype something and quickly work with large amounts of data. All of that was different in C. And it took me a few months to really start to understand the C ways.
In the end I made a breakthrough with the design process when I finally discovered unions. And it's been a few weeks since. For now the C port of the project lives on the `newdawn` branch of the [github repo](https://github.com/reepass/reedb/tree/newdawn). The issue tracking has since been migrated to the [Lonely Robot Redmine](https://bugs.lonelyrobot.io/projects/reedb/issues) where you're welcome to fly by and check out the progress.
### The Future
I don't know how long it will take for me to finish this port. I'm making good progress, wind is in my favour. But there are still questions to be answered. Especially when it comes to the encryption of things.
But overall I'm happy with my descision. C is definately different. But it's a good kind of different where you can feel the control you have over your code. The performance is brilliant and a pure C binding makes integrating it into other languages or writing extentions for it as easy as pie.
I'll wrap this article up for now, it's gotten rather long. I hope that I can post updates about Reedb soon. Plus, I also have some other cool stuff lining up in the hardware section of my mad projects. I still want to do the Omnitool project and I'll definately keep that series alive. But it's a rather large undertaking. And I want to get some experience with smaller projects before I try to do something as mad as that. + it isn't exactly cheap to fuck up a prototype ;)
---
Anyways, I have to sail back into the C...
Kate
P.S. Sorry for the bad sailing puns. I promise there won't be any more, for shore.

@ -0,0 +1,59 @@
Title: Recovering a destroyed LUKs container
Category: Blog
Date: 2015-11-19 11:41
Tags: Dev Diary
So...funny thing happened to me the other day. And by funny I mean not funny. Actually I mean quite the oposite of funny. I booted my computer after a normal night of sleep (after I had actually shut down my laptop after several weeks of activity) and...nothing.
I stared at my plymouth boot screen while nothing prompted me to type in my passphrase to decrypt my harddrive and the first thought through my mind was:
> Fuck...I don't have backup.
### How to debug
Now...not to worry, after some time I was dropped into a recovery console where I could ask very simple questions like what kernel modules were present and what Systemd had been up to. And at first I thought the problem was clear: `Module failed to load: vboxdrv` and other messages populated my screen – all about VirtualBox kernel modules.
So the problem was clear. I had fucked up something when installing a new kernel or VirtualBox or anything else. So I blacklisted the modules and moved on...just...that it didn't. The problem persisted. Thinking that I had fucked something up when dealing with the GRUB config or the GRUB recovery console I got my trusty Fedora 22 live-USB out and booted off that.
### How not to panic
To the realise that my 256GB SSD was only 500MB full (which was rightfully detected as an `ext4` formatted volume. The rest of my drive was marked as `unpartitioned space`. \jawdrop.
Now...here is where things get and got interesting. But first let's have a look at my setup.
```
sda (the actual drive)
├── sda1 (ext4, mounted as /boot, contains my kernel)
└── sda2 (LUKS Encrypted Volume, contains subvolumes)
├── vc-root (RootFS)
├── vc-home (HomeFS)
└── vc-swap (guess c:)
```
So as you can see my boot drive is outside the LUKS container and unencrypted which was why I even got the chance to enter a recovery console. The rest of my system is encrypted. And seeing that only sda1 was being picked up it meant that the partition table on my disk must have had been destroyed to the point that it no longer knew sda2.
Knowing this didn't help very much though and it took me a few hours to fix this.
### Restoring the Partition Table
So the main problem was that my partition table was broken. I don't want to start speculating as to why this happened. Maybe my SSD just lost a few blocks, maybe it was bombarded by solar radiation or maybe (just maybe) I was obducted by aliens in the night, refused to give out my master passphrase in my sleep and because of frustration of not being able to get to my data they deleted some junks from my partition table just to spite me.
Either way, a combination of two applications saved my life and hopefully will save yours.
`testdisk` and `cfdisk`
At first, make sure you have backups ;) And don't blame me if you fuck it up. Also you need to know EXACTLY what your layout is to restore this. Otherwise BAD THINGS WILL HAPPEN *waves hand around warning-ly*
Run `testdisk` on your drive, enter through the screens, let it do a deep search and just say yes to everything it wants to do. This restored the LUKS header for me again at which point my computer at least started seeing the encryption container again. Didn't mean I could log in because keyfiles couldn't be found (they're not in the header apparently).
After that, I ran `cfdisk`. What this program does (or can do) is rebuild your partition table. After letting testdisk have it's go it found my LUKS header and completely destroyed my ext4 bootpartition. So in my case this is what it looked like.
![cfdisk before it saved us](/images/cf_disk1.png "cfdisk before")
What you will want to do is hit NEW, select the correct size of your partitions. Depending on how running testdisk went for you it might have found different parititions, all of them or none. Please! For the love of god, make sure you get your sectors right. Becase if you don't it will seriously damage your system and might make it completely unusable.
In my caseit was easy, I filled in my boot partition, marked it as bootable and set it's type correctly, also fixed the type error where before sda2 was being picked up as an LVM and not a LUKS container (this is obviously from my running system). And this is what I ended up with.
![ ](/images/cf_disk.png "cfdisk after")
Make sure you write your changes, exit and reboot. And if you did everything right, you will have a working system again.
And that's that. I hope this article will be of use to someone at some point. And remember: make backups!
Cheers o/

@ -0,0 +1,91 @@
Title: Getting started with XMPP/ Jabber
Category: Blog
Date: 2015-11-24 12:14
Tags: Dev Diary
So after having spoken to a friend the other day and trying to get him to start using XMPP (aka as Jabber) instead of facebook messenger I realised that even while I thought it was trivial to set up other people might disagree with me. So here a little guide :)
Now...this isn't just a step-by-step instruction of what to do. In fact this article is more about getting you to understand XMPP than registered with a specific server. XMPP (formerly known as Jabber, just so you know why some people use the terms interchangably) is a chat protocol, not a chat service. It is based on XML and was originally created for near instantanious message delivery (chats). However since then it has been extended to also be able to VoIP and video (more or less good, that all depends on your client).
So XMPP is a protocol that anyone can just use. However...when I say "get started with XMPP" I don't mean set up your own servers and chat system. I mean Jabber, which is still the name of a chat service.
### A network instead of a server
The current open Jabber infrastructure is built around a bunch of servers (actually quite a **lot** of servers) that can communicate with each other. While inside the network it doesn't matter what server someone is registered with. As long as both people are part of the network they can chat with each other. And that's that. (Cryptographically and version wise it becomes a bit more complicated than that. But for the end user, that's what it boils down to).
There is a list of servers in the Jabber network (also called directory) available [here](https://xmpp.net/directory.php). As you can see there are quite a few servers out there that will allow you to register. Now...when picking a server please make note of a few things.
- Check the software has had updates in at least the last year. You don't want to trust your private chats to outdated software, especially because that will usually mean that the server admin can't be bothered to update to newer versions of plugins and protocols.
- Check that the server passes both "Server to Server" and "Client to Client" security tests. (Both in the green).
- You like the domain. You don't want to have a domain "@kinkymotherfucker.com" if you don't like it :D
### Register with a server
So let's asume you've found a server you like. Scolling through the list I would probably register at [blah.im](https://blah.im). Note that you will have to import an SSL certificate. You will have to if you don't have the CA [Cert Root certificate installed](https://www.google.com/search?q=What+is+CA+Cert&ie=utf-8&oe=utf-8#q=What+is+CACert).
But you will also notice that the server doesn't actually have anything on it's website. To register on servers in a lot of cases you will need a jabber client to do it for you. I am using Pidgin and will thus also demonstrate it with that client. Pidgin is free open source software and runs on almost any platform. But feel free to use a different client if you find one you like more. The features should all just be transferable.
To install Pidgin please go to their website and follow download and installation instructions for your platform. For mine (Fedora) it's as simple as typing `dnf install pidgin`. I will assume you managed to install it and we
move on :)
In Pidgin navigate to accounts and Manage your accounts.
![Pidgin Manage Accounts](/images/jabber/pidgin1.png "Manage accounts")
In the opening window click on **add** and then select XMPP from the list of possible accounts to add.
Fill in your desired username, the server you want to register with and a passphrase. You can leave the resource blank. Also make sure you tick the box "Create this new Account on the Server".
Servers provide different ways to register. Some just have a registration webpage, some have an API that pidgin can talk to. Some make pidgin open a browser window and guide you to their registration site. This is something unique to the server you choose to register on.
In the case of the *blah.im* server pidgin opens a new website where I can register my nickname (which I will not do because I already have an account I like to use). Check your input with the example picture below.
![Creating new Account](/images/jabber/pidgin2.png "Create new account")
And that's that. You should be registered and ready to log in and chat with other people who also use Jabber/ XMPP, no matter what server they're on.
### Encryption via Jabber (OTR)
Jabber by itself can be secured via SSL and several transport layer security measures but that makes it no more secure than any other service. The server provider can still read all messages and log them without you ever knowing it.
Because of that a lot of people use separate encryption with Jabber called "Off the Record", short "OTR".
What OTR does is encrypt messages on your computer, sends them to your friend and then locally on their computer decrypts them again. This has however two drawbacks.
1. Both you and your friend need to be online to chat with each other over OTR. You can't send them an offline message and let the server cache it until they come back online to read it.
2. OTR does not support multiple devices. That means you can't start chatting on your PC, have to leave and pick up the conversation on your phone. You will need to start a new conversation. And a lot of mobile clients don't properly support OTR because they shut down the session when you lock your screen.
To address both these issues there is a new crypto protocol called "Axolotl" which fixes both of these issues. Axolotl is however a generic protocol and can be used with literally anything. To adapt it to XMPP and integrate it into the already existing infrastructure of servers there is a second protocol called "OMEMO" which implements Axolotl for XMPP. It is however still very new and *very* few clients support it at this time. In fact, the only Jabber client I know of is **Conversations** on Android.
But let's assume the downsides of OTR don't bother you (they don't bother most people). How would you go about using it? OTR in Pidgin is a plugin that needs to be enabled. Depending on what platform you install it to you might have to install the plugin yourself which can be more or less work. (On Fedora it's just `dnf install pidgin-otr`)
But [you can figure that out yourself, I hope.](http://lmgtfy.com/?q=Install+Pidgin+OTR+plugin).
*Waits for you to install the plugin*
Good, now what needs to happen. First you need to active the plugin and generate yourself a key. Go to **Tools** and then **Plugins**, search for the OTR plugin and enable it. Then go to it's configuration page.
<img class="dual" src="/images/jabber/pidgin3.png" align="left"><img class="dual" src="/images/jabber/pidgin4.png" align="right">
You will need to generate a key. A key in this case means a private key, if you're already somewhat familiar with cryptographic concepts. It's a key that is unique to you, should be protected, private and *never* shared with anyone. It is thus called your **private key**.
When clicking the button to generate a key Pidgin will make one for you and save it somewhere on your filesystem. It allows you to encrypt and decrypt data (chats, files, etc.) that people send to you.
Afterwards a key fingerprint will show up and the generate button will be greyed out.
A key fingerprint is sort of a signature. It can identify you as you. So if someone sees your fingerprint they can be sure they're talking to the right person (if they've verified the fingerprint via another medium, e.g. meeting in person). But the fingerprint doesn't expose any secure information about your key.
You can also change some basic information about how OTR should work on your system. I won't go over these for now.
![OTR Configuration](/images/jabber/pidgin5.png "OTR Config")
And that's it. You're done. You can initiate new private conversations with people via the **OTR** submenu in the chat screen. And know that everything you say to the person in that session is secure. And here is the best thing: OTR provides something known as "forward secrecy". That means that if at some point someone steals your laptop or phone and you loose your private key that doesn't mean that, even if someone logged every single piece of encryted text going over the network between you and a certain person and has all the information needed to theoretically decrypt your messages, they can't!
Because while you chat with OTR the key continously changes. So if you ever loose your key, you don't have to worry about old chats becoming public or visible for others to see.
(As long as you don't log them in cleartext of course).
![Let's go off the record](/images/jabber/pidgin6.png "Let's go OTR")
#### Happy chattin'
~ Kate

@ -0,0 +1,127 @@
Title: Hacking on Reedb
Category: Blog
Date: 2016-03-14 10:43
Tags: Dev Diary, Reedb
So...it's been a while :) Exams are over, code has been written, bugs have been fixed, frustrations have been had. Terrible christmas gifts have been sold off on ebay and found a new owner with a misguided sense of style. I've also gone a bit mad with one of my other projects: The Christmas bauble. As you might recall it started as a harmless joke to learn KiCAD, ended up actually being manufactured (I never saw that bonus from dirtypcb for mentioning them a lot :c) and has now gone into planning phase for Revision B.
![Reedb Banner](/images/reedb_banner.png "Reedb Banner")
But more on that later. I'm back, in the spring with new energy and drive. To talk to you about Reedb (yet again).
With `0.12` coming closer and closer to being a reality I wanted to quickly draft up something how to interact with Reedb. The API is basically stable at this point and while the C-binding isn't quite done the C++ interface is ready to be used (and almost actually hooked up :) ).
### Initialising a context
Getting started with reedb requires a context which holds a bunch of information about what vaults exist, what tokens haven been scoped, users active, watchdogs, etc. etc.
In addition to that there are vault interfaces that get attached to a context that can then actually interact with vaults. This way different vaults can get handled by different interfaces that are completely separated from each other.
```C++
reedb *rdb = new reedb();
rdb->set_os(LINUX);
rdb->set_distro(SYSTEM_D);
rdb->set_verbose(true);
rdb->finalise();
```
The OS and sitro flags determine what configuration paths and formats are specified as well as how to launch reedb at system startup (if such a behaviour is wanted/ set up).
After defining all the parameters required or wanted to initialise the Reedb context call finalise to make it official and make the context usable. Before `finalise()` is called, trying to access other functions via the context will result in an error being thrown.
### Vault interfaces
So after having a Reedb context you have to register a vaults interface to it. Multiple interfaces can be registered and separated which means that certain vaults can be accessed that require different settings (for example a minimum passphrase length). Generally it just offers more flexibility to the developers.
```C++
rdb_vaults *v = new rdb_vaults();
rdb->register_vinterface(v);
vault_meta meta = v->create("fancy_vault", "~/Documents/", "MyD0gisnot!mypassword!"); // P.S. I don't have a dog :)
```
The create function will generate a key, encrypt the Master key with the provided passphrase and dump it to disk. In addition a folder structure and configuration is written. The config is mostly future proofing - none of the values are actually currently used. But it will hold information about zones, users and cipher modes in the future.
---
After creating a vault you still need to authenticate on it. The unencrypted key might still be held in RAM (in secure memory that is) but just because you created a vault doesn't automaticaly mean you have access to it. So after calling `create` you need to call:
```C++
// A token is malloced for you in secmem. Do not free it yourself. Let Reedb do it for you!
rdb_token *token = v->authenticate(meta.id, "MyD0gisnot!mypassword!");
```
You need the UUID from the interface we are addressing the vault via - we can find the UUID in the vault_meta we were handed during creation. Alternatively we can ask the vaults interface.
From the docs:
> A UUID is provided from the management wrapper and isn't stored in the vault itself. A vault doesn't care about its own ID, nor does it even know it has one.
>
> Do not try to hard-code UUIDs into your program as they might be non-persistent across runtimes.
Authentication only takes the ID and passphrase at the moment. However a user-auth function will be added in at least the next version. Both return a token that will be required for **every** operation that follows.
And that's it...you can now interact with your shiny new Reedb Vault :)
```C++
std::string file_id = "Reedb.org";
map<std::string*, std::string*> content();
content["Username"] = "Peter Pan";
content["Passphrase"] = "flower123";
/* Then take all that data and insert it */
v->insert(meta.id, token, &file_id, &content); // Takes the pointer to a content map to save memory during inserts.
```
As you can see you need a vault-id and a token to even be allowed to the next step. Then to insert a piece of data you need to give it a name. Reedb is object-oriented which means that every dataset has a name and is an "object" on the FS ( Blockdevice mode is in planning :) ). So from that day on your piece of data will be available if you query for "Reedb.org".
```C++
map<std::string*, file_meta*> data;
data = query_file(meta.id, token, "Reedb.org");
```
That will put a query return into your map. A query return isn't quite data. It's basically a name of a data-set mapped to it's head. A file head contains a bunch of metadata that isn't exactly deemed "important". Like it's name, a category, some tags and whatever else you might want to save in there.
In fact you can extend header fields at will.
```C++
map<std::string*, std::string*> meta_delta();
// ...
v->migrate_headers(&meta_delta);
```
From the docs (again):
> A meta_delta is the name of a meta-field that should be inserted mapped to its type in a std::map<?,?>.
> If a meta should be removed set the type to "-1".
>
> When removing meta fields from active vaults data needs to be migrated via rdb_meta_migr(...). Also be aware that removing active meta fields can cause terrible memory corruption. Be warned!
A file_meta is exactly that: a vault header. It can be further searched and filtered with RQL (Reedb Query Language) that we will not go into further in this blog post. Just know that it exists :)
*hint hint* `"$CATEGORY: [Social | Website | Online] $TAGS:[Private & Friends] $NAME: ~[Face]"` :)
Deleting, updating files and updating vaults is analogue to what we already saw. Basically you always keep your vault ID and token on you, then provide the interface with some data.
Some of the steps might seem a bit verbose but that's just so that the user (aka developer) gets maximum control over what she is doing with her code. It also allows for more precice error handling - narrowing down the source of the error further for the end-user.
### A tiny last thing
There are two interfaces for Reedb. A C++ and a C one. And you pick which one you want to use by either doing
```C++
#include<reedb/core.hpp>
```
or
```C
#include<reedb/core.h>
```
The C Interface is pretty much analogue to the C++ one (with obvious slight differences).
```C
vault_meta *meta;
rdb_vaults *vaults = rdb->create(&meta, ...);
```
That's it for today. I hope this article gave you a quick introduction to the native interface and makes you at least a little curious or excited to work with it :)

@ -0,0 +1,27 @@
Title: Winter update
Category: Blog
Tags: Dev Diary, Meta
Date: 2016-12-2 10:43
Howdy everybody!
As the year is winding down and we're all getting ready for the jump to take us out of what has (in my opinion) been a *very* shitty year, I looked at my blog and could only shake my head.
I had moved this over from Wordpress to Pelican and basically replicated all of the layouts to the extent that some of Pelicans own functionality had to be abused to make it work. But as I kept publishing things on here I realised that most of the features I had implemented went unused.
And so, for the last few days I have tweaked the layout (and design - as some might notice) to be a bit more traditional again.
I was also considering to change theme but after not finding anything I liked I decided to hack the fuck out of my current one instead. You can check out all of my horrible changes [here](https://github.com/spacekookie/nest).
I've also finally done some stuff that I've wanted to do for ages - such as pimping up the front page, adding a proper projects page and go through some of my old tutorial series, fix their formatting (yea right "perfect wordpress import...") and update them to newer API's of libraries. Some articles have just been dropped because I would have had to re-work their formatting and they were no longer relevant. Stuff will slowly be introduced again, with proper formatting :)
### Everything else
In the terms of literally everything except my blog: I'm looking forward to the **33C3**. I'll be joining with the c-base assembly. My first congress in almost a decade! Expect maybe an update from that. And maybe there might be some christmas hacking. It's always more fun to do silly RGB LED stuff if it ends up annoying people on the tree!
Also, with the blog now in a bit better shape I will try to keep a closer journal of what I'm doing. But hey...no promises, right? ;)
I shall leave you with this piece of relaxing GIF.
<img class="padded" src="http://i.imgur.com/KZquOZM.gif" align="center">

@ -0,0 +1,67 @@
Title: Post 33C3, what next?
Category: Blog
Tags: Dev Diary, Congress, CCC, Hamburg
Date: 2017-01-03 12:28
Howdy everybody,
I just came back from the annual hacker conference in Hamburg, Germany known as the "Chaos Communication Congress" (or CCC for short). It was the first time I was there for the entire venue and the first time I was able to go at all since *2008*. So yay!
It was a lot of fun and I have a lot of nice memories to hold onto now. I talked to a lot of interesting people, learned new things, got inspired to do new things and continue on old things.
More importantly, I loved the chance to get in touch with some other women in the tech industry (via Haecksen & Queer Feminist Geeks), talk about problems, attempt to come up with solutions and just generally rant about things :)
I also found out that I am in no way, shape or form a dancing person. Although electronic club music is fun!
## Some talks I went to
Following is a non-comprehensive list of the talks I went to. I am filling this from memory, so some talks might have been missed or dropped. And maybe I'll just edit them in later without anyone ever knowing.
<br/>
**[How Do I Crack Satellite and Cable Pay TV?](https://fahrplan.events.ccc.de/congress/2016/Fahrplan/events/8127.html)**
A really quite epic lecture about using glitching to extract keys from a very dated security layout. Not that anyone should do this (it's not worth doing it anyways...never anything good on) but it will teach you a lot of stuff about hardware security
**[Bootstraping a slightly more secure laptop](https://fahrplan.events.ccc.de/congress/2016/Fahrplan/events/8314.html)**
A talk about the flip-side of TAILS which aims to introduce trusted computing into a world where the machine can't be trusted. HEADS on the other hand uses coreboot and cleverness to create a verifiable machine environment to build an OS on top of. Made me want to get an old thinkpad on ebay to play with :)
**[The Nibbletronic](https://fahrplan.events.ccc.de/congress/2016/Fahrplan/events/7925.html)**
A relatively short talk about the creation of a musical instrument. Learning by doing and failing. Quite interesting for me as a hardware designer (as a hobbyist) but also a musician.
**[Shut Up and Take My Money!](https://fahrplan.events.ccc.de/congress/2016/Fahrplan/events/7969.html)**
If you have a bank account with N26...stop having a bank account with N26. Their security is absolutely horrible. And while, yes, all of these security issues have been fixed, it shows a rather lacking attitude towards security from their engineering team. Best demonstration of client-side security gone wrong. And why ReST APIs are fucking aweful!
**[Untrusting the CPU](https://fahrplan.events.ccc.de/congress/2016/Fahrplan/events/8014.html)**
This was a great talk given by a close friend of mine about one of his super crazy projects. The idea being to construct an FPGA powered PCI-E device for laptops and/ or desktop computers that intercepts messages to the display, encodes and decodes text into them to provide an interface for encrypted messages without using the CPU. It's really quite interesting and I can't wait to see what he does with it.
**[Making Technology Inclusive Through Papercraft and Sound](https://fahrplan.events.ccc.de/congress/2016/Fahrplan/events/7975.html)**
One of my favourite talks was about an engineering toy kit that was aiming to be more inclusive. The problem it attempts to tackle are the incredible low numbers of women in computer science and engineering (significantly lower than in other scientific fields). There are a lot of reasons why women aren't well represented in the fields and they are all cultural. This talk was about trying to change the culture around teaching people about electronics and code to be more inclusive towards groups of people (mostly girls/ women) who would otherwise be missed.
I really enjoyed the talk on a lot of different levels. One was the technical aspect of creating a childrens toy on the cheap that is inclusive and universally programmable through audio encoding. Quite worth a watch.
I don't think that just with projects like this the culture around women in tech will change. But it's a start. What we realistically need is a change in culture throughout all layers of society. I think the problems around women in tech are quite complicated. And unfortunately usually result in a bunch of assholes starting to shout either about how feminism is evil or how diversity isn't important. And biases aren't actually thaaaaat bad, right? */s*
I could rant here forever and it's questionable how many people would actually care :) I can recommend this talk. Let's leave it at that :)
**[The Moon and European Space Exploration](https://fahrplan.events.ccc.de/congress/2016/Fahrplan/events/8406.html) and [Interplanetary Colonization](https://fahrplan.events.ccc.de/congress/2016/Fahrplan/events/7942.html)**
Those were just the first two talks from a series of space talks. The first one was from one of the heads of ESA about their plans to colonise the moon for profit! And science of course... It was quite funny and definately worth watching.
The second one I almost liked more, though mostly the first part of it. Liz George manages to explain incredibly well in a very short amount of time what challenges exist when discovering exo-planets. The second part (by somebody else) is a bit more vague about how to actually get there and is less science, more fiction. But hey :P
## Going into 2017
So in short: 33C3 was pretty epic! And I honestly can't wait for next year. It's not clear yet where it will be held but it will be epic non-the-less. And who knows, maybe I have a talk to hold by then :)
Which brings me to this year. Last year was fucking shitty. Politically...On a personal level it actually went quite well. And I got a lot of shit done. I did Google Summer of Code, I made *huge* progress on my game project (yes, I will post about that at some point). And especially in the last months of the year, I redesigned and rerouted the Open Plantb0t board. On january 1st, 2017 the revision A2 design went into production.
I hope to get all my parts together soon and build up a second prototype series which (hopefully) works better than the last ;) I will keep y'all updated on that.
Until then, I hope you've had a happy new years eve and not an all too terrible year...yet ;)

@ -0,0 +1,116 @@
Title: LibGDX UI utility: Super UI
Category: Blog
Tags: Dev Diary, LibGDX, Game Dev, Lonely Robot
Date: 2017-01-24 00:14
**Let me tell you a factual statement**
*UI programming is terrible*
**Let me tell you an even more factual statement**
*UI programming in LibGDX is even more terrible*
I am a big fan of LibGDX. It's a really nifty library/ framework to get started with game development if you're more comfortable inside a code editor than a full blown game engine that is more targeted towards designers and artists. And I put my money where my mouth is: I have a series about LibGDX development for beginners on this blog and work almost exclusively with it when it comes to my own projects.
Yet, there is something that bothers me and there didn't seem to be a great solution to fix it. UI code structure. In this post I want to highlight a utility I have written for LibGDX which is very easily embeddable into your existing projects which will you help structure UI code more efficiently.
## The root problem
The reason I dislike UI programming with LibGDX is that it usually results in very long code files or passing dozens of parameters into sub-classes that are needed to update the UI for button presses, etc.
This goes so far that I have written an editor for game assets before just to realise that (once the development was complete) it had become completely unmaintainable and I had to start from scratch with better structure. It is incredibly easy to just throw out a UI design with Scene2D and LibGDX but unfortunately it is equally easy to produce very bad code which will turn into a big spaghetti mess.
Let's look at an example problem that I wanted to solve.
![LibGDX UI design problem](/images/libgdx_ui/01_base_problem.png)
Looking at this structure we have three main components that interact with each other. We have a class that handles UI logic (setting up actors in tables, adding listeners, etc), we have a window state which in the particular case which made me write an alternative was a "Lobby Handle" which coordinated what players were going to enter a match, the map, game mode and if everybody in the multiplayer match was set to "Ready". Lastly we have the actual network signal handlers that listen to TCP/ UDP packets and execute code to write/ read from the window state as well as update UI elements.
Implementing this structure with Scene2D and LibGDX will result in a lot of very ugly code. Because the network signals need to know everything about the UI (how it is structured, etc). And our window state can be written to by two different sources which means that we need to mutex it to avoid race conditions.
So, what was I trying to solve? First a bit of limitation of scope. Because a lot of UI problems have been solved over and over again and usually at the cost of runtime performance or with a *lot* of extra code.
1. UI code doesn't have to be embedded in a screen
2. All UI code can access the shared context of the screen
3. UI elements can update each other
4. Clean API that can be called on from anywhere (with a reference to the handle) that triggers range of functions.
So with that in mind, this is what I did.
```java
class MyUIHandle extands UIHandle {
public static enum UI implements UI_BASE {
PLAYER_LIST;
}
{ /** Initialiser block for new objects */
registerHandle(new PlayerList(), UI.PLAYER_LIST);
// ... more handles
}
@Override
public void initialise(Stage s, Object ... var) { ... }
public class PlayerList extends UIContainer {
@Override
public void initialise(Stage s) { ... }
// Define more API here ...
}
}
```
When we initialise a new `UIHandle` the initialiser block will create our `PlayerLists` and register them with the `UIHandle`. That code is hidden away from you. You can see that we're implementing a different enum type that we overload with values so that we can address submodules via a compile-time checkable value (such as enums). From inside (and outside) this class `UIContainer's` are available via `handle.get(UI.SUB_HANDLE)`. Obviously keeping your enum labels short will make your function calls snappier :)
The following graphic will sort-of explain the layout in more detail.
![Super UI fixing attempt](/images/libgdx_ui/02_ui_structure.png)
What you might also notice is that the `UIHandle` has an initialise function with variadic parameters while the `UIContainer` class only takes a stage. That is because window context is stored once in the `UIHandle` and then accessable from all `UIContainer` classes. This way we only need to do the inversion of control pattern once instead of for every sub-component.
You can keep the `UIContainer` classes outside this code-file. Then you might however want to provide a construct that does another inversion of control so that an external `UIContainer` can access the context provided via initialise!
```java
public class PlayerList extends UIContainer {
private MyUIHandle parent;
public PlayerList(MyUIHandle parent) { this.parent = parent; }
// ...
}
```
Now let's talk about that public API. In our original example we wanted to have networking code update some UI elements. And we want UI elements to update other UI elements. So first of all, we keep context in each `UIContainer` about what UI elements are accessable to it. So what we can do in every of our submodules is this:
```java
parent.get(UI.PLAYER_LIST).updatePlayers(playerList);
```
It also means that if we get new data from – say – a network socket or AI simulation, we can very easily update data in some random UI element.
```java
handle.get(UI.PLAYER_LIST).populate(playerList);
```
So all in all, we have solved the following problems:
1. We have access to all game state in the UI code without passing too many parameters into lots of sub-classes
2. UI code can be moved into lots of files for easier understandability
3. Context isn't duplicated
4. UI code can update other UI code without needing a direct reference to it.
The individual `UIContainer` instances are essentially independant of each other via dependency injection.
This library isn't done yet. Most of this is kinda hacked together to fit into **my** game. But I'm interested in making it more generic and putting it on Github. Especially because I can see myself using it again in the future.
Hope this might be useful to somebody out there. If you have questions, comments, hatemail...
[Twitter](https://twitter.com/spacekookie) or [E-Mail](mailto:kookie@spacekookie.de)

@ -0,0 +1,60 @@
Title: Dabbling with Moonscript
Category: Blog
Tags: Dev Diary, moonscript, programming
Date: 2017-05-06 11:55
![Lua means moon in portuguese](/images/lua_moon_banner.png)
Recently I've started learning/ using Moonscript. It's a language that compiles to [lua](https://www.lua.org/) and as such can run in the LuaJIT, an alternative lua engine which allows very easy and *fast* ffi calls into native code. This makes lua code capable of writing very performant applications and games that use native rendering, window creation or general libraries.
But in my opinion lua has always felt a bit cumbersome. I use awesomewm so I had to write it occasionally to customise my UI layout. And this is where Moonscript comes in. It's a lot of syntactic sugar on top of lua as well as some other concepts such as object orientation which lua just plain out doesn't have. And while yes, you can write good code without OO (*cough* **C** *cough*) it is a nice tool to have in your pocket, especially when writing GUI applications or games.
## The language
```Moonscript
class Thing
name: "unknown"
class Person extends Thing
say_name: => print "Hello, I am #{@name}!"
with Person!
.name = "MoonScript"
\say_name!
```
As you can see Moonscript is an indentation based language which (in my opinion) combines syntactic elements from lua and ruby together. In the snippet above (which is from the [moonscript website](http://moonscript.org/)) you can see classes, inheritance as well as the `with` keyword which allows you to initialise/ work with objects without typing it's variable name over and over again.
If you want to learn more about the language, I can only recommend you have a look at the [Moonscript in 15 minutes guide](https://github.com/leafo/moonscript/wiki/Learn-MoonScript-in-15-Minutes)
## How to use it
You can just write Moonscript files, add `#!/usr/bin/env moon` to them and get going. Obviously that's pretty cool for little scripts that you just want to get going. But not so great for larger applications because a) you don't have access to `ffi` via luaJIT and b) it adds additional startup cost.
So instead for my projects so far (which so far are a [game](https://github.com/spacekookie/dinodino) and a desktop app) I use a `Makefile` to build and run the Moonscript compiler and then execute the `init.lua` with luajit.
```Makefile
SOURCES := $(wildcard *.moon) $(wildcard **/*.moon)
LUAOUT := $(SOURCES:.moon=.lua)0
.PHONY: all run build
all: run
build: $(LUAOUT)
%.lua: %.moon
moonc $<
run: build
luajit init.lua
```
## Wrapping up
So...I'm kinda excited about this. Most of the code I write is either in C or Java (depending on what exactly I'm doing). And those two strongly typed and compiled languages have served me well and will continue to be my go-to solutions for a lot of problems.
But I've long been looking for a dynamicly typed, interpreted/ just-in-time compiled language that I can use for anything from little scripts to medium-sized desktop applications. I used to use python for this but have recently (over the last 6-9 months) fallen out of love and developed a rather passionate dislike of it and it's ecosystem.
My current project will get it's own little article at some point but I don't mind teasing the progress here. I'm writing a new UI for redshift which works with X11 linux backends and is heavily inspired by f.lux on MacOS. It's written in moonscript, with my own forked version of redshift (which I call [libredshift](https://github.com/spacekookie/libredshift)). It's on [github](https://github.com/spacekookie/redshift_ctrl) and licensed under MIT.
Hope I've made you a little curious about Moonscript. And stay tuned for updates on future projects with it :)

@ -0,0 +1,25 @@
Title: I got accepted to GSoC 2016
Category: Blog
Date: 2016-04-27 18:47
Tags: GSoC2016
![Acceptence Mail](/images/gsoc/00_acceptance.png "Acceptence Mail")
The title should be self explanatory about that one :)
But let me go back a little bit. A couple of weeks ago I sat in the basement of my local hackerspace talking to a friend about crypto when somebody joined the conversation, asking if I was a student and if I might be interested in Google Summer of Code.
After I looked up the project and familiarised myself with what had to be done, I thought it would be interesting to try to apply. And so I did. I wrote a long-ish proposal of what I wanted to do, how I would do it and when exactly I would acomplish my goals. (You can read my original proposal [here](https://storage.googleapis.com/summerofcode-prod.appspot.com/gsoc/core_project/doc/1458924075_GSOCProposal-KatharinaSabel.pdf?Expires=1461863360&GoogleAccessId=summerofcode-prod%40appspot.gserviceaccount.com&Signature=h0y5Nzi7llFNWKzt9%2BLGLvxcAPZ%2FaO7ni1ZyRDA3uFi6PD%2BDBmtIB6RJAr4Ulhv6fe64IFyB%2FI9iuVIYWIInYTmN7pZ9aUxw6TgxgFYguIywfcE2yUZ4o5UKb0PUbwI0Pu7o6mq%2BzSDXqlegpVOgujQ9k2QuTg1T1CqGzSi%2FnC4u6H0mB%2BxzWGGpoBC6rFwkKM1S70gE7hJ0EZpgYWr9H9zKPcwrfPtx99zqb488sH6STGYJf4tFrDRnnr57k2zbSN%2BO17chZtVBjGUYrKoyU6B%2FGB8MexFE6rmYaTCr5AjgqGWm97VCCwZkpHbRiTtFH5yT825G9%2FkRPYHkxsPnCw%3D%3D))
In the meantime I actually had a sit-down with my mentor (the person joining the conversation in that basement) and made further plans how to implement things.
And so this is it. The next month or so I will have time to get to know the code base of the project (although I partially already have), meet more people from the community and generally get into the rythm of what GSoC is.
I will be posting three blog posts on the official [Freifunk Blog](http://blog.freifunk.net/), one in a couple of days/ weeks, one in the height of the project and one that will go into the aftermath of the project.
But in the meantime I will be keeping my blog up to date about what I am doing, how things are going, my challenges and things I learn.
In the hopes that people might find it useful and lean things from it. Or just to save my insane ramblings in some narcissistic pleasure...to think that I am relevant in the world :P
Read you soon,
Kate

@ -0,0 +1,37 @@
Title: First steps...baby steps
Category: Blog
Date: 2016-06-02 19:56
Tags: GSoC2016
So it's been almost two months, the community bonding period has passed, blog posts were written, talks held and slowly but surely I'm working myself into the qaul.net codebase.
It's always weird joining a larger project and seeing established build setups, code conventions or generally things where your first thought is "I would have done that differently...". But it's really fun.
I'm currently working myself into [mbed.tls](https://tls.mbed.org/) which is the crypto library which was chosen to power the cryptographic backend for libqaul (which powers qaul.net).
That includes some code that will probably not make it into a later version of my branch: the debugger.
### The De-bugger?!
![Debugger Pro 2016](/images/gsoc/01_debugger.png "Debugger")
Well...debuger might be a bit of a strong word, it's basically a way to develop core functions of qaul.net without having to start a GUI, going through NetworkManager dialup or oslr bootup.
There I am currently busy writing a wrapper around a new namespace added to libqaul: `qcry` (short for qaul crypto) and properly integrate all the mbed.tls sources into the library so they can be accessed by libqaul. The idea being that I don't have to leave vim and the terminal to develop on the core cryptographic components such as:
- Key generation
- Identify generation (with private key fingerprints)
- Identity verification
- ???
Only in the last step of the last bulletin do I actually have to involve the GUI of qaul.net. And until that point I wish to not come in contact with it (if avoidable).
So most of next week will be getting to know mbed-tls as I have never worked with it before. But hey...can't be worse than the gcrypt documentation¹ :')
Hope to read you soon with more updates (probably rants).
Kate o/
---
¹I am sure I will eat my words in 4 weeks

@ -0,0 +1,69 @@
Title: What I have done in GSoC 2016
Category: Blog
Date: 2016-08-19 18:13
Tags: GSoC2016
Google Summer of Code is coming to an end. And as the final bugs are getting squashed and more code is being prepared for the big merge, I am sitting here, trying to think of how to represent my work.
I thought I would write up a little blog post, explaining what I've done and what still remains to be done.
### The TLDR
My main contributions are all available [here](https://github.com/spacekookie/qaul.net/commits/qaul_crypto?author=spacekookie) (spacekookie/qaul.net on the `qaul_crypto` branch). I did a lot of small commits. Most of my code can be found in this [sub-directory](https://github.com/spacekookie/qaul.net/tree/qaul_crypto/src/libqaul/crypto).
In addition to that I ported an existing project (from python) to C to be relevant for future front-end endevours of the client. It's called [librobohash](https://github.com/spacekookie/librobohash). I didn't end up finishing the port because there were more pressing issues in qaul.net and the UI was delayed.
While most of my work has been in hidden backend systems there is a demo you can run. The source compiles and has been tested under Linux (Ubuntu 16.04 and Fedora 24) and is located under the `src/client/dbg/` directory. The demo creates two new users (to simulate communication between two nodes), adds the public keys to the keystore and then continues to sign and verify messages. If the demo returns lots of "0" and "OK" it went okay :)
Feel free to play with the demo; for example, switch out `message` for `fakemessage` during verification :) The source for the demo can be found under `src/libqaul/qcry_wrapper.c`
### The good (aka what I have done)
<img class="dual" src="/images/gsoc/02_cryptoui.png" align="left">
The two main components that I've written during GSoC2016 are internally referenced as `qcry_arbit` and `qcry_context`. They are two modules that make up the new crypto module in qaul.net.
As I explained in my first blog post on the [Freifunk blog](http://blog.freifunk.net/2016/gsoc2016-wrapping-crypto-module-qaulnet) the Arbiter provides a static API for the rest of the library (libqaul) to interact with the crypto module.
The context holds the actual magic of holding user keys, signing and verifying messages and (theoretically) encrypting messages as well.
Possible with this API at this time is to create users, to sign messages with a users private key and to verify messages that are sent to you from other users. Originally it was planned to split the arbiter into the actual API and a dispatcher which would allow for concurrent access to the inner functions. However it was established through tests that the design was overkill and was thus scrapped.
A keystore was added in addition to the user store already existing in qaul.net to provide an easy way to store public keys (mapped against fingerprints) that are received from flood events on the network.
In total the crypto submodule adds another ~2.2k lines of code to the project.
### The bad (aka what I haven't yet done)
So far completely un-implemented is encryption. Unfortunately working with the crypto library selected for the task turned out to be more challenging than expected. With almost no documentation and a few very niche examples I basically went through the library line-by-line to understand how it worked.
As such, my focus was set on signature exchanges at first because the verifiability of messages and the change to address users by their fingerprints was deemed more important.
My contributions to qaul.net won't end with the end of Summer of Code. The function stubs are already provided and I plan on implementing the encryption features in the coming weeks.
### The ugly (aka what I can't do yet)
Signatures (and also encryption) of private messages (so messages that aren't flooded to everybody) is currently impossible. This is due to the way that the communication system in qaul.net works.
I have talked to my mentor and he said that they were currently in the process of re-writing the communication sub-system in libqaul. This means two things:
1. I need to wait for those changes to be done until I can finish what I set out to do
2. Some of the code I wrote (hooking into the current communication system) is being made obsolete :(
### In conclusion
What I can say is this: qaul.net has gotten a very big step closer to becoming a more secure network of communication. The crypto submodule is tested and easy to use. What might happen is that parts of the code get merged (the crypto submodule itself) without merging any of the code that hooks into the communication stack.
I had a lot of fun working on this project and I am looking forward to more contributions. I have a few cool ideas that I want to discuss with the rest of the team and I am glad that I participated in the Google Summer of Code.
I was interested in open source before and I contributed to my own projects on github. But the experience I gained this summer will be helpful for me, not just for my own work, but to be less reluctant to join other developer communities.
And I look forward to seeing my code get merged into qaul.net :)
Read you soon,
~Kate

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 834 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 719 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 720 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 592 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

@ -0,0 +1,112 @@
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
❤ (rayya) ~> cat msg
Following are my public gpg key as well as Threema Fingerprint and others.
Threema
=======
ID: 77WYDHA2
Fingerprint: AB2A 4F8A 8FF9 6335 75C2 4E0C 175B C0D6
Public Key Cryptograpy (GnuPG)
==============================
Plain copy of my key can be found here
https://spacekookie.de/pgp/6FE1BBF3.asc
It is also available on the MIT keyserver.
This document was last changed/ signed at around
❤ (rayya) ~> date
Sun 7 May 14:09:59 CEST 2017
❤ (rayya) ~> gpg2 --fingerprint 6FE1BBF3
pub rsa4096 2017-02-02 [SC] [expires: 2019-02-02]
9F18 A093 CF65 F938 E4C8 EFA4 29E0 5751 6FE1 BBF3
uid [ultimate] spacekookie c-base <spacekookie@c-base.org>
uid [ultimate] spacekookie (Using computers to create weird random patterns...) <kookie@spacekookie.de>
sub rsa4096 2017-02-02 [E] [expires: 2019-02-02]
❤ (rayya) ~> gpg2 --armor --export 6FE1BBF3
- -----BEGIN PGP PUBLIC KEY BLOCK-----
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
=vSgE
- -----END PGP PUBLIC KEY BLOCK-----
-----BEGIN PGP SIGNATURE-----
iQIzBAEBCAAdFiEEnxigk89l+TjkyO+kKeBXUW/hu/MFAlkPFaQACgkQKeBXUW/h
u/NbgQ/+LRikzv8yFpVzbNZTg1mEQ+wFDZEnrwSDvdEL/+iqZ8X8V3NWz9svUIF/
mMjQeYH3XcZqJ19XpyfSd+1MiFoNRCU04aaOwopmWrok0qYoKW7zdwTHmiBnftCs
vctvO5o0INN2Qfrhwjzot2EfBiuo6LBG3lV6rWdMZFkJFlzoCqlFrMVWBAYBtXlN
QhPgxfanp3Fg7hKGS5sYjtGlGEY6Qu1nkbU/92sHtCnSb+2TM8fRij4Su/5B+XMH
e2UbmMcSY2iS2tn46sG0hAVky5+BF2JHKWVOECrszqVwxDRhqPBdVOKD3biXrQsM
9NistBGaFoYcVxN7wvhVdOd07pqc6HV1Dmv3ngro6kX3j9KsB/70OvKntsVWbnph
kEwoOVAhPs8f6zNo/lGhs9vYsLgkbSpzflKYlEqHlOFOPSGzHAAeM7eMi6aWVMWB
LnVxaKtogE1m7lPdgkHt0V6sqHUFf+j7eHrWp0J8w514FcO9dhhNiY0Yvn1xJCBM
tEkemLyMfk8gx3M1lz8p7RkKR601GcXi6mtpetREPL40zUt8IhRDwUwXM6Pvuspl
pKUxhkbE8CeJ9vvyqVhoAjTfEGDpXI6sb53le7RXkw8JdQ9ueoJyt4Fk/zXXxvdC
3XMB6dIEFQ979IHp04Pb8njdWEokzNOMlUPyrTR0UvYXUPeDmhs=
=ZvDg
-----END PGP SIGNATURE-----

@ -0,0 +1,21 @@
Title: whoami
Slug: about
```scala
❤ (idenna) ~> whoami
spacekookie
```
I'm a computer science student from Berlin, Germany. In my free time I make games, write free and open-source software and am an allround nerd.
I grew up in a small town in West Germany in the mid 90's. As a girl I loved technology, played around with electronics and copied bad BASIC game code from books. I wanted to become an inventor and designer.
Through my teenage years that changed. While I was still interested in technology, I got deeply into story writing, music and 3D modelling/ animation. All of that I wanted to one day put together and make games.
In my early 20's I started studying engineering, then later computer science. Though interested in chip design, my passion for video games had made me attempt to create one; and become obsessed with programming. I learned to code in Java, later in python, Ruby, C. I fell in love with free software and linux. Since then, I've tried to expand my knowledge on all things technology, trying not to loose touch too much with my artistic side.
I write too much C code, try to contribute to open source projects, try to make games. This blog is to be a journal of how projects are going, showcases of finished projects (yea right..."finished") and off-topic thoughts about whatever comes to mind.
I hope that you find any of this stuff even remotely useful. If so, yay! If you want to get in touch with me, the easiest way is probably my [twitter](https://twitter.com/spacekookie) or e-mail me at [kookie@spacekookie.de](mailto:kookie@spacekookie.de). You can find my GnuPG public key [here](/kookie.txt).
I also implement a 512mg Prime MTU according to the [RFC2549](https://tools.ietf.org/html/rfc2549).

@ -0,0 +1,9 @@
Title: Fun memory violations
Subtitle: NULL
URL: /
Save_As: index.html
Template: home
Hi! Welcome to my dusty internet hangout place.
My name is <b>Katharina Fey</b> and I'm a software developer from Berlin. I like taking photos, writing stories and starting way too many personal projects.

@ -0,0 +1,6 @@
Title: Notable errors
Slug: showcase
My goal has always been to make things. Sometimes by myself, sometimes with others. I start many things that will never be done due to my own perfectionism. But some things might be worth highlighting. Things that could be useful to others. Or are still actively being developed for support. Or are just plain beautiful.
**Consider this my extended CV...**

@ -0,0 +1,6 @@
Title: Tutorials
Slug: guides
I started writing a few tutorials on my blog. But in order for you to find them easier I created this static page that will link you to the respective blog posts. Check out the dropdown menu above or icons below to view the available tutorials and courses.
TODO: Add links to list pages here

@ -0,0 +1,114 @@
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
❤ (idenna) ~/pgp> cat msg
Following are my public gpg key as well as Threema Fingerprint and others.
Threema
=======
ID: 77WYDHA2
Fingerprint: AB2A 4F8A 8FF9 6335 75C2 4E0C 175B C0D6
Public Key Cryptograpy (GnuPG)
==============================
Plain copy of my key can be found here
https://spacekookie.de/pgp/6FE1BBF3.asc
It is also available on the MIT keyserver.
This document was last changed/ signed at around
❤ (idenna) ~/pgp> date
Thu 2 Feb 11:52:00 CET 2017
❤ (idenna) ~/pgp> gpg2 --fingerprint 6FE1BBF3
pub rsa4096 2017-02-02 [SC] [expires: 2019-02-02]
9F18 A093 CF65 F938 E4C8 EFA4 29E0 5751 6FE1 BBF3
uid [ultimate] spacekookie c-base <spacekookie@c-base.org>
uid [ultimate] spacekookie (Using computers to create weird random patterns...) <kookie@spacekookie.de>
sub rsa4096 2017-02-02 [E] [expires: 2019-02-02]
❤ (idenna) ~/pgp> gpg2 --armor --export 6FE1BBF3
- -----BEGIN PGP PUBLIC KEY BLOCK-----
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
=vSgE
- -----END PGP PUBLIC KEY BLOCK-----
-----BEGIN PGP SIGNATURE-----
iQIzBAEBCAAdFiEEnxigk89l+TjkyO+kKeBXUW/hu/MFAliTEe0ACgkQKeBXUW/h
u/Pb1w/+IYx8RUaxGQxq8jphBaCwAfUvOOl3DQwPLETsvz1UYQPcNTmXbKK8GziJ
ki69eizxMcikVwTT0CinRX0NtE1qeGKmPiTT9Zxoi688QeXdDZDksOrLHGS+bqfV
WxwQG2hGUjLUqCjKsBIz4OwiZ8xqff+Z3HqYhTc1GpdwbIXG43l+tLFkU5eTaERU
u/uSPjnmbxrZRGLzv0fnrppEKXPTBmm8O3hIM9Cp+rZIQw9rbbkGSGeRXtSDDsC/
6dkBKvM7YDqw/9/EnFbrw1vMBnVDdmMvMH/KQIxDuF+mEkq9eNOvR8QCJa8SDMOH
Hdhi8sJqS7oX91kH0TU86Uym+/GKlUfq/VDZCGssOqPlFLc0ZOWKL1VoReVwb+34
hkowMP5i4XieXuY4JtBTuDjvGbauZDorFqONosAzq67zf2FTY3JrGZay0Q+3/rs9
q3FbU8esjM/q64XltuWmZfGnbRU3Xdfr+V/YCqLiUXfsLJ38WZBXruL31ar9CjcL
PMN/YipyvSkSze8IBHBtyonDg5Zug7ntL6Ku58XitQBHRy8KDuJL74RiABmri2DM
Tpo1kwGokd3Sj24VX4JEg/jAczC93x/F9B2BKCY1tvqSDCdavrToSbSOva7//9sC
MV2oN8slEE5fPgxT9A8DTORImfstI9AnUBUn+julhMer3FSaNWk=
=MXQM
-----END PGP SIGNATURE-----

@ -0,0 +1,16 @@
Following are my public gpg key as well as Threema Fingerprint and others.
Threema
=======
ID: 77WYDHA2
Fingerprint: AB2A 4F8A 8FF9 6335 75C2 4E0C 175B C0D6
Public Key Cryptograpy (GnuPG)
==============================
Plain copy of my key can be found here
https://spacekookie.de/pgp/6FE1BBF3.asc
It is also available on the MIT keyserver.
This document was last changed/ signed at around

@ -0,0 +1,296 @@
Title: 01. (LibGDX) Game of Codes: The Setup & Basics
Category: Game of Codes
Tags: LibGDX, Tutorial, Game Dev
Slug: 01-libgdx-game-of-codes-the-setup-basics
Status: published
**Hey everybody and welcome to a new/ old series on this blog about LibGDX.**
LibGDX is a Java game development framework based on LWJGL and OpenGL which makes it relatively easy to make a game from scratch without requiring a big engine. It supports Desktop, Android, iOS and HTML as export targets which means that your game is automatically cross platform.
Getting to know the framework can be challenging in the beginning, which is why I wanted to make a little series about it. Before I moved my blog to a static site generator I had a rather popular series about LibGDX called "Game of Codes". Unfortunately large parts of the guides are now outdated and no longer relevant. And the Wordpress export destroyed most of the formatting.
Which is why I decided to rewrite them. Here it is: the Game of Codes! *plays theme song*
NOTE: This tutorial requires a basic level of programming/ scripting skills. General Java knowledge is required or at the very least knowledge of how coding works. If you don't know that yet then I
recommend [Bucky Roberts Java Programming series on Youtube](https://www.youtube.com/watch?v=Hl-zzrqQoSE&list=PLYJQBQw9Wdiid6eT1_DqBP3lnbJCzo3s8).
It's very good!
### Setting up LibGDX
Now that we've got that out-of-the-way let's set up our workspace to make some neat games. I am writing and testing these tutorials on Linux. So if there are some platform specific issues you encounter, please give me feedback at [kookie@spacekookie.de](mailto:kookie@spacekookie.de).
1. First of all you'll need to have Java and an IDE (Integrated Development Environment) installed on your computer. In this series I will be assuming that you're using **Eclipse**. For pointers on how to install that, please use Google!
- LibGDX uses Gradle as a build system. The latest version of eclipse has it integrated but older versions might require a plugin!
3. Go to [libgdx.badlogicgames.com](http://libgdx.badlogicgames.com/) and download the libgdx setup app. It will help you configure your project with Gradle so you can either develop on it in a text editor of your choice or import it into an IDE.
<img class="dual" src="/images/gameofcodes/series01/02_setup_ui.png" align="left">
<img class="dual" src="/images/gameofcodes/series01/01_setup_ui.png" align="right">
Let's step through the setup UI on your left real quick. We have some base settings. You can fill out the name of the game, the name of the main class as well as the package. If you're new to Java, the convention is that every application has a unique package root. And it's usually the reverse of a web-address. So for me it's `de.spacekookie` and then the project name. In homage to the original tutorial series I will call it `de.spacekookie.starchaser`.
Also important to choose are the directory where to setup the project as well as your Android SDK location (if you want to build on Android). I will be ignoring Android for now and focus on the Desktop.
<br/><br/><br/>
<!-- Introduction to the module we need -->
Make sure that you tick the following extentions (and extentions from the "third party" visible below the main window):
- Ashley (Entity management library)
- Box2D (2D physics)
- Box2DLights (2D realistic lighting)
- VisUI (Good looking skin for UI elements)
Also make sure that if you want to use an IDE (such as Eclipse or IntelliJ) to select the project export from under "Advanced". When you're done with the configuration, hit that lovely "Generate" button and let's get going with development :)
I will skip the importing step because that will be different for different IDE's. All I will say is that in Eclipse you should avoid putting your workspace *inside* your project directory as it will cause issues for you in the future (or during import).
> **Tip**
> While there are many ways to work on LibGDX, in this series I will assume that the project was added to Eclipse via Gradle while the building is done via a normal "Java Application" launch target in Eclipse. This is (in my opinion) the best of both worlds with a quick and easy build but the dependency management of Gradle built int the IDE.
### Working with LibGDX
So assuming that you were able to follow until here, you should now have a Java development IDE in front of you
<!-- Add a picture of Eclipse here? -->
> **Tip**
> LibGDX is very closely entangled with Android. For example, if you create a project to have an Android target, all of the game assets will be stored in the "Android" subfolder because of who the system handles file imports. This means that the Desktop/ iOS and HTML versions only use symlinks to the Android assets directory.
> If you don't have an Android project (only Desktop for example) assets are simply stored in your core project with all your game code!
Now that everything is ready to go, let's investigate a little into what code was already generated for us and what we can do with it. Feel free to just hit that "build" button and get started but we're taking a more scientific approach :)
<img class="dual" src="/images/gameofcodes/series01/04_eclipse.png" align="left">
As you should already have noted there are several projects that were created for you. One project without a suffix and multiples with suffixes. The one project without a suffix is called the "meta" project (it contains relatively uninteresting things), while the other projects have to be divided into "core" and "targets". The idea is simple: you write all your logic, rendering and gameplay into the "core" while platform dependant code is used in the "targets". If this is complicated to understand, don't worry. It'll become clearer when using it.
So as explained above, we will write most of our code in the highlighted "core" module. It is where you should in fact write all of your game code that isn't platform-specific to launch the game (for example getting the screen size or setting a custom icon).
Please go ahead and open up the two files marked by arrows. They are the only code files that were generated for me. The lower one labelled `DesktopLauncher.java` contains the main function which will actually launch our game. The code should be very straight forward and we will look at the configuration settings later.
<!-- Explain the basic structure of the project & function lifetimes -->
The second file, labelled `StarChaser.java` in my case (and whatever you named your main class in the setup tool) contains much more interesting goodies: game code!
Inspecting the code from the StarChaser class you can see a few functions in there that are responsible for describing the lifetime of our game object. These function are `create`, `render` and `dispose`. The create, play and, when we're done, destroy our game object. Everything else we do lives in between those functions.
In fact, there are a few extra steps in between that are hidden from you by default. Check out the following list:
```java
/** Called when the game is created **/
public void create();
/** Called after create and every time the window is resized (if that is allowed) **/
public void resize(int width, int heights);
/** Starts calling after create() and resize() and will be
* recalled every frame. This is your game loop! **/
public void render();
/** Called when the game is closed on Android **/
public void pause();
/** Called when the game is re-opened on Android **/
public void resume();
/** Called when the game is closed. **/
public void dispose();
```
This layout allows for very structured game code that walks through stages. You can of course allocate new objects in any of these functions to move functionality away from one class but in the end, you are always bound by the lifecycle of your game object. Note that all of these functions are provided by the `ApplicationAdapter` super-class that our main game class implements.
> **Tip**
> If you're ever curious about something you use/ extend/ implement works under the hood, don't be afraid to right-click on the part in question and click "Open Declaration" (when using Eclipse). This will open the source file for this module and you can see what is happening behind the scenes. In fact, I highly recommend being curious throughout this entire series.
<!-- Explain the awefulness that is Eclipse run configurations -->
If you haven't already launched the game to see what it does, I would recommend you do that now. Click the small black arrow next to the green "play" symbol in the top bar (or F5 in Eclipse), select "Launch Configurations" and create a new "Java Application" config. Check out the picture below for reference on how to fill it out. And if you have issues in this step, there are plenty of tutorials that go into depth online!
![Eclipse Launch](/images/gameofcodes/series01/05_eclipse.png)
<div class="alert alert-warning">
<h1>Fixing an Eclipse error</h1>
<br />
<p>By default LibGDX uses Gradle. This means that paths are considered differently than when you're using Eclipse. For example, the above code will not by default work with Eclipse unless you tweak something. In fact, you might encounter an error like this:</p>
<pre>
Exception in thread "LWJGL Application" com.badlogic.gdx.utils.GdxRuntimeException: Couldn't load file: badlogic.jpg
at com.badlogic.gdx.graphics.Pixmap.<init>(Pixmap.java:148)
at com.badlogic.gdx.graphics.TextureData$Factory.loadFromFile(TextureData.java:98)
at com.badlogic.gdx.graphics.Texture.<init>(Texture.java:100)
at com.badlogic.gdx.graphics.Texture.<init>(Texture.java:92)
at com.badlogic.gdx.graphics.Texture.<init>(Texture.java:88)
at de.spacekookie.starchaser.StarChaser.create(StarChaser.java:17)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:147)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:124)
Caused by: com.badlogic.gdx.utils.GdxRuntimeException: File not found: badlogic.jpg (Internal)
at com.badlogic.gdx.files.FileHandle.read(FileHandle.java:136)
at com.badlogic.gdx.files.FileHandle.readBytes(FileHandle.java:222)
at com.badlogic.gdx.graphics.Pixmap.<init>(Pixmap.java:145)
... 7 more
</pre>
<p>While when you build your project with <code>gradle run</code> it will work. This is because Eclipse handles import scopes differently and we need to respect that. You now have two choices:</p>
<ol>
<li>You hard-code import paths from the filesystem root (i.e. "/home/spacekookie/.../artpack1/uss_pixel.png"</li>
<li>You add your assets folder to the source path in Eclipse. <strong>This is what I will be doing in this series!</strong></li>
</ol>
<p>Right-click on your desktop project and navigate to "configure build path" as shown in the picture below.</p>
<img src="/images/gameofcodes/series01/06_eclipse.png">
<p>Select "Add Folder" in the window that should have opened and in that dialog select "assets". Close the dialog and try to run the game again. It should now work!</p>
<p>If you're having issues with this step, feel free to e-mail me at <a href="mailto:kookie@spacekookie.de">kookie@spacekookie.de</a></p>
</div>
### Understanding the Code
*waits for you to launch the game*
Cute, eh? Not exactly a game but it's a start. The example demonstrates a few basic principles as well as *super* basic 2D rendering. However, before we go, throw it all away and implement our own cool stuff we should try to understand how the current code works.
```java
//...
public class StarChaser extends ApplicationAdapter {
SpriteBatch batch;
Texture img;
@Override
public void create () {
batch = new SpriteBatch();
img = new Texture("badlogic.jpg");
}
@Override
public void render () {
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.draw(img, 0, 0);
batch.end();
}
@Override
public void dispose () {
batch.dispose();
img.dispose();
}
}
```
Let's ignore the package definition and import statements and jump straight into the class declaration. We're creating a class, extending the `ApplicationAdapter` which is responsible for turning the class into an actual game object (as described above).
The first function that would be invoked is the Constructor. Because there is none here, we will skip it. The next function being called is `create()`. It initialises a new SpriteBatch and afterwards a texture for "badlogic.jpg".
You will be able to find the texture in the assets folder. And, if you change it, you will notice the changes in game as well. So far so good. What the hell is a SpriteBatch?
A `SpriteBatch` is an object which is used to keep context during 2D render calls. Basically, you give it a positional and transformational reference frame (in our case DEFAULT) and then tell it to draw 2D images. But I'm getting ahead of myself. Because in this function we only create a new SpriteBatch. So all is good.
Moving swiftly on to the `render()` function. This one is more interesting. The first two lines are two OpenGL calls which prepare a frame to be drawn. The first line sets up a colour while the second line tells the graphics processor to take the prepared colour and paint the entire frame with it. The colour representation is in RGBA (Red, Green, Blue, Alpha) with floating numbers between 0 and 1. So (1, 0, 0, 1) is red. *Try to change the colour and see the result!*
The last three lines in the `render` function tell the SpriteBatch we created early to start, draw our texture and afterwards stop again. This marks the end of the frame at which point the next one will begin shortly.
> **Tip**
> Try to copy the `batch.draw(...)` command and change the coordinates from (0,0) to (200, 0). You will notice how a second instance of our texture is drawn at a different location. Cool, eh?
The last function in the file is `dispose()`. It is only called when we close the game and usually only has other dispose calls in it. In our case, we make sure to properly dispose of the SpriteBatch and the Texture as both of them allocate memory on the graphics processor and we don't want to leak memory!
### Adding to the game
Phew! That was quite a lot to take in, I'm sure. And don't worry if you're a bit fuzzy on some of the details. We will go over some of these things again when we use it. Additionally there are a lot of great resources out on the internet for you to help you out.
But before we wrap up this (way too long) article, I want to do something to make the game feel more like...well, a game. So go ahead and open the image processor of your choice (I will be using GIMP) and create a 128x128 pixel texture that one might consider a spaceship.
<!-- ADD PICTURE OF USS PIXEL HERE -->
You don't have to neccessarily make it 128x128 (I will) but the dimentions of the picture need to be a power of two (so 2, 4, 8,
16, 32, 64, 128, 256, 512, 1024, 2048, 4096, ...). This has to do with how computers load textures (details later).
What is that you say? You're too lazy? You don't have an image processing application? You managed to delete Paint from your computer? Kudos. Fine, you can use my graphics (contains the USS Pixel, a laser burst and a background image from the web).
**Download [my artpack here](/downloads/gameofcodes/artpack1.zip).**
I would suggest you create a new directory inside your games "assets" folder so that we don't get confused about what's what. So this is how your core/assets/ folder should look like now:
<pre>
❤ (idenna) ~/P/p/c/starchaser/core> tree assets/
assets/
├── artpack1
   ├── background.png
   ├── pixel_blast.png
   └── uss_pixel.png
└── badlogic.jpg
1 directory, 4 files
</pre>
First, why don't you go and change the line
```java
img = new Texture("badlogic.jpg");9
```
to
```java
img = new Texture("artpack1/uss_pixel.png");
```
and marvel at the amazingness that is my art skills :)
When launching the game now you will notice that the face texture has been replaced with a spaceship. However, this doesn't feel very space-y or even game-y yet. So let's not stop here! Reserve a new texture variable in your class and create it with a different resource file during the create function. Your source code should resemble something like the following
```java
Texture img, background;
@Override
public void create() {
batch = new SpriteBatch();
img = new Texture("artpack1/uss_pixel.png");
background = new Texture("artpack1/background.png");
}
```
Then in the render function, before drawing the ship, draw the background texture first! This will make sure that the background is always behind the ship and not vice versa.
```java
batch.begin();
batch.draw(background, 0, 0);
batch.draw(img, 0, 0);
batch.end();
```
Run the game and feel your jaw drop. It should look a lot nicer now. There is still no game logic or advanced rendering but we're getting there. Try to flip the draw calls around and see what happens to the ship.
Also, you might have played around with the draw calls earlier and realised that `batch.draw(...)` in it's simplest form takes a texture and a coordinate. We will use more advanced draw calls later as this (for example) can't consider rotation.
![StarChaser Mk1](/images/gameofcodes/series01/07_gamechange.png)
<hr/>
Wow! That ended up being longer than I expected :)
In the next tutorial we will look at how to bring movement into the game. This consists of actually updating certain parts of the game as well as handling user input. See you then!
Kate
[[Next post about Input & Movement](/game-of-codes/02-input-and-movement/)]

@ -0,0 +1,270 @@
Title: 02. (LibGDX) Game of Codes: Input & Movement
Category: Game of Codes
Tags: LibGDX, Tutorial, Game Dev
Slug: 02-input-and-movement
Status: published
Welcome back to the Game of Codes, an introduction series to the LibGDX framework. In the last edition we learned how to set up LibGDX with a new Java project and draw simple pictures onto the screen. We used textures to import that image and then drew it via a SpriteBatch.
Today we will look at basic input handling and how to make things move on screen. And though we won't be able to cover everything in this article we will explore the basic input stack that LibGDX has to offer and how to make things in your game move.
Exciting! :)
A little note: all the code that gets shown off here is available in a [Github repository](https://github.com/spacekookie/starchaser) for you to tinker with. After each tutorial I tag the commit so that it's obvious what got changed when!
You can also use that repository to report issues or give feedback if you'd like. Otherwise, my email is always available!
### Registering input
Before we talk about inputs, we need to think about what it even means to register an input. When the user presses a button in our game, we want that button press to notify us so we can affect some behaviour. To understand what is going on here, we should consult the following graphic.
![Life of a Frame](/images/gameofcodes/series02/01_framelife.png)
You can see that LibGDX (obviously) considers the main run loop of our game...a loop :) In this series we only really care about the purple boxes. And in this article in particular, we are only considering the first purple box: "Input". What LibGDX does during this step is poll all input hardware for activity. It then writes this activity into a buffer and signals all registered input adapters to handle their input.
So with that in mind, there are two ways of checking for input. The first is essentially polling the hardware again yourself during the "Render" step, while the other hooks into the "Input" step and is called asynchronously.
Both ways of handling input are slightly unique. And we will start with the polling aproach first to demonstrate some basic functions.
First, go into the main game class and add a position variable into the class body:
```java
import com.badlogic.gdx.math.Vector2;
public class StarChaser extends ApplicationAdapter {
//...
Vector2 position;
// ...
}
```
Furthermore, in the `create` block of the game, initialise the position to some value that is greater than `(0,0)` and not too big to be off window :)
```java
position = new Vector2(250, 150);
```
If you're not too familar with Java, what this means is that we declare `position` to be a object variable which means that every function in an instance of this class can access it (Object-Oriented Programming). In the `create` function we then initialise it to have a value other than `null`.
What that means now is that we can use the position variable (which has an `x` and a `y` component) in our draw calls to tell the picture where to go. The main advantage of this is that when we change the position variable (say...via a button press), the picture gets an updated position!
```java
public void render() {
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
updateInputs();
batch.begin();
batch.draw(background, 0, 0);
batch.draw(img, position.x, position.y);
batch.end();
}
```
So far so good...wait. Do you see that `updateInputs()` function call there? That wasn't there last time. In fact, it doesn't yet exist. But it should soon. Why don't you go and create a new function in the class somewhere with the signature `void updateInputs() { ... }`. We will fill it's body with some stuff soon.
So fundamentally, we want to poll inputs and then when we have determined that an input is pressed we want to enact some functionality. The simplest form of polling buttons is with the `Gdx.input.isKeyPressed(key)` function where `key` is an integer variable that corresponds to a key-code. Don't worry, there are bindings that make it easier and you don't have to manually check for numbers ;)
> **Tip**
> Other input polling functions include `isButtonPressed(button)` for mouse buttons as well as `getX()`, `getY()` which give you the cursor position in your game window!
So why don't you add the following lines of code to your `updateInputs` function and see where it gets us.
```java
if (Gdx.input.isKeyPressed(Keys.W)) {
position.y++;
} else if (Gdx.input.isKeyPressed(Keys.S)) {
position.y--;
} else if (Gdx.input.isKeyPressed(Keys.A)) {
position.x--;
} else if (Gdx.input.isKeyPressed(Keys.D)) {
position.x++;
}
```
You can run this now and see what happens. When we press the keys in question the image on screen will move all over the place. Cool! But...it's not particularly pretty, is it?
For one, we can only move in one direction simultaniously. But even if we split the X-Y axis into two different if-blocks, there is still the problem that `W` will always have precedence over `S` and `A` will have precedence over `D`. Which means that if we press all keys, we will *always* move top-left. And that's not particularly great :(
> **Tip**
> Also consider the following: when you move in one direction you apply 1 to the axis you're moving along. But if you move in two directions, you apply 1 in both x and y direction. Which means that (via trigonometry) you actually move **~1.41** in total. This means your game isn't consistent about rules.
> It's clear that more logic is required to move!
So how do we fix this? We can of course add more logic to our `updateInputs()` function but it will result in a lot of dirty hacks. And while game development is often about making dirty hacks that work, starting a project off some will quickly make your code-base unmaintainable.
### Using Input Adapters
The second method of getting input from the user I mentioned earlier is via an input adapter. It can be considered faster because we only do input polling once and it allows us to use input signals between different game components (gameplay, game HUD, etc.)
So how do we use this awesome functionality? Well, it's simple. We need an InputAdapter. So first, create a new class via Eclipse. If you don't know how, consult the *suuuuper* helpful screenshot below :')
![Life of a Frame](/images/gameofcodes/series02/02_createclass.png)
Give it a useful name like `InputHandle` or `ShipInputHandle` or something. You can be quite specific in the naming because you very often have multiple input adapters for different aspects and parts of your game. So being specific in the naming just helps you out in the long run.
Once you've done that you should be greeted with a very boring and empty class in your editor. So we need to add some basic code to get going. I took the liberty of doing that and will now show off what I did (and you'll finally get to see what name I chose...).
```java
import com.badlogic.gdx.InputAdapter;
import com.badlogic.gdx.math.Vector2;
public class ShipInputHandle extends InputAdapter {
Vector2 shipPosition;
public ShipInputHandle(Vector2 shipPosition) {
this.shipPosition = shipPosition;
}
}
```
So, as you can see we have a class that extends `InputAdapter` as a subclass. With that comes free functionality we don't have to implement ourselves. Additionally I create a constructor that takes a vector and stores it as an instance variable (like before in the game class). Note that we're not copying the value here but rather storing a reference to the "original" variable in the game.
> **Tip**
> If you're coming from a language like C or C++ this can be quite confusing. What is a copy, what is a reference? In general: java always passes by reference (pointer) unless it is a primitive value. What is a primitive value? `int`, `float`, `double`, `boolean`, `byte`, `long` and all other lower-case types that become purple in the IDE (keywords).
Next up, let's handle some inputs! The principle is similar to the polling: we check what input we are handling (because we only have generic functions - this will become obvious in a second), then invoke some behaviour. But as we have already seen before, we need to store some state. And that's why this is perfect: we have a new class where we can store the input state to check against. But at the same time, it's contained and doesn't clutter our main game class.
Now...to solve the problem of moving in multiple directions at the same time, without letting one direction take precidence over another we can use a tri-state variable. In Java this can easily be done with an enum. Create a enum titled `TS` (or TriState if you feel verbose) in our `ShipInputHandle` class and create two values `x` and `y` that use it. The initial value should be `NEUTRAL`
```java
enum TS { POS, NEG, NEUT };
TS x = TS.NEUT, y = TS.NEUT;
```
In the `keyDown(int keycode)` and `keyUp(int keycode)` functions we can then use a switch statement to flick the `x` and `y` variables in their favour. We *can* also perform a simple check if the `x`, `y` variables are already set to avoid another direction overwriting our current movement. But then again, maybe you consider this preferred behaviour. I chose to perform the check in the following code!
```java
public boolean keyDown(int keycode) {
switch (keycode) {
case Keys.W:
if (y == TS.NEUT)
y = TS.POS;
break;
case Keys.S:
if (y == TS.NEUT)
y = TS.NEG;
break;
case Keys.A:
if (x == TS.NEUT)
x = TS.NEG;
break;
case Keys.D:
if (x == TS.NEUT)
x = TS.POS;
break;
}
return true;
}
```
Notice that `return true` at the end of that function? That's what you could call "Input Cascade". It is a concept that we will use extensively in later articles of this series. In short, it is the concept of letting an input signal cascade through different input adapters until it is ended. Returning true in this function signals the core input controller that we are ending the signal: it will not cascade to lower ranking controllers. This means that if you replace it with a `return false`, controllers down the stack will be able to pick up on the signal and use it.
But again, this will become important in later tutorials. For now, let's just end the signal and get it over with. Next up, we can implement the `keyUp` function very simply by checking what axis our key-presses affect and then resetting that direction back to `NEUT` if it is applicable. Not a perfect solution but something that will definately work is implemented below.
```java
public boolean keyUp(int keycode) {
switch (keycode) {
case Keys.W:
if (y == TS.POS)
y = TS.NEUT;
break;
case Keys.S:
if (y == TS.NEG)
y = TS.NEUT;
break;
case Keys.A:
if (x == TS.NEG)
x = TS.NEUT;
break;
case Keys.D:
if (x == TS.POS)
x = TS.NEUT;
break;
}
return true;
}
```
Now we're almost done. One thing is missing however! We keep a state depending on the inputs of our user. But we don't apply anything to the vector we stored based on that state. This is where we will need to build something slightly custom because the InputAdapter doesn't force you into any workflow.
I recommend you create a new function `void update() { ... }` in the input class and make it public. We consider this function to be called every frame and apply values to the x and y components of the position vector, depending on the state of our inputs.
The following code very quickly checks if we need to apply movement at all (is not NEUT) and then does a conditional application of 1 or -1 to each component.
```java
public void update() {
if(x != TS.NEUT) shipPosition.x += (x == TS.POS) ? 1 : -1;
if(y != TS.NEUT) shipPosition.y += (y == TS.POS) ? 1 : -1;
}
```
Now we're done modifying the ShipInputHandle...for now :) Go back to the main game class. There are two more things to do before we can enjoy our new input handles. First, remove the old `handleInputs()` function. We don't need or want it anymore. Also make sure to remove it's function call from the `render()` function.
Secondly, create a ShipInputHandle object and initialise it with our vector. Take the following code segment as reference.
The last line in the `create()` function is key and not to be forgotten! It registers our custom input handler with the LibGDX input system and makes sure that our functions are *actually* being called :)
```java
public class StarChaser extends ApplicationAdapter {
// ...
ShipInputHandle input;
@Override
public void create() {
// ...
position = new Vector2(250, 150);
input = new ShipInputHandle(position);
Gdx.input.setInputProcessor(input);
}
@Override
public void render() {
// ...
input.update();
// ...
}
// ...
}
```
And that's it! Run that code and you'll be able to move the image around in a much nicer fashion! Again, this is far from perfect. And you will notice that switching quickly from going-left to going-right can make the whole thing just stop on "Neutral". You can remove the additional check which I added. Realistically, you need a lot more state to mirror what the user is putting into your system if you want real-feedback and logical behaviour from your units. But this will do for now!
And more importantly...it should have given you a glimpse at how to use the InputAdapters.
<hr />
And that's it for this article! Originally I wanted to talk a little bit about rotation. But I realised that I would have had to make a lot of assumptions about systems and not be able to go into too much depth without making the article *waaaayy* too long.
So that'll be handled in the [next issue](https://media.giphy.com/media/z85AlA6CBKxEI/giphy.gif).
Have a good day/ night,
Kate

@ -0,0 +1,159 @@
Title: 03. (LibGDX) Game of Codes: Rotation & Advanced Movement
Category: Game of Codes
Tags: LibGDX, Tutorial, Game Dev
Slug: 03-rotation-and-advmovements
Status: published
Welcome back to the Game of Codes, an introduction series to the LibGDX framework. In the öast edition we learned how to listen for user input, keep it's state for consistency and apply it to the world we are building. We did this by simply using a vector as a position for an image to align to.
Today we will have a look at some more input but more importantly: rotation! And with that, also look at some more advanced movement concepts like momentum and some advice how to implement certain movement patterns.
A little note: all the code that gets shown off here is available in a [Github repository](https://github.com/spacekookie/starchaser) for you to tinker with. After each tutorial I tag the commit so that it's obvious what got changed when!
You can also use that repository to report issues or give feedback if you'd like. Otherwise, my email is always available!
### Naïve approach
So let's just take a naïve approach here. We have a vector that is essentially the position of our "ship". And it can have a rotation. So what we do is listen for two new key presses (in my case for `Q` and `E` - left and right rotation) and then create another tri-state variable `rotation` that we can use to determine whether we should rotate left or right.
```java
switch (keycode) {
case Keys.W:
// ...
/** Handling rotation */
case Keys.Q:
rotation = TS.NEG;
break;
case Keys.E:
rotation = TS.POS;
break;
}
```
The inverse applies for the `keyUp(...)` function.
```java
switch (keycode) {
// ...
case Keys.Q:
if (rotation == TS.NEG)
rotation = TS.NEUT;
break;
case Keys.E:
if (rotation == TS.POS)
rotation = TS.NEUT;
break;
}
```
Our update code needs to be appended slightly. This isn't the most pretty way to do this but for now it'll be alright.
```java
public void update() {
// ...
if (rotation == TS.POS)
shipPosition.rotate(1);
else if (rotation == TS.NEG)
shipPosition.rotate(-1);
}
```
Now. What does this actually mean. We rotate the *positional* vector for the ship. You might have an inkling of what is about to happen but if you don't start the game and look at it. Not quite what we had in mind, is it?
![Bad rotation GIF](/images/gameofcodes/series03/01_badrotation.gif)
So what's happening here? Well, our positional vector points to where the ship is. From the origin. Which is in the bottom left of the screen. At coordinates `(0, 0)`... So when we rotate the positional vector, we rotate the ship around the origin. Furthermore, we never told the `SpriteBatch` to rotate the image we're drawing. That's why the ship orientation stays exactly the same: pointed upwards.
### Using TextureRegions
So let's fix this one problem at a time. Let's actually make the ship texture rotate depending on some value (in our case, the phony vector angle). For this we need to look at how we draw things. Right now, that's a texture.
A texture is essentially a raw memory map of an image, loaded onto the GPU. That's why the texture needs to be a power of two because that's how GPU's handle textures in their memory. But what this also means is that if we have multiple textures this will cause a lot of overhead because loading textures in and out of memory from the GPU is expensive.
Also, all transformations to the texture we need to apply manually. Transformations include scaling, moving and rotation. And especially the last one can be challenging.
**Enter: TextureRegion!**
Now, a `TextureRegion` is a collection of textures, essentially a large texture with bits cut out of it. This way we can bundle all our textures together into one large one (or several large ones) while marking different parts of the texture as regions so that we can handle them in the future.
What this also means is that simple transformations can be done on the CPU which is slower but much easier than performing them on the GPU. This means the textures are still stored on the GPU but we get more control over how to transform them. Let's use this in our game!
```java
public class StarChaser extends ApplicationAdapter {
// ...
TextureRegion img;
// ...
@Override
public void create() {
batch = new SpriteBatch();
img = new TextureRegion(new Texture("artpack1/uss_pixel.png"));
// ...
}
```
The code above creates a TextureRegion instead of a Texture. In this case, we aren't using any of the memory saving benefits of using TextureRegions but that doesn't matter. We can still take advantage of it.
Specifically, we will change the `batch.draw(...)` function to take more parameters. But first, create a second vector, call it "direction" and initialise it with `(0, 1)`.
```java
final float sizeX = img.getRegionWidth();
final float sizeY = img.getRegionHeight();
batch.draw(img, // The TextureRegion we draw
position.x, // Root X position
position.y, // Root Y position
sizeX / 2, // Rotation origin X (center point)
sizeY / 2, // Rotation origin X (center point)
sizeX, // Draw width
sizeY, // Draw height
1, 1, // Scaling factor (1 is fine)
direction.angle()); // Region angle (around origin)
```
Additionally, we need to adjust our ShipInputHandle class because we need to make it use our direction vector. The code snippet below will outline what you need to change. Essentially: we rotate our direction vector and noramlise it after every step because rotating vectors actually changes their length.
```java
public class ShipInputHandle extends InputAdapter {
Vector2 pos, dir;
// ...
public ShipInputHandle(Vector2 shipPosition, Vector2 direction) {
this.pos = shipPosition;
this.dir = direction;
}
// ...
public void update() {
if (rotation == TS.POS)
dir.rotate(1);
else if (rotation == TS.NEG)
dir.rotate(-1);
dir.nor();
// ...
}
}
```
If you launch this configuration you will notice that the ship rotates around it's centre point correctly! YAY! You will notice that you can still move your ship independant of it's rotation. You might consider this a feature because it allows you to fly one way and shoot backwards (think Battlestar Galactica Vipers!). But in our case, we want the ship to always fly in the direction that it's pointing towards.
![Proper rotation](/images/gameofcodes/series03/02_rotating.gif)
This is relatively simple. We only need to change the position update code to make this happen. In fact, we only need to consider the direction vector when applying a new position.

@ -0,0 +1,110 @@
Title: 01. (Java Native Access) The basics
Category: JNI
Tags: Java, Tutorial, Programming
Slug: 01-jni-the-idea-foreign-function-interfaces
Status: draft
Regular readers of my blog (or listeners of my afk ramblings) will know that I like Java. I'm sometimes not quite sure why but there it goes, let's just assume that as an axiome for a second.
Java is pretty damn good at a lot of stuff. It compiles to a high performant byte-code and it's JIT compiler is smart, fault-tolerant and self optimising. It has a plethora of libraries and toolkits to choose from and making nearly anything is pretty damn if you don't mind writing a verbose language or [cheating](https://projectlombok.org/) a bit.
Then so far so good. What is this about then? Well...many things that Java doesn't do in it's standard lib you can still do. And it's something too many people to know about. For good reasons. Fault tolerance and optimisation on the side of the JIT compiler goes out the window and existing documentation is lackluster at best, in most cases outdated by decades at this point. Java is (among other things) an enterprise language and the tech hipsters have *looong* moved on from it. And so have people writing guides about it.
That is about to change (to some small extent)
### What is JNI?
The **J**ava **N**ative **I**nterface is a foreign-function-interface to the JVM, the virtual machine and JIT compiler environment that all Java code runs in. It allows you to write C/C++ code that is called by your existing Java project and even make calls *back* into your java code for callbacks (for example for logging).
It features a very low overhead, practically non-existant safety checking and allows for pretty performant Java-native interop. In fact, switching from the Java context to a native function context only takes [a few nanoseconds](http://stackoverflow.com/a/13977914/2443595). After that you get the raw performance of native code and all the beautiful header bindings that come with that.
Unfortunately setting this up isn't trivial and outdated documentation/ tutorials, that ignore modern build systems, don't make it easier. And while I will get into the nitty-gritty of what you should do/ avoid in the next article (or two), first I want to outline how java-native interop generally works.
### Writing a "native" class
Everything in Java is a class and this is no exception. Thus we first need to provide one that has a few `native` functions that we can then later implement. Other than native functions this class can contain normal java code although I would recommend you don't do that for the sake of readability.
```java
class JniSomething {
static {
// TODO: Load library
}
private long something;
public native void initSomething(String name, int count);
public native void doSomething();
public static native void status(int mode);
}
```
Two things that you should notice
1. We have a static initialiser block which we will later use to load a native library
2. We have a `long` type field in our class which will become important later. For now it shows that "native" classes can have fields just like any other class.
You can also see that we can have static and non-static native functions. Parameters can be primitives and classes although I only demonstrated `String` as a class here (which is a bit of a special case in JNI land)
### Native code generation
We are about a third of the way there. Unfortunately this is where it becomes a little less clean and easy to manage. From our class definition that includes native functions we will now generate a header that we can build native function implementations for.
The tool we will use is called `javah` so make sure it's included in what your operating system packages as java. On most Linux distributions it should come installed with the JDK, on Windows and Mac...I have no idea. Figure it out and e-mail me so I can add it to the article.
Assuming that your "project" structure looks something like this and your current directory is `src`
```
🚀 (normandy) ~> tree project/
project/
└── src
└── de
└── spacekookie
└── JniSomething.java
```
then you can generate the jni header file in the project root directory as follows
```console
javah -verbose -jni -o ../JniSomething.h de.spacekookie.JniSomething
```
So far so good. You can look at the file now if you want. It's actually pretty ugly code. The function names are designed to *never* clash with anything else because of how Java and C++ have *very* different approaches when it comes to scoping things. The last part of this intro will be writing code that uses these headers to do something in native code.
### Writing & linking native functions
Aaaaand this is where things get really complicated real fast. There are a few things we need to do at this point and none of them are trivial
1. We need to setup our build environment so that we can find the `<jni.h>` utility header
- Platform specific problems I might add
- Also very dependant on the build system we might be using later
2. Write and compile the native code that does *something* and make a library (for us that is an `.so` because Linux)
3. Load the library correctly as to not crash the JVM
Easy as pie :)
First things first, we need to find the Java home directory. Again, I can only speak from a Linux perspective. But the `$JAVA_HOME` environment variable was depreciated years ago by most distributions. This might not be the best way to find out but it works.
```bash
# Bash
echo $(dirname $(readlink -f $(which javac)))
```
```fish
# fish
echo (dirname (dirname (readlink -f (which javac))))
```
From the directory we get with these queuries we need to go up one directory and then into a other directory. In the end the path we want to build should look something like this. The second one will obviously be different depending on your platform.
```
/usr/lib/jvm/java-8-openjdk-amd64/bin/../include
/usr/lib/jvm/java-8-openjdk-amd64/bin/../include/linux
```

@ -0,0 +1,103 @@
#!/usr/bin/env bash
##
# This section should match your Makefile
##
PY=${PY:-python3}
PELICAN=${PELICAN:-pelican}
PELICANOPTS=
BASEDIR=$(pwd)
INPUTDIR=$BASEDIR/content
OUTPUTDIR=$BASEDIR/output
CONFFILE=$BASEDIR/pelicanconf.py
###
# Don't change stuff below here unless you are sure
###
SRV_PID=$BASEDIR/srv.pid
PELICAN_PID=$BASEDIR/pelican.pid
function usage(){
echo "usage: $0 (stop) (start) (restart) [port]"
echo "This starts Pelican in debug and reload mode and then launches"
echo "an HTTP server to help site development. It doesn't read"
echo "your Pelican settings, so if you edit any paths in your Makefile"
echo "you will need to edit your settings as well."
exit 3
}
function alive() {
kill -0 $1 >/dev/null 2>&1
}
function shut_down(){
PID=$(cat $SRV_PID)
if [[ $? -eq 0 ]]; then
if alive $PID; then
echo "Stopping HTTP server"
kill $PID
else
echo "Stale PID, deleting"
fi
rm $SRV_PID
else
echo "HTTP server PIDFile not found"
fi
PID=$(cat $PELICAN_PID)
if [[ $? -eq 0 ]]; then
if alive $PID; then
echo "Killing Pelican"
kill $PID
else
echo "Stale PID, deleting"
fi
rm $PELICAN_PID
else
echo "Pelican PIDFile not found"
fi
}
function start_up(){
local port=$1
echo "Starting up Pelican and HTTP server"
shift
$PELICAN --debug --autoreload -r $INPUTDIR -o $OUTPUTDIR -s $CONFFILE $PELICANOPTS &
pelican_pid=$!
echo $pelican_pid > $PELICAN_PID
cd $OUTPUTDIR
$PY -m pelican.server $port &
srv_pid=$!
echo $srv_pid > $SRV_PID
cd $BASEDIR
sleep 1
if ! alive $pelican_pid ; then
echo "Pelican didn't start. Is the Pelican package installed?"
return 1
elif ! alive $srv_pid ; then
echo "The HTTP server didn't start. Is there another service using port" $port "?"
return 1
fi
echo 'Pelican and HTTP server processes now running in background.'
}
###
# MAIN
###
[[ ($# -eq 0) || ($# -gt 2) ]] && usage
port=''
[[ $# -eq 2 ]] && port=$2
if [[ $1 == "stop" ]]; then
shut_down
elif [[ $1 == "restart" ]]; then
shut_down
start_up $port
elif [[ $1 == "start" ]]; then
if ! start_up $port; then
shut_down
fi
else
usage
fi

94
fabfile.py vendored

@ -0,0 +1,94 @@
from fabric.api import *
import fabric.contrib.project as project
import os
import shutil
import sys
import SocketServer
from pelican.server import ComplexHTTPRequestHandler
# Local path configuration (can be absolute or relative to fabfile)
env.deploy_path = 'output'
DEPLOY_PATH = env.deploy_path
# Remote server configuration
production = 'spacekookie@lonelyrobot.io:22'
dest_path = '/var/www'
# Rackspace Cloud Files configuration settings
env.cloudfiles_username = 'my_rackspace_username'
env.cloudfiles_api_key = 'my_rackspace_api_key'
env.cloudfiles_container = 'my_cloudfiles_container'
# Github Pages configuration
env.github_pages_branch = "gh-pages"
# Port for `serve`
PORT = 4000
def clean():
"""Remove generated files"""
if os.path.isdir(DEPLOY_PATH):
shutil.rmtree(DEPLOY_PATH)
os.makedirs(DEPLOY_PATH)
def build():
"""Build local version of site"""
local('pelican -s pelicanconf.py')
def rebuild():
"""`clean` then `build`"""
clean()
build()
def regenerate():
"""Automatically regenerate site upon file modification"""
local('pelican -r -s pelicanconf.py')
def serve():
"""Serve site at http://localhost:4000/"""
os.chdir(env.deploy_path)
class AddressReuseTCPServer(SocketServer.TCPServer):
allow_reuse_address = True
server = AddressReuseTCPServer(('', PORT), ComplexHTTPRequestHandler)
sys.stderr.write('Serving on port {0} ...\n'.format(PORT))
server.serve_forever()
def reserve():
"""`build`, then `serve`"""
build()
serve()
def preview():
"""Build production version of site"""
local('pelican -s publishconf.py')
def cf_upload():
"""Publish to Rackspace Cloud Files"""
rebuild()
with lcd(DEPLOY_PATH):
local('swift -v -A https://auth.api.rackspacecloud.com/v1.0 '
'-U {cloudfiles_username} '
'-K {cloudfiles_api_key} '
'upload -c {cloudfiles_container} .'.format(**env))
@hosts(production)
def publish():
"""Publish to production via rsync"""
local('pelican -s publishconf.py')
project.rsync_project(
remote_dir=dest_path,
exclude=".DS_Store",
local_dir=DEPLOY_PATH.rstrip('/') + '/',
delete=True,
extra_opts='-c',
)
def gh_pages():
"""Publish to GitHub Pages"""
rebuild()
local("ghp-import -b {github_pages_branch} {deploy_path}".format(**env))
local("git push origin {github_pages_branch}".format(**env))

@ -0,0 +1,85 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*- #
from __future__ import unicode_literals
AUTHOR = 'Kate'
SITENAME = 'Fun Memory Violations'
SITEURL = ''
# DISQUS_SITENAME = 'katesnullpointers'
THEME = 'nest'
# NEST_HEADER_IMAGES = 'banner_bg2x.png'
EXTRA_PATH_METADATA = {
# 'robots.txt': {'path': 'robots.txt'},
'favicon.ico': {'path': 'favicon.ico'}
}
PLUGIN_PATHS = ['plugins/',]
PLUGINS = ['summary', ]
TEMPLATE_DEBUG = True
DEBUG = True
PATH = 'content'
STATIC_PATHS = ['images', 'downloads', 'kookie.txt']
SITE_LOGO = 'favicon.ico'
SUMMARY_MAX_LENGTH = 140
#############################################
#############################################
# THEME = 'lazystrap' # Why doesn't this work? :(
DEFAULT_CATEGORY = 'Dev Diary'
DEFAULT_DATE = 'fs'
DISPLAY_CATEGORIES_ON_MENU = False
DISPLAY_PAGES_ON_MENU = False
MENUITEMS = (
('Home', '/'),
('Blog', '/blog/'),
# ('Guides', '/guides/'),
# ('Showcase', '/showcase/'),
('About Me', '/about/'),
)
ARTICLE_URL = '{category}/{slug}'
ARTICLE_SAVE_AS = '{category}/{slug}/index.html'
PAGE_URL = '{slug}'
PAGE_SAVE_AS = '{slug}/index.html'
CATEGORY_URL = '{slug}'
CATEGORY_SAVE_AS = '{slug}/index.html'
TAG_URL = '{slug}'
TAG_SAVE_AS = '{slug}/index.html'
#############################################
#############################################
TIMEZONE = 'Europe/Berlin'
DEFAULT_LANG = 'en'
LOCALE = 'C'
DEFAULT_DATE_FORMAT = '%Y-%m-%d'
# Feed generation is usually not desired when developing
FEED_ALL_ATOM = None
CATEGORY_FEED_ATOM = None
TRANSLATION_FEED_ATOM = None
AUTHOR_FEED_ATOM = None
FEED_RSS = 'rss.xml'
CATEGORY_FEED_RSS = '%s/rss.xml'
JINJA_EXTENSIONS = ['webassets.ext.jinja2.AssetsExtension', 'jinja2.ext.with_']
# Blogroll
# LINKS = (('Lonely Robot', 'http://www.lonelyrobot.io'), )
# Social widget
SOCIAL = (('Twitter', 'https://www.twitter.com/spacekookie'),('Github','https://www.github.com/spacekookie'),)
DEFAULT_PAGINATION = 20

@ -0,0 +1,53 @@
Summary
-------
This plugin allows easy, variable length summaries directly embedded into the
body of your articles. It introduces two new settings: ``SUMMARY_BEGIN_MARKER``
and ``SUMMARY_END_MARKER``: strings which can be placed directly into an article
to mark the beginning and end of a summary. When found, the standard
``SUMMARY_MAX_LENGTH`` setting will be ignored. The markers themselves will also
be removed from your articles before they are published. The default values
are ``<!-- PELICAN_BEGIN_SUMMARY -->`` and ``<!-- PELICAN_END_SUMMARY -->``.
For example::
Title: My super title
Date: 2010-12-03 10:20
Tags: thats, awesome
Category: yeah
Slug: my-super-post
Author: Alexis Metaireau
This is the content of my super blog post.
<!-- PELICAN_END_SUMMARY -->
and this content occurs after the summary.
Here, the summary is taken to be the first line of the post. Because no
beginning marker was found, it starts at the top of the body. It is possible
to leave out the end marker instead, in which case the summary will start at the
beginning marker and continue to the end of the body.
The plugin also sets a ``has_summary`` attribute on every article. It is True
for articles with an explicitly-defined summary, and False otherwise. (It is
also False for an article truncated by ``SUMMARY_MAX_LENGTH``.) Your templates
can use this e.g. to add a link to the full text at the end of the summary.
reST example
~~~~~~~~~~~~
Inserting the markers into a reStructuredText document makes use of the
comment directive, because raw HTML is automatically escaped. The reST equivalent of the above Markdown example looks like this::
My super title
##############
:date: 2010-12-03 10:20
:tags: thats, awesome
:category: yeah
:slug: my-super-post
:author: Alexis Metaireau
This is the content of my super blog post.
.. PELICAN_END_SUMMARY
and this content occurs after the summary.

@ -0,0 +1 @@
from .summary import *

@ -0,0 +1,90 @@
"""
Summary
-------
This plugin allows easy, variable length summaries directly embedded into the
body of your articles.
"""
from __future__ import unicode_literals
from pelican import signals
from pelican.generators import ArticlesGenerator, StaticGenerator, PagesGenerator
def initialized(pelican):
from pelican.settings import DEFAULT_CONFIG
DEFAULT_CONFIG.setdefault('SUMMARY_BEGIN_MARKER',
'<!-- PELICAN_BEGIN_SUMMARY -->')
DEFAULT_CONFIG.setdefault('SUMMARY_END_MARKER',
'<!-- PELICAN_END_SUMMARY -->')
if pelican:
pelican.settings.setdefault('SUMMARY_BEGIN_MARKER',
'<!-- PELICAN_BEGIN_SUMMARY -->')
pelican.settings.setdefault('SUMMARY_END_MARKER',
'<!-- PELICAN_END_SUMMARY -->')
def extract_summary(instance):
# if summary is already specified, use it
# if there is no content, there's nothing to do
if hasattr(instance, '_summary'):
instance.has_summary = True
return
if not instance._content:
instance.has_summary = False
return
begin_marker = instance.settings['SUMMARY_BEGIN_MARKER']
end_marker = instance.settings['SUMMARY_END_MARKER']
content = instance._content
begin_summary = -1
end_summary = -1
if begin_marker:
begin_summary = content.find(begin_marker)
if end_marker:
end_summary = content.find(end_marker)
if begin_summary == -1 and end_summary == -1:
instance.has_summary = False
return
# skip over the begin marker, if present
if begin_summary == -1:
begin_summary = 0
else:
begin_summary = begin_summary + len(begin_marker)
if end_summary == -1:
end_summary = None
summary = content[begin_summary:end_summary]
# remove the markers from the content
if begin_summary:
content = content.replace(begin_marker, '', 1)
if end_summary:
content = content.replace(end_marker, '', 1)
instance._content = content
instance._summary = summary
instance.has_summary = True
def run_plugin(generators):
for generator in generators:
if isinstance(generator, ArticlesGenerator):
for article in generator.articles:
extract_summary(article)
elif isinstance(generator, PagesGenerator):
for page in generator.pages:
extract_summary(page)
def register():
signals.initialized.connect(initialized)
try:
signals.all_generators_finalized.connect(run_plugin)
except AttributeError:
# NOTE: This results in #314 so shouldn't really be relied on
# https://github.com/getpelican/pelican-plugins/issues/314
signals.content_object_init.connect(extract_summary)

@ -0,0 +1,75 @@
# -*- coding: utf-8 -*-
import unittest
from jinja2.utils import generate_lorem_ipsum
# generate one paragraph, enclosed with <p>
TEST_CONTENT = str(generate_lorem_ipsum(n=1))
TEST_SUMMARY = generate_lorem_ipsum(n=1, html=False)
from pelican.contents import Page
import summary
class TestSummary(unittest.TestCase):
def setUp(self):
super(TestSummary, self).setUp()
summary.register()
summary.initialized(None)
self.page_kwargs = {
'content': TEST_CONTENT,
'context': {
'localsiteurl': '',
},
'metadata': {
'summary': TEST_SUMMARY,
'title': 'foo bar',
'author': 'Blogger',
},
}
def _copy_page_kwargs(self):
# make a deep copy of page_kwargs
page_kwargs = dict([(key, self.page_kwargs[key]) for key in
self.page_kwargs])
for key in page_kwargs:
if not isinstance(page_kwargs[key], dict):
break
page_kwargs[key] = dict([(subkey, page_kwargs[key][subkey])
for subkey in page_kwargs[key]])
return page_kwargs
def test_end_summary(self):
page_kwargs = self._copy_page_kwargs()
del page_kwargs['metadata']['summary']
page_kwargs['content'] = (
TEST_SUMMARY + '<!-- PELICAN_END_SUMMARY -->' + TEST_CONTENT)
page = Page(**page_kwargs)
# test both the summary and the marker removal
self.assertEqual(page.summary, TEST_SUMMARY)
self.assertEqual(page.content, TEST_SUMMARY + TEST_CONTENT)
def test_begin_summary(self):
page_kwargs = self._copy_page_kwargs()
del page_kwargs['metadata']['summary']
page_kwargs['content'] = (
'FOOBAR<!-- PELICAN_BEGIN_SUMMARY -->' + TEST_CONTENT)
page = Page(**page_kwargs)
# test both the summary and the marker removal
self.assertEqual(page.summary, TEST_CONTENT)
self.assertEqual(page.content, 'FOOBAR' + TEST_CONTENT)
def test_begin_end_summary(self):
page_kwargs = self._copy_page_kwargs()
del page_kwargs['metadata']['summary']
page_kwargs['content'] = (
'FOOBAR<!-- PELICAN_BEGIN_SUMMARY -->' + TEST_SUMMARY +
'<!-- PELICAN_END_SUMMARY -->' + TEST_CONTENT)
page = Page(**page_kwargs)
# test both the summary and the marker removal
self.assertEqual(page.summary, TEST_SUMMARY)
self.assertEqual(page.content, 'FOOBAR' + TEST_SUMMARY + TEST_CONTENT)

@ -0,0 +1,24 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*- #
from __future__ import unicode_literals
# This file is only used if you use `make publish` or
# explicitly specify it as your config file.
import os
import sys
sys.path.append(os.curdir)
from pelicanconf import *
SITEURL = 'https://spacekookie.de'
RELATIVE_URLS = False
FEED_ALL_ATOM = 'feeds/all.atom.xml'
CATEGORY_FEED_ATOM = 'feeds/%s.atom.xml'
DELETE_OUTPUT_DIRECTORY = True
# Following items are often useful when publishing
# DISQUS_SITENAME = "katesnullpointers"
# GOOGLE_ANALYTICS = ""

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save