Thursday, March 30, 2017

PomodoroTimer

Recently I heard about Pomodoro technique and decided to try it out. Basically it's a method for increasing productivity by focusing on work for 25 minutes, having a break, and then repeating.

There is a ton of different ways to measure those 25 mins and breaks. If you type "25 min timer" in Google, you will see countdown above search results. So thoughtful.

I wanted a light and discrete timer but noticeable when it dings. Something like Thyme + ding. I'm sure that there are plenty of nice timers on Internet but till I find the right one, I can make my own and learn something in the process.

Few tomatoes later, and there it is, ticking in navigation bar: PomodoroTimer


When time reaches zero, a short sound plays and notification pops up:


The timer starts when the app is open (cmd + space > PomodoroTimer). And it's killed when tapped on it.

In first tomato I created a new Xcode project from macOS > Cocoa Application template. By default, template app shows blank app window. One way of hiding it is to just delete it from MainMenu.xib. Standard app menu is also unwanted. To disable app menu, new entry Application is agent (UIElement) = YES must be added to Info.plist.

"Blow" is one of sounds located in /System/Library/Sounds.The rest of the code is pretty self explanatory:
import Cocoa

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
    
    private var timer: Timer?
    private let statusItem = NSStatusBar.system().statusItem(withLength: 42)

    func applicationDidFinishLaunching(_ aNotification: Notification) {
        statusItem.action = #selector(terminate)
        
        let startDate = Date()
        let pomodoroInterval: Double = 25 * 60
        
        self.statusItem.title = formatTime(seconds: pomodoroInterval)
        
        timer = Timer.scheduledTimer(withTimeInterval: 0.5,
                                     repeats: true,
                                     block: { [weak self] timer in
            guard let `self` = self else { return }
                                        
            let elapsedTime = Date().timeIntervalSince(startDate)
            let remainingTime = pomodoroInterval - elapsedTime
            
            if remainingTime < 0 {
                timer.invalidate()
                let notification = NSUserNotification()
                notification.title = "Pomodoro!"
                notification.soundName = "Blow"
                NSUserNotificationCenter.default.deliver(notification)
            }
            else {
                self.statusItem.title = self.formatTime(seconds: remainingTime)
            }
        })
    }
    
    func formatTime(seconds: TimeInterval) -> String {
        let minutes = Int(seconds / 60)
        let remainingSeconds = Int(seconds) % 60
        return String(format:"%02d:%02d", minutes, remainingSeconds)
    }

    func terminate() {
        timer?.invalidate()
        NSApp.terminate(self)
    }
}
github   -   binary

Sunday, February 7, 2016

Global Game Jam

Last week was held Global Game Jam. I was there with my team Pixel Farmers, especially assembled for the event. Matej was first to apply for the event, then me, maybe 10 days before the event and then Dario applied just 3 days before the event.

As we applied, we started picking on LibGDX. That Java gaming framework looked good: it's open source, cross-platform, community is active, documentation comprehensive and thanks to Gradle it works with several IDEs easily. We went there to have some fun, learn and experience something new. We achieved all of that and more.

As I sad, we didn't have much time to prepare due our daily work and late apply, so we had to type code whole day to get ready for the event where we will type code for two whole days and good part of nights :) Luckily I have an account on Packtpub and they have like 5 or 6 books about LibGDX. They even have a book titled "The Game Jam Survival Guide". That one is pretty interesting. It has some good tips and funny ones like "How to save your relationship/marriage during game jam". Well, it's not a joke for some people I guess. :)

No one in the team was experienced game maker, but we are seasoned developers working at FIVE so we had confidence. My confidence was little bit shaken after we could not agree on the game for four hours after the theme was announced!! Less then an hour before midnight we decided that we gonna save a goat. I was very excited with the idea. I never created top down shouter but I always wanted too. Something like Crimsonland. Sure, "top-down-shooter" is not very original, but it's a fun genre and we can give it charm with fine story, humour, twists and so on.

We started working. At least we didn't lose additional time on creating a project and Github repo. Skeleton project with few basic classes like GameScreen and methods like render, update and draw was set 2 days before. Well, we should have added more, things like asset manager, logic for screen transition, logic for cut scenes... Oh well, next time!

We came to the jam straight from work, so we were a bit tired. At the end of that first day, we had just black screen with white circle and one white rectangle inside that circle. Circle obeyed WASD keys and rectangle rotated in direction of mouse pointer so it wasn't that bad. We were among first to go home to sleep around 1:30 am.

Next day was a big day, we had to push hard. White circle and rectangle are not very exciting. Class room at Faculty of Electrical Engineering and Computing (FER) was filled with jammers. I wondered who worked whole night. My team recharged their batteries so we were ready to rock, but what pumped spirits high were first sprites. I wasn't sure about graphics style of our game, since officially we were all devs, but it turned out that Dario, beside being a great dev, has also awesome artist skills. Commits were flowing. Every 15 mins when I typed git pull, something new was added to the game and you could see it on a screen. Matej added bad guys, Dario added walls and tiles and I added means to fight bad guys. Before lunch we had core mechanics, so we felt good and awarded ourselves with a walk around faculty to stretch legs and enjoy daylight.

List of features was long and we had a good laugh when throwing ideas on it. While day was turning into night, we polished animations, corrected hit boxes and collision detection. Although we wanted to go to sleep around usual hours, we stayed longer because of other jammers, because that's how jammers roll, they drink tons of energy drinks, eat pizza and sleep later. We went to sleep around 3:30 am :P

Next morning when we started working it was barely morning and our game still didn't have head
and tail. By head I mean introduction to the game story. By tail I mean end game mechanics with goat and end game screen. Although overall we didn't have difficulties with LibGDX, some stupid things were more complicated to implement then they should. Things like classic UI elements, because they require "skin" JSON file. Anyways, one hour before dead line we had head and tail. We spent last hour polishing and testing the game.

Teams produced 10 games and every team had 10 minutes to present their game. After that, 3 judges from prominent Croatian game companies (Croteam, Little Green Man, Lion Game Lion) played games, talked with teams and at end decided which games are winners. Their criteria was: game completeness, ease to understand game rules and playability. When I heard that, little voice in my head followed with "check, check, check". And really, they liked our game and gave us this fancy piece of cardboard:
Picture from Vidi.hr
This was the first GGJ in Croatia and I hope that it will become tradition. Like I said, we had fun, learned new things and meet interesting people. Organizers did a pretty good job, we had food and drinks. They also provided laptops but majority of people brought their own, so what almost everyone could use was an extra display.

You can check Goat Rescue HERE and all games made for GGJ Zagreb 2016 HERE.

Tuesday, June 30, 2015

Mini quadcopter

Drone mania bite me and now I have a new hobby. After two weeks of research and tons of watched videos, I placed my order, actually dozens of orders. Complete solutions are cool, but I like to build things from pieces. That way I can learn how things work and have unique product at the end. I decided to start with 250 mm FPV category. These kind of quadcopters are very popular, meaning it's easy to find parts and build tutorials.

Main tutorial that I followed was recorded by Bruce Simpson. Here is the first part in series:

In video's description on YT, there is a list of parts but it's incomplete, so here is a full list of parts I used:
FPV system:

I bought as much as I could from local stores. To my surprise, some prices were lower than ones on ebay.

Short build log

After one month majority of parts came:

and fun started:

I didn't documented the whole process, so it might look from pictures above that it can be completed between breakfast and lunch, but just video tutorial series that I linked above lasts few hours.

PS4 or quadcopter?

The price between those two is pretty similar. That is, if a quadcopter survives first fly tests. My first fly attempt ended after just a few seconds. Quad raised a bit but floated backwards and scraped a wall with propellers, resulting with light prop damage and one prop cap falling off. On my second fly attempt I managed to get quad in the air and wrestled with controls on the radio to hold quad steady. My happy grin didn't last long, because suddenly, at maybe 3 meters height, prop cap got loss, and quad hit the grass. I spent half hour searching through grass, but didn't find the cap.


Flying by looking at quadcopter is OK, but the real fun starts with FPV. I'm still waiting for my action camera to come, so I'll share a FPV video from a pro pilot Boris B.:

So all in all, my answer to the question is quadcopter.

UPDATE:

Here are two videos that I took. First one is altitude test, second is distance test.







Monday, February 16, 2015

dotSwift

dotSwift is a Swift conference, held this year on February 6th. With my colleagues from FIVE, I had the honour to attend this event in gorgeous Théâtre des Variétés in Paris. With the promises given on their website and a sound list of lecturers, expectations were high.

Taken at dotSwift in Paris on November 6th, 2015 by Nicolas Ravelli

One of dotSwift's mottos is "Made by developers, for developers". At the very start of the conference, director Sylvain instructed audience to shake hands and introduce with people around. Interaction between developers was additionally encouraged at coffee breaks. The conference consisted of three blocks of lectures with coffee breaks between blocks.
There were 8 lectures capped on 20 minutes and 5 mini lectures caped on 5 minutes. Twenty minutes is short enough for keeping concentration but barely enough for deeper insight into a topic, not to mention five minute ones. Though, it all depends on lecturer and how he's prepared and there were noticeable differences in quality between lecturers.

Main theme of the conference was state and maturity of the language and accompanying tools like XCode and comparison with its ancestor Objective C. Overall conclusion is that language is mature enough for production but XCode is trailing behind and still has some frustrating bugs. All lectures were recorded and are available on dotSwift's website. I advise watching lectures from Ash Furrow on Swift in production, Daniel Steinberg on comparison between Objective C and Swift, Dimitri Dupuis-Latour on Optionals in Swift and Kyle Fuller on Functional programming.
After the conference, main sponsor BlaBlaCar paid a round in nearby French Beer Factory and socializing continued till late hours.
Next day, there was a workshop organized on a subject of building frameworks with Swift. It was available only to first 30 people who registered via external page and a lot of people ended on a waiting list.

This was a first dotSwift conference and there is a space for improvements. Inspiration should be WWDC. Themes should be more distinct. Specific lectures like Core Bluetooth can't be fitted in just five minutes. It would be nice to have more than one workshop. Updates and news should be visible on official website, not just on Twitter. With all that said, it was an interesting conference with several great lecturers that I mentioned above. I recommend it.

Saturday, November 2, 2013

zipcracker

zipcracker is an application that can find zip-file password using brute force or dictionary attack method.


Source code is available at https://bitbucket.org/mijo_gracanin/zipcracker

Inspiration for doing this app I found in book Violent Python by TJ O'Connor. Example in the book shoved me how easy it is to crack zip-file, using dictionary attack, thanks to zipfile library. Basically, method looks like this:
 from zipfile import ZipFile, zlib  
 z = ZipFile(file)  
 d = open(dictionary)  
 for line in d.readlines():  
   password = line.strip('\n')  
   try:  
     z.extractall(path='', pwd=password)  
     print(password)  
   except zlib.error:  
     pass  

I upgraded the example code from the book with GUI and brute force method. Brute force is easily implemented with itertools library, which contains permutations function. For GUI I used tkinter library, which mostly comes included with Python. I found tkinter good enough for simple applications, but some tasks, like restricting Entry widget to only accepts numbers, can be surprisingly difficult and requires, to quote a poster from StackOverflow, Voodoo code.

Of course Python may not be the best choice for this kind of task, because of speed. TJ O'Connor tried to speed up things a bit by using multithreading, but according to Mark Summerfield's book: Python in Practice, multithreading can even decrease performance because of GIL (Global Interpreter Lock) and he advises writing  code in Cython and using multiprocessing module. It would be interesting to see comparison between this approaches.
Other desirable improvements would be adding support for additional file types like rar and 7z. There is a rarfile library with similar interface like zipfile library available on PyPI, and for 7z there is a pylzma library also on PyPI.

Friday, August 16, 2013

Switch to linux

I haven't forgot my blog, just many things happened in the meantime, like: I bought PS3, started to seriously train climbing, work at workplace intensified, then summer and vacation came, and so on. Many times I tried it before, always finding some obstacle or constraint which made me return back to the dark side, but I always knew that one day we would get along just fine. That day came 4 months ago and since then Windows is only "collecting dust" on one partition of HDD, preserved just in case I must work from home. I've chose Linux Mint 14 Cinnamon for my primary OS and I have to say my laptop responds more agile on my commands and almost all apps I need are working, except Visual Studio of course. As for games, like I said earlier, I have PS3 for them, so it's all cool :)  In four months it froze once, which ain't that bad but not as stable as Windows 7 which never crashed in two years.
In initial post I announced that I'll post an useful wxPython project but I left it on that almost forgotten partition of HDD, half complete, with core functionality, but much work remains for it to look attractive and polished. I'll orient more on Tkinter now since it's better integrated with Python and it's future seems more promising. Soon I'll post Python/Tkinter app for crackin zip and rar files.

Wednesday, February 13, 2013

Hello world!

Interestingly, I get new ideas usually just before the bed time. Like with this one, to finally start the tech blog. I'm not sure is it because that way I can't do much real work or so that I can't sleep because of excitement and brain activity. Anyway, blog is started, showcase apps and code are almost done and I'm ready to fill this place with bits and bytes.

What to expect? First few posts will be about Python projects I'm working on in my free time. Just a few apps made with wxPython, to make some daily tasks easier. And later, we will see.