February 24, 2019
I havent done anything to this blog in last year. After fixes in mar 2018 I have added ping endpoint in august (it took me almost 10 minutes, including deployment!), then I have removed file watcher in christmas, because someone from linode contacted me and kindly asked to stop using 100% of cpu all the time.
But I have big plans for this blog in this year and already started by changing way how to push new posts. Previously I have used scp to upload them to server and filewatcher catched them. After I have disabled it, I had to restart app each time, when I post something (that is twice a year). aLthough I have finally remember scp syntax, I want to have something simplier and easy to do using just phone.
Now I store all posts in github (thanks MS, they added private repositories), and add webhook to pull each time something pushed to "publish" branch. This seems not a very complex stuff, but I have added libgit2sharp to project, repository to use it, cleaned code (and posts structure - now it loads from all directories recursively, images in separate folder etc) - and all of it using 20 minutes before sleep time breaks.
I could have played zelda in that time... 😭
btw, this post I have created just to test git sync, do not read it, it is boring
February 7, 2019
On my main job we have a project, that contain all kinds of technologies. Mostly it us angularJs or razor pages, but we got also knockout, that works in pair with signalr. This cause many problems and one of the technical debt currently is to replace signalr hubs to ajax calls. But problem is we cant do this at once, we have to support both versions at the time to turn it off, if something goes south. Now coffeescript is packed with checkings, what to call, but problem is that in response from server signalr hub return parameters in camelCase, and ajax return in CamelCase. I got a strong feeling, that if I will add another useSignalR checking, this code will be cursed forewher, so I wrote small function:
replaceAttributesToLowerCase: (object) ->
for propertyName in Object.keys(object)
lowerCaseProperty = propertyName.toLowerCase()
object[lowerCaseProperty] = object[propertyName]
return object
Rare beauty of javascript flexibility, heh 😎 Also now all parameters are lowercase in whole class, which is severely breaking naming conventions. And it double object size in memory. But in my opinion, all parts of projects, that contain knockout, coffeescript or signalr should be buried.
December 3, 2018
One of the very first projects in my career was php (plain php, no frameworks, no js) cms system for medical facilities. By that time, I didn't know how web works (I mean, I knew even less than now) and my coding skills were very rough. I have spent 3 years in support and happily left the company in early 2013. And today I have found, that this project is still alive, used and they haven't changed admin password 🤪
Somewhere in this site there are my own implementation of mvc and orm.. even before I knew about these pattern or read GoF book.
This has the shittiest code, that I have ever wrote for production and I think, by far the oldest that is still in use.
October 19, 2018
One of the first thing, that people learn about programming is control flow and, in particular, loops. I can clearly recall how we have implemented two dimensional loop in qbasic in middle school. It’s very simple task, nevertheless, recently I have found a way to make it complex and cumbersome. May be task, that I will explain below, would be good for a interview.
Let’s imagine, that we have two-dimensional array W x H. Simplest way to iterate throw would be double loop directly from 6th grade:
for(int i1 = 0; i1 < H; i1++)
for(int i2 = 0; i2 < W; i2++)
var el = array[i1 * W + i2];
I hope I didn’t make a mistakes here, I haven’t checked this
But what if we need to get chunks of data from left to right?
var container = array[]
for(int i1 = 0; i1 < H; i1++)
for(int i2 = 0; i2 < W; i2++)
container.add(array[i1 * W + i2]);
This is basically transforms one array to another, not good. We need to use iterators. What is iterators? Here is abstract interface:
protocol BaseIterator
{
T? next();
func clear();
}
We should have ability to create iterators from containers and call next()
until it will not return null (or nil or whatever crap, which mean, that array is over). Internally it should store some counter or pointer to next element. clear()
function set counter back to the beginning of collection.
For one dimensional array, that allocates in memory lineally, such pointer is trivial. But what should we do in case two dimensional array?
protocol CellsIterator {
func next() -> LineCellsContainer?
}
class BaseCellsIterator {
internal let gameModel : GameModel
internal var line = LineCellsContainer()
internal var y: Int = 0
internal var x: Int = 0
internal var w: Int { return self.gameModel.fieldWidth }
internal var h: Int { return self.gameModel.fieldHeight }
}
Here is cropped version on baseIterator in my game and also protocol for cells iterator. I use them both because protocols with associated types (PAT) exist and annoy me, but that is a theme for another post.
So, here I store:
gameModel
), that is completely unrelated to the topicline
), that will store result of current iterationx, y
) as pointer to current iterator positionw, h
), that describe the size the matrix
Here is implementation of simple iterator x from 0 to w and y from 0 to h func next() -> LineCellsContainer? {
// clear container
line.clear()
// if end of line, increment to next one
if x >= w {
x = 0
y += 1
}
// if it was last line, then we need to stop
if y >= h {
return nil;
}
// iterate through end of the line
for _ in x ..< w {
let cell = getCell(x, y)
x += 1
if(cell.isBlocked) {
break
}
line.add(cell)
}
// return container
return line;
}
I have added comments to make it more readable, although it is already pretty simple. Unfortunately, swift doesn’t allow creation of for loops with outside variable, otherwise it would be even simpler for(;x<w;x++)
.
Another remark: because of the game logic (cell.isBlocked
), it is possible, that loop should stop, return current container and continue with new one.
This all seems very simple, however it took for me several days to figure out how to do it right. And now I have iterators not only for 4 directions (up, down, left, right), but also by diagonals. I’m using this to check game logic for player move and at another place, to check, can player make any move at all.
DRY
September 26, 2018
Last time I have played Half-Life twelve years ago, on my first fall semester, when I got cold, stayed in bed for couple days with fathers laptop. I have played multiplayer a lot since, but never a storyline.
It was my favorite game in school and, at some point, i swear, I remembered all maps from the beginning until, at least, to chapter "surface tension". But twelve years later I have found, that although I still remember chapters order, but have completely forgot all small details and the entire feeling from game is slightly shifted from regular first person shooter to brilliant sci-fi story action game.
And 20 years old graphic technology is not breaking experience of watching slightly scary movie about brave scientist.
Enterance to final boss is magnificent
100% JS-free